import React, { useState, useEffect } from 'react'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from './ui/dialog'; import { Button } from './ui/button'; import { Input } from './ui/input'; import { Label } from './ui/label'; import { Textarea } from './ui/textarea'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from './ui/select'; import { toast } from 'sonner'; import { Loader2 } from 'lucide-react'; import api from '../utils/api'; const MONTHS = [ { value: 1, label: 'January' }, { value: 2, label: 'February' }, { value: 3, label: 'March' }, { value: 4, label: 'April' }, { value: 5, label: 'May' }, { value: 6, label: 'June' }, { value: 7, label: 'July' }, { value: 8, label: 'August' }, { value: 9, label: 'September' }, { value: 10, label: 'October' }, { value: 11, label: 'November' }, { value: 12, label: 'December' } ]; const PlanDialog = ({ open, onOpenChange, plan, onSuccess }) => { const [loading, setLoading] = useState(false); const [formData, setFormData] = useState({ name: '', description: '', price_cents: 3000, // Legacy field, default $30 billing_cycle: 'yearly', stripe_price_id: '', active: true, // Custom billing cycle custom_cycle_enabled: false, custom_cycle_start_month: 1, custom_cycle_start_day: 1, custom_cycle_end_month: 12, custom_cycle_end_day: 31, // Dynamic pricing minimum_price_cents: 3000, // $30 minimum suggested_price_cents: 3000, allow_donation: true }); useEffect(() => { if (plan) { setFormData({ name: plan.name, description: plan.description || '', price_cents: plan.price_cents || 3000, billing_cycle: plan.billing_cycle, stripe_price_id: plan.stripe_price_id || '', active: plan.active, custom_cycle_enabled: plan.custom_cycle_enabled || false, custom_cycle_start_month: plan.custom_cycle_start_month || 1, custom_cycle_start_day: plan.custom_cycle_start_day || 1, custom_cycle_end_month: plan.custom_cycle_end_month || 12, custom_cycle_end_day: plan.custom_cycle_end_day || 31, minimum_price_cents: plan.minimum_price_cents || 3000, suggested_price_cents: plan.suggested_price_cents || plan.minimum_price_cents || 3000, allow_donation: plan.allow_donation !== undefined ? plan.allow_donation : true }); } else { setFormData({ name: '', description: '', price_cents: 3000, billing_cycle: 'yearly', stripe_price_id: '', active: true, custom_cycle_enabled: false, custom_cycle_start_month: 1, custom_cycle_start_day: 1, custom_cycle_end_month: 12, custom_cycle_end_day: 31, minimum_price_cents: 3000, suggested_price_cents: 3000, allow_donation: true }); } }, [plan, open]); const handleSubmit = async (e) => { e.preventDefault(); setLoading(true); try { // Validate minimum price if (formData.minimum_price_cents < 3000) { toast.error('Minimum price must be at least $30'); setLoading(false); return; } // Validate suggested price if (formData.suggested_price_cents < formData.minimum_price_cents) { toast.error('Suggested price must be >= minimum price'); setLoading(false); return; } // Validate custom cycle dates if enabled if (formData.custom_cycle_enabled) { if (!formData.custom_cycle_start_month || !formData.custom_cycle_start_day || !formData.custom_cycle_end_month || !formData.custom_cycle_end_day) { toast.error('All custom cycle dates must be provided'); setLoading(false); return; } } const endpoint = plan ? `/admin/subscriptions/plans/${plan.id}` : '/admin/subscriptions/plans'; const method = plan ? 'put' : 'post'; await api[method](endpoint, { ...formData, price_cents: parseInt(formData.price_cents), minimum_price_cents: parseInt(formData.minimum_price_cents), suggested_price_cents: parseInt(formData.suggested_price_cents) }); toast.success(plan ? 'Plan updated successfully' : 'Plan created successfully'); onSuccess(); onOpenChange(false); } catch (error) { toast.error(error.response?.data?.detail || 'Failed to save plan'); } finally { setLoading(false); } }; const formatPriceForDisplay = (cents) => { return (cents / 100).toFixed(2); }; const handlePriceChange = (field, value) => { const dollars = parseFloat(value) || 0; setFormData({ ...formData, [field]: Math.round(dollars * 100) }); }; return ( {plan ? 'Edit Plan' : 'Create New Plan'} {plan ? 'Update plan details below' : 'Enter plan details to create a new subscription plan'}
{/* Name */}
setFormData({ ...formData, name: e.target.value })} placeholder="e.g., Annual Membership" required className="mt-2" />
{/* Description */}