'use client' import { useEffect, useState } from 'react' import { getMyOrders, createOrder, updateOrder, updateOrderStatus, deleteOrder, getSessionUser, } from '@/app/actions' import { Button, buttonVariants } from '@/components/ui/button' import { cn } from '@/lib/utils' import { ShareButton } from '@/components/ShareButton' 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' import { Checkbox } from '@/components/ui/checkbox' import { format, isToday } from 'date-fns' import { id as idLocale } from 'date-fns/locale' import Link from 'next/link' import { PlusCircle, MinusCircle, Copy, FileText, Loader2, Plus, Users, Sparkles, Layers, Pencil, Lock, Trash2, AlertTriangle, ChevronLeft, ChevronRight, } from 'lucide-react' import PiutangManager from '@/components/PiutangManager' export default function MyOrdersPage() { const [userId, setUserId] = useState(null) const [orders, setOrders] = useState([]) const [loading, setLoading] = useState(true) const [isCreateOpen, setIsCreateOpen] = useState(false) const [editingOrder, setEditingOrder] = useState(null) const [orderToDelete, setOrderToDelete] = useState(null) const [orderToDuplicate, setOrderToDuplicate] = useState(null) const [deleting, setDeleting] = useState(false) const [mainTab, setMainTab] = useState<'PO' | 'PIUTANG'>('PO') const [activeTab, setActiveTab] = useState<'ALL' | 'OPEN' | 'DRAFT' | 'CLOSE'>('ALL') const [currentPage, setCurrentPage] = useState(1) const [searchQuery, setSearchQuery] = useState('') const ITEMS_PER_PAGE = 5 useEffect(() => { const init = async () => { const user = await getSessionUser() if (user?.id) { setUserId(user.id) loadOrders(user.id) } } init() }, []) const loadOrders = async (id: string) => { setLoading(true) const data = await getMyOrders(id) setOrders(data) setLoading(false) } const handleStatusChange = async (orderId: string, newStatus: string) => { const res = await updateOrderStatus(orderId, newStatus) if (res.success && userId) { loadOrders(userId) } } const handleDelete = async () => { if (!orderToDelete) return setDeleting(true) const res = await deleteOrder(orderToDelete.id) if (res.success && userId) { setOrderToDelete(null) loadOrders(userId) } setDeleting(false) } const getStatusBadge = (status: string) => { switch (status) { case 'OPEN': return ( ● OPEN ) case 'CLOSE': return ( ● CLOSE ) default: return ( ● DRAFT ) } } const filteredOrders = orders.filter((o) => { const matchTab = activeTab === 'ALL' ? true : o.status === activeTab const matchSearch = o.title.toLowerCase().includes(searchQuery.toLowerCase()) return matchTab && matchSearch }) // Pagination logic const totalPages = Math.ceil(filteredOrders.length / ITEMS_PER_PAGE) const startIndex = (currentPage - 1) * ITEMS_PER_PAGE const paginatedOrders = filteredOrders.slice(startIndex, startIndex + ITEMS_PER_PAGE) // Reset page when tab or search changes useEffect(() => { setCurrentPage(1) }, [activeTab, searchQuery]) if (loading) { return (
Memuat data PO Anda...
) } return (
{/* Main Tab Switcher */}
{mainTab === 'PO' ? ( <> {/* 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 */} Buka Jasa PO Baru { setIsCreateOpen(false) 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
)}
{/* 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) => ( ))}
)}
)} ) : ( )}
) } function CreateOrderModal({ userId, onSuccess, initialData, }: { userId: string onSuccess: () => void initialData?: any }) { const [title, setTitle] = useState(initialData ? `${initialData.title} (Copy)` : '') const [description, setDescription] = useState(initialData ? initialData.description || '' : '') const [allowCustom, setAllowCustom] = useState(initialData ? initialData.allow_custom : false) const [items, setItems] = useState<{ id: string; name: string }[]>( initialData && initialData.available_items?.length > 0 ? initialData.available_items.map((ai: any) => ({ id: Math.random().toString(), name: ai.name, })) : [{ id: '1', name: '' }] ) const [loading, setLoading] = useState(false) const [error, setError] = useState('') const addItem = () => setItems([...items, { id: Math.random().toString(), name: '' }]) const removeItem = (id: string) => setItems(items.filter((i: { id: string; name: string }) => i.id !== id)) const updateItem = (id: string, name: string) => setItems(items.map((i: { id: string; name: string }) => (i.id === id ? { ...i, name } : i))) const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() setError('') if (!title.trim()) return setError('Judul PO wajib diisi.') const validItems = items .filter((i: { id: string; name: string }) => i.name.trim()) .map((i: { id: string; name: string }) => i.name.trim()) if (!allowCustom && validItems.length === 0) { return setError( 'Wajib menambahkan minimal 1 menu pilihan jika tidak mengizinkan custom item.' ) } setLoading(true) const res = await createOrder({ creator_id: userId, title: title.trim(), description: description.trim(), date: new Date(), allow_custom: allowCustom, available_items: validItems, }) if (res.success) { onSuccess() } else { setError(res.error || 'Gagal membuat order') } setLoading(false) } return (
Form Buka PO Buka Jasa Titip Baru

Tentukan nama pesanan dan daftar menu yang bisa dipesan teman kantor.

setTitle(e.target.value)} className="h-11 rounded-xl border-slate-200 focus-visible:border-[#1B2CC1] focus-visible:ring-4 focus-visible:ring-[#1B2CC1]/15 dark:border-slate-800" />