diff --git a/src/lib/statusHelpers.ts b/src/lib/statusHelpers.ts new file mode 100644 index 0000000..1b98912 --- /dev/null +++ b/src/lib/statusHelpers.ts @@ -0,0 +1,124 @@ +/** + * Centralized status management for consistent labels, colors, and badges + * Single source of truth for all status-related UI + */ + +export type PaymentStatus = 'paid' | 'pending' | 'failed' | 'cancelled' | 'refunded' | 'partially_refunded'; +export type ConsultingSlotStatus = 'pending_payment' | 'confirmed' | 'completed' | 'cancelled'; + +/** + * Get Indonesian label for payment status + */ +export const getPaymentStatusLabel = (status: PaymentStatus | string | null): string => { + switch (status) { + case 'paid': + return 'Lunas'; + case 'pending': + return 'Pending'; + case 'failed': + return 'Gagal'; + case 'cancelled': + return 'Dibatalkan'; + case 'refunded': + return 'Refund'; + case 'partially_refunded': + return 'Refund Sebagian'; + default: + return status || 'Pending'; + } +}; + +/** + * Get CSS class for payment status badge + */ +export const getPaymentStatusColor = (status: PaymentStatus | string | null): string => { + switch (status) { + case 'paid': + return 'bg-brand-accent text-white'; + case 'pending': + return 'bg-amber-500 text-white'; + case 'failed': + return 'bg-red-500 text-white'; + case 'cancelled': + return 'bg-destructive text-white'; + case 'refunded': + return 'bg-purple-500 text-white'; + case 'partially_refunded': + return 'bg-purple-500/80 text-white'; + default: + return 'bg-secondary text-primary'; + } +}; + +/** + * Get label for consulting slot status + */ +export const getConsultingSlotStatusLabel = (status: ConsultingSlotStatus | string): string => { + switch (status) { + case 'pending_payment': + return 'Menunggu Pembayaran'; + case 'confirmed': + return 'Terkonfirmasi'; + case 'completed': + return 'Selesai'; + case 'cancelled': + return 'Dibatalkan'; + default: + return status; + } +}; + +/** + * Get CSS class for consulting slot status badge + */ +export const getConsultingSlotStatusColor = (status: ConsultingSlotStatus | string): string => { + switch (status) { + case 'pending_payment': + return 'bg-amber-500 text-white'; + case 'confirmed': + return 'bg-green-500 text-white'; + case 'completed': + return 'bg-blue-500 text-white'; + case 'cancelled': + return 'bg-destructive text-white'; + default: + return 'bg-secondary text-primary'; + } +}; + +/** + * Get label for product type + */ +export const getProductTypeLabel = (type: string): string => { + switch (type) { + case 'consulting': + return 'Konsultasi'; + case 'webinar': + return 'Webinar'; + case 'bootcamp': + return 'Bootcamp'; + default: + return type; + } +}; + +/** + * Check if order can be refunded + */ +export const canRefundOrder = (paymentStatus: PaymentStatus | string | null, refundedAt: string | null = null): boolean => { + return paymentStatus === 'paid' && !refundedAt; +}; + +/** + * Check if order can be cancelled + */ +export const canCancelOrder = (paymentStatus: PaymentStatus | string | null, refundedAt: string | null = null): boolean => { + return !refundedAt && paymentStatus !== 'cancelled' && paymentStatus !== 'refunded' && paymentStatus !== 'partially_refunded'; +}; + +/** + * Check if order can be marked as paid + */ +export const canMarkAsPaid = (paymentStatus: PaymentStatus | string | null, refundedAt: string | null = null): boolean => { + return !refundedAt && paymentStatus !== 'paid' && paymentStatus !== 'refunded' && paymentStatus !== 'partially_refunded'; +}; diff --git a/src/pages/admin/AdminOrders.tsx b/src/pages/admin/AdminOrders.tsx index 8d2c64c..5eabdeb 100644 --- a/src/pages/admin/AdminOrders.tsx +++ b/src/pages/admin/AdminOrders.tsx @@ -15,6 +15,7 @@ import { Textarea } from "@/components/ui/textarea"; import { formatIDR, formatDateTime } from "@/lib/format"; import { Eye, CheckCircle, XCircle, Video, ExternalLink, Trash2, AlertTriangle, RefreshCw, Link as LinkIcon } from "lucide-react"; import { toast } from "@/hooks/use-toast"; +import { getPaymentStatusLabel, getPaymentStatusColor, canRefundOrder, canCancelOrder, canMarkAsPaid } from "@/lib/statusHelpers"; interface Order { id: string; @@ -272,20 +273,11 @@ export default function AdminOrders() { }; const getStatusBadge = (status: string | null) => { - switch (status) { - case "paid": - return Lunas; - case "refunded": - return Refund; - case "partially_refunded": - return Refund Sebagian; - case "pending": - return Pending; - case "cancelled": - return Dibatalkan; - default: - return {status}; - } + return ( + + {getPaymentStatusLabel(status)} + + ); }; if (authLoading || loading) { @@ -499,7 +491,7 @@ export default function AdminOrders() { )}
- {selectedOrder.payment_status === "paid" && !selectedOrder.refunded_at && ( + {canRefundOrder(selectedOrder.payment_status, selectedOrder.refunded_at) && ( )} - {selectedOrder.payment_status !== "cancelled" && !selectedOrder.refunded_at && ( + {canCancelOrder(selectedOrder.payment_status, selectedOrder.refunded_at) && (