microtecflix/src/components/AdminMessagesView.tsx

666 lines
32 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState, useEffect, useRef } from 'react';
import { Mail, MessageSquare, BookOpen, Send, User, Reply, CheckCircle2, AlertCircle, Smartphone, Save, Smile, Megaphone, Clock } from 'lucide-react';
import CustomModal from './CustomModal';
interface SupportTicket {
id: string;
content: string;
status: string;
createdAt: string;
user: {
id: string;
name: string;
email: string;
avatarUrl: string | null;
whatsapp: string | null;
};
}
interface Note {
id: string;
content: string;
createdAt: string;
user: {
id: string;
name: string;
email: string;
avatarUrl: string | null;
whatsapp: string | null;
};
lesson: {
title: string;
module: {
course: {
title: string;
}
}
};
}
// Simple emoji picker groups
const EMOJI_LIST = [
'😊','😁','🎉','🙏','💪','🚀','❤️','✅','⭐','🔥','💡','📚','🎓','👏','🤝',
'💰','💳','🛒','📱','📧','🌟','🏆','✨','🎯','📢','👋','😀','🥳','💎','🌈'
];
// Default template texts
const DEFAULT_TEMPLATES: Record<string, string> = {
whatsappTemplatePayment: `Olá, *{nome}*! 🎉
Recebemos a confirmação do seu pagamento com sucesso!
💰 *Valor:* {valor}
📦 *Plano/Curso:* {plano}{curso}
Seu acesso já está liberado na plataforma. Qualquer dúvida, estamos à disposição.
Muito obrigado pela sua confiança! 🙏
_Equipe MicrotecFlix_`,
whatsappTemplateWelcome: `Olá, *{nome}*! 👋
Seja muito bem-vindo(a) à *MicrotecFlix*! 🎓🚀
Estamos felizes em ter você conosco. Agora você tem acesso à nossa plataforma de cursos de informática e pacote Office.
Acesse: https://estudo.microtecinformaticacurso.com.br
Se tiver qualquer dúvida, é só chamar. 😊
_Equipe MicrotecFlix_`,
whatsappTemplateNewContent: `Oi, *{nome}*! 🎬
Temos uma novidade imperdível para você na plataforma!
⭐ *Novo conteúdo disponível:* Acabamos de publicar um novo curso/módulo/aula.
Acesse agora mesmo e aproveite: https://estudo.microtecinformaticacurso.com.br
Bons estudos! 💪
_Equipe MicrotecFlix_`,
whatsappTemplatePromo: `Oi, *{nome}*! 🌟
Temos uma oferta especial para você hoje!
🎯 Aproveite nossa promoção exclusiva e acelere seus estudos de informática e pacote Office.
Não perca essa oportunidade única! Acesse agora:
https://estudo.microtecinformaticacurso.com.br
Qualquer dúvida, estamos aqui. 🙏
_Equipe MicrotecFlix_`
};
export default function AdminMessagesView() {
const [activeTab, setActiveTab] = useState<'tickets' | 'notes' | 'whatsapp_templates'>('tickets');
const [tickets, setTickets] = useState<SupportTicket[]>([]);
const [notes, setNotes] = useState<Note[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [replyText, setReplyText] = useState('');
const [replyingTo, setReplyingTo] = useState<string | null>(null);
const [isSending, setIsSending] = useState(false);
const [alertModal, setAlertModal] = useState<{isOpen: boolean, title: string, message: string, isError?: boolean}>({isOpen: false, title: '', message: ''});
// WhatsApp Templates State
const [settings, setSettings] = useState<any>(null);
const [activeTemplateModal, setActiveTemplateModal] = useState<string | null>(null);
const [currentTemplateText, setCurrentTemplateText] = useState('');
const [isSavingTemplate, setIsSavingTemplate] = useState(false);
const [isTestingTemplate, setIsTestingTemplate] = useState<string | null>(null);
const [showEmojiPicker, setShowEmojiPicker] = useState(false);
const textareaRef = useRef<HTMLTextAreaElement>(null);
// Broadcast state
const [broadcastText, setBroadcastText] = useState('');
const [broadcastDelay, setBroadcastDelay] = useState(10);
const [isBroadcasting, setIsBroadcasting] = useState(false);
const [showBroadcastEmojiPicker, setShowBroadcastEmojiPicker] = useState(false);
const broadcastRef = useRef<HTMLTextAreaElement>(null);
useEffect(() => {
fetchData();
}, []);
const fetchData = async () => {
setIsLoading(true);
try {
const token = localStorage.getItem('admin_token');
const [msgRes, settingsRes] = await Promise.all([
fetch('/api/admin/messages', { headers: { 'Authorization': `Bearer ${token}` } }),
fetch('/api/admin/settings', { headers: { 'Authorization': `Bearer ${token}` } })
]);
if (msgRes.ok) {
const data = await msgRes.json();
setTickets(data.tickets);
setNotes(data.notes);
}
if (settingsRes.ok) {
const data = await settingsRes.json();
setSettings(data);
// Pre-fill broadcast from template
if (data.whatsappTemplatePromo) {
setBroadcastText(data.whatsappTemplatePromo);
}
}
} catch (error) {
console.error('Error fetching data:', error);
} finally {
setIsLoading(false);
}
};
const handleReply = async (userId: string, ticketId?: string) => {
if (!replyText.trim()) return;
setIsSending(true);
try {
const token = localStorage.getItem('admin_token');
const res = await fetch('/api/admin/reply-message', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ userId, message: replyText, ticketId })
});
if (res.ok) {
setReplyText('');
setReplyingTo(null);
fetchData();
setAlertModal({isOpen: true, title: 'Sucesso', message: 'Resposta enviada com sucesso!'});
} else {
setAlertModal({isOpen: true, title: 'Erro', message: 'Erro ao enviar resposta.', isError: true});
}
} catch (error) {
console.error('Error replying:', error);
setAlertModal({isOpen: true, title: 'Erro', message: 'Erro interno ao enviar resposta.', isError: true});
} finally {
setIsSending(false);
}
};
const handleSaveTemplate = async (field: string) => {
setIsSavingTemplate(true);
try {
const token = localStorage.getItem('admin_token');
const res = await fetch('/api/admin/settings', {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ [field]: currentTemplateText })
});
if (res.ok) {
setSettings({...settings, [field]: currentTemplateText});
setActiveTemplateModal(null);
setAlertModal({isOpen: true, title: 'Sucesso', message: 'Template salvo com sucesso! O envio automático já está ativado.'});
} else {
setAlertModal({isOpen: true, title: 'Erro', message: 'Erro ao salvar template.', isError: true});
}
} catch (error) {
console.error('Error saving template:', error);
setAlertModal({isOpen: true, title: 'Erro', message: 'Erro interno ao salvar template.', isError: true});
} finally {
setIsSavingTemplate(false);
}
};
const handleTestTemplate = async (templateId: string, e: React.MouseEvent) => {
e.stopPropagation();
setIsTestingTemplate(templateId);
try {
const token = localStorage.getItem('admin_token');
const res = await fetch('/api/admin/whatsapp/test-template', {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ templateId })
});
const data = await res.json();
if (res.ok) {
setAlertModal({isOpen: true, title: 'Enviado! 📱', message: data.message});
} else {
setAlertModal({isOpen: true, title: 'Erro no Teste', message: data.error, isError: true});
}
} catch (error) {
console.error('Error testing template:', error);
setAlertModal({isOpen: true, title: 'Erro', message: 'Erro interno ao testar template.', isError: true});
} finally {
setIsTestingTemplate(null);
}
};
const insertEmoji = (emoji: string, isForBroadcast = false) => {
const ref = isForBroadcast ? broadcastRef : textareaRef;
const setter = isForBroadcast ? setBroadcastText : setCurrentTemplateText;
const current = isForBroadcast ? broadcastText : currentTemplateText;
if (ref.current) {
const start = ref.current.selectionStart;
const end = ref.current.selectionEnd;
const newText = current.substring(0, start) + emoji + current.substring(end);
setter(newText);
setTimeout(() => {
if (ref.current) {
ref.current.focus();
ref.current.setSelectionRange(start + emoji.length, start + emoji.length);
}
}, 0);
} else {
setter(current + emoji);
}
if (isForBroadcast) setShowBroadcastEmojiPicker(false);
else setShowEmojiPicker(false);
};
const handleBroadcast = async () => {
if (!broadcastText.trim()) return;
setIsBroadcasting(true);
try {
const token = localStorage.getItem('admin_token');
const res = await fetch('/api/admin/whatsapp/broadcast', {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ message: broadcastText, delaySeconds: broadcastDelay })
});
const data = await res.json();
if (res.ok) {
setAlertModal({isOpen: true, title: 'Envio Iniciado! 🚀', message: data.message || 'Broadcast iniciado com sucesso!'});
} else {
setAlertModal({isOpen: true, title: 'Erro', message: data.error || 'Erro ao iniciar broadcast.', isError: true});
}
} catch (error) {
console.error('Error broadcasting:', error);
setAlertModal({isOpen: true, title: 'Erro', message: 'Erro interno ao enviar.', isError: true});
} finally {
setIsBroadcasting(false);
}
};
const whatsappTemplates = [
{ id: 'whatsappTemplatePayment', title: 'Pagamento Confirmado', desc: 'Enviada automaticamente quando o aluno paga um plano ou curso.', icon: '💰', tags: ['{nome}', '{valor}', '{plano}', '{curso}'] },
{ id: 'whatsappTemplateWelcome', title: 'Boas-Vindas (Nova Conta)', desc: 'Enviada automaticamente quando o aluno cria uma conta.', icon: '👋', tags: ['{nome}'] },
{ id: 'whatsappTemplateNewContent', title: 'Novo Conteúdo (Carrossel)', desc: 'Enviada manualmente ao postar curso/módulo/aula.', icon: '🎬', tags: ['{nome}'] },
];
return (
<div className="space-y-6">
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-4">
<div>
<h2 className="text-2xl font-bold text-white flex items-center space-x-2">
<Mail className="w-6 h-6 text-[#E50914]" />
<span>Mensagens e Comunicações</span>
</h2>
<p className="text-zinc-400 text-sm mt-1">Gerencie dúvidas, anotações e configure as mensagens automáticas do WhatsApp.</p>
</div>
</div>
<div className="flex space-x-4 border-b border-white/10 overflow-x-auto">
<button
onClick={() => setActiveTab('tickets')}
className={`pb-3 px-1 text-sm font-bold flex items-center space-x-2 border-b-2 transition-colors whitespace-nowrap ${activeTab === 'tickets' ? 'border-[#E50914] text-white' : 'border-transparent text-zinc-500 hover:text-zinc-300'}`}
>
<MessageSquare className="w-4 h-4" />
<span>Comentários / Ajuda ({tickets.length})</span>
</button>
<button
onClick={() => setActiveTab('notes')}
className={`pb-3 px-1 text-sm font-bold flex items-center space-x-2 border-b-2 transition-colors whitespace-nowrap ${activeTab === 'notes' ? 'border-[#E50914] text-white' : 'border-transparent text-zinc-500 hover:text-zinc-300'}`}
>
<BookOpen className="w-4 h-4" />
<span>Anotações de Aulas ({notes.length})</span>
</button>
<button
onClick={() => setActiveTab('whatsapp_templates')}
className={`pb-3 px-1 text-sm font-bold flex items-center space-x-2 border-b-2 transition-colors whitespace-nowrap ${activeTab === 'whatsapp_templates' ? 'border-[#E50914] text-white' : 'border-transparent text-zinc-500 hover:text-zinc-300'}`}
>
<Smartphone className="w-4 h-4" />
<span>Modelos WhatsApp</span>
</button>
</div>
{isLoading ? (
<div className="flex justify-center items-center py-20">
<div className="w-8 h-8 border-4 border-[#E50914] border-t-transparent rounded-full animate-spin"></div>
</div>
) : (
<div className="space-y-4">
{activeTab === 'tickets' && (
tickets.length === 0 ? (
<div className="text-center py-12 text-zinc-500">Nenhum comentário recebido.</div>
) : (
tickets.map(ticket => (
<div key={ticket.id} className="bg-zinc-900 border border-white/10 rounded-xl p-5 space-y-4 relative">
{ticket.status === 'REPLIED' && (
<div className="absolute top-4 right-4 text-[10px] uppercase font-bold text-emerald-500 bg-emerald-500/10 px-2 py-1 rounded">
Respondido
</div>
)}
<div className="flex items-start space-x-4">
<div className="w-10 h-10 rounded-full bg-zinc-800 flex items-center justify-center flex-shrink-0 overflow-hidden">
{ticket.user.avatarUrl ? (
<img src={ticket.user.avatarUrl} alt={ticket.user.name} className="w-full h-full object-cover" />
) : (
<User className="w-5 h-5 text-zinc-400" />
)}
</div>
<div>
<h4 className="font-bold text-white text-sm">{ticket.user.name}</h4>
<p className="text-xs text-zinc-500">{ticket.user.email} {ticket.user.whatsapp && `• WA: ${ticket.user.whatsapp}`}</p>
<p className="text-[10px] text-zinc-600 mt-0.5">{new Date(ticket.createdAt).toLocaleString('pt-BR')}</p>
</div>
</div>
<div className="bg-black/20 p-4 rounded-lg text-zinc-300 text-sm whitespace-pre-wrap">
{ticket.content}
</div>
{replyingTo === ticket.id ? (
<div className="mt-4 space-y-3">
<textarea
value={replyText}
onChange={(e) => setReplyText(e.target.value)}
placeholder="Escreva sua resposta (será enviada via Notificação e WhatsApp se ativado)..."
className="w-full h-24 bg-black/40 border border-white/10 rounded-lg p-3 text-white text-sm focus:outline-none focus:border-[#E50914] resize-none"
/>
<div className="flex justify-end space-x-2">
<button onClick={() => { setReplyingTo(null); setReplyText(''); }} className="px-3 py-1.5 text-xs text-zinc-400 hover:text-white transition-colors">Cancelar</button>
<button
onClick={() => handleReply(ticket.user.id, ticket.id)}
disabled={!replyText.trim() || isSending}
className="bg-[#E50914] hover:bg-red-700 text-white px-4 py-1.5 rounded text-xs font-bold transition-colors disabled:opacity-50 flex items-center space-x-2"
>
{isSending ? <div className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" /> : <><Send className="w-3 h-3" /><span>Enviar Resposta</span></>}
</button>
</div>
</div>
) : (
<button onClick={() => { setReplyingTo(ticket.id); setReplyText(''); }} className="text-xs text-[#E50914] hover:text-red-400 transition-colors font-bold flex items-center space-x-1">
<Reply className="w-3 h-3" />
<span>Responder</span>
</button>
)}
</div>
))
)
)}
{activeTab === 'notes' && (
notes.length === 0 ? (
<div className="text-center py-12 text-zinc-500">Nenhuma anotação registrada.</div>
) : (
notes.map(note => (
<div key={note.id} className="bg-zinc-900 border border-white/10 rounded-xl p-5 space-y-4">
<div className="flex items-start justify-between">
<div className="flex items-start space-x-4">
<div className="w-10 h-10 rounded-full bg-zinc-800 flex items-center justify-center flex-shrink-0 overflow-hidden">
{note.user.avatarUrl ? (
<img src={note.user.avatarUrl} alt={note.user.name} className="w-full h-full object-cover" />
) : (
<User className="w-5 h-5 text-zinc-400" />
)}
</div>
<div>
<h4 className="font-bold text-white text-sm">{note.user.name}</h4>
<p className="text-xs text-zinc-500">{note.user.email}</p>
<p className="text-[10px] text-zinc-600 mt-0.5">{new Date(note.createdAt).toLocaleString('pt-BR')}</p>
</div>
</div>
<div className="text-right max-w-[200px]">
<span className="text-[10px] uppercase font-bold text-blue-500 bg-blue-500/10 px-2 py-1 rounded block truncate">
{note.lesson.module.course.title}
</span>
<span className="text-xs text-zinc-400 block mt-1 truncate">{note.lesson.title}</span>
</div>
</div>
<div className="bg-black/20 p-4 rounded-lg text-zinc-300 text-sm whitespace-pre-wrap">
{note.content}
</div>
{replyingTo === note.id ? (
<div className="mt-4 space-y-3">
<textarea
value={replyText}
onChange={(e) => setReplyText(e.target.value)}
placeholder="Escreva sua resposta para esta anotação..."
className="w-full h-24 bg-black/40 border border-white/10 rounded-lg p-3 text-white text-sm focus:outline-none focus:border-[#E50914] resize-none"
/>
<div className="flex justify-end space-x-2">
<button onClick={() => { setReplyingTo(null); setReplyText(''); }} className="px-3 py-1.5 text-xs text-zinc-400 hover:text-white transition-colors">Cancelar</button>
<button
onClick={() => handleReply(note.user.id)}
disabled={!replyText.trim() || isSending}
className="bg-[#E50914] hover:bg-red-700 text-white px-4 py-1.5 rounded text-xs font-bold transition-colors disabled:opacity-50 flex items-center space-x-2"
>
{isSending ? <div className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" /> : <><Send className="w-3 h-3" /><span>Enviar Resposta</span></>}
</button>
</div>
</div>
) : (
<button onClick={() => { setReplyingTo(note.id); setReplyText(''); }} className="text-xs text-[#E50914] hover:text-red-400 transition-colors font-bold flex items-center space-x-1">
<Reply className="w-3 h-3" />
<span>Responder</span>
</button>
)}
</div>
))
)
)}
{activeTab === 'whatsapp_templates' && (
<div className="space-y-6 mt-4">
{/* Automatic Templates */}
<div>
<h3 className="text-sm font-bold text-zinc-400 uppercase tracking-wider mb-3 flex items-center gap-2">
<Smartphone className="w-4 h-4 text-green-500" />
Mensagens Automáticas
</h3>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
{whatsappTemplates.map(t => (
<div
key={t.id}
className="bg-zinc-900 border border-white/10 rounded-xl p-5 hover:border-white/25 transition-all cursor-pointer group"
onClick={() => {
setCurrentTemplateText(settings?.[t.id] || DEFAULT_TEMPLATES[t.id] || '');
setActiveTemplateModal(t.id);
}}
>
<div className="flex items-start gap-3 mb-3">
<span className="text-2xl">{t.icon}</span>
<div className="flex-1 min-w-0">
<h3 className="text-sm font-bold text-white group-hover:text-[#E50914] transition-colors">{t.title}</h3>
<p className="text-[11px] text-zinc-500 leading-snug mt-0.5">{t.desc}</p>
</div>
</div>
<div className="bg-black/30 p-2.5 rounded-lg text-[11px] text-zinc-400 line-clamp-3 min-h-[50px] whitespace-pre-wrap mb-2">
{settings?.[t.id] || DEFAULT_TEMPLATES[t.id] || 'Clique para configurar...'}
</div>
<div className="flex flex-wrap gap-1">
{t.tags.map(tag => (
<span key={tag} className="text-[9px] bg-blue-500/10 text-blue-300 px-1.5 py-0.5 rounded font-mono">{tag}</span>
))}
</div>
<div className="mt-3 flex items-center justify-between">
<div className="flex items-center gap-1.5">
<div className={`w-2 h-2 rounded-full ${settings?.[t.id] ? 'bg-green-500' : 'bg-zinc-600'}`}></div>
<span className={`text-[10px] font-bold ${settings?.[t.id] ? 'text-green-400' : 'text-zinc-500'}`}>
{settings?.[t.id] ? 'Ativo' : 'Não configurado'}
</span>
</div>
{settings?.[t.id] && (
<button
onClick={(e) => handleTestTemplate(t.id, e)}
disabled={isTestingTemplate === t.id}
className="bg-zinc-800 hover:bg-zinc-700 text-zinc-300 px-3 py-1 rounded text-[10px] font-bold flex items-center gap-1 transition-colors"
>
{isTestingTemplate === t.id ? (
<div className="w-3 h-3 border-2 border-white/30 border-t-white rounded-full animate-spin" />
) : (
<>
<Send className="w-3 h-3" />
<span>Testar Envio</span>
</>
)}
</button>
)}
</div>
</div>
))}
</div>
</div>
{/* Mass Broadcast */}
<div className="bg-zinc-900 border border-amber-500/20 rounded-xl p-6">
<div className="flex items-center gap-3 mb-4">
<div className="w-10 h-10 bg-amber-500/10 rounded-full flex items-center justify-center text-xl">🚀</div>
<div>
<h3 className="text-lg font-bold text-white flex items-center gap-2">
<Megaphone className="w-5 h-5 text-amber-400" />
Promoção em Massa
</h3>
<p className="text-xs text-zinc-500">Envia para todos os alunos que têm WhatsApp cadastrado.</p>
</div>
</div>
<div className="bg-amber-500/5 border border-amber-500/15 p-3 rounded-lg text-xs text-amber-200 mb-4 space-y-1">
<p><strong> Anti-Spam:</strong> Configure o intervalo de envio para evitar bloqueio pelo WhatsApp.</p>
<p><strong>Tag dinâmica:</strong> Use <code className="bg-black/40 px-1 rounded">{'{nome}'}</code> para personalizar com o primeiro nome do aluno.</p>
</div>
<div className="space-y-3">
<div className="relative">
<textarea
ref={broadcastRef}
value={broadcastText}
onChange={(e) => setBroadcastText(e.target.value)}
className="w-full h-40 bg-black/40 border border-white/10 rounded-lg p-3 pr-12 text-white text-sm focus:outline-none focus:border-amber-500/50 resize-none"
placeholder="Escreva a mensagem de promoção aqui..."
/>
<div className="absolute bottom-3 right-3">
<button
onClick={() => setShowBroadcastEmojiPicker(!showBroadcastEmojiPicker)}
className="w-8 h-8 flex items-center justify-center text-zinc-400 hover:text-amber-400 transition-colors"
title="Inserir emoji"
>
<Smile className="w-5 h-5" />
</button>
</div>
{showBroadcastEmojiPicker && (
<div className="absolute bottom-12 right-3 bg-zinc-800 border border-white/10 rounded-xl p-3 grid grid-cols-6 gap-1.5 z-10 shadow-2xl">
{EMOJI_LIST.map(emoji => (
<button key={emoji} onClick={() => insertEmoji(emoji, true)} className="text-xl hover:scale-125 transition-transform p-1 rounded hover:bg-white/10">
{emoji}
</button>
))}
</div>
)}
</div>
<div className="flex items-center gap-3">
<Clock className="w-4 h-4 text-amber-400 flex-shrink-0" />
<label className="text-xs text-zinc-300 flex-shrink-0">Intervalo entre mensagens:</label>
<input
type="number"
value={broadcastDelay}
onChange={e => setBroadcastDelay(Math.max(5, Math.min(120, Number(e.target.value))))}
min={5}
max={120}
className="w-20 bg-black/40 border border-white/10 rounded-lg px-3 py-1.5 text-white text-sm focus:outline-none focus:border-amber-500/50"
/>
<span className="text-xs text-zinc-500">segundos (mín: 5s / máx: 120s)</span>
</div>
<div className="flex justify-end">
<button
onClick={handleBroadcast}
disabled={!broadcastText.trim() || isBroadcasting}
className="bg-amber-600 hover:bg-amber-500 text-white px-6 py-2.5 rounded-lg font-bold transition-colors disabled:opacity-50 flex items-center space-x-2"
>
{isBroadcasting
? <><div className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" /><span>Iniciando...</span></>
: <><Megaphone className="w-4 h-4" /><span>Enviar para Todos</span></>
}
</button>
</div>
</div>
</div>
</div>
)}
</div>
)}
{/* Template Edit Modal */}
<CustomModal isOpen={!!activeTemplateModal} onClose={() => { setActiveTemplateModal(null); setShowEmojiPicker(false); }} title={whatsappTemplates.find(t => t.id === activeTemplateModal)?.title || 'Editar Template'} isGlass={true}>
<div className="space-y-4">
<div className="bg-blue-500/10 border border-blue-500/20 p-3 rounded-lg text-xs text-blue-200 space-y-1">
<p><strong>Formatação do WhatsApp:</strong> Use <code className="bg-black/40 px-1 rounded">*negrito*</code>, <code className="bg-black/40 px-1 rounded">_itálico_</code>, <code className="bg-black/40 px-1 rounded">~riscado~</code>.</p>
<p><strong>Tags disponíveis:</strong>{' '}
{whatsappTemplates.find(t => t.id === activeTemplateModal)?.tags.map(tag => (
<code key={tag} className="bg-black/40 px-1 rounded font-bold text-blue-100 mr-1">{tag}</code>
))}
</p>
</div>
<div className="relative">
<textarea
ref={textareaRef}
value={currentTemplateText}
onChange={(e) => setCurrentTemplateText(e.target.value)}
className="w-full h-52 bg-black/40 border border-white/10 rounded-lg p-3 pr-12 text-white text-sm focus:outline-none focus:border-[#E50914] resize-none"
placeholder="Escreva a mensagem aqui..."
/>
<div className="absolute bottom-3 right-3">
<button
onClick={() => setShowEmojiPicker(!showEmojiPicker)}
className="w-8 h-8 flex items-center justify-center text-zinc-400 hover:text-[#E50914] transition-colors"
title="Inserir emoji"
>
<Smile className="w-5 h-5" />
</button>
</div>
{showEmojiPicker && (
<div className="absolute bottom-12 right-3 bg-zinc-800 border border-white/10 rounded-xl p-3 grid grid-cols-6 gap-1.5 z-10 shadow-2xl">
{EMOJI_LIST.map(emoji => (
<button key={emoji} onClick={() => insertEmoji(emoji, false)} className="text-xl hover:scale-125 transition-transform p-1 rounded hover:bg-white/10">
{emoji}
</button>
))}
</div>
)}
</div>
<div className="flex justify-end space-x-2">
<button onClick={() => { setActiveTemplateModal(null); setShowEmojiPicker(false); }} className="px-4 py-2 text-zinc-400 hover:text-white transition-colors text-sm">
Cancelar
</button>
<button
onClick={() => handleSaveTemplate(activeTemplateModal!)}
disabled={isSavingTemplate}
className="bg-[#E50914] hover:bg-red-700 text-white px-6 py-2 rounded-lg font-bold transition-colors disabled:opacity-50 flex items-center space-x-2"
>
{isSavingTemplate ? <div className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" /> : <><Save className="w-4 h-4" /><span>Salvar Template</span></>}
</button>
</div>
</div>
</CustomModal>
{/* Alert Modal */}
<CustomModal isOpen={alertModal.isOpen} onClose={() => setAlertModal({...alertModal, isOpen: false})} title={alertModal.title} isGlass={true}>
<div className="flex items-start gap-4">
{alertModal.isError ? (
<div className="bg-red-500/10 p-3 rounded-full shrink-0"><AlertCircle className="w-6 h-6 text-red-500" /></div>
) : (
<div className="bg-green-500/10 p-3 rounded-full shrink-0"><CheckCircle2 className="w-6 h-6 text-green-500" /></div>
)}
<div className="flex-1">
<p className="text-zinc-300 text-base">{alertModal.message}</p>
<div className="mt-6 flex justify-end">
<button onClick={() => setAlertModal({...alertModal, isOpen: false})} className="px-6 py-2 bg-zinc-800 hover:bg-zinc-700 text-white rounded-lg font-bold transition-colors">
OK
</button>
</div>
</div>
</div>
</CustomModal>
</div>
);
}