'use client'; import { useState, useEffect, useCallback } from 'react'; import { api } from '@/lib/api'; import { PageHeader } from '@/components/ui/page-header'; import { DataTable } from '@/components/ui/data-table'; import { Badge, statusBadgeVariant } from '@/components/ui/badge'; import { ActionIcon } from '@/components/ui/action-icon'; import { ActionMenu, ActionMenuItem } from '@/components/ui/action-menu'; import { Modal } from '@/components/ui/modal'; import { Button } from '@/components/ui/button'; import { useToast } from '@/components/ui/toast'; interface Subscription { id: string; type: string; status: string; client: { id: string; firstName: string; lastName: string; accountNumber: string }; plan: { id: string; name: string; price: string; speedDown: number; speedUp: number }; createdAt: string; } export default function SubscriptionsPage() { const { toast } = useToast(); const [subs, setSubs] = useState([]); const [loading, setLoading] = useState(true); const [search, setSearch] = useState(''); const [detailTarget, setDetailTarget] = useState(null); const loadSubs = useCallback(async () => { try { const res = await api.get<{ data: Subscription[] }>('/subscriptions'); setSubs(res.data.data); } catch { toast('Failed to load subscriptions', 'error'); } finally { setLoading(false); } }, [toast]); useEffect(() => { loadSubs(); }, [loadSubs]); async function handleAction(id: string, action: string) { try { await api.patch(`/subscriptions/${id}/${action}`); toast(`Subscription ${action}d`, 'success'); loadSubs(); } catch { toast(`Failed to ${action} subscription`, 'error'); } } const filtered = search ? subs.filter((s) => `${s.client.firstName} ${s.client.lastName} ${s.client.accountNumber} ${s.plan.name}`.toLowerCase().includes(search.toLowerCase())) : subs; function getActionItems(s: Subscription): ActionMenuItem[] { const items: ActionMenuItem[] = []; if (s.status === 'active') { items.push({ icon: 'pause', label: 'Suspend', onClick: () => handleAction(s.id, 'suspend') }); } if (s.status === 'suspended') { items.push({ icon: 'play', label: 'Reactivate', onClick: () => handleAction(s.id, 'reactivate') }); } if (['pending', 'active', 'suspended'].includes(s.status)) { items.push({ icon: 'x-circle', label: 'Cancel', onClick: () => handleAction(s.id, 'cancel'), variant: 'danger' }); } return items; } return (
s.id} emptyTitle="No subscriptions" emptyDescription="Subscriptions are created when clients sign up for plans." searchPlaceholder="Search by client, account #, or plan..." searchValue={search} onSearchChange={setSearch} onRowClick={(s) => setDetailTarget(s)} columns={[ { key: 'client', label: 'Client', sortable: true, render: (s) => (
{s.client.firstName} {s.client.lastName} {s.client.accountNumber}
)}, { key: 'plan', label: 'Plan', sortable: true, render: (s) => {s.plan.name} }, { key: 'type', label: 'Type', render: (s) => ( )}, { key: 'status', label: 'Status', sortable: true, render: (s) => }, { key: 'createdAt', label: 'Created', sortable: true, render: (s) => {new Date(s.createdAt).toLocaleDateString()} }, { key: 'actions', label: '', align: 'right', render: (s) => { const items = getActionItems(s); return items.length > 0 ? (
e.stopPropagation()}>
) : null; }}, ]} />
{/* Subscription Detail Modal */} setDetailTarget(null)} title="Subscription Details" description={detailTarget ? `${detailTarget.client.firstName} ${detailTarget.client.lastName}` : ''}> {detailTarget && (
Account: {detailTarget.client.accountNumber}
Plan: {detailTarget.plan.name}
Speed: {detailTarget.plan.speedDown}/{detailTarget.plan.speedUp} Mbps
Price: PHP {Number(detailTarget.plan.price).toLocaleString()}
Type: {detailTarget.type}
Status:
Created: {new Date(detailTarget.createdAt).toLocaleDateString()}
)}
); }