import React, { useEffect } from 'react'; import { useParams, useNavigate, Link } from 'react-router-dom'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { ArrowLeft, Play, Pause, XCircle, RefreshCw, Calendar, User, Package, CreditCard, Clock, FileText } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { Skeleton } from '@/components/ui/skeleton'; import { usePageHeader } from '@/contexts/PageHeaderContext'; import { __ } from '@/lib/i18n'; import { toast } from 'sonner'; interface SubscriptionOrder { id: number; subscription_id: number; order_id: number; order_type: 'parent' | 'renewal' | 'switch' | 'resubscribe'; order_status: string; created_at: string; } interface Subscription { id: number; user_id: number; order_id: number; product_id: number; variation_id: number | null; product_name: string; product_image: string; user_name: string; user_email: string; status: string; billing_period: string; billing_interval: number; billing_schedule: string; recurring_amount: string; start_date: string; trial_end_date: string | null; next_payment_date: string | null; end_date: string | null; last_payment_date: string | null; payment_method: string; payment_method_title?: string; pause_count: number; failed_payment_count: number; cancel_reason: string | null; created_at: string; can_pause: boolean; can_resume: boolean; can_cancel: boolean; orders: SubscriptionOrder[]; } const statusColors: Record = { 'pending': 'bg-yellow-100 text-yellow-800', 'active': 'bg-green-100 text-green-800', 'on-hold': 'bg-blue-100 text-blue-800', 'cancelled': 'bg-gray-100 text-gray-800', 'expired': 'bg-red-100 text-red-800', 'pending-cancel': 'bg-orange-100 text-orange-800', 'draft': 'bg-gray-100 text-gray-600', }; const statusLabels: Record = { 'pending': __('Pending'), 'active': __('Active'), 'on-hold': __('On Hold'), 'cancelled': __('Cancelled'), 'expired': __('Expired'), 'pending-cancel': __('Pending Cancel'), 'draft': __('Draft'), }; const orderTypeLabels: Record = { 'parent': __('Initial Order'), 'renewal': __('Renewal'), 'switch': __('Plan Switch'), 'resubscribe': __('Resubscribe'), }; const formatPrice = (amount: string | number) => { const val = typeof amount === 'string' ? parseFloat(amount) : amount; if (isNaN(val)) return amount; // Simple formatting using browser's locale but keeping currency from store try { return new Intl.NumberFormat(window.WNW_STORE?.locale || 'en-US', { style: 'currency', currency: window.WNW_STORE?.currency || 'USD', minimumFractionDigits: window.WNW_STORE?.decimals || 2, }).format(val); } catch (e) { return (window.WNW_STORE?.currency_symbol || '$') + val; } }; async function fetchSubscription(id: string) { const res = await fetch(`${window.WNW_API.root}/subscriptions/${id}`, { headers: { 'X-WP-Nonce': window.WNW_API.nonce }, }); if (!res.ok) throw new Error('Failed to fetch subscription'); return res.json(); } async function subscriptionAction(id: number, action: string, reason?: string) { const res = await fetch(`${window.WNW_API.root}/subscriptions/${id}/${action}`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': window.WNW_API.nonce, }, body: JSON.stringify({ reason }), }); if (!res.ok) { const error = await res.json(); throw new Error(error.message || `Failed to ${action} subscription`); } return res.json(); } export default function SubscriptionDetail() { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); const queryClient = useQueryClient(); const { setPageHeader, clearPageHeader } = usePageHeader(); const { data: subscription, isLoading, error } = useQuery({ queryKey: ['subscription', id], queryFn: () => fetchSubscription(id!), enabled: !!id, }); useEffect(() => { if (subscription) { setPageHeader(__('Subscription') + ' #' + subscription.id); } return () => clearPageHeader(); }, [subscription, setPageHeader, clearPageHeader]); const actionMutation = useMutation({ mutationFn: ({ action, reason }: { action: string; reason?: string }) => subscriptionAction(parseInt(id!), action, reason), onSuccess: (_, { action }) => { queryClient.invalidateQueries({ queryKey: ['subscription', id] }); queryClient.invalidateQueries({ queryKey: ['subscriptions'] }); toast.success(__(`Subscription ${action}d successfully`)); }, onError: (error: Error) => { toast.error(error.message); }, }); const handleAction = (action: string) => { if (action === 'cancel' && !confirm(__('Are you sure you want to cancel this subscription?'))) { return; } actionMutation.mutate({ action }); }; if (isLoading) { return (
); } if (error || !subscription) { return (

{__('Failed to load subscription')}

); } return (
{/* Back button and actions */}
{subscription.can_pause && ( )} {subscription.can_resume && ( )} {subscription.status === 'active' && ( )} {subscription.can_cancel && ( )}
{/* Status and product info */}
{/* Subscription Info */}
{__('Subscription Details')} {statusLabels[subscription.status] || subscription.status}
{subscription.product_image ? ( {subscription.product_name} ) : (
)}

{subscription.product_name}

{subscription.billing_schedule}

{formatPrice(subscription.recurring_amount)}

{__('Start Date')}
{new Date(subscription.start_date).toLocaleDateString()}
{subscription.next_payment_date && (
{__('Next Payment')}
{new Date(subscription.next_payment_date).toLocaleDateString()}
)} {subscription.trial_end_date && (
{__('Trial End')}
{new Date(subscription.trial_end_date).toLocaleDateString()}
)} {subscription.end_date && (
{__('End Date')}
{new Date(subscription.end_date).toLocaleDateString()}
)}
{subscription.cancel_reason && (
{__('Cancel Reason')}
{subscription.cancel_reason}
)}
{/* Customer Info */} {__('Customer')}
{subscription.user_name}
{subscription.user_email}
{__('Payment Method')}
{subscription.payment_method_title || subscription.payment_method || __('Not set')}
{__('Pause Count')}
{subscription.pause_count}
{__('Failed Payments')}
0 ? 'text-red-600' : ''}> {subscription.failed_payment_count}
{__('Parent Order')}
#{subscription.order_id}
{/* Related Orders */} {__('Related Orders')} {__('All orders associated with this subscription')} {__('Order')} {__('Type')} {__('Status')} {__('Date')} {subscription.orders?.length === 0 ? ( {__('No orders found')} ) : ( subscription.orders?.map((order) => { const rawStatus = order.order_status?.replace('wc-', '') || 'pending'; return ( #{order.order_id} {orderTypeLabels[order.order_type] || order.order_type} {statusLabels[rawStatus] || rawStatus} {new Date(order.created_at).toLocaleDateString()} ); }) )}
); }