Merge consulting order details into single card
- Consolidate "Informasi Order" and "Detail Sesi Konsultasi" cards into one - Remove duplicate "Order Info" card for consulting orders - Display all information in single, cleaner merged card: - Session details (time, date, category, notes, meet link) - QR code for pending payments - Expired/cancelled order handling with rebooking - Status alerts (paid/cancelled/pending) - Total payment - Keep separate cards for product orders unchanged 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -333,37 +333,38 @@ export default function OrderDetail() {
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
{/* Order Info */}
|
||||
<Card className="border-2 border-border mb-6">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg flex items-center gap-2">
|
||||
<CalendarIcon className="w-5 h-5" />
|
||||
Informasi Order
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="grid grid-cols-2 gap-4 text-sm">
|
||||
<div>
|
||||
<p className="text-muted-foreground">Tanggal Order</p>
|
||||
<p className="font-medium">{formatDate(order.created_at)}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground">Terakhir Update</p>
|
||||
<p className="font-medium">{formatDate(order.updated_at)}</p>
|
||||
</div>
|
||||
{order.payment_method && (
|
||||
{/* Order Info - Only show for product orders */}
|
||||
{!isConsultingOrder && (
|
||||
<Card className="border-2 border-border mb-6">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg flex items-center gap-2">
|
||||
<CalendarIcon className="w-5 h-5" />
|
||||
Informasi Order
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="grid grid-cols-2 gap-4 text-sm">
|
||||
<div>
|
||||
<p className="text-muted-foreground">Metode Pembayaran</p>
|
||||
<p className="font-medium uppercase">{order.payment_method}</p>
|
||||
<p className="text-muted-foreground">Tanggal Order</p>
|
||||
<p className="font-medium">{formatDate(order.created_at)}</p>
|
||||
</div>
|
||||
)}
|
||||
{order.payment_provider && (
|
||||
<div>
|
||||
<p className="text-muted-foreground">Provider</p>
|
||||
<p className="font-medium capitalize">{order.payment_provider}</p>
|
||||
<p className="text-muted-foreground">Terakhir Update</p>
|
||||
<p className="font-medium">{formatDate(order.updated_at)}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{order.payment_method && (
|
||||
<div>
|
||||
<p className="text-muted-foreground">Metode Pembayaran</p>
|
||||
<p className="font-medium uppercase">{order.payment_method}</p>
|
||||
</div>
|
||||
)}
|
||||
{order.payment_provider && (
|
||||
<div>
|
||||
<p className="text-muted-foreground">Provider</p>
|
||||
<p className="font-medium capitalize">{order.payment_provider}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* QR Code Display for pending QRIS payments */}
|
||||
{order.payment_status === "pending" && order.payment_method === "qris" && !isQrExpired && (
|
||||
@@ -442,78 +443,46 @@ export default function OrderDetail() {
|
||||
<Alert className="mb-4 border-orange-200 bg-orange-50">
|
||||
<AlertCircle className="h-4 w-4 text-orange-600" />
|
||||
<AlertDescription className="text-orange-900">
|
||||
{isConsultingOrder
|
||||
? "Waktu pembayaran telah habis. Slot konsultasi telah dilepaskan. Silakan buat booking baru."
|
||||
: "QR Code telah kadaluarsa. Anda dapat me-regenerate QR code untuk melanjutkan pembayaran."}
|
||||
QR Code telah kadaluarsa. Anda dapat me-regenerate QR code untuk melanjutkan pembayaran.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
{isConsultingOrder ? (
|
||||
// Consulting order - show booking button with pre-filled data
|
||||
<div className="text-center space-y-4">
|
||||
{/* Product order - show regenerate button */}
|
||||
<div className="space-y-4">
|
||||
<div className="text-center">
|
||||
<p className="text-2xl font-bold">{formatIDR(order.total_amount)}</p>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Order ini telah dibatalkan secara otomatis karena waktu pembayaran habis.
|
||||
</p>
|
||||
<Button
|
||||
onClick={() => {
|
||||
// Pass expired order data to prefill the booking form
|
||||
const expiredData = {
|
||||
fromExpiredOrder: true,
|
||||
orderId: order.id,
|
||||
topicCategory: consultingSlots[0]?.topic_category || '',
|
||||
notes: consultingSlots[0]?.notes || ''
|
||||
};
|
||||
// Store in sessionStorage for the booking page to retrieve
|
||||
sessionStorage.setItem('expiredConsultingOrder', JSON.stringify(expiredData));
|
||||
navigate("/consulting");
|
||||
}}
|
||||
className="shadow-sm"
|
||||
>
|
||||
<CalendarIcon className="w-4 h-4 mr-2" />
|
||||
Buat Booking Baru
|
||||
</Button>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Kategori dan catatan akan terisi otomatis dari order sebelumnya
|
||||
Order ID: {order.id.slice(0, 8)}
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
// Product order - show regenerate button
|
||||
<div className="space-y-4">
|
||||
<div className="text-center">
|
||||
<p className="text-2xl font-bold">{formatIDR(order.total_amount)}</p>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Order ID: {order.id.slice(0, 8)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
onClick={handleRegenerateQR}
|
||||
disabled={regeneratingQR}
|
||||
className="w-full shadow-sm"
|
||||
>
|
||||
{regeneratingQR ? (
|
||||
<>
|
||||
<RefreshCw className="w-4 h-4 mr-2 animate-spin" />
|
||||
Memproses...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<RefreshCw className="w-4 h-4 mr-2" />
|
||||
Regenerate QR Code
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleRegenerateQR}
|
||||
disabled={regeneratingQR}
|
||||
className="w-full shadow-sm"
|
||||
>
|
||||
{regeneratingQR ? (
|
||||
<>
|
||||
<RefreshCw className="w-4 h-4 mr-2 animate-spin" />
|
||||
Memproses...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<RefreshCw className="w-4 h-4 mr-2" />
|
||||
Regenerate QR Code
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={() => navigate("/products")}
|
||||
variant="outline"
|
||||
className="w-full"
|
||||
>
|
||||
<Package className="w-4 h-4 mr-2" />
|
||||
Kembali ke Produk
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
<Button
|
||||
onClick={() => navigate("/products")}
|
||||
variant="outline"
|
||||
className="w-full"
|
||||
>
|
||||
<Package className="w-4 h-4 mr-2" />
|
||||
Kembali ke Produk
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -523,48 +492,19 @@ export default function OrderDetail() {
|
||||
<Alert className="mb-4 border-red-200 bg-red-50">
|
||||
<AlertCircle className="h-4 w-4 text-red-600" />
|
||||
<AlertDescription className="text-red-900">
|
||||
{isConsultingOrder
|
||||
? "Order ini telah dibatalkan. Slot konsultasi telah dilepaskan."
|
||||
: "Order ini telah dibatalkan."}
|
||||
Order ini telah dibatalkan.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
{isConsultingOrder ? (
|
||||
// Consulting order - show booking button with pre-filled data
|
||||
<div className="text-center space-y-4">
|
||||
<Button
|
||||
onClick={() => {
|
||||
// Pass expired order data to prefill the booking form
|
||||
const expiredData = {
|
||||
fromExpiredOrder: true,
|
||||
orderId: order.id,
|
||||
topicCategory: consultingSlots[0]?.topic_category || '',
|
||||
notes: consultingSlots[0]?.notes || ''
|
||||
};
|
||||
// Store in sessionStorage for the booking page to retrieve
|
||||
sessionStorage.setItem('expiredConsultingOrder', JSON.stringify(expiredData));
|
||||
navigate("/consulting");
|
||||
}}
|
||||
className="shadow-sm"
|
||||
>
|
||||
<CalendarIcon className="w-4 h-4 mr-2" />
|
||||
Buat Booking Baru
|
||||
</Button>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Kategori dan catatan akan terisi otomatis dari order sebelumnya
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
// Product order - show back to products button
|
||||
<Button
|
||||
onClick={() => navigate("/products")}
|
||||
variant="outline"
|
||||
className="w-full"
|
||||
>
|
||||
<Package className="w-4 h-4 mr-2" />
|
||||
Kembali ke Produk
|
||||
</Button>
|
||||
)}
|
||||
{/* Product order - show back to products button */}
|
||||
<Button
|
||||
onClick={() => navigate("/products")}
|
||||
variant="outline"
|
||||
className="w-full"
|
||||
>
|
||||
<Package className="w-4 h-4 mr-2" />
|
||||
Kembali ke Produk
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -581,120 +521,265 @@ export default function OrderDetail() {
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Smart Item/Service Display */}
|
||||
{consultingSlots.length > 0 ? (
|
||||
// === Consulting Orders (NO order_items, has consulting_sessions) ===
|
||||
<>
|
||||
<Card className="border-2 border-primary bg-primary/5 mb-6">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg flex items-center gap-2">
|
||||
<Video className="w-5 h-5" />
|
||||
Detail Sesi Konsultasi
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{/* Summary Card */}
|
||||
<div className="bg-background p-4 rounded-lg border-2 border-border">
|
||||
<div className="grid grid-cols-1 gap-4 text-sm">
|
||||
// === Consulting Orders - Single Merged Card ===
|
||||
<Card className="border-2 border-primary bg-primary/5 mb-6">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg flex items-center gap-2">
|
||||
<Video className="w-5 h-5" />
|
||||
Detail Sesi Konsultasi
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{/* Session Information */}
|
||||
<div className="bg-background p-4 rounded-lg border-2 border-border">
|
||||
<div className="grid grid-cols-1 gap-4 text-sm">
|
||||
<div>
|
||||
<p className="text-muted-foreground">Waktu Konsultasi</p>
|
||||
<p className="font-bold text-lg">
|
||||
{consultingSlots[0].start_time.substring(0,5)} - {consultingSlots[0].end_time.substring(0,5)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="text-muted-foreground">Tanggal</p>
|
||||
<p className="font-medium">
|
||||
{new Date(consultingSlots[0].session_date).toLocaleDateString("id-ID", {
|
||||
weekday: "long",
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric"
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{consultingSlots[0]?.topic_category && (
|
||||
<div>
|
||||
<p className="text-muted-foreground">Waktu Konsultasi</p>
|
||||
<p className="font-bold text-lg">
|
||||
{consultingSlots[0].start_time.substring(0,5)} - {consultingSlots[0].end_time.substring(0,5)}
|
||||
</p>
|
||||
<p className="text-muted-foreground">Kategori</p>
|
||||
<p className="font-medium">{consultingSlots[0].topic_category}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{consultingSlots[0]?.notes && (
|
||||
<div>
|
||||
<p className="text-muted-foreground">Tanggal</p>
|
||||
<p className="font-medium">
|
||||
{new Date(consultingSlots[0].session_date).toLocaleDateString("id-ID", {
|
||||
weekday: "long",
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric"
|
||||
})}
|
||||
</p>
|
||||
<p className="text-muted-foreground">Catatan</p>
|
||||
<p className="font-medium">{consultingSlots[0].notes}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{consultingSlots[0]?.topic_category && (
|
||||
{consultingSlots[0]?.meet_link && (
|
||||
<div className="space-y-2">
|
||||
<div>
|
||||
<p className="text-muted-foreground">Kategori</p>
|
||||
<p className="font-medium">{consultingSlots[0].topic_category}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{consultingSlots[0]?.notes && (
|
||||
<div>
|
||||
<p className="text-muted-foreground">Catatan</p>
|
||||
<p className="font-medium">{consultingSlots[0].notes}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{consultingSlots[0]?.meet_link && (
|
||||
<div className="space-y-2">
|
||||
<div>
|
||||
<p className="text-muted-foreground text-sm">Google Meet Link</p>
|
||||
<a
|
||||
href={consultingSlots[0].meet_link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="font-medium text-primary hover:underline text-sm"
|
||||
>
|
||||
{consultingSlots[0].meet_link.substring(0, 40)}...
|
||||
</a>
|
||||
</div>
|
||||
<Button
|
||||
asChild
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="w-full border-2"
|
||||
<p className="text-muted-foreground text-sm">Google Meet Link</p>
|
||||
<a
|
||||
href={consultingSlots[0].meet_link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="font-medium text-primary hover:underline text-sm"
|
||||
>
|
||||
<a
|
||||
href={generateCalendarLink(consultingSlots[0]) || '#'}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Download className="w-4 h-4 mr-2" />
|
||||
Tambah ke Kalender
|
||||
</a>
|
||||
</Button>
|
||||
{consultingSlots[0].meet_link.substring(0, 40)}...
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
<Button
|
||||
asChild
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="w-full border-2"
|
||||
>
|
||||
<a
|
||||
href={generateCalendarLink(consultingSlots[0]) || '#'}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Download className="w-4 h-4 mr-2" />
|
||||
Tambah ke Kalender
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* QR Code Display for pending QRIS payments */}
|
||||
{order.payment_status === "pending" && order.payment_method === "qris" && !isQrExpired && (
|
||||
<div className="pt-4">
|
||||
{order.qr_string ? (
|
||||
<>
|
||||
<Alert className="mb-4">
|
||||
<Clock className="h-4 w-4" />
|
||||
<AlertDescription>
|
||||
Scan QR code ini dengan aplikasi e-wallet atau mobile banking Anda
|
||||
{timeRemaining && (
|
||||
<span className="ml-2 font-medium">
|
||||
(Kadaluarsa dalam {timeRemaining})
|
||||
</span>
|
||||
)}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
<div className="bg-white p-6 rounded-lg border-2 border-border flex flex-col items-center justify-center space-y-4">
|
||||
<div className="bg-white p-2 rounded">
|
||||
<QRCodeSVG value={order.qr_string} size={200} />
|
||||
</div>
|
||||
|
||||
<div className="text-center space-y-2">
|
||||
<p className="text-2xl font-bold">{formatIDR(order.total_amount)}</p>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Order ID: {order.id.slice(0, 8)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{isPolling && (
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<RefreshCw className="w-4 h-4 animate-spin" />
|
||||
Menunggu pembayaran...
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex items-center justify-center gap-4 text-xs text-muted-foreground">
|
||||
<span>🔒 Pembayaran Aman</span>
|
||||
<span>⚡ QRIS Standar Bank Indonesia</span>
|
||||
</div>
|
||||
|
||||
{order.payment_url && (
|
||||
<Button asChild variant="outline" className="w-full">
|
||||
<a href={order.payment_url} target="_blank" rel="noopener noreferrer">
|
||||
<CreditCard className="w-4 h-4 mr-2" />
|
||||
Bayar di Halaman Pembayaran
|
||||
</a>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<Alert className="border-orange-200 bg-orange-50">
|
||||
<Clock className="h-4 w-4 text-orange-600" />
|
||||
<AlertDescription className="text-orange-900">
|
||||
Sedang memproses QR code...
|
||||
{order.payment_url && (
|
||||
<Button asChild className="mt-2" variant="outline" size="sm">
|
||||
<a href={order.payment_url} target="_blank" rel="noopener noreferrer">
|
||||
<CreditCard className="w-4 h-4 mr-2" />
|
||||
Bayar di Halaman Pembayaran
|
||||
</a>
|
||||
</Button>
|
||||
)}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Expired QR Handling for Consulting */}
|
||||
{order.payment_status === "pending" && order.payment_method === "qris" && isQrExpired && (
|
||||
<div className="pt-4">
|
||||
<Alert className="mb-4 border-orange-200 bg-orange-50">
|
||||
<AlertCircle className="h-4 w-4 text-orange-600" />
|
||||
<AlertDescription className="text-orange-900">
|
||||
Waktu pembayaran telah habis. Slot konsultasi telah dilepaskan. Silakan buat booking baru.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
<div className="text-center space-y-4">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Order ini telah dibatalkan secara otomatis karena waktu pembayaran habis.
|
||||
</p>
|
||||
<Button
|
||||
onClick={() => {
|
||||
const expiredData = {
|
||||
fromExpiredOrder: true,
|
||||
orderId: order.id,
|
||||
topicCategory: consultingSlots[0]?.topic_category || '',
|
||||
notes: consultingSlots[0]?.notes || ''
|
||||
};
|
||||
sessionStorage.setItem('expiredConsultingOrder', JSON.stringify(expiredData));
|
||||
navigate("/consulting");
|
||||
}}
|
||||
className="shadow-sm"
|
||||
>
|
||||
<CalendarIcon className="w-4 h-4 mr-2" />
|
||||
Buat Booking Baru
|
||||
</Button>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Kategori dan catatan akan terisi otomatis dari order sebelumnya
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Status Alert */}
|
||||
{order.payment_status === "paid" ? (
|
||||
<Alert className="bg-green-50 border-green-200">
|
||||
<Video className="h-4 w-4" />
|
||||
<AlertDescription>
|
||||
Pembayaran berhasil! Silakan bergabung sesuai jadwal.
|
||||
{/* Cancelled Order Handling for Consulting */}
|
||||
{order.status === "cancelled" && (
|
||||
<div className="pt-4">
|
||||
<Alert className="mb-4 border-red-200 bg-red-50">
|
||||
<AlertCircle className="h-4 w-4 text-red-600" />
|
||||
<AlertDescription className="text-red-900">
|
||||
Order ini telah dibatalkan. Slot konsultasi telah dilepaskan.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
) : order.status === "cancelled" ? (
|
||||
<Alert className="bg-red-50 border-red-200">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertDescription>
|
||||
Order telah dibatalkan. Silakan buat booking baru jika masih tertarik.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
) : (
|
||||
<Alert className="bg-yellow-50 border-yellow-200">
|
||||
<Clock className="h-4 w-4" />
|
||||
<AlertDescription>
|
||||
Selesaikan pembayaran untuk mengkonfirmasi jadwal sesi konsultasi.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{/* Total */}
|
||||
<div className="flex items-center justify-between text-lg font-bold pt-4 border-t">
|
||||
<span>Total Pembayaran</span>
|
||||
<span>{formatIDR(order.total_amount)}</span>
|
||||
<div className="text-center space-y-4">
|
||||
<Button
|
||||
onClick={() => {
|
||||
const expiredData = {
|
||||
fromExpiredOrder: true,
|
||||
orderId: order.id,
|
||||
topicCategory: consultingSlots[0]?.topic_category || '',
|
||||
notes: consultingSlots[0]?.notes || ''
|
||||
};
|
||||
sessionStorage.setItem('expiredConsultingOrder', JSON.stringify(expiredData));
|
||||
navigate("/consulting");
|
||||
}}
|
||||
className="shadow-sm"
|
||||
>
|
||||
<CalendarIcon className="w-4 h-4 mr-2" />
|
||||
Buat Booking Baru
|
||||
</Button>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Kategori dan catatan akan terisi otomatis dari order sebelumnya
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Fallback button for pending payments without QR */}
|
||||
{order.payment_status === "pending" && !order.qr_string && order.payment_url && (
|
||||
<div className="pt-4">
|
||||
<Button asChild className="w-full shadow-sm">
|
||||
<a href={order.payment_url} target="_blank" rel="noopener noreferrer">
|
||||
<CreditCard className="w-4 h-4 mr-2" />
|
||||
Lanjutkan Pembayaran
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Status Alert */}
|
||||
{order.payment_status === "paid" ? (
|
||||
<Alert className="bg-green-50 border-green-200">
|
||||
<Video className="h-4 w-4" />
|
||||
<AlertDescription>
|
||||
Pembayaran berhasil! Silakan bergabung sesuai jadwal.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
) : order.status !== "cancelled" && order.payment_status === "pending" && !isQrExpired ? (
|
||||
<Alert className="bg-yellow-50 border-yellow-200">
|
||||
<Clock className="h-4 w-4" />
|
||||
<AlertDescription>
|
||||
Selesaikan pembayaran untuk mengkonfirmasi jadwal sesi konsultasi.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
) : null}
|
||||
|
||||
{/* Total */}
|
||||
<div className="flex items-center justify-between text-lg font-bold pt-4 border-t">
|
||||
<span>Total Pembayaran</span>
|
||||
<span>{formatIDR(order.total_amount)}</span>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
) : order.order_items.length > 0 ? (
|
||||
// === Product Orders (has order_items) ===
|
||||
<Card className="border-2 border-border mb-6">
|
||||
|
||||
Reference in New Issue
Block a user