import { ref, computed, watch } from 'vue' import { refDebounced } from '@vueuse/core' import type { District } from '~/models/district' import type { SelectItem } from '~/components/pub/my-ui/form/select.vue' import { toTitleCase } from '~/lib/utils' import * as districtService from '~/services/district.service' // Global cache untuk districts berdasarkan regency code const districtsCache = ref>(new Map()) const loadingStates = ref>(new Map()) const errorStates = ref>(new Map()) export function useDistricts(regencyCode: Ref | string | undefined) { // Convert regencyCode ke ref jika bukan ref const regencyCodeRef = typeof regencyCode === 'string' || regencyCode === undefined ? ref(regencyCode) : regencyCode // Computed untuk mendapatkan districts berdasarkan regency code const districts = computed(() => { const code = regencyCodeRef.value if (!code) return [] return districtsCache.value.get(code) || [] }) // Computed untuk loading state const isLoading = computed(() => { const code = regencyCodeRef.value if (!code) return false return loadingStates.value.get(code) || false }) // Computed untuk error state const error = computed(() => { const code = regencyCodeRef.value if (!code) return null return errorStates.value.get(code) || null }) // Computed untuk format SelectItem const districtOptions = computed(() => { return districts.value.map((district) => ({ label: toTitleCase(district.name), value: district.code, searchValue: `${district.code} ${district.name}`.trim(), })) }) // Function untuk fetch districts berdasarkan regency code async function fetchDistricts(regencyCodeParam?: string, forceRefresh = false, isUserAction = false) { const code = regencyCodeParam || regencyCodeRef.value if (!code) return // Jika user action atau force refresh, selalu fetch // Jika bukan user action dan sudah ada cache, skip if (!isUserAction && !forceRefresh && districtsCache.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 districtService.getList({ sort: 'name:asc', 'regency-code': code, 'page-no-limit': true, }) if (response.success) { const districtsData = response.body.data || [] districtsCache.value.set(code, districtsData) } else { errorStates.value.set(code, 'Gagal memuat data kecamatan') console.error('Failed to fetch districts:', response) } } catch (err) { errorStates.value.set(code, 'Terjadi kesalahan saat memuat data kecamatan') console.error('Error fetching districts:', err) } finally { loadingStates.value.set(code, false) loadingStates.value.delete(pendingKey) } } // Function untuk mencari district berdasarkan code function getDistrictByCode(code: string): District | undefined { const regencyCode = regencyCodeRef.value if (!regencyCode) return undefined const districtsForRegency = districtsCache.value.get(regencyCode) || [] return districtsForRegency.find((district) => district.code === code) } // Function untuk mencari district berdasarkan name function getDistrictByName(name: string): District | undefined { const regencyCode = regencyCodeRef.value if (!regencyCode) return undefined const districtsForRegency = districtsCache.value.get(regencyCode) || [] return districtsForRegency.find((district) => district.name.toLowerCase() === name.toLowerCase()) } // Function untuk clear cache regency tertentu function clearCache(regencyCodeParam?: string) { const code = regencyCodeParam || regencyCodeRef.value if (code) { districtsCache.value.delete(code) loadingStates.value.delete(code) errorStates.value.delete(code) } } // Function untuk clear semua cache function clearAllCache() { districtsCache.value.clear() loadingStates.value.clear() errorStates.value.clear() } // Function untuk refresh data function refreshDistricts(regencyCodeParam?: string) { const code = regencyCodeParam || regencyCodeRef.value if (code) { return fetchDistricts(code, true) } } // Debounced regency code untuk mencegah multiple calls const debouncedRegencyCode = refDebounced(regencyCodeRef, 100) // Watch perubahan regency code untuk auto fetch watch( debouncedRegencyCode, (newCode, oldCode) => { if (newCode && newCode !== oldCode) { // Jika ada oldCode berarti user action (ganti pilihan) const isUserAction = !!oldCode fetchDistricts(newCode, false, isUserAction) } }, { immediate: true }, ) return { // Data districts: readonly(districts), districtOptions, // State isLoading: readonly(isLoading), error: readonly(error), // Methods fetchDistricts, refreshDistricts, getDistrictByCode, getDistrictByName, clearCache, clearAllCache, } } // Export untuk direct access ke cached data (jika diperlukan) export const useDistrictsCache = () => ({ districtsCache: readonly(districtsCache), loadingStates: readonly(loadingStates), errorStates: readonly(errorStates), })