import { ref, computed, readonly } from 'vue' import type { CheckInHistoryItem, ScannedQRHistoryItem, HistoryStatus } from '~/types/checkin' import { HISTORY_STORAGE_KEY, SCANNED_QR_STORAGE_KEY, MAX_HISTORY_ITEMS, MAX_SCANNED_QR_ITEMS, HISTORY_STATUS_OPTIONS } from '~/constants/checkin' export const useCheckInHistory = () => { const checkInHistory = ref([]) const scannedQRHistory = ref([]) const historySearch = ref('') const historyStatusFilter = ref('') const historyDateFilter = ref('') const loadHistory = () => { if (typeof window !== 'undefined') { const stored = localStorage.getItem(HISTORY_STORAGE_KEY) if (stored) { try { checkInHistory.value = JSON.parse(stored) } catch (e) { console.error('Error loading history:', e) checkInHistory.value = [] } } } } const saveToHistory = (item: CheckInHistoryItem) => { const historyItem = { ...item, queueNumber: item.queueNumber || `ANT-${Date.now()}`, } checkInHistory.value.unshift(historyItem) // Simpan maksimal item sesuai constant if (checkInHistory.value.length > MAX_HISTORY_ITEMS) { checkInHistory.value = checkInHistory.value.slice(0, MAX_HISTORY_ITEMS) } if (typeof window !== 'undefined') { localStorage.setItem(HISTORY_STORAGE_KEY, JSON.stringify(checkInHistory.value)) } } const deleteHistoryItem = (index: number) => { checkInHistory.value.splice(index, 1) if (typeof window !== 'undefined') { localStorage.setItem(HISTORY_STORAGE_KEY, JSON.stringify(checkInHistory.value)) } } const clearHistory = () => { checkInHistory.value = [] if (typeof window !== 'undefined') { localStorage.removeItem(HISTORY_STORAGE_KEY) } } const loadScannedQRHistory = () => { if (typeof window !== 'undefined') { const stored = localStorage.getItem(SCANNED_QR_STORAGE_KEY) if (stored) { try { scannedQRHistory.value = JSON.parse(stored) } catch (e) { console.error('Error loading QR history:', e) scannedQRHistory.value = [] } } else { scannedQRHistory.value = [] } } } const saveScannedQRData = (qrData: string) => { if (typeof window !== 'undefined') { const scannedQRs = JSON.parse(localStorage.getItem(SCANNED_QR_STORAGE_KEY) || '[]') scannedQRs.unshift({ data: qrData, timestamp: new Date().toISOString(), date: new Date().toLocaleDateString('id-ID'), time: new Date().toLocaleTimeString('id-ID').replace(/\./g, ':') }) // Simpan maksimal item sesuai constant if (scannedQRs.length > MAX_SCANNED_QR_ITEMS) { scannedQRs.pop() } localStorage.setItem(SCANNED_QR_STORAGE_KEY, JSON.stringify(scannedQRs)) } } const clearQRHistory = () => { scannedQRHistory.value = [] if (typeof window !== 'undefined') { localStorage.removeItem(SCANNED_QR_STORAGE_KEY) } } const deleteQRHistoryItem = (index: number) => { scannedQRHistory.value.splice(index, 1) if (typeof window !== 'undefined') { localStorage.setItem(SCANNED_QR_STORAGE_KEY, JSON.stringify(scannedQRHistory.value)) } } const filteredHistory = computed(() => { let filtered = [...checkInHistory.value] // Filter by search if (historySearch.value) { const search = historySearch.value.toLowerCase() filtered = filtered.filter(item => item.patientId.toLowerCase().includes(search) || (item.queueNumber && item.queueNumber.toLowerCase().includes(search)) ) } // Filter by status if (historyStatusFilter.value) { filtered = filtered.filter(item => { if (historyStatusFilter.value === 'success') { return item.status === 'ALLOWED' || item.status === 'success' } else if (historyStatusFilter.value === 'failed') { return item.status === 'NOT_ALLOWED' || item.status === 'failed' } return true }) } // Filter by date if (historyDateFilter.value && historyDateFilter.value.trim() !== '') { filtered = filtered.filter(item => { if (!item.checkInDate) return false try { const itemDate = new Date(item.checkInDate) const filterDate = new Date(historyDateFilter.value) // Validate dates if (isNaN(itemDate.getTime()) || isNaN(filterDate.getTime())) { return false } // Compare dates (year, month, day only, ignore time) const itemDateStr = itemDate.toISOString().substring(0, 10) const filterDateStr = filterDate.toISOString().substring(0, 10) return itemDateStr === filterDateStr } catch (e) { console.error('Error filtering by date:', e) return false } }) } return filtered }) const filteredQRHistory = computed(() => { let filtered = [...scannedQRHistory.value] // Filter by search if (historySearch.value) { const search = historySearch.value.toLowerCase() filtered = filtered.filter(item => item.data.toLowerCase().includes(search) ) } // Filter by date if (historyDateFilter.value && historyDateFilter.value.trim() !== '') { filtered = filtered.filter(item => { if (!item.timestamp && !item.date) return false try { let itemDate: Date if (item.timestamp) { itemDate = new Date(item.timestamp) } else { // Parse Indonesian date format (dd/mm/yyyy or dd mmm yyyy) itemDate = new Date(item.date) } const filterDate = new Date(historyDateFilter.value) // Validate dates if (isNaN(itemDate.getTime()) || isNaN(filterDate.getTime())) { return false } // Compare dates (year, month, day only, ignore time) const itemDateStr = itemDate.toISOString().substring(0, 10) const filterDateStr = filterDate.toISOString().substring(0, 10) return itemDateStr === filterDateStr } catch (e) { console.error('Error filtering QR history by date:', e) return false } }) } return filtered }) const getStatusColor = (status: string) => { if (status === 'ALLOWED' || status === 'success') return 'success' if (status === 'NOT_ALLOWED' || status === 'failed') return 'error' return 'warning' } const getStatusIcon = (status: string) => { if (status === 'ALLOWED' || status === 'success') return 'mdi-check-circle' if (status === 'NOT_ALLOWED' || status === 'failed') return 'mdi-close-circle' return 'mdi-clock-alert' } const getStatusText = (status: string) => { if (status === 'ALLOWED' || status === 'success') return 'Berhasil' if (status === 'NOT_ALLOWED' || status === 'failed') return 'Gagal' return 'Pending' } const getStatusClass = (status: string) => { if (status === 'ALLOWED' || status === 'success') return 'history-success' if (status === 'NOT_ALLOWED' || status === 'failed') return 'history-failed' return 'history-pending' } const formatDateTime = (dateString: string) => { const date = new Date(dateString) // Format jam dengan titik dua (HH:MM:SS) const timeString = date.toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit', second: '2-digit' }) return timeString.replace(/\./g, ':') } const formatDate = (dateString: string) => { const date = new Date(dateString) return date.toLocaleDateString('id-ID', { day: '2-digit', month: 'short', year: 'numeric' }) } // Load history on initialization if (typeof window !== 'undefined') { loadHistory() loadScannedQRHistory() } return { checkInHistory: readonly(checkInHistory), scannedQRHistory: readonly(scannedQRHistory), historySearch, historyStatusFilter, historyDateFilter, filteredHistory, filteredQRHistory, loadHistory, saveToHistory, deleteHistoryItem, clearHistory, loadScannedQRHistory, saveScannedQRData, clearQRHistory, deleteQRHistoryItem, getStatusColor, getStatusIcon, getStatusText, getStatusClass, formatDateTime, formatDate, historyStatusOptions: [...HISTORY_STATUS_OPTIONS] as Array<{ title: string; value: string }>, } }