feat: implement flexible payment processing with partial cash payments and automatic balance deduction in reports
This commit is contained in:
@@ -10,7 +10,7 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Checkbox } from '@/components/ui/checkbox'
|
||||
import { format } from 'date-fns'
|
||||
import { format, isToday } from 'date-fns'
|
||||
import { id as idLocale } from 'date-fns/locale'
|
||||
import Link from 'next/link'
|
||||
import {
|
||||
@@ -306,10 +306,10 @@ export default function MyOrdersPage() {
|
||||
return (
|
||||
<div
|
||||
key={order.id}
|
||||
className="flex flex-col md:flex-row h-full md:h-auto rounded-2xl border border-slate-200/90 dark:border-slate-800 bg-white dark:bg-slate-900 shadow-sm hover:shadow-md hover:border-[#1B2CC1]/40 transition-all overflow-hidden"
|
||||
className="flex flex-col md:flex-row shrink-0 rounded-2xl border border-slate-200/90 dark:border-slate-800 bg-white dark:bg-slate-900 shadow-sm hover:shadow-md hover:border-[#1B2CC1]/40 transition-all overflow-hidden"
|
||||
>
|
||||
{/* Left: Info */}
|
||||
<div className="flex-1 p-5 md:border-r border-slate-100 dark:border-slate-800/80 flex flex-col justify-center">
|
||||
<div className="w-full md:flex-1 p-5 md:border-r border-slate-100 dark:border-slate-800/80 flex flex-col justify-center">
|
||||
<div className="flex justify-between items-start gap-4">
|
||||
<h3 className="text-xl font-bold text-slate-900 dark:text-white line-clamp-2 leading-snug flex-1 min-w-0">
|
||||
{order.title}
|
||||
@@ -358,14 +358,14 @@ export default function MyOrdersPage() {
|
||||
</div>
|
||||
|
||||
{/* Right: Actions */}
|
||||
<div className="w-full md:w-64 p-5 bg-slate-50/70 dark:bg-slate-800/40 flex flex-col justify-center gap-3 md:border-l border-slate-100 dark:border-slate-800/80 mt-auto md:mt-0">
|
||||
<div className="grid grid-cols-2 gap-2 w-full">
|
||||
<div className="w-full md:w-[260px] p-4 sm:p-5 bg-slate-50/70 dark:bg-slate-800/40 flex flex-col justify-center gap-3 shrink-0">
|
||||
<div className="flex flex-row gap-2 w-full">
|
||||
{/* Detail Link */}
|
||||
<Link
|
||||
href={`/my-orders/${order.id}`}
|
||||
className={cn(
|
||||
buttonVariants({ variant: "outline", size: "sm" }),
|
||||
"w-full h-10 rounded-xl border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 font-bold text-xs gap-1.5 hover:bg-blue-50/60 hover:text-[#1B2CC1] hover:border-[#1B2CC1]/40 shadow-2xs transition-all flex items-center justify-center px-2"
|
||||
"flex-1 h-10 rounded-xl border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 font-bold text-xs gap-1.5 hover:bg-blue-50/60 hover:text-[#1B2CC1] hover:border-[#1B2CC1]/40 shadow-sm transition-all flex items-center justify-center px-2"
|
||||
)}
|
||||
>
|
||||
<FileText className="w-4 h-4 text-[#1B2CC1] shrink-0" />
|
||||
@@ -373,12 +373,18 @@ export default function MyOrdersPage() {
|
||||
</Link>
|
||||
|
||||
{/* Status Action Button */}
|
||||
<div className="w-full">
|
||||
<div className="flex-1">
|
||||
{order.status === 'DRAFT' && (
|
||||
<Button
|
||||
onClick={() => handleStatusChange(order.id, 'OPEN')}
|
||||
className="w-full h-10 rounded-xl bg-emerald-600 hover:bg-emerald-700 text-white font-bold text-xs shadow-sm gap-1.5 transition-all cursor-pointer px-2"
|
||||
title="Buka PO"
|
||||
disabled={!isToday(new Date(order.date))}
|
||||
className={cn(
|
||||
"w-full h-10 rounded-xl font-bold text-xs shadow-sm gap-1.5 transition-all px-2",
|
||||
isToday(new Date(order.date))
|
||||
? "bg-emerald-600 hover:bg-emerald-700 text-white cursor-pointer"
|
||||
: "bg-slate-200 text-slate-500 cursor-not-allowed opacity-50"
|
||||
)}
|
||||
title={isToday(new Date(order.date)) ? "Buka PO" : "Hanya PO hari ini yang bisa dibuka"}
|
||||
>
|
||||
<Sparkles className="w-3.5 h-3.5 shrink-0" />
|
||||
<span className="truncate">Buka</span>
|
||||
@@ -397,8 +403,14 @@ export default function MyOrdersPage() {
|
||||
{order.status === 'CLOSE' && (
|
||||
<Button
|
||||
onClick={() => handleStatusChange(order.id, 'OPEN')}
|
||||
className="w-full h-10 rounded-xl bg-emerald-600 hover:bg-emerald-700 text-white font-bold text-xs shadow-sm gap-1.5 transition-all cursor-pointer px-2"
|
||||
title="Buka Kembali PO"
|
||||
disabled={!isToday(new Date(order.date))}
|
||||
className={cn(
|
||||
"w-full h-10 rounded-xl font-bold text-xs shadow-sm gap-1.5 transition-all px-2",
|
||||
isToday(new Date(order.date))
|
||||
? "bg-emerald-600 hover:bg-emerald-700 text-white cursor-pointer"
|
||||
: "bg-slate-200 text-slate-500 cursor-not-allowed opacity-50"
|
||||
)}
|
||||
title={isToday(new Date(order.date)) ? "Buka Kembali PO" : "Hanya PO hari ini yang bisa dibuka"}
|
||||
>
|
||||
<Sparkles className="w-3.5 h-3.5 shrink-0" />
|
||||
<span className="truncate">Buka</span>
|
||||
@@ -408,33 +420,33 @@ export default function MyOrdersPage() {
|
||||
</div>
|
||||
|
||||
{/* Utility Tools Row */}
|
||||
<div className="grid grid-cols-3 gap-1.5 pt-2 border-t border-slate-200/60 dark:border-slate-800/60">
|
||||
<div className="flex items-center justify-between gap-1 pt-3 border-t border-slate-200/60 dark:border-slate-800/60">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
disabled={isClosed}
|
||||
disabled={isClosed || !isToday(new Date(order.date))}
|
||||
onClick={() => setEditingOrder(order)}
|
||||
className={cn(
|
||||
"h-8 rounded-lg font-bold text-[11px] gap-1 px-1.5 transition-all",
|
||||
isClosed
|
||||
"flex-1 h-8 rounded-lg font-bold text-[10px] sm:text-[11px] gap-1 px-1 transition-all",
|
||||
(isClosed || !isToday(new Date(order.date)))
|
||||
? "opacity-35 cursor-not-allowed text-slate-400"
|
||||
: "text-slate-600 hover:text-[#1B2CC1] hover:bg-[#1B2CC1]/10 dark:text-slate-300"
|
||||
)}
|
||||
title={isClosed ? "PO sudah CLOSE" : "Edit PO"}
|
||||
title={isClosed ? "PO sudah CLOSE" : !isToday(new Date(order.date)) ? "Hanya PO hari ini yang bisa diedit" : "Edit PO"}
|
||||
>
|
||||
<Pencil className="w-3.5 h-3.5" />
|
||||
<span>Edit</span>
|
||||
<Pencil className="w-3.5 h-3.5 shrink-0" />
|
||||
<span className="truncate">Edit</span>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setOrderToDuplicate(order)}
|
||||
className="h-8 rounded-lg font-bold text-[11px] gap-1 px-1.5 text-slate-600 hover:text-slate-900 hover:bg-slate-200/60 dark:text-slate-300 transition-all"
|
||||
className="flex-1 h-8 rounded-lg font-bold text-[10px] sm:text-[11px] gap-1 px-1 text-slate-600 hover:text-slate-900 hover:bg-slate-200/60 dark:text-slate-300 transition-all"
|
||||
title="Duplikasi PO ini"
|
||||
>
|
||||
<Copy className="w-3.5 h-3.5" />
|
||||
<span>Duplikat</span>
|
||||
<Copy className="w-3.5 h-3.5 shrink-0" />
|
||||
<span className="truncate">Duplikat</span>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
@@ -443,15 +455,15 @@ export default function MyOrdersPage() {
|
||||
disabled={!canDelete}
|
||||
onClick={() => setOrderToDelete(order)}
|
||||
className={cn(
|
||||
"h-8 rounded-lg font-bold text-[11px] gap-1 px-1.5 transition-all",
|
||||
"flex-1 h-8 rounded-lg font-bold text-[10px] sm:text-[11px] gap-1 px-1 transition-all",
|
||||
!canDelete
|
||||
? "opacity-35 cursor-not-allowed text-slate-400"
|
||||
: "text-red-600 hover:text-red-700 hover:bg-red-50 dark:hover:bg-red-950/40"
|
||||
)}
|
||||
title={!canDelete ? "PO OPEN tidak dapat dihapus" : "Hapus PO"}
|
||||
>
|
||||
<Trash2 className="w-3.5 h-3.5" />
|
||||
<span>Hapus</span>
|
||||
<Trash2 className="w-3.5 h-3.5 shrink-0" />
|
||||
<span className="truncate">Hapus</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user