Skip to content

Commit 74f149a

Browse files
fix(dashboard): Fix editing of order history entries
1 parent 971ecca commit 74f149a

File tree

4 files changed

+141
-144
lines changed

4 files changed

+141
-144
lines changed

packages/dashboard/src/app/routes/_authenticated/_orders/components/order-history/order-history.tsx

Lines changed: 67 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,9 @@
11
import { HistoryEntry, HistoryEntryItem } from '@/vdb/components/shared/history-timeline/history-entry.js';
2+
import { HistoryNoteEditor } from '@/vdb/components/shared/history-timeline/history-note-editor.js';
23
import { HistoryNoteInput } from '@/vdb/components/shared/history-timeline/history-note-input.js';
3-
import {
4-
HistoryTimeline,
5-
useHistoryTimeline,
6-
} from '@/vdb/components/shared/history-timeline/history-timeline.js';
4+
import { HistoryTimeline } from '@/vdb/components/shared/history-timeline/history-timeline.js';
75
import { Badge } from '@/vdb/components/ui/badge.js';
86
import { Button } from '@/vdb/components/ui/button.js';
9-
import {
10-
DropdownMenu,
11-
DropdownMenuContent,
12-
DropdownMenuItem,
13-
DropdownMenuTrigger,
14-
} from '@/vdb/components/ui/dropdown-menu.js';
15-
import { Separator } from '@/vdb/components/ui/separator.js';
167
import { Trans } from '@/vdb/lib/trans.js';
178
import {
189
ArrowRightToLine,
@@ -22,11 +13,7 @@ import {
2213
ChevronUp,
2314
CreditCardIcon,
2415
Edit3,
25-
MoreVerticalIcon,
26-
PencilIcon,
27-
RefreshCcw,
2816
SquarePen,
29-
TrashIcon,
3017
Truck,
3118
UserX,
3219
} from 'lucide-react';
@@ -56,7 +43,29 @@ export function OrderHistory({
5643
onDeleteNote,
5744
}: Readonly<OrderHistoryProps>) {
5845
const [expandedGroups, setExpandedGroups] = useState<Set<number>>(new Set());
59-
const { editNote, deleteNote } = useHistoryTimeline();
46+
const [noteEditorOpen, setNoteEditorOpen] = useState(false);
47+
const [noteEditorNote, setNoteEditorNote] = useState<{
48+
noteId: string;
49+
note: string;
50+
isPrivate: boolean;
51+
}>({
52+
noteId: '',
53+
note: '',
54+
isPrivate: true,
55+
});
56+
57+
const handleEditNote = (noteId: string, note: string, isPrivate: boolean) => {
58+
setNoteEditorNote({ noteId, note, isPrivate });
59+
setNoteEditorOpen(true);
60+
};
61+
62+
const handleDeleteNote = (noteId: string) => {
63+
onDeleteNote?.(noteId);
64+
};
65+
66+
const handleNoteEditorSave = (noteId: string, note: string, isPrivate: boolean) => {
67+
onUpdateNote?.(noteId, note, isPrivate);
68+
};
6069

6170
const isPrimaryEvent = (entry: HistoryEntryItem) => {
6271
// Based on Angular component's isFeatured method
@@ -229,7 +238,7 @@ export function OrderHistory({
229238
<div className="mb-4">
230239
<HistoryNoteInput onAddNote={onAddNote} />
231240
</div>
232-
<HistoryTimeline onEditNote={onUpdateNote} onDeleteNote={onDeleteNote}>
241+
<HistoryTimeline>
233242
{groupedEntries.map((group, groupIndex) => {
234243
if (group.type === 'primary') {
235244
const entry = group.entry;
@@ -242,6 +251,8 @@ export function OrderHistory({
242251
title={getTitle(entry)}
243252
isPrimary={true}
244253
customer={order.customer}
254+
onEditNote={handleEditNote}
255+
onDeleteNote={handleDeleteNote}
245256
>
246257
{entry.type === 'ORDER_NOTE' && (
247258
<div className="space-y-2">
@@ -253,36 +264,6 @@ export function OrderHistory({
253264
>
254265
{entry.isPublic ? 'Public' : 'Private'}
255266
</Badge>
256-
<DropdownMenu>
257-
<DropdownMenuTrigger asChild>
258-
<Button variant="ghost" size="sm" className="h-6 w-6 p-0">
259-
<MoreVerticalIcon className="h-3 w-3" />
260-
</Button>
261-
</DropdownMenuTrigger>
262-
<DropdownMenuContent align="end">
263-
<DropdownMenuItem
264-
onClick={() =>
265-
editNote(
266-
entry.id,
267-
entry.data.note,
268-
!entry.isPublic,
269-
)
270-
}
271-
className="cursor-pointer"
272-
>
273-
<PencilIcon className="mr-2 h-4 w-4" />
274-
<Trans>Edit</Trans>
275-
</DropdownMenuItem>
276-
<Separator className="my-1" />
277-
<DropdownMenuItem
278-
onClick={() => deleteNote(entry.id)}
279-
className="cursor-pointer text-red-600 focus:text-red-600"
280-
>
281-
<TrashIcon className="mr-2 h-4 w-4" />
282-
<span>Delete</span>
283-
</DropdownMenuItem>
284-
</DropdownMenuContent>
285-
</DropdownMenu>
286267
</div>
287268
</div>
288269
)}
@@ -307,39 +288,33 @@ export function OrderHistory({
307288
</Trans>
308289
</p>
309290
)}
310-
{entry.type === 'ORDER_FULFILLMENT_TRANSITION' && entry.data.from !== 'Created' && (
311-
<p className="text-xs text-muted-foreground">
312-
<Trans>
313-
Fulfillment #{entry.data.fulfillmentId} from {entry.data.from} to {entry.data.to}
314-
</Trans>
315-
</p>
316-
)}
291+
{entry.type === 'ORDER_FULFILLMENT_TRANSITION' &&
292+
entry.data.from !== 'Created' && (
293+
<p className="text-xs text-muted-foreground">
294+
<Trans>
295+
Fulfillment #{entry.data.fulfillmentId} from {entry.data.from}{' '}
296+
to {entry.data.to}
297+
</Trans>
298+
</p>
299+
)}
317300
{entry.type === 'ORDER_FULFILLMENT' && (
318301
<p className="text-xs text-muted-foreground">
319-
<Trans>
320-
Fulfillment #{entry.data.fulfillmentId} created
321-
</Trans>
302+
<Trans>Fulfillment #{entry.data.fulfillmentId} created</Trans>
322303
</p>
323304
)}
324305
{entry.type === 'ORDER_MODIFIED' && (
325306
<p className="text-xs text-muted-foreground">
326-
<Trans>
327-
Order modification #{entry.data.modificationId}
328-
</Trans>
307+
<Trans>Order modification #{entry.data.modificationId}</Trans>
329308
</p>
330309
)}
331310
{entry.type === 'ORDER_CUSTOMER_UPDATED' && (
332311
<p className="text-xs text-muted-foreground">
333-
<Trans>
334-
Customer information updated
335-
</Trans>
312+
<Trans>Customer information updated</Trans>
336313
</p>
337314
)}
338315
{entry.type === 'ORDER_CANCELLATION' && (
339316
<p className="text-xs text-muted-foreground">
340-
<Trans>
341-
Order cancelled
342-
</Trans>
317+
<Trans>Order cancelled</Trans>
343318
</p>
344319
)}
345320
</HistoryEntry>
@@ -362,6 +337,8 @@ export function OrderHistory({
362337
title={getTitle(entry)}
363338
isPrimary={false}
364339
customer={order.customer}
340+
onEditNote={handleEditNote}
341+
onDeleteNote={handleDeleteNote}
365342
>
366343
{entry.type === 'ORDER_NOTE' && (
367344
<div className="space-y-1">
@@ -393,43 +370,38 @@ export function OrderHistory({
393370
{entry.type === 'ORDER_REFUND_TRANSITION' && (
394371
<p className="text-xs text-muted-foreground">
395372
<Trans>
396-
Refund #{entry.data.refundId} transitioned to {entry.data.to}
397-
</Trans>
398-
</p>
399-
)}
400-
{entry.type === 'ORDER_FULFILLMENT_TRANSITION' && entry.data.from !== 'Created' && (
401-
<p className="text-xs text-muted-foreground">
402-
<Trans>
403-
Fulfillment #{entry.data.fulfillmentId} from {entry.data.from} to {entry.data.to}
373+
Refund #{entry.data.refundId} transitioned to{' '}
374+
{entry.data.to}
404375
</Trans>
405376
</p>
406377
)}
378+
{entry.type === 'ORDER_FULFILLMENT_TRANSITION' &&
379+
entry.data.from !== 'Created' && (
380+
<p className="text-xs text-muted-foreground">
381+
<Trans>
382+
Fulfillment #{entry.data.fulfillmentId} from{' '}
383+
{entry.data.from} to {entry.data.to}
384+
</Trans>
385+
</p>
386+
)}
407387
{entry.type === 'ORDER_FULFILLMENT' && (
408388
<p className="text-xs text-muted-foreground">
409-
<Trans>
410-
Fulfillment #{entry.data.fulfillmentId} created
411-
</Trans>
389+
<Trans>Fulfillment #{entry.data.fulfillmentId} created</Trans>
412390
</p>
413391
)}
414392
{entry.type === 'ORDER_MODIFIED' && (
415393
<p className="text-xs text-muted-foreground">
416-
<Trans>
417-
Order modification #{entry.data.modificationId}
418-
</Trans>
394+
<Trans>Order modification #{entry.data.modificationId}</Trans>
419395
</p>
420396
)}
421397
{entry.type === 'ORDER_CUSTOMER_UPDATED' && (
422398
<p className="text-xs text-muted-foreground">
423-
<Trans>
424-
Customer information updated
425-
</Trans>
399+
<Trans>Customer information updated</Trans>
426400
</p>
427401
)}
428402
{entry.type === 'ORDER_CANCELLATION' && (
429403
<p className="text-xs text-muted-foreground">
430-
<Trans>
431-
Order cancelled
432-
</Trans>
404+
<Trans>Order cancelled</Trans>
433405
</p>
434406
)}
435407
</HistoryEntry>
@@ -462,6 +434,15 @@ export function OrderHistory({
462434
}
463435
})}
464436
</HistoryTimeline>
437+
<HistoryNoteEditor
438+
key={noteEditorNote.noteId}
439+
note={noteEditorNote.note}
440+
onNoteChange={handleNoteEditorSave}
441+
open={noteEditorOpen}
442+
onOpenChange={setNoteEditorOpen}
443+
noteId={noteEditorNote.noteId}
444+
isPrivate={noteEditorNote.isPrivate}
445+
/>
465446
</div>
466447
);
467448
}

packages/dashboard/src/lib/components/shared/history-timeline/history-entry.tsx

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
1+
import { Badge } from '@/vdb/components/ui/badge.js';
2+
import { Button } from '@/vdb/components/ui/button.js';
3+
import {
4+
DropdownMenu,
5+
DropdownMenuContent,
6+
DropdownMenuItem,
7+
DropdownMenuTrigger,
8+
} from '@/vdb/components/ui/dropdown-menu.js';
9+
import { Separator } from '@/vdb/components/ui/separator.js';
10+
import { Trans } from '@/vdb/lib/trans.js';
111
import { cn } from '@/vdb/lib/utils.js';
12+
import { MoreVerticalIcon, PencilIcon, TrashIcon } from 'lucide-react';
213
import { HistoryEntryDate } from './history-entry-date.js';
314

415
export interface HistoryEntryItem {
@@ -27,6 +38,8 @@ interface HistoryEntryProps {
2738
children: React.ReactNode;
2839
isPrimary?: boolean;
2940
customer?: OrderCustomer | null;
41+
onEditNote?: (noteId: string, note: string, isPrivate: boolean) => void;
42+
onDeleteNote?: (noteId: string) => void;
3043
}
3144

3245
export function HistoryEntry({
@@ -37,6 +50,8 @@ export function HistoryEntry({
3750
children,
3851
isPrimary = true,
3952
customer,
53+
onEditNote,
54+
onDeleteNote,
4055
}: Readonly<HistoryEntryProps>) {
4156
const getIconColor = (type: string) => {
4257
// Check for success states (payment settled, order delivered)
@@ -97,7 +112,57 @@ export function HistoryEntry({
97112
>
98113
{title}
99114
</h4>
100-
<div className="mt-1">{children}</div>
115+
<div className="mt-1">
116+
{entry.type === 'ORDER_NOTE' ? (
117+
<div className={`space-y-${isPrimary ? '2' : '1'}`}>
118+
<p className={`${isPrimary ? 'text-sm' : 'text-xs'} text-foreground`}>
119+
{entry.data.note}
120+
</p>
121+
<div className="flex items-center gap-2">
122+
<Badge
123+
variant={entry.isPublic ? 'outline' : 'secondary'}
124+
className="text-xs"
125+
>
126+
{entry.isPublic ? 'Public' : 'Private'}
127+
</Badge>
128+
{isPrimary && onEditNote && onDeleteNote && (
129+
<DropdownMenu>
130+
<DropdownMenuTrigger asChild>
131+
<Button variant="ghost" size="sm" className="h-6 w-6 p-0">
132+
<MoreVerticalIcon className="h-3 w-3" />
133+
</Button>
134+
</DropdownMenuTrigger>
135+
<DropdownMenuContent align="end">
136+
<DropdownMenuItem
137+
onClick={() => {
138+
onEditNote(
139+
entry.id,
140+
entry.data.note,
141+
!entry.isPublic,
142+
);
143+
}}
144+
className="cursor-pointer"
145+
>
146+
<PencilIcon className="mr-2 h-4 w-4" />
147+
<Trans>Edit</Trans>
148+
</DropdownMenuItem>
149+
<Separator className="my-1" />
150+
<DropdownMenuItem
151+
onClick={() => onDeleteNote(entry.id)}
152+
className="cursor-pointer text-red-600 focus:text-red-600"
153+
>
154+
<TrashIcon className="mr-2 h-4 w-4" />
155+
<span>Delete</span>
156+
</DropdownMenuItem>
157+
</DropdownMenuContent>
158+
</DropdownMenu>
159+
)}
160+
</div>
161+
</div>
162+
) : (
163+
children
164+
)}
165+
</div>
101166
</div>
102167

103168
<div className="flex items-center gap-2 ml-4 flex-shrink-0">

0 commit comments

Comments
 (0)