develop #83
@ -786,14 +786,14 @@ const ProfissionalPage = () => {
|
|||||||
const todayEvents = getTodayEvents();
|
const todayEvents = getTodayEvents();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="bg-card shadow-md rounded-lg border border-border p-6">
|
<section className="bg-card shadow-md rounded-lg border border-border p-3 sm:p-4 md:p-6 w-full">
|
||||||
<div className="flex justify-between items-center mb-4">
|
<div className="flex justify-between items-center mb-4">
|
||||||
<h2 className="text-2xl font-bold">Agenda do Dia</h2>
|
<h2 className="text-xl sm:text-2xl font-bold">Agenda do Dia</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Navegação de Data */}
|
{/* Navegação de Data - Responsiva */}
|
||||||
<div className="flex items-center justify-between mb-6 p-4 bg-blue-50 rounded-lg dark:bg-muted">
|
<div className="flex items-center justify-between mb-6 p-3 sm:p-4 bg-blue-50 rounded-lg dark:bg-muted flex-wrap gap-2 sm:gap-4">
|
||||||
<div className="flex items-center space-x-4">
|
<div className="flex items-center gap-2 sm:gap-4">
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
@ -802,7 +802,7 @@ const ProfissionalPage = () => {
|
|||||||
>
|
>
|
||||||
<ChevronLeft className="h-4 w-4" />
|
<ChevronLeft className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
<h3 className="text-lg font-medium text-foreground">
|
<h3 className="text-base sm:text-lg font-medium text-foreground whitespace-nowrap line-clamp-2">
|
||||||
{formatDate(currentCalendarDate)}
|
{formatDate(currentCalendarDate)}
|
||||||
</h3>
|
</h3>
|
||||||
<Button
|
<Button
|
||||||
@ -813,20 +813,19 @@ const ProfissionalPage = () => {
|
|||||||
>
|
>
|
||||||
<ChevronRight className="h-4 w-4" />
|
<ChevronRight className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm text-gray-600 dark:text-muted-foreground">
|
<div className="text-xs sm:text-sm text-gray-600 dark:text-muted-foreground whitespace-nowrap">
|
||||||
{todayEvents.length} consulta{todayEvents.length !== 1 ? 's' : ''} agendada{todayEvents.length !== 1 ? 's' : ''}
|
{todayEvents.length} consulta{todayEvents.length !== 1 ? 's' : ''}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Lista de Pacientes do Dia */}
|
{/* Lista de Pacientes do Dia - Responsiva */}
|
||||||
<div className="space-y-4 max-h-[calc(100vh-450px)] overflow-y-auto pr-2">
|
<div className="space-y-3 sm:space-y-4 max-h-[calc(100vh-450px)] overflow-y-auto pr-2">
|
||||||
{todayEvents.length === 0 ? (
|
{todayEvents.length === 0 ? (
|
||||||
<div className="text-center py-8 text-gray-600 dark:text-muted-foreground">
|
<div className="text-center py-6 sm:py-8 text-gray-600 dark:text-muted-foreground">
|
||||||
<CalendarIcon className="h-12 w-12 mx-auto mb-4 text-gray-400 dark:text-muted-foreground/50" />
|
<CalendarIcon className="h-10 sm:h-12 w-10 sm:w-12 mx-auto mb-3 sm:mb-4 text-gray-400 dark:text-muted-foreground/50" />
|
||||||
<p className="text-lg mb-2">Nenhuma consulta agendada para este dia</p>
|
<p className="text-base sm:text-lg mb-2">Nenhuma consulta agendada para este dia</p>
|
||||||
<p className="text-sm">Agenda livre para este dia</p>
|
<p className="text-xs sm:text-sm">Agenda livre para este dia</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
todayEvents.map((appointment) => {
|
todayEvents.map((appointment) => {
|
||||||
@ -834,47 +833,46 @@ const ProfissionalPage = () => {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={appointment.id}
|
key={appointment.id}
|
||||||
className="border-l-4 border-t border-r border-b p-4 rounded-lg shadow-sm bg-card border-border"
|
className="border-l-4 border-t border-r border-b p-3 sm:p-4 rounded-lg shadow-sm bg-card border-border"
|
||||||
style={{ borderLeftColor: getStatusColor(appointment.type) }}
|
style={{ borderLeftColor: getStatusColor(appointment.type) }}
|
||||||
>
|
>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4 items-center">
|
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-2 sm:gap-4 items-center">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center gap-2">
|
||||||
<div
|
<div
|
||||||
className="w-3 h-3 rounded-full mr-3"
|
className="w-3 h-3 rounded-full flex-shrink-0"
|
||||||
style={{ backgroundColor: getStatusColor(appointment.type) }}
|
style={{ backgroundColor: getStatusColor(appointment.type) }}
|
||||||
></div>
|
></div>
|
||||||
<div>
|
<div className="min-w-0">
|
||||||
<div className="font-medium flex items-center">
|
<div className="font-medium text-sm sm:text-base flex items-center gap-2">
|
||||||
<User className="h-4 w-4 mr-2 text-gray-500 dark:text-muted-foreground" />
|
<User className="h-3 w-3 sm:h-4 sm:w-4 text-gray-500 dark:text-muted-foreground flex-shrink-0" />
|
||||||
{appointment.title}
|
<span className="truncate">{appointment.title}</span>
|
||||||
</div>
|
</div>
|
||||||
{paciente && (
|
{paciente && (
|
||||||
<div className="text-sm text-gray-600 dark:text-muted-foreground">
|
<div className="text-xs text-gray-600 dark:text-muted-foreground truncate">
|
||||||
CPF: {getPatientCpf(paciente)} • {getPatientAge(paciente)} anos
|
CPF: {getPatientCpf(paciente)} • {getPatientAge(paciente)} anos
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center gap-2">
|
||||||
<Clock className="h-4 w-4 mr-2 text-gray-500 dark:text-muted-foreground" />
|
<Clock className="h-3 w-3 sm:h-4 sm:w-4 text-gray-500 dark:text-muted-foreground flex-shrink-0" />
|
||||||
<span className="font-medium">{appointment.time}</span>
|
<span className="font-medium text-sm sm:text-base">{appointment.time}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div
|
<div
|
||||||
className="px-3 py-1 rounded-full text-sm font-medium text-white"
|
className="px-2 sm:px-3 py-1 rounded-full text-xs sm:text-sm font-medium text-white whitespace-nowrap"
|
||||||
style={{ backgroundColor: getStatusColor(appointment.type) }}
|
style={{ backgroundColor: getStatusColor(appointment.type) }}
|
||||||
>
|
>
|
||||||
{appointment.type}
|
{appointment.type}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-end space-x-2">
|
<div className="flex items-center justify-end">
|
||||||
<div className="relative group">
|
<div className="relative group">
|
||||||
<div className="absolute bottom-full left-1/2 transform -translate-x-1/2 mb-2 px-3 py-1 bg-gray-900 dark:bg-gray-100 text-white dark:text-gray-900 text-xs rounded-md opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none whitespace-nowrap z-50">
|
<div className="absolute bottom-full left-1/2 transform -translate-x-1/2 mb-2 px-3 py-1 bg-gray-900 dark:bg-gray-100 text-white dark:text-gray-900 text-xs rounded-md opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none whitespace-nowrap z-50">
|
||||||
Ver informações do paciente
|
Ver informações do paciente
|
||||||
<div className="absolute top-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-l-4 border-r-4 border-t-4 border-transparent border-t-gray-900 dark:border-t-gray-100"></div>
|
<div className="absolute top-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-l-4 border-r-4 border-t-4 border-transparent border-t-gray-900 dark:border-t-gray-100"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -2691,20 +2689,17 @@ const ProfissionalPage = () => {
|
|||||||
|
|
||||||
|
|
||||||
const renderComunicacaoSection = () => (
|
const renderComunicacaoSection = () => (
|
||||||
<div className="bg-card shadow-md rounded-lg p-6">
|
<div className="bg-card shadow-md rounded-lg border border-border p-3 sm:p-4 md:p-6 w-full">
|
||||||
<h2 className="text-2xl font-bold mb-4 text-foreground">Comunicação com o Paciente</h2>
|
<h2 className="text-xl sm:text-2xl font-bold mb-4">Comunicação com o Paciente</h2>
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div className="grid grid-cols-1 gap-4">
|
<div className="grid grid-cols-1 gap-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="patientSelect">Paciente *</Label>
|
<Label htmlFor="patientSelect" className="text-xs sm:text-sm">Paciente *</Label>
|
||||||
<Select
|
<Select
|
||||||
value={commPatientId ?? ''}
|
value={commPatientId ?? ''}
|
||||||
onValueChange={(val: string) => {
|
onValueChange={(val: string) => {
|
||||||
// Radix Select does not allow an Item with empty string as value.
|
|
||||||
// Use a sentinel value "__none" for the "-- nenhum --" choice and map it to null here.
|
|
||||||
const v = val === "__none" ? null : (val || null);
|
const v = val === "__none" ? null : (val || null);
|
||||||
setCommPatientId(v);
|
setCommPatientId(v);
|
||||||
// clear previous responses when changing selection
|
|
||||||
setCommResponses([]);
|
setCommResponses([]);
|
||||||
setCommResponsesError(null);
|
setCommResponsesError(null);
|
||||||
if (!v) {
|
if (!v) {
|
||||||
@ -2724,11 +2719,10 @@ const ProfissionalPage = () => {
|
|||||||
console.warn('[ProfissionalPage] erro ao preencher telefone do paciente selecionado', e);
|
console.warn('[ProfissionalPage] erro ao preencher telefone do paciente selecionado', e);
|
||||||
setCommPhoneNumber('');
|
setCommPhoneNumber('');
|
||||||
}
|
}
|
||||||
// carregar respostas do paciente selecionado
|
|
||||||
void loadCommResponses(String(v));
|
void loadCommResponses(String(v));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-full">
|
<SelectTrigger className="w-full text-xs sm:text-sm">
|
||||||
<SelectValue placeholder="-- nenhum --" />
|
<SelectValue placeholder="-- nenhum --" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@ -2743,47 +2737,47 @@ const ProfissionalPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="phoneNumber">Número (phone_number)</Label>
|
<Label htmlFor="phoneNumber" className="text-xs sm:text-sm">Número (phone_number)</Label>
|
||||||
<Input id="phoneNumber" placeholder="+5511999999999" value={commPhoneNumber} readOnly disabled className="bg-muted/50" />
|
<Input id="phoneNumber" placeholder="+5511999999999" value={commPhoneNumber} readOnly disabled className="bg-muted/50 text-xs sm:text-sm" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="message">Mensagem (message)</Label>
|
<Label htmlFor="message" className="text-xs sm:text-sm">Mensagem (message)</Label>
|
||||||
<textarea id="message" className="w-full p-2 border rounded" rows={5} value={commMessage} onChange={(e) => setCommMessage(e.target.value)} />
|
<textarea id="message" className="w-full p-2 sm:p-3 border rounded text-xs sm:text-sm" rows={5} value={commMessage} onChange={(e) => setCommMessage(e.target.value)} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-end mt-6">
|
<div className="flex justify-end mt-6">
|
||||||
<Button onClick={handleSave} disabled={smsSending}>
|
<Button onClick={handleSave} disabled={smsSending} size="sm" className="text-xs sm:text-sm">
|
||||||
{smsSending ? 'Enviando...' : 'Enviar SMS'}
|
{smsSending ? 'Enviando...' : 'Enviar SMS'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Respostas do paciente */}
|
{/* Respostas do paciente */}
|
||||||
<div className="mt-6 border-t border-border pt-4">
|
<div className="mt-6 border-t border-border pt-4">
|
||||||
<div className="flex items-center justify-between mb-3">
|
<div className="flex items-center justify-between mb-3 flex-wrap gap-2">
|
||||||
<h3 className="text-lg font-semibold">Últimas respostas do paciente</h3>
|
<h3 className="text-base sm:text-lg font-semibold">Últimas respostas do paciente</h3>
|
||||||
<div>
|
<div>
|
||||||
<Button size="sm" variant="outline" onClick={() => void loadCommResponses()} disabled={!commPatientId || commResponsesLoading}>
|
<Button size="sm" variant="outline" onClick={() => void loadCommResponses()} disabled={!commPatientId || commResponsesLoading} className="text-xs sm:text-sm">
|
||||||
{commResponsesLoading ? 'Atualizando...' : 'Atualizar respostas'}
|
{commResponsesLoading ? 'Atualizando...' : 'Atualizar respostas'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{commResponsesLoading ? (
|
{commResponsesLoading ? (
|
||||||
<div className="text-sm text-muted-foreground">Carregando respostas...</div>
|
<div className="text-xs sm:text-sm text-muted-foreground">Carregando respostas...</div>
|
||||||
) : commResponsesError ? (
|
) : commResponsesError ? (
|
||||||
<div className="text-sm text-red-500">{commResponsesError}</div>
|
<div className="text-xs sm:text-sm text-red-500">{commResponsesError}</div>
|
||||||
) : (commResponses && commResponses.length) ? (
|
) : (commResponses && commResponses.length) ? (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{commResponses.map((m:any) => (
|
{commResponses.map((m:any) => (
|
||||||
<div key={m.id} className="p-3 rounded border border-border bg-muted/10">
|
<div key={m.id} className="p-3 rounded border border-border bg-muted/10">
|
||||||
<div className="text-xs text-muted-foreground">{m.created_at ? new Date(m.created_at).toLocaleString() : ''}</div>
|
<div className="text-xs text-muted-foreground">{m.created_at ? new Date(m.created_at).toLocaleString() : ''}</div>
|
||||||
<div className="mt-1 whitespace-pre-wrap">{m.body ?? m.content ?? m.message ?? '-'}</div>
|
<div className="mt-1 whitespace-pre-wrap text-xs sm:text-sm">{m.body ?? m.content ?? m.message ?? '-'}</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-sm text-muted-foreground">Nenhuma resposta encontrada para o paciente selecionado.</div>
|
<div className="text-xs sm:text-sm text-muted-foreground">Nenhuma resposta encontrada para o paciente selecionado.</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -2793,24 +2787,24 @@ const ProfissionalPage = () => {
|
|||||||
|
|
||||||
|
|
||||||
const renderPerfilSection = () => (
|
const renderPerfilSection = () => (
|
||||||
<div className="mx-auto flex w-full max-w-6xl flex-col gap-6 px-4 py-10 md:px-8">
|
<div className="mx-auto flex w-full max-w-6xl flex-col gap-4 sm:gap-6 px-0 py-4 sm:py-8 md:px-4">
|
||||||
{/* Header com Título e Botão */}
|
{/* Header com Título e Botão */}
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-3xl font-bold">Meu Perfil</h2>
|
<h2 className="text-2xl sm:text-3xl font-bold">Meu Perfil</h2>
|
||||||
<p className="text-muted-foreground mt-1">Bem-vindo à sua área exclusiva.</p>
|
<p className="text-xs sm:text-sm text-muted-foreground mt-1">Bem-vindo à sua área exclusiva.</p>
|
||||||
</div>
|
</div>
|
||||||
{!isEditingProfile ? (
|
{!isEditingProfile ? (
|
||||||
<Button
|
<Button
|
||||||
className="bg-blue-600 hover:bg-blue-700"
|
className="bg-blue-600 hover:bg-blue-700 text-xs sm:text-sm w-full sm:w-auto"
|
||||||
onClick={() => setIsEditingProfile(true)}
|
onClick={() => setIsEditingProfile(true)}
|
||||||
>
|
>
|
||||||
✏️ Editar Perfil
|
✏️ Editar Perfil
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2 w-full sm:w-auto">
|
||||||
<Button
|
<Button
|
||||||
className="bg-green-600 hover:bg-green-700"
|
className="bg-green-600 hover:bg-green-700 flex-1 sm:flex-initial text-xs sm:text-sm"
|
||||||
onClick={handleSaveProfile}
|
onClick={handleSaveProfile}
|
||||||
>
|
>
|
||||||
✓ Salvar
|
✓ Salvar
|
||||||
@ -2818,6 +2812,7 @@ const ProfissionalPage = () => {
|
|||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={handleCancelEdit}
|
onClick={handleCancelEdit}
|
||||||
|
className="flex-1 sm:flex-initial text-xs sm:text-sm"
|
||||||
>
|
>
|
||||||
✕ Cancelar
|
✕ Cancelar
|
||||||
</Button>
|
</Button>
|
||||||
@ -2825,21 +2820,21 @@ const ProfissionalPage = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Grid de 3 colunas (2 + 1) */}
|
{/* Grid de 3 colunas (2 + 1) - Responsivo */}
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 sm:gap-6">
|
||||||
{/* Coluna Esquerda - Informações Pessoais */}
|
{/* Coluna Esquerda - Informações Pessoais */}
|
||||||
<div className="lg:col-span-2 space-y-6">
|
<div className="lg:col-span-2 space-y-4 sm:space-y-6">
|
||||||
{/* Informações Pessoais */}
|
{/* Informações Pessoais */}
|
||||||
<div className="border border-border rounded-lg p-6">
|
<div className="border border-border rounded-lg p-4 sm:p-6">
|
||||||
<h3 className="text-lg font-semibold mb-4">Informações Pessoais</h3>
|
<h3 className="text-base sm:text-lg font-semibold mb-4">Informações Pessoais</h3>
|
||||||
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{/* Nome Completo */}
|
{/* Nome Completo */}
|
||||||
<div>
|
<div>
|
||||||
<Label className="text-sm font-medium text-muted-foreground">
|
<Label className="text-xs sm:text-sm font-medium text-muted-foreground">
|
||||||
Nome Completo
|
Nome Completo
|
||||||
</Label>
|
</Label>
|
||||||
<div className="mt-2 p-3 bg-muted rounded text-foreground font-medium">
|
<div className="mt-2 p-3 bg-muted rounded text-xs sm:text-sm text-foreground font-medium">
|
||||||
{profileData.nome || "Não preenchido"}
|
{profileData.nome || "Não preenchido"}
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-muted-foreground mt-1">
|
<p className="text-xs text-muted-foreground mt-1">
|
||||||
@ -2849,18 +2844,18 @@ const ProfissionalPage = () => {
|
|||||||
|
|
||||||
{/* Email */}
|
{/* Email */}
|
||||||
<div>
|
<div>
|
||||||
<Label className="text-sm font-medium text-muted-foreground">
|
<Label className="text-xs sm:text-sm font-medium text-muted-foreground">
|
||||||
Email
|
Email
|
||||||
</Label>
|
</Label>
|
||||||
{isEditingProfile ? (
|
{isEditingProfile ? (
|
||||||
<Input
|
<Input
|
||||||
value={profileData.email || ""}
|
value={profileData.email || ""}
|
||||||
onChange={(e) => handleProfileChange('email', e.target.value)}
|
onChange={(e) => handleProfileChange('email', e.target.value)}
|
||||||
className="mt-2"
|
className="mt-2 text-xs sm:text-sm"
|
||||||
type="email"
|
type="email"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="mt-2 p-3 bg-muted rounded text-foreground">
|
<div className="mt-2 p-3 bg-muted rounded text-xs sm:text-sm text-foreground">
|
||||||
{profileData.email || "Não preenchido"}
|
{profileData.email || "Não preenchido"}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -2868,18 +2863,18 @@ const ProfissionalPage = () => {
|
|||||||
|
|
||||||
{/* Telefone */}
|
{/* Telefone */}
|
||||||
<div>
|
<div>
|
||||||
<Label className="text-sm font-medium text-muted-foreground">
|
<Label className="text-xs sm:text-sm font-medium text-muted-foreground">
|
||||||
Telefone
|
Telefone
|
||||||
</Label>
|
</Label>
|
||||||
{isEditingProfile ? (
|
{isEditingProfile ? (
|
||||||
<Input
|
<Input
|
||||||
value={profileData.telefone || ""}
|
value={profileData.telefone || ""}
|
||||||
onChange={(e) => handleProfileChange('telefone', e.target.value)}
|
onChange={(e) => handleProfileChange('telefone', e.target.value)}
|
||||||
className="mt-2"
|
className="mt-2 text-xs sm:text-sm"
|
||||||
placeholder="(00) 00000-0000"
|
placeholder="(00) 00000-0000"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="mt-2 p-3 bg-muted rounded text-foreground">
|
<div className="mt-2 p-3 bg-muted rounded text-xs sm:text-sm text-foreground">
|
||||||
{profileData.telefone || "Não preenchido"}
|
{profileData.telefone || "Não preenchido"}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -2887,10 +2882,10 @@ const ProfissionalPage = () => {
|
|||||||
|
|
||||||
{/* CRM */}
|
{/* CRM */}
|
||||||
<div>
|
<div>
|
||||||
<Label className="text-sm font-medium text-muted-foreground">
|
<Label className="text-xs sm:text-sm font-medium text-muted-foreground">
|
||||||
CRM
|
CRM
|
||||||
</Label>
|
</Label>
|
||||||
<div className="mt-2 p-3 bg-muted rounded text-foreground font-medium">
|
<div className="mt-2 p-3 bg-muted rounded text-xs sm:text-sm text-foreground font-medium">
|
||||||
{profileData.crm || "Não preenchido"}
|
{profileData.crm || "Não preenchido"}
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-muted-foreground mt-1">
|
<p className="text-xs text-muted-foreground mt-1">
|
||||||
@ -2900,18 +2895,18 @@ const ProfissionalPage = () => {
|
|||||||
|
|
||||||
{/* Especialidade */}
|
{/* Especialidade */}
|
||||||
<div>
|
<div>
|
||||||
<Label className="text-sm font-medium text-muted-foreground">
|
<Label className="text-xs sm:text-sm font-medium text-muted-foreground">
|
||||||
Especialidade
|
Especialidade
|
||||||
</Label>
|
</Label>
|
||||||
{isEditingProfile ? (
|
{isEditingProfile ? (
|
||||||
<Input
|
<Input
|
||||||
value={profileData.especialidade || ""}
|
value={profileData.especialidade || ""}
|
||||||
onChange={(e) => handleProfileChange('especialidade', e.target.value)}
|
onChange={(e) => handleProfileChange('especialidade', e.target.value)}
|
||||||
className="mt-2"
|
className="mt-2 text-xs sm:text-sm"
|
||||||
placeholder="Ex: Cardiologia"
|
placeholder="Ex: Cardiologia"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="mt-2 p-3 bg-muted rounded text-foreground">
|
<div className="mt-2 p-3 bg-muted rounded text-xs sm:text-sm text-foreground">
|
||||||
{profileData.especialidade || "Não preenchido"}
|
{profileData.especialidade || "Não preenchido"}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -2920,24 +2915,24 @@ const ProfissionalPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Endereço e Contato */}
|
{/* Endereço e Contato */}
|
||||||
<div className="border border-border rounded-lg p-6">
|
<div className="border border-border rounded-lg p-4 sm:p-6">
|
||||||
<h3 className="text-lg font-semibold mb-4">Endereço e Contato</h3>
|
<h3 className="text-base sm:text-lg font-semibold mb-4">Endereço e Contato</h3>
|
||||||
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{/* Logradouro */}
|
{/* Logradouro */}
|
||||||
<div>
|
<div>
|
||||||
<Label className="text-sm font-medium text-muted-foreground">
|
<Label className="text-xs sm:text-sm font-medium text-muted-foreground">
|
||||||
Logradouro
|
Logradouro
|
||||||
</Label>
|
</Label>
|
||||||
{isEditingProfile ? (
|
{isEditingProfile ? (
|
||||||
<Input
|
<Input
|
||||||
value={profileData.endereco || ""}
|
value={profileData.endereco || ""}
|
||||||
onChange={(e) => handleProfileChange('endereco', e.target.value)}
|
onChange={(e) => handleProfileChange('endereco', e.target.value)}
|
||||||
className="mt-2"
|
className="mt-2 text-xs sm:text-sm"
|
||||||
placeholder="Rua, avenida, etc."
|
placeholder="Rua, avenida, etc."
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="mt-2 p-3 bg-muted rounded text-foreground">
|
<div className="mt-2 p-3 bg-muted rounded text-xs sm:text-sm text-foreground">
|
||||||
{profileData.endereco || "Não preenchido"}
|
{profileData.endereco || "Não preenchido"}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -2945,18 +2940,18 @@ const ProfissionalPage = () => {
|
|||||||
|
|
||||||
{/* Cidade */}
|
{/* Cidade */}
|
||||||
<div>
|
<div>
|
||||||
<Label className="text-sm font-medium text-muted-foreground">
|
<Label className="text-xs sm:text-sm font-medium text-muted-foreground">
|
||||||
Cidade
|
Cidade
|
||||||
</Label>
|
</Label>
|
||||||
{isEditingProfile ? (
|
{isEditingProfile ? (
|
||||||
<Input
|
<Input
|
||||||
value={profileData.cidade || ""}
|
value={profileData.cidade || ""}
|
||||||
onChange={(e) => handleProfileChange('cidade', e.target.value)}
|
onChange={(e) => handleProfileChange('cidade', e.target.value)}
|
||||||
className="mt-2"
|
className="mt-2 text-xs sm:text-sm"
|
||||||
placeholder="São Paulo"
|
placeholder="São Paulo"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="mt-2 p-3 bg-muted rounded text-foreground">
|
<div className="mt-2 p-3 bg-muted rounded text-xs sm:text-sm text-foreground">
|
||||||
{profileData.cidade || "Não preenchido"}
|
{profileData.cidade || "Não preenchido"}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -2964,18 +2959,18 @@ const ProfissionalPage = () => {
|
|||||||
|
|
||||||
{/* CEP */}
|
{/* CEP */}
|
||||||
<div>
|
<div>
|
||||||
<Label className="text-sm font-medium text-muted-foreground">
|
<Label className="text-xs sm:text-sm font-medium text-muted-foreground">
|
||||||
CEP
|
CEP
|
||||||
</Label>
|
</Label>
|
||||||
{isEditingProfile ? (
|
{isEditingProfile ? (
|
||||||
<Input
|
<Input
|
||||||
value={profileData.cep || ""}
|
value={profileData.cep || ""}
|
||||||
onChange={(e) => handleProfileChange('cep', e.target.value)}
|
onChange={(e) => handleProfileChange('cep', e.target.value)}
|
||||||
className="mt-2"
|
className="mt-2 text-xs sm:text-sm"
|
||||||
placeholder="00000-000"
|
placeholder="00000-000"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="mt-2 p-3 bg-muted rounded text-foreground">
|
<div className="mt-2 p-3 bg-muted rounded text-xs sm:text-sm text-foreground">
|
||||||
{profileData.cep || "Não preenchido"}
|
{profileData.cep || "Não preenchido"}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -2986,18 +2981,18 @@ const ProfissionalPage = () => {
|
|||||||
|
|
||||||
{/* Coluna Direita - Foto do Perfil */}
|
{/* Coluna Direita - Foto do Perfil */}
|
||||||
<div>
|
<div>
|
||||||
<div className="border border-border rounded-lg p-6">
|
<div className="border border-border rounded-lg p-4 sm:p-6">
|
||||||
<h3 className="text-lg font-semibold mb-4">Foto do Perfil</h3>
|
<h3 className="text-base sm:text-lg font-semibold mb-4">Foto do Perfil</h3>
|
||||||
|
|
||||||
<div className="flex flex-col items-center gap-4">
|
<div className="flex flex-col items-center gap-4">
|
||||||
<Avatar className="h-24 w-24">
|
<Avatar className="h-20 w-20 sm:h-24 sm:w-24">
|
||||||
<AvatarFallback className="bg-primary text-primary-foreground text-2xl font-bold">
|
<AvatarFallback className="bg-primary text-primary-foreground text-lg sm:text-2xl font-bold">
|
||||||
{profileData.nome?.split(' ').map((n: string) => n[0]).join('').toUpperCase().slice(0, 2) || 'MD'}
|
{profileData.nome?.split(' ').map((n: string) => n[0]).join('').toUpperCase().slice(0, 2) || 'MD'}
|
||||||
</AvatarFallback>
|
</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
|
|
||||||
<div className="text-center space-y-2">
|
<div className="text-center space-y-2">
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-xs sm:text-sm text-muted-foreground">
|
||||||
{profileData.nome?.split(' ').map((n: string) => n[0]).join('').toUpperCase().slice(0, 2) || 'MD'}
|
{profileData.nome?.split(' ').map((n: string) => n[0]).join('').toUpperCase().slice(0, 2) || 'MD'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@ -3015,23 +3010,23 @@ const ProfissionalPage = () => {
|
|||||||
return renderCalendarioSection();
|
return renderCalendarioSection();
|
||||||
case 'pacientes':
|
case 'pacientes':
|
||||||
return (
|
return (
|
||||||
<section className="bg-card shadow-md rounded-lg border border-border p-6">
|
<section className="bg-card shadow-md rounded-lg border border-border p-3 sm:p-4 md:p-6 w-full">
|
||||||
<h2 className="text-2xl font-bold mb-4">Pacientes</h2>
|
<h2 className="text-xl sm:text-2xl font-bold mb-4">Pacientes</h2>
|
||||||
<div className="overflow-x-auto">
|
<div className="overflow-x-auto w-full">
|
||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead>Nome</TableHead>
|
<TableHead className="text-xs sm:text-sm">Nome</TableHead>
|
||||||
<TableHead>CPF</TableHead>
|
<TableHead className="text-xs sm:text-sm">CPF</TableHead>
|
||||||
<TableHead>Idade</TableHead>
|
<TableHead className="text-xs sm:text-sm">Idade</TableHead>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{pacientes.map((paciente) => (
|
{pacientes.map((paciente) => (
|
||||||
<TableRow key={paciente.id ?? paciente.cpf}>
|
<TableRow key={paciente.id ?? paciente.cpf}>
|
||||||
<TableCell>{paciente.nome}</TableCell>
|
<TableCell className="text-xs sm:text-sm">{paciente.nome}</TableCell>
|
||||||
<TableCell>{paciente.cpf}</TableCell>
|
<TableCell className="text-xs sm:text-sm">{paciente.cpf}</TableCell>
|
||||||
<TableCell>{getPatientAge(paciente) ? `${getPatientAge(paciente)} anos` : '-'}</TableCell>
|
<TableCell className="text-xs sm:text-sm">{getPatientAge(paciente) ? `${getPatientAge(paciente)} anos` : '-'}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
@ -3050,81 +3045,139 @@ const ProfissionalPage = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ProtectedRoute requiredUserType={["profissional"]}>
|
<ProtectedRoute requiredUserType={["profissional"]}>
|
||||||
<div className="container mx-auto px-4 py-8">
|
<div className="flex flex-col min-h-screen">
|
||||||
<header className="bg-card shadow-md rounded-lg border border-border p-4 mb-6 flex items-center justify-between">
|
{/* Header - Responsivo */}
|
||||||
<div className="flex items-center gap-4">
|
<header className="bg-card shadow-md border-b border-border sticky top-0 z-40">
|
||||||
<Avatar className="h-12 w-12">
|
<div className="px-4 py-3 md:px-6">
|
||||||
|
<div className="flex items-center justify-between gap-4 flex-wrap md:flex-nowrap">
|
||||||
|
{/* Logo/Avatar Section */}
|
||||||
|
<div className="flex items-center gap-3 min-w-0 flex-1 md:flex-none">
|
||||||
|
<Avatar className="h-10 w-10 md:h-12 md:w-12 flex-shrink-0">
|
||||||
<AvatarImage src={(profileData as any).fotoUrl || undefined} alt={profileData.nome} />
|
<AvatarImage src={(profileData as any).fotoUrl || undefined} alt={profileData.nome} />
|
||||||
<AvatarFallback className="bg-muted">
|
<AvatarFallback className="bg-muted text-xs md:text-sm">
|
||||||
<User className="h-5 w-5" />
|
<User className="h-4 w-4 md:h-5 md:w-5" />
|
||||||
</AvatarFallback>
|
</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<p className="text-sm text-muted-foreground truncate">Conta do profissional</p>
|
<p className="text-xs md:text-sm text-muted-foreground truncate">Profissional de Saúde</p>
|
||||||
<h2 className="text-lg font-semibold leading-none truncate">{profileData.nome}</h2>
|
<h2 className="text-sm md:text-base font-semibold leading-none truncate">{profileData.nome}</h2>
|
||||||
<p className="text-sm text-muted-foreground truncate">{(profileData.crm ? `CRM: ${profileData.crm}` : '') + (profileData.especialidade ? ` • ${profileData.especialidade}` : '')}</p>
|
<p className="text-xs text-muted-foreground truncate line-clamp-1">{(profileData.crm ? `CRM: ${profileData.crm}` : '') + (profileData.especialidade ? ` • ${profileData.especialidade}` : '')}</p>
|
||||||
{user?.email && (
|
|
||||||
<p className="text-xs text-muted-foreground truncate">Logado como: {user.email}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
|
{/* Actions - Mobile hidden on small screens */}
|
||||||
|
<div className="flex items-center gap-1 md:gap-2 flex-shrink-0">
|
||||||
<SimpleThemeToggle />
|
<SimpleThemeToggle />
|
||||||
<Button asChild variant="default" className="mr-2 bg-primary hover:bg-primary/90 text-primary-foreground px-3 py-1 rounded shadow-sm shadow-blue-500/10 border border-primary">
|
|
||||||
|
{/* Desktop Buttons - Hidden on mobile */}
|
||||||
|
<div className="hidden sm:flex items-center gap-1 md:gap-2">
|
||||||
|
<Button asChild variant="default" size="sm" className="bg-primary hover:bg-primary/90 text-primary-foreground rounded shadow-sm shadow-blue-500/10 border border-primary text-xs md:text-sm px-2 md:px-4 h-8 md:h-9">
|
||||||
<Link href="/" aria-label="Início">Início</Link>
|
<Link href="/" aria-label="Início">Início</Link>
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={logout}
|
onClick={logout}
|
||||||
className="text-red-600 border-red-600 hover:bg-red-50 cursor-pointer dark:hover:bg-red-600 dark:hover:text-white"
|
size="sm"
|
||||||
|
className="text-red-600 border-red-600 hover:bg-red-50 cursor-pointer dark:hover:bg-red-600 dark:hover:text-white text-xs md:text-sm px-2 md:px-4 h-8 md:h-9"
|
||||||
>
|
>
|
||||||
Sair
|
Sair
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile Menu Button */}
|
||||||
|
<button
|
||||||
|
onClick={() => setSidebarOpen(!sidebarOpen)}
|
||||||
|
className="md:hidden p-2 hover:bg-muted rounded transition-colors flex-shrink-0"
|
||||||
|
aria-label="Menu"
|
||||||
|
>
|
||||||
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d={sidebarOpen ? "M6 18L18 6M6 6l12 12" : "M4 6h16M4 12h16M4 18h16"} />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile menu items - visible when sidebarOpen */}
|
||||||
|
{sidebarOpen && (
|
||||||
|
<div className="md:hidden flex flex-col gap-2 mt-3 pt-3 border-t border-border">
|
||||||
|
<Button asChild variant="default" size="sm" className="w-full bg-primary hover:bg-primary/90 text-primary-foreground">
|
||||||
|
<Link href="/">Início</Link>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={logout}
|
||||||
|
size="sm"
|
||||||
|
className="w-full text-red-600 border-red-600 hover:bg-red-50 dark:hover:bg-red-600 dark:hover:text-white"
|
||||||
|
>
|
||||||
|
Sair
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-[220px_1fr] gap-6">
|
<div className="flex-1 flex flex-col md:flex-row gap-0 md:gap-6 px-3 sm:px-4 md:px-8 py-4 md:py-8">
|
||||||
{}
|
{/* Sidebar - Mobile Drawer or Desktop */}
|
||||||
<aside className="md:sticky md:top-8 h-fit">
|
<aside className={`${
|
||||||
<nav className="bg-card shadow-md rounded-lg border border-border p-3 space-y-1">
|
sidebarOpen ? 'block' : 'hidden md:block'
|
||||||
|
} md:sticky md:top-24 md:h-fit w-full md:w-[220px] mb-4 md:mb-0`}>
|
||||||
|
<nav className="bg-card shadow-md rounded-lg border border-border p-2 md:p-3 space-y-1">
|
||||||
<Button
|
<Button
|
||||||
variant={activeSection === 'calendario' ? 'default' : 'ghost'}
|
variant={activeSection === 'calendario' ? 'default' : 'ghost'}
|
||||||
className="w-full justify-start transition-colors hover:bg-primary! hover:text-white! cursor-pointer"
|
className="w-full justify-start text-sm md:text-base transition-colors hover:bg-primary! hover:text-white! cursor-pointer"
|
||||||
onClick={() => setActiveSection('calendario')}
|
onClick={() => {
|
||||||
|
setActiveSection('calendario');
|
||||||
|
setSidebarOpen(false);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<CalendarIcon className="mr-2 h-4 w-4" />
|
<CalendarIcon className="mr-2 h-4 w-4" />
|
||||||
Calendário
|
<span className="hidden sm:inline">Calendário</span>
|
||||||
|
<span className="sm:hidden">Calendário</span>
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant={activeSection === 'pacientes' ? 'default' : 'ghost'}
|
variant={activeSection === 'pacientes' ? 'default' : 'ghost'}
|
||||||
className="w-full justify-start transition-colors hover:bg-primary! hover:text-white! cursor-pointer"
|
className="w-full justify-start text-sm md:text-base transition-colors hover:bg-primary! hover:text-white! cursor-pointer"
|
||||||
onClick={() => setActiveSection('pacientes')}
|
onClick={() => {
|
||||||
|
setActiveSection('pacientes');
|
||||||
|
setSidebarOpen(false);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Users className="mr-2 h-4 w-4" />
|
<Users className="mr-2 h-4 w-4" />
|
||||||
Pacientes
|
Pacientes
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant={activeSection === 'laudos' ? 'default' : 'ghost'}
|
variant={activeSection === 'laudos' ? 'default' : 'ghost'}
|
||||||
className="w-full justify-start transition-colors hover:bg-primary! hover:text-white! cursor-pointer"
|
className="w-full justify-start text-sm md:text-base transition-colors hover:bg-primary! hover:text-white! cursor-pointer"
|
||||||
onClick={() => setActiveSection('laudos')}
|
onClick={() => {
|
||||||
|
setActiveSection('laudos');
|
||||||
|
setSidebarOpen(false);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<FileText className="mr-2 h-4 w-4" />
|
<FileText className="mr-2 h-4 w-4" />
|
||||||
Laudos
|
Laudos
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant={activeSection === 'comunicacao' ? 'default' : 'ghost'}
|
variant={activeSection === 'comunicacao' ? 'default' : 'ghost'}
|
||||||
className="w-full justify-start transition-colors hover:bg-primary! hover:text-white! cursor-pointer"
|
className="w-full justify-start text-sm md:text-base transition-colors hover:bg-primary! hover:text-white! cursor-pointer"
|
||||||
onClick={() => setActiveSection('comunicacao')}
|
onClick={() => {
|
||||||
|
setActiveSection('comunicacao');
|
||||||
|
setSidebarOpen(false);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<MessageSquare className="mr-2 h-4 w-4" />
|
<MessageSquare className="mr-2 h-4 w-4" />
|
||||||
SMS
|
SMS
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant={activeSection === 'perfil' ? 'default' : 'ghost'}
|
variant={activeSection === 'perfil' ? 'default' : 'ghost'}
|
||||||
className="w-full justify-start transition-colors hover:bg-primary! hover:text-white! cursor-pointer"
|
className="w-full justify-start text-sm md:text-base transition-colors hover:bg-primary! hover:text-white! cursor-pointer"
|
||||||
onClick={() => setActiveSection('perfil')}
|
onClick={() => {
|
||||||
|
setActiveSection('perfil');
|
||||||
|
setSidebarOpen(false);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Settings className="mr-2 h-4 w-4" />
|
<Settings className="mr-2 h-4 w-4" />
|
||||||
Meu Perfil
|
Meu Perfil
|
||||||
@ -3132,11 +3185,12 @@ const ProfissionalPage = () => {
|
|||||||
</nav>
|
</nav>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<main>
|
{/* Main Content Area */}
|
||||||
|
<main className="flex-1 min-w-0 w-full">
|
||||||
<div className="flex justify-between items-center mb-4">
|
<div className="flex justify-between items-center mb-4">
|
||||||
<h1 className="text-3xl font-bold">Área do Profissional de Saúde</h1>
|
<h1 className="text-2xl md:text-3xl font-bold">Área do Profissional</h1>
|
||||||
</div>
|
</div>
|
||||||
<p className="mb-8">Bem-vindo à sua área exclusiva.</p>
|
<p className="mb-6 md:mb-8 text-sm md:text-base">Bem-vindo à sua área exclusiva.</p>
|
||||||
|
|
||||||
{renderActiveSection()}
|
{renderActiveSection()}
|
||||||
</main>
|
</main>
|
||||||
@ -3256,21 +3310,21 @@ const ProfissionalPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{}
|
{/* Modal de ação para editar evento */}
|
||||||
{showActionModal && selectedEvent && (
|
{showActionModal && selectedEvent && (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-50">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-50 p-4">
|
||||||
<div className="bg-card border border-border p-6 rounded-lg w-96">
|
<div className="bg-card border border-border p-4 sm:p-6 rounded-lg w-full max-w-md">
|
||||||
<h3 className="text-lg font-semibold mb-2">
|
<h3 className="text-base sm:text-lg font-semibold mb-2">
|
||||||
Consulta de {selectedEvent.title}
|
Consulta de {selectedEvent.title}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-sm text-gray-600 mb-4">
|
<p className="text-xs sm:text-sm text-gray-600 mb-4">
|
||||||
{selectedEvent.extendedProps.type} às {selectedEvent.extendedProps.time}
|
{selectedEvent.extendedProps.type} às {selectedEvent.extendedProps.time}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Button
|
<Button
|
||||||
onClick={handleStartEdit}
|
onClick={handleStartEdit}
|
||||||
className="flex-1 flex items-center gap-2"
|
className="flex-1 flex items-center justify-center gap-2 text-xs sm:text-sm"
|
||||||
>
|
>
|
||||||
<Edit className="h-4 w-4" />
|
<Edit className="h-4 w-4" />
|
||||||
Editar
|
Editar
|
||||||
@ -3280,7 +3334,7 @@ const ProfissionalPage = () => {
|
|||||||
<Button
|
<Button
|
||||||
onClick={() => setShowActionModal(false)}
|
onClick={() => setShowActionModal(false)}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="w-full mt-2 hover:bg-primary! hover:text-white! transition-colors"
|
className="w-full mt-2 hover:bg-primary! hover:text-white! transition-colors text-xs sm:text-sm"
|
||||||
>
|
>
|
||||||
Cancelar
|
Cancelar
|
||||||
</Button>
|
</Button>
|
||||||
@ -3293,25 +3347,24 @@ const ProfissionalPage = () => {
|
|||||||
<div className="fixed inset-0 bg-black/50 flex justify-center items-center z-50 p-4">
|
<div className="fixed inset-0 bg-black/50 flex justify-center items-center z-50 p-4">
|
||||||
<div className="bg-card border border-border rounded-lg shadow-xl w-full max-w-2xl max-h-[80vh] overflow-hidden flex flex-col">
|
<div className="bg-card border border-border rounded-lg shadow-xl w-full max-w-2xl max-h-[80vh] overflow-hidden flex flex-col">
|
||||||
{/* Header com navegação */}
|
{/* Header com navegação */}
|
||||||
<div className="flex items-center justify-between p-4 border-b border-border">
|
<div className="flex items-center justify-between p-3 sm:p-4 border-b border-border gap-2">
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const prev = new Date(selectedDayDate);
|
const prev = new Date(selectedDayDate);
|
||||||
prev.setDate(prev.getDate() - 1);
|
prev.setDate(prev.getDate() - 1);
|
||||||
setSelectedDayDate(prev);
|
setSelectedDayDate(prev);
|
||||||
}}
|
}}
|
||||||
className="p-2 hover:bg-muted rounded transition-colors"
|
className="p-2 hover:bg-muted rounded transition-colors flex-shrink-0"
|
||||||
aria-label="Dia anterior"
|
aria-label="Dia anterior"
|
||||||
>
|
>
|
||||||
<ChevronLeft className="h-5 w-5" />
|
<ChevronLeft className="h-4 w-4 sm:h-5 sm:w-5" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<h2 className="text-lg font-semibold flex-1 text-center">
|
<h2 className="text-base sm:text-lg font-semibold flex-1 text-center line-clamp-2">
|
||||||
{selectedDayDate.toLocaleDateString('pt-BR', {
|
{selectedDayDate.toLocaleDateString('pt-BR', {
|
||||||
weekday: 'long',
|
weekday: 'short',
|
||||||
day: 'numeric',
|
day: 'numeric',
|
||||||
month: 'long',
|
month: 'short'
|
||||||
year: 'numeric'
|
|
||||||
})}
|
})}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
@ -3321,20 +3374,18 @@ const ProfissionalPage = () => {
|
|||||||
next.setDate(next.getDate() + 1);
|
next.setDate(next.getDate() + 1);
|
||||||
setSelectedDayDate(next);
|
setSelectedDayDate(next);
|
||||||
}}
|
}}
|
||||||
className="p-2 hover:bg-muted rounded transition-colors"
|
className="p-2 hover:bg-muted rounded transition-colors flex-shrink-0"
|
||||||
aria-label="Próximo dia"
|
aria-label="Próximo dia"
|
||||||
>
|
>
|
||||||
<ChevronRight className="h-5 w-5" />
|
<ChevronRight className="h-4 w-4 sm:h-5 sm:w-5" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div className="w-12" />
|
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowDayModal(false)}
|
onClick={() => setShowDayModal(false)}
|
||||||
className="p-2 hover:bg-muted rounded transition-colors ml-2"
|
className="p-2 hover:bg-muted rounded transition-colors flex-shrink-0"
|
||||||
aria-label="Fechar"
|
aria-label="Fechar"
|
||||||
>
|
>
|
||||||
<X className="h-5 w-5" />
|
<X className="h-4 w-4 sm:h-5 sm:w-5" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -3346,16 +3397,16 @@ const ProfissionalPage = () => {
|
|||||||
|
|
||||||
if (dayEvents.length === 0) {
|
if (dayEvents.length === 0) {
|
||||||
return (
|
return (
|
||||||
<div className="text-center py-8 text-muted-foreground">
|
<div className="text-center py-6 sm:py-8 text-muted-foreground">
|
||||||
<CalendarIcon className="h-12 w-12 mx-auto mb-4 text-muted-foreground/50" />
|
<CalendarIcon className="h-10 sm:h-12 w-10 sm:w-12 mx-auto mb-3 sm:mb-4 text-muted-foreground/50" />
|
||||||
<p className="text-lg">Nenhuma consulta agendada para este dia</p>
|
<p className="text-base sm:text-lg">Nenhuma consulta agendada para este dia</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<p className="text-sm text-muted-foreground mb-4">
|
<p className="text-xs sm:text-sm text-muted-foreground mb-4">
|
||||||
{dayEvents.length} consulta{dayEvents.length !== 1 ? 's' : ''} agendada{dayEvents.length !== 1 ? 's' : ''}
|
{dayEvents.length} consulta{dayEvents.length !== 1 ? 's' : ''} agendada{dayEvents.length !== 1 ? 's' : ''}
|
||||||
</p>
|
</p>
|
||||||
{dayEvents.map((appointment) => {
|
{dayEvents.map((appointment) => {
|
||||||
@ -3363,20 +3414,20 @@ const ProfissionalPage = () => {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={appointment.id}
|
key={appointment.id}
|
||||||
className="border-l-4 p-4 rounded-lg bg-muted/20"
|
className="border-l-4 p-3 sm:p-4 rounded-lg bg-muted/20"
|
||||||
style={{ borderLeftColor: getStatusColor(appointment.type) }}
|
style={{ borderLeftColor: getStatusColor(appointment.type) }}
|
||||||
>
|
>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<h3 className="font-semibold flex items-center gap-2">
|
<h3 className="font-semibold text-xs sm:text-sm flex items-center gap-2">
|
||||||
<User className="h-4 w-4" />
|
<User className="h-4 w-4" />
|
||||||
{appointment.title}
|
{appointment.title}
|
||||||
</h3>
|
</h3>
|
||||||
<span className="px-2 py-1 rounded-full text-xs font-medium text-white" style={{ backgroundColor: getStatusColor(appointment.type) }}>
|
<span className="px-2 sm:px-3 py-1 rounded-full text-xs font-medium text-white" style={{ backgroundColor: getStatusColor(appointment.type) }}>
|
||||||
{appointment.type}
|
{appointment.type}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-4 text-sm text-muted-foreground">
|
<div className="flex items-center gap-2 sm:gap-4 text-xs sm:text-sm text-muted-foreground flex-wrap">
|
||||||
<span className="flex items-center gap-1">
|
<span className="flex items-center gap-1">
|
||||||
<Clock className="h-4 w-4" />
|
<Clock className="h-4 w-4" />
|
||||||
{appointment.time}
|
{appointment.time}
|
||||||
@ -3424,3 +3475,4 @@ const getShortId = (id?: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default ProfissionalPage;
|
export default ProfissionalPage;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user