1 Commits
2 changed files with 36 additions and 14 deletions
+30 -8
View File
@@ -436,12 +436,14 @@ function SubmissionRow({
const [paidAmount, setPaidAmount] = useState(sub.paid_amount ?? '') const [paidAmount, setPaidAmount] = useState(sub.paid_amount ?? '')
const [status, setStatus] = useState(sub.payment_status || 'BELUM_BAYAR') const [status, setStatus] = useState(sub.payment_status || 'BELUM_BAYAR')
const [saving, setSaving] = useState(false) const [saving, setSaving] = useState(false)
const [isEditingLunas, setIsEditingLunas] = useState(false)
// Sync state when props change after save // Sync state when props change after save
useEffect(() => { useEffect(() => {
setBill(sub.bill ?? '') setBill(sub.bill ?? '')
setPaidAmount(sub.paid_amount ?? '') setPaidAmount(sub.paid_amount ?? '')
setStatus(sub.payment_status || 'BELUM_BAYAR') setStatus(sub.payment_status || 'BELUM_BAYAR')
setIsEditingLunas(false) // reset edit mode after save/refresh
}, [sub]) }, [sub])
const handleSave = async (overrideStatus?: string, overridePaid?: string | number) => { const handleSave = async (overrideStatus?: string, overridePaid?: string | number) => {
@@ -551,7 +553,7 @@ function SubmissionRow({
type="number" type="number"
placeholder="Rp" placeholder="Rp"
value={bill} value={bill}
disabled={sub.payment_status === 'LUNAS'} disabled={sub.payment_status === 'LUNAS' && !isEditingLunas}
onChange={e => { onChange={e => {
const val = e.target.value const val = e.target.value
setBill(val) setBill(val)
@@ -574,7 +576,7 @@ function SubmissionRow({
type="number" type="number"
placeholder="Rp" placeholder="Rp"
value={paidAmount} value={paidAmount}
disabled={sub.payment_status === 'LUNAS'} disabled={sub.payment_status === 'LUNAS' && !isEditingLunas}
onChange={e => { onChange={e => {
const val = e.target.value const val = e.target.value
setPaidAmount(val) setPaidAmount(val)
@@ -593,7 +595,7 @@ function SubmissionRow({
<label className="text-[10px] font-bold uppercase tracking-wider text-slate-400"> <label className="text-[10px] font-bold uppercase tracking-wider text-slate-400">
Status Status
</label> </label>
<Select value={status} onValueChange={setStatus} disabled={sub.payment_status === 'LUNAS'}> <Select value={status} onValueChange={setStatus} disabled={sub.payment_status === 'LUNAS' && !isEditingLunas}>
<SelectTrigger className="h-8 rounded-md text-xs font-semibold px-2"> <SelectTrigger className="h-8 rounded-md text-xs font-semibold px-2">
<SelectValue /> <SelectValue />
</SelectTrigger> </SelectTrigger>
@@ -606,7 +608,22 @@ function SubmissionRow({
</div> </div>
<div className="flex gap-2 w-full mt-1"> <div className="flex gap-2 w-full mt-1">
{sub.payment_status !== 'LUNAS' ? ( {sub.payment_status === 'LUNAS' && !isEditingLunas ? (
// Locked state — show paid badge + edit icon
<div className="flex items-center justify-between w-full">
<div className="flex-1 bg-emerald-50 dark:bg-emerald-900/30 text-emerald-600 dark:text-emerald-400 border border-emerald-200 dark:border-emerald-800 rounded-md h-8 flex items-center justify-center text-xs font-bold gap-1.5">
<Check className="w-4 h-4" /> Telah Lunas
</div>
<button
onClick={() => setIsEditingLunas(true)}
title="Edit tagihan"
className="ml-2 h-8 w-8 shrink-0 flex items-center justify-center rounded-md border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-800 text-slate-500 hover:text-[#1B2CC1] hover:border-[#1B2CC1] transition-colors"
>
<Pencil className="w-3.5 h-3.5" />
</button>
</div>
) : (
// Editable state — show save + cancel
<> <>
<Button <Button
size="sm" size="sm"
@@ -617,6 +634,15 @@ function SubmissionRow({
{saving ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <><Save className="w-3.5 h-3.5" /> Simpan</>} {saving ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <><Save className="w-3.5 h-3.5" /> Simpan</>}
</Button> </Button>
{sub.payment_status === 'LUNAS' && isEditingLunas && (
<button
onClick={() => setIsEditingLunas(false)}
className="h-8 px-3 shrink-0 flex items-center justify-center rounded-md border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-800 text-slate-500 hover:text-rose-600 hover:border-rose-300 text-xs font-semibold transition-colors"
>
Batal
</button>
)}
{currentBalance !== undefined && currentBalance > 0 && status !== 'LUNAS' && ( {currentBalance !== undefined && currentBalance > 0 && status !== 'LUNAS' && (
<Button <Button
size="sm" size="sm"
@@ -630,10 +656,6 @@ function SubmissionRow({
</Button> </Button>
)} )}
</> </>
) : (
<div className="w-full bg-emerald-50 dark:bg-emerald-900/30 text-emerald-600 dark:text-emerald-400 border border-emerald-200 dark:border-emerald-800 rounded-md h-8 flex items-center justify-center text-xs font-bold gap-1.5 cursor-not-allowed opacity-80">
<Check className="w-4 h-4" /> Telah Lunas
</div>
)} )}
</div> </div>
</> </>
+6 -6
View File
@@ -144,7 +144,7 @@ export default function ReportByPersonGrid({ data, balancesData = [], creatorId,
<th className="px-6 py-4 font-bold">Nama Pemesan</th> <th className="px-6 py-4 font-bold">Nama Pemesan</th>
<th className="px-6 py-4 font-bold text-center">Total PO</th> <th className="px-6 py-4 font-bold text-center">Total PO</th>
<th className="px-6 py-4 font-bold text-right">Total Piutang</th> <th className="px-6 py-4 font-bold text-right">Total Piutang</th>
<th className="px-6 py-4 font-bold text-center">Aksi</th> {/* <th className="px-6 py-4 font-bold text-center">Aksi</th> */}
</tr> </tr>
</thead> </thead>
<tbody className="divide-y divide-slate-100 dark:divide-slate-800"> <tbody className="divide-y divide-slate-100 dark:divide-slate-800">
@@ -191,7 +191,7 @@ export default function ReportByPersonGrid({ data, balancesData = [], creatorId,
<p className="text-[10px] text-slate-500 font-semibold mt-0.5">Lunas: {formatRupiah(userObj.totalPaid)}</p> <p className="text-[10px] text-slate-500 font-semibold mt-0.5">Lunas: {formatRupiah(userObj.totalPaid)}</p>
)} )}
</td> </td>
<td className="px-6 py-4 text-center"> {/* <td className="px-6 py-4 text-center">
{unpaid.length > 0 ? ( {unpaid.length > 0 ? (
<Button <Button
onClick={(e) => openModal(e, unpaid.map((s: any) => s.id), `Semua tagihan ${userObj.user.name}`, userObj.totalPiutang, userObj.user.id)} onClick={(e) => openModal(e, unpaid.map((s: any) => s.id), `Semua tagihan ${userObj.user.name}`, userObj.totalPiutang, userObj.user.id)}
@@ -201,7 +201,7 @@ export default function ReportByPersonGrid({ data, balancesData = [], creatorId,
<CheckCircle2 className="w-3.5 h-3.5" /> Lunasi Semua <CheckCircle2 className="w-3.5 h-3.5" /> Lunasi Semua
</Button> </Button>
):( <span className="text-[10px] font-bold text-slate-400">Selesai</span>)} ):( <span className="text-[10px] font-bold text-slate-400">Selesai</span>)}
</td> </td> */}
</tr> </tr>
{isExpanded && ( {isExpanded && (
@@ -219,7 +219,7 @@ export default function ReportByPersonGrid({ data, balancesData = [], creatorId,
<th className="px-4 py-2.5 text-left">Tgl Order</th> <th className="px-4 py-2.5 text-left">Tgl Order</th>
<th className="px-4 py-2.5 text-left">Status</th> <th className="px-4 py-2.5 text-left">Status</th>
<th className="px-4 py-2.5 text-right">Tagihan</th> <th className="px-4 py-2.5 text-right">Tagihan</th>
<th className="px-4 py-2.5 text-center">Aksi</th> {/* <th className="px-4 py-2.5 text-center">Aksi</th> */}
</tr> </tr>
</thead> </thead>
<tbody className="divide-y divide-slate-100 dark:divide-slate-700/50"> <tbody className="divide-y divide-slate-100 dark:divide-slate-700/50">
@@ -244,7 +244,7 @@ export default function ReportByPersonGrid({ data, balancesData = [], creatorId,
<td className={cn('px-4 py-2.5 text-right font-black', isUnpaid ? 'text-rose-600 dark:text-rose-400' : 'text-emerald-600 dark:text-emerald-400')}> <td className={cn('px-4 py-2.5 text-right font-black', isUnpaid ? 'text-rose-600 dark:text-rose-400' : 'text-emerald-600 dark:text-emerald-400')}>
{sub.bill ? formatRupiah(sub.bill) : 'Rp0'} {sub.bill ? formatRupiah(sub.bill) : 'Rp0'}
</td> </td>
<td className="px-4 py-2.5 text-center"> {/* <td className="px-4 py-2.5 text-center">
{isUnpaid ? ( {isUnpaid ? (
<Button <Button
onClick={(e) => openModal(e, [sub.id], `PO: ${sub.orderTitle}`, Number(sub.bill) || 0, sub.user.id)} onClick={(e) => openModal(e, [sub.id], `PO: ${sub.orderTitle}`, Number(sub.bill) || 0, sub.user.id)}
@@ -257,7 +257,7 @@ export default function ReportByPersonGrid({ data, balancesData = [], creatorId,
) : ( ) : (
<span className="text-[10px] font-bold text-slate-400">Selesai</span> <span className="text-[10px] font-bold text-slate-400">Selesai</span>
)} )}
</td> </td> */}
</tr> </tr>
) )
})} })}