Correcao Sidebar Classico e Rail, Correcao Layout, Ajuste de Breakpoint para Tailwind, Ajuste AppTopbar, Ajuste Menu PopOver, Recriado Paleta de Cores, Inserido algumas animações leves, Reajuste Cor items NOVOS da tabela, Drawer Ajuda Corrigido no Logout, Whatsapp, sms, email, recursos extras

This commit is contained in:
Leonardo
2026-03-24 21:26:58 -03:00
parent a89d1f5560
commit 53a4980396
453 changed files with 121427 additions and 174407 deletions

View File

@@ -0,0 +1,427 @@
-- =============================================================================
-- SEED 014 — Dados Globais (Email Templates, Notification Templates, Carousel)
-- =============================================================================
-- Idempotente: ON CONFLICT DO UPDATE / DO NOTHING
--
-- Cria:
-- 11 email_templates_global (templates de email do sistema)
-- 7 notification_templates WhatsApp (default)
-- 6 notification_templates SMS (default)
-- 3 login_carousel_slides (slides da página de login)
-- =============================================================================
BEGIN;
-- ============================================================
-- 1. Email Templates Globais
-- ============================================================
INSERT INTO public.email_templates_global
(key, domain, channel, subject, body_html, body_text, version, is_active, variables)
VALUES
-- session.reminder.email
(
'session.reminder.email',
'session',
'email',
'Lembrete: sua sessão amanhã às {{session_time}}',
'
<p>Olá, <strong>{{patient_name}}</strong>!</p>
<p>Este é um lembrete da sua sessão agendada para <strong>{{session_date}}</strong> às <strong>{{session_time}}</strong>.</p>
<p>Modalidade: <strong>{{session_modality}}</strong></p>
{{#if session_link}}
<p><a href="{{session_link}}">Clique aqui para entrar na sessão online</a></p>
{{/if}}
<p>Em caso de necessidade de cancelamento, entre em contato com antecedência.</p>
<p>Até logo,<br><strong>{{therapist_name}}</strong></p>
',
'Olá, {{patient_name}}! Lembrete da sua sessão: {{session_date}} às {{session_time}} ({{session_modality}}).',
2,
true,
'{"patient_name":"Nome completo do paciente","session_date":"Data da sessão (ex: 20/03/2026)","session_time":"Horário da sessão (ex: 14:00)","session_modality":"Presencial ou Online","session_link":"Link da videochamada (apenas online)","therapist_name":"Nome do terapeuta"}'
),
-- session.confirmation.email
(
'session.confirmation.email',
'session',
'email',
'Sessão confirmada — {{session_date}} às {{session_time}}',
'
<p>Olá, <strong>{{patient_name}}</strong>!</p>
<p>Sua sessão foi confirmada com sucesso.</p>
<ul>
<li><strong>Data:</strong> {{session_date}}</li>
<li><strong>Horário:</strong> {{session_time}}</li>
<li><strong>Modalidade:</strong> {{session_modality}}</li>
{{#if session_address}}<li><strong>Local:</strong> {{session_address}}</li>{{/if}}
</ul>
<p>Até lá,<br><strong>{{therapist_name}}</strong></p>
',
'Sessão confirmada: {{session_date}} às {{session_time}} ({{session_modality}}).',
1,
true,
'{"patient_name":"Nome do paciente","session_date":"Data da sessão","session_time":"Horário da sessão","session_modality":"Presencial ou Online","session_address":"Endereço (apenas presencial)","therapist_name":"Nome do terapeuta"}'
),
-- session.cancellation.email
(
'session.cancellation.email',
'session',
'email',
'Sessão cancelada — {{session_date}}',
'
<p>Olá, <strong>{{patient_name}}</strong>!</p>
<p>Informamos que sua sessão do dia <strong>{{session_date}}</strong> às <strong>{{session_time}}</strong> foi cancelada.</p>
{{#if cancellation_reason}}<p>Motivo: {{cancellation_reason}}</p>{{/if}}
<p>Entre em contato para reagendar.</p>
<p><strong>{{therapist_name}}</strong></p>
',
NULL,
1,
true,
'{"patient_name":"Nome do paciente","session_date":"Data cancelada","session_time":"Horário cancelado","cancellation_reason":"Motivo do cancelamento (opcional)","therapist_name":"Nome do terapeuta"}'
),
-- session.rescheduled.email
(
'session.rescheduled.email',
'session',
'email',
'Sessão reagendada — {{session_date}} às {{session_time}}',
'
<p>Olá, <strong>{{patient_name}}</strong>!</p>
<p>Sua sessão foi reagendada para <strong>{{session_date}}</strong> às <strong>{{session_time}}</strong>.</p>
<p>Modalidade: <strong>{{session_modality}}</strong></p>
<p>Até lá,<br><strong>{{therapist_name}}</strong></p>
',
NULL,
1,
true,
'{"patient_name":"Nome do paciente","session_date":"Nova data","session_time":"Novo horário","session_modality":"Presencial ou Online","therapist_name":"Nome do terapeuta"}'
),
-- intake.received.email
(
'intake.received.email',
'intake',
'email',
'Recebemos seu cadastro — {{clinic_name}}',
'
<p>Olá, <strong>{{patient_name}}</strong>!</p>
<p>Recebemos seu cadastro com sucesso. Nossa equipe entrará em contato em breve para dar continuidade ao processo.</p>
<p>Obrigado pela confiança,<br><strong>{{clinic_name}}</strong></p>
',
NULL,
1,
true,
'{"patient_name":"Nome do solicitante","clinic_name":"Nome da clínica ou terapeuta"}'
),
-- intake.approved.email
(
'intake.approved.email',
'intake',
'email',
'Cadastro aprovado — bem-vindo(a)!',
'
<p>Olá, <strong>{{patient_name}}</strong>!</p>
<p>Seu cadastro foi aprovado. Você já pode acessar o portal e agendar sua primeira sessão.</p>
<p><a href="{{portal_link}}">Acessar portal →</a></p>
<p>Qualquer dúvida, estamos à disposição.<br><strong>{{therapist_name}}</strong></p>
',
NULL,
1,
true,
'{"patient_name":"Nome do paciente","therapist_name":"Nome do terapeuta","portal_link":"Link do portal do paciente"}'
),
-- intake.rejected.email
(
'intake.rejected.email',
'intake',
'email',
'Atualização sobre seu cadastro — {{clinic_name}}',
'
<p>Olá, <strong>{{patient_name}}</strong>!</p>
<p>Agradecemos seu interesse. Infelizmente não será possível dar continuidade ao seu cadastro no momento.</p>
{{#if rejection_reason}}<p>{{rejection_reason}}</p>{{/if}}
<p><strong>{{clinic_name}}</strong></p>
',
NULL,
1,
true,
'{"patient_name":"Nome do paciente","clinic_name":"Nome da clínica","rejection_reason":"Motivo (opcional)"}'
),
-- scheduler.request_accepted.email
(
'scheduler.request_accepted.email',
'session',
'email',
'Sua solicitação foi aceita — {{session_date}} às {{session_time}}',
'
<p>Olá, <strong>{{patient_name}}</strong>!</p>
<p>Sua solicitação de agendamento foi aceita.</p>
<ul>
<li><strong>Data:</strong> {{session_date}}</li>
<li><strong>Horário:</strong> {{session_time}}</li>
<li><strong>Tipo:</strong> {{session_type}}</li>
<li><strong>Modalidade:</strong> {{session_modality}}</li>
</ul>
<p>Até logo,<br><strong>{{therapist_name}}</strong></p>
',
NULL,
1,
true,
'{"patient_name":"Nome do paciente","session_date":"Data confirmada","session_time":"Horário confirmado","session_type":"Primeira consulta / Retorno","session_modality":"Presencial ou Online","therapist_name":"Nome do terapeuta"}'
),
-- scheduler.request_rejected.email
(
'scheduler.request_rejected.email',
'session',
'email',
'Atualização sobre sua solicitação de agendamento',
'
<p>Olá, <strong>{{patient_name}}</strong>!</p>
<p>Infelizmente não foi possível confirmar sua solicitação de agendamento para <strong>{{session_date}}</strong>.</p>
{{#if rejection_reason}}<p>Motivo: {{rejection_reason}}</p>{{/if}}
<p>Entre em contato para verificar outros horários disponíveis.</p>
<p><strong>{{therapist_name}}</strong></p>
',
NULL,
1,
true,
'{"patient_name":"Nome do paciente","session_date":"Data solicitada","rejection_reason":"Motivo (opcional)","therapist_name":"Nome do terapeuta"}'
),
-- system.welcome.email
(
'system.welcome.email',
'system',
'email',
'Bem-vindo(a) ao {{clinic_name}}!',
'
<p>Olá, <strong>{{patient_name}}</strong>!</p>
<p>Seja bem-vindo(a)! Sua conta foi criada com sucesso.</p>
<p><a href="{{portal_link}}">Acessar minha área →</a></p>
',
NULL,
1,
true,
'{"patient_name":"Nome do paciente","clinic_name":"Nome da clínica","portal_link":"Link do portal"}'
),
-- system.password_reset.email
(
'system.password_reset.email',
'system',
'email',
'Redefinição de senha',
'
<p>Olá, <strong>{{patient_name}}</strong>!</p>
<p>Recebemos uma solicitação para redefinir sua senha.</p>
<p><a href="{{reset_link}}">Clique aqui para redefinir sua senha →</a></p>
<p>Se você não solicitou a redefinição, ignore este e-mail.</p>
',
NULL,
1,
true,
'{"patient_name":"Nome do usuário","reset_link":"Link de redefinição de senha"}'
)
ON CONFLICT (key) DO UPDATE SET
domain = EXCLUDED.domain,
channel = EXCLUDED.channel,
subject = EXCLUDED.subject,
body_html = EXCLUDED.body_html,
body_text = EXCLUDED.body_text,
version = EXCLUDED.version,
is_active = EXCLUDED.is_active,
variables = EXCLUDED.variables,
updated_at = now();
-- ============================================================
-- 2. Notification Templates — WhatsApp (default)
-- ============================================================
INSERT INTO public.notification_templates
(tenant_id, owner_id, key, domain, channel, event_type, body_text, variables, is_default, is_active)
VALUES
-- Lembrete 24h
(
NULL, NULL,
'session.lembrete.whatsapp',
'session', 'whatsapp', 'lembrete_sessao',
E'Olá, {{nome_paciente}}! \U0001F44B\n\nLembrete da sua sessão com {{nome_terapeuta}}.\n\n\U0001F4C5 Data: {{data_sessao}}\n\U0001F550 Hora: {{hora_sessao}}\n\U0001F4CD Modalidade: {{modalidade}}\n\nQualquer dúvida, entre em contato. Até lá! \U0001F49A',
'["nome_paciente","nome_terapeuta","data_sessao","hora_sessao","modalidade"]',
true, true
),
-- Lembrete 2h
(
NULL, NULL,
'session.lembrete_2h.whatsapp',
'session', 'whatsapp', 'lembrete_sessao',
E'Olá, {{nome_paciente}}! Sua sessão com {{nome_terapeuta}} começa em 2 horas.\n\n\U0001F550 Hora: {{hora_sessao}}\n\U0001F4CD Modalidade: {{modalidade}}\n\nAté já! \U0001F60A',
'["nome_paciente","nome_terapeuta","data_sessao","hora_sessao","modalidade"]',
true, true
),
-- Confirmação
(
NULL, NULL,
'session.confirmacao.whatsapp',
'session', 'whatsapp', 'confirmacao_sessao',
E'Olá, {{nome_paciente}}! \u2705\n\nSua sessão foi confirmada!\n\n\U0001F4C5 Data: {{data_sessao}}\n\U0001F550 Hora: {{hora_sessao}}\n\U0001F4CD Modalidade: {{modalidade}}\n\nAté lá! \U0001F49A',
'["nome_paciente","nome_terapeuta","data_sessao","hora_sessao","modalidade","link_confirmacao"]',
true, true
),
-- Cancelamento
(
NULL, NULL,
'session.cancelamento.whatsapp',
'session', 'whatsapp', 'cancelamento_sessao',
E'Olá, {{nome_paciente}}. Infelizmente a sessão do dia {{data_sessao}} às {{hora_sessao}} foi cancelada.\n\nEntre em contato para reagendar. \U0001F64F',
'["nome_paciente","nome_terapeuta","data_sessao","hora_sessao","modalidade"]',
true, true
),
-- Reagendamento
(
NULL, NULL,
'session.reagendamento.whatsapp',
'session', 'whatsapp', 'reagendamento',
E'Olá, {{nome_paciente}}! Sua sessão foi reagendada.\n\n\U0001F4C5 Nova data: {{data_sessao}}\n\U0001F550 Novo horário: {{hora_sessao}}\n\U0001F4CD Modalidade: {{modalidade}}\n\nAté lá! \U0001F60A',
'["nome_paciente","nome_terapeuta","data_sessao","hora_sessao","modalidade"]',
true, true
),
-- Cobrança pendente
(
NULL, NULL,
'cobranca.pendente.whatsapp',
'billing', 'whatsapp', 'cobranca_pendente',
E'Olá, {{nome_paciente}}. Identificamos uma cobrança pendente no valor de {{valor_sessao}} referente à sua sessão do dia {{data_sessao}}.\n\nPor favor, entre em contato para regularizar. \U0001F64F',
'["nome_paciente","nome_terapeuta","data_sessao","hora_sessao","modalidade","valor_sessao"]',
true, true
),
-- Boas-vindas
(
NULL, NULL,
'sistema.boas_vindas.whatsapp',
'system', 'whatsapp', 'boas_vindas_paciente',
E'Olá, {{nome_paciente}}! \U0001F389\n\nSeja muito bem-vindo(a)! Estamos felizes em ter você aqui.\n\nEm caso de dúvidas, estamos à disposição. Até a nossa primeira sessão! \U0001F49A',
'["nome_paciente","nome_terapeuta","data_sessao","hora_sessao","modalidade"]',
true, true
)
ON CONFLICT (tenant_id, owner_id, key, deleted_at) DO NOTHING;
-- ============================================================
-- 3. Notification Templates — SMS (default)
-- ============================================================
INSERT INTO public.notification_templates
(tenant_id, owner_id, key, domain, channel, event_type, body_text, variables, is_default, is_active)
VALUES
(
NULL, NULL,
'session.reminder.sms',
'session', 'sms', 'lembrete_sessao',
'Olá {{patient_name}}, lembrete da sua sessão em {{session_date}} às {{session_time}} com {{therapist_name}}. Modalidade: {{session_modality}}.',
'["patient_name","session_date","session_time","therapist_name","session_modality"]',
true, true
),
(
NULL, NULL,
'session.confirmation.sms',
'session', 'sms', 'confirmacao_sessao',
'Sessão confirmada! {{session_date}} às {{session_time}} ({{session_modality}}) com {{therapist_name}}.',
'["patient_name","session_date","session_time","session_modality","therapist_name"]',
true, true
),
(
NULL, NULL,
'session.cancellation.sms',
'session', 'sms', 'cancelamento_sessao',
'Sua sessão de {{session_date}} às {{session_time}} foi cancelada. Entre em contato para reagendar. — {{therapist_name}}',
'["patient_name","session_date","session_time","therapist_name"]',
true, true
),
(
NULL, NULL,
'session.rescheduled.sms',
'session', 'sms', 'reagendamento',
'Sua sessão foi reagendada para {{session_date}} às {{session_time}} ({{session_modality}}). — {{therapist_name}}',
'["patient_name","session_date","session_time","session_modality","therapist_name"]',
true, true
),
(
NULL, NULL,
'intake.received.sms',
'intake', 'sms', 'intake_recebido',
'Olá {{patient_name}}, recebemos seu cadastro. Em breve entraremos em contato. — {{clinic_name}}',
'["patient_name","clinic_name"]',
true, true
),
(
NULL, NULL,
'intake.approved.sms',
'intake', 'sms', 'intake_aprovado',
'Olá {{patient_name}}, seu cadastro foi aprovado! Acesse o portal para agendar sua sessão. — {{therapist_name}}',
'["patient_name","therapist_name"]',
true, true
)
ON CONFLICT (tenant_id, owner_id, key, deleted_at) DO NOTHING;
-- ============================================================
-- 4. Login Carousel Slides
-- ============================================================
-- Limpa slides existentes e reinsere
DELETE FROM public.login_carousel_slides;
INSERT INTO public.login_carousel_slides (title, body, icon, ordem, ativo)
VALUES
(
'<strong>Gestão clínica simplificada</strong>',
'Agendamentos, prontuários e sessões em um único painel. Foco no que importa: <em>seus pacientes</em>.',
'pi-calendar-clock',
0,
true
),
(
'<strong>Múltiplos profissionais, uma só plataforma</strong>',
'Adicione terapeutas, gerencie vínculos por clínica e mantenha equipes organizadas com controle de acesso por papel.',
'pi-users',
1,
true
),
(
'<strong>Seguro, privado e sempre disponível</strong>',
'Dados protegidos com autenticação robusta, controle de acesso por perfil e conformidade com as boas práticas de privacidade.',
'pi-shield',
2,
true
);
-- ============================================================
-- 5. Confirma
-- ============================================================
DO $$
DECLARE
v_emails integer;
v_notif integer;
v_slides integer;
BEGIN
SELECT count(*) INTO v_emails FROM public.email_templates_global;
SELECT count(*) INTO v_notif FROM public.notification_templates WHERE is_default = true;
SELECT count(*) INTO v_slides FROM public.login_carousel_slides WHERE ativo = true;
RAISE NOTICE 'seed_014_global_data: % email templates, % notification templates, % carousel slides.', v_emails, v_notif, v_slides;
END;
$$;
COMMIT;