147 lines
7.5 KiB
TypeScript
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>
|
|
</>
|
|
);
|
|
}
|