mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-09-30 10:23:11 +00:00
99 lines
3.8 KiB
TypeScript
99 lines
3.8 KiB
TypeScript
import { Box } from "@mui/material";
|
|
import { Plus } from "lucide-react";
|
|
import { useState } from "react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { PageHeader } from "@/components/ui/page-header";
|
|
import { QueryErrorPanel } from "@/components/ui/query-error-panel";
|
|
import { SearchInput } from "@/components/ui/search-input";
|
|
import { Text } from "@/components/ui/text";
|
|
import {
|
|
COMPLETION_TEMPLATE_COPY,
|
|
templateCountLabel,
|
|
} from "@/domain/completion-templates/constants/completion-template-constants";
|
|
import type { CompletionTemplate } from "@/domain/completion-templates/types/completion-template";
|
|
import { useCompletionTemplates } from "@/domain/completion-templates/use-cases/use-completion-templates";
|
|
import { useDebounce } from "@/hooks/use-debounce";
|
|
import { CompletionTemplateDialog } from "./_components/completion-template-dialog";
|
|
import { CompletionTemplatesTable } from "./_components/completion-templates-table";
|
|
import type { CompletionTemplateDialogMode } from "./_components/use-completion-template-dialog";
|
|
import { useCompletionTemplatePermissions } from "./_components/use-completion-template-permissions";
|
|
|
|
type OpenDialog = { template: CompletionTemplate | null; mode: CompletionTemplateDialogMode };
|
|
|
|
export default function CompletionDocsPage() {
|
|
const permissions = useCompletionTemplatePermissions();
|
|
const [search, setSearch] = useState("");
|
|
const debouncedSearch = useDebounce(search, 250);
|
|
const all = useCompletionTemplates();
|
|
const filtered = useCompletionTemplates(debouncedSearch);
|
|
const [dialog, setDialog] = useState<OpenDialog | null>(null);
|
|
const templates = filtered.data ?? [];
|
|
|
|
return (
|
|
<Box className="flex h-full flex-col overflow-hidden p-2.5">
|
|
<PageHeader
|
|
surface
|
|
title={COMPLETION_TEMPLATE_COPY.pageTitle}
|
|
subtitle={templateCountLabel(all.data?.length ?? 0)}
|
|
actions={
|
|
<div className="flex items-center gap-2">
|
|
<SearchInput
|
|
value={search}
|
|
onChange={setSearch}
|
|
placeholder={COMPLETION_TEMPLATE_COPY.searchPlaceholder}
|
|
aria-label="Search document title"
|
|
className="w-56"
|
|
/>
|
|
{permissions.canCreate && (
|
|
<Button
|
|
onClick={() => setDialog({ template: null, mode: "create" })}
|
|
className="gap-1.5"
|
|
>
|
|
<Plus size={13} /> {COMPLETION_TEMPLATE_COPY.addTemplate}
|
|
</Button>
|
|
)}
|
|
</div>
|
|
}
|
|
/>
|
|
|
|
{filtered.error !== null && (
|
|
<QueryErrorPanel
|
|
className="mt-3 shrink-0"
|
|
compact
|
|
message={filtered.error.message || "Failed to load templates."}
|
|
onRetry={() => void filtered.refetch()}
|
|
/>
|
|
)}
|
|
|
|
<div
|
|
className="mt-4 min-h-0 flex-1 overflow-auto rounded-lg border border-border"
|
|
style={{ background: "var(--card)" }}
|
|
>
|
|
<CompletionTemplatesTable
|
|
templates={templates}
|
|
isLoading={filtered.isPending}
|
|
hasError={filtered.error !== null}
|
|
canEdit={permissions.canEdit}
|
|
onView={(template) => setDialog({ template, mode: "view" })}
|
|
onEdit={(template) => setDialog({ template, mode: "edit" })}
|
|
/>
|
|
</div>
|
|
<div className="shrink-0 px-4 py-2">
|
|
<Text variant="caption" tone="muted" sx={{ fontSize: 11 }}>
|
|
{templateCountLabel(templates.length)}
|
|
</Text>
|
|
</div>
|
|
|
|
{dialog !== null && (
|
|
<CompletionTemplateDialog
|
|
key={dialog.template?.id ?? "new"}
|
|
template={dialog.template}
|
|
initialMode={dialog.mode}
|
|
permissions={permissions}
|
|
onClose={() => setDialog(null)}
|
|
onSaved={(template) => setDialog({ template, mode: "view" })}
|
|
/>
|
|
)}
|
|
</Box>
|
|
);
|
|
}
|