import { ucFirst } from "core/utils";
import type { Entity, EntityData, EntityRelation } from "data";
import { Fragment, useState } from "react";
import { TbDots } from "react-icons/tb";
import { useApiQuery, useEntityQuery } from "ui/client";
import { useBkndData } from "ui/client/schema/data/use-bknd-data";
import { Button } from "ui/components/buttons/Button";
import { IconButton } from "ui/components/buttons/IconButton";
import { Message } from "ui/components/display/Message";
import { Dropdown } from "ui/components/overlay/Dropdown";
import { useBrowserTitle } from "ui/hooks/use-browser-title";
import * as AppShell from "ui/layouts/AppShell/AppShell";
import { Breadcrumbs2 } from "ui/layouts/AppShell/Breadcrumbs2";
import { routes, useNavigate } from "ui/lib/routes";
import { bkndModals } from "ui/modals";
import { EntityForm } from "ui/modules/data/components/EntityForm";
import { EntityTable2 } from "ui/modules/data/components/EntityTable2";
import { useEntityForm } from "ui/modules/data/hooks/useEntityForm";
export function DataEntityUpdate({ params }) {
const { $data, relations } = useBkndData();
const entity = $data.entity(params.entity as string);
if (!entity) {
return ;
}
const entityId = Number.parseInt(params.id as string);
const [error, setError] = useState(null);
const [navigate] = useNavigate();
useBrowserTitle(["Data", entity.label, `#${entityId}`]);
const targetRelations = relations.listableRelationsOf(entity);
const local_relation_refs = relations
.sourceRelationsOf(entity)
?.map((r) => r.other(entity).reference);
const $q = useEntityQuery(
entity.name,
entityId,
{
with: local_relation_refs,
},
{
keepPreviousData: false,
revalidateOnFocus: false,
shouldRetryOnError: false,
},
);
function goBack() {
window.history.go(-1);
}
async function onSubmitted(changeSet?: EntityData) {
console.log("update:changeSet", changeSet);
//return;
if (!changeSet) {
goBack();
return;
}
try {
await $q.update(changeSet);
if (error) setError(null);
goBack();
} catch (e) {
setError(e instanceof Error ? e.message : "Failed to update");
}
}
async function handleDelete() {
if (confirm("Are you sure to delete?")) {
try {
await $q._delete();
if (error) setError(null);
goBack();
} catch (e) {
setError(e instanceof Error ? e.message : "Failed to delete");
}
}
}
const data = $q.data;
const { Form, handleSubmit } = useEntityForm({
action: "update",
entity,
initialData: $q.data?.toJSON(),
onSubmitted,
});
if (!data && !$q.isLoading) {
return (
);
}
const makeKey = (key: string | number = "") => `${entity.name}_${entityId}_${String(key)}`;
const fieldsDisabled = $q.isLoading || $q.isValidating || Form.state.isSubmitting;
return (
{
bkndModals.open("debug", {
data: {
data: data as any,
entity: entity.toJSON(),
schema: entity.toSchema({ clean: true }),
form: Form.state.values,
state: Form.state,
},
});
},
},
{
label: "Settings",
onClick: () =>
navigate(routes.settings.path(["data", "entities", entity.name]), {
absolute: true,
}),
},
{
label: "Delete",
onClick: handleDelete,
destructive: true,
disabled: fieldsDisabled,
},
]}
>
[state.canSubmit, state.isSubmitting]}
children={([canSubmit, isSubmitting]) => (
)}
/>
>
}
className="pl-3"
>
{error && (
Update failed: {error}
)}
{targetRelations.length > 0 ? (
) : null}
);
}
function EntityDetailRelations({
id,
entity,
relations,
}: {
id: number;
entity: Entity;
relations: EntityRelation[];
}) {
const [selected, setSelected] = useState(
// @ts-ignore
relations.length > 0 ? relations[0] : undefined,
);
function handleClick(relation: EntityRelation) {
setSelected(relation);
}
if (relations.length === 0) {
return null;
}
//console.log("selected", selected, relations[0].helper(entity.name).other.reference);
return (
{
const other = relation.other(entity);
return {
as: "button",
type: "button",
label: ucFirst(other.reference),
onClick: () => handleClick(relation),
active: selected?.other(entity).reference === other.reference,
badge: relation.type(),
};
})}
/>
);
}
function EntityDetailInner({
id,
entity,
relation,
}: {
id: number;
entity: Entity;
relation: EntityRelation;
}) {
const other = relation.other(entity);
const [navigate] = useNavigate();
const search = {
select: other.entity.getSelect(undefined, "table"),
limit: 10,
offset: 0,
};
// @todo: add custom key for invalidation
const $q = useApiQuery((api) =>
api.data.readManyByReference(entity.name, id, other.reference, search),
);
function handleClickRow(row: Record) {
navigate(routes.data.entity.edit(other.entity.name, row.id));
}
let handleClickNew: any;
try {
if (other.entity.type !== "system") {
const ref = relation.getReferenceQuery(other.entity, id, other.reference);
handleClickNew = () => {
navigate(routes.data.entity.create(other.entity.name), {
query: ref.where,
});
//navigate(routes.data.entity.create(other.entity.name) + `?${query}`);
};
}
} catch (e) {}
if (!$q.data) {
return null;
}
const isUpdating = $q.isValidating || $q.isLoading;
return (
);
}