183 lines
4.9 KiB
Svelte
Raw Normal View History

<script>
import { onMount } from 'svelte';
import { fetchGeographicalAreas, fetchProvinces, fetchCities } from '$lib/api/geography.js';
import { success as toastSuccess, error as toastError } from '$lib/utils/toast.js';
import DataTable from '$lib/components/DataTable.svelte';
import SelectDropdown from '$lib/components/SelectDropdown.svelte';
import { ArrowLeft, MapPin, Globe, Building2 } from 'lucide-svelte';
let loading = $state(false);
let activeTab = $state('provinces');
let areas = $state([]);
let provinces = $state([]);
let cities = $state([]);
let selectedProvince = $state('');
const areaColumns = [
{ key: 'AreaGeoID', label: 'ID', class: 'font-medium' },
{ key: 'AreaCode', label: 'Code' },
{ key: 'AreaName', label: 'Name' },
{ key: 'Class', label: 'Class' },
{ key: 'Parent', label: 'Parent' },
];
const provinceColumns = [
{ key: 'value', label: 'ID', class: 'font-medium' },
{ key: 'label', label: 'Province Name' },
];
const cityColumns = [
{ key: 'value', label: 'ID', class: 'font-medium' },
{ key: 'label', label: 'City Name' },
];
onMount(async () => {
await loadProvinces();
});
async function loadAreas() {
loading = true;
try {
const response = await fetchGeographicalAreas();
areas = response.data || [];
} catch (err) {
toastError(err.message || 'Failed to load geographical areas');
areas = [];
} finally {
loading = false;
}
}
async function loadProvinces() {
loading = true;
try {
const response = await fetchProvinces();
provinces = Array.isArray(response) ? response : (Array.isArray(response.data) ? response.data : []);
} catch (err) {
toastError(err.message || 'Failed to load provinces');
provinces = [];
} finally {
loading = false;
}
}
async function loadCities() {
loading = true;
try {
const provinceId = selectedProvince || null;
const response = await fetchCities(provinceId);
cities = Array.isArray(response) ? response : (Array.isArray(response.data) ? response.data : []);
} catch (err) {
toastError(err.message || 'Failed to load cities');
cities = [];
} finally {
loading = false;
}
}
function handleTabChange(tab) {
activeTab = tab;
if (tab === 'areas' && areas.length === 0) {
loadAreas();
} else if (tab === 'cities' && cities.length === 0) {
loadCities();
}
}
const provinceOptions = $derived(
provinces.map((p) => ({ value: p.value, label: p.label }))
);
// Reload cities when province filter changes
$effect(() => {
if (activeTab === 'cities') {
loadCities();
}
});
</script>
<div class="p-6">
<div class="flex items-center gap-4 mb-6">
<a href="/master-data" class="btn btn-ghost btn-circle">
<ArrowLeft class="w-5 h-5" />
</a>
<div class="flex-1">
<h1 class="text-3xl font-bold text-gray-800">Geography</h1>
<p class="text-gray-600">View geographical areas, provinces, and cities</p>
</div>
</div>
<div class="tabs tabs-boxed mb-6">
<button
class="tab gap-2"
class:tab-active={activeTab === 'provinces'}
onclick={() => handleTabChange('provinces')}
>
<MapPin class="w-4 h-4" />
Provinces
</button>
<button
class="tab gap-2"
class:tab-active={activeTab === 'cities'}
onclick={() => handleTabChange('cities')}
>
<Building2 class="w-4 h-4" />
Cities
</button>
<button
class="tab gap-2"
class:tab-active={activeTab === 'areas'}
onclick={() => handleTabChange('areas')}
>
<Globe class="w-4 h-4" />
All Areas
</button>
</div>
{#if activeTab === 'provinces'}
<div class="bg-base-100 rounded-lg shadow border border-base-200">
<DataTable
columns={provinceColumns}
data={provinces}
{loading}
emptyMessage="No provinces found"
hover={true}
bordered={false}
/>
</div>
{:else if activeTab === 'cities'}
<div class="space-y-4">
<div class="bg-base-200 p-4 rounded-lg">
<SelectDropdown
label="Filter by Province"
name="province"
bind:value={selectedProvince}
options={provinceOptions}
placeholder="All Provinces"
/>
</div>
<div class="bg-base-100 rounded-lg shadow border border-base-200">
<DataTable
columns={cityColumns}
data={cities}
{loading}
emptyMessage="No cities found"
hover={true}
bordered={false}
/>
</div>
</div>
{:else if activeTab === 'areas'}
<div class="bg-base-100 rounded-lg shadow border border-base-200">
<DataTable
columns={areaColumns}
data={areas}
{loading}
emptyMessage="No geographical areas found"
hover={true}
bordered={false}
/>
</div>
{/if}
</div>