import React, { useState, useEffect } from 'react'; import { Head, router } from '@inertiajs/react'; import AdminLayout from '@/Layouts/AdminLayout'; import { Plus, Edit2, Trash2, Check, X, Info, MoreVertical, DollarSign, Clock, Zap, Shield, Trophy, Search } from 'lucide-react'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; export default function SubscriptionsIndex({ plans: initialPlans, errors = {} }) { const mapIncomingPlans = (rawPlans) => { if (!rawPlans) return []; return rawPlans.map(p => ({ ...p, price: Number(p.price), maxContactPeople: p.max_contact_people !== undefined ? p.max_contact_people : p.maxContactPeople, unlimitedContacts: p.unlimited_contacts !== undefined ? !!p.unlimited_contacts : !!p.unlimitedContacts, enableJobApply: p.enable_job_apply !== undefined ? !!p.enable_job_apply : !!p.enableJobApply, usageCount: p.usage_count !== undefined ? Number(p.usage_count) : 0 })); }; const [plans, setPlans] = useState(() => mapIncomingPlans(initialPlans || [])); useEffect(() => { if (initialPlans) { setPlans(mapIncomingPlans(initialPlans)); } }, [initialPlans]); const [isDialogOpen, setIsDialogOpen] = useState(false); const [editingPlan, setEditingPlan] = useState(null); const [searchQuery, setSearchQuery] = useState(''); // Form states const [name, setName] = useState(''); const [price, setPrice] = useState(''); const [duration, setDuration] = useState('Monthly'); const [features, setFeatures] = useState(''); const [maxContactPeople, setMaxContactPeople] = useState(''); const [unlimitedContacts, setUnlimitedContacts] = useState(false); const [enableJobApply, setEnableJobApply] = useState(false); const [status, setStatus] = useState('Active'); const handleCreateClick = () => { setEditingPlan(null); setName(''); setPrice(''); setDuration('Monthly'); setFeatures(''); setMaxContactPeople(''); setUnlimitedContacts(false); setEnableJobApply(false); setStatus('Active'); setIsDialogOpen(true); }; const handleEdit = (plan) => { setEditingPlan(plan); setName(plan.name); setPrice(plan.price); setDuration(plan.duration); setFeatures(plan.features.join('\n')); setMaxContactPeople(plan.maxContactPeople !== null && plan.maxContactPeople !== undefined ? plan.maxContactPeople : ''); setUnlimitedContacts(!!plan.unlimitedContacts); setEnableJobApply(!!plan.enableJobApply); setStatus(plan.status || 'Active'); setIsDialogOpen(true); }; const handleDelete = (id) => { if (confirm('Are you sure you want to delete this plan?')) { router.delete(`/admin/subscriptions/${id}`, { onSuccess: () => { // Props are re-loaded automatically by Inertia, updating state via useEffect } }); } }; const handleSave = (e) => { e.preventDefault(); if (!name.trim() || !price) { alert('Please fill out Name and Price.'); return; } const featuresArray = features .split('\n') .map(f => f.trim()) .filter(Boolean); const payload = { name, price: Number(price), duration, features: featuresArray, max_contact_people: unlimitedContacts ? null : (maxContactPeople !== '' ? Number(maxContactPeople) : null), unlimited_contacts: !!unlimitedContacts, enable_job_apply: !!enableJobApply, status }; if (editingPlan) { router.post(`/admin/subscriptions/${editingPlan.id}/update`, payload, { onSuccess: () => { setIsDialogOpen(false); } }); } else { const newId = name.toLowerCase().replace(/\s+/g, '-'); router.post('/admin/subscriptions', { id: newId || `plan-${Date.now()}`, ...payload }, { onSuccess: () => { setIsDialogOpen(false); } }); } }; const filteredPlans = plans.filter(plan => plan.name.toLowerCase().includes(searchQuery.toLowerCase()) || plan.duration.toLowerCase().includes(searchQuery.toLowerCase()) || plan.features.some(f => f.toLowerCase().includes(searchQuery.toLowerCase())) ); return (
{errors.status && (
{errors.status}
)} {/* Header Actions */}
setSearchQuery(e.target.value)} className="w-full pl-10 pr-4 py-2 bg-white border border-slate-200 rounded-lg text-sm focus:ring-2 focus:ring-teal-500/10 focus:border-teal-500 outline-none transition-all" />
{/* Plans Table */}
Plan Name Pricing (AED) Duration Max Contacts Job Apply Key Features Status Actions {filteredPlans.length === 0 ? ( No plans found ) : ( filteredPlans.map((plan) => (
{plan.id === 'basic' ? : plan.id === 'premium' ? : }
{plan.name}
{plan.price} {plan.duration} {plan.unlimitedContacts ? 'Unlimited' : (plan.maxContactPeople || 'Unlimited')} {plan.enableJobApply ? 'Enabled' : 'Disabled'}
{plan.features.map((f, i) => ( {f} ))}
{plan.status || 'Active'} {plan.usageCount > 0 && ( {plan.usageCount} {plan.usageCount === 1 ? 'user' : 'users'} )}
)) )}
{/* Plan Modal */} {editingPlan ? 'Edit Subscription Plan' : 'Create New Plan'} Configure pricing and limits for employers
setName(e.target.value)} className="w-full px-4 py-2.5 bg-slate-50 border border-slate-100 rounded-xl text-sm font-bold focus:ring-4 focus:ring-teal-500/10 outline-none" placeholder="e.g. Pro Search" />
setPrice(e.target.value)} className="w-full px-4 py-2.5 bg-slate-50 border border-slate-100 rounded-xl text-sm font-bold focus:ring-4 focus:ring-teal-500/10 outline-none" placeholder="299" />
setMaxContactPeople(e.target.value)} className={`w-full px-4 py-2.5 border rounded-xl text-sm font-bold focus:ring-4 focus:ring-teal-500/10 outline-none transition-all ${ unlimitedContacts ? 'bg-slate-100 border-slate-200 text-slate-400 cursor-not-allowed' : 'bg-slate-50 border-slate-100 text-slate-800' }`} placeholder={unlimitedContacts ? 'Unlimited' : 'e.g. 10'} />
{status}
Active plans are visible to employers during registration. {errors.status && ( {errors.status} )}
{editingPlan && editingPlan.usageCount > 0 && (
Warning: {editingPlan.usageCount} {editingPlan.usageCount === 1 ? 'person is' : 'people are'} currently using this plan. Disabling this plan is blocked.
)}
setEnableJobApply(e.target.checked)} className="w-4.5 h-4.5 text-teal-600 border-slate-300 rounded focus:ring-teal-500" />