| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- import { useState, useEffect, useCallback } from "react"
- import { useSession } from "next-auth/react"
- import { notifications } from "@/lib/notifications"
- import { downloadReactPDF } from "@/utils/pdf"
- import { generateTXTReport } from "@/utils/reports"
- import { Record } from "@/components/records/types"
- export function useRecords() {
- const { data: session, status } = useSession()
- const [records, setRecords] = useState<Record[]>([])
- const [filteredRecords, setFilteredRecords] = useState<Record[]>([])
- const [loading, setLoading] = useState(true)
- const [selectedRecord, setSelectedRecord] = useState<Record | null>(null)
- const [showModal, setShowModal] = useState(false)
- const [currentPage, setCurrentPage] = useState(1)
- const [generatingPDF, setGeneratingPDF] = useState(false)
-
- // Filtros y paginación
- const [searchTerm, setSearchTerm] = useState("")
- const [selectedPatientId, setSelectedPatientId] = useState<string | null>(null)
- const [selectedPatient, setSelectedPatient] = useState<{
- id: string
- name: string
- lastname: string
- email: string
- username: string
- profileImage: string | null
- createdAt: string
- _count: {
- records: number
- }
- } | null>(null)
- const [dateFilter, setDateFilter] = useState("")
- const [itemsPerPage, setItemsPerPage] = useState(3)
- const [showFilters, setShowFilters] = useState(false)
- const [showLoadingSkeleton, setShowLoadingSkeleton] = useState(false)
- const fetchRecords = useCallback(async () => {
- if (status !== "authenticated") return
-
- try {
- setLoading(true)
-
- // Construir URL con parámetros según el rol
- let url = "/api/chat/report"
- if (session?.user?.role === "PATIENT") {
- // Los pacientes solo ven sus propios reportes
- url += `?userId=${session.user.id}`
- } else if ((session?.user?.role === "DOCTOR" || session?.user?.role === "ADMIN") && selectedPatientId) {
- // Los doctores y admins pueden filtrar por paciente específico
- url += `?userId=${selectedPatientId}`
- }
- // Los doctores ven todos los reportes (sin parámetros) si no hay paciente seleccionado
-
- const response = await fetch(url, {
- credentials: "include",
- headers: {
- "Content-Type": "application/json",
- },
- })
-
- if (response.ok) {
- const data = await response.json()
- setRecords(data.records || [])
- setFilteredRecords(data.records || [])
- } else {
- console.error("Error response:", response.status, response.statusText)
- notifications.records.loadError()
- }
- } catch (error) {
- console.error("Error fetching records:", error)
- notifications.records.loadError()
- } finally {
- setLoading(false)
- }
- }, [status, session?.user?.role, session?.user?.id, selectedPatientId])
- // Efecto para recargar datos cuando cambia el paciente seleccionado
- useEffect(() => {
- if (status === "authenticated" && (session?.user?.role === "DOCTOR" || session?.user?.role === "ADMIN") && selectedPatientId) {
- setShowLoadingSkeleton(false)
- fetchRecords()
- }
- }, [status, selectedPatientId, fetchRecords])
- // Función para manejar la selección de paciente
- const handlePatientSelect = (patient: {
- id: string
- name: string
- lastname: string
- email: string
- username: string
- profileImage: string | null
- createdAt: string
- _count: {
- records: number
- }
- } | null) => {
- if (patient) {
- setSelectedPatientId(patient.id)
- setSelectedPatient(patient)
- } else {
- setSelectedPatientId(null)
- setSelectedPatient(null)
- }
- }
- // Efecto separado para mostrar skeleton después de 3 segundos
- useEffect(() => {
- let skeletonTimer: NodeJS.Timeout
-
- if (loading && status === "authenticated" && (session?.user?.role === "DOCTOR" || session?.user?.role === "ADMIN")) {
- skeletonTimer = setTimeout(() => {
- setShowLoadingSkeleton(true)
- }, 3000)
- } else {
- setShowLoadingSkeleton(false)
- }
- return () => {
- if (skeletonTimer) {
- clearTimeout(skeletonTimer)
- }
- }
- }, [loading, status, session?.user?.role])
- useEffect(() => {
- if (status === "authenticated") {
- fetchRecords()
- }
- }, [status, fetchRecords])
- // Filtrar registros
- useEffect(() => {
- let filtered = [...records]
- // Filtro por fecha
- if (dateFilter) {
- const filterDate = new Date(dateFilter)
- filtered = filtered.filter((record) => {
- const recordDate = new Date(record.createdAt)
- return recordDate.toDateString() === filterDate.toDateString()
- })
- }
- setFilteredRecords(filtered)
- setCurrentPage(1) // Resetear a la primera página cuando se filtran
- }, [records, dateFilter])
- const downloadReport = (record: Record) => {
- try {
- // Generar el reporte TXT mejorado
- const reportContent = generateTXTReport(record)
- const blob = new Blob([reportContent], {
- type: "text/plain; charset=utf-8",
- })
- const url = URL.createObjectURL(blob)
- const a = document.createElement("a")
- a.href = url
- a.download = `reporte-medico-${record.id.slice(-8)}-${
- new Date().toISOString().split("T")[0]
- }.txt`
- document.body.appendChild(a)
- a.click()
- document.body.removeChild(a)
- URL.revokeObjectURL(url)
- notifications.records.txtDownloaded()
- } catch (error) {
- console.error("Error generando reporte TXT:", error)
- notifications.records.txtError()
- }
- }
- const handleGeneratePDF = async (record: Record) => {
- if (!session?.user?.role) return
- setGeneratingPDF(true)
- try {
- console.log("Iniciando generación de PDF con React-PDF...")
- await downloadReactPDF(record)
- notifications.records.pdfDownloaded()
- } catch (error) {
- console.error("Error generando PDF:", error)
- notifications.records.pdfError()
- } finally {
- setGeneratingPDF(false)
- }
- }
- const copyToClipboard = (text: string) => {
- navigator.clipboard.writeText(text)
- notifications.records.copied()
- }
- const clearFilters = () => {
- setSearchTerm("")
- setSelectedPatientId(null)
- setSelectedPatient(null)
- setDateFilter("")
- setCurrentPage(1)
- setShowLoadingSkeleton(false)
- }
- const handleViewRecord = (record: Record) => {
- setSelectedRecord(record)
- setShowModal(true)
- }
- const handleCloseModal = () => {
- setShowModal(false)
- setSelectedRecord(null)
- }
- // Calcular paginación
- const totalPages = Math.ceil(filteredRecords.length / itemsPerPage)
- const startIndex = (currentPage - 1) * itemsPerPage
- const endIndex = startIndex + itemsPerPage
- const currentRecords = filteredRecords.slice(startIndex, endIndex)
- const handlePageChange = (page: number) => {
- setCurrentPage(page)
- }
- return {
- // Estado
- records,
- filteredRecords,
- loading,
- selectedRecord,
- showModal,
- currentPage,
- generatingPDF,
- searchTerm,
- selectedPatientId,
- selectedPatient,
- dateFilter,
- itemsPerPage,
- showFilters,
- showLoadingSkeleton,
- totalPages,
- startIndex,
- endIndex,
- currentRecords,
- session,
- status,
-
- // Acciones
- setSearchTerm,
- setSelectedPatientId,
- setSelectedPatient,
- setDateFilter,
- setItemsPerPage,
- setShowFilters,
- downloadReport,
- handleGeneratePDF,
- copyToClipboard,
- clearFilters,
- handleViewRecord,
- handleCloseModal,
- handlePageChange,
- fetchRecords,
- handlePatientSelect
- }
- }
|