From 1337af0102d897cf2c792ec9d463a24b7971851b Mon Sep 17 00:00:00 2001 From: Firman Ramdhani <33869609+firmanramdhani@users.noreply.github.com> Date: Wed, 16 Sep 2026 14:23:12 +0700 Subject: [PATCH] refactor: remove duplicate order feature and unused UI imports in my-orders page --- src/app/(app)/my-orders/page.tsx | 907 +++++++++++++++---------------- src/app/actions.ts | 101 +--- 2 files changed, 465 insertions(+), 543 deletions(-) diff --git a/src/app/(app)/my-orders/page.tsx b/src/app/(app)/my-orders/page.tsx index b68ca2a..a2c8346 100644 --- a/src/app/(app)/my-orders/page.tsx +++ b/src/app/(app)/my-orders/page.tsx @@ -5,30 +5,15 @@ import { getMyOrders, createOrder, updateOrder, - duplicateOrder, updateOrderStatus, deleteOrder, getSessionUser, } from '@/app/actions' import { Button, buttonVariants } from '@/components/ui/button' import { cn } from '@/lib/utils' -import { - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from '@/components/ui/card' -import { Badge } from '@/components/ui/badge' + import { ShareButton } from '@/components/ShareButton' -import { - Dialog, - DialogContent, - DialogHeader, - DialogTitle, - DialogTrigger, -} from '@/components/ui/dialog' +import { Dialog, DialogContent, DialogTitle, DialogTrigger } from '@/components/ui/dialog' import { Textarea } from '@/components/ui/textarea' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' @@ -186,468 +171,474 @@ export default function MyOrdersPage() { <> {/* Top Controls & Segmented Control */}
-
- {/* Segmented Control / Tabs */} -
- {(['ALL', 'OPEN', 'DRAFT', 'CLOSE'] as const).map((tab) => ( - + ))} +
+ + {/* Search Input */} +
+
+ + + +
+ setSearchQuery(e.target.value)} + className="h-10 w-full rounded-xl border-slate-200 bg-slate-50 pl-9 text-sm focus-visible:ring-[#1B2CC1] dark:border-slate-800 dark:bg-slate-900" + /> +
+
+ + {/* Action Button */} + + - {tab === 'ALL' ? 'Semua PO' : tab} - - ({tab === 'ALL' ? orders.length : orders.filter((o) => o.status === tab).length}) - - - ))} + Buka Jasa PO Baru + + { + setIsCreateOpen(false) + if (userId) loadOrders(userId) + }} + /> +
- {/* Search Input */} -
-
- - - -
- setSearchQuery(e.target.value)} - className="h-10 w-full rounded-xl border-slate-200 bg-slate-50 pl-9 text-sm focus-visible:ring-[#1B2CC1] dark:border-slate-800 dark:bg-slate-900" - /> -
- + {/* Edit Order Modal */} + {editingOrder && ( + !open && setEditingOrder(null)}> + setEditingOrder(null)} + onSuccess={() => { + setEditingOrder(null) + if (userId) loadOrders(userId) + }} + /> + + )} - {/* Action Button */} - - - Buka Jasa PO Baru - - { - setIsCreateOpen(false) - if (userId) loadOrders(userId) - }} - /> - - + {/* Duplicate Order Modal */} + {orderToDuplicate && ( + !open && setOrderToDuplicate(null)} + > + { + setOrderToDuplicate(null) + if (userId) loadOrders(userId) + }} + /> + + )} - {/* Edit Order Modal */} - {editingOrder && ( - !open && setEditingOrder(null)}> - setEditingOrder(null)} - onSuccess={() => { - setEditingOrder(null) - if (userId) loadOrders(userId) - }} - /> - - )} - - {/* Duplicate Order Modal */} - {orderToDuplicate && ( - !open && setOrderToDuplicate(null)} - > - { - setOrderToDuplicate(null) - if (userId) loadOrders(userId) - }} - /> - - )} - - {/* Delete Confirmation Modal */} - {orderToDelete && ( - !open && setOrderToDelete(null)}> - -
-
- -
-
- - Hapus Jasa PO Ini? - -

- Tindakan ini permanen dan tidak dapat dibatalkan. -

-
-
- -
-
-

- {orderToDelete.title} -

-

- Status:{' '} - - {orderToDelete.status} - {' '} - • {orderToDelete.submissions?.length || 0} titipan pemesan -

-
- -

- Seluruh data pesanan dan daftar menu yang ada di dalam PO ini akan dihapus dari - sistem. -

- -
- - -
-
-
-
- )} - - {/* Order List */} - {filteredOrders.length === 0 ? ( -
-
- -
-

- {activeTab === 'ALL' ? 'Belum Ada Jasa PO' : `Tidak Ada PO Berstatus ${activeTab}`} -

-

- Mulai buka jasa titip pesanan makanan atau kebutuhan untuk teman kantor. -

- -
- ) : ( -
-
- {paginatedOrders.map((order) => { - const date = new Date(order.date) - const isClosed = order.status === 'CLOSE' - const isDraft = order.status === 'DRAFT' - const canDelete = isDraft || isClosed - - return ( -
- {/* Left: Info */} -
-
-
-

- {order.title} -

- {order.description && ( -

- {order.description} -

- )} -
-
- - {format(date, 'EEEE, dd MMM yyyy', { locale: idLocale })} - - {getStatusBadge(order.status)} -
-
- -
-
- - - {order.submissions.length} Orang Menitip - - {isClosed && order.submissions.length > 0 && ( -
- - Lunas:{' '} - { - order.submissions.filter((s: any) => s.payment_status === 'LUNAS') - .length - } - - - Belum:{' '} - { - order.submissions.filter((s: any) => s.payment_status !== 'LUNAS') - .length - } - -
- )} -
- -
- -
- {order.available_items.length > 0 && ( - - {order.available_items.length} Menu Pilihan - - )} - {order.allow_custom && ( -
- Custom Item Aktif -
- )} -
-
+ {/* Delete Confirmation Modal */} + {orderToDelete && ( + !open && setOrderToDelete(null)}> + +
+
+
- - {/* Right: Actions */} -
-
- {/* Detail Link */} - - - Detail - - - {/* Status Action Button */} -
- {order.status === 'DRAFT' && ( - - )} - {order.status === 'OPEN' && ( - - )} - {order.status === 'CLOSE' && ( - - )} -
-
- - {/* Utility Tools Row */} -
- - - - - - - {order.status === 'OPEN' && ( - - )} -
+
+ + Hapus Jasa PO Ini? + +

+ Tindakan ini permanen dan tidak dapat dibatalkan. +

- ) - })} -
- {/* Pagination Controls */} - {totalPages > 1 && ( -
- - Menampilkan{' '} - - {(currentPage - 1) * ITEMS_PER_PAGE + 1} - {' '} - hingga{' '} - - {Math.min(currentPage * ITEMS_PER_PAGE, filteredOrders.length)} - {' '} - dari{' '} - - {filteredOrders.length} - {' '} - PO - +
+
+

+ {orderToDelete.title} +

+

+ Status:{' '} + + {orderToDelete.status} + {' '} + • {orderToDelete.submissions?.length || 0} titipan pemesan +

+
-
- +

+ Seluruh data pesanan dan daftar menu yang ada di dalam PO ini akan dihapus dari + sistem. +

-
- {Array.from({ length: totalPages }, (_, i) => i + 1).map((page) => ( +
- ))} + +
+ +
+ )} - + {/* Order List */} + {filteredOrders.length === 0 ? ( +
+
+
+

+ {activeTab === 'ALL' ? 'Belum Ada Jasa PO' : `Tidak Ada PO Berstatus ${activeTab}`} +

+

+ Mulai buka jasa titip pesanan makanan atau kebutuhan untuk teman kantor. +

+ +
+ ) : ( +
+
+ {paginatedOrders.map((order) => { + const date = new Date(order.date) + const isClosed = order.status === 'CLOSE' + const isDraft = order.status === 'DRAFT' + const canDelete = isDraft || isClosed + + return ( +
+ {/* Left: Info */} +
+
+
+

+ {order.title} +

+ {order.description && ( +

+ {order.description} +

+ )} +
+
+ + {format(date, 'EEEE, dd MMM yyyy', { locale: idLocale })} + + {getStatusBadge(order.status)} +
+
+ +
+
+ + + {order.submissions.length} Orang Menitip + + {isClosed && order.submissions.length > 0 && ( +
+ + Lunas:{' '} + { + order.submissions.filter( + (s: any) => s.payment_status === 'LUNAS' + ).length + } + + + Belum:{' '} + { + order.submissions.filter( + (s: any) => s.payment_status !== 'LUNAS' + ).length + } + +
+ )} +
+ +
+ +
+ {order.available_items.length > 0 && ( + + {order.available_items.length} Menu Pilihan + + )} + {order.allow_custom && ( +
+ Custom Item Aktif +
+ )} +
+
+
+ + {/* Right: Actions */} +
+
+ {/* Detail Link */} + + + Detail + + + {/* Status Action Button */} +
+ {order.status === 'DRAFT' && ( + + )} + {order.status === 'OPEN' && ( + + )} + {order.status === 'CLOSE' && ( + + )} +
+
+ + {/* Utility Tools Row */} +
+ + + + + + + {order.status === 'OPEN' && ( + + )} +
+
+
+ ) + })} +
+ + {/* Pagination Controls */} + {totalPages > 1 && ( +
+ + Menampilkan{' '} + + {(currentPage - 1) * ITEMS_PER_PAGE + 1} + {' '} + hingga{' '} + + {Math.min(currentPage * ITEMS_PER_PAGE, filteredOrders.length)} + {' '} + dari{' '} + + {filteredOrders.length} + {' '} + PO + + +
+ + +
+ {Array.from({ length: totalPages }, (_, i) => i + 1).map((page) => ( + + ))} +
+ + +
+
+ )}
)} -
- )} ) : ( diff --git a/src/app/actions.ts b/src/app/actions.ts index 5374e7a..01a73b1 100644 --- a/src/app/actions.ts +++ b/src/app/actions.ts @@ -271,37 +271,6 @@ export async function createOrder(data: { } } -export async function duplicateOrder(order_id: string) { - try { - const oldOrder = await prisma.order.findUnique({ - where: { id: order_id }, - include: { available_items: true }, - }) - if (!oldOrder) return { success: false, error: 'Order tidak ditemukan' } - - const newOrder = await prisma.order.create({ - data: { - title: oldOrder.title + ' (Copy)', - description: oldOrder.description, - date: new Date(), - allow_custom: oldOrder.allow_custom, - creator_id: oldOrder.creator_id, - status: 'DRAFT', - available_items: { - create: oldOrder.available_items.map((ai) => ({ - name: ai.name, - is_sold_out: ai.is_sold_out, - })), - }, - }, - }) - revalidatePath('/my-orders') - return { success: true, order: newOrder } - } catch (e) { - return { success: false, error: 'Gagal menduplikasi order.' } - } -} - export async function updateOrder( order_id: string, data: { @@ -440,48 +409,6 @@ export async function updateSubmissionPayment( } } -export async function updateBulkSubmissionPayment( - submission_ids: string[], - payment_status: string, - use_balance: boolean = false -) { - try { - if (payment_status === 'LUNAS') { - const submissions = await prisma.submission.findMany({ - where: { id: { in: submission_ids } }, - }) - const ops = submissions.map((sub) => - prisma.submission.update({ - where: { id: sub.id }, - data: { - payment_status, - paid_amount: use_balance - ? sub.paid_amount || 0 - : sub.paid_amount != null - ? sub.paid_amount - : sub.bill, - saldo_used: use_balance ? Math.max(0, (sub.bill || 0) - (sub.paid_amount || 0)) : 0, - }, - }) - ) - await prisma.$transaction(ops) - } else { - await prisma.submission.updateMany({ - where: { id: { in: submission_ids } }, - data: { payment_status }, - }) - } - revalidatePath(`/my-orders`) - revalidatePath(`/my-purchases`) - revalidatePath(`/reports`) - revalidatePath(`/balances`) - return { success: true } - } catch (e) { - console.error(e) - return { success: false, error: 'Gagal mengubah status tagihan massal.' } - } -} - export async function processBulkPayment(data: { submission_ids: string[] cash_amount: number @@ -570,19 +497,23 @@ export async function processBulkPayment(data: { // Partially covered -> BELUM_BAYAR let balanceToUse = Math.min(remainingBalance, totalAvailable) remainingBalance -= balanceToUse - + let cashToUse = totalAvailable - balanceToUse remainingCash -= cashToUse - + let finalPaid = prevPaid + cashToUse let finalSaldoUsed = prevSaldoUsed + balanceToUse - + totalAvailable = 0 ops.push( prisma.submission.update({ where: { id: sub.id }, - data: { payment_status: 'BELUM_BAYAR', paid_amount: finalPaid, saldo_used: finalSaldoUsed }, + data: { + payment_status: 'BELUM_BAYAR', + paid_amount: finalPaid, + saldo_used: finalSaldoUsed, + }, }) ) } @@ -909,7 +840,7 @@ export async function getPiutangSummary(creator_id: string) { }) const grouped = new Map() - + unpaidSubmissions.forEach((sub) => { if (!grouped.has(sub.user_id)) { grouped.set(sub.user_id, { @@ -918,20 +849,20 @@ export async function getPiutangSummary(creator_id: string) { submissions: [], }) } - + const u = grouped.get(sub.user_id) - + const paidAmount = (sub.paid_amount || 0) + (sub.saldo_used || 0) const unpaid = Math.max(0, (sub.bill || 0) - paidAmount) - + if (unpaid > 0) { u.totalPiutang += unpaid u.submissions.push({ - ...sub, - unpaidAmount: unpaid + ...sub, + unpaidAmount: unpaid, }) } }) - - return Array.from(grouped.values()).filter(g => g.totalPiutang > 0) + + return Array.from(grouped.values()).filter((g) => g.totalPiutang > 0) }