"use client"; import { useState } from "react"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { RefreshCw, Package, Plus, Pencil, Trash2 } from "lucide-react"; import { Card, CardContent, CardHeader } from "@/components/ui/Card"; import { Table, TableHead, TableBody, TableRow, Th, Td, EmptyState } from "@/components/ui/Table"; import { Badge } from "@/components/ui/Badge"; import { Button } from "@/components/ui/Button"; import { Input } from "@/components/ui/Input"; import { Modal } from "@/components/ui/Modal"; import { formatCurrency } from "@/lib/utils"; import api from "@/lib/api"; import { toast } from "sonner"; interface Plan { id: string; name: string; type: "PREPAID" | "POSTPAID"; speed: string; price: string | number; description?: string; } interface PlansResponse { data: Plan[]; total: number; page: number; limit: number; } const typeVariant: Record = { PREPAID: "success", POSTPAID: "muted", }; const emptyForm = { name: "", type: "PREPAID" as "PREPAID" | "POSTPAID", speed: "", price: "", description: "" }; export default function PlansPage() { const qc = useQueryClient(); const [search, setSearch] = useState(""); const [page, setPage] = useState(1); // Modals const [showCreate, setShowCreate] = useState(false); const [editPlan, setEditPlan] = useState(null); const [deletePlan, setDeletePlan] = useState(null); // Forms const [createForm, setCreateForm] = useState({ ...emptyForm }); const [editForm, setEditForm] = useState({ ...emptyForm }); const { data, isLoading, isError, refetch } = useQuery({ queryKey: ["plans", search, page], queryFn: async () => { const params = new URLSearchParams({ page: String(page), limit: "20" }); if (search) params.set("search", search); const res = await api.get(`/api/v1/plans?${params}`); return res.data; }, }); const createMutation = useMutation({ mutationFn: async () => { await api.post("/api/v1/plans", { name: createForm.name, type: createForm.type, speed: createForm.speed, price: Number(createForm.price), description: createForm.description || undefined, }); }, onSuccess: () => { toast.success("Plan created!"); setShowCreate(false); setCreateForm({ ...emptyForm }); qc.invalidateQueries({ queryKey: ["plans"] }); }, onError: (e: any) => toast.error(e.response?.data?.message ?? "Failed to create plan"), }); const updateMutation = useMutation({ mutationFn: async () => { await api.patch(`/api/v1/plans/${editPlan!.id}`, { name: editForm.name, type: editForm.type, speed: editForm.speed, price: Number(editForm.price), description: editForm.description || undefined, }); }, onSuccess: () => { toast.success("Plan updated!"); setEditPlan(null); qc.invalidateQueries({ queryKey: ["plans"] }); }, onError: (e: any) => toast.error(e.response?.data?.message ?? "Failed to update plan"), }); const deleteMutation = useMutation({ mutationFn: async () => { await api.delete(`/api/v1/plans/${deletePlan!.id}`); }, onSuccess: () => { toast.success("Plan deleted!"); setDeletePlan(null); qc.invalidateQueries({ queryKey: ["plans"] }); }, onError: (e: any) => toast.error(e.response?.data?.message ?? "Failed to delete plan"), }); const plans = data?.data ?? []; const total = data?.total ?? 0; const openEdit = (plan: Plan) => { setEditForm({ name: plan.name, type: plan.type, speed: plan.speed, price: String(plan.price), description: plan.description ?? "", }); setEditPlan(plan); }; return (
{/* Header */}

Plans

{total} total plans

{ setSearch(e.target.value); setPage(1); }} data-testid="input-search" /> {isLoading ? ( Array.from({ length: 6 }).map((_, i) => ( )) ) : isError ? ( ) : plans.length === 0 ? ( } /> ) : ( plans.map(plan => ( )) )}
Name Type Speed Price Description

Failed to load plans.{" "}

{plan.name} {plan.type} {plan.speed} {formatCurrency(Number(plan.price))} {plan.description ?? "—"}
{total > 20 && (
Showing {(page - 1) * 20 + 1}–{Math.min(page * 20, total)} of {total}
)}
{/* Create Plan Modal */} { setShowCreate(false); setCreateForm({ ...emptyForm }); }} title="Add Plan" className="max-w-md" data-testid="modal-create-plan">
setCreateForm(f => ({ ...f, name: e.target.value }))} placeholder="e.g. Basic 25Mbps" data-testid="input-plan-name" />
setCreateForm(f => ({ ...f, speed: e.target.value }))} placeholder="e.g. 25Mbps" data-testid="input-plan-speed" /> setCreateForm(f => ({ ...f, price: e.target.value }))} placeholder="e.g. 999" data-testid="input-plan-price" /> setCreateForm(f => ({ ...f, description: e.target.value }))} placeholder="e.g. Perfect for households" data-testid="input-plan-description" />
{/* Edit Plan Modal */} setEditPlan(null)} title={`Edit Plan: ${editPlan?.name ?? ""}`} className="max-w-md">
setEditForm(f => ({ ...f, name: e.target.value }))} data-testid="input-edit-name" />
setEditForm(f => ({ ...f, speed: e.target.value }))} data-testid="input-edit-speed" /> setEditForm(f => ({ ...f, price: e.target.value }))} data-testid="input-edit-price" /> setEditForm(f => ({ ...f, description: e.target.value }))} data-testid="input-edit-description" />
{/* Delete Confirmation Modal */} setDeletePlan(null)} title="Delete Plan" className="max-w-sm">

Are you sure you want to delete {deletePlan?.name}? This action cannot be undone.

); }