Files
device-management/resources/js/pages/checkout/show.tsx
T
Wian Drs 60946ddf37
tests / ci (push) Has been cancelled
update lisensi prosess
2026-08-25 13:43:55 +07:00

147 lines
7.5 KiB
TypeScript

import { Form, Head, Link, usePage } from '@inertiajs/react';
import { CheckCircle2, Clock3, CreditCard, TriangleAlert } from 'lucide-react';
import PublicThemeToggle from '@/components/public-theme-toggle';
type Order = {
uuid: string;
plan: string;
status: string;
total: number;
currency: string;
checkout_url: string | null;
gateway: string;
payment_method: string | null;
payment_methods: { code: string; name: string; fee: number }[];
gateway_error: string | null;
};
export default function CheckoutShow({ order }: { order: Order }) {
const { errors } = usePage().props;
const paid = order.status === 'paid';
const total = new Intl.NumberFormat('id-ID', {
style: 'currency',
currency: order.currency,
maximumFractionDigits: 0,
}).format(order.total);
return (
<>
<Head title="Checkout Lisensi" />
<main className="min-h-screen bg-background px-5 py-8 text-foreground">
<div className="mx-auto max-w-xl">
<header className="mb-10 flex items-center justify-between">
<Link href="/" className="flex items-center gap-3">
<img
src="/images/radiq-ndm-logo.png"
alt="RADIQ NDM"
className="size-12 object-contain"
/>
<span className="font-semibold">RADIQ NDM</span>
</Link>
<PublicThemeToggle />
</header>
<div className="rounded-2xl border bg-card p-6 shadow-sm">
<div className="flex items-center gap-3">
{paid ? (
<CheckCircle2 className="size-7 text-emerald-500" />
) : (
<CreditCard className="size-7 text-sky-500" />
)}
<div>
<p className="text-sm text-muted-foreground">
Checkout lisensi bulanan
</p>
<h1 className="text-2xl font-bold">
{order.plan}
</h1>
</div>
</div>
<div className="mt-6 rounded-xl bg-muted/50 p-4">
<div className="flex justify-between">
<span>Total pembayaran</span>
<strong>{total}</strong>
</div>
<div className="mt-2 flex justify-between text-sm text-muted-foreground">
<span>Gateway</span>
<span>{order.gateway}</span>
</div>
<div className="mt-2 flex justify-between text-sm text-muted-foreground">
<span>Status</span>
<span>{order.status}</span>
</div>
</div>
{paid ? (
<div className="mt-6">
<p className="text-sm text-emerald-600">
Pembayaran diterima dan lisensi telah
diaktifkan.
</p>
<Link
href="/login"
className="mt-4 block rounded-lg bg-sky-500 px-4 py-3 text-center font-semibold text-slate-950"
>
Login Tenant Admin
</Link>
</div>
) : order.checkout_url ? (
<div className="mt-6">
<a
href={order.checkout_url}
className="block rounded-lg bg-sky-500 px-4 py-3 text-center font-semibold text-slate-950"
>
Lanjut Bayar dengan Duitku
</a>
<p className="mt-3 text-center text-xs text-muted-foreground">
<Clock3 className="mr-1 inline size-3" />
Status aktif setelah callback pembayaran
terverifikasi.
</p>
</div>
) : (
<div className="mt-6 rounded-lg border p-4 text-sm">
{order.gateway_error ? (
<p className="text-destructive">
<TriangleAlert className="mr-2 inline size-4" />
{order.gateway_error}
</p>
) : (
<p className="text-muted-foreground">
Pilih kanal pembayaran Duitku. Order ini tetap dapat dilanjutkan tanpa membuat order baru.
</p>
)}
{errors.payment && (
<p className="mt-2 text-destructive">{String(errors.payment)}</p>
)}
<Form
action={`/checkout/${order.uuid}/retry`}
method="post"
className="mt-3"
>
{order.payment_methods.length > 0 && (
<select
name="payment_method"
defaultValue={order.payment_method ?? ''}
required
className="mb-3 w-full rounded-md border bg-background px-3 py-2"
>
<option value="" disabled>Pilih kanal pembayaran</option>
{order.payment_methods.map((method) => (
<option key={method.code} value={method.code}>
{method.name}{method.fee > 0 ? ` (biaya ${new Intl.NumberFormat('id-ID').format(method.fee)})` : ''}
</option>
))}
</select>
)}
<button disabled={order.payment_methods.length === 0} className="w-full rounded-md bg-sky-500 px-3 py-2 font-semibold text-slate-950 disabled:opacity-50">
Buat dan Lanjutkan Pembayaran
</button>
</Form>
</div>
)}
</div>
</div>
</main>
</>
);
}