import { useEffect, useState } from "react" import { useParams, useNavigate } from "react-router-dom" import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Switch } from "@/components/ui/switch" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { ArrowLeft, Loader2 } from "lucide-react" import { subscriptionService, type PlanFeatures } from "@/services" import { toast } from "sonner" import type { ApiError } from "@/types/error.types" function formatFeatureLabel(key: string) { return key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()) } export default function PlanManagementPage() { const { id } = useParams() const navigate = useNavigate() const queryClient = useQueryClient() const [displayName, setDisplayName] = useState("") const [description, setDescription] = useState("") const [monthlyPrice, setMonthlyPrice] = useState("") const [yearlyPrice, setYearlyPrice] = useState("") const [isActive, setIsActive] = useState(true) const [features, setFeatures] = useState({ features: {}, limits: {} }) const { data: plan, isLoading } = useQuery({ queryKey: ['admin', 'subscription-plans', id], queryFn: () => subscriptionService.getAdminPlan(id!), enabled: !!id, }) useEffect(() => { if (plan) { setDisplayName(plan.displayName) setDescription(plan.description ?? "") setMonthlyPrice(String(plan.monthlyPrice)) setYearlyPrice(String(plan.yearlyPrice)) setIsActive(plan.isActive) setFeatures(plan.features) } }, [plan]) const updatePlanMutation = useMutation({ mutationFn: () => subscriptionService.updatePlan(id!, { displayName, description, monthlyPrice: Number(monthlyPrice), yearlyPrice: Number(yearlyPrice), isActive, }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin', 'subscription-plans'] }) toast.success("Plan settings updated") }, onError: (error) => { const apiError = error as ApiError toast.error(apiError.response?.data?.message || "Failed to update plan") }, }) const updateFeaturesMutation = useMutation({ mutationFn: () => subscriptionService.updatePlanFeatures(id!, features), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin', 'subscription-plans'] }) toast.success("Plan features updated") }, onError: (error) => { const apiError = error as ApiError toast.error(apiError.response?.data?.message || "Failed to update features") }, }) const toggleFeature = (key: string) => { setFeatures((prev) => ({ ...prev, features: { ...prev.features, [key]: !prev.features[key] }, })) } const updateLimit = (key: string, value: string) => { const parsed = value.trim() === "" ? null : Number(value) setFeatures((prev) => ({ ...prev, limits: { ...prev.limits, [key]: parsed }, })) } if (isLoading) { return (
Loading plan...
) } if (!plan) { return
Plan not found.
} return (

{plan.displayName}

{plan.name} plan

Pricing & Status Features & Limits Pricing Settings
setDisplayName(e.target.value)} />
setDescription(e.target.value)} />
{!plan.isFree && ( <>
setMonthlyPrice(e.target.value)} />
setYearlyPrice(e.target.value)} />
)}

Inactive plans are hidden from new subscriptions.

Feature Flags {Object.entries(features.features).map(([key, enabled]) => (
toggleFeature(key)} />
))}
Usage Limits {Object.entries(features.limits).map(([key, limit]) => (
updateLimit(key, e.target.value)} />
))}
) }