Spreadsheet-UX op een echte relationele engine
Deze repository wordt als momentopname gepubliceerd: een clone bevat de volledige inhoud, maar geen commitgeschiedenis.
import { type ReactNode } from 'react';
import { formatCell, type Row, type TableMeta } from '@wellformed/shared';
import { LINK_OPTION_LIMIT } from '../api/hooks';
import { useI18n } from '../i18n';
import { useCurrency } from '../state/session';
import { Modal } from './Modal';
interface RecordPanelProps {
table: TableMeta;
/** Undefined when the row falls outside the link options already loaded. */
row: Row | undefined;
onClose(): void;
onOpenTable(): void;
}
/**
* The far side of a link, without leaving the row you are reading.
*
* Everything shown here is already in the client — `useLinkTargets` loads the
* target rows so link cells can offer them — so following a relation costs no
* request.
*/
export function RecordPanel({ table, row, onClose, onOpenTable }: RecordPanelProps): ReactNode {
const currency = useCurrency();
const { t, locale } = useI18n();
return (
<Modal
title={row ? describe(row, table) : table.label}
onClose={onClose}
footer={
<>
<button className="btn" onClick={onClose}>
{t('common.close')}
</button>
<button className="btn primary" onClick={onOpenTable}>
{t('grid.openInTable', table.label)}
</button>
</>
}
>
<div className="mb">
{!row ? (
<p className="hint" style={{ margin: 0 }}>
{t('grid.linkRowNotLoaded', LINK_OPTION_LIMIT, table.label, locale)}
</p>
) : (
<div className="record">
{table.columns.map((col) => {
const text = formatCell(row.values[col.name] ?? null, col, {
label: row.labels[col.name],
currency,
locale,
});
return (
<div className="record-row" key={col.name}>
<span className="k">{col.label}</span>
<span className="v">{text === '' ? '—' : text}</span>
</div>
);
})}
</div>
)}
</div>
</Modal>
);
}
function describe(row: Row, table: TableMeta): string {
if (!table.display) return row.id;
const value = row.values[table.display];
return value === null || value === undefined || value === '' ? row.id : String(value);
}