fix(holiday-api): add error handling and fallback for countries with states API

- Implemented try-catch block in `getCountriesWithStates` to handle API errors gracefully.
- Added logging for errors when fetching countries, with a fallback to static data if the API call fails.
- Updated the `SettingsPage` to utilize the selected country code state for improved state selection logic.
This commit is contained in:
Chamika J
2025-08-01 17:17:57 +05:30
parent 8f407b45a9
commit 11a6224fb3
2 changed files with 50 additions and 38 deletions

View File

@@ -245,13 +245,15 @@ export const holidayApiService = {
// Countries with states // Countries with states
getCountriesWithStates: async (): Promise<IServerResponse<ICountryWithStates[]>> => { getCountriesWithStates: async (): Promise<IServerResponse<ICountryWithStates[]>> => {
try {
const response = await apiClient.get<IServerResponse<ICountryWithStates[]>>( const response = await apiClient.get<IServerResponse<ICountryWithStates[]>>(
`${API_BASE_URL}/admin-center/countries-with-states` `${API_BASE_URL}/admin-center/countries-with-states`
); );
return response.data; return response.data;
} catch (error) {
logger.error('Error fetching countries with states from API, falling back to static data', error);
// Fallback to static data if API fails // Fallback to static data if API fails
/*const supportedCountries = [ const supportedCountries = [
{ code: 'AD', name: 'Andorra' }, { code: 'AD', name: 'Andorra' },
{ code: 'AE', name: 'United Arab Emirates' }, { code: 'AE', name: 'United Arab Emirates' },
{ code: 'AG', name: 'Antigua & Barbuda' }, { code: 'AG', name: 'Antigua & Barbuda' },
@@ -690,7 +692,8 @@ export const holidayApiService = {
return { return {
done: true, done: true,
body: supportedCountries, body: supportedCountries,
} as IServerResponse<ICountryWithStates[]>;*/ } as IServerResponse<ICountryWithStates[]>;
}
}, },
// Combined holidays (official + custom) - Database-driven approach // Combined holidays (official + custom) - Database-driven approach

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState, useMemo } from 'react';
import { import {
Button, Button,
Card, Card,
@@ -46,6 +46,7 @@ const SettingsPage: React.FC = () => {
const [workingHours, setWorkingHours] = useState<Settings['workingHours']>(8); const [workingHours, setWorkingHours] = useState<Settings['workingHours']>(8);
const [saving, setSaving] = useState(false); const [saving, setSaving] = useState(false);
const [savingHolidays, setSavingHolidays] = useState(false); const [savingHolidays, setSavingHolidays] = useState(false);
const [selectedCountryCode, setSelectedCountryCode] = useState<string | undefined>(undefined);
const [form] = Form.useForm(); const [form] = Form.useForm();
const [holidayForm] = Form.useForm(); const [holidayForm] = Form.useForm();
@@ -127,6 +128,7 @@ const SettingsPage: React.FC = () => {
state_code: holidaySettings.state_code, state_code: holidaySettings.state_code,
auto_sync_holidays: holidaySettings.auto_sync_holidays ?? true, auto_sync_holidays: holidaySettings.auto_sync_holidays ?? true,
}); });
setSelectedCountryCode(holidaySettings.country_code);
} }
}, [holidaySettings, holidayForm]); }, [holidaySettings, holidayForm]);
@@ -143,12 +145,12 @@ const SettingsPage: React.FC = () => {
} }
}; };
const getSelectedCountryStates = () => { const selectedCountryStates = useMemo(() => {
const selectedCountry = countriesWithStates.find( const selectedCountry = countriesWithStates.find(
country => country.code === holidayForm.getFieldValue('country_code') country => country.code === selectedCountryCode
); );
return selectedCountry?.states || []; return selectedCountry?.states || [];
}; }, [countriesWithStates, selectedCountryCode]);
return ( return (
<div style={{ width: '100%' }}> <div style={{ width: '100%' }}>
@@ -193,9 +195,13 @@ const SettingsPage: React.FC = () => {
</Row> </Row>
</Checkbox.Group> </Checkbox.Group>
</Form.Item> </Form.Item>
<Row>
<Col span={6}>
<Form.Item label={t('workingHours')} name="workingHours"> <Form.Item label={t('workingHours')} name="workingHours">
<Input type="number" min={1} max={24} suffix={t('hours')} width={100} /> <Input type="number" min={1} max={24} suffix={t('hours')} />
</Form.Item> </Form.Item>
</Col>
</Row>
<Form.Item> <Form.Item>
<Button type="primary" htmlType="submit" loading={saving}> <Button type="primary" htmlType="submit" loading={saving}>
{t('saveButton') || 'Save'} {t('saveButton') || 'Save'}
@@ -233,8 +239,9 @@ const SettingsPage: React.FC = () => {
<Select <Select
placeholder={t('selectCountry') || 'Select country'} placeholder={t('selectCountry') || 'Select country'}
loading={loadingCountries} loading={loadingCountries}
onChange={() => { onChange={(value) => {
holidayForm.setFieldValue('state_code', undefined); holidayForm.setFieldValue('state_code', undefined);
setSelectedCountryCode(value);
}} }}
showSearch showSearch
filterOption={(input, option) => filterOption={(input, option) =>
@@ -249,6 +256,7 @@ const SettingsPage: React.FC = () => {
</Select> </Select>
</Form.Item> </Form.Item>
</Col> </Col>
{selectedCountryStates.length > 0 && (
<Col span={12}> <Col span={12}>
<Form.Item label={t('state') || 'State/Province'} name="state_code"> <Form.Item label={t('state') || 'State/Province'} name="state_code">
<Select <Select
@@ -260,7 +268,7 @@ const SettingsPage: React.FC = () => {
(option?.children as unknown as string)?.toLowerCase().includes(input.toLowerCase()) (option?.children as unknown as string)?.toLowerCase().includes(input.toLowerCase())
} }
> >
{getSelectedCountryStates().map(state => ( {selectedCountryStates.map(state => (
<Select.Option key={state.code} value={state.code}> <Select.Option key={state.code} value={state.code}>
{state.name} {state.name}
</Select.Option> </Select.Option>
@@ -268,6 +276,7 @@ const SettingsPage: React.FC = () => {
</Select> </Select>
</Form.Item> </Form.Item>
</Col> </Col>
)}
</Row> </Row>
<Form.Item <Form.Item
label={t('autoSyncHolidays') || 'Automatically sync official holidays'} label={t('autoSyncHolidays') || 'Automatically sync official holidays'}