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:
@@ -245,13 +245,15 @@ export const holidayApiService = {
|
|||||||
|
|
||||||
// Countries with states
|
// Countries with states
|
||||||
getCountriesWithStates: async (): Promise<IServerResponse<ICountryWithStates[]>> => {
|
getCountriesWithStates: async (): Promise<IServerResponse<ICountryWithStates[]>> => {
|
||||||
const response = await apiClient.get<IServerResponse<ICountryWithStates[]>>(
|
try {
|
||||||
`${API_BASE_URL}/admin-center/countries-with-states`
|
const response = await apiClient.get<IServerResponse<ICountryWithStates[]>>(
|
||||||
);
|
`${API_BASE_URL}/admin-center/countries-with-states`
|
||||||
return response.data;
|
);
|
||||||
|
return response.data;
|
||||||
// Fallback to static data if API fails
|
} catch (error) {
|
||||||
/*const supportedCountries = [
|
logger.error('Error fetching countries with states from API, falling back to static data', error);
|
||||||
|
// Fallback to static data if API fails
|
||||||
|
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' },
|
||||||
@@ -687,10 +689,11 @@ export const holidayApiService = {
|
|||||||
{ code: 'ZA', name: 'South Africa' }
|
{ code: 'ZA', name: 'South Africa' }
|
||||||
];
|
];
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@@ -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>
|
||||||
<Form.Item label={t('workingHours')} name="workingHours">
|
<Row>
|
||||||
<Input type="number" min={1} max={24} suffix={t('hours')} width={100} />
|
<Col span={6}>
|
||||||
</Form.Item>
|
<Form.Item label={t('workingHours')} name="workingHours">
|
||||||
|
<Input type="number" min={1} max={24} suffix={t('hours')} />
|
||||||
|
</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,25 +256,27 @@ const SettingsPage: React.FC = () => {
|
|||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={12}>
|
{selectedCountryStates.length > 0 && (
|
||||||
<Form.Item label={t('state') || 'State/Province'} name="state_code">
|
<Col span={12}>
|
||||||
<Select
|
<Form.Item label={t('state') || 'State/Province'} name="state_code">
|
||||||
placeholder={t('selectState') || 'Select state/province (optional)'}
|
<Select
|
||||||
allowClear
|
placeholder={t('selectState') || 'Select state/province (optional)'}
|
||||||
disabled={!holidayForm.getFieldValue('country_code')}
|
allowClear
|
||||||
showSearch
|
disabled={!holidayForm.getFieldValue('country_code')}
|
||||||
filterOption={(input, option) =>
|
showSearch
|
||||||
(option?.children as unknown as string)?.toLowerCase().includes(input.toLowerCase())
|
filterOption={(input, option) =>
|
||||||
}
|
(option?.children as unknown as string)?.toLowerCase().includes(input.toLowerCase())
|
||||||
>
|
}
|
||||||
{getSelectedCountryStates().map(state => (
|
>
|
||||||
<Select.Option key={state.code} value={state.code}>
|
{selectedCountryStates.map(state => (
|
||||||
{state.name}
|
<Select.Option key={state.code} value={state.code}>
|
||||||
</Select.Option>
|
{state.name}
|
||||||
))}
|
</Select.Option>
|
||||||
</Select>
|
))}
|
||||||
</Form.Item>
|
</Select>
|
||||||
</Col>
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t('autoSyncHolidays') || 'Automatically sync official holidays'}
|
label={t('autoSyncHolidays') || 'Automatically sync official holidays'}
|
||||||
|
|||||||
Reference in New Issue
Block a user