86 lines
2.6 KiB
TypeScript
86 lines
2.6 KiB
TypeScript
"use client"
|
|
|
|
import { BillStatus } from "@garage/api"
|
|
import { Badge, badgeVariants } from "@/shared/components/ui/badge"
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@/shared/components/ui/select"
|
|
import { confirm } from "@/shared/components/confirm-dialog"
|
|
import { useAuthApi } from "@/shared/useApi"
|
|
import { useRouter } from "next/navigation"
|
|
import { toast } from "sonner"
|
|
import { useState } from "react"
|
|
import { formatEnum } from "@/shared/utils/formatters"
|
|
|
|
const STATUS_TRIGGER_CLASS_NAMES: Record<string, string> = {
|
|
draft: badgeVariants({ variant: "outline" }),
|
|
open: badgeVariants({ variant: "secondary" }),
|
|
un_paid: badgeVariants({ variant: "destructive" }),
|
|
partially_paid: badgeVariants({ variant: "default" }),
|
|
paid: badgeVariants({ variant: "default" }),
|
|
}
|
|
|
|
function isBillStatus(value: unknown): value is BillStatus {
|
|
return typeof value === "string" && BillStatus.includes(value as BillStatus)
|
|
}
|
|
|
|
type BillStatusBadgeProps = {
|
|
bill: {
|
|
id: string
|
|
status: string | null | undefined
|
|
}
|
|
}
|
|
|
|
export default function BillStatusBadge({ bill }: BillStatusBadgeProps) {
|
|
const api = useAuthApi()
|
|
const router = useRouter()
|
|
const [isLoading, setIsLoading] = useState(false)
|
|
|
|
const { id: billId, status } = bill
|
|
|
|
if (!isBillStatus(status)) return null
|
|
|
|
const handleStatusChange = async (nextStatus: string) => {
|
|
if (!isBillStatus(nextStatus)) return
|
|
|
|
const confirmed = await confirm({
|
|
title: "Update Bill Status",
|
|
description: `Change bill status to ${formatEnum(nextStatus)}?`,
|
|
})
|
|
|
|
if (!confirmed) return
|
|
|
|
try {
|
|
setIsLoading(true)
|
|
await api.bills.update(billId, { status: nextStatus })
|
|
toast.success("Bill status updated")
|
|
router.refresh()
|
|
} catch (error) {
|
|
toast.error("Failed to update bill status")
|
|
} finally {
|
|
setIsLoading(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Select value={status} onValueChange={handleStatusChange} disabled={isLoading}>
|
|
<SelectTrigger
|
|
className={`border-0 size-auto p-0 h-auto font-medium ${STATUS_TRIGGER_CLASS_NAMES[status]}`}
|
|
>
|
|
<SelectValue placeholder="Select status" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{BillStatus.map((s) => (
|
|
<SelectItem key={s} value={s}>
|
|
{formatEnum(s)}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
)
|
|
}
|