OperationQueueSidePanel.tsx88 lines · main
1import {
2 Button,
3 KeyboardShortcut,
4 Sheet,
5 SheetContent,
6 SheetDescription,
7 SheetFooter,
8 SheetHeader,
9 SheetSection,
10 SheetTitle,
11} from 'ui'
12
13import { OperationList } from './OperationList'
14import { useOperationQueueActions } from '@/components/grid/hooks/useOperationQueueActions'
15import { DiscardChangesConfirmationDialog } from '@/components/ui-patterns/Dialogs/DiscardChangesConfirmationDialog'
16import { useConfirmOnClose } from '@/hooks/ui/useConfirmOnClose'
17import { useTableEditorStateSnapshot } from '@/state/table-editor'
18import { QueuedOperation } from '@/state/table-editor-operation-queue.types'
19
20export const OperationQueueSidePanel = () => {
21 const snap = useTableEditorStateSnapshot()
22
23 const visible = snap.sidePanel?.type === 'operation-queue'
24 const operations = snap.operationQueue.operations as readonly QueuedOperation[]
25
26 const { handleSave, handleCancel, isSaving } = useOperationQueueActions({
27 onSaveSuccess: snap.closeSidePanel,
28 onCancelSuccess: snap.closeSidePanel,
29 })
30
31 const { confirmOnClose, modalProps: closeConfirmationModalProps } = useConfirmOnClose({
32 checkIsDirty: () => true,
33 onClose: () => handleCancel(),
34 })
35
36 return (
37 <>
38 <Sheet open={visible} onOpenChange={(open) => !open && snap.closeSidePanel()}>
39 <SheetContent
40 className="flex flex-col gap-y-0"
41 onOpenAutoFocus={(event) => event.preventDefault()}
42 >
43 <SheetHeader>
44 <SheetTitle>Pending changes</SheetTitle>
45 <SheetDescription>
46 {operations.length} operation{operations.length !== 1 ? 's' : ''}
47 </SheetDescription>
48 </SheetHeader>
49
50 <SheetSection className="overflow-auto grow p-0">
51 <OperationList operations={operations} />
52 </SheetSection>
53
54 <SheetFooter className="justify-between!">
55 <Button
56 type="default"
57 onClick={snap.closeSidePanel}
58 iconRight={<KeyboardShortcut keys={['Meta', '.']} variant="inline" />}
59 >
60 Close
61 </Button>
62 <div className="flex space-x-3">
63 <Button
64 type="default"
65 onClick={confirmOnClose}
66 disabled={isSaving || operations.length === 0}
67 >
68 Discard
69 </Button>
70 <Button
71 onClick={handleSave}
72 disabled={isSaving || operations.length === 0}
73 loading={isSaving}
74 iconRight={
75 isSaving ? undefined : <KeyboardShortcut keys={['Meta', 's']} variant="inline" />
76 }
77 >
78 Save
79 </Button>
80 </div>
81 </SheetFooter>
82 </SheetContent>
83 </Sheet>
84
85 <DiscardChangesConfirmationDialog {...closeConfirmationModalProps} />
86 </>
87 )
88}