@giouwur/biometric-sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +215 -0
- package/bin/init.js +50 -0
- package/dist/index.d.mts +569 -0
- package/dist/index.d.ts +569 -0
- package/dist/index.js +4725 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +4667 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +45 -0
- package/templates/test-page.tsx +1219 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/BiometricProvider.tsx","../src/lib/stores/biometricStore.ts","../src/lib/stores/uiStore.ts","../src/components/enrollment/FingerEnrollModule.tsx","../src/lib/stores/enrollmentStore.ts","../src/types/abis-types.ts","../src/lib/utils/imageHelpers.ts","../src/components/ui/BiometricSlot.tsx","../src/components/ui/MissingFingerModal.tsx","../src/components/ui/Modal.tsx","../src/components/ui/Button.tsx","../src/components/ui/ProgressBar.tsx","../src/components/enrollment/ModuleHeader.tsx","../src/components/ui/Select.tsx","../src/components/ui/QualityBadge.tsx","../src/components/ui/Loader.tsx","../src/components/enrollment/FingerCaptureModal.tsx","../src/lib/constants/fingerPositions.ts","../src/components/enrollment/FaceEnrollModule.tsx","../src/components/enrollment/FaceCameraModal.tsx","../src/components/enrollment/PalmEnrollModule.tsx","../src/components/enrollment/PalmCaptureModal.tsx","../src/components/enrollment/IrisEnrollModule.tsx","../src/components/enrollment/IrisCameraModal.tsx","../src/components/enrollment/FingerRollEnrollModule.tsx","../src/components/enrollment/FingerRollCaptureModal.tsx","../src/components/ui/Card.tsx","../src/components/ui/Input.tsx","../src/components/ui/StatusChip.tsx","../src/components/ui/Tabs.tsx","../src/components/ui/TableWrapper.tsx","../src/lib/api.ts","../src/lib/stores/authStore.ts","../src/lib/services/biometricService.ts"],"sourcesContent":["\"use client\";\r\n\r\nimport React, { createContext, useContext, useEffect, useRef } from 'react';\r\nimport { useBiometricStore } from '../lib/stores/biometricStore';\r\n\r\nexport interface BiometricConfig {\r\n /** WebSocket URL for the biometric device server */\r\n wsUrl: string;\r\n /** Optional API base URL — exposed via useBiometricConfig() for the consuming app */\r\n apiBaseUrl?: string;\r\n /** Device identifier */\r\n deviceId?: string;\r\n}\r\n\r\nconst BiometricContext = createContext<BiometricConfig | null>(null);\r\n\r\n/**\r\n * Hook to access the SDK configuration from any child component.\r\n * \r\n * @example\r\n * ```tsx\r\n * const { apiBaseUrl } = useBiometricConfig();\r\n * const res = await fetch(`${apiBaseUrl}/applicant/${id}`);\r\n * ```\r\n */\r\nexport function useBiometricConfig(): BiometricConfig {\r\n const ctx = useContext(BiometricContext);\r\n if (!ctx) {\r\n throw new Error(\r\n 'useBiometricConfig must be used within a <BiometricProvider>. ' +\r\n 'Wrap your app with <BiometricProvider config={{...}}>.'\r\n );\r\n }\r\n return ctx;\r\n}\r\n\r\n/**\r\n * Provider that initializes and configures the Biometric SDK.\r\n * Wrap your application (or the section that uses biometric components) with this provider.\r\n *\r\n * @example\r\n * ```tsx\r\n * import { BiometricProvider } from '@intell/biometric-sdk';\r\n * \r\n * export default function Layout({ children }) {\r\n * return (\r\n * <BiometricProvider config={{\r\n * wsUrl: \"ws://localhost:5000/biometric\",\r\n * apiBaseUrl: \"http://localhost:8080/api/v1\",\r\n * deviceId: \"scanner_01\"\r\n * }}>\r\n * {children}\r\n * </BiometricProvider>\r\n * );\r\n * }\r\n * ```\r\n */\r\nexport function BiometricProvider({\r\n config,\r\n children,\r\n}: {\r\n config: BiometricConfig;\r\n children: React.ReactNode;\r\n}) {\r\n const initialized = useRef(false);\r\n\r\n useEffect(() => {\r\n if (!initialized.current) {\r\n initialized.current = true;\r\n useBiometricStore.getState().init(config.wsUrl, config.deviceId);\r\n }\r\n }, [config.wsUrl, config.deviceId]);\r\n\r\n return (\r\n <BiometricContext.Provider value={config}>\r\n {children}\r\n </BiometricContext.Provider>\r\n );\r\n}\r\n","import { create } from 'zustand';\r\nimport { useUiStore } from './uiStore';\r\n\r\nconst DEFAULT_WS_URL = \"ws://127.0.0.1:5000/biometric\";\r\nconst RECONNECT_DELAY = 3000;\r\n\r\nconst getOrCreateSessionId = (): string => {\r\n \r\n let sid = localStorage.getItem(\"bio_session_id\");\r\n\r\n \r\n if (!sid) {\r\n sid = typeof crypto !== 'undefined' && crypto.randomUUID\r\n ? crypto.randomUUID()\r\n : `sess_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\r\n\r\n localStorage.setItem(\"bio_session_id\", sid);\r\n }\r\n return sid;\r\n};\r\n\r\n\r\nexport type MessageHandler = (message: any) => void;\r\n\r\nexport interface SocketMessage {\r\n messageType: string;\r\n [key: string]: any;\r\n}\r\n\r\nexport interface DeviceStatus {\r\n fingerprintDevices: Array<{ deviceModel: string; status: string }>;\r\n irisDeviceOpen: boolean;\r\n}\r\n\r\nexport interface BiometricState {\r\n \r\n socket: WebSocket | null;\r\n isConnected: boolean;\r\n deviceStatus: DeviceStatus | null;\r\n\r\n \r\n \r\n lastMessage: SocketMessage | null;\r\n\r\n handlers: Map<string, MessageHandler>;\r\n\r\n \r\n missingFingers: Record<string, string>;\r\n markFingerAsMissing: (position: string, reason: string) => void;\r\n restoreFinger: (position: string) => void;\r\n clearAllMissingFingers: () => void;\r\n getExpectedFingers: (allPositions: string[]) => string[];\r\n\r\n \r\n init: (wsUrl?: string, deviceId?: string) => void;\r\n connect: () => void;\r\n disconnect: () => void;\r\n sendMessage: (message: object) => void;\r\n registerHandler: (messageType: string, handler: MessageHandler) => void;\r\n unregisterHandler: (messageType: string) => void;\r\n resetSession: () => void;\r\n}\r\n\r\nexport const useBiometricStore = create<BiometricState>((set, get) => ({\r\n \r\n socket: null,\r\n isConnected: false,\r\n deviceStatus: null,\r\n lastMessage: null, \r\n handlers: new Map(),\r\n missingFingers: {},\r\n\r\n \r\n \r\n \r\n markFingerAsMissing: (position, reason) => {\r\n const { missingFingers, sendMessage, isConnected } = get();\r\n const newMissing = { ...missingFingers, [position]: reason };\r\n\r\n set({ missingFingers: newMissing });\r\n\r\n if (isConnected) {\r\n console.log(\"📤 Sincronizando dedos faltantes con Backend...\", Object.keys(newMissing));\r\n sendMessage({\r\n messageType: \"UPDATE_MISSING_BIOMETRICS\",\r\n payload: Object.keys(newMissing)\r\n });\r\n }\r\n },\r\n\r\n restoreFinger: (position) => {\r\n const { missingFingers, sendMessage, isConnected } = get();\r\n const newMissing = { ...missingFingers };\r\n delete newMissing[position];\r\n\r\n set({ missingFingers: newMissing });\r\n\r\n if (isConnected) {\r\n console.log(\"📤 Sincronizando dedos faltantes con Backend...\", Object.keys(newMissing));\r\n sendMessage({\r\n messageType: \"UPDATE_MISSING_BIOMETRICS\",\r\n payload: Object.keys(newMissing)\r\n });\r\n }\r\n },\r\n\r\n getExpectedFingers: (allPositions) => {\r\n const { missingFingers } = get();\r\n return allPositions.filter(pos => !missingFingers[pos]);\r\n },\r\n\r\n clearAllMissingFingers: () => {\r\n const { isConnected, sendMessage } = get();\r\n set({ missingFingers: {} });\r\n\r\n if (isConnected) {\r\n console.log(\"🧹 Limpiando todas las excepciones biométricas...\");\r\n sendMessage({\r\n messageType: \"UPDATE_MISSING_BIOMETRICS\",\r\n payload: []\r\n });\r\n }\r\n },\r\n\r\n init: (wsUrl?: string, deviceId?: string) => {\r\n if (wsUrl && typeof window !== 'undefined') {\r\n localStorage.setItem('biometric_ws_url', wsUrl);\r\n }\r\n if (deviceId && typeof window !== 'undefined') {\r\n localStorage.setItem('biometric_device_id', deviceId);\r\n }\r\n get().connect();\r\n },\r\n\r\n registerHandler: (messageType, handler) => {\r\n get().handlers.set(messageType, handler);\r\n },\r\n\r\n unregisterHandler: (messageType) => {\r\n get().handlers.delete(messageType);\r\n },\r\n\r\n sendMessage: (message) => {\r\n const { socket, isConnected } = get();\r\n if (socket && isConnected) {\r\n socket.send(JSON.stringify(message));\r\n } else {\r\n useUiStore.getState().addMessage(\"Socket no conectado. Mensaje no enviado.\");\r\n console.error(\"Socket no conectado.\");\r\n }\r\n },\r\n\r\n disconnect: () => {\r\n const { socket } = get();\r\n if (socket) {\r\n socket.close();\r\n }\r\n set({ isConnected: false, socket: null });\r\n },\r\n\r\n resetSession: () => {\r\n localStorage.removeItem(\"bio_session_id\");\r\n get().disconnect();\r\n \r\n setTimeout(() => get().connect(), 500);\r\n },\r\n\r\n connect: () => {\r\n const { socket } = get();\r\n\r\n if (socket && (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING)) {\r\n return; \r\n }\r\n\r\n let baseUrl = DEFAULT_WS_URL;\r\n if (typeof window !== 'undefined') {\r\n const storedUrl = localStorage.getItem(\"biometric_ws_url\");\r\n if (storedUrl) {\r\n baseUrl = storedUrl;\r\n }\r\n }\r\n\r\n \r\n const sid = getOrCreateSessionId();\r\n \r\n const finalUrl = `${baseUrl.replace(/\\/$/, '')}?sid=${sid}`;\r\n\r\n const log = useUiStore.getState().addMessage;\r\n console.log(`Intentando conectar a: ${finalUrl}`);\r\n\r\n const ws = new WebSocket(finalUrl);\r\n\r\n ws.onopen = () => {\r\n log(`📡 Conexión establecida (Sesión: ${sid.substring(0, 8)}...)`);\r\n set({ isConnected: true, socket: ws });\r\n\r\n \r\n const { missingFingers } = get();\r\n const missingKeys = Object.keys(missingFingers);\r\n if (missingKeys.length > 0) {\r\n ws.send(JSON.stringify({\r\n messageType: \"UPDATE_MISSING_BIOMETRICS\",\r\n payload: missingKeys\r\n }));\r\n }\r\n };\r\n ws.onclose = (event) => {\r\n log(`🔌 Desconectado. Código: ${event.code}. Reconectando en 3s...`);\r\n set({ isConnected: false, socket: null });\r\n\r\n \r\n if (event.code !== 1000) {\r\n setTimeout(() => {\r\n get().connect();\r\n }, RECONNECT_DELAY);\r\n }\r\n };\r\n\r\n ws.onerror = (error) => {\r\n log(\"💥 Error en WebSocket. Ver consola.\");\r\n console.error(\"💥 Error en WebSocket:\", error);\r\n };\r\n\r\n ws.onmessage = (event) => {\r\n try {\r\n const message: SocketMessage = JSON.parse(event.data);\r\n\r\n \r\n \r\n \r\n if (!message.messageType.includes(\"_FRAME\")) {\r\n set({ lastMessage: message });\r\n }\r\n\r\n \r\n if (message.messageType === \"DEVICE_STATUS_UPDATE\") {\r\n set({ deviceStatus: message.payload });\r\n return;\r\n }\r\n\r\n \r\n const handler = get().handlers.get(message.messageType);\r\n\r\n if (handler) {\r\n handler(message);\r\n } else {\r\n \r\n if (message.messageType !== \"FINGER_PREVIEW_FRAME\" &&\r\n message.messageType !== \"FACE_QUALITY_FEEDBACK\" &&\r\n message.messageType !== \"PALM_PREVIEW_FRAME\" &&\r\n message.messageType !== \"IRIS_PREVIEW_FRAME\" &&\r\n message.messageType !== \"CURRENT_CONFIG\") {\r\n\r\n log(`Mensaje recibido sin handler: ${message.messageType}`);\r\n }\r\n }\r\n } catch (error) {\r\n log(\"Error al procesar mensaje.\");\r\n console.error(\"Error parsing JSON:\", error);\r\n }\r\n };\r\n\r\n set({ socket: ws });\r\n },\r\n}));\r\n\r\n\r\n","import { create } from 'zustand';\r\n\r\n// Límite de mensajes en la consola para evitar problemas de rendimiento\r\nconst MAX_MESSAGES = 100;\r\n\r\nexport interface UiState {\r\n messages: string[];\r\n isConsoleOpen: boolean;\r\n addMessage: (message: string) => void;\r\n toggleConsole: () => void;\r\n clearMessages: () => void;\r\n}\r\n\r\nexport const useUiStore = create<UiState>((set, get) => ({\r\n messages: [],\r\n isConsoleOpen: false,\r\n\r\n /**\r\n * Añade un nuevo mensaje de log a la consola global.\r\n */\r\n addMessage: (message: string) => {\r\n const timestamp = new Date().toLocaleTimeString();\r\n const formattedMessage = `[${timestamp}] ${message}`;\r\n\r\n set((state) => ({\r\n messages: [\r\n ...state.messages.slice(\r\n state.messages.length >= MAX_MESSAGES ? 1 : 0\r\n ),\r\n formattedMessage,\r\n ],\r\n }));\r\n },\r\n\r\n /**\r\n * Abre o cierra la consola de eventos.\r\n */\r\n toggleConsole: () => {\r\n set((state) => ({ isConsoleOpen: !state.isConsoleOpen }));\r\n },\r\n\r\n /**\r\n * Limpia todos los mensajes de la consola.\r\n */\r\n clearMessages: () => {\r\n set({ messages: [] });\r\n },\r\n}));","\"use client\";\r\n\r\nimport { useState, useEffect, useMemo, useRef } from \"react\";\r\nimport { toast } from \"react-hot-toast\";\r\nimport { useBiometricStore } from \"../../lib/stores/biometricStore\";\r\nimport { useUiStore } from \"../../lib/stores/uiStore\";\r\nimport { useEnrollmentStore } from \"../../lib/stores/enrollmentStore\";\r\nimport { BiometricSlot } from \"../ui/BiometricSlot\";\r\nimport { MissingFingerModal } from \"../ui/MissingFingerModal\";\r\nimport { ModuleHeader } from \"./ModuleHeader\";\r\nimport { Button } from \"../ui/Button\";\r\nimport { Select } from \"../ui/Select\";\r\nimport { FingerCaptureModal } from \"./FingerCaptureModal\";\r\nimport { TbSend, TbReload, TbFingerprint, TbHandClick } from \"react-icons/tb\";\r\nimport {\r\n FINGER_NAMES,\r\n RIGHT_FINGERS,\r\n LEFT_FINGERS,\r\n} from \"../../lib/constants/fingerPositions\";\r\nimport {\r\n getImageSrcForDisplay,\r\n normalizeImageForStorage,\r\n} from \"../../lib/utils/imageHelpers\";\r\n\r\nenum CaptureMode {\r\n Mode1_1 = \"MODE_1_1\",\r\n Mode2_2 = \"MODE_2_2\",\r\n Mode4_4_2 = \"MODE_4_4_2\",\r\n}\r\n\r\nconst CAPTURE_GROUPS_4_4_2 = [\r\n { label: \"Mano Derecha (4 dedos)\", backendMode: \"RightSlap4\" },\r\n { label: \"Mano Izquierda (4 dedos)\", backendMode: \"LeftSlap4\" },\r\n { label: \"Pulgares (2 dedos)\", backendMode: \"Thumbs2\" },\r\n];\r\n\r\nconst CAPTURE_GROUPS_2_2 = [\r\n { label: \"Índice y Medio Der.\", backendMode: \"RightIndexMiddle\" },\r\n { label: \"Anular y Meñique Der.\", backendMode: \"RightRingLittle\" },\r\n { label: \"Índice y Medio Izq.\", backendMode: \"LeftIndexMiddle\" },\r\n { label: \"Anular y Meñique Izq.\", backendMode: \"LeftRingLittle\" },\r\n { label: \"Ambos Pulgares\", backendMode: \"Thumbs2\" },\r\n];\r\n\r\nconst getFingersForMode = (backendMode: string): string[] => {\r\n switch (backendMode) {\r\n case \"RightSlap4\":\r\n return [\"RIGHT_INDEX\", \"RIGHT_MIDDLE\", \"RIGHT_RING\", \"RIGHT_LITTLE\"];\r\n case \"LeftSlap4\":\r\n return [\"LEFT_INDEX\", \"LEFT_MIDDLE\", \"LEFT_RING\", \"LEFT_LITTLE\"];\r\n case \"Thumbs2\":\r\n return [\"RIGHT_THUMB\", \"LEFT_THUMB\"];\r\n case \"RightIndexMiddle\":\r\n return [\"RIGHT_INDEX\", \"RIGHT_MIDDLE\"];\r\n case \"RightRingLittle\":\r\n return [\"RIGHT_RING\", \"RIGHT_LITTLE\"];\r\n case \"LeftIndexMiddle\":\r\n return [\"LEFT_INDEX\", \"LEFT_MIDDLE\"];\r\n case \"LeftRingLittle\":\r\n return [\"LEFT_RING\", \"LEFT_LITTLE\"];\r\n default:\r\n return [];\r\n }\r\n};\r\n\r\ninterface FingerResult {\r\n Finger: string;\r\n Quality: number;\r\n Image: string;\r\n Error?: string | null;\r\n}\r\n\r\ntype FingerResultsMap = Record<string, FingerResult>;\r\n\r\nexport default function FingerEnrollModule({ className = \"\" }: { className?: string }) {\r\n const {\r\n addFingerprint,\r\n addMissingFinger,\r\n removeMissingFinger,\r\n removeFingerprint,\r\n fingerprints: storeFingerprints,\r\n missingFingers: enrollmentMissingFingers,\r\n } = useEnrollmentStore();\r\n const [fingerResults, setFingerResults] = useState<FingerResultsMap>({});\r\n const [selectedMode, setSelectedMode] = useState<CaptureMode>(\r\n CaptureMode.Mode4_4_2,\r\n );\r\n\r\n const [isModalOpen, setIsModalOpen] = useState(false);\r\n const isModalOpenRef = useRef(isModalOpen);\r\n const [isProcessing, setIsProcessing] = useState(false);\r\n const [currentCaptureInfo, setCurrentCaptureInfo] = useState<any>(null);\r\n const [previewImage, setPreviewImage] = useState<string | null>(null);\r\n const [previewQuality, setPreviewQuality] = useState<number | null>(null);\r\n const [fingerToMarkMissing, setFingerToMarkMissing] = useState<string | null>(\r\n null,\r\n );\r\n\r\n const {\r\n isConnected,\r\n sendMessage,\r\n registerHandler,\r\n unregisterHandler,\r\n getExpectedFingers,\r\n markFingerAsMissing,\r\n restoreFinger,\r\n missingFingers,\r\n clearAllMissingFingers,\r\n } = useBiometricStore();\r\n\r\n const addMessage = useUiStore((s) => s.addMessage);\r\n\r\n useEffect(() => {\r\n const loaded: FingerResultsMap = {};\r\n Object.entries(storeFingerprints).forEach(([key, item]) => {\r\n loaded[key] = {\r\n Finger: key,\r\n Quality: item.quality,\r\n Image: item.image,\r\n Error: null,\r\n };\r\n });\r\n setFingerResults((prev) => ({ ...prev, ...loaded }));\r\n }, [storeFingerprints]);\r\n\r\n const allMissingFingers = useMemo(\r\n () => ({ ...enrollmentMissingFingers, ...missingFingers }),\r\n [enrollmentMissingFingers, missingFingers],\r\n );\r\n\r\n const capturedCount = useMemo(() => {\r\n const successCount = Object.values(fingerResults).filter(\r\n (r) => r && r.Quality >= 40 && !r.Error,\r\n ).length;\r\n const missingCount = Object.keys(allMissingFingers).length;\r\n return successCount + missingCount;\r\n }, [fingerResults, allMissingFingers]);\r\n\r\n const isCapturing = isProcessing || isModalOpen;\r\n\r\n const modeOptions = [\r\n { value: CaptureMode.Mode4_4_2, label: \"4–4–2 (Estándar)\", icon: \"👋\" },\r\n { value: CaptureMode.Mode2_2, label: \"2–2 (Pares)\", icon: \"✌️\" },\r\n { value: CaptureMode.Mode1_1, label: \"1–1 (Individual)\", icon: \"☝️\" },\r\n ];\r\n\r\n useEffect(() => {\r\n isModalOpenRef.current = isModalOpen;\r\n }, [isModalOpen]);\r\n\r\n useEffect(() => {\r\n const handlePreview = (data: any) => {\r\n if (!isModalOpenRef.current) return;\r\n setPreviewImage(data.biometricData?.capturedImage || null);\r\n setPreviewQuality(data.biometricData?.quality || null);\r\n };\r\n\r\n const handleComplete = (data: any) => {\r\n setIsModalOpen(false);\r\n setIsProcessing(false);\r\n setCurrentCaptureInfo(null);\r\n setPreviewImage(null);\r\n setPreviewQuality(null);\r\n\r\n const segments = data.biometricData?.segments;\r\n if (Array.isArray(segments)) {\r\n const newRes: FingerResultsMap = {};\r\n for (const seg of segments) {\r\n if (seg.finger) {\r\n newRes[seg.finger] = {\r\n Finger: seg.finger,\r\n Quality: seg.quality,\r\n Image: seg.image,\r\n Error: null,\r\n };\r\n addMessage(\r\n `Huella ${FINGER_NAMES[seg.finger]} capturada (${seg.quality}).`,\r\n );\r\n }\r\n }\r\n setFingerResults((prev) => ({ ...prev, ...newRes }));\r\n toast.success(\"Captura completada\");\r\n }\r\n };\r\n\r\n const handleError = (data: any) => {\r\n toast.error(data.error || data.messageType || \"Error desconocido\");\r\n addMessage(`Error captura: ${data.error}`);\r\n setIsModalOpen(false);\r\n setIsProcessing(false);\r\n setPreviewImage(null);\r\n setPreviewQuality(null);\r\n };\r\n\r\n const handleEnrollment = (data: any) => {\r\n setIsProcessing(false);\r\n const wsqs = data.biometricData?.wsqFiles || {};\r\n const count = Object.keys(wsqs).length;\r\n\r\n Object.entries(wsqs).forEach(([pos, base64]) => {\r\n const fingerInfo = fingerResults[pos];\r\n const imageToSave = fingerInfo?.Image || (base64 as string);\r\n const normalizedImage = normalizeImageForStorage(imageToSave);\r\n addFingerprint(pos, normalizedImage, fingerInfo?.Quality || 100);\r\n });\r\n\r\n Object.entries(missingFingers).forEach(([pos, reason]) => {\r\n addMissingFinger(pos, reason as string);\r\n });\r\n\r\n addMessage(`Procesamiento finalizado. ${count} huellas listas.`);\r\n toast.success(\"Huellas planas guardadas\");\r\n };\r\n\r\n registerHandler(\"FINGER_PREVIEW_FRAME\", handlePreview);\r\n registerHandler(\"FINGER_CAPTURE_COMPLETE\", handleComplete);\r\n registerHandler(\"ENROLLMENT_COMPLETE\", handleEnrollment);\r\n registerHandler(\"FINGER_QUALITY_LOW\", handleError);\r\n registerHandler(\"DUPLICATE_FINGER\", handleError);\r\n registerHandler(\"FINGER_ERROR\", handleError);\r\n registerHandler(\"ERROR_DEVICE_BUSY\", handleError);\r\n registerHandler(\"ERROR_DEVICE_NOT_FOUND\", handleError);\r\n registerHandler(\"ERROR_CAPTURE_FAILED\", handleError);\r\n registerHandler(\"ERROR\", handleError);\r\n\r\n return () => {\r\n unregisterHandler(\"FINGER_PREVIEW_FRAME\");\r\n unregisterHandler(\"FINGER_CAPTURE_COMPLETE\");\r\n unregisterHandler(\"ENROLLMENT_COMPLETE\");\r\n unregisterHandler(\"FINGER_QUALITY_LOW\");\r\n unregisterHandler(\"DUPLICATE_FINGER\");\r\n unregisterHandler(\"FINGER_ERROR\");\r\n unregisterHandler(\"ERROR_DEVICE_BUSY\");\r\n unregisterHandler(\"ERROR_DEVICE_NOT_FOUND\");\r\n unregisterHandler(\"ERROR_CAPTURE_FAILED\");\r\n unregisterHandler(\"ERROR\");\r\n };\r\n }, [\r\n registerHandler,\r\n unregisterHandler,\r\n addMessage,\r\n addFingerprint,\r\n addMissingFinger,\r\n missingFingers,\r\n fingerResults,\r\n ]);\r\n\r\n const startCapture = (mode: string, info: any) => {\r\n if (!isConnected) {\r\n toast.error(\"Servicio no conectado.\");\r\n return;\r\n }\r\n if (isProcessing) return;\r\n\r\n let fingersAttempting: string[] = [];\r\n if (info.type === CaptureMode.Mode1_1) {\r\n fingersAttempting = [info.targetFinger];\r\n } else {\r\n fingersAttempting = getFingersForMode(mode);\r\n }\r\n\r\n const fingersWithoutEnrollmentMissing = fingersAttempting.filter(\r\n (f) => !enrollmentMissingFingers[f],\r\n );\r\n const expectedFingers = getExpectedFingers(fingersWithoutEnrollmentMissing);\r\n\r\n if (expectedFingers.length === 0) {\r\n const msg =\r\n \"Todos los dedos de este grupo están marcados como omitidos/faltantes.\";\r\n toast.error(msg);\r\n addMessage(msg);\r\n return;\r\n }\r\n\r\n setIsProcessing(true);\r\n setIsModalOpen(true);\r\n setCurrentCaptureInfo(info);\r\n setPreviewImage(null);\r\n setPreviewQuality(null);\r\n\r\n sendMessage({\r\n messageType: \"START_FINGER_CAPTURE\",\r\n biometricData: {\r\n mode,\r\n targetFinger: info?.targetFinger || null,\r\n expectedFingers: expectedFingers,\r\n },\r\n });\r\n addMessage(`Iniciando captura: ${mode}.`);\r\n };\r\n\r\n const cancelCapture = () => {\r\n sendMessage({ messageType: \"ABORT_FINGER_CAPTURE\" });\r\n setIsModalOpen(false);\r\n setIsProcessing(false);\r\n setPreviewImage(null);\r\n setPreviewQuality(null);\r\n addMessage(\"Captura cancelada.\");\r\n };\r\n\r\n const processBatch = () => {\r\n if (capturedCount < 10) {\r\n const msg = `Faltan dedos por procesar (${capturedCount}/10).`;\r\n toast.error(msg);\r\n return;\r\n }\r\n setIsProcessing(true);\r\n addMessage(\"Procesando huellas capturadas...\");\r\n sendMessage({ messageType: \"FINALIZE_ENROLLMENT\" });\r\n };\r\n\r\n const resetAll = () => {\r\n setFingerResults({});\r\n setIsProcessing(false);\r\n clearAllMissingFingers();\r\n addMessage(\"Módulo reiniciado.\");\r\n };\r\n\r\n const handleConfirmMissing = (reason: string) => {\r\n if (fingerToMarkMissing) {\r\n markFingerAsMissing(fingerToMarkMissing, reason);\r\n addMissingFinger(fingerToMarkMissing, reason);\r\n setFingerResults((prev) => {\r\n const next = { ...prev };\r\n delete next[fingerToMarkMissing];\r\n return next;\r\n });\r\n removeFingerprint(fingerToMarkMissing);\r\n addMessage(`Dedo ${fingerToMarkMissing} marcado como: ${reason}`);\r\n setFingerToMarkMissing(null);\r\n }\r\n };\r\n\r\n const renderFingerGrid = (fingers: string[]) =>\r\n fingers.map((f) => {\r\n const res = fingerResults[f];\r\n const missing = allMissingFingers[f] || null;\r\n return (\r\n <BiometricSlot\r\n key={f}\r\n position={f}\r\n title={FINGER_NAMES[f].split(\" \")[0]}\r\n status={res ? (res.Error ? \"error\" : \"captured\") : \"pending\"}\r\n imageUrl={getImageSrcForDisplay(res?.Image, \"png\")}\r\n quality={res?.Quality}\r\n iconType=\"finger\"\r\n missingReason={missing}\r\n onCapture={() =>\r\n startCapture(\"SingleFinger\", {\r\n type: CaptureMode.Mode1_1,\r\n targetFinger: f,\r\n label: FINGER_NAMES[f],\r\n })\r\n }\r\n onRequestMissing={() => setFingerToMarkMissing(f)}\r\n onRestore={() => {\r\n removeMissingFinger(f);\r\n if (missingFingers[f]) restoreFinger(f);\r\n }}\r\n onDelete={() => {\r\n removeFingerprint(f);\r\n setFingerResults((prev) => {\r\n const next = { ...prev };\r\n delete next[f];\r\n return next;\r\n });\r\n }}\r\n isDisabled={isCapturing || !isConnected}\r\n />\r\n );\r\n });\r\n\r\n return (\r\n <div className=\"space-y-8 animate-in fade-in duration-500\">\r\n <ModuleHeader\r\n icon={<TbFingerprint size={24} />}\r\n title=\"Huellas Planas\"\r\n subtitle=\"Capture las 10 huellas digitales (Slaps).\"\r\n progress={{ current: capturedCount, total: 10 }}\r\n >\r\n <Button\r\n variant=\"success\"\r\n size=\"sm\"\r\n icon={<TbSend size={16} />}\r\n onClick={processBatch}\r\n disabled={!isConnected || isCapturing || capturedCount < 10}\r\n isLoading={isProcessing}\r\n >\r\n Guardar\r\n </Button>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n icon={<TbReload size={16} />}\r\n onClick={resetAll}\r\n disabled={isCapturing}\r\n >\r\n Limpiar\r\n </Button>\r\n </ModuleHeader>\r\n\r\n <div className=\"flex flex-col lg:flex-row gap-4 items-stretch lg:items-center bg-secondary/30 p-4 rounded-md border border-white/5\">\r\n <div className=\"flex flex-col sm:flex-row items-start sm:items-center gap-3 flex-1\">\r\n <label className=\"text-xs font-bold uppercase tracking-wider text-foreground/50 min-w-max\">\r\n Modo:\r\n </label>\r\n <div className=\"w-full sm:max-w-xs\">\r\n <Select\r\n options={modeOptions}\r\n value={selectedMode}\r\n onChange={(val) => setSelectedMode(val as CaptureMode)}\r\n disabled={isCapturing}\r\n />\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex gap-3 w-full sm:w-auto flex-wrap\">\r\n {(selectedMode === CaptureMode.Mode4_4_2\r\n ? CAPTURE_GROUPS_4_4_2\r\n : selectedMode === CaptureMode.Mode2_2\r\n ? CAPTURE_GROUPS_2_2\r\n : []\r\n ).map((g) => (\r\n <button\r\n key={g.label}\r\n disabled={!isConnected || isCapturing}\r\n onClick={() =>\r\n startCapture(g.backendMode, {\r\n type: selectedMode,\r\n label: g.label,\r\n })\r\n }\r\n className=\"flex items-center gap-2 px-4 py-2.5 rounded-md bg-background border border-border/60 text-foreground/70 font-medium text-xs hover:border-primary hover:text-primary hover:bg-primary/5 active:scale-95 transition-all duration-200 disabled:opacity-50\"\r\n >\r\n <TbHandClick size={16} /> {g.label}\r\n </button>\r\n ))}\r\n {selectedMode === CaptureMode.Mode1_1 && (\r\n <p className=\"text-sm text-foreground/50 italic py-2\">\r\n Seleccione un dedo abajo para capturar individualmente.\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n\r\n <div className=\"grid grid-cols-1 xl:grid-cols-2 gap-8\">\r\n <div className=\"glass p-6 rounded-sm border border-white/10 relative overflow-hidden group\">\r\n <div className=\"absolute top-0 right-0 p-4 opacity-5 group-hover:opacity-10 transition-opacity\">\r\n <TbFingerprint size={120} />\r\n </div>\r\n <h3 className=\"text-lg font-bold text-foreground mb-5 pl-3 border-l-4 border-primary\">\r\n Mano Derecha\r\n </h3>\r\n <div className=\"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-4\">\r\n {renderFingerGrid(RIGHT_FINGERS)}\r\n </div>\r\n </div>\r\n\r\n <div className=\"glass p-6 rounded-sm border border-white/10 relative overflow-hidden group\">\r\n <div className=\"absolute top-0 right-0 p-4 opacity-5 group-hover:opacity-10 transition-opacity\">\r\n <TbFingerprint size={120} />\r\n </div>\r\n <h3 className=\"text-lg font-bold text-foreground mb-5 pl-3 border-l-4 border-secondary-foreground/50\">\r\n Mano Izquierda\r\n </h3>\r\n <div className=\"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-4\">\r\n {renderFingerGrid(LEFT_FINGERS)}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <FingerCaptureModal\r\n isOpen={isModalOpen}\r\n onCancel={cancelCapture}\r\n captureType={currentCaptureInfo?.label || \"Captura de huella\"}\r\n previewImage={previewImage}\r\n previewQuality={previewQuality}\r\n />\r\n\r\n <MissingFingerModal\r\n isOpen={!!fingerToMarkMissing}\r\n onClose={() => setFingerToMarkMissing(null)}\r\n onConfirm={handleConfirmMissing}\r\n positionName={\r\n fingerToMarkMissing ? FINGER_NAMES[fingerToMarkMissing] : \"\"\r\n }\r\n />\r\n </div>\r\n );\r\n}\r\n","import { create } from \"zustand\";\r\nimport {\r\n EnrollApplicantRequest,\r\n FingerprintPosition,\r\n FingerprintImpressionType,\r\n IrisPosition,\r\n MissingFaceItem,\r\n MissingIrisItem,\r\n} from \"../../types/abis-types\";\r\nimport {\r\n normalizeImageForStorage,\r\n isRemoteImage,\r\n downloadImageAsBase64,\r\n} from \"../utils/imageHelpers\";\r\n\r\nexport interface BiometricItem {\r\n image: string;\r\n quality: number;\r\n impressionType?: string; // Agregado para persistir el tipo exacto\r\n}\r\n\r\nexport interface OriginalSnapshot {\r\n fingerprints: Record<string, BiometricItem>;\r\n rolledFingerprints: Record<string, BiometricItem>;\r\n missingFingers: Record<string, string>;\r\n palms: Record<string, BiometricItem>;\r\n missingPalms: Record<string, string>;\r\n faces: BiometricItem[];\r\n faceCaptures: (BiometricItem | null)[];\r\n missingFaces: Record<number, string>;\r\n irises: { right?: BiometricItem; left?: BiometricItem };\r\n missingIrises: Record<string, string>;\r\n}\r\n\r\nexport interface EnrollmentState {\r\n externalId: string;\r\n fullName: string;\r\n isUpdateMode: boolean;\r\n isLoading: boolean;\r\n\r\n fingerprints: Record<string, BiometricItem>;\r\n rolledFingerprints: Record<string, BiometricItem>;\r\n missingFingers: Record<string, string>;\r\n palms: Record<string, BiometricItem>;\r\n missingPalms: Record<string, string>;\r\n faces: BiometricItem[];\r\n faceCaptures: (BiometricItem | null)[];\r\n missingFaces: Record<number, string>;\r\n irises: {\r\n right?: BiometricItem;\r\n left?: BiometricItem;\r\n };\r\n missingIrises: Record<string, string>;\r\n\r\n _originalSnapshot: OriginalSnapshot | null;\r\n\r\n setDemographics: (id: string, name: string) => void;\r\n\r\n addFingerprint: (pos: string, image: string, quality?: number) => void;\r\n addRolledFingerprint: (pos: string, image: string, quality?: number) => void;\r\n removeFingerprint: (pos: string) => void;\r\n removeRolledFingerprint: (pos: string) => void;\r\n addMissingFinger: (pos: string, reason: string) => void;\r\n removeMissingFinger: (pos: string) => void;\r\n\r\n addPalm: (pos: string, image: string, quality?: number) => void;\r\n removePalm: (pos: string) => void;\r\n addMissingPalm: (pos: string, reason: string) => void;\r\n removeMissingPalm: (pos: string) => void;\r\n\r\n setFaces: (items: { image: string; quality: number }[]) => void;\r\n setFaceCaptures: (\r\n items: ({ image: string; quality: number } | null)[],\r\n ) => void;\r\n removeFace: (index: number) => void;\r\n addMissingFace: (index: number, reason: string) => void;\r\n removeMissingFace: (index: number) => void;\r\n\r\n setIrises: (\r\n right?: { image: string; quality: number },\r\n left?: { image: string; quality: number },\r\n ) => void;\r\n removeIris: (side: \"left\" | \"right\") => void;\r\n addMissingIris: (side: string, reason: string) => void;\r\n removeMissingIris: (side: string) => void;\r\n\r\n loadApplicantData: (data: any) => Promise<void>;\r\n buildEnrollmentRequest: () => EnrollApplicantRequest;\r\n buildUpdateRequest: () => Partial<EnrollApplicantRequest>;\r\n getDirtyModalities: () => Set<string>;\r\n resetEnrollment: () => void;\r\n}\r\n\r\nconst FINGER_MAP_INV: Record<string, string> = {\r\n RightThumb: \"RIGHT_THUMB\",\r\n RightIndex: \"RIGHT_INDEX\",\r\n RightMiddle: \"RIGHT_MIDDLE\",\r\n RightRing: \"RIGHT_RING\",\r\n RightLittle: \"RIGHT_LITTLE\",\r\n LeftThumb: \"LEFT_THUMB\",\r\n LeftIndex: \"LEFT_INDEX\",\r\n LeftMiddle: \"LEFT_MIDDLE\",\r\n LeftRing: \"LEFT_RING\",\r\n LeftLittle: \"LEFT_LITTLE\",\r\n};\r\n\r\nconst PALM_MAP_INV: Record<string, string> = {\r\n RightUpperPalm: \"UPPERPALMRIGHT\",\r\n RightLowerPalm: \"LOWERPALMRIGHT\",\r\n RightWritersPalm: \"WRITERSPALMRIGHT\",\r\n LeftUpperPalm: \"UPPERPALMLEFT\",\r\n LeftLowerPalm: \"LOWERPALMLEFT\",\r\n LeftWritersPalm: \"WRITERSPALMLEFT\",\r\n};\r\n\r\nconst FINGER_MAP: Record<string, FingerprintPosition> = {\r\n RIGHT_THUMB: FingerprintPosition.RightThumb,\r\n RIGHT_INDEX: FingerprintPosition.RightIndex,\r\n RIGHT_MIDDLE: FingerprintPosition.RightMiddle,\r\n RIGHT_RING: FingerprintPosition.RightRing,\r\n RIGHT_LITTLE: FingerprintPosition.RightLittle,\r\n LEFT_THUMB: FingerprintPosition.LeftThumb,\r\n LEFT_INDEX: FingerprintPosition.LeftIndex,\r\n LEFT_MIDDLE: FingerprintPosition.LeftMiddle,\r\n LEFT_RING: FingerprintPosition.LeftRing,\r\n LEFT_LITTLE: FingerprintPosition.LeftLittle,\r\n};\r\n\r\nconst PALM_MAP: Record<string, FingerprintPosition> = {\r\n UPPERPALMLEFT: FingerprintPosition.LeftUpperPalm,\r\n LOWERPALMLEFT: FingerprintPosition.LeftLowerPalm,\r\n WRITERSPALMLEFT: FingerprintPosition.LeftWritersPalm,\r\n UPPERPALMRIGHT: FingerprintPosition.RightUpperPalm,\r\n LOWERPALMRIGHT: FingerprintPosition.RightLowerPalm,\r\n WRITERSPALMRIGHT: FingerprintPosition.RightWritersPalm,\r\n};\r\n\r\n// DEPRECATED: Usar normalizeImageForStorage() del helper centralizado\r\n// Mantenido por compatibilidad, ahora es un alias\r\nconst cleanBase64 = normalizeImageForStorage;\r\n\r\nexport const useEnrollmentStore = create<EnrollmentState>((set, get) => ({\r\n externalId: \"\",\r\n fullName: \"\",\r\n isUpdateMode: false,\r\n isLoading: false,\r\n fingerprints: {},\r\n rolledFingerprints: {},\r\n missingFingers: {},\r\n palms: {},\r\n missingPalms: {},\r\n faces: [],\r\n faceCaptures: Array(5).fill(null),\r\n missingFaces: {},\r\n irises: {},\r\n missingIrises: {},\r\n _originalSnapshot: null,\r\n\r\n setDemographics: (id, name) => set({ externalId: id, fullName: name }),\r\n\r\n addFingerprint: (pos, image, quality = 100) =>\r\n set((state) => {\r\n const nextMissing = { ...state.missingFingers };\r\n delete nextMissing[pos];\r\n return {\r\n fingerprints: {\r\n ...state.fingerprints,\r\n [pos]: { image, quality, impressionType: \"LiveScanPlain\" },\r\n },\r\n missingFingers: nextMissing,\r\n };\r\n }),\r\n\r\n addRolledFingerprint: (pos, image, quality = 100) =>\r\n set((state) => {\r\n const nextMissing = { ...state.missingFingers };\r\n delete nextMissing[pos];\r\n return {\r\n rolledFingerprints: {\r\n ...state.rolledFingerprints,\r\n [pos]: { image, quality, impressionType: \"RolledContact\" },\r\n },\r\n missingFingers: nextMissing,\r\n };\r\n }),\r\n\r\n removeFingerprint: (pos) =>\r\n set((state) => {\r\n const next = { ...state.fingerprints };\r\n delete next[pos];\r\n return { fingerprints: next };\r\n }),\r\n\r\n removeRolledFingerprint: (pos) =>\r\n set((state) => {\r\n const next = { ...state.rolledFingerprints };\r\n delete next[pos];\r\n return { rolledFingerprints: next };\r\n }),\r\n\r\n addMissingFinger: (pos, reason) =>\r\n set((state) => {\r\n const nextFingers = { ...state.fingerprints };\r\n const nextRolled = { ...state.rolledFingerprints };\r\n delete nextFingers[pos];\r\n delete nextRolled[pos];\r\n return {\r\n missingFingers: { ...state.missingFingers, [pos]: reason },\r\n fingerprints: nextFingers,\r\n rolledFingerprints: nextRolled,\r\n };\r\n }),\r\n\r\n removeMissingFinger: (pos) =>\r\n set((state) => {\r\n const next = { ...state.missingFingers };\r\n delete next[pos];\r\n return { missingFingers: next };\r\n }),\r\n\r\n addPalm: (pos, image, quality = 100) =>\r\n set((state) => {\r\n const nextMissing = { ...state.missingPalms };\r\n delete nextMissing[pos];\r\n return {\r\n palms: {\r\n ...state.palms,\r\n [pos]: { image, quality, impressionType: \"LiveScanPalm\" },\r\n },\r\n missingPalms: nextMissing,\r\n };\r\n }),\r\n\r\n removePalm: (pos) =>\r\n set((state) => {\r\n const next = { ...state.palms };\r\n delete next[pos];\r\n return { palms: next };\r\n }),\r\n\r\n addMissingPalm: (pos, reason) =>\r\n set((state) => {\r\n const nextPalms = { ...state.palms };\r\n delete nextPalms[pos];\r\n return {\r\n missingPalms: { ...state.missingPalms, [pos]: reason },\r\n palms: nextPalms,\r\n };\r\n }),\r\n\r\n removeMissingPalm: (pos) =>\r\n set((state) => {\r\n const next = { ...state.missingPalms };\r\n delete next[pos];\r\n return { missingPalms: next };\r\n }),\r\n\r\n setFaces: (items) => set({ faces: items }),\r\n setFaceCaptures: (items) => set({ faceCaptures: items }),\r\n\r\n removeFace: (index) =>\r\n set((state) => {\r\n const nextCaptures = [...state.faceCaptures];\r\n nextCaptures[index] = null;\r\n const nextFaces = state.faces.filter((_, i) => i !== index);\r\n return { faceCaptures: nextCaptures, faces: nextFaces };\r\n }),\r\n\r\n addMissingFace: (index, reason) =>\r\n set((state) => {\r\n const nextCaptures = [...state.faceCaptures];\r\n nextCaptures[index] = null;\r\n const nextFaces = state.faces.filter((_, i) => i !== index);\r\n return {\r\n missingFaces: { ...state.missingFaces, [index]: reason },\r\n faceCaptures: nextCaptures,\r\n faces: nextFaces,\r\n };\r\n }),\r\n\r\n removeMissingFace: (index) =>\r\n set((state) => {\r\n const next = { ...state.missingFaces };\r\n delete next[index];\r\n return { missingFaces: next };\r\n }),\r\n\r\n setIrises: (right, left) =>\r\n set((state) => {\r\n const nextMissing = { ...state.missingIrises };\r\n if (right) delete nextMissing.right;\r\n if (left) delete nextMissing.left;\r\n return { irises: { right, left }, missingIrises: nextMissing };\r\n }),\r\n\r\n removeIris: (side) =>\r\n set((state) => {\r\n const next = { ...state.irises };\r\n if (side === \"left\") delete next.left;\r\n if (side === \"right\") delete next.right;\r\n return { irises: next };\r\n }),\r\n\r\n addMissingIris: (side, reason) =>\r\n set((state) => {\r\n const nextIrises = { ...state.irises };\r\n if (side === \"left\") delete nextIrises.left;\r\n if (side === \"right\") delete nextIrises.right;\r\n return {\r\n missingIrises: { ...state.missingIrises, [side]: reason },\r\n irises: nextIrises,\r\n };\r\n }),\r\n\r\n removeMissingIris: (side) =>\r\n set((state) => {\r\n const next = { ...state.missingIrises };\r\n delete next[side];\r\n return { missingIrises: next };\r\n }),\r\n\r\n resetEnrollment: () =>\r\n set({\r\n externalId: \"\",\r\n fullName: \"\",\r\n isUpdateMode: false,\r\n fingerprints: {},\r\n rolledFingerprints: {},\r\n missingFingers: {},\r\n palms: {},\r\n missingPalms: {},\r\n faces: [],\r\n faceCaptures: Array(5).fill(null),\r\n missingFaces: {},\r\n irises: {},\r\n missingIrises: {},\r\n _originalSnapshot: null,\r\n }),\r\n\r\n loadApplicantData: async (data: any) => {\r\n set({ isLoading: true });\r\n try {\r\n\r\n const updates: Partial<EnrollmentState> = {\r\n externalId: data.externalId,\r\n fullName: data.customDetails?.fullName || \"Solicitante\",\r\n isUpdateMode: true,\r\n fingerprints: {},\r\n rolledFingerprints: {},\r\n missingFingers: {},\r\n palms: {},\r\n missingPalms: {},\r\n faces: [],\r\n faceCaptures: Array(5).fill(null),\r\n missingFaces: {},\r\n irises: {},\r\n missingIrises: {},\r\n };\r\n\r\n // Mapeo de Huellas y Palmas\r\n if (data.fingerprintModality?.fingerprints) {\r\n for (const fp of data.fingerprintModality.fingerprints) {\r\n // 1. Intentar mapear como Dedo\r\n let internalPos = FINGER_MAP_INV[fp.position];\r\n let isPalm = false;\r\n\r\n // 2. Si no es dedo, intentar como Palma\r\n if (!internalPos) {\r\n internalPos = PALM_MAP_INV[fp.position];\r\n isPalm = true;\r\n }\r\n\r\n if (!internalPos) continue; // No reconocido\r\n\r\n // Preferir dataBytes (base64); si solo hay dataUrl (HTTP), descargar\r\n let rawImage = fp.image.dataBytes || \"\";\r\n if (\r\n !rawImage &&\r\n fp.image.dataUrl &&\r\n isRemoteImage(fp.image.dataUrl)\r\n ) {\r\n try {\r\n rawImage = await downloadImageAsBase64(fp.image.dataUrl);\r\n } catch (e) {\r\n console.warn(`No se pudo descargar imagen de ${fp.position}:`, e);\r\n rawImage = fp.image.dataUrl; // fallback a URL\r\n }\r\n } else if (!rawImage && fp.image.dataUrl) {\r\n rawImage = fp.image.dataUrl;\r\n }\r\n const imageSrc = normalizeImageForStorage(rawImage);\r\n\r\n // Preferir display.quality (0-100), fallback a image qualities\r\n const qualityVal =\r\n fp.display?.quality ??\r\n fp.image.qualities?.placement ??\r\n fp.image.qualities?.imageQuality ??\r\n 0;\r\n\r\n // Detectar tipo de impresión para evitar colisiones\r\n const impression = fp.impressionType || \"Unknown\";\r\n\r\n const item: BiometricItem = {\r\n image: imageSrc,\r\n quality: qualityVal,\r\n impressionType: impression,\r\n };\r\n\r\n if (isPalm) {\r\n updates.palms![internalPos] = item;\r\n } else {\r\n // Lógica estricta para separar Roladas de Planas\r\n const impressionLower = impression.toLowerCase();\r\n const isRolled = impressionLower.includes(\"rolled\");\r\n\r\n if (isRolled) {\r\n updates.rolledFingerprints![internalPos] = item;\r\n } else {\r\n // Asumimos plana si no dice explícitamente rolled\r\n updates.fingerprints![internalPos] = item;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Mapeo de Huellas y Palmas Faltantes\r\n if (data.fingerprintModality?.missingFingerprints) {\r\n data.fingerprintModality.missingFingerprints.forEach((mf: any) => {\r\n const fingerPos = FINGER_MAP_INV[mf.position];\r\n if (fingerPos) {\r\n updates.missingFingers![fingerPos] = mf.missingReasonText || \"Amputación\";\r\n if (updates.fingerprints) delete updates.fingerprints[fingerPos];\r\n if (updates.rolledFingerprints) delete updates.rolledFingerprints[fingerPos];\r\n return;\r\n }\r\n const palmPos = PALM_MAP_INV[mf.position];\r\n if (palmPos) {\r\n updates.missingPalms![palmPos] = mf.missingReasonText || \"No capturable\";\r\n if (updates.palms) delete updates.palms[palmPos];\r\n }\r\n });\r\n }\r\n\r\n // Mapeo de Rostros\r\n // La API acumula caras de múltiples enrollments/updates.\r\n // Filtramos solo las válidas (con template y valid=true) y tomamos las últimas 5.\r\n if (data.faceModality?.faces) {\r\n const validFaces = data.faceModality.faces.filter(\r\n (f: any) => f.template && f.image?.qualities?.valid === true,\r\n );\r\n\r\n // Tomar las últimas 5 válidas (más recientes)\r\n const latestFaces = validFaces.slice(-5);\r\n\r\n const loadedFaces = [];\r\n for (const f of latestFaces) {\r\n let rawImage = f.image.dataBytes || \"\";\r\n if (!rawImage && f.image.dataUrl && isRemoteImage(f.image.dataUrl)) {\r\n try {\r\n rawImage = await downloadImageAsBase64(f.image.dataUrl);\r\n } catch (e) {\r\n console.warn(\"No se pudo descargar imagen de rostro:\", e);\r\n rawImage = f.image.dataUrl;\r\n }\r\n } else if (!rawImage && f.image.dataUrl) {\r\n rawImage = f.image.dataUrl;\r\n }\r\n\r\n // Quality viene de template.qualities.quality (IFace SDK, rango ~0-300)\r\n // Normalizamos a 0-100 dividiendo entre 2\r\n const rawQuality = f.template?.qualities?.quality || 0;\r\n const normalizedQuality = Math.min(Math.round(rawQuality / 2), 100);\r\n\r\n loadedFaces.push({\r\n image: normalizeImageForStorage(rawImage),\r\n quality: normalizedQuality,\r\n });\r\n }\r\n\r\n updates.faces = loadedFaces;\r\n\r\n const newCaptures: (BiometricItem | null)[] = Array(5).fill(null);\r\n loadedFaces.forEach((face, index) => {\r\n if (index < 5) newCaptures[index] = face;\r\n });\r\n updates.faceCaptures = newCaptures;\r\n }\r\n\r\n // Mapeo de Iris\r\n if (data.irisModality?.irises) {\r\n const newIrises: any = {};\r\n for (const iris of data.irisModality.irises) {\r\n let rawImage = iris.image.dataBytes || \"\";\r\n if (\r\n !rawImage &&\r\n iris.image.dataUrl &&\r\n isRemoteImage(iris.image.dataUrl)\r\n ) {\r\n try {\r\n rawImage = await downloadImageAsBase64(iris.image.dataUrl);\r\n } catch (e) {\r\n console.warn(\r\n `No se pudo descargar imagen de iris ${iris.position}:`,\r\n e,\r\n );\r\n rawImage = iris.image.dataUrl;\r\n }\r\n } else if (!rawImage && iris.image.dataUrl) {\r\n rawImage = iris.image.dataUrl;\r\n }\r\n const item: BiometricItem = {\r\n image: normalizeImageForStorage(rawImage),\r\n quality: iris.image.qualities?.quality || 100,\r\n };\r\n\r\n if (iris.position === \"Right\") newIrises.right = item;\r\n if (iris.position === \"Left\") newIrises.left = item;\r\n }\r\n updates.irises = newIrises;\r\n }\r\n\r\n // Mapeo de Iris Faltantes\r\n if (data.irisModality?.missingIrises) {\r\n data.irisModality.missingIrises.forEach((mi: any) => {\r\n if (mi.position === \"Right\") {\r\n updates.missingIrises![\"right\"] = mi.missingReasonText || \"No capturable\";\r\n if (updates.irises) delete updates.irises.right;\r\n }\r\n if (mi.position === \"Left\") {\r\n updates.missingIrises![\"left\"] = mi.missingReasonText || \"No capturable\";\r\n if (updates.irises) delete updates.irises.left;\r\n }\r\n });\r\n }\r\n\r\n // Mapeo de Rostros Faltantes\r\n if (data.faceModality?.missingFaces) {\r\n data.faceModality.missingFaces.forEach((mf: any) => {\r\n updates.missingFaces![mf.index] = mf.missingReasonText || \"No capturable\";\r\n if (updates.faceCaptures) {\r\n updates.faceCaptures[mf.index] = null;\r\n }\r\n });\r\n\r\n // Refilter valid faces if any were marked as missing\r\n if (updates.faces && updates.faces.length > 0) {\r\n updates.faces = updates.faceCaptures!.filter((item): item is BiometricItem => item !== null);\r\n }\r\n }\r\n\r\n // Crear snapshot para dirty tracking\r\n const snapshot: OriginalSnapshot = {\r\n fingerprints: { ...updates.fingerprints! },\r\n rolledFingerprints: { ...updates.rolledFingerprints! },\r\n missingFingers: { ...updates.missingFingers! },\r\n palms: { ...updates.palms! },\r\n missingPalms: { ...updates.missingPalms! },\r\n faces: [...(updates.faces || [])],\r\n faceCaptures: [...(updates.faceCaptures || Array(5).fill(null))],\r\n missingFaces: { ...updates.missingFaces! },\r\n irises: { ...updates.irises! },\r\n missingIrises: { ...updates.missingIrises! },\r\n };\r\n\r\n set((state) => ({\r\n ...state,\r\n ...updates,\r\n _originalSnapshot: snapshot,\r\n isLoading: false,\r\n }));\r\n } catch (error: any) {\r\n console.error('Error loading applicant data:', error);\r\n } finally {\r\n set({ isLoading: false });\r\n }\r\n },\r\n\r\n buildEnrollmentRequest: () => {\r\n const state = get();\r\n const plainFingerprints = Object.entries(state.fingerprints)\r\n .map(([key, item]) => ({\r\n position: FINGER_MAP[key],\r\n impressionType: FingerprintImpressionType.LiveScanPlain,\r\n image: { dataBytes: normalizeImageForStorage(item.image) },\r\n }))\r\n .filter((f) => f.position);\r\n\r\n const rolledFingerprints = Object.entries(state.rolledFingerprints)\r\n .map(([key, item]) => ({\r\n position: FINGER_MAP[key],\r\n impressionType: FingerprintImpressionType.RolledContact,\r\n image: { dataBytes: normalizeImageForStorage(item.image) },\r\n }))\r\n .filter((f) => f.position);\r\n\r\n const palmFingerprints = Object.entries(state.palms)\r\n .map(([key, item]) => ({\r\n position: PALM_MAP[key],\r\n impressionType: FingerprintImpressionType.LiveScanPlain,\r\n image: { dataBytes: normalizeImageForStorage(item.image) },\r\n }))\r\n .filter((f) => f.position);\r\n\r\n const allFrictionRidge = [\r\n ...plainFingerprints,\r\n ...rolledFingerprints,\r\n ...palmFingerprints,\r\n ];\r\n\r\n const fingerMissing = Object.entries(state.missingFingers)\r\n .map(([key, reason]) => ({\r\n position: FINGER_MAP[key],\r\n missingReasonCode: \"UAP\",\r\n missingReasonText: reason,\r\n }))\r\n .filter((f) => f.position);\r\n\r\n const palmMissing = Object.entries(state.missingPalms)\r\n .map(([key, reason]) => ({\r\n position: PALM_MAP[key],\r\n missingReasonCode: \"UAP\",\r\n missingReasonText: reason,\r\n }))\r\n .filter((f) => f.position);\r\n\r\n const allMissingFingerprints = [...fingerMissing, ...palmMissing];\r\n\r\n let finalFaces: any[] = [];\r\n if (state.faces.length > 0) {\r\n finalFaces = state.faces.map((item) => ({\r\n image: { dataBytes: normalizeImageForStorage(item.image) },\r\n }));\r\n } else {\r\n finalFaces = state.faceCaptures\r\n .filter((item): item is BiometricItem => item !== null)\r\n .map((item) => ({\r\n image: { dataBytes: normalizeImageForStorage(item.image) },\r\n }));\r\n }\r\n\r\n const faceMissing: MissingFaceItem[] = Object.entries(\r\n state.missingFaces,\r\n ).map(([idx, reason]) => ({\r\n index: Number(idx),\r\n missingReasonCode: \"UAP\",\r\n missingReasonText: reason,\r\n }));\r\n\r\n const finalIrises = [];\r\n if (state.irises.right) {\r\n finalIrises.push({\r\n position: IrisPosition.Right,\r\n image: {\r\n dataBytes: normalizeImageForStorage(state.irises.right.image),\r\n },\r\n });\r\n }\r\n if (state.irises.left) {\r\n finalIrises.push({\r\n position: IrisPosition.Left,\r\n image: { dataBytes: normalizeImageForStorage(state.irises.left.image) },\r\n });\r\n }\r\n\r\n const irisMissing: MissingIrisItem[] = Object.entries(\r\n state.missingIrises,\r\n ).map(([side, reason]) => ({\r\n position: side === \"right\" ? IrisPosition.Right : IrisPosition.Left,\r\n missingReasonCode: \"UAP\",\r\n missingReasonText: reason,\r\n }));\r\n\r\n const request: EnrollApplicantRequest = {\r\n externalId: state.externalId || `AUTO-${Date.now()}`,\r\n enrollAction: { enrollActionType: \"Masterize\" },\r\n customDetails: {\r\n fullName: state.fullName || \"Unknown Applicant\",\r\n },\r\n fingerprintModality: {\r\n fingerprints: allFrictionRidge,\r\n missingFingerprints: allMissingFingerprints,\r\n },\r\n faceModality: {\r\n faces: finalFaces,\r\n missingFaces: faceMissing.length > 0 ? faceMissing : undefined,\r\n },\r\n irisModality: {\r\n irises: finalIrises,\r\n missingIrises: irisMissing.length > 0 ? irisMissing : undefined,\r\n },\r\n };\r\n\r\n return request;\r\n },\r\n\r\n getDirtyModalities: () => {\r\n const state = get();\r\n const snap = state._originalSnapshot;\r\n const dirty = new Set<string>();\r\n\r\n if (!snap) {\r\n if (\r\n Object.keys(state.fingerprints).length > 0 ||\r\n Object.keys(state.rolledFingerprints).length > 0 ||\r\n Object.keys(state.missingFingers).length > 0 ||\r\n Object.keys(state.palms).length > 0 ||\r\n Object.keys(state.missingPalms).length > 0\r\n )\r\n dirty.add(\"fingerprint\");\r\n if (\r\n state.faces.length > 0 ||\r\n state.faceCaptures.some((f) => f !== null) ||\r\n Object.keys(state.missingFaces).length > 0\r\n )\r\n dirty.add(\"face\");\r\n if (\r\n state.irises.right ||\r\n state.irises.left ||\r\n Object.keys(state.missingIrises).length > 0\r\n )\r\n dirty.add(\"iris\");\r\n return dirty;\r\n }\r\n\r\n const fingerprintChanged =\r\n JSON.stringify(state.fingerprints) !==\r\n JSON.stringify(snap.fingerprints) ||\r\n JSON.stringify(state.rolledFingerprints) !==\r\n JSON.stringify(snap.rolledFingerprints) ||\r\n JSON.stringify(state.missingFingers) !==\r\n JSON.stringify(snap.missingFingers) ||\r\n JSON.stringify(state.palms) !== JSON.stringify(snap.palms) ||\r\n JSON.stringify(state.missingPalms) !== JSON.stringify(snap.missingPalms);\r\n if (fingerprintChanged) dirty.add(\"fingerprint\");\r\n\r\n const faceChanged =\r\n JSON.stringify(state.faces) !== JSON.stringify(snap.faces) ||\r\n JSON.stringify(state.faceCaptures) !==\r\n JSON.stringify(snap.faceCaptures) ||\r\n JSON.stringify(state.missingFaces) !== JSON.stringify(snap.missingFaces);\r\n if (faceChanged) dirty.add(\"face\");\r\n\r\n const irisChanged =\r\n JSON.stringify(state.irises) !== JSON.stringify(snap.irises) ||\r\n JSON.stringify(state.missingIrises) !==\r\n JSON.stringify(snap.missingIrises);\r\n if (irisChanged) dirty.add(\"iris\");\r\n\r\n return dirty;\r\n },\r\n\r\n buildUpdateRequest: () => {\r\n const state = get();\r\n const dirty = state.getDirtyModalities();\r\n\r\n const request: Partial<EnrollApplicantRequest> = {\r\n customDetails: {\r\n fullName: state.fullName || \"Unknown Applicant\",\r\n },\r\n };\r\n\r\n if (dirty.has(\"fingerprint\")) {\r\n const plainFingerprints = Object.entries(state.fingerprints)\r\n .map(([key, item]) => ({\r\n position: FINGER_MAP[key],\r\n impressionType: FingerprintImpressionType.LiveScanPlain,\r\n image: { dataBytes: normalizeImageForStorage(item.image) },\r\n }))\r\n .filter((f) => f.position);\r\n\r\n const rolledFingerprints = Object.entries(state.rolledFingerprints)\r\n .map(([key, item]) => ({\r\n position: FINGER_MAP[key],\r\n impressionType: FingerprintImpressionType.RolledContact,\r\n image: { dataBytes: normalizeImageForStorage(item.image) },\r\n }))\r\n .filter((f) => f.position);\r\n\r\n const palmFingerprints = Object.entries(state.palms)\r\n .map(([key, item]) => ({\r\n position: PALM_MAP[key],\r\n impressionType: FingerprintImpressionType.LiveScanPlain,\r\n image: { dataBytes: normalizeImageForStorage(item.image) },\r\n }))\r\n .filter((f) => f.position);\r\n\r\n const fingerMissing = Object.entries(state.missingFingers)\r\n .map(([key, reason]) => ({\r\n position: FINGER_MAP[key],\r\n missingReasonCode: \"UAP\",\r\n missingReasonText: reason,\r\n }))\r\n .filter((f) => f.position);\r\n\r\n const palmMissing = Object.entries(state.missingPalms)\r\n .map(([key, reason]) => ({\r\n position: PALM_MAP[key],\r\n missingReasonCode: \"UAP\",\r\n missingReasonText: reason,\r\n }))\r\n .filter((f) => f.position);\r\n\r\n request.fingerprintModality = {\r\n fingerprints: [\r\n ...plainFingerprints,\r\n ...rolledFingerprints,\r\n ...palmFingerprints,\r\n ],\r\n missingFingerprints: [...fingerMissing, ...palmMissing],\r\n };\r\n }\r\n\r\n if (dirty.has(\"face\")) {\r\n let finalFaces: any[] = [];\r\n if (state.faces.length > 0) {\r\n finalFaces = state.faces.map((item) => ({\r\n image: { dataBytes: normalizeImageForStorage(item.image) },\r\n }));\r\n } else {\r\n finalFaces = state.faceCaptures\r\n .filter((item): item is BiometricItem => item !== null)\r\n .map((item) => ({\r\n image: { dataBytes: normalizeImageForStorage(item.image) },\r\n }));\r\n }\r\n\r\n const faceMissing: MissingFaceItem[] = Object.entries(\r\n state.missingFaces,\r\n ).map(([idx, reason]) => ({\r\n index: Number(idx),\r\n missingReasonCode: \"UAP\",\r\n missingReasonText: reason,\r\n }));\r\n\r\n request.faceModality = {\r\n faces: finalFaces,\r\n missingFaces: faceMissing.length > 0 ? faceMissing : undefined,\r\n };\r\n }\r\n\r\n if (dirty.has(\"iris\")) {\r\n const finalIrises = [];\r\n if (state.irises.right) {\r\n finalIrises.push({\r\n position: IrisPosition.Right,\r\n image: {\r\n dataBytes: normalizeImageForStorage(state.irises.right.image),\r\n },\r\n });\r\n }\r\n if (state.irises.left) {\r\n finalIrises.push({\r\n position: IrisPosition.Left,\r\n image: {\r\n dataBytes: normalizeImageForStorage(state.irises.left.image),\r\n },\r\n });\r\n }\r\n\r\n const irisMissing: MissingIrisItem[] = Object.entries(\r\n state.missingIrises,\r\n ).map(([side, reason]) => ({\r\n position: side === \"right\" ? IrisPosition.Right : IrisPosition.Left,\r\n missingReasonCode: \"UAP\",\r\n missingReasonText: reason,\r\n }));\r\n\r\n request.irisModality = {\r\n irises: finalIrises,\r\n missingIrises: irisMissing.length > 0 ? irisMissing : undefined,\r\n };\r\n }\r\n\r\n return request;\r\n },\r\n}));\r\n","\r\nexport enum FingerprintPosition {\r\n \r\n RightThumb = \"RightThumb\",\r\n RightIndex = \"RightIndex\",\r\n RightMiddle = \"RightMiddle\",\r\n RightRing = \"RightRing\",\r\n RightLittle = \"RightLittle\",\r\n LeftThumb = \"LeftThumb\",\r\n LeftIndex = \"LeftIndex\",\r\n LeftMiddle = \"LeftMiddle\",\r\n LeftRing = \"LeftRing\",\r\n LeftLittle = \"LeftLittle\",\r\n\r\n \r\n RightUpperPalm = \"RightUpperPalm\",\r\n RightLowerPalm = \"RightLowerPalm\",\r\n RightWritersPalm = \"RightWritersPalm\",\r\n LeftUpperPalm = \"LeftUpperPalm\",\r\n LeftLowerPalm = \"LeftLowerPalm\",\r\n LeftWritersPalm = \"LeftWritersPalm\"\r\n}\r\n\r\n\r\nexport enum FingerprintImpressionType {\r\n LiveScanPlain = \"LiveScanPlain\",\r\n LiveScanRolled = \"LiveScanRolled\",\r\n RolledContact = \"RolledContact\",\r\n NonLiveScanPlain = \"NonLiveScanPlain\",\r\n NonLiveScanRolled = \"NonLiveScanRolled\",\r\n LatentImpression = \"LatentImpression\",\r\n LatentTracing = \"LatentTracing\",\r\n LatentPhoto = \"LatentPhoto\",\r\n LatentLift = \"LatentLift\",\r\n LiveScanPalm = \"LiveScanPalm\",\r\n NonLiveScanPalm = \"NonLiveScanPalm\",\r\n LatentPalmImpression = \"LatentPalmImpression\",\r\n LatentPalmTracing = \"LatentPalmTracing\",\r\n LatentPalmPhoto = \"LatentPalmPhoto\",\r\n LatentPalmLift = \"LatentPalmLift\",\r\n LiveScanOpticalContactPlain = \"LiveScanOpticalContactPlain\",\r\n LiveScanOpticalContactRolled = \"LiveScanOpticalContactRolled\",\r\n LiveScanOpticalContactlessPlain = \"LiveScanOpticalContactlessPlain\",\r\n LiveScanOpticalContactlessRolled = \"LiveScanOpticalContactlessRolled\",\r\n LiveScanCapacitivePlain = \"LiveScanCapacitivePlain\",\r\n LiveScanCapacitiveRolled = \"LiveScanCapacitiveRolled\",\r\n LiveScanUltrasonicPlain = \"LiveScanUltrasonicPlain\",\r\n LiveScanUltrasonicRolled = \"LiveScanUltrasonicRolled\",\r\n LiveScanThermalPlain = \"LiveScanThermalPlain\",\r\n LiveScanThermalRolled = \"LiveScanThermalRolled\",\r\n LiveScanVerticalSwipe = \"LiveScanVerticalSwipe\",\r\n LiveScanOpticalPalm = \"LiveScanOpticalPalm\",\r\n NonLiveScanOpticalPalm = \"NonLiveScanOpticalPalm\",\r\n Swipe = \"Swipe\",\r\n LiveScanContactless = \"LiveScanContactless\"\r\n}\r\n\r\nexport enum IrisPosition {\r\n Right = \"Right\",\r\n Left = \"Left\",\r\n}\r\n\r\n\r\nexport interface BiometricImage {\r\n dataBytes: string; \r\n}\r\n\r\nexport interface FingerprintItem {\r\n position: FingerprintPosition;\r\n impressionType?: FingerprintImpressionType; \r\n image: BiometricImage;\r\n}\r\n\r\nexport interface MissingFingerprintItem {\r\n position: FingerprintPosition;\r\n missingReasonCode?: string; \r\n missingReasonText?: string;\r\n}\r\n\r\nexport interface FaceItem {\r\n image: BiometricImage;\r\n}\r\n\r\nexport interface MissingFaceItem {\r\n index: number;\r\n missingReasonCode?: string;\r\n missingReasonText?: string;\r\n}\r\n\r\nexport interface IrisItem {\r\n position: IrisPosition;\r\n image: BiometricImage;\r\n}\r\n\r\nexport interface MissingIrisItem {\r\n position: IrisPosition;\r\n missingReasonCode?: string;\r\n missingReasonText?: string;\r\n}\r\n\r\nexport interface EnrollAction {\r\n enrollActionType: \"Masterize\" | \"Verify\";\r\n}\r\n\r\nexport interface CustomDetails {\r\n fullName: string;\r\n citizenship?: string;\r\n dateOfBirth?: string;\r\n gender?: string;\r\n [key: string]: any; \r\n}\r\n\r\n\r\nexport interface EnrollApplicantRequest {\r\n externalId: string;\r\n enrolledBy?: string;\r\n enrollAction: EnrollAction;\r\n customDetails: CustomDetails;\r\n fingerprintModality?: {\r\n fingerprints: FingerprintItem[];\r\n missingFingerprints: MissingFingerprintItem[];\r\n };\r\n faceModality?: {\r\n faces: FaceItem[];\r\n missingFaces?: MissingFaceItem[];\r\n };\r\n irisModality?: {\r\n irises: IrisItem[];\r\n missingIrises?: MissingIrisItem[];\r\n };\r\n \r\n}","\r\nexport function normalizeImageForStorage(\r\n imageString: string | undefined | null\r\n): string {\r\n if (!imageString) return \"\";\r\n\r\n if (imageString.startsWith(\"http://\") || imageString.startsWith(\"https://\")) {\r\n return imageString;\r\n }\r\n\r\n if (imageString.includes(\"data:image\") && imageString.includes(\",\")) {\r\n const parts = imageString.split(\",\");\r\n return parts.length > 1 ? parts[1] : imageString;\r\n }\r\n\r\n return imageString;\r\n}\r\n\r\nexport function getImageSrcForDisplay(\r\n imageString: string | undefined | null,\r\n format: \"png\" | \"jpeg\" | \"jpg\" | \"bmp\" | \"jp2\" = \"png\"\r\n): string | undefined {\r\n if (!imageString) return undefined;\r\n\r\n if (imageString.startsWith(\"http://\") || imageString.startsWith(\"https://\")) {\r\n return imageString;\r\n }\r\n if (imageString.startsWith(\"data:image\")) {\r\n return imageString;\r\n }\r\n return `data:image/${format};base64,${imageString}`;\r\n}\r\n\r\nexport function isRemoteImage(\r\n imageString: string | undefined | null\r\n): boolean {\r\n if (!imageString) return false;\r\n return (\r\n imageString.startsWith(\"http://\") || imageString.startsWith(\"https://\")\r\n );\r\n}\r\n\r\n/**\r\n * Descarga una imagen remota y la convierte a base64.\r\n * Sigue el patrón de `Utils.downloadResource` de los ABIS training samples.\r\n * Para usar en el navegador con fetch + FileReader.\r\n */\r\nexport async function downloadImageAsBase64(url: string): Promise<string> {\r\n const response = await fetch(url);\r\n if (!response.ok) {\r\n throw new Error(`Failed to download image: ${response.status} ${response.statusText}`);\r\n }\r\n const blob = await response.blob();\r\n return new Promise((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onloadend = () => {\r\n const dataUrl = reader.result as string;\r\n // Extraer solo el base64 sin el prefijo data:image/...;base64,\r\n const base64 = dataUrl.split(\",\")[1] || \"\";\r\n resolve(base64);\r\n };\r\n reader.onerror = reject;\r\n reader.readAsDataURL(blob);\r\n });\r\n}\r\n\r\nexport function canvasToBase64(\r\n canvas: HTMLCanvasElement,\r\n format: \"image/jpeg\" | \"image/png\" = \"image/jpeg\",\r\n quality: number = 0.95\r\n): string {\r\n const dataUrl = canvas.toDataURL(format, quality);\r\n return dataUrl.split(\",\")[1] || \"\";\r\n}\r\n\r\nexport function base64toBlob(base64Data: string): Blob | null {\r\n try {\r\n const sliceSize = 512;\r\n const byteCharacters = atob(base64Data);\r\n const byteArrays = [];\r\n\r\n for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {\r\n const slice = byteCharacters.slice(offset, offset + sliceSize);\r\n const byteNumbers = new Array(slice.length);\r\n for (let i = 0; i < slice.length; i++) {\r\n byteNumbers[i] = slice.charCodeAt(i);\r\n }\r\n byteArrays.push(new Uint8Array(byteNumbers));\r\n }\r\n\r\n return new Blob(byteArrays, { type: \"application/octet-stream\" });\r\n } catch (error) {\r\n console.error(\"Error converting base64 to blob:\", error);\r\n return null;\r\n }\r\n}\r\n\r\nexport function detectImageFormat(\r\n base64Data: string | undefined | null\r\n): string {\r\n if (!base64Data) return \"unknown\";\r\n\r\n const cleanData = normalizeImageForStorage(base64Data);\r\n if (!cleanData) return \"unknown\";\r\n\r\n try {\r\n if (cleanData.startsWith(\"iVBOR\")) return \"image/png\";\r\n if (cleanData.startsWith(\"/9j/\")) return \"image/jpeg\";\r\n if (cleanData.startsWith(\"R0lGO\")) return \"image/gif\";\r\n if (cleanData.startsWith(\"Qk\")) return \"image/bmp\";\r\n if (cleanData.includes(\"V0VCU\")) return \"image/webp\";\r\n if (cleanData.startsWith(\"AAAA\")) return \"image/jp2\";\r\n\r\n return \"unknown\";\r\n } catch (error) {\r\n console.error(\"Error detecting image format:\", error);\r\n return \"unknown\";\r\n }\r\n}\r\n\r\nexport function isValidBase64(str: string): boolean {\r\n if (!str || typeof str !== \"string\") return false;\r\n\r\n try {\r\n const cleaned = normalizeImageForStorage(str);\r\n atob(cleaned);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n","\"use client\";\r\n\r\nimport { motion } from \"framer-motion\";\r\nimport {\r\n TbFingerprint,\r\n TbFaceId,\r\n TbHandStop,\r\n TbEye,\r\n TbPlus,\r\n TbRefresh,\r\n TbCheck,\r\n TbBan,\r\n TbRestore,\r\n TbCloud,\r\n TbTrash,\r\n} from \"react-icons/tb\";\r\n\r\ntype SlotStatus = \"pending\" | \"captured\" | \"error\";\r\n\r\nexport interface BiometricSlotProps {\r\n title: string;\r\n position: string;\r\n status: SlotStatus;\r\n quality?: number | null;\r\n imageUrl?: string | null;\r\n onCapture: () => void;\r\n onRequestMissing?: () => void;\r\n onRestore?: () => void;\r\n onDelete?: () => void;\r\n missingReason?: string | null;\r\n iconType: \"finger\" | \"face\" | \"palm\" | \"iris\";\r\n isDisabled?: boolean;\r\n className?: string;\r\n isLoadedFromBackend?: boolean;\r\n}\r\n\r\nconst iconMap = {\r\n finger: TbFingerprint,\r\n face: TbFaceId,\r\n palm: TbHandStop,\r\n iris: TbEye,\r\n};\r\n\r\nexport function BiometricSlot({\r\n title,\r\n position,\r\n status,\r\n quality,\r\n imageUrl,\r\n onCapture,\r\n onRequestMissing,\r\n onRestore,\r\n onDelete,\r\n missingReason: externalMissingReason,\r\n iconType,\r\n isDisabled = false,\r\n className = \"\",\r\n isLoadedFromBackend = false,\r\n}: BiometricSlotProps) {\r\n const IconComponent = iconMap[iconType];\r\n\r\n const missingReason = externalMissingReason || null;\r\n const isMissing = !!missingReason;\r\n\r\n // --- Lógica de Estilos Dinámicos ---\r\n let ringClass = \"ring-border/50 dark:ring-white/10\";\r\n let glowClass = \"\";\r\n let elevationClass = \"elevation-1 hover:elevation-2\";\r\n let statusColor = \"text-foreground/40\";\r\n let buttonStyle =\r\n \"bg-primary text-primary-foreground hover:bg-primary/90 hover:shadow-glow-primary\";\r\n let borderClass = \"border-white/10\";\r\n\r\n if (status === \"captured\" && !isMissing) {\r\n const q = quality || 0;\r\n if (q >= 80) {\r\n ringClass = \"ring-quality-good/60\";\r\n glowClass = \"glow-success\";\r\n elevationClass = \"elevation-3\";\r\n statusColor = \"text-quality-good\";\r\n buttonStyle =\r\n \"bg-secondary text-foreground hover:bg-secondary/80 border border-border/50\";\r\n borderClass = \"border-quality-good/30\";\r\n } else if (q >= 50) {\r\n ringClass = \"ring-quality-ok/50\";\r\n glowClass = \"\";\r\n elevationClass = \"elevation-2\";\r\n statusColor = \"text-quality-ok\";\r\n buttonStyle =\r\n \"bg-secondary text-foreground hover:bg-secondary/80 border border-border/50\";\r\n borderClass = \"border-quality-ok/30\";\r\n } else {\r\n ringClass = \"ring-quality-bad/50\";\r\n glowClass = \"glow-danger\";\r\n elevationClass = \"elevation-2\";\r\n statusColor = \"text-quality-bad\";\r\n buttonStyle =\r\n \"bg-secondary text-foreground hover:bg-secondary/80 border border-border/50\";\r\n borderClass = \"border-quality-bad/30\";\r\n }\r\n } else if (isMissing) {\r\n ringClass = \"ring-red-500/30\";\r\n borderClass = \"border-red-500/20 border-dashed\";\r\n glowClass = \"\";\r\n elevationClass = \"elevation-1\";\r\n statusColor = \"text-red-400\";\r\n buttonStyle =\r\n \"bg-transparent border border-red-500/30 text-red-400 cursor-not-allowed opacity-50\";\r\n }\r\n\r\n return (\r\n <motion.div\r\n className={`\r\n relative flex flex-col p-3 rounded-md transition-all duration-300\r\n group cursor-pointer select-none\r\n bg-card/40\r\n ${elevationClass}\r\n ${borderClass}\r\n ${\r\n status === \"captured\" && !isMissing\r\n ? \"ring-2 \" + ringClass\r\n : \"hover:ring-1 hover:ring-primary/30 hover:border-primary/30\"\r\n }\r\n ${glowClass}\r\n hover:-translate-y-1\r\n ${isDisabled ? \"opacity-50 pointer-events-none grayscale hover:translate-y-0\" : \"\"}\r\n ${isMissing ? \"bg-red-500/5\" : \"\"}\r\n ${className}\r\n `}\r\n >\r\n {/* Header */}\r\n <div className=\"flex justify-between items-start w-full mb-3 z-10 h-6\">\r\n <p\r\n className=\"text-xs font-bold truncate text-foreground/70\"\r\n title={title}\r\n >\r\n {title}\r\n </p>\r\n\r\n <div className=\"flex items-center gap-1\">\r\n {/* Badge: Cargado vs Nuevo */}\r\n {status === \"captured\" && !isMissing && (\r\n <>\r\n {isLoadedFromBackend ? (\r\n <div className=\"bg-blue-500/90 text-white text-[9px] px-1.5 py-0.5 rounded-full font-bold flex items-center gap-1\">\r\n <TbCloud size={10} />\r\n <span>Cargado</span>\r\n </div>\r\n ) : (\r\n <div className=\"bg-green-500/90 text-white text-[9px] px-1.5 py-0.5 rounded-full font-bold flex items-center gap-1\">\r\n <TbCheck size={10} />\r\n <span>Nuevo</span>\r\n </div>\r\n )}\r\n </>\r\n )}\r\n\r\n {/* Botones de Acción */}\r\n {isMissing ? (\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n onRestore?.();\r\n }}\r\n className=\"text-green-500 hover:bg-green-500/10 p-1 rounded-full transition-colors\"\r\n title=\"Restaurar\"\r\n >\r\n <TbRestore size={16} />\r\n </button>\r\n ) : (\r\n <div className=\"flex items-center gap-0.5\">\r\n {/* Eliminar captura */}\r\n {status === \"captured\" && onDelete && (\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n onDelete();\r\n }}\r\n disabled={isDisabled}\r\n className=\"text-foreground/20 hover:text-red-500 hover:bg-red-500/10 p-1 rounded-full disabled:opacity-0 transition-colors\"\r\n title=\"Eliminar captura\"\r\n >\r\n <TbTrash size={16} />\r\n </button>\r\n )}\r\n {/* Marcar como no capturable */}\r\n {onRequestMissing && (\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n onRequestMissing();\r\n }}\r\n disabled={isDisabled}\r\n className=\"text-foreground/20 hover:text-red-500 hover:bg-red-500/10 p-1 rounded-full disabled:opacity-0 transition-colors\"\r\n title=\"Marcar como no capturable\"\r\n >\r\n <TbBan size={16} />\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Área Central (Imagen o Icono) */}\r\n <div\r\n className=\"\r\n relative w-full flex-1 min-h-[100px] flex items-center justify-center\r\n rounded-md overflow-hidden\r\n bg-black/5 dark:bg-white/5 border border-transparent\r\n group-hover:border-white/5 transition-all\r\n \"\r\n onClick={!isDisabled && !isMissing ? onCapture : undefined}\r\n >\r\n {isMissing ? (\r\n <div className=\"flex flex-col items-center text-center p-2 animate-in zoom-in duration-300\">\r\n <TbBan size={32} className=\"text-red-400/50 mb-2\" />\r\n <p className=\"text-[10px] text-red-400 font-bold uppercase tracking-wider\">\r\n {missingReason}\r\n </p>\r\n </div>\r\n ) : imageUrl ? (\r\n <motion.img\r\n initial={{ opacity: 0 }}\r\n animate={{ opacity: 1 }}\r\n src={imageUrl}\r\n className=\"w-full h-full object-contain p-2\"\r\n alt={title}\r\n />\r\n ) : (\r\n <IconComponent\r\n size={40}\r\n className={`\r\n text-foreground/10 transition-all duration-300\r\n ${\r\n !isDisabled &&\r\n \"group-hover:scale-110 group-hover:text-primary/40\"\r\n }\r\n `}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Footer */}\r\n <div className=\"w-full mt-4 flex items-center justify-between gap-2\">\r\n {/* Estado Texto */}\r\n <span\r\n className={`text-[10px] uppercase font-bold tracking-wider ${statusColor}`}\r\n >\r\n {isMissing\r\n ? \"Omitido\"\r\n : status === \"captured\"\r\n ? `${quality}% Calidad`\r\n : \"Pendiente\"}\r\n </span>\r\n\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n if (!isMissing) onCapture();\r\n }}\r\n disabled={isDisabled || isMissing}\r\n className={`h-8 px-3 rounded-sm text-xs font-bold flex items-center gap-1 transition-all shadow-sm ${buttonStyle}`}\r\n >\r\n {status === \"captured\" ? (\r\n <TbRefresh size={14} />\r\n ) : (\r\n <TbPlus size={14} />\r\n )}\r\n <span>{status === \"captured\" ? \"Repetir\" : \"Capturar\"}</span>\r\n </button>\r\n </div>\r\n </motion.div>\r\n );\r\n}\r\n","// src/components/ui/MissingFingerModal.tsx\r\nimport React, { useState, useEffect } from \"react\";\r\nimport { Modal } from \"./Modal\";\r\nimport { Button } from \"./Button\";\r\nimport { TbBan } from \"react-icons/tb\";\r\n\r\ntype BiometricType = \"finger\" | \"palm\" | \"iris\" | \"face\";\r\n\r\ninterface MissingBiometricModalProps {\r\n isOpen: boolean;\r\n onClose: () => void;\r\n onConfirm: (reason: string) => void;\r\n positionName: string;\r\n biometricType?: BiometricType;\r\n}\r\n\r\nconst REASONS_BY_TYPE: Record<BiometricType, string[]> = {\r\n finger: [\r\n \"Amputación Total\",\r\n \"Amputación Parcial\",\r\n \"Herida / Vendaje\",\r\n \"Deformidad\",\r\n \"Imposibilidad Física\",\r\n \"Otro\",\r\n ],\r\n palm: [\r\n \"Herida / Vendaje\",\r\n \"Deformidad\",\r\n \"Imposibilidad Física\",\r\n \"Otro\",\r\n ],\r\n iris: [\r\n \"Prótesis Ocular\",\r\n \"Lesión / Cirugía\",\r\n \"Ceguera\",\r\n \"Imposibilidad Física\",\r\n \"Otro\",\r\n ],\r\n face: [\r\n \"Lesión Facial\",\r\n \"Vendaje / Cubrimiento\",\r\n \"Imposibilidad Física\",\r\n \"Otro\",\r\n ],\r\n};\r\n\r\nconst WARNINGS: Record<BiometricType, string> = {\r\n finger:\r\n \"Al marcar este dedo como no capturable, el sistema lo ignorará automáticamente durante el escaneo.\",\r\n palm:\r\n \"Al marcar esta palma como no capturable, será excluida del enrolamiento.\",\r\n iris:\r\n \"Al marcar este iris como no capturable, será excluido del enrolamiento.\",\r\n face:\r\n \"Al marcar este ángulo facial como no capturable, será excluido del enrolamiento.\",\r\n};\r\n\r\nexport const MissingBiometricModal: React.FC<MissingBiometricModalProps> = ({\r\n isOpen,\r\n onClose,\r\n onConfirm,\r\n positionName,\r\n biometricType = \"finger\",\r\n}) => {\r\n const reasons = REASONS_BY_TYPE[biometricType];\r\n const [selectedReason, setSelectedReason] = useState(reasons[0]);\r\n\r\n useEffect(() => {\r\n if (isOpen) {\r\n setSelectedReason(REASONS_BY_TYPE[biometricType][0]);\r\n }\r\n }, [isOpen, biometricType]);\r\n\r\n return (\r\n <Modal\r\n isOpen={isOpen}\r\n onClose={onClose}\r\n title={`Omitir captura: ${positionName}`}\r\n >\r\n <div className=\"p-4 space-y-4\">\r\n <div className=\"bg-warning/10 border-l-4 border-warning p-3 text-sm text-warning\">\r\n <p>{WARNINGS[biometricType]}</p>\r\n </div>\r\n\r\n <div className=\"space-y-2 mt-4\">\r\n <p className=\"font-semibold text-foreground/70 mb-2\">\r\n Seleccione el motivo:\r\n </p>\r\n {reasons.map((reason) => (\r\n <label\r\n key={reason}\r\n className={`flex items-center p-3 border rounded-sm cursor-pointer transition-colors ${\r\n selectedReason === reason\r\n ? \"bg-primary/10 border-primary ring-1 ring-primary\"\r\n : \"hover:bg-secondary/50 border-border-default\"\r\n }`}\r\n >\r\n <input\r\n type=\"radio\"\r\n name=\"reason\"\r\n value={reason}\r\n checked={selectedReason === reason}\r\n onChange={(e) => setSelectedReason(e.target.value)}\r\n className=\"h-4 w-4 text-primary focus:ring-primary border-border-default\"\r\n />\r\n <span className=\"ml-3 text-foreground\">{reason}</span>\r\n </label>\r\n ))}\r\n </div>\r\n\r\n <div className=\"flex justify-end space-x-3 pt-4 border-t border-border-default mt-4\">\r\n <Button\r\n onClick={onClose}\r\n variant=\"secondary\"\r\n size=\"md\"\r\n >\r\n Cancelar\r\n </Button>\r\n <Button\r\n onClick={() => onConfirm(selectedReason)}\r\n variant=\"danger\"\r\n size=\"md\"\r\n icon={<TbBan />}\r\n >\r\n Confirmar Excepción\r\n </Button>\r\n </div>\r\n </div>\r\n </Modal>\r\n );\r\n};\r\n\r\n// Alias para compatibilidad con imports existentes\r\nexport const MissingFingerModal = MissingBiometricModal;\r\n","\"use client\";\r\n\r\nimport { motion, AnimatePresence } from \"framer-motion\";\r\nimport { TbX } from \"react-icons/tb\";\r\nimport { useEffect, useState } from \"react\";\r\nimport { createPortal } from \"react-dom\";\r\n\r\nexport interface ModalProps {\r\n isOpen: boolean;\r\n onClose: () => void;\r\n title: string;\r\n children: React.ReactNode;\r\n allowClose?: boolean;\r\n}\r\n\r\nexport function Modal({\r\n isOpen,\r\n onClose,\r\n title,\r\n children,\r\n allowClose = true,\r\n}: ModalProps): React.ReactNode {\r\n const [mounted, setMounted] = useState(false);\r\n\r\n useEffect(() => {\r\n setMounted(true);\r\n return () => setMounted(false);\r\n }, []);\r\n\r\n // Bloquear el scroll del fondo cuando el modal está abierto\r\n useEffect(() => {\r\n if (isOpen) document.body.style.overflow = \"hidden\";\r\n else document.body.style.overflow = \"unset\";\r\n return () => {\r\n document.body.style.overflow = \"unset\";\r\n };\r\n }, [isOpen]);\r\n\r\n // No renderizar nada en el servidor (evita errores de hidratación)\r\n if (!mounted) return null;\r\n\r\n const modalContent = (\r\n <AnimatePresence>\r\n {isOpen && (\r\n <div className=\"fixed inset-0 z-[9999] flex items-center justify-center p-4 sm:p-6\">\r\n {/* --- BACKDROP --- */}\r\n <motion.div\r\n className=\"absolute inset-0 backdrop-blur-md transition-all\"\r\n initial={{ opacity: 0 }}\r\n animate={{ opacity: 1 }}\r\n exit={{ opacity: 0 }}\r\n onClick={allowClose ? onClose : undefined}\r\n />\r\n\r\n {/* --- CONTENEDOR DEL MODAL --- */}\r\n <motion.div\r\n className=\"\r\n relative z-10 w-full max-w-2xl flex flex-col\r\n rounded-sm overflow-hidden\r\n bg-card/95\r\n elevation-5\r\n max-h-[85vh]\r\n \"\r\n initial={{ scale: 0.92, opacity: 0, y: 25 }}\r\n animate={{ scale: 1, opacity: 1, y: 0 }}\r\n exit={{ scale: 0.95, opacity: 0, y: 15 }}\r\n transition={{\r\n type: \"spring\",\r\n bounce: 0.35,\r\n duration: 0.5,\r\n }}\r\n >\r\n {/* Glow Decorativo Superior */}\r\n <div className=\"absolute top-0 inset-x-0 h-[1px] bg-gradient-to-r from-transparent via-primary/60 to-transparent z-20\" />\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between px-6 py-5 border-b border-white/5 bg-white/5 relative z-10\">\r\n <h2 className=\"text-xl font-bold text-foreground tracking-tight drop-shadow-sm\">\r\n {title}\r\n </h2>\r\n {allowClose && (\r\n <button\r\n onClick={onClose}\r\n className=\"\r\n group p-2 rounded-full\r\n text-foreground/50 hover:text-foreground\r\n hover:bg-white/10 transition-all duration-200\r\n \"\r\n >\r\n <TbX\r\n size={22}\r\n className=\"group-hover:scale-110 transition-transform\"\r\n />\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Contenido Scrollable */}\r\n <div\r\n className=\"\r\n p-6 sm:p-8 \r\n overflow-y-auto \r\n scrollbar-thin scrollbar-track-transparent scrollbar-thumb-border/40 hover:scrollbar-thumb-border/70\r\n \"\r\n >\r\n {children}\r\n </div>\r\n </motion.div>\r\n </div>\r\n )}\r\n </AnimatePresence>\r\n );\r\n\r\n // Usamos createPortal para renderizar fuera de la jerarquía actual, directamente en el body\r\n return createPortal(modalContent, document.body);\r\n}","// src/components/ui/Button.tsx\r\nimport React from \"react\";\r\nimport { TbLoader } from \"react-icons/tb\";\r\n\r\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\r\n variant?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'ghost';\r\n size?: 'sm' | 'md' | 'lg';\r\n isLoading?: boolean;\r\n icon?: React.ReactNode;\r\n children: React.ReactNode;\r\n}\r\n\r\nexport function Button({\r\n variant = 'primary',\r\n size = 'md',\r\n isLoading = false,\r\n icon,\r\n className = '',\r\n children,\r\n disabled,\r\n ...props\r\n}: ButtonProps) {\r\n const variantClasses = {\r\n primary: `\r\n bg-primary text-primary-foreground\r\n elevation-2\r\n hover:elevation-3 hover:-translate-y-1 hover:scale-[1.02]\r\n active:scale-[0.97] active:translate-y-0\r\n shadow-primary/20\r\n `,\r\n secondary: `\r\n bg-secondary text-secondary-foreground\r\n elevation-1\r\n hover:elevation-2 hover:-translate-y-1\r\n active:scale-[0.97]\r\n `,\r\n success: `\r\n bg-success/10 text-success\r\n elevation-1\r\n hover:bg-success hover:text-white hover:elevation-2 hover:-translate-y-1 hover:glow-success\r\n active:scale-[0.97]\r\n `,\r\n danger: `\r\n bg-danger/10 text-danger\r\n elevation-1\r\n hover:bg-danger hover:text-white hover:elevation-2 hover:-translate-y-1 hover:glow-danger\r\n active:scale-[0.97]\r\n `,\r\n warning: `\r\n bg-warning/10 text-warning\r\n elevation-1\r\n hover:bg-warning hover:text-foreground hover:elevation-2 hover:-translate-y-1 hover:glow-warning\r\n active:scale-[0.97]\r\n `,\r\n ghost: `\r\n bg-transparent\r\n border border-border-default\r\n hover:bg-secondary/50 hover:elevation-1 hover:-translate-y-1\r\n active:scale-[0.97]\r\n `\r\n };\r\n\r\n const sizeClasses = {\r\n sm: 'px-3 py-1.5 text-xs rounded-sm',\r\n md: 'px-4 py-2.5 text-sm rounded-md',\r\n lg: 'px-6 py-3.5 text-base rounded-md'\r\n };\r\n\r\n return (\r\n <button\r\n className={`\r\n ${variantClasses[variant]}\r\n ${sizeClasses[size]}\r\n font-semibold inline-flex items-center justify-center gap-2\r\n transition-all duration-250\r\n disabled:opacity-50 disabled:cursor-not-allowed\r\n ${className}\r\n `}\r\n disabled={disabled || isLoading}\r\n {...props}\r\n >\r\n {isLoading ? <TbLoader className=\"animate-spin\" /> : icon}\r\n {children}\r\n </button>\r\n );\r\n}\r\n","\"use client\";\r\n\r\ninterface ProgressBarProps {\r\n current: number;\r\n total: number;\r\n label?: string;\r\n className?: string;\r\n}\r\n\r\nexport function ProgressBar({\r\n current,\r\n total,\r\n label = \"Progreso del enrolamiento\",\r\n className = \"\",\r\n}: ProgressBarProps) {\r\n // Asegurar que el porcentaje esté entre 0 y 100\r\n const progress = Math.min(100, Math.max(0, (current / total) * 100));\r\n\r\n return (\r\n <div className={`w-full mt-8 ${className}`}>\r\n <div className=\"flex justify-between text-xs font-semibold text-foreground/50 mb-2 uppercase tracking-wider\">\r\n <span>{label}</span>\r\n <span>\r\n {current} / {total} Completadas\r\n </span>\r\n </div>\r\n\r\n <div className=\"h-3 w-full bg-secondary rounded-full overflow-hidden border border-white/5\">\r\n <div\r\n className=\"h-full bg-gradient-to-r from-primary to-purple-500 transition-all duration-700 ease-out relative\"\r\n style={{ width: `${progress}%` }}\r\n >\r\n {/* Efecto de brillo animado interior */}\r\n <div className=\"absolute inset-0 bg-white/20 animate-pulse\" />\r\n\r\n {/* Línea de luz en el borde derecho de la barra */}\r\n <div className=\"absolute right-0 top-0 bottom-0 w-[1px] bg-white/50 shadow-[0_0_10px_2px_rgba(255,255,255,0.5)]\" />\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport React from \"react\";\r\nimport { ProgressBar } from \"../ui/ProgressBar\";\r\nimport { useBiometricStore } from \"../../lib/stores/biometricStore\";\r\n\r\ninterface ModuleHeaderProps {\r\n icon: React.ReactNode;\r\n title: string;\r\n subtitle: string;\r\n progress?: { current: number; total: number };\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport function ModuleHeader({\r\n icon,\r\n title,\r\n subtitle,\r\n progress,\r\n children,\r\n}: ModuleHeaderProps) {\r\n const isConnected = useBiometricStore((s) => s.isConnected);\r\n\r\n return (\r\n <div className=\"glass rounded-sm p-6 md:p-8 border border-white/10\">\r\n <div className=\"flex flex-col md:flex-row justify-between items-start md:items-center gap-6\">\r\n <div>\r\n <h2 className=\"text-2xl font-bold text-foreground flex items-center gap-3\">\r\n <div className=\"p-2 bg-primary/10 rounded-sm text-primary\">\r\n {icon}\r\n </div>\r\n {title}\r\n </h2>\r\n <p className=\"text-foreground/60 mt-2 max-w-xl text-sm\">\r\n {subtitle}\r\n </p>\r\n </div>\r\n\r\n <div className=\"flex flex-wrap gap-3 items-center\">\r\n <div\r\n className={`px-3 py-1.5 rounded-sm text-[10px] font-bold uppercase tracking-wider flex items-center gap-2 border ${\r\n isConnected\r\n ? \"bg-green-500/10 border-green-500/20 text-green-600 dark:text-green-400\"\r\n : \"bg-red-500/10 border-red-500/20 text-red-600 dark:text-red-400\"\r\n }`}\r\n >\r\n <span\r\n className={`w-1.5 h-1.5 rounded-full ${\r\n isConnected ? \"bg-green-500 animate-pulse\" : \"bg-red-500\"\r\n }`}\r\n />\r\n {isConnected ? \"Conectado\" : \"Desconectado\"}\r\n </div>\r\n\r\n {children}\r\n </div>\r\n </div>\r\n\r\n {progress && (\r\n <ProgressBar current={progress.current} total={progress.total} />\r\n )}\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { useState, useRef, useEffect } from \"react\";\r\nimport { motion, AnimatePresence } from \"framer-motion\";\r\nimport { TbChevronDown, TbCheck } from \"react-icons/tb\";\r\n\r\nexport interface SelectOption {\r\n value: string;\r\n label: string;\r\n icon?: React.ReactNode;\r\n}\r\n\r\ninterface SelectProps {\r\n value: string;\r\n onChange: (value: string) => void;\r\n options: SelectOption[];\r\n placeholder?: string;\r\n disabled?: boolean;\r\n className?: string;\r\n}\r\n\r\nexport function Select({\r\n value,\r\n onChange,\r\n options,\r\n placeholder = \"Seleccionar...\",\r\n disabled = false,\r\n className = \"\",\r\n}: SelectProps) {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n\r\n // Cerrar al hacer clic fuera\r\n useEffect(() => {\r\n function handleClickOutside(event: MouseEvent) {\r\n if (\r\n containerRef.current &&\r\n !containerRef.current.contains(event.target as Node)\r\n ) {\r\n setIsOpen(false);\r\n }\r\n }\r\n document.addEventListener(\"mousedown\", handleClickOutside);\r\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\r\n }, []);\r\n\r\n const selectedOption = options.find((opt) => opt.value === value);\r\n\r\n return (\r\n <div\r\n className={`relative w-full min-w-[200px] ${className}`}\r\n ref={containerRef}\r\n >\r\n {/* --- TRIGGER BUTTON --- */}\r\n <button\r\n type=\"button\"\r\n onClick={() => !disabled && setIsOpen(!isOpen)}\r\n disabled={disabled}\r\n className={`\r\n w-full flex items-center justify-between\r\n px-4 py-3 rounded-md text-sm font-medium\r\n transition-all duration-250\r\n ${\r\n disabled\r\n ? \"opacity-50 cursor-not-allowed bg-secondary border-border elevation-1\"\r\n : isOpen\r\n ? \"bg-card elevation-3 ring-2 ring-primary/50 glow-primary text-foreground\"\r\n : \"bg-card/50 elevation-1 hover:elevation-2 hover:-translate-y-0.5 hover:border-primary/30 text-foreground/80\"\r\n }\r\n `}\r\n >\r\n <span className=\"flex items-center gap-2 truncate\">\r\n {selectedOption?.icon && (\r\n <span className=\"text-primary/80\">{selectedOption.icon}</span>\r\n )}\r\n {selectedOption ? (\r\n selectedOption.label\r\n ) : (\r\n <span className=\"text-muted-foreground\">{placeholder}</span>\r\n )}\r\n </span>\r\n\r\n <TbChevronDown\r\n className={`\r\n w-4 h-4 opacity-50 transition-transform duration-300\r\n ${isOpen ? \"rotate-180 text-primary\" : \"\"}\r\n `}\r\n />\r\n </button>\r\n\r\n {/* --- DROPDOWN MENU --- */}\r\n <AnimatePresence>\r\n {isOpen && (\r\n <motion.div\r\n initial={{ opacity: 0, y: 8, scale: 0.98 }}\r\n animate={{ opacity: 1, y: 0, scale: 1 }}\r\n exit={{ opacity: 0, y: 8, scale: 0.98 }}\r\n transition={{ duration: 0.2, ease: \"easeOut\" }}\r\n className=\"\r\n absolute z-50 top-full left-0 right-0 mt-2\r\n p-1.5 rounded-md border border-white/10\r\n bg-card/95 backdrop-blur-2xl\r\n shadow-2xl shadow-black/20\r\n max-h-64 overflow-y-auto\r\n scrollbar-thin scrollbar-track-transparent scrollbar-thumb-border/50\r\n \"\r\n >\r\n {options.map((option) => {\r\n const isSelected = option.value === value;\r\n return (\r\n <div\r\n key={option.value}\r\n onClick={() => {\r\n onChange(option.value);\r\n setIsOpen(false);\r\n }}\r\n className={`\r\n flex items-center justify-between px-3 py-2.5 rounded-sm cursor-pointer\r\n text-sm transition-all duration-150\r\n ${\r\n isSelected\r\n ? \"bg-primary/10 text-primary font-semibold\"\r\n : \"text-foreground/70 hover:bg-white/5 hover:text-foreground\"\r\n }\r\n `}\r\n >\r\n <div className=\"flex items-center gap-2.5\">\r\n {option.icon && (\r\n <span\r\n className={isSelected ? \"text-primary\" : \"opacity-50\"}\r\n >\r\n {option.icon}\r\n </span>\r\n )}\r\n <span>{option.label}</span>\r\n </div>\r\n\r\n {isSelected && (\r\n <motion.div\r\n initial={{ scale: 0 }}\r\n animate={{ scale: 1 }}\r\n transition={{\r\n type: \"spring\",\r\n stiffness: 300,\r\n damping: 20,\r\n }}\r\n >\r\n <TbCheck size={16} />\r\n </motion.div>\r\n )}\r\n </div>\r\n );\r\n })}\r\n </motion.div>\r\n )}\r\n </AnimatePresence>\r\n </div>\r\n );\r\n}\r\n","interface QualityBadgeProps {\r\n quality: number | null | undefined;\r\n className?: string;\r\n}\r\n\r\nexport function QualityBadge({ quality, className = \"\" }: QualityBadgeProps) {\r\n // Si no hay calidad (null/undefined), no renderizamos nada\r\n if (quality === null || quality === undefined) return null;\r\n\r\n // Clases base (forma, tamaño, bordes, animación)\r\n const baseClasses =\r\n \"flex flex-col items-center justify-center w-16 h-16 rounded-full border-2 backdrop-blur-xl shadow-lg animate-in zoom-in duration-300\";\r\n\r\n // Lógica de colores según el umbral\r\n let colorClasses = \"\";\r\n\r\n if (quality >= 80) {\r\n // Rango Bueno (Verde)\r\n colorClasses =\r\n \"text-quality-good border-quality-good/30 bg-quality-good/10 shadow-[0_0_10px_-3px_rgba(var(--quality-good),0.3)]\";\r\n } else if (quality >= 50) {\r\n // Rango Medio (Amarillo)\r\n colorClasses =\r\n \"text-quality-ok border-quality-ok/30 bg-quality-ok/10 shadow-[0_0_10px_-3px_rgba(var(--quality-ok),0.3)]\";\r\n } else {\r\n // Rango Malo (Rojo)\r\n colorClasses =\r\n \"text-quality-bad border-quality-bad/30 bg-quality-bad/10 shadow-[0_0_10px_-3px_rgba(var(--quality-bad),0.3)]\";\r\n }\r\n\r\n return (\r\n <div className={`${baseClasses} ${colorClasses} ${className}`}>\r\n <span className=\"text-xl font-bold tracking-tighter leading-none\">\r\n {quality}\r\n </span>\r\n <span className=\"text-[8px] font-bold uppercase tracking-widest opacity-70 mt-0.5\">\r\n CALIDAD\r\n </span>\r\n </div>\r\n );\r\n}\r\n","import { TbLoader } from \"react-icons/tb\";\r\n\r\ninterface LoaderProps {\r\n size?: number;\r\n text?: string;\r\n className?: string;\r\n}\r\n\r\nexport function Loader({ size = 24, text, className }: LoaderProps) {\r\n return (\r\n <div className={`flex flex-col items-center justify-center gap-2 text-primary ${className}`}>\r\n <TbLoader size={size} className=\"animate-spin\" />\r\n {text && <p className=\"text-sm text-foreground/80\">{text}</p>}\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { Modal } from \"../ui/Modal\";\r\nimport { QualityBadge } from \"../ui/QualityBadge\";\r\nimport { Loader } from \"../ui/Loader\";\r\nimport { TbFingerprint, TbX, TbScan } from \"react-icons/tb\";\r\nimport { motion } from \"framer-motion\";\r\n\r\ninterface FingerCaptureModalProps {\r\n isOpen: boolean;\r\n onCancel: () => void;\r\n captureType: string;\r\n previewImage: string | null;\r\n previewQuality: number | null;\r\n}\r\n\r\nexport function FingerCaptureModal({\r\n isOpen,\r\n onCancel,\r\n captureType,\r\n previewImage,\r\n previewQuality,\r\n}: FingerCaptureModalProps) {\r\n const isWaiting = !previewImage;\r\n\r\n return (\r\n <Modal\r\n isOpen={isOpen}\r\n onClose={onCancel}\r\n title={captureType}\r\n allowClose={true}\r\n >\r\n <div className=\"flex flex-col md:flex-row gap-8 items-stretch p-2\">\r\n <div className=\"flex-1 flex justify-center\">\r\n <div\r\n className=\"\r\n relative w-full max-w-[280px] aspect-[3/4]\r\n rounded-md overflow-hidden\r\n bg-black/5 dark:bg-white/5\r\n border border-border/50 dark:border-white/10\r\n shadow-inner flex items-center justify-center\r\n \"\r\n >\r\n {isWaiting && (\r\n <motion.div\r\n className=\"absolute inset-x-0 h-[2px] bg-primary/80 z-10 shadow-[0_0_15px_2px_rgba(var(--primary),0.6)]\"\r\n animate={{ top: [\"0%\", \"100%\", \"0%\"] }}\r\n transition={{ duration: 3, repeat: Infinity, ease: \"linear\" }}\r\n />\r\n )}\r\n\r\n {previewImage ? (\r\n <motion.img\r\n initial={{ opacity: 0, scale: 0.95 }}\r\n animate={{ opacity: 1, scale: 1 }}\r\n transition={{ duration: 0.3 }}\r\n src={previewImage}\r\n alt=\"Vista previa\"\r\n className=\"object-contain w-full h-full p-4 rotate-180 drop-shadow-xl\"\r\n />\r\n ) : (\r\n <div className=\"flex flex-col items-center justify-center text-foreground/30 gap-4\">\r\n <div className=\"relative\">\r\n <TbFingerprint size={80} className=\"animate-pulse\" />\r\n <TbScan\r\n size={30}\r\n className=\"absolute -bottom-2 -right-2 text-primary animate-bounce\"\r\n />\r\n </div>\r\n <div className=\"flex flex-col items-center gap-2\">\r\n <Loader size={20} />\r\n <p className=\"text-xs font-medium tracking-wide uppercase\">\r\n Esperando Escáner\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <div\r\n className=\"absolute inset-0 pointer-events-none opacity-10\"\r\n style={{\r\n backgroundImage:\r\n \"radial-gradient(circle, currentColor 1px, transparent 1px)\",\r\n backgroundSize: \"20px 20px\",\r\n }}\r\n />\r\n\r\n <div className=\"absolute top-4 right-4\">\r\n <QualityBadge quality={previewQuality} />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex-1 flex flex-col justify-between min-h-[320px]\">\r\n <div className=\"space-y-6\">\r\n <div className=\"space-y-2\">\r\n <h4 className=\"text-sm font-bold text-foreground uppercase tracking-wider flex items-center gap-2\">\r\n <span className=\"w-2 h-2 rounded-full bg-primary animate-pulse\" />\r\n Estado del Dispositivo\r\n </h4>\r\n <div className=\"p-4 rounded-md bg-secondary/50 border border-border/50 text-sm text-foreground/80 leading-relaxed\">\r\n {isWaiting ? (\r\n <p>\r\n El dispositivo está inicializando. Por favor, prepare al\r\n usuario para la captura.\r\n </p>\r\n ) : (\r\n <p className=\"text-quality-good font-medium\">\r\n ¡Imagen capturada! Analizando calidad biométrica...\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n\r\n <div className=\"space-y-3\">\r\n <h4 className=\"text-xs font-semibold text-foreground/60 uppercase tracking-wide\">\r\n Instrucciones\r\n </h4>\r\n <ul className=\"text-sm text-foreground/70 space-y-2 list-disc list-inside marker:text-primary\">\r\n <li>Coloque el dedo firmemente en el centro.</li>\r\n <li>Aplique presión uniforme.</li>\r\n <li>Mantenga la posición hasta escuchar el tono.</li>\r\n </ul>\r\n </div>\r\n </div>\r\n\r\n <div className=\"mt-auto pt-6\">\r\n <button\r\n onClick={onCancel}\r\n className=\"\r\n group w-full flex items-center justify-center gap-2 px-4 py-3.5\r\n rounded-md font-semibold text-sm\r\n bg-red-500/10 text-red-600 dark:text-red-400 \r\n border border-red-500/20\r\n hover:bg-red-500 hover:text-white hover:border-red-500\r\n transition-all duration-200 shadow-sm\r\n \"\r\n >\r\n <TbX\r\n size={18}\r\n className=\"transition-transform group-hover:rotate-90\"\r\n />\r\n Cancelar Captura\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </Modal>\r\n );\r\n}\r\n","export const FINGER_NAMES: Record<string, string> = {\r\n RIGHT_THUMB: \"Pulgar Der.\",\r\n RIGHT_INDEX: \"Índice Der.\",\r\n RIGHT_MIDDLE: \"Medio Der.\",\r\n RIGHT_RING: \"Anular Der.\",\r\n RIGHT_LITTLE: \"Meñique Der.\",\r\n LEFT_THUMB: \"Pulgar Izq.\",\r\n LEFT_INDEX: \"Índice Izq.\",\r\n LEFT_MIDDLE: \"Medio Izq.\",\r\n LEFT_RING: \"Anular Izq.\",\r\n LEFT_LITTLE: \"Meñique Izq.\",\r\n};\r\n\r\nexport const RIGHT_FINGERS = [\r\n \"RIGHT_THUMB\",\r\n \"RIGHT_INDEX\",\r\n \"RIGHT_MIDDLE\",\r\n \"RIGHT_RING\",\r\n \"RIGHT_LITTLE\",\r\n];\r\n\r\nexport const LEFT_FINGERS = [\r\n \"LEFT_THUMB\",\r\n \"LEFT_INDEX\",\r\n \"LEFT_MIDDLE\",\r\n \"LEFT_RING\",\r\n \"LEFT_LITTLE\",\r\n];\r\n","\"use client\";\r\n\r\nimport { useState, useEffect, useMemo } from \"react\";\r\nimport { toast } from \"react-hot-toast\";\r\nimport { useBiometricStore } from \"../../lib/stores/biometricStore\";\r\nimport { useUiStore } from \"../../lib/stores/uiStore\";\r\nimport { BiometricSlot } from \"../ui/BiometricSlot\";\r\nimport { FaceCameraModal } from \"./FaceCameraModal\";\r\nimport { ModuleHeader } from \"./ModuleHeader\";\r\nimport { Button } from \"../ui/Button\";\r\nimport { TbDownload, TbReload, TbSend, TbFaceId } from \"react-icons/tb\";\r\nimport { MissingBiometricModal } from \"../ui/MissingFingerModal\";\r\nimport { useEnrollmentStore } from \"../../lib/stores/enrollmentStore\";\r\nimport {\r\n getImageSrcForDisplay,\r\n normalizeImageForStorage,\r\n} from \"../../lib/utils/imageHelpers\";\r\n\r\ntype FaceSlotData = {\r\n image: string;\r\n quality: number;\r\n} | null;\r\n\r\nconst INITIAL_SLOTS: FaceSlotData[] = Array(5).fill(null);\r\n\r\nexport default function FaceEnrollModule({ className = \"\" }: { className?: string }) {\r\n const {\r\n faceCaptures,\r\n setFaceCaptures,\r\n removeFace,\r\n addMissingFace,\r\n removeMissingFace,\r\n missingFaces,\r\n } = useEnrollmentStore();\r\n const [slots, setSlots] = useState<FaceSlotData[]>(INITIAL_SLOTS);\r\n const [faceToMarkMissing, setFaceToMarkMissing] = useState<number | null>(\r\n null,\r\n );\r\n const [finalTemplate, setFinalTemplate] = useState<string | null>(null);\r\n const [isModalOpen, setIsModalOpen] = useState(false);\r\n const [activeSlot, setActiveSlot] = useState(0);\r\n const [isProcessing, setIsProcessing] = useState(false);\r\n const [jp2Images, setJp2Images] = useState<string[]>([]);\r\n\r\n const { isConnected, sendMessage, registerHandler, unregisterHandler } =\r\n useBiometricStore();\r\n const addMessage = useUiStore((s) => s.addMessage);\r\n\r\n useEffect(() => {\r\n if (faceCaptures && faceCaptures.length > 0) {\r\n const newSlots = [...faceCaptures];\r\n while (newSlots.length < 5) newSlots.push(null);\r\n setSlots(newSlots);\r\n }\r\n }, [faceCaptures]);\r\n\r\n useEffect(() => {\r\n const onComplete = (msg: any) => {\r\n setIsProcessing(false);\r\n const tmpl = msg.biometricData?.finalTemplate;\r\n const jp2List = msg.biometricData?.jp2Base64Images || [];\r\n\r\n setFinalTemplate(tmpl);\r\n setJp2Images(jp2List);\r\n\r\n const formattedFaces = jp2List.map((img: string) => ({\r\n image: normalizeImageForStorage(img),\r\n quality: 100,\r\n }));\r\n\r\n setFaceCaptures(formattedFaces);\r\n addMessage(\"Plantilla facial generada exitosamente.\");\r\n toast.success(\"Enrolamiento facial completado\");\r\n };\r\n\r\n const onError = (msg: any) => {\r\n setIsProcessing(false);\r\n const err = msg.error || \"Error de validación\";\r\n toast.error(err, { duration: 5000 });\r\n addMessage(\"Error: \" + err);\r\n };\r\n\r\n registerHandler(\"FACE_ENROLLMENT_COMPLETE\", onComplete);\r\n registerHandler(\"ERROR\", onError);\r\n\r\n return () => {\r\n unregisterHandler(\"FACE_ENROLLMENT_COMPLETE\");\r\n unregisterHandler(\"ERROR\");\r\n };\r\n }, [registerHandler, unregisterHandler, addMessage, setFaceCaptures]);\r\n\r\n const capturedCount = useMemo(() => {\r\n const captured = slots.filter((s) => s !== null).length;\r\n const missing = Object.keys(missingFaces).length;\r\n return captured + missing;\r\n }, [slots, missingFaces]);\r\n\r\n const openSlot = (idx: number) => {\r\n if (!isConnected) return toast.error(\"Sistema desconectado.\");\r\n setActiveSlot(idx);\r\n setIsModalOpen(true);\r\n };\r\n\r\n const handleCaptured = (img: string, quality: number) => {\r\n const next = [...slots];\r\n next[activeSlot] = {\r\n image: normalizeImageForStorage(img),\r\n quality: quality,\r\n };\r\n setSlots(next);\r\n setFaceCaptures(next);\r\n setIsModalOpen(false);\r\n };\r\n\r\n const handleDeleteFace = (index: number) => {\r\n const next = [...slots];\r\n next[index] = null;\r\n setSlots(next);\r\n removeFace(index);\r\n toast.success(`Ángulo ${index + 1} eliminado`);\r\n };\r\n\r\n const handleConfirmMissingFace = (reason: string) => {\r\n if (faceToMarkMissing !== null) {\r\n const next = [...slots];\r\n next[faceToMarkMissing] = null;\r\n setSlots(next);\r\n removeFace(faceToMarkMissing);\r\n addMissingFace(faceToMarkMissing, reason);\r\n setFaceToMarkMissing(null);\r\n }\r\n };\r\n\r\n const finalize = () => {\r\n const validSlots = slots.filter((s) => s !== null);\r\n const missingCount = Object.keys(missingFaces).length;\r\n const totalAccountedFor = validSlots.length + missingCount;\r\n const imgs = validSlots.map((s) => s!.image);\r\n\r\n if (totalAccountedFor < 5) {\r\n return toast.error(\r\n `Se requieren 5 ángulos (${validSlots.length} capturados, ${missingCount} omitidos).`,\r\n );\r\n }\r\n if (imgs.length === 0) {\r\n return toast.error(\"Capture al menos un ángulo facial.\");\r\n }\r\n setIsProcessing(true);\r\n sendMessage({\r\n messageType: \"FINALIZE_FACE_ENROLLMENT\",\r\n biometricData: { faceImages: imgs },\r\n });\r\n };\r\n\r\n const downloadPackage = () => {\r\n if (jp2Images.length === 0)\r\n return toast.error(\"No hay datos para descargar\");\r\n const payload = { faceIsoImages: jp2Images, template: finalTemplate };\r\n const blob = new Blob([JSON.stringify(payload, null, 2)], {\r\n type: \"application/json\",\r\n });\r\n const url = URL.createObjectURL(blob);\r\n const a = document.createElement(\"a\");\r\n a.href = url;\r\n a.download = `FACE_ENROLL_${new Date().getTime()}.json`;\r\n a.click();\r\n };\r\n\r\n const resetAll = () => {\r\n setSlots(INITIAL_SLOTS);\r\n setFinalTemplate(null);\r\n setFaceCaptures(Array(5).fill(null));\r\n setJp2Images([]);\r\n setIsProcessing(false);\r\n };\r\n\r\n const isBusy = isProcessing || isModalOpen;\r\n\r\n return (\r\n <div className=\"space-y-8 animate-in fade-in duration-500\">\r\n <ModuleHeader\r\n icon={<TbFaceId size={24} />}\r\n title=\"Enrolamiento Facial\"\r\n subtitle=\"Capture 5 ángulos de alta definición para el registro facial.\"\r\n progress={{ current: capturedCount, total: 5 }}\r\n >\r\n <Button\r\n variant=\"success\"\r\n size=\"sm\"\r\n icon={<TbSend size={16} />}\r\n onClick={finalize}\r\n disabled={!isConnected || isBusy || capturedCount < 5}\r\n isLoading={isProcessing}\r\n >\r\n Guardar\r\n </Button>\r\n {finalTemplate && (\r\n <Button\r\n variant=\"secondary\"\r\n size=\"sm\"\r\n icon={<TbDownload size={16} />}\r\n onClick={downloadPackage}\r\n >\r\n Exportar\r\n </Button>\r\n )}\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n icon={<TbReload size={16} />}\r\n onClick={resetAll}\r\n disabled={isBusy}\r\n >\r\n Limpiar\r\n </Button>\r\n </ModuleHeader>\r\n\r\n {finalTemplate && (\r\n <div className=\"glass p-8 rounded-sm text-center w-full relative overflow-hidden border border-green-500/20\">\r\n <div className=\"absolute inset-0 bg-gradient-to-b from-quality-good/10 to-transparent pointer-events-none\" />\r\n <TbFaceId className=\"mx-auto text-green-500 mb-4\" size={40} />\r\n <h3 className=\"text-xl font-bold text-foreground mb-2\">\r\n Biometría Generada Correctamente\r\n </h3>\r\n <div className=\"flex justify-center gap-3 mt-6\">\r\n <Button\r\n variant=\"success\"\r\n size=\"md\"\r\n icon={<TbDownload size={18} />}\r\n onClick={downloadPackage}\r\n >\r\n Exportar JSON\r\n </Button>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"md\"\r\n icon={<TbReload size={18} />}\r\n onClick={resetAll}\r\n >\r\n Nuevo Trámite\r\n </Button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {!finalTemplate && (\r\n <div className=\"grid grid-cols-2 md:grid-cols-5 gap-4\">\r\n {slots.map((s, i) => {\r\n const isMissing = !!missingFaces[i];\r\n return (\r\n <BiometricSlot\r\n key={i}\r\n title={`Ángulo ${i + 1}`}\r\n position={`${i + 1}`}\r\n status={isMissing ? \"pending\" : s ? \"captured\" : \"pending\"}\r\n imageUrl={s ? getImageSrcForDisplay(s.image, \"jpeg\") : null}\r\n quality={s?.quality}\r\n iconType=\"face\"\r\n onCapture={() => openSlot(i)}\r\n onDelete={() => handleDeleteFace(i)}\r\n onRequestMissing={() => setFaceToMarkMissing(i)}\r\n onRestore={() => removeMissingFace(i)}\r\n missingReason={missingFaces[i] || null}\r\n isDisabled={!isConnected || isBusy}\r\n />\r\n );\r\n })}\r\n </div>\r\n )}\r\n\r\n <MissingBiometricModal\r\n isOpen={faceToMarkMissing !== null}\r\n onClose={() => setFaceToMarkMissing(null)}\r\n onConfirm={handleConfirmMissingFace}\r\n positionName={\r\n faceToMarkMissing !== null ? `Ángulo ${faceToMarkMissing + 1}` : \"\"\r\n }\r\n biometricType=\"face\"\r\n />\r\n\r\n <FaceCameraModal\r\n isOpen={isModalOpen}\r\n onClose={() => setIsModalOpen(false)}\r\n onCaptured={handleCaptured}\r\n />\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { useState, useRef, useEffect, useCallback } from \"react\";\r\nimport { toast } from \"react-hot-toast\";\r\nimport { useBiometricStore } from \"../../lib/stores/biometricStore\";\r\nimport { useUiStore } from \"../../lib/stores/uiStore\";\r\nimport { Modal } from \"../ui/Modal\";\r\nimport { Loader } from \"../ui/Loader\";\r\nimport { TbCamera, TbAlertTriangle } from \"react-icons/tb\";\r\n\r\ninterface FaceCameraModalProps {\r\n isOpen: boolean;\r\n onClose: () => void;\r\n onCaptured: (img: string, quality: number) => void;\r\n}\r\n\r\nexport function FaceCameraModal({\r\n isOpen,\r\n onClose,\r\n onCaptured,\r\n}: FaceCameraModalProps) {\r\n const videoRef = useRef<HTMLVideoElement>(null);\r\n const canvasRef = useRef<HTMLCanvasElement>(null);\r\n\r\n const [isCameraLoading, setIsCameraLoading] = useState(true);\r\n const [isValidating, setIsValidating] = useState(false);\r\n const [validationError, setValidationError] = useState<string | null>(null);\r\n const [tempImage, setTempImage] = useState<string | null>(null);\r\n\r\n const { sendMessage, registerHandler, unregisterHandler } =\r\n useBiometricStore();\r\n const addMessage = useUiStore((s) => s.addMessage);\r\n\r\n const startCamera = useCallback(async () => {\r\n setIsCameraLoading(true);\r\n setValidationError(null);\r\n try {\r\n const stream = await navigator.mediaDevices.getUserMedia({\r\n video: {\r\n width: { ideal: 1920 },\r\n height: { ideal: 1080 },\r\n facingMode: \"user\",\r\n },\r\n });\r\n\r\n if (videoRef.current) {\r\n videoRef.current.srcObject = stream;\r\n videoRef.current.onloadedmetadata = () => setIsCameraLoading(false);\r\n }\r\n } catch (err) {\r\n const msg = \"No se pudo acceder a la cámara. Verifique permisos.\";\r\n toast.error(msg);\r\n setValidationError(msg);\r\n setIsCameraLoading(false);\r\n }\r\n }, []);\r\n\r\n const stopCamera = useCallback(() => {\r\n if (videoRef.current?.srcObject) {\r\n (videoRef.current.srcObject as MediaStream)\r\n .getTracks()\r\n .forEach((t) => t.stop());\r\n videoRef.current.srcObject = null;\r\n }\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (isOpen) {\r\n const timer = setTimeout(() => {\r\n startCamera();\r\n }, 0);\r\n\r\n return () => clearTimeout(timer);\r\n } else {\r\n stopCamera();\r\n }\r\n return () => stopCamera();\r\n }, [isOpen, startCamera, stopCamera]);\r\n\r\n const captureAndValidate = () => {\r\n const video = videoRef.current;\r\n const canvas = canvasRef.current;\r\n if (!video || !canvas) return;\r\n\r\n setValidationError(null);\r\n\r\n canvas.width = video.videoWidth;\r\n canvas.height = video.videoHeight;\r\n const ctx = canvas.getContext(\"2d\");\r\n ctx?.drawImage(video, 0, 0);\r\n\r\n const base64 = canvas.toDataURL(\"image/jpeg\", 0.95).split(\",\")[1];\r\n setTempImage(base64);\r\n\r\n setIsValidating(true);\r\n sendMessage({\r\n messageType: \"VALIDATE_FACE_IMAGE\",\r\n Payload: base64,\r\n });\r\n };\r\n\r\n useEffect(() => {\r\n const onValidationResult = (msg: any) => {\r\n if (!isValidating) return;\r\n\r\n setIsValidating(false);\r\n const { isValid, message, qualityScore } = msg.payload;\r\n\r\n if (isValid) {\r\n toast.success(`Foto aceptada (Calidad: ${qualityScore})`);\r\n addMessage(`✅ Foto aceptada. Calidad: ${qualityScore}`);\r\n setValidationError(null);\r\n\r\n if (tempImage) onCaptured(tempImage, qualityScore || 0);\r\n } else {\r\n setValidationError(message || \"La imagen no cumple los estándares.\");\r\n addMessage(`❌ Foto rechazada: ${message}`);\r\n setTempImage(null);\r\n }\r\n };\r\n\r\n registerHandler(\"FACE_VALIDATION_RESULT\", onValidationResult);\r\n return () => unregisterHandler(\"FACE_VALIDATION_RESULT\");\r\n }, [\r\n isValidating,\r\n tempImage,\r\n onCaptured,\r\n registerHandler,\r\n unregisterHandler,\r\n addMessage,\r\n ]);\r\n\r\n return (\r\n <Modal\r\n isOpen={isOpen}\r\n onClose={onClose}\r\n title=\"Captura de Rostro\"\r\n allowClose={!isValidating}\r\n >\r\n <div className=\"flex flex-col items-center w-full max-w-4xl mx-auto\">\r\n <div\r\n className={`relative w-full aspect-video bg-black rounded-md overflow-hidden shadow-2xl border-2 transition-colors duration-300 ${\r\n validationError ? \"border-red-500/50\" : \"border-white/10\"\r\n }`}\r\n >\r\n <video\r\n ref={videoRef}\r\n autoPlay\r\n playsInline\r\n muted\r\n className={`w-full h-full object-cover transform scale-x-[-1] ${\r\n isValidating ? \"opacity-50 blur-sm\" : \"\"\r\n }`}\r\n />\r\n\r\n {(isCameraLoading || isValidating) && (\r\n <div className=\"absolute inset-0 flex flex-col items-center justify-center z-20 bg-black/40 backdrop-blur-sm\">\r\n <Loader\r\n text={isValidating ? \"Validando...\" : \"Iniciando cámara...\"}\r\n size={50}\r\n />\r\n </div>\r\n )}\r\n\r\n {!isCameraLoading && !isValidating && (\r\n <div className=\"absolute inset-0 pointer-events-none opacity-60\">\r\n <div className=\"absolute inset-0 m-auto w-[30%] h-[50%] border-2 border-dashed border-white/70 rounded-[40%]\"></div>\r\n <div className=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-4 h-4 text-white/80\">\r\n +\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {validationError && (\r\n <div className=\"w-full mt-4 p-3 bg-red-500/10 border border-red-500/20 rounded-md flex items-center justify-center gap-3 animate-in fade-in slide-in-from-bottom-2\">\r\n <div className=\"p-2 bg-red-500/20 rounded-full text-red-500\">\r\n <TbAlertTriangle size={20} />\r\n </div>\r\n <p className=\"text-red-500 font-medium text-sm text-center\">\r\n {validationError}\r\n </p>\r\n </div>\r\n )}\r\n\r\n <div className=\"w-full mt-6 flex justify-center\">\r\n <button\r\n onClick={captureAndValidate}\r\n disabled={isCameraLoading || isValidating}\r\n className={`flex items-center gap-3 px-12 py-4 rounded-full font-bold text-lg shadow-xl transition-all ${\r\n isCameraLoading || isValidating\r\n ? \"bg-secondary text-foreground/50 cursor-wait\"\r\n : \"bg-primary text-white hover:scale-105 active:scale-95 shadow-primary/25\"\r\n }`}\r\n >\r\n {isValidating ? (\r\n \"Analizando...\"\r\n ) : (\r\n <>\r\n <TbCamera size={26} /> <span>CAPTURAR</span>\r\n </>\r\n )}\r\n </button>\r\n </div>\r\n <canvas ref={canvasRef} className=\"hidden\"></canvas>\r\n </div>\r\n </Modal>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { useState, useEffect, useMemo, useRef } from \"react\";\r\nimport { toast } from \"react-hot-toast\";\r\nimport { useBiometricStore } from \"../../lib/stores/biometricStore\";\r\nimport { useUiStore } from \"../../lib/stores/uiStore\";\r\nimport { useEnrollmentStore } from \"../../lib/stores/enrollmentStore\";\r\nimport { BiometricSlot } from \"../ui/BiometricSlot\";\r\nimport { PalmCaptureModal } from \"./PalmCaptureModal\";\r\nimport { ModuleHeader } from \"./ModuleHeader\";\r\nimport { Modal } from \"../ui/Modal\";\r\nimport { Button } from \"../ui/Button\";\r\nimport { TbDownload, TbReload, TbSend, TbHandStop } from \"react-icons/tb\";\r\nimport { MissingBiometricModal } from \"../ui/MissingFingerModal\";\r\nimport {\r\n getImageSrcForDisplay,\r\n} from \"../../lib/utils/imageHelpers\";\r\n\r\nconst PALM_NAMES: Record<string, string> = {\r\n UPPERPALMLEFT: \"Superior Izq.\",\r\n LOWERPALMLEFT: \"Inferior Izq.\",\r\n WRITERSPALMLEFT: \"Escritor Izq.\",\r\n UPPERPALMRIGHT: \"Superior Der.\",\r\n LOWERPALMRIGHT: \"Inferior Der.\",\r\n WRITERSPALMRIGHT: \"Escritor Der.\",\r\n};\r\n\r\nconst LEFT_PALMS = [\"UPPERPALMLEFT\", \"LOWERPALMLEFT\", \"WRITERSPALMLEFT\"];\r\nconst RIGHT_PALMS = [\"UPPERPALMRIGHT\", \"LOWERPALMRIGHT\", \"WRITERSPALMRIGHT\"];\r\n\r\ninterface PalmResult {\r\n finger: string;\r\n quality: number;\r\n image: string;\r\n isCaptured: boolean;\r\n error?: string | null;\r\n}\r\n\r\ntype PalmResultsMap = Record<string, PalmResult>;\r\n\r\nexport default function PalmEnrollModule({ className = \"\" }: { className?: string }) {\r\n const {\r\n addPalm,\r\n removePalm,\r\n addMissingPalm,\r\n removeMissingPalm,\r\n missingPalms,\r\n palms: storePalms,\r\n } = useEnrollmentStore();\r\n const [palmResults, setPalmResults] = useState<PalmResultsMap>({});\r\n const [finalTemplate, setFinalTemplate] = useState<string | null>(null);\r\n const [palmWsqs, setPalmWsqs] = useState<Record<string, string>>({});\r\n\r\n const [isModalOpen, setIsModalOpen] = useState(false);\r\n const isModalOpenRef = useRef(isModalOpen);\r\n const [isProcessing, setIsProcessing] = useState(false);\r\n const [currentPalm, setCurrentPalm] = useState<string | null>(null);\r\n const [previewImage, setPreviewImage] = useState<string | null>(null);\r\n const [modalStatus, setModalStatus] = useState(\"Esperando...\");\r\n const [modalError, setModalError] = useState(false);\r\n\r\n const [pendingPalm, setPendingPalm] = useState<string | null>(null);\r\n const [showReplaceConfirm, setShowReplaceConfirm] = useState(false);\r\n const [palmToMarkMissing, setPalmToMarkMissing] = useState<string | null>(\r\n null,\r\n );\r\n\r\n const { isConnected, sendMessage, registerHandler, unregisterHandler } =\r\n useBiometricStore();\r\n const addMessage = useUiStore((s) => s.addMessage);\r\n\r\n useEffect(() => {\r\n const loaded: PalmResultsMap = {};\r\n Object.entries(storePalms).forEach(([key, item]) => {\r\n loaded[key] = {\r\n finger: key,\r\n quality: item.quality,\r\n image: item.image,\r\n isCaptured: true,\r\n error: null,\r\n };\r\n });\r\n setPalmResults((prev) => ({ ...prev, ...loaded }));\r\n }, [storePalms]);\r\n\r\n const capturedCount = useMemo(() => {\r\n const captured = Object.values(palmResults).filter(\r\n (p) => p?.isCaptured,\r\n ).length;\r\n const missing = Object.keys(missingPalms).length;\r\n return captured + missing;\r\n }, [palmResults, missingPalms]);\r\n\r\n const isCapturing = isProcessing || isModalOpen;\r\n\r\n useEffect(() => {\r\n isModalOpenRef.current = isModalOpen;\r\n }, [isModalOpen]);\r\n\r\n useEffect(() => {\r\n const onPreview = (d: any) => {\r\n if (!isModalOpenRef.current) return;\r\n setPreviewImage(d.payload);\r\n };\r\n\r\n const onStatus = (d: any) => {\r\n if (!isModalOpenRef.current) return;\r\n setModalStatus(d.payload.message);\r\n };\r\n\r\n const onComplete = (d: any) => {\r\n const seg = d.biometricData?.segments?.[0];\r\n if (seg && seg.finger === currentPalm) {\r\n setPalmResults((prev) => ({\r\n ...prev,\r\n [seg.finger]: { ...seg, isCaptured: true },\r\n }));\r\n }\r\n toast.success(\"Palma capturada\");\r\n setIsProcessing(false);\r\n setTimeout(() => setIsModalOpen(false), 500);\r\n };\r\n\r\n const onError = (d: any) => {\r\n const msg = d.error || \"Error durante la captura\";\r\n toast.error(msg);\r\n setModalError(true);\r\n setModalStatus(msg);\r\n setIsProcessing(false);\r\n };\r\n\r\n const onTemplate = (d: any) => {\r\n const tmpl = d.biometricData?.finalTemplate || \"\";\r\n const wsqFiles = d.biometricData?.wsqFiles || {};\r\n setPalmWsqs(wsqFiles);\r\n setFinalTemplate(tmpl);\r\n\r\n Object.entries(wsqFiles).forEach(([pos, base64]) => {\r\n const cached = palmResults[pos];\r\n const imageToSave = cached?.image || (base64 as string);\r\n addPalm(pos, imageToSave, cached?.quality || 100);\r\n });\r\n\r\n addMessage(\"Plantilla de palmas generada exitosamente.\");\r\n toast.success(\"Plantilla generada\");\r\n };\r\n\r\n registerHandler(\"PALM_PREVIEW_FRAME\", onPreview);\r\n registerHandler(\"PALM_CAPTURE_STATUS\", onStatus);\r\n registerHandler(\"PALM_CAPTURE_COMPLETE\", onComplete);\r\n registerHandler(\"PALM_TEMPLATE_GENERATED\", onTemplate);\r\n registerHandler(\"PALM_ERROR\", onError);\r\n registerHandler(\"ERROR\", onError);\r\n\r\n return () => {\r\n unregisterHandler(\"PALM_PREVIEW_FRAME\");\r\n unregisterHandler(\"PALM_CAPTURE_STATUS\");\r\n unregisterHandler(\"PALM_CAPTURE_COMPLETE\");\r\n unregisterHandler(\"PALM_TEMPLATE_GENERATED\");\r\n unregisterHandler(\"PALM_ERROR\");\r\n unregisterHandler(\"ERROR\");\r\n };\r\n }, [\r\n currentPalm,\r\n registerHandler,\r\n unregisterHandler,\r\n addMessage,\r\n addPalm,\r\n palmResults,\r\n ]);\r\n\r\n const openCapture = (pos: string) => {\r\n setPreviewImage(null);\r\n setModalError(false);\r\n setModalStatus(\"Iniciando escáner...\");\r\n setCurrentPalm(pos);\r\n setIsModalOpen(true);\r\n setIsProcessing(true);\r\n sendMessage({\r\n messageType: \"START_PALM_CAPTURE\",\r\n biometricData: { targetFinger: pos },\r\n });\r\n };\r\n\r\n const startCapture = (pos: string) => {\r\n if (!isConnected || isCapturing) return;\r\n if (palmResults[pos]?.isCaptured) {\r\n setPendingPalm(pos);\r\n setShowReplaceConfirm(true);\r\n return;\r\n }\r\n openCapture(pos);\r\n };\r\n\r\n const retryCapture = () => {\r\n if (!currentPalm) return;\r\n openCapture(currentPalm);\r\n };\r\n\r\n const cancelCapture = () => {\r\n sendMessage({ messageType: \"ABORT_PALM_CAPTURE\" });\r\n setIsModalOpen(false);\r\n setIsProcessing(false);\r\n setModalError(false);\r\n setPreviewImage(null);\r\n setCurrentPalm(null);\r\n };\r\n\r\n const handleDeletePalm = (pos: string) => {\r\n setPalmResults((prev) => {\r\n const next = { ...prev };\r\n delete next[pos];\r\n return next;\r\n });\r\n removePalm(pos);\r\n toast.success(`Palma ${PALM_NAMES[pos]} eliminada`);\r\n };\r\n\r\n const handleConfirmMissingPalm = (reason: string) => {\r\n if (palmToMarkMissing) {\r\n setPalmResults((prev) => {\r\n const next = { ...prev };\r\n delete next[palmToMarkMissing];\r\n return next;\r\n });\r\n removePalm(palmToMarkMissing);\r\n addMissingPalm(palmToMarkMissing, reason);\r\n setPalmToMarkMissing(null);\r\n }\r\n };\r\n\r\n const finalize = () => {\r\n if (capturedCount === 0)\r\n return toast.error(\"Capture al menos una palma.\");\r\n setIsProcessing(true);\r\n sendMessage({ messageType: \"FINALIZE_PALM_ENROLLMENT\" });\r\n };\r\n\r\n const resetState = () => {\r\n setPalmResults({});\r\n setFinalTemplate(null);\r\n setIsProcessing(false);\r\n };\r\n\r\n const downloadTemplate = () => {\r\n if (!finalTemplate) return;\r\n const payload = {\r\n template: finalTemplate,\r\n wsqImages: palmWsqs,\r\n };\r\n const blob = new Blob([JSON.stringify(payload, null, 2)], {\r\n type: \"application/json\",\r\n });\r\n const url = URL.createObjectURL(blob);\r\n const a = document.createElement(\"a\");\r\n a.href = url;\r\n a.download = \"paquete_palmas_abis.json\";\r\n a.click();\r\n URL.revokeObjectURL(url);\r\n };\r\n\r\n const renderPalmGrid = (palms: string[]) =>\r\n palms.map((pos) => {\r\n const r = palmResults[pos];\r\n const isMissing = !!missingPalms[pos];\r\n const status = isMissing\r\n ? \"pending\"\r\n : r\r\n ? r.error\r\n ? \"error\"\r\n : \"captured\"\r\n : \"pending\";\r\n return (\r\n <BiometricSlot\r\n key={pos}\r\n position={pos}\r\n title={PALM_NAMES[pos]}\r\n status={status}\r\n imageUrl={getImageSrcForDisplay(r?.image, \"png\")}\r\n quality={r?.quality}\r\n iconType=\"palm\"\r\n onCapture={() => startCapture(pos)}\r\n onDelete={() => handleDeletePalm(pos)}\r\n onRequestMissing={() => setPalmToMarkMissing(pos)}\r\n onRestore={() => removeMissingPalm(pos)}\r\n missingReason={missingPalms[pos] || null}\r\n isDisabled={!isConnected || isCapturing}\r\n />\r\n );\r\n });\r\n\r\n return (\r\n <div className=\"space-y-8 animate-in fade-in duration-500\">\r\n <ModuleHeader\r\n icon={<TbHandStop size={24} />}\r\n title=\"Enrolamiento de Palmas\"\r\n subtitle=\"Capture las palmas superiores, inferiores y de escritor de ambas manos.\"\r\n progress={{ current: capturedCount, total: 6 }}\r\n >\r\n <Button\r\n variant=\"success\"\r\n size=\"sm\"\r\n icon={<TbSend size={16} />}\r\n onClick={finalize}\r\n disabled={!isConnected || isCapturing || capturedCount === 0}\r\n isLoading={isProcessing}\r\n >\r\n Guardar\r\n </Button>\r\n {finalTemplate && (\r\n <Button\r\n variant=\"secondary\"\r\n size=\"sm\"\r\n icon={<TbDownload size={16} />}\r\n onClick={downloadTemplate}\r\n >\r\n Exportar\r\n </Button>\r\n )}\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n icon={<TbReload size={16} />}\r\n onClick={resetState}\r\n disabled={isCapturing}\r\n >\r\n Limpiar\r\n </Button>\r\n </ModuleHeader>\r\n\r\n {finalTemplate && (\r\n <div className=\"glass p-8 rounded-sm text-center w-full relative overflow-hidden border border-green-500/20\">\r\n <div className=\"absolute inset-0 bg-gradient-to-b from-quality-good/10 to-transparent pointer-events-none\" />\r\n <p className=\"text-foreground/60 mb-6 text-base\">\r\n Paquete ABIS generado exitosamente\r\n </p>\r\n <div className=\"flex flex-col sm:flex-row justify-center gap-3\">\r\n <Button\r\n variant=\"success\"\r\n size=\"md\"\r\n icon={<TbDownload size={18} />}\r\n onClick={downloadTemplate}\r\n >\r\n Descargar Paquete ABIS\r\n </Button>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"md\"\r\n icon={<TbReload size={18} />}\r\n onClick={resetState}\r\n >\r\n Nuevo Trámite\r\n </Button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <div className=\"grid grid-cols-1 xl:grid-cols-2 gap-8\">\r\n <div className=\"glass p-6 rounded-sm border border-white/10 relative overflow-hidden group\">\r\n <div className=\"absolute top-0 right-0 p-4 opacity-5 group-hover:opacity-10 transition-opacity\">\r\n <TbHandStop size={120} />\r\n </div>\r\n <h3 className=\"text-lg font-bold text-foreground mb-5 pl-3 border-l-4 border-primary\">\r\n Mano Derecha\r\n </h3>\r\n <div className=\"grid grid-cols-1 sm:grid-cols-3 gap-4\">\r\n {renderPalmGrid(RIGHT_PALMS)}\r\n </div>\r\n </div>\r\n\r\n <div className=\"glass p-6 rounded-sm border border-white/10 relative overflow-hidden group\">\r\n <div className=\"absolute top-0 right-0 p-4 opacity-5 group-hover:opacity-10 transition-opacity\">\r\n <TbHandStop size={120} className=\"-scale-x-100\" />\r\n </div>\r\n <h3 className=\"text-lg font-bold text-foreground mb-5 pl-3 border-l-4 border-secondary-foreground/50\">\r\n Mano Izquierda\r\n </h3>\r\n <div className=\"grid grid-cols-1 sm:grid-cols-3 gap-4\">\r\n {renderPalmGrid(LEFT_PALMS)}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <PalmCaptureModal\r\n isOpen={isModalOpen}\r\n onCancel={cancelCapture}\r\n onRetry={retryCapture}\r\n previewImage={previewImage}\r\n statusMessage={modalStatus}\r\n errorState={modalError}\r\n captureType={\r\n currentPalm ? PALM_NAMES[currentPalm] : \"Captura de Palma\"\r\n }\r\n />\r\n\r\n <Modal\r\n isOpen={showReplaceConfirm}\r\n onClose={() => setShowReplaceConfirm(false)}\r\n title=\"¿Reemplazar Captura?\"\r\n >\r\n <div className=\"text-center p-4\">\r\n <p className=\"text-foreground/80 mb-6 text-sm leading-relaxed\">\r\n Ya existe una captura guardada para{\" \"}\r\n <span className=\"font-bold text-foreground\">\r\n {pendingPalm && PALM_NAMES[pendingPalm]}\r\n </span>\r\n . ¿Desea capturar nuevamente y sobrescribir la anterior?\r\n </p>\r\n <div className=\"flex gap-3 justify-center\">\r\n <Button\r\n variant=\"secondary\"\r\n size=\"md\"\r\n onClick={() => setShowReplaceConfirm(false)}\r\n >\r\n Cancelar\r\n </Button>\r\n <Button\r\n variant=\"primary\"\r\n size=\"md\"\r\n onClick={() => {\r\n if (!pendingPalm) return;\r\n setShowReplaceConfirm(false);\r\n openCapture(pendingPalm);\r\n }}\r\n >\r\n Confirmar Reemplazo\r\n </Button>\r\n </div>\r\n </div>\r\n </Modal>\r\n\r\n <MissingBiometricModal\r\n isOpen={!!palmToMarkMissing}\r\n onClose={() => setPalmToMarkMissing(null)}\r\n onConfirm={handleConfirmMissingPalm}\r\n positionName={palmToMarkMissing ? PALM_NAMES[palmToMarkMissing] : \"\"}\r\n biometricType=\"palm\"\r\n />\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { Modal } from \"../ui/Modal\";\r\nimport { Loader } from \"../ui/Loader\";\r\nimport {\r\n TbHandStop,\r\n TbX,\r\n TbReload,\r\n TbScan,\r\n TbCheck,\r\n TbAlertTriangle,\r\n} from \"react-icons/tb\";\r\nimport { motion } from \"framer-motion\";\r\n\r\ninterface PalmCaptureModalProps {\r\n isOpen: boolean;\r\n onCancel: () => void;\r\n onRetry: () => void;\r\n captureType: string;\r\n previewImage: string | null;\r\n statusMessage: string;\r\n errorState: boolean;\r\n}\r\n\r\nexport function PalmCaptureModal({\r\n isOpen,\r\n onCancel,\r\n onRetry,\r\n captureType,\r\n previewImage,\r\n statusMessage,\r\n errorState,\r\n}: PalmCaptureModalProps) {\r\n const isWaiting = !previewImage && !errorState;\r\n\r\n let statusStyles = \"bg-primary/10 border-primary/20 text-primary\";\r\n let statusIcon = <Loader size={18} className=\"animate-spin\" />;\r\n\r\n if (errorState) {\r\n statusStyles =\r\n \"bg-red-500/10 border-red-500/20 text-red-600 dark:text-red-400\";\r\n statusIcon = <TbAlertTriangle size={20} />;\r\n } else if (\r\n statusMessage.toLowerCase().includes(\"éxito\") ||\r\n statusMessage.toLowerCase().includes(\"capturada\")\r\n ) {\r\n statusStyles =\r\n \"bg-green-500/10 border-green-500/20 text-green-600 dark:text-green-400\";\r\n statusIcon = <TbCheck size={20} />;\r\n }\r\n\r\n return (\r\n <Modal\r\n isOpen={isOpen}\r\n onClose={onCancel}\r\n title={captureType}\r\n allowClose={true}\r\n >\r\n <div className=\"flex flex-col md:flex-row gap-8 items-stretch p-2\">\r\n <div className=\"flex-1 flex justify-center bg-card/50 rounded-md p-4 border border-border/50 shadow-sm\">\r\n <div\r\n className=\"\r\n relative w-full max-w-[320px] aspect-[4/5]\r\n rounded-md overflow-hidden\r\n bg-zinc-950 border border-white/10\r\n shadow-inner flex items-center justify-center\r\n \"\r\n >\r\n <div\r\n className=\"absolute inset-0 pointer-events-none opacity-20\"\r\n style={{\r\n backgroundImage:\r\n \"linear-gradient(0deg, transparent 24%, #444 25%, #444 26%, transparent 27%, transparent 74%, #444 75%, #444 76%, transparent 77%, transparent), linear-gradient(90deg, transparent 24%, #444 25%, #444 26%, transparent 27%, transparent 74%, #444 75%, #444 76%, transparent 77%, transparent)\",\r\n backgroundSize: \"40px 40px\",\r\n }}\r\n />\r\n\r\n {isWaiting && (\r\n <motion.div\r\n className=\"absolute inset-x-0 h-[2px] bg-primary z-10 shadow-[0_0_15px_2px_rgba(var(--primary),0.8)]\"\r\n animate={{ top: [\"0%\", \"100%\", \"0%\"] }}\r\n transition={{ duration: 4, repeat: Infinity, ease: \"linear\" }}\r\n />\r\n )}\r\n\r\n <div className=\"relative z-1 w-full h-full flex items-center justify-center p-4\">\r\n {previewImage ? (\r\n <img\r\n src={previewImage}\r\n alt=\"Vista previa\"\r\n className=\"object-contain w-full h-full\"\r\n />\r\n ) : (\r\n <div className=\"flex flex-col items-center justify-center text-white/20 gap-4\">\r\n <div className=\"relative\">\r\n <TbHandStop size={90} className=\"opacity-60\" />\r\n <TbScan\r\n size={30}\r\n className=\"absolute -bottom-2 -right-2 text-primary animate-pulse\"\r\n />\r\n </div>\r\n <p className=\"text-[10px] font-bold tracking-[0.25em] uppercase opacity-60 text-center\">\r\n Esperando Escáner\r\n </p>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex-1 flex flex-col justify-between gap-6 min-h-[340px]\">\r\n <div className=\"space-y-6\">\r\n <div className=\"space-y-2\">\r\n <h4 className=\"text-xs font-bold text-muted-foreground uppercase tracking-wider\">\r\n Estado del Dispositivo\r\n </h4>\r\n <div\r\n className={`\r\n p-4 rounded-md border flex items-start gap-3 shadow-sm\r\n transition-colors duration-200 ${statusStyles}\r\n `}\r\n >\r\n <div className=\"mt-0.5 shrink-0\">{statusIcon}</div>\r\n <p className=\"text-sm font-medium leading-snug\">\r\n {statusMessage}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <div className=\"space-y-3\">\r\n <h4 className=\"text-xs font-semibold text-muted-foreground uppercase tracking-wide flex items-center gap-2\">\r\n <TbScan className=\"text-primary\" /> Instrucciones\r\n </h4>\r\n <div className=\"bg-secondary/30 border border-border rounded-md p-4\">\r\n <ul className=\"text-sm text-foreground/80 space-y-3\">\r\n <li className=\"flex gap-3\">\r\n <span className=\"w-1.5 h-1.5 rounded-full bg-primary mt-2 shrink-0\" />\r\n <span>Retire anillos y accesorios de la mano.</span>\r\n </li>\r\n <li className=\"flex gap-3\">\r\n <span className=\"w-1.5 h-1.5 rounded-full bg-primary mt-2 shrink-0\" />\r\n <span>Mantenga la palma plana contra la superficie.</span>\r\n </li>\r\n <li className=\"flex gap-3\">\r\n <span className=\"w-1.5 h-1.5 rounded-full bg-primary mt-2 shrink-0\" />\r\n <span>Junte los dedos firmemente.</span>\r\n </li>\r\n </ul>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex gap-3 pt-4 border-t border-border\">\r\n {errorState ? (\r\n <>\r\n <button\r\n onClick={onCancel}\r\n className=\"flex-1 px-4 py-3 rounded-md font-medium text-sm border border-border hover:bg-secondary transition-colors\"\r\n >\r\n Cancelar\r\n </button>\r\n <button\r\n onClick={onRetry}\r\n className=\"flex-1 flex items-center justify-center gap-2 px-4 py-3 rounded-md font-medium text-sm bg-primary text-primary-foreground hover:bg-primary/90 transition-all shadow-lg shadow-primary/20\"\r\n >\r\n <TbReload size={18} /> Reintentar\r\n </button>\r\n </>\r\n ) : (\r\n <button\r\n onClick={onCancel}\r\n className=\"\r\n w-full flex items-center justify-center gap-2 px-4 py-3\r\n rounded-md font-semibold text-sm\r\n bg-secondary hover:bg-red-500/10 \r\n text-foreground hover:text-red-600\r\n border border-transparent hover:border-red-500/20\r\n transition-all duration-200\r\n \"\r\n >\r\n <TbX size={18} />\r\n Cancelar Captura\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </Modal>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { useState, useEffect, useRef, useMemo } from \"react\";\r\nimport { toast } from \"react-hot-toast\";\r\nimport { useBiometricStore } from \"../../lib/stores/biometricStore\";\r\nimport { useUiStore } from \"../../lib/stores/uiStore\";\r\nimport { useEnrollmentStore } from \"../../lib/stores/enrollmentStore\";\r\nimport { BiometricSlot } from \"../ui/BiometricSlot\";\r\nimport { IrisCameraModal } from \"./IrisCameraModal\";\r\nimport { ModuleHeader } from \"./ModuleHeader\";\r\nimport { Select } from \"../ui/Select\";\r\nimport { Modal } from \"../ui/Modal\";\r\nimport { Button } from \"../ui/Button\";\r\nimport { MissingBiometricModal } from \"../ui/MissingFingerModal\";\r\nimport { TbDownload, TbReload, TbEye, TbScanEye } from \"react-icons/tb\";\r\nimport {\r\n getImageSrcForDisplay,\r\n normalizeImageForStorage,\r\n} from \"../../lib/utils/imageHelpers\";\r\n\r\nconst IRIS_NAMES: Record<string, string> = {\r\n right: \"Ojo Derecho\",\r\n left: \"Ojo Izquierdo\",\r\n};\r\n\r\nexport default function IrisEnrollModule({ className = \"\" }: { className?: string }) {\r\n const {\r\n setIrises,\r\n removeIris,\r\n addMissingIris,\r\n removeMissingIris,\r\n missingIrises,\r\n irises: storeIrises,\r\n } = useEnrollmentStore();\r\n\r\n const [finalTemplate, setFinalTemplate] = useState<string | null>(null);\r\n const [finalQuality, setFinalQuality] = useState<number | null>(null);\r\n const [jp2IrisImages, setJp2IrisImages] = useState<any>([]);\r\n\r\n const [rightIrisImage, setRightIrisImage] = useState<string | null>(null);\r\n const [leftIrisImage, setLeftIrisImage] = useState<string | null>(null);\r\n\r\n const [irisQualities, setIrisQualities] = useState({\r\n right: null as number | null,\r\n left: null as number | null,\r\n });\r\n\r\n const [irisMode, setIrisMode] = useState(\"both\");\r\n\r\n const [isModalOpen, setIsModalOpen] = useState(false);\r\n const isModalOpenRef = useRef(isModalOpen);\r\n const [isCapturing, setIsCapturing] = useState(false);\r\n\r\n const [modalStatus, setModalStatus] = useState(\"Esperando...\");\r\n const [previewRight, setPreviewRight] = useState<string | null>(null);\r\n const [previewLeft, setPreviewLeft] = useState<string | null>(null);\r\n const [distance, setDistance] = useState<number | null>(null);\r\n const [cameraStatus, setCameraStatus] = useState(\"Desconocido\");\r\n\r\n const [showReplaceConfirm, setShowReplaceConfirm] = useState(false);\r\n const [irisToMarkMissing, setIrisToMarkMissing] = useState<string | null>(\r\n null,\r\n );\r\n\r\n const { isConnected, sendMessage, registerHandler, unregisterHandler } =\r\n useBiometricStore();\r\n const addMessage = useUiStore((s) => s.addMessage);\r\n\r\n // Sincronizar desde el store cuando se cargan datos de la API\r\n useEffect(() => {\r\n if (storeIrises.right && !rightIrisImage) {\r\n const srcRight = getImageSrcForDisplay(storeIrises.right.image) || null;\r\n setRightIrisImage(srcRight);\r\n setIrisQualities((prev) => ({\r\n ...prev,\r\n right: storeIrises.right!.quality,\r\n }));\r\n }\r\n if (storeIrises.left && !leftIrisImage) {\r\n const srcLeft = getImageSrcForDisplay(storeIrises.left.image) || null;\r\n setLeftIrisImage(srcLeft);\r\n setIrisQualities((prev) => ({\r\n ...prev,\r\n left: storeIrises.left!.quality,\r\n }));\r\n }\r\n }, [storeIrises]);\r\n\r\n const capturedCount = useMemo(() => {\r\n let count = 0;\r\n if (rightIrisImage) count++;\r\n if (leftIrisImage) count++;\r\n count += Object.keys(missingIrises).length;\r\n return count;\r\n }, [rightIrisImage, leftIrisImage, missingIrises]);\r\n\r\n const modeOptions = [\r\n { value: \"both\", label: \"Ambos Ojos (Dual)\", icon: \"👀\" },\r\n { value: \"right\", label: \"Solo Derecho\", icon: \"👁\" },\r\n { value: \"left\", label: \"Solo Izquierdo\", icon: \"👁\" },\r\n ];\r\n\r\n const parseCameraStatus = (code: any) => {\r\n switch (Number(code)) {\r\n case 2:\r\n return \"Cámara lista\";\r\n case 4:\r\n return \"Capturando\";\r\n case 5:\r\n return \"Completado\";\r\n default:\r\n return \"Estado desconocido\";\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n isModalOpenRef.current = isModalOpen;\r\n }, [isModalOpen]);\r\n\r\n useEffect(() => {\r\n const handlePreviewFrame = (msg: any) => {\r\n if (!isModalOpenRef.current) return;\r\n const { irisRightBase64, irisLeftBase64 } = msg.biometricData || {};\r\n if (irisRightBase64)\r\n setPreviewRight(getImageSrcForDisplay(irisRightBase64) || null);\r\n if (irisLeftBase64)\r\n setPreviewLeft(getImageSrcForDisplay(irisLeftBase64) || null);\r\n };\r\n\r\n const handleComplete = (msg: any) => {\r\n const d = msg.biometricData || {};\r\n\r\n if (d.irisRightBase64)\r\n setRightIrisImage(getImageSrcForDisplay(d.irisRightBase64) || null);\r\n if (d.irisLeftBase64)\r\n setLeftIrisImage(getImageSrcForDisplay(d.irisLeftBase64) || null);\r\n\r\n setFinalTemplate(d.finalTemplate || null);\r\n setFinalQuality(d.quality || null);\r\n\r\n const jp2List = {\r\n right: d.irisRightBase64 || null,\r\n left: d.irisLeftBase64 || null,\r\n };\r\n setJp2IrisImages(jp2List);\r\n\r\n const rightData = d.irisRightBase64\r\n ? {\r\n image: normalizeImageForStorage(d.irisRightBase64),\r\n quality: d.irisRightQuality || 100,\r\n }\r\n : undefined;\r\n\r\n const leftData = d.irisLeftBase64\r\n ? {\r\n image: normalizeImageForStorage(d.irisLeftBase64),\r\n quality: d.irisLeftQuality || 100,\r\n }\r\n : undefined;\r\n\r\n setIrises(rightData, leftData);\r\n\r\n setIrisQualities({\r\n right: d.irisRightQuality || null,\r\n left: d.irisLeftQuality || null,\r\n });\r\n\r\n setIsCapturing(false);\r\n setIsModalOpen(false);\r\n setPreviewRight(null);\r\n setPreviewLeft(null);\r\n\r\n toast.success(\"Plantilla de iris generada\");\r\n };\r\n\r\n const handleStatusUpdate = (msg: any) => {\r\n if (!isModalOpenRef.current) return;\r\n const d = msg.biometricData || {};\r\n\r\n if (d.distance !== undefined) setDistance(d.distance);\r\n if (d.status !== undefined) {\r\n const st = parseCameraStatus(d.status);\r\n setCameraStatus(st);\r\n setModalStatus(\"Captura en proceso...\");\r\n }\r\n };\r\n\r\n const handleError = (msg: any) => {\r\n const err = msg.error || \"Error desconocido\";\r\n toast.error(err);\r\n setIsCapturing(false);\r\n setModalStatus(\"Error: \" + err);\r\n };\r\n\r\n registerHandler(\"IRIS_PREVIEW_FRAME\", handlePreviewFrame);\r\n registerHandler(\"IRIS_ENROLLMENT_COMPLETE\", handleComplete);\r\n registerHandler(\"IRIS_STATUS_UPDATE\", handleStatusUpdate);\r\n registerHandler(\"IRIS_ERROR\", handleError);\r\n\r\n return () => {\r\n unregisterHandler(\"IRIS_PREVIEW_FRAME\");\r\n unregisterHandler(\"IRIS_ENROLLMENT_COMPLETE\");\r\n unregisterHandler(\"IRIS_STATUS_UPDATE\");\r\n unregisterHandler(\"IRIS_ERROR\");\r\n };\r\n }, [registerHandler, unregisterHandler, setIrises]);\r\n\r\n const startCapture = () => {\r\n if (!isConnected) return toast.error(\"Servicio no conectado.\");\r\n\r\n setFinalTemplate(null);\r\n setFinalQuality(null);\r\n setRightIrisImage(null);\r\n setLeftIrisImage(null);\r\n setIrisQualities({ right: null, left: null });\r\n setPreviewRight(null);\r\n setPreviewLeft(null);\r\n\r\n setIsModalOpen(true);\r\n setModalStatus(\"Listo para iniciar\");\r\n setDistance(0);\r\n\r\n sendMessage({\r\n messageType: \"START_IRIS_PREVIEW\",\r\n biometricData: { mode: irisMode },\r\n });\r\n };\r\n\r\n const openModal = () => {\r\n const hasExistingData =\r\n (irisMode === \"both\" && (rightIrisImage || leftIrisImage)) ||\r\n (irisMode === \"right\" && rightIrisImage) ||\r\n (irisMode === \"left\" && leftIrisImage);\r\n\r\n if (hasExistingData) {\r\n setShowReplaceConfirm(true);\r\n } else {\r\n startCapture();\r\n }\r\n };\r\n\r\n const handleStartCapture = () => {\r\n setIsCapturing(true);\r\n setModalStatus(\"Capturando... Mantenga la mirada fija.\");\r\n sendMessage({\r\n messageType: \"START_IRIS_CAPTURE\",\r\n biometricData: { mode: irisMode },\r\n });\r\n };\r\n\r\n const handleAbortCapture = () => {\r\n setIsCapturing(false);\r\n setModalStatus(\"Cancelado por el usuario.\");\r\n sendMessage({ messageType: \"ABORT_IRIS_CAPTURE\" });\r\n };\r\n\r\n const closeModal = () => {\r\n if (isCapturing) handleAbortCapture();\r\n setIsModalOpen(false);\r\n };\r\n\r\n const downloadTemplate = () => {\r\n if (!finalTemplate) return;\r\n const payload = {\r\n template: finalTemplate,\r\n irisIsoImages: jp2IrisImages,\r\n };\r\n const blob = new Blob([JSON.stringify(payload, null, 2)], {\r\n type: \"application/json\",\r\n });\r\n const url = URL.createObjectURL(blob);\r\n const a = document.createElement(\"a\");\r\n a.href = url;\r\n a.download = \"paquete_iris_abis.json\";\r\n a.click();\r\n URL.revokeObjectURL(url);\r\n addMessage(\"Paquete de iris descargado correctamente.\");\r\n };\r\n\r\n const resetState = () => {\r\n setFinalTemplate(null);\r\n setFinalQuality(null);\r\n setRightIrisImage(null);\r\n setLeftIrisImage(null);\r\n setIrisQualities({ right: null, left: null });\r\n };\r\n\r\n const handleDeleteIris = (side: \"left\" | \"right\") => {\r\n if (side === \"right\") {\r\n setRightIrisImage(null);\r\n setIrisQualities((prev) => ({ ...prev, right: null }));\r\n } else {\r\n setLeftIrisImage(null);\r\n setIrisQualities((prev) => ({ ...prev, left: null }));\r\n }\r\n removeIris(side);\r\n toast.success(`Iris ${IRIS_NAMES[side]} eliminado`);\r\n };\r\n\r\n const handleConfirmMissingIris = (reason: string) => {\r\n if (irisToMarkMissing) {\r\n const side = irisToMarkMissing as \"left\" | \"right\";\r\n handleDeleteIris(side);\r\n addMissingIris(irisToMarkMissing, reason);\r\n setIrisToMarkMissing(null);\r\n }\r\n };\r\n\r\n const isBusy = isCapturing || isModalOpen;\r\n\r\n return (\r\n <div className=\"space-y-8 animate-in fade-in duration-500\">\r\n <ModuleHeader\r\n icon={<TbEye size={24} />}\r\n title=\"Enrolamiento de Iris\"\r\n subtitle=\"Utilice el escáner binocular para capturar el patrón del iris.\"\r\n progress={{ current: capturedCount, total: 2 }}\r\n >\r\n {finalTemplate && (\r\n <Button\r\n variant=\"secondary\"\r\n size=\"sm\"\r\n icon={<TbDownload size={16} />}\r\n onClick={downloadTemplate}\r\n >\r\n Exportar\r\n </Button>\r\n )}\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n icon={<TbReload size={16} />}\r\n onClick={resetState}\r\n disabled={isBusy}\r\n >\r\n Limpiar\r\n </Button>\r\n </ModuleHeader>\r\n\r\n <div className=\"flex flex-col sm:flex-row gap-4 items-end bg-secondary/30 p-4 rounded-md border border-white/5\">\r\n <div className=\"flex-1 w-full sm:w-auto\">\r\n <label className=\"text-xs font-bold text-foreground/50 uppercase tracking-wider mb-2 block\">\r\n Modo de Captura\r\n </label>\r\n <div className=\"w-full sm:max-w-xs\">\r\n <Select\r\n options={modeOptions}\r\n value={irisMode}\r\n onChange={setIrisMode}\r\n disabled={isBusy || !isConnected}\r\n />\r\n </div>\r\n </div>\r\n\r\n <Button\r\n variant=\"success\"\r\n size=\"md\"\r\n icon={<TbScanEye size={20} />}\r\n onClick={openModal}\r\n disabled={!isConnected || isBusy}\r\n >\r\n Iniciar Escáner\r\n </Button>\r\n </div>\r\n\r\n {finalTemplate && (\r\n <div className=\"glass p-8 rounded-sm text-center w-full relative overflow-hidden border border-green-500/20\">\r\n <div className=\"absolute inset-0 bg-gradient-to-b from-quality-good/10 to-transparent pointer-events-none\" />\r\n <p className=\"text-foreground/60 mb-6 text-base\">\r\n Paquete ABIS generado correctamente.\r\n </p>\r\n <div className=\"flex flex-col sm:flex-row justify-center gap-3\">\r\n <Button\r\n variant=\"success\"\r\n size=\"md\"\r\n icon={<TbDownload size={18} />}\r\n onClick={downloadTemplate}\r\n >\r\n Descargar Paquete ABIS\r\n </Button>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"md\"\r\n icon={<TbReload size={18} />}\r\n onClick={resetState}\r\n >\r\n Nuevo Trámite\r\n </Button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-8\">\r\n {([\"right\", \"left\"] as const).map((side) => {\r\n const image = side === \"right\" ? rightIrisImage : leftIrisImage;\r\n const quality = irisQualities[side];\r\n const missing = missingIrises[side] || null;\r\n\r\n return (\r\n <BiometricSlot\r\n key={side}\r\n position={side}\r\n title={IRIS_NAMES[side]}\r\n status={image ? \"captured\" : \"pending\"}\r\n imageUrl={image}\r\n quality={quality}\r\n iconType=\"iris\"\r\n missingReason={missing}\r\n onCapture={openModal}\r\n onDelete={() => handleDeleteIris(side)}\r\n onRequestMissing={() => setIrisToMarkMissing(side)}\r\n onRestore={() => removeMissingIris(side)}\r\n isDisabled={!isConnected || isBusy}\r\n className=\"min-h-[260px]\"\r\n />\r\n );\r\n })}\r\n </div>\r\n\r\n <IrisCameraModal\r\n isOpen={isModalOpen}\r\n onClose={closeModal}\r\n onStartCapture={handleStartCapture}\r\n onAbortCapture={handleAbortCapture}\r\n isCapturing={isCapturing}\r\n statusMessage={modalStatus}\r\n previewRight={previewRight}\r\n previewLeft={previewLeft}\r\n distance={distance}\r\n cameraStatus={cameraStatus}\r\n />\r\n\r\n <MissingBiometricModal\r\n isOpen={!!irisToMarkMissing}\r\n onClose={() => setIrisToMarkMissing(null)}\r\n onConfirm={handleConfirmMissingIris}\r\n positionName={\r\n irisToMarkMissing ? IRIS_NAMES[irisToMarkMissing] : \"\"\r\n }\r\n biometricType=\"iris\"\r\n />\r\n\r\n <Modal\r\n isOpen={showReplaceConfirm}\r\n onClose={() => setShowReplaceConfirm(false)}\r\n title=\"¿Reemplazar Captura?\"\r\n >\r\n <div className=\"text-center p-4\">\r\n <p className=\"text-foreground/80 mb-6 text-sm leading-relaxed\">\r\n Ya existe una captura de iris para este modo. ¿Desea capturar\r\n nuevamente y sobrescribir la anterior?\r\n </p>\r\n <div className=\"flex gap-3 justify-center\">\r\n <Button\r\n variant=\"secondary\"\r\n size=\"md\"\r\n onClick={() => setShowReplaceConfirm(false)}\r\n >\r\n Cancelar\r\n </Button>\r\n <Button\r\n variant=\"primary\"\r\n size=\"md\"\r\n onClick={() => {\r\n setShowReplaceConfirm(false);\r\n startCapture();\r\n }}\r\n >\r\n Confirmar Reemplazo\r\n </Button>\r\n </div>\r\n </div>\r\n </Modal>\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { useEffect, useRef } from \"react\";\r\nimport { Modal } from \"../ui/Modal\";\r\nimport {\r\n TbEye,\r\n TbPlayerPlay,\r\n TbPlayerStop,\r\n TbRuler,\r\n TbScan,\r\n TbActivity,\r\n} from \"react-icons/tb\";\r\nimport { Loader } from \"../ui/Loader\";\r\n\r\ninterface IrisCameraModalProps {\r\n isOpen: boolean;\r\n onClose: () => void;\r\n onStartCapture: () => void;\r\n onAbortCapture: () => void;\r\n isCapturing: boolean;\r\n statusMessage: string;\r\n previewRight: string | null;\r\n previewLeft: string | null;\r\n distance: number | null;\r\n cameraStatus: string;\r\n}\r\n\r\nexport function IrisCameraModal({\r\n isOpen,\r\n onClose,\r\n onStartCapture,\r\n onAbortCapture,\r\n isCapturing,\r\n statusMessage,\r\n previewRight,\r\n previewLeft,\r\n distance,\r\n cameraStatus,\r\n}: IrisCameraModalProps) {\r\n const imgRef = useRef<HTMLImageElement>(null);\r\n const lastBlobUrl = useRef<string | null>(null);\r\n\r\n useEffect(() => {\r\n const base64 = previewRight || previewLeft;\r\n if (imgRef.current && base64) {\r\n try {\r\n const byteString = atob(base64.split(\",\")[1]);\r\n const arrayBuffer = new ArrayBuffer(byteString.length);\r\n const intArray = new Uint8Array(arrayBuffer);\r\n for (let i = 0; i < byteString.length; i++) {\r\n intArray[i] = byteString.charCodeAt(i);\r\n }\r\n const blob = new Blob([intArray], { type: \"image/bmp\" });\r\n const url = URL.createObjectURL(blob);\r\n\r\n imgRef.current.src = url;\r\n\r\n if (lastBlobUrl.current) URL.revokeObjectURL(lastBlobUrl.current);\r\n lastBlobUrl.current = url;\r\n } catch (e) {\r\n console.warn(\"⚠️ Error cargando frame BMP:\", e);\r\n }\r\n }\r\n }, [previewRight, previewLeft]);\r\n\r\n useEffect(() => {\r\n if (!isOpen && lastBlobUrl.current) {\r\n URL.revokeObjectURL(lastBlobUrl.current);\r\n lastBlobUrl.current = null;\r\n }\r\n }, [isOpen]);\r\n\r\n let statusColor = \"text-foreground/70\";\r\n let statusBg = \"bg-secondary/50 border-border\";\r\n\r\n if (statusMessage.toLowerCase().includes(\"error\")) {\r\n statusColor = \"text-red-500\";\r\n statusBg = \"bg-red-500/10 border-red-500/20\";\r\n } else if (\r\n statusMessage.toLowerCase().includes(\"lista\") ||\r\n statusMessage.toLowerCase().includes(\"completado\")\r\n ) {\r\n statusColor = \"text-green-500\";\r\n statusBg = \"bg-green-500/10 border-green-500/20\";\r\n }\r\n\r\n const isDistanceOptimal =\r\n distance !== null && distance >= 100 && distance <= 120;\r\n const distanceColor = isDistanceOptimal\r\n ? \"text-green-500\"\r\n : \"text-yellow-500\";\r\n\r\n const hasPreview = !!(previewRight || previewLeft);\r\n\r\n return (\r\n <Modal\r\n isOpen={isOpen}\r\n onClose={onClose}\r\n title=\"Captura de Iris\"\r\n allowClose={!isCapturing}\r\n >\r\n <div className=\"flex flex-col md:flex-row gap-6 items-stretch\">\r\n <div className=\"flex-1 flex justify-center\">\r\n <div className=\"relative w-full max-w-[340px] aspect-[4/3] rounded-md p-1 bg-muted/20 border border-border shadow-sm\">\r\n <div className=\"w-full h-full rounded-md overflow-hidden bg-zinc-950 relative flex items-center justify-center border border-white/5 shadow-inner group\">\r\n <div\r\n className=\"absolute inset-0 opacity-20 pointer-events-none\"\r\n style={{\r\n backgroundImage:\r\n \"linear-gradient(#333 1px, transparent 1px), linear-gradient(90deg, #333 1px, transparent 1px)\",\r\n backgroundSize: \"20px 20px\",\r\n }}\r\n />\r\n\r\n <img\r\n ref={imgRef}\r\n alt=\"Vista previa\"\r\n className={`\r\n relative z-10 object-contain w-full h-full transition-opacity duration-200\r\n ${hasPreview ? \"opacity-100\" : \"opacity-0\"}\r\n `}\r\n />\r\n\r\n {!hasPreview && (\r\n <div className=\"absolute inset-0 flex flex-col items-center justify-center text-white/20 gap-4 z-0\">\r\n <div className=\"relative\">\r\n <TbEye size={80} className=\"opacity-50\" />\r\n {isCapturing && (\r\n <div className=\"absolute inset-0 flex items-center justify-center\">\r\n <Loader size={30} />\r\n </div>\r\n )}\r\n </div>\r\n <p className=\"text-[10px] font-bold tracking-[0.2em] uppercase opacity-60\">\r\n {isCapturing ? \"Iniciando Sensor...\" : \"Cámara en espera\"}\r\n </p>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex-1 flex flex-col justify-between gap-6 min-h-[320px] py-1\">\r\n <div className=\"space-y-5\">\r\n <div className=\"grid grid-cols-2 gap-3\">\r\n <div className=\"bg-card border border-border rounded-md p-3 flex flex-col gap-1\">\r\n <span className=\"text-[10px] uppercase font-bold text-muted-foreground flex items-center gap-1\">\r\n <TbRuler /> Distancia\r\n </span>\r\n <span\r\n className={`text-lg font-mono font-bold ${distanceColor}`}\r\n >\r\n {distance ?? \"--\"}{\" \"}\r\n <span className=\"text-xs text-muted-foreground\">mm</span>\r\n </span>\r\n </div>\r\n <div className=\"bg-card border border-border rounded-md p-3 flex flex-col gap-1\">\r\n <span className=\"text-[10px] uppercase font-bold text-muted-foreground flex items-center gap-1\">\r\n <TbActivity /> Estado\r\n </span>\r\n <span\r\n className=\"text-sm font-medium truncate\"\r\n title={cameraStatus}\r\n >\r\n {cameraStatus}\r\n </span>\r\n </div>\r\n </div>\r\n\r\n <div\r\n className={`p-4 rounded-md border ${statusBg} transition-colors duration-300`}\r\n >\r\n <div className=\"flex items-start gap-3\">\r\n <TbScan\r\n className={`mt-0.5 shrink-0 ${statusColor}`}\r\n size={18}\r\n />\r\n <p\r\n className={`text-sm font-medium leading-snug ${statusColor}`}\r\n >\r\n {statusMessage}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"space-y-3 pt-4 border-t border-border\">\r\n {!isCapturing ? (\r\n <div className=\"flex gap-3\">\r\n <button\r\n onClick={onClose}\r\n className=\"flex-1 flex items-center justify-center gap-2 px-4 py-3 rounded-md font-semibold text-sm border border-border hover:bg-secondary transition-colors\"\r\n >\r\n Cerrar\r\n </button>\r\n <button\r\n onClick={onStartCapture}\r\n className=\"flex-[2] flex items-center justify-center gap-2 px-4 py-3 rounded-md font-semibold text-sm bg-primary text-white hover:bg-primary/90 shadow-lg shadow-primary/20 transition-all\"\r\n >\r\n <TbPlayerPlay size={18} /> Iniciar Captura\r\n </button>\r\n </div>\r\n ) : (\r\n <button\r\n onClick={onAbortCapture}\r\n className=\"w-full flex items-center justify-center gap-2 px-4 py-3 rounded-md font-semibold text-sm bg-red-500/10 text-red-600 border border-red-500/20 hover:bg-red-500 hover:text-white transition-all\"\r\n >\r\n <TbPlayerStop size={18} /> Detener / Cancelar\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </Modal>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { useState, useEffect, useMemo, useRef } from \"react\";\r\nimport { toast } from \"react-hot-toast\";\r\nimport { useBiometricStore } from \"../../lib/stores/biometricStore\";\r\nimport { useUiStore } from \"../../lib/stores/uiStore\";\r\nimport { useEnrollmentStore } from \"../../lib/stores/enrollmentStore\";\r\nimport { BiometricSlot } from \"../ui/BiometricSlot\";\r\nimport { MissingFingerModal } from \"../ui/MissingFingerModal\";\r\nimport { ModuleHeader } from \"./ModuleHeader\";\r\nimport { Button } from \"../ui/Button\";\r\nimport { FingerRollCaptureModal } from \"./FingerRollCaptureModal\";\r\nimport { TbReload, TbSend, TbFingerprint } from \"react-icons/tb\";\r\nimport {\r\n FINGER_NAMES,\r\n RIGHT_FINGERS,\r\n LEFT_FINGERS,\r\n} from \"../../lib/constants/fingerPositions\";\r\nimport {\r\n getImageSrcForDisplay,\r\n} from \"../../lib/utils/imageHelpers\";\r\n\r\ninterface FingerResult {\r\n Finger: string;\r\n Quality: number;\r\n Image: string;\r\n Error?: string | null;\r\n}\r\n\r\ntype FingerResultsMap = Record<string, FingerResult>;\r\n\r\nexport default function FingerRollEnrollModule({ className = \"\" }: { className?: string }) {\r\n const {\r\n addRolledFingerprint,\r\n addMissingFinger,\r\n removeMissingFinger,\r\n removeRolledFingerprint,\r\n rolledFingerprints: storeRolled,\r\n missingFingers: enrollmentMissingFingers,\r\n } = useEnrollmentStore();\r\n\r\n const [fingerResults, setFingerResults] = useState<FingerResultsMap>({});\r\n\r\n const [isModalOpen, setIsModalOpen] = useState(false);\r\n const isModalOpenRef = useRef(isModalOpen);\r\n const [isProcessing, setIsProcessing] = useState(false);\r\n const [currentFinger, setCurrentFinger] = useState<string | null>(null);\r\n\r\n const [previewImage, setPreviewImage] = useState<string | null>(null);\r\n const [previewQuality, setPreviewQuality] = useState<number | null>(null);\r\n const [rollStatus, setRollStatus] = useState(\"Coloque el dedo...\");\r\n\r\n const [fingerToMarkMissing, setFingerToMarkMissing] = useState<string | null>(\r\n null,\r\n );\r\n\r\n const {\r\n isConnected,\r\n sendMessage,\r\n registerHandler,\r\n unregisterHandler,\r\n missingFingers,\r\n markFingerAsMissing,\r\n restoreFinger,\r\n clearAllMissingFingers,\r\n } = useBiometricStore();\r\n\r\n const addMessage = useUiStore((s) => s.addMessage);\r\n\r\n useEffect(() => {\r\n const loaded: FingerResultsMap = {};\r\n Object.entries(storeRolled).forEach(([key, item]) => {\r\n loaded[key] = {\r\n Finger: key,\r\n Quality: item.quality,\r\n Image: item.image,\r\n Error: null,\r\n };\r\n });\r\n setFingerResults((prev) => ({ ...prev, ...loaded }));\r\n }, [storeRolled]);\r\n\r\n const allMissingFingers = useMemo(\r\n () => ({ ...enrollmentMissingFingers, ...missingFingers }),\r\n [enrollmentMissingFingers, missingFingers],\r\n );\r\n\r\n const capturedCount = useMemo(() => {\r\n const success = Object.values(fingerResults).filter(\r\n (r) => r && r.Quality >= 40,\r\n ).length;\r\n const missing = Object.keys(allMissingFingers).length;\r\n return success + missing;\r\n }, [fingerResults, allMissingFingers]);\r\n\r\n const isCapturing = isProcessing || isModalOpen;\r\n\r\n useEffect(() => {\r\n isModalOpenRef.current = isModalOpen;\r\n }, [isModalOpen]);\r\n\r\n useEffect(() => {\r\n const handlePreview = (d: any) => {\r\n if (!isModalOpenRef.current) return;\r\n setPreviewImage(d.biometricData?.capturedImage || null);\r\n setPreviewQuality(d.biometricData?.quality || null);\r\n };\r\n\r\n const handleRollStart = (d: any) => {\r\n setRollStatus(d.payload || \"Dedo detectado. Comience a rolar...\");\r\n };\r\n\r\n const handleRollComplete = (d: any) => {\r\n setRollStatus(d.payload || \"Rolado completo. Procesando...\");\r\n };\r\n\r\n const handleCaptureComplete = (d: any) => {\r\n setIsProcessing(false);\r\n setIsModalOpen(false);\r\n\r\n const seg = d.biometricData?.segments?.[0];\r\n if (!seg || seg.finger !== currentFinger) {\r\n toast.error(\"No se recibió el segmento esperado.\");\r\n return;\r\n }\r\n\r\n setFingerResults((prev) => ({\r\n ...prev,\r\n [seg.finger]: {\r\n Finger: seg.finger,\r\n Quality: seg.quality,\r\n Image: seg.image,\r\n Error: null,\r\n },\r\n }));\r\n\r\n if (seg.image) {\r\n addRolledFingerprint(seg.finger, seg.image, seg.quality || 100);\r\n }\r\n\r\n toast.success(`Huella rolada capturada (${seg.quality}%)`);\r\n setCurrentFinger(null);\r\n setPreviewImage(null);\r\n setPreviewQuality(null);\r\n setRollStatus(\"Coloque el dedo...\");\r\n };\r\n\r\n const handleError = (d: any) => {\r\n const msg = d.error || d.messageType || \"Error desconocido\";\r\n toast.error(msg);\r\n setIsModalOpen(false);\r\n setIsProcessing(false);\r\n setCurrentFinger(null);\r\n setPreviewImage(null);\r\n setPreviewQuality(null);\r\n };\r\n\r\n const handleEnrollmentComplete = (d: any) => {\r\n const wsqs = d.biometricData?.wsqFiles;\r\n if (wsqs) {\r\n Object.entries(wsqs).forEach(([pos, base64]) => {\r\n const localResult = fingerResults[pos];\r\n const imageToStore = localResult?.Image || (base64 as string);\r\n const quality = localResult?.Quality || 100;\r\n addRolledFingerprint(pos, imageToStore, quality);\r\n });\r\n addMessage(\"Huellas roladas guardadas en memoria.\");\r\n }\r\n\r\n toast.success(\"Procesamiento finalizado\");\r\n setIsProcessing(false);\r\n };\r\n\r\n registerHandler(\"FINGER_PREVIEW_FRAME\", handlePreview);\r\n registerHandler(\"FINGER_ROLL_START_SIGNAL\", handleRollStart);\r\n registerHandler(\"FINGER_ROLL_COMPLETE_SIGNAL\", handleRollComplete);\r\n registerHandler(\"FINGER_CAPTURE_COMPLETE\", handleCaptureComplete);\r\n registerHandler(\"ENROLLMENT_COMPLETE\", handleEnrollmentComplete);\r\n registerHandler(\"ERROR\", handleError);\r\n registerHandler(\"FINGER_ERROR\", handleError);\r\n registerHandler(\"DUPLICATE_FINGER\", handleError);\r\n registerHandler(\"FINGER_QUALITY_LOW\", handleError);\r\n\r\n return () => {\r\n unregisterHandler(\"FINGER_PREVIEW_FRAME\");\r\n unregisterHandler(\"FINGER_ROLL_START_SIGNAL\");\r\n unregisterHandler(\"FINGER_ROLL_COMPLETE_SIGNAL\");\r\n unregisterHandler(\"FINGER_CAPTURE_COMPLETE\");\r\n unregisterHandler(\"ENROLLMENT_COMPLETE\");\r\n unregisterHandler(\"ERROR\");\r\n unregisterHandler(\"FINGER_ERROR\");\r\n unregisterHandler(\"DUPLICATE_FINGER\");\r\n unregisterHandler(\"FINGER_QUALITY_LOW\");\r\n };\r\n }, [\r\n registerHandler,\r\n unregisterHandler,\r\n currentFinger,\r\n addMessage,\r\n addRolledFingerprint,\r\n fingerResults,\r\n ]);\r\n\r\n const startRollCapture = (finger: string) => {\r\n if (!isConnected) return toast.error(\"Servicio no conectado.\");\r\n\r\n if (allMissingFingers[finger]) {\r\n toast.error(`El dedo ${FINGER_NAMES[finger]} está marcado como omitido.`);\r\n return;\r\n }\r\n\r\n setIsProcessing(true);\r\n setIsModalOpen(true);\r\n setCurrentFinger(finger);\r\n setPreviewImage(null);\r\n setPreviewQuality(null);\r\n setRollStatus(`Coloque ${FINGER_NAMES[finger]}...`);\r\n addMessage(`Iniciando captura rolada: ${FINGER_NAMES[finger]}`);\r\n\r\n sendMessage({\r\n messageType: \"START_FINGER_ROLL_CAPTURE\",\r\n biometricData: {\r\n targetFinger: finger,\r\n expectedFingers: [finger],\r\n },\r\n });\r\n };\r\n\r\n const cancelCapture = () => {\r\n sendMessage({ messageType: \"ABORT_FINGER_ROLL_CAPTURE\" });\r\n setIsModalOpen(false);\r\n setIsProcessing(false);\r\n setCurrentFinger(null);\r\n setPreviewImage(null);\r\n setPreviewQuality(null);\r\n };\r\n\r\n const processBatch = () => {\r\n if (capturedCount < 10) {\r\n toast.error(`Faltan huellas por procesar (${capturedCount}/10).`);\r\n return;\r\n }\r\n setIsProcessing(true);\r\n sendMessage({ messageType: \"FINALIZE_ENROLLMENT\" });\r\n };\r\n\r\n const resetState = () => {\r\n setFingerResults({});\r\n setIsProcessing(false);\r\n clearAllMissingFingers();\r\n addMessage(\"Módulo reiniciado.\");\r\n };\r\n\r\n const handleConfirmMissing = (reason: string) => {\r\n if (fingerToMarkMissing) {\r\n markFingerAsMissing(fingerToMarkMissing, reason);\r\n addMissingFinger(fingerToMarkMissing, reason);\r\n setFingerResults((prev) => {\r\n const next = { ...prev };\r\n delete next[fingerToMarkMissing];\r\n return next;\r\n });\r\n removeRolledFingerprint(fingerToMarkMissing);\r\n addMessage(`Dedo ${fingerToMarkMissing} marcado como: ${reason}`);\r\n setFingerToMarkMissing(null);\r\n }\r\n };\r\n\r\n const renderFingerGrid = (fingers: string[]) =>\r\n fingers.map((finger) => {\r\n const res = fingerResults[finger];\r\n const missing = allMissingFingers[finger] || null;\r\n return (\r\n <BiometricSlot\r\n key={finger}\r\n position={finger}\r\n title={FINGER_NAMES[finger].split(\" \")[0]}\r\n status={res ? (res.Error ? \"error\" : \"captured\") : \"pending\"}\r\n iconType=\"finger\"\r\n imageUrl={getImageSrcForDisplay(res?.Image, \"png\")}\r\n quality={res?.Quality}\r\n missingReason={missing}\r\n onCapture={() => startRollCapture(finger)}\r\n onRequestMissing={() => setFingerToMarkMissing(finger)}\r\n onRestore={() => {\r\n removeMissingFinger(finger);\r\n if (missingFingers[finger]) restoreFinger(finger);\r\n }}\r\n onDelete={() => {\r\n removeRolledFingerprint(finger);\r\n setFingerResults((prev) => {\r\n const next = { ...prev };\r\n delete next[finger];\r\n return next;\r\n });\r\n }}\r\n isDisabled={!isConnected || isCapturing}\r\n />\r\n );\r\n });\r\n\r\n return (\r\n <div className=\"space-y-8 animate-in fade-in duration-500\">\r\n <ModuleHeader\r\n icon={<TbFingerprint size={24} />}\r\n title=\"Huellas Roladas\"\r\n subtitle=\"Capture las huellas rodando el dedo de un lado a otro.\"\r\n progress={{ current: capturedCount, total: 10 }}\r\n >\r\n <Button\r\n variant=\"success\"\r\n size=\"sm\"\r\n icon={<TbSend size={16} />}\r\n onClick={processBatch}\r\n disabled={!isConnected || isCapturing || capturedCount < 10}\r\n isLoading={isProcessing}\r\n >\r\n Guardar\r\n </Button>\r\n <Button\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n icon={<TbReload size={16} />}\r\n onClick={resetState}\r\n disabled={isCapturing}\r\n >\r\n Limpiar\r\n </Button>\r\n </ModuleHeader>\r\n\r\n <div className=\"grid grid-cols-1 xl:grid-cols-2 gap-8\">\r\n <div className=\"glass p-6 rounded-sm border border-white/10 relative overflow-hidden group\">\r\n <div className=\"absolute top-0 right-0 p-4 opacity-5 group-hover:opacity-10 transition-opacity\">\r\n <TbFingerprint size={120} />\r\n </div>\r\n <h3 className=\"text-lg font-bold text-foreground mb-5 pl-3 border-l-4 border-primary\">\r\n Mano Derecha\r\n </h3>\r\n <div className=\"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-4\">\r\n {renderFingerGrid(RIGHT_FINGERS)}\r\n </div>\r\n </div>\r\n\r\n <div className=\"glass p-6 rounded-sm border border-white/10 relative overflow-hidden group\">\r\n <div className=\"absolute top-0 right-0 p-4 opacity-5 group-hover:opacity-10 transition-opacity\">\r\n <TbFingerprint size={120} />\r\n </div>\r\n <h3 className=\"text-lg font-bold text-foreground mb-5 pl-3 border-l-4 border-secondary-foreground/50\">\r\n Mano Izquierda\r\n </h3>\r\n <div className=\"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-4\">\r\n {renderFingerGrid(LEFT_FINGERS)}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <FingerRollCaptureModal\r\n isOpen={isModalOpen}\r\n onCancel={cancelCapture}\r\n captureType={\r\n currentFinger\r\n ? `${FINGER_NAMES[currentFinger]} (Rolado)`\r\n : \"Captura Rolada\"\r\n }\r\n previewImage={previewImage}\r\n previewQuality={previewQuality}\r\n rollStatus={rollStatus}\r\n />\r\n\r\n <MissingFingerModal\r\n isOpen={!!fingerToMarkMissing}\r\n onClose={() => setFingerToMarkMissing(null)}\r\n onConfirm={handleConfirmMissing}\r\n positionName={\r\n fingerToMarkMissing ? FINGER_NAMES[fingerToMarkMissing] : \"\"\r\n }\r\n />\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { Modal } from \"../ui/Modal\";\r\nimport { QualityBadge } from \"../ui/QualityBadge\";\r\nimport { Loader } from \"../ui/Loader\";\r\nimport {\r\n TbFingerprint,\r\n TbX,\r\n TbScan,\r\n TbRotateClockwise,\r\n TbCheck,\r\n} from \"react-icons/tb\";\r\nimport { motion } from \"framer-motion\";\r\n\r\ninterface FingerRollCaptureModalProps {\r\n isOpen: boolean;\r\n onCancel: () => void;\r\n captureType: string;\r\n previewImage: string | null;\r\n previewQuality: number | null;\r\n rollStatus: string;\r\n}\r\n\r\nexport function FingerRollCaptureModal({\r\n isOpen,\r\n onCancel,\r\n captureType,\r\n previewImage,\r\n previewQuality,\r\n rollStatus,\r\n}: FingerRollCaptureModalProps) {\r\n let statusStyles = \"bg-secondary/50 border-border/50 text-foreground/80\";\r\n let statusIcon = (\r\n <Loader size={18} className=\"text-foreground/50 animate-spin\" />\r\n );\r\n\r\n const statusLower = rollStatus.toLowerCase();\r\n\r\n if (\r\n statusLower.includes(\"rolar\") ||\r\n statusLower.includes(\"detectado\") ||\r\n statusLower.includes(\"coloque\")\r\n ) {\r\n statusStyles = \"bg-primary/10 border-primary/20 text-primary\";\r\n statusIcon = <TbRotateClockwise size={20} className=\"animate-pulse\" />;\r\n } else if (\r\n statusLower.includes(\"completo\") ||\r\n statusLower.includes(\"éxito\") ||\r\n statusLower.includes(\"ok\")\r\n ) {\r\n statusStyles =\r\n \"bg-quality-good/10 border-quality-good/20 text-quality-good\";\r\n statusIcon = <TbCheck size={20} />;\r\n } else if (\r\n statusLower.includes(\"error\") ||\r\n statusLower.includes(\"falla\") ||\r\n statusLower.includes(\"mala\")\r\n ) {\r\n statusStyles = \"bg-quality-bad/10 border-quality-bad/20 text-quality-bad\";\r\n statusIcon = <TbX size={20} />;\r\n }\r\n\r\n return (\r\n <Modal\r\n isOpen={isOpen}\r\n onClose={onCancel}\r\n title={captureType}\r\n allowClose={true}\r\n >\r\n <div className=\"flex flex-col md:flex-row gap-8 items-stretch p-2\">\r\n <div className=\"flex-1 flex justify-center bg-card/50 rounded-md p-4 border border-white/5\">\r\n <div\r\n className=\"\r\n relative w-full max-w-[280px] aspect-[3/4]\r\n rounded-md overflow-hidden\r\n bg-black/5 dark:bg-white/5\r\n border border-border/50 dark:border-white/10\r\n shadow-inner flex items-center justify-center\r\n \"\r\n >\r\n <motion.div\r\n className=\"absolute inset-y-0 w-[2px] bg-primary/80 z-10 shadow-[0_0_20px_2px_rgba(var(--primary),0.6)]\"\r\n animate={{ left: [\"5%\", \"95%\", \"5%\"] }}\r\n transition={{ duration: 4, repeat: Infinity, ease: \"easeInOut\" }}\r\n />\r\n\r\n <div\r\n className=\"absolute inset-0 pointer-events-none opacity-[0.08] z-0\"\r\n style={{\r\n backgroundImage:\r\n \"linear-gradient(0deg, transparent 24%, currentColor 25%, currentColor 26%, transparent 27%, transparent 74%, currentColor 75%, currentColor 76%, transparent 77%, transparent), linear-gradient(90deg, transparent 24%, currentColor 25%, currentColor 26%, transparent 27%, transparent 74%, currentColor 75%, currentColor 76%, transparent 77%, transparent)\",\r\n backgroundSize: \"20px 20px\",\r\n color: \"currentColor\",\r\n }}\r\n />\r\n\r\n <div className=\"relative z-1 w-full h-full flex items-center justify-center\">\r\n {previewImage ? (\r\n <motion.img\r\n initial={{ opacity: 0, scale: 0.95 }}\r\n animate={{ opacity: 1, scale: 1 }}\r\n src={previewImage}\r\n alt=\"Huella rolada\"\r\n className=\"object-contain w-full h-full p-4 rotate-180 drop-shadow-lg\"\r\n />\r\n ) : (\r\n <div className=\"flex flex-col items-center justify-center text-foreground/30 gap-3\">\r\n <div className=\"relative\">\r\n <TbFingerprint size={70} className=\"opacity-80\" />\r\n <motion.div\r\n className=\"absolute -right-2 -bottom-2 text-primary\"\r\n animate={{ rotate: 360 }}\r\n transition={{\r\n duration: 8,\r\n repeat: Infinity,\r\n ease: \"linear\",\r\n }}\r\n >\r\n <TbRotateClockwise size={28} />\r\n </motion.div>\r\n </div>\r\n <p className=\"text-[10px] font-bold tracking-widest uppercase opacity-70\">\r\n Esperando inicio\r\n </p>\r\n </div>\r\n )}\r\n </div>\r\n\r\n <div className=\"absolute top-3 right-3 z-20\">\r\n <QualityBadge quality={previewQuality} />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex-1 flex flex-col justify-between gap-6 min-h-[300px]\">\r\n <div className=\"space-y-4\">\r\n <div>\r\n <h4 className=\"text-xs font-bold text-foreground/50 uppercase tracking-wider mb-2\">\r\n Estado del Proceso\r\n </h4>\r\n <div\r\n className={`\r\n p-4 rounded-md border flex items-start gap-3 shadow-sm\r\n transition-all duration-300 ${statusStyles}\r\n `}\r\n >\r\n <div className=\"mt-0.5 shrink-0\">{statusIcon}</div>\r\n <p className=\"text-sm font-medium leading-snug\">{rollStatus}</p>\r\n </div>\r\n </div>\r\n\r\n <div className=\"space-y-2\">\r\n <h4 className=\"text-xs font-semibold text-foreground/60 uppercase tracking-wide flex items-center gap-1\">\r\n <TbScan className=\"mb-0.5\" /> Guía de Rolado\r\n </h4>\r\n <div className=\"bg-card border border-border/60 rounded-md p-3 space-y-2\">\r\n <div className=\"flex gap-3 items-center text-sm text-foreground/70\">\r\n <span className=\"w-6 h-6 rounded-full bg-secondary flex items-center justify-center text-xs font-bold shrink-0\">\r\n 1\r\n </span>\r\n <span className=\"leading-tight\">\r\n Apoye el <strong>borde lateral</strong> de la uña.\r\n </span>\r\n </div>\r\n <div className=\"h-px w-8 bg-border mx-auto\" />\r\n <div className=\"flex gap-3 items-center text-sm text-foreground/70\">\r\n <span className=\"w-6 h-6 rounded-full bg-secondary flex items-center justify-center text-xs font-bold shrink-0\">\r\n 2\r\n </span>\r\n <span className=\"leading-tight\">\r\n Gire suavemente hacia el lado opuesto.\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"pt-4 border-t border-border/40\">\r\n <button\r\n onClick={onCancel}\r\n className=\"\r\n group w-full flex items-center justify-center gap-2 px-4 py-3.5\r\n rounded-md font-semibold text-sm\r\n bg-red-500/10 text-red-600 dark:text-red-400 \r\n border border-red-500/20\r\n hover:bg-red-500 hover:text-white hover:border-red-500\r\n transition-all duration-200 shadow-sm\r\n \"\r\n >\r\n <TbX size={18} />\r\n Abortar Captura\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </Modal>\r\n );\r\n}\r\n","// src/components/ui/Card.tsx\r\nimport React from \"react\";\r\n\r\nexport interface CardProps {\r\n variant?: 'subtle' | 'default' | 'medium' | 'strong' | 'modal' | 'glass' | 'glass-subtle' | 'glass-strong' | 'outlined';\r\n padding?: 'none' | 'sm' | 'md' | 'lg';\r\n rounded?: 'lg' | 'xl' | '2xl' | '3xl';\r\n className?: string;\r\n children: React.ReactNode;\r\n}\r\n\r\nexport function Card({\r\n variant = 'default',\r\n padding = 'md',\r\n rounded = '3xl',\r\n className = '',\r\n children\r\n}: CardProps) {\r\n const variantClasses = {\r\n subtle: 'bg-card/50 elevation-1 hover:elevation-2 hover:-translate-y-1',\r\n default: 'bg-card/60 elevation-2 hover:elevation-3 hover:-translate-y-1',\r\n medium: 'bg-card/70 elevation-3 hover:elevation-4 hover:-translate-y-1',\r\n strong: 'bg-card/80 elevation-4',\r\n modal: 'bg-card/90 elevation-5',\r\n // Mantener las antiguas para compatibilidad\r\n glass: 'glass',\r\n 'glass-subtle': 'glass-subtle',\r\n 'glass-strong': 'glass-strong',\r\n outlined: 'bg-transparent border-2 border-border-emphasis elevation-1'\r\n };\r\n\r\n const paddingClasses = {\r\n none: 'p-0',\r\n sm: 'p-4',\r\n md: 'p-6 md:p-8',\r\n lg: 'p-8 md:p-12'\r\n };\r\n\r\n const roundedClasses = {\r\n lg: 'rounded-sm',\r\n xl: 'rounded-md',\r\n '2xl': 'rounded-md',\r\n '3xl': 'rounded-md'\r\n };\r\n\r\n return (\r\n <div className={`\r\n ${variantClasses[variant]}\r\n ${paddingClasses[padding]}\r\n ${roundedClasses[rounded]}\r\n transition-all duration-300\r\n ${className}\r\n `}>\r\n {children}\r\n </div>\r\n );\r\n}\r\n","// src/components/ui/Input.tsx\r\nimport React from \"react\";\r\n\r\nexport interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {\r\n label?: string;\r\n icon?: React.ReactNode;\r\n error?: string;\r\n}\r\n\r\nexport function Input({\r\n label,\r\n icon,\r\n error,\r\n className = '',\r\n ...props\r\n}: InputProps) {\r\n return (\r\n <div className=\"space-y-2 w-full\">\r\n {label && (\r\n <label className=\"block text-xs font-semibold uppercase tracking-wider text-foreground/50 ml-1\">\r\n {label}\r\n </label>\r\n )}\r\n <div className=\"relative\">\r\n {icon && (\r\n <div className=\"absolute left-4 top-1/2 -translate-y-1/2 text-foreground/40\">\r\n {icon}\r\n </div>\r\n )}\r\n <input\r\n className={`\r\n w-full bg-secondary/50 border border-border-default\r\n rounded-md py-3 px-4\r\n ${icon ? 'pl-11' : ''}\r\n\r\n elevation-1\r\n hover:elevation-2 hover:-translate-y-0.5\r\n focus:elevation-3 focus:ring-2 focus:ring-primary/50 focus:glow-primary focus:-translate-y-1\r\n\r\n outline-none\r\n transition-all duration-250\r\n text-foreground placeholder:text-foreground/30\r\n disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:translate-y-0\r\n\r\n ${error ? 'border-danger/50 focus:ring-danger/50 focus:glow-danger' : ''}\r\n ${className}\r\n `}\r\n {...props}\r\n />\r\n </div>\r\n {error && (\r\n <p className=\"text-xs text-danger ml-1\">{error}</p>\r\n )}\r\n </div>\r\n );\r\n}\r\n","// src/components/ui/StatusChip.tsx\r\nimport React from \"react\";\r\nimport { TbLoader } from \"react-icons/tb\";\r\n\r\ninterface StatusChipProps {\r\n status: 'success' | 'warning' | 'danger' | 'info' | 'neutral';\r\n label: string;\r\n icon?: React.ReactNode;\r\n isLoading?: boolean;\r\n size?: 'sm' | 'md';\r\n showDot?: boolean;\r\n}\r\n\r\nexport function StatusChip({\r\n status,\r\n label,\r\n icon,\r\n isLoading = false,\r\n size = 'md',\r\n showDot = true\r\n}: StatusChipProps) {\r\n const statusClasses = {\r\n success: `\r\n bg-success/10 border-success/20 text-success\r\n elevation-1 glow-success\r\n hover:scale-105 hover:elevation-2\r\n `,\r\n warning: `\r\n bg-warning/10 border-warning/20 text-warning\r\n elevation-1 glow-warning\r\n hover:scale-105 hover:elevation-2\r\n animate-pulse\r\n `,\r\n danger: `\r\n bg-danger/10 border-danger/20 text-danger\r\n elevation-1 glow-danger\r\n hover:scale-105 hover:elevation-2\r\n `,\r\n info: `\r\n bg-info/10 border-info/20 text-info\r\n elevation-1\r\n shadow-[0_0_12px_rgba(59,130,246,0.2)]\r\n hover:scale-105 hover:elevation-2\r\n `,\r\n neutral: `\r\n bg-secondary/50 border-border-default text-foreground/60\r\n elevation-1\r\n hover:scale-105 hover:elevation-2\r\n `\r\n };\r\n\r\n const sizeClasses = {\r\n sm: 'px-2 py-1 text-[10px] rounded-custom-sm',\r\n md: 'px-3 py-1.5 text-xs rounded-custom-md'\r\n };\r\n\r\n return (\r\n <div className={`\r\n inline-flex items-center gap-2 border font-semibold uppercase tracking-wider\r\n transition-all duration-250\r\n ${statusClasses[status]}\r\n ${sizeClasses[size]}\r\n `}>\r\n {isLoading ? <TbLoader className=\"animate-spin\" /> : icon}\r\n <span>{label}</span>\r\n {showDot && !isLoading && (\r\n <div className={`w-1.5 h-1.5 rounded-full bg-current ${\r\n status === 'success' ? 'shadow-[0_0_8px_currentColor] animate-pulse' : ''\r\n }`} />\r\n )}\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport * as React from \"react\";\r\n//import { cn } from \"@/lib/utils\";\r\n\r\n// Si no tienes 'cn' en lib/utils, descomenta esta función y úsala en lugar de cn()\r\n function cn(...classes: (string | undefined | null | false)[]) {\r\n return classes.filter(Boolean).join(\" \");\r\n }\r\n\r\nconst TabsContext = React.createContext<{\r\n activeTab: string;\r\n setActiveTab: (id: string) => void;\r\n} | null>(null);\r\n\r\nexport function Tabs({\r\n defaultValue,\r\n value, // Agregado para soportar modo controlado si se necesita\r\n className,\r\n children,\r\n onValueChange,\r\n}: {\r\n defaultValue?: string;\r\n value?: string;\r\n className?: string;\r\n children: React.ReactNode;\r\n onValueChange?: (value: string) => void;\r\n}) {\r\n const [internalTab, setInternalTab] = React.useState(defaultValue || \"\");\r\n\r\n const activeTab = value !== undefined ? value : internalTab;\r\n\r\n const handleTabChange = (val: string) => {\r\n setInternalTab(val);\r\n if (onValueChange) onValueChange(val);\r\n };\r\n\r\n return (\r\n <TabsContext.Provider value={{ activeTab, setActiveTab: handleTabChange }}>\r\n <div className={cn(\"w-full\", className)}>{children}</div>\r\n </TabsContext.Provider>\r\n );\r\n}\r\n\r\nexport function TabsList({\r\n className,\r\n children,\r\n}: {\r\n className?: string;\r\n children: React.ReactNode;\r\n}) {\r\n return (\r\n // Quitamos 'inline-flex' y 'h-12' fijo para permitir responsive real\r\n <div\r\n className={cn(\r\n \"flex items-center justify-start w-full overflow-x-auto scrollbar-hide\",\r\n className,\r\n )}\r\n >\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nexport function TabsTrigger({\r\n value,\r\n children,\r\n className,\r\n disabled,\r\n}: {\r\n value: string;\r\n children: React.ReactNode;\r\n className?: string;\r\n disabled?: boolean;\r\n}) {\r\n const context = React.useContext(TabsContext);\r\n if (!context) throw new Error(\"TabsTrigger must be used within Tabs\");\r\n\r\n const isActive = context.activeTab === value;\r\n\r\n return (\r\n <button\r\n onClick={() => !disabled && context.setActiveTab(value)}\r\n disabled={disabled}\r\n data-state={isActive ? \"active\" : \"inactive\"} // Crucial para estilos CSS/Tailwind\r\n className={cn(\r\n \"inline-flex items-center justify-center whitespace-nowrap px-4 py-2 text-sm font-medium transition-all ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\r\n className,\r\n )}\r\n >\r\n {children}\r\n </button>\r\n );\r\n}\r\n\r\nexport function TabsContent({\r\n value,\r\n children,\r\n className,\r\n}: {\r\n value: string;\r\n children: React.ReactNode;\r\n className?: string;\r\n}) {\r\n const context = React.useContext(TabsContext);\r\n if (!context) throw new Error(\"TabsContent must be used within Tabs\");\r\n\r\n if (context.activeTab !== value) return null;\r\n\r\n return (\r\n <div\r\n className={cn(\r\n \"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 animate-in fade-in zoom-in-95 duration-200\",\r\n className,\r\n )}\r\n >\r\n {children}\r\n </div>\r\n );\r\n}\r\n","// src/components/ui/TableWrapper.tsx\r\nimport React from 'react';\r\n\r\nfunction cn(...classes: (string | boolean | undefined)[]) {\r\n return classes.filter(Boolean).join(' ');\r\n}\r\n\r\ninterface TableWrapperProps {\r\n children: React.ReactNode;\r\n className?: string;\r\n variant?: 'default' | 'strong';\r\n}\r\n\r\nexport const TableWrapper: React.FC<TableWrapperProps> = ({\r\n children,\r\n className,\r\n variant = 'default'\r\n}) => {\r\n const elevationClass = variant === 'strong' ? 'elevation-3' : 'elevation-2';\r\n\r\n return (\r\n <div className={cn(\r\n 'rounded-md overflow-hidden',\r\n elevationClass,\r\n className\r\n )}>\r\n {children}\r\n </div>\r\n );\r\n};\r\n\r\ninterface TableHeaderProps {\r\n children: React.ReactNode;\r\n className?: string;\r\n}\r\n\r\nexport const TableHeader: React.FC<TableHeaderProps> = ({ children, className }) => (\r\n <thead className={cn(\r\n 'elevation-3',\r\n 'bg-card/80',\r\n className\r\n )}>\r\n {children}\r\n </thead>\r\n);\r\n\r\ninterface TableRowProps {\r\n children: React.ReactNode;\r\n onClick?: () => void;\r\n className?: string;\r\n}\r\n\r\nexport const TableRow: React.FC<TableRowProps> = ({ children, onClick, className }) => (\r\n <tr\r\n onClick={onClick}\r\n className={cn(\r\n 'bg-card/40',\r\n 'elevation-1',\r\n 'hover:elevation-2',\r\n 'hover:-translate-y-0.5',\r\n 'hover:bg-card/60',\r\n 'transition-all duration-250',\r\n onClick && 'cursor-pointer',\r\n className\r\n )}\r\n >\r\n {children}\r\n </tr>\r\n);\r\n","import axios from 'axios';\r\nimport { useAuthStore } from './stores/authStore';\r\n\r\nlet _apiBaseUrl = 'http://localhost:8080/api/v1';\r\n\r\nexport function setApiBaseUrl(url: string) {\r\n _apiBaseUrl = url;\r\n api.defaults.baseURL = url;\r\n}\r\n\r\nconst api = axios.create({\r\n baseURL: _apiBaseUrl,\r\n headers: { 'Content-Type': 'application/json' }\r\n});\r\n\r\napi.interceptors.request.use((config) => {\r\n const token = useAuthStore.getState().token;\r\n if (token) {\r\n config.headers['x-access-token'] = token;\r\n }\r\n return config;\r\n});\r\n\r\nexport default api;","import { create } from 'zustand';\r\nimport Cookies from 'js-cookie';\r\n\r\ninterface User {\r\n id: string;\r\n username: string;\r\n role: string;\r\n}\r\n\r\ninterface AuthState {\r\n token: string | null;\r\n user: User | null;\r\n login: (token: string, user: User) => void;\r\n logout: () => void;\r\n initializeAuth: () => void;\r\n}\r\n\r\nexport const useAuthStore = create<AuthState>((set) => ({\r\n token: null,\r\n user: null,\r\n\r\n login: (token, user) => {\r\n \r\n Cookies.set('auth-token', token, {\r\n expires: 7, \r\n sameSite: 'strict',\r\n secure: typeof window !== 'undefined' && window.location.protocol === 'https:'\r\n });\r\n\r\n \r\n localStorage.setItem('auth-user', JSON.stringify(user));\r\n\r\n set({ token, user });\r\n },\r\n\r\n logout: () => {\r\n \r\n Cookies.remove('auth-token');\r\n localStorage.removeItem('auth-user');\r\n set({ token: null, user: null });\r\n },\r\n\r\n initializeAuth: () => {\r\n \r\n const token = Cookies.get('auth-token') || null;\r\n const userStr = localStorage.getItem('auth-user');\r\n const user = userStr ? JSON.parse(userStr) : null;\r\n\r\n set({ token, user });\r\n },\r\n}));\r\n","import api from \"../api\";\r\nimport { EnrollApplicantRequest } from \"../../types/abis-types\";\r\nexport const AuthService = {\r\n login: async (credentials: { username: string; password: string }) => {\r\n \r\n const { data } = await api.post(\"/auth/login\", credentials);\r\n return data;\r\n },\r\n};\r\n\r\nexport const BiometricService = {\r\n enrollApplicant: async (payload: EnrollApplicantRequest) => {\r\n const { data } = await api.post(\"/biometric/enrollment\", payload);\r\n return data;\r\n },\r\n\r\n updateApplicant: async (\r\n externalId: string,\r\n payload: Partial<EnrollApplicantRequest>\r\n ) => {\r\n const { data } = await api.put(`/biometric/update/${externalId}`, payload);\r\n return data;\r\n },\r\n\r\n getApplicant: async (externalId: string) => {\r\n const { data } = await api.get(`/biometric/${externalId}`);\r\n return data;\r\n },\r\n\r\n verifyIdentity: async (externalId: string, biometricData: any) => {\r\n const { data } = await api.post(`/biometric/${externalId}/verify`, biometricData);\r\n return data;\r\n },\r\n\r\n identifyProbe: async (biometricData: any) => {\r\n const { data } = await api.post(`/biometric/identify`, biometricData);\r\n return data;\r\n }\r\n};"],"mappings":"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","names":["create","create","useState","useEffect","useRef","create","FingerprintPosition","FingerprintImpressionType","IrisPosition","create","jsx","useState","useEffect","motion","useEffect","jsx","jsxs","jsx","jsxs","TbBan","jsx","jsxs","useState","useEffect","jsx","jsxs","jsx","jsxs","useState","useRef","useEffect","motion","AnimatePresence","TbCheck","jsx","jsxs","jsx","jsxs","TbLoader","jsx","jsxs","TbFingerprint","TbX","motion","jsx","jsxs","TbFingerprint","jsx","jsxs","useState","useRef","useEffect","jsx","jsxs","TbFingerprint","useState","useEffect","useMemo","toast","useState","useRef","useEffect","toast","Fragment","jsx","jsxs","useRef","useState","toast","useEffect","TbReload","TbSend","TbFaceId","jsx","jsxs","useState","useEffect","toast","useMemo","TbFaceId","TbSend","TbReload","useState","useEffect","useMemo","useRef","toast","TbHandStop","TbX","TbReload","TbScan","TbCheck","TbAlertTriangle","motion","Fragment","jsx","jsxs","TbDownload","TbReload","TbSend","TbHandStop","jsx","jsxs","useState","useRef","useEffect","useMemo","toast","TbHandStop","TbSend","TbDownload","TbReload","useState","useEffect","useRef","useMemo","toast","useEffect","useRef","TbEye","TbScan","jsx","jsxs","useRef","useEffect","TbEye","TbScan","TbDownload","TbReload","TbEye","jsx","jsxs","useState","useRef","useEffect","useMemo","toast","TbEye","TbDownload","TbReload","useState","useEffect","useMemo","useRef","toast","TbFingerprint","TbX","TbScan","TbCheck","motion","jsx","jsxs","TbReload","TbSend","TbFingerprint","jsx","jsxs","useState","useRef","useEffect","useMemo","toast","TbFingerprint","TbSend","TbReload","jsx","jsx","jsxs","TbLoader","jsx","jsxs","React","jsx","jsx","cn","create"]}
|