guisilvagomes 0d3cad1b55 feat: Implementar todas correções desde desvinculação Netlify
- Corrigir sintaxe PostgREST em todos serviços (getById, update, delete)
  * patientService: ?id=eq.uuid
  * doctorService: ?id=eq.uuid
  * appointmentService: ?id=eq.uuid
  * reportService: ?id=eq.uuid

- Adicionar componente Chatbot com IA
  * Respostas inteligentes baseadas em palavras-chave
  * Quick replies para perguntas frequentes
  * Integrado em CentralAjuda e CentralAjudaMedico

- Padronizar LoginPaciente
  * Usar loginComEmailSenha (mesma API de LoginSecretaria)
  * Remover lógica antiga de loginPaciente
  * Simplificar fluxo de autenticação
2025-10-23 17:21:21 -03:00

416 lines
18 KiB
TypeScript

import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import {
MessageCircle,
Phone,
Mail,
Search,
ChevronDown,
BookOpen,
Video,
FileText,
Shield,
AlertCircle,
Headphones,
ArrowLeft,
} from "lucide-react";
import { Chatbot } from "../components/Chatbot";
interface FAQ {
question: string;
answer: string;
category: string;
}
const faqs: FAQ[] = [
{
category: "Agendamento",
question: "Como agendar uma consulta?",
answer:
"Para agendar uma consulta, vá até a seção 'Agendar Consulta' no menu lateral, selecione o médico desejado, escolha uma data e horário disponível, e confirme o agendamento. Você receberá uma confirmação por e-mail.",
},
{
category: "Agendamento",
question: "Posso cancelar ou remarcar uma consulta?",
answer:
"Sim, você pode cancelar ou remarcar suas consultas em 'Minhas Consultas'. Recomendamos fazer isso com pelo menos 24 horas de antecedência para evitar taxas de cancelamento.",
},
{
category: "Agendamento",
question: "Posso agendar consulta para outra pessoa?",
answer:
"Sim, você pode agendar consultas para dependentes cadastrados em seu perfil. Basta selecioná-los no momento do agendamento.",
},
{
category: "Consultas",
question: "Como funciona a teleconsulta?",
answer:
"A teleconsulta é realizada por videochamada. No horário da consulta, acesse 'Minhas Consultas' e clique em 'Iniciar Consulta Online'. Certifique-se de ter uma conexão estável de internet e permita o acesso à câmera e microfone.",
},
{
category: "Consultas",
question: "Quanto tempo antes devo chegar para a consulta presencial?",
answer:
"Recomendamos chegar com 15 minutos de antecedência para realizar o check-in e atualizar suas informações cadastrais se necessário.",
},
{
category: "Consultas",
question: "Como acesso o histórico das minhas consultas?",
answer:
"Seu histórico completo de consultas está disponível em 'Minhas Consultas'. Lá você pode ver consultas realizadas, relatórios médicos e prescrições anteriores.",
},
{
category: "Pagamento",
question: "Quais formas de pagamento são aceitas?",
answer:
"Aceitamos cartão de crédito, débito, PIX e boleto bancário. Os pagamentos são processados de forma segura através da nossa plataforma.",
},
{
category: "Pagamento",
question: "Posso parcelar o pagamento?",
answer:
"Sim, oferecemos parcelamento em até 3x sem juros no cartão de crédito para consultas acima de R$ 150,00.",
},
{
category: "Pagamento",
question: "Como funciona o reembolso em caso de cancelamento?",
answer:
"Cancelamentos feitos com mais de 24 horas de antecedência têm reembolso integral. Cancelamentos com menos de 24 horas podem ter retenção de 30% como taxa administrativa.",
},
{
category: "Informações Médicas",
question: "Como acesso meu histórico médico?",
answer:
"Seu histórico médico, incluindo consultas anteriores, exames e receitas, pode ser acessado na seção 'Meu Perfil'. Você pode fazer download de documentos quando necessário.",
},
{
category: "Informações Médicas",
question: "Os médicos têm acesso ao meu histórico completo?",
answer:
"Sim, os médicos da plataforma têm acesso ao seu histórico de consultas e exames realizados dentro do sistema para oferecer melhor atendimento.",
},
{
category: "Informações Médicas",
question: "Posso adicionar exames feitos fora da plataforma?",
answer:
"Sim, você pode fazer upload de exames e documentos médicos externos na seção 'Meu Perfil' > 'Documentos Médicos'.",
},
{
category: "Segurança",
question: "Meus dados estão seguros?",
answer:
"Sim, utilizamos criptografia de ponta a ponta e seguimos todos os protocolos da LGPD para proteger seus dados pessoais e médicos.",
},
{
category: "Segurança",
question: "Quem tem acesso às minhas informações?",
answer:
"Apenas você, os médicos que te atendem e profissionais autorizados da clínica têm acesso às suas informações. Nunca compartilhamos seus dados com terceiros sem autorização.",
},
{
category: "Suporte",
question: "Como entro em contato com o suporte?",
answer:
"Você pode entrar em contato através do chat online, telefone (0800-123-4567) ou e-mail (secretaria.mediconnect@gmail.com). Horário de atendimento: Segunda a Sexta, das 8h às 18h.",
},
{
category: "Suporte",
question: "O que fazer em caso de emergência?",
answer:
"Em casos de emergência, procure imediatamente o pronto-socorro mais próximo ou ligue para 192 (SAMU). Nossa plataforma é destinada a consultas agendadas e não substitui o atendimento de emergência.",
},
{
category: "Médicos",
question: "Posso escolher qualquer médico?",
answer:
"Sim, você pode escolher qualquer médico disponível na plataforma. Recomendamos verificar a especialidade, avaliações de outros pacientes e disponibilidade antes de agendar.",
},
{
category: "Médicos",
question: "Como avaliar um médico após a consulta?",
answer:
"Após cada consulta, você receberá um convite por e-mail para avaliar o atendimento. Você também pode avaliar acessando 'Minhas Consultas' e selecionando a consulta realizada.",
},
];
const CentralAjuda: React.FC = () => {
const navigate = useNavigate();
const [searchTerm, setSearchTerm] = useState("");
const [expandedIndex, setExpandedIndex] = useState<number | null>(null);
const [selectedCategory, setSelectedCategory] = useState<string>("Todas");
const categories = [
"Todas",
...Array.from(new Set(faqs.map((faq) => faq.category))),
];
const filteredFaqs = faqs.filter((faq) => {
const matchesSearch =
faq.question.toLowerCase().includes(searchTerm.toLowerCase()) ||
faq.answer.toLowerCase().includes(searchTerm.toLowerCase());
const matchesCategory =
selectedCategory === "Todas" || faq.category === selectedCategory;
return matchesSearch && matchesCategory;
});
const toggleFaq = (index: number) => {
setExpandedIndex(expandedIndex === index ? null : index);
};
return (
<div className="min-h-screen bg-gray-50 dark:bg-gray-900">
{/* Header */}
<div className="bg-gradient-to-br from-blue-600 to-blue-400 dark:from-blue-700 dark:to-blue-500 text-white py-12">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="relative">
<button
onClick={() => navigate("/acompanhamento")}
className="absolute left-0 top-0 flex items-center gap-2 px-4 py-2 bg-white/10 hover:bg-white/20 rounded-lg transition-colors backdrop-blur-sm"
>
<ArrowLeft className="h-5 w-5" />
<span>Voltar ao Painel</span>
</button>
<div className="text-center">
<Headphones className="h-16 w-16 mx-auto mb-4" />
<h1 className="text-4xl font-bold mb-2">Central de Ajuda</h1>
<p className="text-blue-100 text-lg">
Encontre respostas para suas dúvidas rapidamente
</p>
</div>
</div>
</div>
</div>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
{/* Quick Contact Cards */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 -mt-16 mb-8">
<div className="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 hover:shadow-xl transition-shadow">
<div className="flex flex-col items-center text-center">
<div className="h-14 w-14 rounded-full bg-blue-100 dark:bg-blue-900 flex items-center justify-center mb-4">
<MessageCircle className="h-7 w-7 text-blue-600 dark:text-blue-400" />
</div>
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
Chat Online
</h3>
<p className="text-gray-600 dark:text-gray-400 text-sm mb-4">
Fale conosco em tempo real
</p>
<button className="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded-lg transition-colors">
Iniciar Chat
</button>
</div>
</div>
<div className="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 hover:shadow-xl transition-shadow">
<div className="flex flex-col items-center text-center">
<div className="h-14 w-14 rounded-full bg-green-100 dark:bg-green-900 flex items-center justify-center mb-4">
<Phone className="h-7 w-7 text-green-600 dark:text-green-400" />
</div>
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
Telefone
</h3>
<p className="text-gray-600 dark:text-gray-400 text-sm mb-4">
0800-123-4567
</p>
<button className="w-full border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300 py-2 px-4 rounded-lg transition-colors">
Ligar Agora
</button>
</div>
</div>
<div className="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 hover:shadow-xl transition-shadow">
<div className="flex flex-col items-center text-center">
<div className="h-14 w-14 rounded-full bg-purple-100 dark:bg-purple-900 flex items-center justify-center mb-4">
<Mail className="h-7 w-7 text-purple-600 dark:text-purple-400" />
</div>
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
E-mail
</h3>
<p className="text-gray-600 dark:text-gray-400 text-sm mb-4">
secretaria.mediconnect@gmail.com
</p>
<button className="w-full border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300 py-2 px-4 rounded-lg transition-colors">
Enviar E-mail
</button>
</div>
</div>
</div>
{/* Search and Filter */}
<div className="bg-white dark:bg-gray-800 rounded-xl shadow-md p-6 mb-8">
<h2 className="text-2xl font-bold text-gray-900 dark:text-white mb-2">
Perguntas Frequentes
</h2>
<p className="text-gray-600 dark:text-gray-400 mb-6">
Busque por palavras-chave ou navegue pelas categorias
</p>
{/* Search Box */}
<div className="relative mb-6">
<Search className="absolute left-4 top-1/2 -translate-y-1/2 h-5 w-5 text-gray-400" />
<input
type="text"
placeholder="Buscar em perguntas frequentes..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="w-full pl-12 pr-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white"
/>
</div>
{/* Category Filter */}
<div className="flex flex-wrap gap-2">
{categories.map((category) => (
<button
key={category}
onClick={() => setSelectedCategory(category)}
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
selectedCategory === category
? "bg-blue-600 text-white"
: "bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600"
}`}
>
{category}
</button>
))}
</div>
</div>
{/* FAQ Accordion */}
<div className="bg-white dark:bg-gray-800 rounded-xl shadow-md p-6 mb-8">
<div className="space-y-4">
{filteredFaqs.map((faq, index) => (
<div
key={index}
className="border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden"
>
<button
onClick={() => toggleFaq(index)}
className="w-full flex items-center justify-between p-4 text-left hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
>
<div className="flex items-start gap-3 flex-1">
<span className="px-2 py-1 bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-400 text-xs font-medium rounded">
{faq.category}
</span>
<span className="text-gray-900 dark:text-white font-medium">
{faq.question}
</span>
</div>
<ChevronDown
className={`h-5 w-5 text-gray-400 transition-transform flex-shrink-0 ml-4 ${
expandedIndex === index ? "transform rotate-180" : ""
}`}
/>
</button>
{expandedIndex === index && (
<div className="px-4 pb-4 pt-2 bg-gray-50 dark:bg-gray-700/50">
<p className="text-gray-600 dark:text-gray-300 leading-relaxed pl-16">
{faq.answer}
</p>
</div>
)}
</div>
))}
</div>
{filteredFaqs.length === 0 && (
<div className="text-center py-12">
<AlertCircle className="h-12 w-12 text-gray-400 mx-auto mb-3" />
<p className="text-gray-500 dark:text-gray-400 text-lg">
Nenhuma pergunta encontrada para "{searchTerm}"
</p>
<p className="text-gray-400 dark:text-gray-500 text-sm mt-2">
Tente outro termo de busca ou entre em contato conosco
</p>
</div>
)}
</div>
{/* Additional Resources */}
<div className="bg-white dark:bg-gray-800 rounded-xl shadow-md p-6">
<h2 className="text-2xl font-bold text-gray-900 dark:text-white mb-6">
Recursos Adicionais
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<button className="flex items-center gap-4 p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors text-left">
<div className="h-12 w-12 rounded-lg bg-blue-100 dark:bg-blue-900 flex items-center justify-center flex-shrink-0">
<BookOpen className="h-6 w-6 text-blue-600 dark:text-blue-400" />
</div>
<div>
<h3 className="font-semibold text-gray-900 dark:text-white">
Guia do Usuário
</h3>
<p className="text-sm text-gray-600 dark:text-gray-400">
Manual completo da plataforma
</p>
</div>
</button>
<button className="flex items-center gap-4 p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors text-left">
<div className="h-12 w-12 rounded-lg bg-red-100 dark:bg-red-900 flex items-center justify-center flex-shrink-0">
<Video className="h-6 w-6 text-red-600 dark:text-red-400" />
</div>
<div>
<h3 className="font-semibold text-gray-900 dark:text-white">
Vídeos Tutoriais
</h3>
<p className="text-sm text-gray-600 dark:text-gray-400">
Aprenda assistindo
</p>
</div>
</button>
<button className="flex items-center gap-4 p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors text-left">
<div className="h-12 w-12 rounded-lg bg-green-100 dark:bg-green-900 flex items-center justify-center flex-shrink-0">
<FileText className="h-6 w-6 text-green-600 dark:text-green-400" />
</div>
<div>
<h3 className="font-semibold text-gray-900 dark:text-white">
Termos de Uso
</h3>
<p className="text-sm text-gray-600 dark:text-gray-400">
Leia nossos termos
</p>
</div>
</button>
<button className="flex items-center gap-4 p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors text-left">
<div className="h-12 w-12 rounded-lg bg-purple-100 dark:bg-purple-900 flex items-center justify-center flex-shrink-0">
<Shield className="h-6 w-6 text-purple-600 dark:text-purple-400" />
</div>
<div>
<h3 className="font-semibold text-gray-900 dark:text-white">
Política de Privacidade
</h3>
<p className="text-sm text-gray-600 dark:text-gray-400">
Como protegemos seus dados
</p>
</div>
</button>
</div>
</div>
{/* Contact Section */}
<div className="bg-gradient-to-br from-blue-600 to-blue-400 dark:from-blue-700 dark:to-blue-500 rounded-xl shadow-md p-8 mt-8 text-center text-white">
<h2 className="text-2xl font-bold mb-3">Ainda tem dúvidas?</h2>
<p className="text-blue-100 mb-6">
Nossa equipe está pronta para ajudar você
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<button className="bg-white text-blue-600 hover:bg-blue-50 px-6 py-3 rounded-lg font-medium transition-colors">
Falar com Suporte
</button>
<button className="border-2 border-white text-white hover:bg-white/10 px-6 py-3 rounded-lg font-medium transition-colors">
Agendar Retorno de Ligação
</button>
</div>
</div>
</div>
{/* Chatbot */}
<Chatbot />
</div>
);
};
export default CentralAjuda;