"use client"; import { Fragment, useEffect, useState } from 'react'; import { Dialog, Transition } from '@headlessui/react'; import Tabs, { TabItem } from '@/components/ui/Tabs'; import { useToast } from '@/components/layout/ToastContext'; import { XMarkIcon, SparklesIcon, UserGroupIcon, ChartBarIcon, FolderIcon, LifebuoyIcon, CreditCardIcon, DocumentTextIcon, ArchiveBoxIcon, ShareIcon, DocumentIcon, CurrencyDollarIcon, SparklesIcon as SparklesIconOutline, CubeIcon, PlusIcon, MinusIcon } from '@heroicons/react/24/outline'; const SOLUTION_ICONS: Record> = { 'crm': UserGroupIcon, 'erp': ChartBarIcon, 'projetos': FolderIcon, 'helpdesk': LifebuoyIcon, 'pagamentos': CreditCardIcon, 'contratos': DocumentTextIcon, 'documentos': ArchiveBoxIcon, 'social': ShareIcon, }; interface Solution { id: string; name: string; slug: string; description?: string; is_active: boolean; } interface EditPlanModalProps { isOpen: boolean; onClose: () => void; planId: string | null; onSuccess: () => void; } export default function EditPlanModal({ isOpen, onClose, planId, onSuccess }: EditPlanModalProps) { const toast = useToast(); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [loadingSolutions, setLoadingSolutions] = useState(true); const [allSolutions, setAllSolutions] = useState([]); const [selectedSolutions, setSelectedSolutions] = useState([]); const [formData, setFormData] = useState({ name: '', slug: '', description: '', monthly_price: '', annual_price: '', min_users: 1, max_users: 30, storage_gb: 1, discount_months: 2, features: '' as string | string[], differentiators: '' as string | string[], is_active: true, }); useEffect(() => { if (isOpen && planId) { fetchPlanData(); fetchAllSolutions(); fetchPlanSolutions(); } }, [isOpen, planId]); const fetchPlanData = async () => { if (!planId) return; try { setLoading(true); const response = await fetch(`/api/admin/plans/${planId}`, { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, }, }); if (response.ok) { const data = await response.json(); const plan = data.plan; console.log('Plano carregado:', plan); console.log('Solu\u00e7\u00f5es do plano:', plan.solutions); setFormData({ name: plan.name || '', slug: plan.slug || '', description: plan.description || '', monthly_price: plan.monthly_price || '', annual_price: plan.annual_price || '', min_users: plan.min_users || 1, max_users: plan.max_users || 30, storage_gb: plan.storage_gb || 1, discount_months: plan.discount_months || 2, features: Array.isArray(plan.features) ? plan.features.join(', ') : (plan.features || ''), differentiators: Array.isArray(plan.differentiators) ? plan.differentiators.join(', ') : (plan.differentiators || ''), is_active: plan.is_active ?? true, }); const solutionIds = plan.solutions?.map((s: Solution) => s.id) || []; console.log('IDs das solu\u00e7\u00f5es extra\u00eddos:', solutionIds); // Não seta aqui, vamos buscar via API separada // setSelectedSolutions(solutionIds); } } catch (error) { console.error('Error fetching plan:', error); } finally { setLoading(false); } }; const fetchPlanSolutions = async () => { if (!planId) return; try { console.log('Buscando soluções do plano...'); const response = await fetch(`/api/admin/plans/${planId}/solutions`, { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, }, }); if (response.ok) { const data = await response.json(); console.log('Soluções do plano (via API separada):', data); const solutionIds = data.solutions?.map((s: Solution) => s.id) || []; console.log('IDs extraídos:', solutionIds); setSelectedSolutions(solutionIds); } else { console.error('Erro ao buscar soluções:', response.status); } } catch (error) { console.error('Error fetching plan solutions:', error); } }; const fetchAllSolutions = async () => { try { setLoadingSolutions(true); const response = await fetch('/api/admin/solutions', { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, }, }); if (response.ok) { const data = await response.json(); console.log('Todas as solu\u00e7\u00f5es dispon\u00edveis:', data.solutions); setAllSolutions(data.solutions || []); } } catch (error) { console.error('Error fetching solutions:', error); } finally { setLoadingSolutions(false); } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!planId) return; setSaving(true); try { const planPayload = { name: formData.name, slug: formData.slug, description: formData.description, monthly_price: parseFloat(String(formData.monthly_price)) || 0, annual_price: parseFloat(String(formData.annual_price)) || 0, min_users: parseInt(String(formData.min_users)) || 1, max_users: parseInt(String(formData.max_users)) || 30, storage_gb: parseInt(String(formData.storage_gb)) || 1, is_active: formData.is_active, features: typeof formData.features === 'string' ? formData.features.split(',').map(f => f.trim()).filter(f => f) : formData.features, differentiators: typeof formData.differentiators === 'string' ? formData.differentiators.split(',').map(d => d.trim()).filter(d => d) : formData.differentiators, }; console.log('Atualizando plano:', planPayload); // Atualizar dados do plano const response = await fetch(`/api/admin/plans/${planId}`, { method: 'PUT', headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, 'Content-Type': 'application/json', }, body: JSON.stringify(planPayload), }); if (!response.ok) { const errorData = await response.json(); console.error('Erro ao atualizar plano:', errorData); toast.error('Erro ao atualizar plano', errorData.message || 'Verifique os dados'); setSaving(false); return; } console.log('Plano atualizado, atualizando soluções:', selectedSolutions); // Atualizar soluções associadas const solutionsResponse = await fetch(`/api/admin/plans/${planId}/solutions`, { method: 'PUT', headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ solution_ids: selectedSolutions }), }); if (!solutionsResponse.ok) { const errorData = await solutionsResponse.json(); console.error('Erro ao atualizar soluções:', errorData); toast.error('Erro ao atualizar soluções', errorData.message || 'Verifique os dados'); setSaving(false); return; } console.log('Soluções atualizadas com sucesso'); toast.success('Plano atualizado!', 'Todas as alterações foram salvas com sucesso'); onSuccess(); onClose(); } catch (error) { console.error('Error updating plan:', error); toast.error('Erro ao atualizar plano', 'Ocorreu um erro inesperado'); } finally { setSaving(false); } }; const handleInputChange = (e: React.ChangeEvent) => { const { name, value, type } = e.target; if (type === 'checkbox') { const checked = (e.target as HTMLInputElement).checked; setFormData(prev => ({ ...prev, [name]: checked })); } else if (type === 'number') { const numValue = parseFloat(value) || 0; setFormData(prev => { const newData = { ...prev, [name]: numValue, }; // Calcular preço anual automaticamente quando mensal ou discount_months muda if ((name === 'monthly_price' || name === 'discount_months')) { const monthlyPrice = name === 'monthly_price' ? numValue : parseFloat(String(prev.monthly_price)) || 0; const discountMonths = name === 'discount_months' ? numValue : prev.discount_months; if (monthlyPrice > 0 && discountMonths >= 0) { // Calcula: (12 meses - meses de desconto) * preço mensal const monthsToPay = Math.max(0, 12 - discountMonths); const annualWithDiscount = (monthlyPrice * monthsToPay).toFixed(2); newData.annual_price = annualWithDiscount; } } return newData; }); } else { setFormData(prev => ({ ...prev, [name]: value })); } }; const incrementValue = (field: 'min_users' | 'max_users' | 'storage_gb' | 'discount_months', step: number = 1) => { setFormData(prev => { const newValue = prev[field] + step; const newData = { ...prev, [field]: newValue, }; // Recalcular preço anual se mudou discount_months if (field === 'discount_months') { const monthlyPrice = parseFloat(String(prev.monthly_price)) || 0; if (monthlyPrice > 0 && newValue >= 0) { const monthsToPay = Math.max(0, 12 - newValue); newData.annual_price = (monthlyPrice * monthsToPay).toFixed(2); } } return newData; }); }; const decrementValue = (field: 'min_users' | 'max_users' | 'storage_gb' | 'discount_months', step: number = 1, min: number = 0) => { setFormData(prev => { const newValue = Math.max(min, prev[field] - step); const newData = { ...prev, [field]: newValue, }; // Recalcular preço anual se mudou discount_months if (field === 'discount_months') { const monthlyPrice = parseFloat(String(prev.monthly_price)) || 0; if (monthlyPrice > 0 && newValue >= 0) { const monthsToPay = Math.max(0, 12 - newValue); newData.annual_price = (monthlyPrice * monthsToPay).toFixed(2); } } return newData; }); }; const handleClose = () => { if (!saving) { onClose(); } }; // Configuração dos tabs const tabsConfig: TabItem[] = [ { name: 'Dados Básicos', icon: DocumentIcon, content: (