import React, { useEffect, useState } from 'react'; import api from '../../utils/api'; import { Card } from '../../components/ui/card'; import { Button } from '../../components/ui/button'; import { Badge } from '../../components/ui/badge'; import { Input } from '../../components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../components/ui/select'; import PlanDialog from '../../components/PlanDialog'; import { toast } from 'sonner'; import { CreditCard, Plus, Edit, Trash2, Users, Search, DollarSign } from 'lucide-react'; const AdminPlans = () => { const [plans, setPlans] = useState([]); const [filteredPlans, setFilteredPlans] = useState([]); const [loading, setLoading] = useState(true); const [searchQuery, setSearchQuery] = useState(''); const [activeFilter, setActiveFilter] = useState('all'); const [planDialogOpen, setPlanDialogOpen] = useState(false); const [selectedPlan, setSelectedPlan] = useState(null); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [planToDelete, setPlanToDelete] = useState(null); useEffect(() => { fetchPlans(); }, []); useEffect(() => { filterPlans(); }, [plans, searchQuery, activeFilter]); const fetchPlans = async () => { try { const response = await api.get('/admin/subscriptions/plans'); setPlans(response.data); } catch (error) { toast.error('Failed to fetch plans'); } finally { setLoading(false); } }; const filterPlans = () => { let filtered = plans; if (activeFilter !== 'all') { filtered = filtered.filter(plan => activeFilter === 'active' ? plan.active : !plan.active ); } if (searchQuery) { const query = searchQuery.toLowerCase(); filtered = filtered.filter(plan => plan.name.toLowerCase().includes(query) || plan.description?.toLowerCase().includes(query) ); } setFilteredPlans(filtered); }; const handleCreatePlan = () => { setSelectedPlan(null); setPlanDialogOpen(true); }; const handleEditPlan = (plan) => { setSelectedPlan(plan); setPlanDialogOpen(true); }; const handleDeleteClick = (plan) => { setPlanToDelete(plan); setDeleteDialogOpen(true); }; const handleDeleteConfirm = async () => { try { await api.delete(`/admin/subscriptions/plans/${planToDelete.id}`); toast.success('Plan deleted successfully'); fetchPlans(); setDeleteDialogOpen(false); } catch (error) { toast.error(error.response?.data?.detail || 'Failed to delete plan'); } }; const formatPrice = (cents) => { return `$${(cents / 100).toFixed(2)}`; }; const getBillingCycleLabel = (cycle) => { const labels = { monthly: 'Monthly', quarterly: 'Quarterly', yearly: 'Yearly', lifetime: 'Lifetime' }; return labels[cycle] || cycle; }; return ( <>

Subscription Plans

Manage membership plans and pricing.

{/* Stats */}

Total Plans

{plans.length}

Active Plans

{plans.filter(p => p.active).length}

Total Subscribers

{plans.reduce((sum, p) => sum + (p.subscriber_count || 0), 0)}

Revenue (Annual Est.)

{formatPrice( plans.reduce((sum, p) => { const annualPrice = p.billing_cycle === 'yearly' ? p.price_cents : p.price_cents * 12; return sum + (annualPrice * (p.subscriber_count || 0)); }, 0) )}

{/* Filters */}
setSearchQuery(e.target.value)} className="pl-12 h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]" />
{/* Plans Grid */} {loading ? (

Loading plans...

) : filteredPlans.length > 0 ? (
{filteredPlans.map((plan) => ( {/* Header with badges */}
{plan.active ? 'Active' : 'Inactive'} {plan.subscriber_count > 0 && ( {plan.subscriber_count} )}
{/* Plan Name */}

{plan.name}

{/* Description */} {plan.description && (

{plan.description}

)} {/* Price */}
{formatPrice(plan.price_cents)}

{getBillingCycleLabel(plan.billing_cycle)}

{/* Stripe Integration Status */}
{plan.stripe_price_id ? ( Stripe Integrated ) : ( Manual/Test Plan )}
{/* Actions */}
{/* Warning for plans with subscribers */} {plan.subscriber_count > 0 && (

Cannot delete plan with active subscribers

)}
))}
) : (

No Plans Found

{searchQuery || activeFilter !== 'all' ? 'Try adjusting your filters' : 'Create your first subscription plan to get started'}

{!searchQuery && activeFilter === 'all' && ( )}
)} {/* Plan Dialog */} {/* Delete Confirmation Dialog */} {deleteDialogOpen && (

Delete Plan

Are you sure you want to delete "{planToDelete?.name}"? This action will deactivate the plan and it won't be available for new subscriptions.

)} ); }; export default AdminPlans;