import { getHotkeyHandler, useHotkeys } from "@mantine/hooks"; import { ucFirst } from "core/utils"; import type { EntityData } from "bknd"; import type { RelationField } from "data/relations"; import { useEffect, useRef, useState } from "react"; import { TbEye } from "react-icons/tb"; import { useEntityQuery } from "bknd/client"; import { useBknd } from "ui/client/bknd"; import { Button } from "ui/components/buttons/Button"; import * as Formy from "ui/components/form/Formy"; import { Popover } from "ui/components/overlay/Popover"; import { Link } from "ui/components/wouter/Link"; import { routes } from "ui/lib/routes"; import { useLocation } from "wouter"; import type { EntityTableProps } from "../EntityTable"; import type { ResponseObject } from "modules/ModuleApi"; import ErrorBoundary from "ui/components/display/ErrorBoundary"; import { EntityTable2 } from "ui/modules/data/components/EntityTable2"; import type { TFieldApi } from "ui/modules/data/components/EntityForm"; // @todo: allow clear if not required export function EntityRelationalFormField({ fieldApi, field, data, disabled, tabIndex, }: { fieldApi: TFieldApi; field: RelationField; data?: EntityData; disabled?: boolean; tabIndex?: number; }) { const { app } = useBknd(); const entity = app.entity(field.target())!; const [query, setQuery] = useState({ limit: 10, page: 1, perPage: 10, select: entity.getSelect(undefined, "table"), }); const [, navigate] = useLocation(); const ref = useRef(null); const $q = useEntityQuery(field.target(), undefined, { select: query.select, limit: query.limit + 1 /* overfetch for softscan=false */, offset: (query.page - 1) * query.limit, }); const [_value, _setValue] = useState<{ id: number | undefined; [key: string]: any }>(); const referenceField = data?.[field.reference()]; const relationalField = data?.[field.name]; useEffect(() => { const value = data?.[field.reference()]; _setValue(value); }, [referenceField]); useEffect(() => { (async () => { const rel_value = field.target(); if (!rel_value || !relationalField) return; const fetched = await $q.api.readOne(field.target(), relationalField); if (fetched.ok && fetched.data) { _setValue(fetched.data as any); } })(); }, [relationalField]); function handleViewItem(e: React.MouseEvent) { e.preventDefault(); e.stopPropagation(); if (_value) { navigate(routes.data.entity.edit(entity.name, _value.id as any)); } } // fix missing value on fields that are required useEffect(() => { if (field.isRequired() && !fieldApi.state.value) { const firstValue = $q.data?.[0]; if (!firstValue) return; console.warn("setting first value because field is required", field.name, firstValue.id); fieldApi.setValue(firstValue.id); _setValue(firstValue as any); } }, [$q.data]); const fetching = $q.isLoading || $q.isValidating; return (
( { fieldApi.setValue(row.id); _setValue(row as any); toggle(); }} onClickPage={(page) => { console.log("setting page", page); setQuery((prev) => ({ ...prev, page })); }} /> )} >
{ ref.current?.click(); }, ], ])} > {_value ? ( <>
{ucFirst(entity.name)}
{_value && Object.entries(_value).map(([key, value]) => { const field = entity.getField(key)!; if (field.isHidden("table")) return null; const _value = field.getValue(value, "table"); return (
{field.getLabel()}: {" "} {_value !== null && typeof _value !== "undefined" ? ( {_value} ) : ( null )}
); })}
) : (
- Select -
)}
); } type PropoverTableProps = Omit & { container: ResponseObject; query: any; toggle: () => void; }; const PopoverTable = ({ container, entity, query, toggle, onClickRow, onClickPage, }: PropoverTableProps) => { function handleNext() { if (query.limit * query.page < container.meta?.count) { onClickPage?.(query.page + 1); } } function handlePrev() { if (query.page > 1) { onClickPage?.(query.page - 1); } } useHotkeys([ ["ArrowRight", handleNext], ["ArrowLeft", handlePrev], ["Escape", toggle], ]); return (
); };