import React, { useEffect, useMemo, useState, useCallback } from 'react'; import DataTable from '../components/DataTable'; import { countryAPI, provinceAPI, cityAPI } from '../services/api'; import { Plus, Search, Pencil, Trash2, MapPin, Globe, Building2 } from 'lucide-react'; import { ToastContainer, toast } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; import { getErrorMessage, getSuccessMessage } from '../utils/errorHandler'; const Location = () => { const [activeTab, setActiveTab] = useState('country'); // 'country', 'province', 'city' // Country states const [countries, setCountries] = useState([]); const [countriesLoading, setCountriesLoading] = useState(true); const [countryFilter, setCountryFilter] = useState(''); const [isCountryModalOpen, setIsCountryModalOpen] = useState(false); const [editingCountry, setEditingCountry] = useState(null); const [countryForm, setCountryForm] = useState({ name: '', phoneCode: '', currencyCode: '', timeZoneName: '' }); // Province states const [provinces, setProvinces] = useState([]); const [provincesLoading, setProvincesLoading] = useState(true); const [provinceFilter, setProvinceFilter] = useState(''); const [selectedCountryFilter, setSelectedCountryFilter] = useState(''); const [isProvinceModalOpen, setIsProvinceModalOpen] = useState(false); const [editingProvince, setEditingProvince] = useState(null); const [provinceForm, setProvinceForm] = useState({ countryId: '', provinceName: '' }); const [selectedCountryForProvince, setSelectedCountryForProvince] = useState(null); // City states const [cities, setCities] = useState([]); const [citiesLoading, setCitiesLoading] = useState(true); const [cityFilter, setCityFilter] = useState(''); const [selectedCountryFilterForCity, setSelectedCountryFilterForCity] = useState(''); const [selectedProvinceFilterForCity, setSelectedProvinceFilterForCity] = useState(''); const [isCityModalOpen, setIsCityModalOpen] = useState(false); const [editingCity, setEditingCity] = useState(null); const [cityForm, setCityForm] = useState({ provinceId: '', cityName: '' }); const [selectedProvinceForCity, setSelectedProvinceForCity] = useState(null); const [provincesForCity, setProvincesForCity] = useState([]); // دریافت کشورها const fetchCountries = useCallback(async () => { try { setCountriesLoading(true); const list = await countryAPI.listAll(); setCountries(Array.isArray(list) ? list : []); } catch (err) { toast.error(getErrorMessage(err)); } finally { setCountriesLoading(false); } }, []); // دریافت استانها const fetchProvinces = useCallback(async (countryId = null) => { try { setProvincesLoading(true); const params = {}; if (countryId) { params.countryId = countryId; } const list = await provinceAPI.list(params); setProvinces(Array.isArray(list) ? list : []); } catch (err) { toast.error(getErrorMessage(err)); } finally { setProvincesLoading(false); } }, []); // دریافت شهرها const fetchCities = useCallback(async (countryId = null, provinceId = null) => { try { setCitiesLoading(true); const params = {}; if (countryId) { params.countryId = countryId; } if (provinceId) { params.provinceId = provinceId; } const list = await cityAPI.list(params); setCities(Array.isArray(list) ? list : []); } catch (err) { toast.error(getErrorMessage(err)); } finally { setCitiesLoading(false); } }, []); // دریافت کشورها - لود اولیه (برای country tab و dropdown ها) useEffect(() => { fetchCountries(); }, [fetchCountries]); // دریافت provinces برای province tab - وقتی tab تغییر میکند یا فیلتر country تغییر میکند useEffect(() => { if (activeTab === 'province') { const countryId = selectedCountryFilter || null; console.log('🔵 Fetching provinces for province tab with countryId:', countryId); fetchProvinces(countryId); } }, [activeTab, selectedCountryFilter, fetchProvinces]); // دریافت provinces برای city tab (برای dropdown) useEffect(() => { if (activeTab === 'city') { if (selectedCountryFilterForCity) { // دریافت provinces برای country انتخاب شده fetchProvinces(selectedCountryFilterForCity); } else { // دریافت همه provinces fetchProvinces(); } } }, [activeTab, selectedCountryFilterForCity, fetchProvinces]); // دریافت cities - وقتی tab تغییر میکند یا فیلترها تغییر میکنند useEffect(() => { if (activeTab === 'city') { const countryId = selectedCountryFilterForCity || null; const provinceId = selectedProvinceFilterForCity || null; console.log('🔵 Fetching cities with filters:', { countryId, provinceId }); fetchCities(countryId, provinceId); } }, [activeTab, selectedCountryFilterForCity, selectedProvinceFilterForCity, fetchCities]); // Reset filters when switching tabs useEffect(() => { if (activeTab !== 'province') { setSelectedCountryFilter(''); } if (activeTab !== 'city') { setSelectedCountryFilterForCity(''); setSelectedProvinceFilterForCity(''); } }, [activeTab]); // وقتی country برای city تغییر میکند، province filter را reset کن useEffect(() => { if (activeTab === 'city' && selectedCountryFilterForCity) { setSelectedProvinceFilterForCity(''); } }, [selectedCountryFilterForCity, activeTab]); // ========== Country Functions ========== const openCountryModal = (country = null) => { if (country) { setEditingCountry(country); setCountryForm({ name: country.name || '', phoneCode: country.phoneCode || '', currencyCode: country.currencyCode || '', timeZoneName: country.timeZoneName || country.timeZone || '', }); } else { setEditingCountry(null); setCountryForm({ name: '', phoneCode: '', currencyCode: '', timeZoneName: '' }); } setIsCountryModalOpen(true); }; const onSaveCountry = async (e) => { e.preventDefault(); // Validation if (!countryForm.name?.trim()) { toast.error('Name is required'); return; } if (!countryForm.phoneCode?.trim()) { toast.error('Phone Code is required'); return; } if (!countryForm.currencyCode?.trim()) { toast.error('Currency Code is required'); return; } if (!countryForm.timeZoneName?.trim()) { toast.error('Time Zone is required'); return; } try { if (editingCountry) { const countryId = editingCountry.id || editingCountry.countryId; if (!countryId) { toast.error('Country ID is missing'); console.error('Editing country:', editingCountry); return; } console.log('Updating country with ID:', countryId, 'Payload:', countryForm); await countryAPI.update(countryId, countryForm); toast.success(getSuccessMessage({ data: { message: 'Country updated successfully' } }) || 'Country updated successfully'); } else { console.log('Creating country with payload:', countryForm); await countryAPI.create(countryForm); toast.success(getSuccessMessage({ data: { message: 'Country added successfully' } }) || 'Country added successfully'); } await fetchCountries(); setIsCountryModalOpen(false); setEditingCountry(null); setCountryForm({ name: '', phoneCode: '', currencyCode: '', timeZoneName: '' }); } catch (err) { console.error('Error saving country:', err); toast.error(getErrorMessage(err)); } }; // ========== Province Functions ========== const openProvinceModal = (province = null) => { if (province) { setEditingProvince(province); setProvinceForm({ countryId: province.countryId || '', provinceName: province.name || '', }); setSelectedCountryForProvince(province.countryId); } else { setEditingProvince(null); setProvinceForm({ countryId: '', provinceName: '' }); setSelectedCountryForProvince(null); } setIsProvinceModalOpen(true); }; const onSaveProvince = async (e) => { e.preventDefault(); if (!provinceForm.countryId) { toast.error('Please select a country'); return; } try { if (editingProvince) { const provinceId = editingProvince.id || editingProvince.provinceId; if (!provinceId) { toast.error('Province ID is missing'); console.error('Editing province:', editingProvince); return; } console.log('Updating province with ID:', provinceId, 'Payload:', provinceForm); await provinceAPI.update(provinceId, provinceForm); toast.success(getSuccessMessage({ data: { message: 'Province updated successfully' } }) || 'Province updated successfully'); } else { await provinceAPI.create(provinceForm); toast.success(getSuccessMessage({ data: { message: 'Province added successfully' } }) || 'Province added successfully'); } await fetchProvinces(); setIsProvinceModalOpen(false); setEditingProvince(null); setProvinceForm({ countryId: '', provinceName: '' }); setSelectedCountryForProvince(null); } catch (err) { console.error('Error saving province:', err); toast.error(getErrorMessage(err)); } }; // ========== City Functions ========== const openCityModal = (city = null) => { if (city) { setEditingCity(city); setCityForm({ provinceId: city.provinceId || '', cityName: city.name || '', }); setSelectedProvinceForCity(city.provinceId); } else { setEditingCity(null); setCityForm({ provinceId: '', cityName: '' }); setSelectedProvinceForCity(null); } setIsCityModalOpen(true); }; const onSaveCity = async (e) => { e.preventDefault(); if (!cityForm.provinceId) { toast.error('Please select a province'); return; } try { if (editingCity) { const cityId = editingCity.id || editingCity.cityId; if (!cityId) { toast.error('City ID is missing'); console.error('Editing city:', editingCity); return; } console.log('Updating city with ID:', cityId, 'Payload:', cityForm); await cityAPI.update(cityId, cityForm); toast.success(getSuccessMessage({ data: { message: 'City updated successfully' } }) || 'City updated successfully'); } else { await cityAPI.create(cityForm); toast.success(getSuccessMessage({ data: { message: 'City added successfully' } }) || 'City added successfully'); } await fetchCities(); setIsCityModalOpen(false); setEditingCity(null); setCityForm({ provinceId: '', cityName: '' }); setSelectedProvinceForCity(null); } catch (err) { console.error('Error saving city:', err); toast.error(getErrorMessage(err)); } }; // ========== Table Columns ========== const countryColumns = useMemo(() => [ { key: 'name', header: 'Name' }, ], []); const provinceColumns = useMemo(() => [ { key: 'name', header: 'Province Name' }, { key: 'countryName', header: 'Country' }, { key: 'actions', header: 'Actions', render: (_val, row) => (
Manage countries, provinces, and cities