瀏覽代碼

ui improvements

Matthew Trejo 2 月之前
父節點
當前提交
0bfd619915

+ 29 - 23
src/app/account/page.tsx

@@ -10,6 +10,7 @@ import { useAccountForm } from "@/hooks/useAccountForm"
 import ProfileImageSection from "@/components/account/ProfileImageSection"
 import PersonalInfoSection from "@/components/account/PersonalInfoSection"
 import PasswordChangeSection from "@/components/account/PasswordChangeSection"
+import MedicalInfoSection from "@/components/account/MedicalInfoSection"
 
 export default function AccountPage() {
   const { data: session, status } = useSession()
@@ -59,7 +60,7 @@ export default function AccountPage() {
 
   return (
     <AuthenticatedLayout>
-      <div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
+      <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
         {/* Header */}
         <div className="mb-8">
           <h1 className="text-3xl font-bold text-gray-900 mb-2">
@@ -71,19 +72,16 @@ export default function AccountPage() {
         </div>
 
         <form onSubmit={handleSubmit}>
-          <div className="grid md:grid-cols-3 gap-8">
-            {/* Foto de Perfil */}
-            <div className="md:col-span-1">
+          <div className="grid lg:grid-cols-3 gap-6">
+            {/* Columna Izquierda - Foto de Perfil y Info Personal */}
+            <div className="lg:col-span-1 space-y-6">
               <ProfileImageSection
                 profileImage={profileImage}
                 loadingImage={loadingImage}
                 onImageChange={handleImageChange}
                 onImageRemove={handleImageRemove}
               />
-            </div>
-
-            {/* Información Personal y Contraseña */}
-            <div className="md:col-span-2 space-y-6">
+              
               <PersonalInfoSection
                 formData={formData}
                 onInputChange={handleInputChange}
@@ -93,24 +91,32 @@ export default function AccountPage() {
                 formData={formData}
                 onInputChange={handleInputChange}
               />
+            </div>
 
-              {/* Botón Guardar */}
-              <div className="pt-4">
-                <Button 
-                  type="submit" 
-                  className="w-full" 
-                  disabled={loading}
-                >
-                  {loading ? (
-                    <div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin mr-2"></div>
-                  ) : (
-                    <Save className="w-4 h-4 mr-2" />
-                  )}
-                  Guardar Cambios
-                </Button>
-              </div>
+            {/* Columna Derecha - Información Médica */}
+            <div className="lg:col-span-2">
+              <MedicalInfoSection
+                formData={formData}
+                onInputChange={handleInputChange}
+              />
             </div>
           </div>
+
+          {/* Botón Guardar */}
+          <div className="pt-6">
+            <Button 
+              type="submit" 
+              className="w-full" 
+              disabled={loading}
+            >
+              {loading ? (
+                <div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin mr-2"></div>
+              ) : (
+                <Save className="w-4 h-4 mr-2" />
+              )}
+              Guardar Cambios
+            </Button>
+          </div>
         </form>
       </div>
     </AuthenticatedLayout>

+ 43 - 0
src/app/api/account/profile-image/route.ts

@@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from "next/server"
 import { getServerSession } from "next-auth"
 import { authOptions } from "@/lib/auth"
 import { prisma } from "@/lib/prisma"
+import { deleteProfileImage } from "@/lib/server-utils"
 
 export async function GET(request: NextRequest) {
   try {
@@ -30,4 +31,46 @@ export async function GET(request: NextRequest) {
       { status: 500 }
     )
   }
+}
+
+export async function DELETE(request: NextRequest) {
+  try {
+    const session = await getServerSession(authOptions)
+
+    if (!session?.user?.id) {
+      return NextResponse.json(
+        { error: "No autorizado" },
+        { status: 401 }
+      )
+    }
+
+    // Obtener usuario actual
+    const currentUser = await prisma.user.findUnique({
+      where: { id: session.user.id },
+      select: { profileImage: true }
+    })
+
+    // Eliminar imagen del servidor si existe
+    if (currentUser?.profileImage) {
+      deleteProfileImage(currentUser.profileImage)
+    }
+
+    // Actualizar usuario en la base de datos
+    await prisma.user.update({
+      where: { id: session.user.id },
+      data: { profileImage: null }
+    })
+
+    return NextResponse.json({
+      success: true,
+      message: "Imagen de perfil eliminada correctamente"
+    })
+
+  } catch (error) {
+    console.error("Error eliminando imagen de perfil:", error)
+    return NextResponse.json(
+      { error: "Error interno del servidor" },
+      { status: 500 }
+    )
+  }
 } 

+ 54 - 7
src/app/api/account/update/route.ts

@@ -29,6 +29,17 @@ export async function POST(request: NextRequest) {
     const currentPassword = formData.get('currentPassword') as string
     const newPassword = formData.get('newPassword') as string
     const profileImage = formData.get('profileImage') as File | null
+    
+    // Nuevos campos médicos y personales
+    const phone = formData.get('phone') as string
+    const gender = formData.get('gender') as string
+    const address = formData.get('address') as string
+    const emergencyContact = formData.get('emergencyContact') as string
+    const medicalHistory = formData.get('medicalHistory') as string
+    const allergies = formData.get('allergies') as string
+    const currentMedications = formData.get('currentMedications') as string
+    
+    // NOTA: dateOfBirth NO se incluye porque es provisto por la API UTB y no debe ser editable
 
     // Obtener información del usuario actual
     const currentUser = await prisma.user.findUnique({
@@ -60,16 +71,44 @@ export async function POST(request: NextRequest) {
       }
     }
 
-    // Preparar datos de actualización (solo email y foto permitidos)
-    const updateData: {
-      email?: string
-      profileImage?: string
-    } = {}
+    // Preparar datos de actualización
+    const updateData: any = {}
 
-    // Actualizar email (único campo editable aparte de foto)
+    // Actualizar email
     if (email) {
       updateData.email = email
     }
+    
+    // Actualizar campos médicos y personales
+    if (phone !== undefined && phone !== null) {
+      updateData.phone = phone || undefined
+    }
+    
+    // dateOfBirth NO se actualiza - es provisto por la API UTB
+    
+    if (gender !== undefined && gender !== null) {
+      updateData.gender = gender || undefined
+    }
+    
+    if (address !== undefined && address !== null) {
+      updateData.address = address || undefined
+    }
+    
+    if (emergencyContact !== undefined && emergencyContact !== null) {
+      updateData.emergencyContact = emergencyContact || undefined
+    }
+    
+    if (medicalHistory !== undefined && medicalHistory !== null) {
+      updateData.medicalHistory = medicalHistory || undefined
+    }
+    
+    if (allergies !== undefined && allergies !== null) {
+      updateData.allergies = allergies || undefined
+    }
+    
+    if (currentMedications !== undefined && currentMedications !== null) {
+      updateData.currentMedications = currentMedications || undefined
+    }
 
     // Los cambios de contraseña no están permitidos - todos los usuarios son UTB
     if (currentPassword || newPassword) {
@@ -131,7 +170,15 @@ export async function POST(request: NextRequest) {
         username: true,
         email: true,
         role: true,
-        profileImage: true
+        profileImage: true,
+        phone: true,
+        dateOfBirth: true,
+        gender: true,
+        address: true,
+        emergencyContact: true,
+        medicalHistory: true,
+        allergies: true,
+        currentMedications: true
       }
     })
 

+ 0 - 77
src/app/dashboard/page.tsx

@@ -237,83 +237,6 @@ export default function DashboardPage() {
               )}
             </CardContent>
           </Card>
-
-          {/* Recent Activity / Info Panel */}
-          <Card className="col-span-3">
-            <CardHeader>
-              <CardTitle>Información del Sistema</CardTitle>
-              <CardDescription>
-                Seguridad y privacidad
-              </CardDescription>
-            </CardHeader>
-            <CardContent className="space-y-6">
-              <div className="space-y-2">
-                <div className="flex items-start gap-3">
-                  <div className="rounded-lg bg-green-100 dark:bg-green-900/20 p-2">
-                    <Shield className="h-4 w-4 text-green-600 dark:text-green-400" />
-                  </div>
-                  <div className="space-y-1">
-                    <p className="text-sm font-medium leading-none">
-                      Seguridad Garantizada
-                    </p>
-                    <p className="text-sm text-muted-foreground">
-                      Encriptación de nivel bancario protege tus datos médicos
-                    </p>
-                  </div>
-                </div>
-              </div>
-
-              <Separator />
-
-              <div className="space-y-2">
-                <div className="flex items-start gap-3">
-                  <div className="rounded-lg bg-blue-100 dark:bg-blue-900/20 p-2">
-                    <Shield className="h-4 w-4 text-blue-600 dark:text-blue-400" />
-                  </div>
-                  <div className="space-y-1">
-                    <p className="text-sm font-medium leading-none">
-                      Privacidad Médica
-                    </p>
-                    <p className="text-sm text-muted-foreground">
-                      Cumplimiento de estándares internacionales HIPAA
-                    </p>
-                  </div>
-                </div>
-              </div>
-
-              <Separator />
-
-              <div className="space-y-2">
-                <div className="flex items-start gap-3">
-                  <div className="rounded-lg bg-violet-100 dark:bg-violet-900/20 p-2">
-                    <Activity className="h-4 w-4 text-violet-600 dark:text-violet-400" />
-                  </div>
-                  <div className="space-y-1">
-                    <p className="text-sm font-medium leading-none">
-                      Disponibilidad 24/7
-                    </p>
-                    <p className="text-sm text-muted-foreground">
-                      Asistencia médica virtual disponible en todo momento
-                    </p>
-                  </div>
-                </div>
-              </div>
-
-              {isPatient && (
-                <>
-                  <Separator />
-                  <div className="pt-2">
-                    <Button className="w-full" asChild>
-                      <Link href="/chat">
-                        Iniciar Consulta
-                        <ArrowRight className="ml-2 h-4 w-4" />
-                      </Link>
-                    </Button>
-                  </div>
-                </>
-              )}
-            </CardContent>
-          </Card>
         </div>
 
         {/* Additional Information */}

+ 13 - 1
src/components/AuthenticatedLayout.tsx

@@ -14,7 +14,19 @@ interface AuthenticatedLayoutProps {
 export default function AuthenticatedLayout({ children }: AuthenticatedLayoutProps) {
   const { data: session, status } = useSession()
   const router = useRouter()
-  const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false)
+  const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(() => {
+    // Cargar el estado desde localStorage al inicializar
+    if (typeof window !== 'undefined') {
+      const saved = localStorage.getItem('sidebarCollapsed')
+      return saved === 'true'
+    }
+    return false
+  })
+
+  // Guardar el estado en localStorage cuando cambie
+  useEffect(() => {
+    localStorage.setItem('sidebarCollapsed', String(isSidebarCollapsed))
+  }, [isSidebarCollapsed])
 
   useEffect(() => {
     if (status === "unauthenticated") {

+ 15 - 13
src/components/Footer.tsx

@@ -17,9 +17,9 @@ export default function Footer({ variant = 'system', className = '' }: FooterPro
       style={{ borderTopColor: COLOR_PALETTE.gray[200] }}
     >
       <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
-        <div className="flex flex-col sm:flex-row justify-between items-center space-y-4 sm:space-y-0">
+        <div className="flex flex-col space-y-4 sm:space-y-0 sm:flex-row sm:justify-between sm:items-center">
           {/* Logo y nombre */}
-          <div className="flex items-center space-x-2">
+          <div className="flex items-center justify-center sm:justify-start space-x-2">
             <Stethoscope 
               className="h-5 w-5" 
               style={{ color: COLOR_PALETTE.primary[500] }} 
@@ -30,17 +30,19 @@ export default function Footer({ variant = 'system', className = '' }: FooterPro
           </div>
 
           {/* Enlaces legales y copyright */}
-          <div className="flex items-center space-x-6 text-sm text-muted-foreground">
-            {FOOTER_CONFIG.legalLinks.map((link) => (
-              <Link 
-                key={link.href}
-                href={link.href} 
-                className="hover:text-foreground transition-colors"
-              >
-                {link.label}
-              </Link>
-            ))}
-            <span className="text-muted-foreground/50">|</span>
+          <div className="flex flex-col space-y-2 sm:space-y-0 sm:flex-row sm:items-center sm:space-x-6 text-sm text-muted-foreground text-center sm:text-left">
+            <div className="flex items-center justify-center space-x-4 sm:space-x-6">
+              {FOOTER_CONFIG.legalLinks.map((link) => (
+                <Link 
+                  key={link.href}
+                  href={link.href} 
+                  className="hover:text-foreground transition-colors"
+                >
+                  {link.label}
+                </Link>
+              ))}
+            </div>
+            <span className="hidden sm:inline text-muted-foreground/50">|</span>
             <span>
               © {new Date().getFullYear()} {FOOTER_CONFIG.company.name}
             </span>

+ 155 - 0
src/components/account/MedicalInfoSection.tsx

@@ -0,0 +1,155 @@
+"use client"
+
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
+import { Input } from "@/components/ui/input"
+import { Label } from "@/components/ui/label"
+import { Textarea } from "@/components/ui/textarea"
+import { Heart } from "lucide-react"
+
+interface MedicalInfoSectionProps {
+  formData: {
+    phone?: string
+    gender?: string
+    address?: string
+    emergencyContact?: string
+    medicalHistory?: string
+    allergies?: string
+    currentMedications?: string
+  }
+  onInputChange: (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => void
+}
+
+export default function MedicalInfoSection({
+  formData,
+  onInputChange
+}: MedicalInfoSectionProps) {
+  return (
+    <Card>
+      <CardHeader>
+        <CardTitle className="flex items-center">
+          <Heart className="w-5 h-5 mr-2 text-primary" />
+          Información Médica y Personal
+        </CardTitle>
+        <p className="text-sm text-muted-foreground">
+          Esta información ayudará al chatbot a brindarte recomendaciones más precisas
+        </p>
+      </CardHeader>
+      <CardContent className="space-y-4">
+        {/* Información Personal */}
+        <div className="space-y-4 pb-4 border-b">
+          <h3 className="font-semibold text-sm text-foreground">Datos de Contacto</h3>
+          
+          <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
+            <div className="space-y-2">
+              <Label htmlFor="phone">Teléfono</Label>
+              <Input
+                id="phone"
+                name="phone"
+                type="tel"
+                placeholder="+1 (555) 123-4567"
+                value={formData.phone || ""}
+                onChange={onInputChange}
+              />
+            </div>
+
+            <div className="space-y-2">
+              <Label htmlFor="gender">Género</Label>
+              <select
+                id="gender"
+                name="gender"
+                value={formData.gender || ""}
+                onChange={onInputChange}
+                className="w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent text-sm bg-background"
+              >
+                <option value="">Seleccionar...</option>
+                <option value="MALE">Masculino</option>
+                <option value="FEMALE">Femenino</option>
+                <option value="OTHER">Otro</option>
+                <option value="PREFER_NOT_TO_SAY">Prefiero no decirlo</option>
+              </select>
+            </div>
+          </div>
+
+          <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
+            <div className="space-y-2">
+              <Label htmlFor="emergencyContact">Contacto de Emergencia</Label>
+              <Input
+                id="emergencyContact"
+                name="emergencyContact"
+                type="tel"
+                placeholder="Nombre y teléfono"
+                value={formData.emergencyContact || ""}
+                onChange={onInputChange}
+              />
+            </div>
+
+            <div className="space-y-2">
+              <Label htmlFor="address">Dirección</Label>
+              <Input
+                id="address"
+                name="address"
+                type="text"
+                placeholder="Calle, número, ciudad, código postal"
+                value={formData.address || ""}
+                onChange={onInputChange}
+              />
+            </div>
+          </div>
+        </div>
+
+        {/* Información Médica */}
+        <div className="space-y-4 pt-2">
+          <h3 className="font-semibold text-sm text-foreground">Información Médica</h3>
+          
+          <div className="space-y-2">
+            <Label htmlFor="medicalHistory">Historial Médico</Label>
+            <Textarea
+              id="medicalHistory"
+              name="medicalHistory"
+              placeholder="Enfermedades previas, cirugías, condiciones crónicas, etc."
+              value={formData.medicalHistory || ""}
+              onChange={onInputChange}
+              rows={3}
+              className="resize-none"
+            />
+            <p className="text-xs text-muted-foreground">
+              Ejemplo: Diabetes tipo 2, hipertensión, apendicectomía en 2020
+            </p>
+          </div>
+
+          <div className="space-y-2">
+            <Label htmlFor="allergies">Alergias</Label>
+            <Textarea
+              id="allergies"
+              name="allergies"
+              placeholder="Alergias a medicamentos, alimentos, o sustancias"
+              value={formData.allergies || ""}
+              onChange={onInputChange}
+              rows={2}
+              className="resize-none"
+            />
+            <p className="text-xs text-muted-foreground">
+              Ejemplo: Penicilina, mariscos, polen
+            </p>
+          </div>
+
+          <div className="space-y-2">
+            <Label htmlFor="currentMedications">Medicamentos Actuales</Label>
+            <Textarea
+              id="currentMedications"
+              name="currentMedications"
+              placeholder="Medicamentos que estás tomando actualmente"
+              value={formData.currentMedications || ""}
+              onChange={onInputChange}
+              rows={3}
+              className="resize-none"
+            />
+            <p className="text-xs text-muted-foreground">
+              Ejemplo: Metformina 850mg (2 veces al día), Losartán 50mg (1 vez al día)
+            </p>
+          </div>
+        </div>
+      </CardContent>
+    </Card>
+  )
+}

+ 17 - 0
src/components/account/PersonalInfoSection.tsx

@@ -11,6 +11,7 @@ interface PersonalInfoSectionProps {
     lastname: string
     email: string
     identificacion?: string
+    dateOfBirth?: string
   }
   onInputChange: (e: React.ChangeEvent<HTMLInputElement>) => void
 }
@@ -92,6 +93,22 @@ export default function PersonalInfoSection({
             </div>
           </div>
 
+          {/* Fecha de Nacimiento (solo lectura) */}
+          {formData.dateOfBirth && (
+            <div className="space-y-2">
+              <Label htmlFor="dateOfBirth">Fecha de Nacimiento</Label>
+              <Input
+                id="dateOfBirth"
+                name="dateOfBirth"
+                type="date"
+                value={formData.dateOfBirth}
+                className="bg-gray-50"
+                disabled
+                readOnly
+              />
+            </div>
+          )}
+
           {/* Email (editable, opcional) */}
           <div className="space-y-2">
             <Label htmlFor="email">

+ 5 - 5
src/components/appointments/AppointmentsHeader.tsx

@@ -21,17 +21,17 @@ export const AppointmentsHeader = ({
   return (
     <div className="mb-6">
       <div className="bg-card rounded-xl p-6 border shadow-sm">
-        <div className="flex items-center justify-between">
-          <div className="flex items-center space-x-3">
-            <div className="w-10 h-10 bg-primary rounded-lg flex items-center justify-center shadow-sm">
+        <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4">
+          <div className="flex items-center space-x-3 flex-1 min-w-0">
+            <div className="w-10 h-10 flex-shrink-0 bg-primary rounded-lg flex items-center justify-center shadow-sm">
               <Calendar className="w-5 h-5 text-primary-foreground" />
             </div>
-            <div>
+            <div className="min-w-0">
               <h1 className="text-xl font-bold text-foreground">{title}</h1>
               <p className="text-sm text-muted-foreground">{description}</p>
             </div>
           </div>
-          <div className="flex items-center gap-3">
+          <div className="flex items-center gap-3 flex-shrink-0">
             <div className="text-right">
               <div className="bg-muted rounded-lg p-3 shadow-sm border">
                 <div className="text-2xl font-bold text-primary">{appointmentsCount}</div>

+ 5 - 5
src/components/records/RecordsFilters.tsx

@@ -65,12 +65,12 @@ export default function RecordsFilters({
   return (
     <Card className="mb-6 border shadow-sm rounded-xl">
       <CardHeader className="pb-4 px-6 pt-6">
-        <div className="flex items-center justify-between">
-          <div className="flex items-center space-x-3">
-            <div className="w-10 h-10 bg-primary rounded-lg flex items-center justify-center shadow-sm">
+        <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3">
+          <div className="flex items-center space-x-3 flex-1 min-w-0">
+            <div className="w-10 h-10 flex-shrink-0 bg-primary rounded-lg flex items-center justify-center shadow-sm">
               <Filter className="w-5 h-5 text-primary-foreground" />
             </div>
-            <div>
+            <div className="min-w-0">
               <CardTitle className="text-xl font-bold text-foreground">Filtros y Búsqueda</CardTitle>
               <p className="text-sm text-muted-foreground">Personaliza tu búsqueda de reportes</p>
             </div>
@@ -79,7 +79,7 @@ export default function RecordsFilters({
             variant="outline"
             size="sm"
             onClick={onShowFiltersToggle}
-            className="flex items-center space-x-2"
+            className="flex items-center space-x-2 flex-shrink-0"
           >
             <span className="font-medium">{showFilters ? "Ocultar" : "Mostrar"} filtros</span>
             <ChevronDown className={`w-4 h-4 transition-transform duration-200 ${showFilters ? 'rotate-180' : ''}`} />

+ 4 - 4
src/components/records/RecordsHeader.tsx

@@ -9,14 +9,14 @@ export default function RecordsHeader({ userRole, recordsCount }: RecordsHeaderP
   return (
     <div className="mb-6">
       <div className="bg-card rounded-xl p-6 border shadow-sm">
-        <div className="flex items-center justify-between">
-          <div className="flex items-center space-x-3">
-            <div className="w-10 h-10 bg-primary rounded-lg flex items-center justify-center shadow-sm">
+        <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4">
+          <div className="flex items-center space-x-3 flex-1 min-w-0">
+            <div className="w-10 h-10 flex-shrink-0 bg-primary rounded-lg flex items-center justify-center shadow-sm">
               <svg className="w-5 h-5 text-primary-foreground" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                 <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
               </svg>
             </div>
-            <div>
+            <div className="min-w-0">
               <h1 className="text-xl font-bold text-foreground">
                 {userRole === "DOCTOR" ? "Todos los Reportes Médicos" : "Mis Reportes Médicos"}
               </h1>

+ 1 - 1
src/components/sidebar/SidebarNavigation.tsx

@@ -57,7 +57,7 @@ export default function SidebarNavigation({ onItemClick, isCollapsed = false }:
     } else {
       if (currentPath === "/dashboard") {
         sectionsToExpand.push("General")
-      } else if (currentPath.startsWith("/chat") || currentPath.startsWith("/records")) {
+      } else if (currentPath.startsWith("/chat") || currentPath.startsWith("/records") || currentPath.startsWith("/appointments")) {
         sectionsToExpand.push("Servicios Médicos")
       }
     }

+ 105 - 15
src/hooks/useAccountForm.ts

@@ -12,6 +12,14 @@ interface FormData {
   currentPassword: string
   newPassword: string
   confirmPassword: string
+  phone?: string
+  dateOfBirth?: string
+  gender?: string
+  address?: string
+  emergencyContact?: string
+  medicalHistory?: string
+  allergies?: string
+  currentMedications?: string
 }
 
 export function useAccountForm() {
@@ -24,7 +32,15 @@ export function useAccountForm() {
     email: "",
     currentPassword: "",
     newPassword: "",
-    confirmPassword: ""
+    confirmPassword: "",
+    phone: "",
+    dateOfBirth: "",
+    gender: "",
+    address: "",
+    emergencyContact: "",
+    medicalHistory: "",
+    allergies: "",
+    currentMedications: ""
   })
   
   const [loading, setLoading] = useState(false)
@@ -69,7 +85,15 @@ export function useAccountForm() {
         name: session.user.name || "",
         lastname: session.user.lastname || "",
         email: session.user.email || "",
-        identificacion: session.user.identificacion || ""
+        identificacion: session.user.identificacion || "",
+        phone: session.user.phone || "",
+        dateOfBirth: session.user.dateOfBirth ? new Date(session.user.dateOfBirth).toISOString().split('T')[0] : "",
+        gender: session.user.gender || "",
+        address: session.user.address || "",
+        emergencyContact: session.user.emergencyContact || "",
+        medicalHistory: session.user.medicalHistory || "",
+        allergies: session.user.allergies || "",
+        currentMedications: session.user.currentMedications || ""
       }))
     }
   }, [session])
@@ -81,7 +105,7 @@ export function useAccountForm() {
     }
   }, [session?.user?.id, imageLoaded, loadProfileImage])
 
-  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
     const { name, value } = e.target
     
     setFormData(prev => ({
@@ -105,10 +129,42 @@ export function useAccountForm() {
     }
   }
 
-  const handleImageRemove = () => {
-    setProfileImage(null)
-    setImageFile(null)
-    setImageLoaded(false)
+  const handleImageRemove = async () => {
+    if (!profileImage) return
+    
+    setLoadingImage(true)
+    try {
+      const response = await fetch("/api/account/profile-image", {
+        method: 'DELETE',
+        headers: {
+          'Content-Type': 'application/json',
+        },
+      })
+      
+      if (response.ok) {
+        setProfileImage(null)
+        setImageFile(null)
+        setImageLoaded(false)
+        
+        // Actualizar el contexto global
+        updateProfileImage(null)
+        
+        // Actualizar la sesión
+        await update({
+          profileImage: null
+        })
+        
+        toast.success("Imagen de perfil eliminada correctamente")
+      } else {
+        const data = await response.json()
+        toast.error(data.error || "Error al eliminar la imagen")
+      }
+    } catch (error) {
+      console.error("Error eliminando imagen:", error)
+      toast.error("Error al eliminar la imagen de perfil")
+    } finally {
+      setLoadingImage(false)
+    }
   }
 
   const handleSubmit = async (e: React.FormEvent) => {
@@ -142,6 +198,37 @@ export function useAccountForm() {
         formDataToSend.append('newPassword', formData.newPassword)
       }
       
+      // Agregar campos médicos y personales
+      if (formData.phone) {
+        formDataToSend.append('phone', formData.phone)
+      }
+      
+      // dateOfBirth NO se envía - es provisto por la API UTB y no es editable
+      
+      if (formData.gender) {
+        formDataToSend.append('gender', formData.gender)
+      }
+      
+      if (formData.address) {
+        formDataToSend.append('address', formData.address)
+      }
+      
+      if (formData.emergencyContact) {
+        formDataToSend.append('emergencyContact', formData.emergencyContact)
+      }
+      
+      if (formData.medicalHistory) {
+        formDataToSend.append('medicalHistory', formData.medicalHistory)
+      }
+      
+      if (formData.allergies) {
+        formDataToSend.append('allergies', formData.allergies)
+      }
+      
+      if (formData.currentMedications) {
+        formDataToSend.append('currentMedications', formData.currentMedications)
+      }
+      
       if (imageFile) {
         formDataToSend.append('profileImage', imageFile)
       }
@@ -154,7 +241,7 @@ export function useAccountForm() {
       const data = await response.json()
 
       if (response.ok) {
-        toast.success("Perfil actualizado correctamente. Serás redirigido para iniciar sesión nuevamente.")
+        toast.success("Perfil actualizado correctamente.")
         
         // Limpiar contraseñas
         setFormData(prev => ({
@@ -164,12 +251,20 @@ export function useAccountForm() {
           confirmPassword: ""
         }))
 
-        // Actualizar la sesión de NextAuth con los nuevos datos
+        // Actualizar la sesión de NextAuth con todos los datos nuevos
         await update({
           name: data.user.name,
           lastname: data.user.lastname,
           email: data.user.email,
-          profileImage: data.user.profileImage
+          profileImage: data.user.profileImage,
+          phone: data.user.phone,
+          dateOfBirth: data.user.dateOfBirth,
+          gender: data.user.gender,
+          address: data.user.address,
+          emergencyContact: data.user.emergencyContact,
+          medicalHistory: data.user.medicalHistory,
+          allergies: data.user.allergies,
+          currentMedications: data.user.currentMedications
         })
 
         // Actualizar la imagen de perfil en el contexto global
@@ -184,11 +279,6 @@ export function useAccountForm() {
             loadProfileImage()
           }, 500)
         }
-
-        // Redirigir a login después de 2 segundos
-        setTimeout(() => {
-          router.push("/auth/login")
-        }, 2000)
       } else {
         toast.error(data.error || "Error al actualizar el perfil")
       }

+ 5 - 0
src/hooks/useChat.ts

@@ -48,9 +48,14 @@ export const useChat = () => {
             setCurrentSuggestions(lastMessage.suggestions);
             setShowDynamicSuggestions(true);
           }
+        } else {
+          // Si no hay mensajes, asegurarse de que las sugerencias estén visibles
+          setShowSuggestions(true);
         }
       } catch (error) {
         console.error("Error loading chat state:", error);
+        // En caso de error, asegurar que las sugerencias estén visibles
+        setShowSuggestions(true);
       }
     }
   }, []);

+ 24 - 0
src/lib/auth.ts

@@ -76,6 +76,14 @@ export const authOptions: NextAuthOptions = {
             profileImage: user.profileImage || undefined,
             isExternalAuth: user.isExternalAuth,
             identificacion: user.identificacion || undefined,
+            phone: user.phone || undefined,
+            dateOfBirth: user.dateOfBirth || undefined,
+            gender: user.gender || undefined,
+            address: user.address || undefined,
+            emergencyContact: user.emergencyContact || undefined,
+            medicalHistory: user.medicalHistory || undefined,
+            allergies: user.allergies || undefined,
+            currentMedications: user.currentMedications || undefined,
           };
         } catch (error) {
           if (error instanceof UTBApiError) {
@@ -105,6 +113,14 @@ export const authOptions: NextAuthOptions = {
         token.profileImage = user.profileImage;
         token.isExternalAuth = user.isExternalAuth;
         token.identificacion = user.identificacion;
+        token.dateOfBirth = user.dateOfBirth;
+        token.phone = user.phone;
+        token.gender = user.gender;
+        token.address = user.address;
+        token.emergencyContact = user.emergencyContact;
+        token.medicalHistory = user.medicalHistory;
+        token.allergies = user.allergies;
+        token.currentMedications = user.currentMedications;
       }
       return token;
     },
@@ -117,6 +133,14 @@ export const authOptions: NextAuthOptions = {
         session.user.profileImage = token.profileImage as string | undefined;
         session.user.isExternalAuth = token.isExternalAuth as boolean | undefined;
         session.user.identificacion = token.identificacion as string | undefined;
+        session.user.dateOfBirth = token.dateOfBirth as Date | undefined;
+        session.user.phone = token.phone as string | undefined;
+        session.user.gender = token.gender as string | undefined;
+        session.user.address = token.address as string | undefined;
+        session.user.emergencyContact = token.emergencyContact as string | undefined;
+        session.user.medicalHistory = token.medicalHistory as string | undefined;
+        session.user.allergies = token.allergies as string | undefined;
+        session.user.currentMedications = token.currentMedications as string | undefined;
       }
       return session;
     }

+ 24 - 0
src/types/next-auth.d.ts

@@ -12,6 +12,14 @@ declare module "next-auth" {
       profileImage?: string
       isExternalAuth?: boolean
       identificacion?: string
+      phone?: string
+      dateOfBirth?: Date
+      gender?: string
+      address?: string
+      emergencyContact?: string
+      medicalHistory?: string
+      allergies?: string
+      currentMedications?: string
     }
   }
 
@@ -24,6 +32,14 @@ declare module "next-auth" {
     profileImage?: string
     isExternalAuth?: boolean
     identificacion?: string
+    phone?: string
+    dateOfBirth?: Date
+    gender?: string
+    address?: string
+    emergencyContact?: string
+    medicalHistory?: string
+    allergies?: string
+    currentMedications?: string
   }
 }
 
@@ -35,5 +51,13 @@ declare module "next-auth/jwt" {
     profileImage?: string
     isExternalAuth?: boolean
     identificacion?: string
+    dateOfBirth?: Date
+    phone?: string
+    gender?: string
+    address?: string
+    emergencyContact?: string
+    medicalHistory?: string
+    allergies?: string
+    currentMedications?: string
   }
 }