import { ref, computed, watch, readonly, type Ref } from 'vue' import { refDebounced } from '@vueuse/core' import type { PostalRegion } from '~/models/postal-region' import type { SelectItem } from '~/components/pub/my-ui/form/select.vue' import * as postalRegionService from '~/services/postal-region.service' // Global cache untuk postal codes berdasarkan village code const postalRegionCache = ref>(new Map()) const loadingStates = ref>(new Map()) const errorStates = ref>(new Map()) export function usePostalRegion(villageCode: Ref | string | undefined) { // Convert villageCode ke ref jika bukan ref const villageCodeRef = typeof villageCode === 'string' || villageCode === undefined ? ref(villageCode) : villageCode // Computed untuk mendapatkan postalRegion berdasarkan village code const postalRegion = computed(() => { const code = villageCodeRef.value if (!code) return [] return postalRegionCache.value.get(code) || [] }) // Computed untuk loading state const isLoading = computed(() => { const code = villageCodeRef.value if (!code) return false return loadingStates.value.get(code) || false }) // Computed untuk error state const error = computed(() => { const code = villageCodeRef.value if (!code) return null return errorStates.value.get(code) || null }) // Computed untuk format SelectItem const postalRegionOptions = computed(() => { return postalRegion.value.map((postalRegion) => ({ label: postalRegion.code, value: postalRegion.code, searchValue: postalRegion.code, })) }) // Function untuk fetch postalRegion berdasarkan village code async function fetchpostalRegion(villageCodeParam?: string, forceRefresh = false, isUserAction = false) { const code = villageCodeParam || villageCodeRef.value if (!code) return // Jika user action atau force refresh, selalu fetch // Jika bukan user action dan sudah ada cache, skip if (!isUserAction && !forceRefresh && postalRegionCache.value.has(code)) { return } // Jika sedang loading, skip untuk mencegah duplicate calls if (loadingStates.value.get(code)) { return } // Tambahan: Cek apakah ada pending request untuk code yang sama const pendingKey = `pending_${code}` if (loadingStates.value.get(pendingKey)) { return } loadingStates.value.set(pendingKey, true) loadingStates.value.set(code, true) errorStates.value.set(code, null) try { const response = await postalRegionService.getList({ sort: 'code:asc', 'village-code': code, 'page-no-limit': true, }) if (response.success) { const postalRegionData = response.body.data || [] postalRegionCache.value.set(code, postalRegionData) } else { errorStates.value.set(code, 'Gagal memuat data kode pos') console.error('Failed to fetch postal codes:', response) } } catch (err) { errorStates.value.set(code, 'Terjadi kesalahan saat memuat data kode pos') console.error('Error fetching postal codes:', err) } finally { loadingStates.value.set(code, false) loadingStates.value.delete(pendingKey) } } // Function untuk mencari postalRegion berdasarkan code function getpostalRegionByCode(code: string): PostalRegion | undefined { const villageCode = villageCodeRef.value if (!villageCode) return undefined const postalRegionForVillage = postalRegionCache.value.get(villageCode) || [] return postalRegionForVillage.find((postalRegion) => postalRegion.code === code) } // Function untuk clear cache village tertentu function clearCache(villageCodeParam?: string) { const code = villageCodeParam || villageCodeRef.value if (code) { postalRegionCache.value.delete(code) loadingStates.value.delete(code) errorStates.value.delete(code) } } // Function untuk clear semua cache function clearAllCache() { postalRegionCache.value.clear() loadingStates.value.clear() errorStates.value.clear() } // Function untuk refresh data function refreshpostalRegion(villageCodeParam?: string) { const code = villageCodeParam || villageCodeRef.value if (code) { return fetchpostalRegion(code, true) } } // Debounced village code untuk mencegah multiple calls const debouncedVillageCode = refDebounced(villageCodeRef, 100) // Watch perubahan village code untuk auto fetch watch( debouncedVillageCode, (newCode, oldCode) => { if (newCode && newCode !== oldCode) { // Jika ada oldCode berarti user action (ganti pilihan) const isUserAction = !!oldCode fetchpostalRegion(newCode, false, isUserAction) } }, { immediate: true }, ) return { // Data postalRegion: readonly(postalRegion), postalRegionOptions, // State isLoading: readonly(isLoading), error: readonly(error), // Methods fetchpostalRegion, refreshpostalRegion, getpostalRegionByCode, clearCache, clearAllCache, } } // Export untuk direct access ke cached data (jika diperlukan) export const usepostalRegionCache = () => ({ postalRegionCache: readonly(postalRegionCache), loadingStates: readonly(loadingStates), errorStates: readonly(errorStates), })