feat(admin-center): implement organization calculation method settings

- Added functionality to update the organization's calculation method (hourly or man-days) in the Admin Center.
- Created a new component for managing the calculation method, including UI elements for selection and saving changes.
- Updated API service to handle the new endpoint for updating the calculation method.
- Enhanced localization files to support new keys related to the calculation method settings.
- Introduced a settings page to manage organization working days and hours alongside the calculation method.
This commit is contained in:
chamikaJ
2025-07-24 12:53:46 +05:30
parent 67a75685a9
commit 4b54f2cc17
28 changed files with 1033 additions and 142 deletions

View File

@@ -4,6 +4,7 @@ import {
ProfileOutlined,
TeamOutlined,
UserOutlined,
SettingOutlined,
} from '@/shared/antd-imports';
import React, { ReactNode, lazy } from 'react';
const Overview = lazy(() => import('./overview/overview'));
@@ -11,6 +12,7 @@ const Users = lazy(() => import('./users/users'));
const Teams = lazy(() => import('./teams/teams'));
const Billing = lazy(() => import('./billing/billing'));
const Projects = lazy(() => import('./projects/projects'));
const Settings = lazy(() => import('./settings/settings'));
// type of a menu item in admin center sidebar
type AdminCenterMenuItems = {
@@ -57,4 +59,11 @@ export const adminCenterItems: AdminCenterMenuItems[] = [
icon: React.createElement(CreditCardOutlined),
element: React.createElement(Billing),
},
{
key: 'settings',
name: 'settings',
endpoint: 'settings',
icon: React.createElement(SettingOutlined),
element: React.createElement(Settings),
},
];

View File

@@ -1,7 +1,10 @@
import { EditOutlined, MailOutlined, PhoneOutlined } from '@/shared/antd-imports';
import { PageHeader } from '@ant-design/pro-components';
import { Button, Card, Input, Space, Tooltip, Typography } from '@/shared/antd-imports';
import React, { useEffect, useState } from 'react';
import {
Card,
Space,
Typography,
} from '@/shared/antd-imports';
import { PageHeader } from '@ant-design/pro-components';
import OrganizationAdminsTable from '@/components/admin-center/overview/organization-admins-table/organization-admins-table';
import { useAppSelector } from '@/hooks/useAppSelector';
import { RootState } from '@/app/store';
@@ -11,9 +14,6 @@ import OrganizationOwner from '@/components/admin-center/overview/organization-o
import { adminCenterApiService } from '@/api/admin-center/admin-center.api.service';
import { IOrganization, IOrganizationAdmin } from '@/types/admin-center/admin-center.types';
import logger from '@/utils/errorLogger';
import { tr } from 'date-fns/locale';
const { Text } = Typography;
const Overview: React.FC = () => {
const [organization, setOrganization] = useState<IOrganization | null>(null);

View File

@@ -0,0 +1 @@
export { default } from './settings';

View File

@@ -0,0 +1,156 @@
import React, { useEffect, useState } from 'react';
import {
Button,
Card,
Input,
Space,
Typography,
Checkbox,
Col,
Form,
Row,
message,
} from '@/shared/antd-imports';
import { PageHeader } from '@ant-design/pro-components';
import { useTranslation } from 'react-i18next';
import { adminCenterApiService } from '@/api/admin-center/admin-center.api.service';
import { IOrganization } from '@/types/admin-center/admin-center.types';
import logger from '@/utils/errorLogger';
import { scheduleAPIService } from '@/api/schedule/schedule.api.service';
import { Settings } from '@/types/schedule/schedule-v2.types';
import OrganizationCalculationMethod from '@/components/admin-center/overview/organization-calculation-method/organization-calculation-method';
const SettingsPage: React.FC = () => {
const [organization, setOrganization] = useState<IOrganization | null>(null);
const [workingDays, setWorkingDays] = useState<Settings['workingDays']>([]);
const [workingHours, setWorkingHours] = useState<Settings['workingHours']>(8);
const [saving, setSaving] = useState(false);
const [form] = Form.useForm();
const { t } = useTranslation('admin-center/settings');
const getOrganizationDetails = async () => {
try {
const res = await adminCenterApiService.getOrganizationDetails();
if (res.done) {
setOrganization(res.body);
}
} catch (error) {
logger.error('Error getting organization details', error);
}
};
const getOrgWorkingSettings = async () => {
try {
const res = await scheduleAPIService.fetchScheduleSettings();
if (res && res.done) {
setWorkingDays(
res.body.workingDays || ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
);
setWorkingHours(res.body.workingHours || 8);
form.setFieldsValue({
workingDays: res.body.workingDays || [
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
],
workingHours: res.body.workingHours || 8,
});
}
} catch (error) {
logger.error('Error getting organization working settings', error);
}
};
const handleSave = async (values: any) => {
setSaving(true);
try {
const res = await scheduleAPIService.updateScheduleSettings({
workingDays: values.workingDays,
workingHours: values.workingHours,
});
if (res && res.done) {
message.success(t('saved'));
setWorkingDays(values.workingDays);
setWorkingHours(values.workingHours);
getOrgWorkingSettings();
}
} catch (error) {
logger.error('Error updating organization working days/hours', error);
message.error(t('errorSaving'));
} finally {
setSaving(false);
}
};
useEffect(() => {
getOrganizationDetails();
getOrgWorkingSettings();
}, []);
return (
<div style={{ width: '100%' }}>
<PageHeader title={<span>{t('settings')}</span>} style={{ padding: '16px 0' }} />
<Space direction="vertical" style={{ width: '100%' }} size={22}>
<Card>
<Typography.Title level={5} style={{ margin: 0 }}>
{t('organizationWorkingDaysAndHours') || 'Organization Working Days & Hours'}
</Typography.Title>
<Form
layout="vertical"
form={form}
initialValues={{ workingDays, workingHours }}
onFinish={handleSave}
style={{ marginTop: 16 }}
>
<Form.Item label={t('workingDays')} name="workingDays">
<Checkbox.Group>
<Row>
<Col span={8}>
<Checkbox value="Monday">{t('monday')}</Checkbox>
</Col>
<Col span={8}>
<Checkbox value="Tuesday">{t('tuesday')}</Checkbox>
</Col>
<Col span={8}>
<Checkbox value="Wednesday">{t('wednesday')}</Checkbox>
</Col>
<Col span={8}>
<Checkbox value="Thursday">{t('thursday')}</Checkbox>
</Col>
<Col span={8}>
<Checkbox value="Friday">{t('friday')}</Checkbox>
</Col>
<Col span={8}>
<Checkbox value="Saturday">{t('saturday')}</Checkbox>
</Col>
<Col span={8}>
<Checkbox value="Sunday">{t('sunday')}</Checkbox>
</Col>
</Row>
</Checkbox.Group>
</Form.Item>
<Form.Item label={t('workingHours')} name="workingHours">
<Input type="number" min={1} max={24} suffix={t('hours')} width={100} />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" loading={saving}>
{t('saveButton') || 'Save'}
</Button>
</Form.Item>
</Form>
</Card>
<OrganizationCalculationMethod
organization={organization}
refetch={getOrganizationDetails}
/>
</Space>
</div>
);
};
export default SettingsPage;