feat: setup crud scheduling data
parent
e737a89a24
commit
1b9c656007
|
@ -10,10 +10,10 @@
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"antd": "^5.21.2",
|
|
||||||
"ag-grid-community": "^31.3.2",
|
"ag-grid-community": "^31.3.2",
|
||||||
"ag-grid-enterprise": "^31.3.2",
|
"ag-grid-enterprise": "^31.3.2",
|
||||||
"ag-grid-react": "^31.3.2",
|
"ag-grid-react": "^31.3.2",
|
||||||
|
"antd": "^5.21.2",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
|
|
|
@ -118,7 +118,7 @@ export default function DefaultValue() {
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
<Row gutter={[8, 8]}>
|
<Row gutter={[8, 8]}>
|
||||||
<Col xl={4} span={12}>
|
<Col span={12}>
|
||||||
<Card loading={loading} styles={{ body: { padding: '6px 12px 6px 12px' } }}>
|
<Card loading={loading} styles={{ body: { padding: '6px 12px 6px 12px' } }}>
|
||||||
<Flex vertical gap={8} justify="space-between">
|
<Flex vertical gap={8} justify="space-between">
|
||||||
<div style={{ fontSize: 12, fontWeight: 600, color: 'rgba(0,0,0,0.4)' }}>DEFAULT PERCENTAGE</div>
|
<div style={{ fontSize: 12, fontWeight: 600, color: 'rgba(0,0,0,0.4)' }}>DEFAULT PERCENTAGE</div>
|
||||||
|
@ -136,7 +136,7 @@ export default function DefaultValue() {
|
||||||
</Flex>
|
</Flex>
|
||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xl={4} span={12}>
|
<Col span={12}>
|
||||||
<Card loading={loading} styles={{ body: { padding: '6px 12px 6px 12px' } }}>
|
<Card loading={loading} styles={{ body: { padding: '6px 12px 6px 12px' } }}>
|
||||||
<Flex vertical gap={8} justify="space-between">
|
<Flex vertical gap={8} justify="space-between">
|
||||||
<div style={{ fontSize: 12, fontWeight: 600, color: 'rgba(0,0,0,0.4)' }}>CURRENT PERCENTAGE</div>
|
<div style={{ fontSize: 12, fontWeight: 600, color: 'rgba(0,0,0,0.4)' }}>CURRENT PERCENTAGE</div>
|
|
@ -0,0 +1,207 @@
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { App, Button, Card, Col, Flex, List, notification, Pagination, Row, Tag, Tooltip } from 'antd';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { makeColorStatus, STATUS_DATA } from '@pos/base';
|
||||||
|
|
||||||
|
import { DeleteOutlined, EditOutlined, LockOutlined, UnlockOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
|
export default function SchedulingData() {
|
||||||
|
const { modal } = App.useApp();
|
||||||
|
|
||||||
|
const [loadingTable, setLoadingTable] = useState(false);
|
||||||
|
const [schedulingData, setSchedulingData] = useState<any[]>([]);
|
||||||
|
const [meta, setMeta] = useState<any>();
|
||||||
|
|
||||||
|
const handleGetData = async (page: number) => {
|
||||||
|
setLoadingTable(true);
|
||||||
|
await axios
|
||||||
|
.get('v1/data-scheduling', { params: { page: page, limit: 10 } })
|
||||||
|
.then((resp: any) => {
|
||||||
|
const data = resp?.data?.data ?? [];
|
||||||
|
const meta = resp?.data?.meta;
|
||||||
|
setMeta(meta);
|
||||||
|
setSchedulingData(data);
|
||||||
|
setLoadingTable(false);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setLoadingTable(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleActivate = async (id: string) => {
|
||||||
|
await axios
|
||||||
|
.patch(`v1/data-scheduling/${id}/active`)
|
||||||
|
.then(() => {
|
||||||
|
handleGetData(meta?.currentPage);
|
||||||
|
})
|
||||||
|
.catch((err: any) => {
|
||||||
|
notification.error({
|
||||||
|
message: 'Gagal mengaktifkan data.',
|
||||||
|
description:
|
||||||
|
err?.message ?? err?.response?.data?.message ?? 'Terjadi kesalahan saat mengaktifkan konfigurasi',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeactivate = async (id: string) => {
|
||||||
|
await axios
|
||||||
|
.patch(`v1/data-scheduling/${id}/inactive`)
|
||||||
|
.then(() => {
|
||||||
|
handleGetData(meta?.currentPage);
|
||||||
|
})
|
||||||
|
.catch((err: any) => {
|
||||||
|
notification.error({
|
||||||
|
message: 'Gagal menonaktifkan data.',
|
||||||
|
description:
|
||||||
|
err?.message ?? err?.response?.data?.message ?? 'Terjadi kesalahan saat menonaktifkan konfigurasi',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDelete = async (id: string) => {
|
||||||
|
await axios
|
||||||
|
.delete(`v1/data-scheduling/${id}`)
|
||||||
|
.then(() => {
|
||||||
|
handleGetData(meta?.currentPage);
|
||||||
|
})
|
||||||
|
.catch((err: any) => {
|
||||||
|
notification.error({
|
||||||
|
message: 'Gagal menghapus data.',
|
||||||
|
description: err?.message ?? err?.response?.data?.message ?? 'Terjadi kesalahan saat menghapus konfigurasi',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function makeColorText(value: number) {
|
||||||
|
if (value <= 30) {
|
||||||
|
return 'text-red-500';
|
||||||
|
} else if (value > 30 && value <= 80) {
|
||||||
|
return 'text-yellow-500';
|
||||||
|
} else if (value > 80 && value <= 100) {
|
||||||
|
return 'text-green-500';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleGetData(1);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Button>Tambah Jadwal</Button>
|
||||||
|
<div style={{ marginBottom: 10 }}></div>
|
||||||
|
<List
|
||||||
|
bordered={!schedulingData || schedulingData?.length <= 0}
|
||||||
|
style={{ maxHeight: 500, overflow: 'auto' }}
|
||||||
|
dataSource={schedulingData}
|
||||||
|
loading={loadingTable}
|
||||||
|
renderItem={(item) => (
|
||||||
|
<List.Item key={item.id} style={{ borderBlockEnd: 'none', padding: 5 }}>
|
||||||
|
<Card style={{ width: '100%' }}>
|
||||||
|
<Flex justify="space-between" style={{ width: '100%' }}>
|
||||||
|
<Row className="w-full">
|
||||||
|
<Col span={12}>
|
||||||
|
<Flex align="center" className="h-full" gap={4}>
|
||||||
|
<div>
|
||||||
|
<div className="text-[#00000066]">{item.name}</div>
|
||||||
|
<div className="font-normal mt-1">{`${dayjs(item?.schedule_date_from).format('DD MMM YYYY')} - ${dayjs(item?.schedule_date_to).format('DD MMM YYYY')}`}</div>
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Flex align="center" className="h-full" gap={8}>
|
||||||
|
<div
|
||||||
|
className={`text-2xl font-bold ${makeColorText(item.indexing_key)}`}
|
||||||
|
>{`${item.indexing_key} %`}</div>
|
||||||
|
<Tag color={makeColorStatus(item.status)}>{item.status}</Tag>
|
||||||
|
</Flex>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Flex align="center" gap={12}>
|
||||||
|
<Tooltip title="Edit" trigger={'hover'} placement="bottom">
|
||||||
|
<Button icon={<EditOutlined />} />
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
{item.status === STATUS_DATA.ACTIVE && (
|
||||||
|
<Tooltip title="Inactive" trigger={'hover'} placement="bottom">
|
||||||
|
<Button
|
||||||
|
icon={<LockOutlined />}
|
||||||
|
onClick={() => {
|
||||||
|
modal.confirm({
|
||||||
|
icon: null,
|
||||||
|
cancelText: 'Batal',
|
||||||
|
title: 'Nonaktifkan Konfigurasi Penjadwalan?',
|
||||||
|
cancelButtonProps: { style: { width: 100 } },
|
||||||
|
okButtonProps: { style: { width: 100 } },
|
||||||
|
content: (
|
||||||
|
<div>
|
||||||
|
<div className="font-semibold italic">{`Perhatian: `}</div>
|
||||||
|
<div className="italic">{`Konfigurasi yang dinonaktifkan tidak akan diikutsertakan dalam proses penjadwalan hingga Anda mengaktifkannya kembali. Ini berguna untuk menjeda proses penjadwalan tertentu tanpa menghapus konfigurasi.`}</div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
onOk: () => handleDeactivate(item.id),
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{item.status === STATUS_DATA.INACTIVE && (
|
||||||
|
<Tooltip title="Active" trigger={'hover'} placement="bottom">
|
||||||
|
<Button
|
||||||
|
icon={<UnlockOutlined />}
|
||||||
|
onClick={() => {
|
||||||
|
modal.confirm({
|
||||||
|
icon: null,
|
||||||
|
cancelText: 'Batal',
|
||||||
|
title: 'Aktifkan Konfigurasi Penjadwalan?',
|
||||||
|
cancelButtonProps: { style: { width: 100 } },
|
||||||
|
okButtonProps: { style: { width: 100 } },
|
||||||
|
content: (
|
||||||
|
<div>
|
||||||
|
<div className="font-semibold italic">{`Perhatian: `}</div>
|
||||||
|
<div className="italic">{`Dengan mengaktifkannya, konfigurasi ini akan kembali diperhitungkan dan digunakan dalam proses penjadwalan selanjutnya, sesuai dengan kriteria yang telah ditetapkan.`}</div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
onOk: () => handleActivate(item.id),
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Tooltip title="Delete" trigger={'hover'} placement="bottom">
|
||||||
|
<Button
|
||||||
|
icon={<DeleteOutlined />}
|
||||||
|
onClick={() => {
|
||||||
|
modal.confirm({
|
||||||
|
icon: null,
|
||||||
|
cancelText: 'Batal',
|
||||||
|
title: 'Hapus Konfigurasi Penjadwalan?',
|
||||||
|
cancelButtonProps: { style: { width: 100 } },
|
||||||
|
okButtonProps: { style: { width: 100 } },
|
||||||
|
content: (
|
||||||
|
<div>
|
||||||
|
<div className="font-semibold italic">{`Perhatian: `}</div>
|
||||||
|
<div className="italic">{`Tindakan ini bersifat permanen. Konfigurasi yang terhapus tidak akan lagi disertakan dalam perhitungan atau proses penjadwalan di masa mendatang dan tidak dapat dipulihkan.`}</div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
onOk: () => handleDelete(item.id),
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Card>
|
||||||
|
</List.Item>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<div style={{ marginBottom: 10 }}></div>
|
||||||
|
<Flex justify="end">
|
||||||
|
<Pagination current={meta?.currentPage} total={meta?.totalPages} />
|
||||||
|
</Flex>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -2,7 +2,10 @@ import { ACCESS_SETTING, UserDataState } from '@pos/base';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import DefaultValue from '../layout/components/default-value';
|
|
||||||
|
import DefaultValue from './components/default-value';
|
||||||
|
import SchedulingData from './components/scheduling-data';
|
||||||
|
import { Flex } from 'antd';
|
||||||
|
|
||||||
export default function SettingModule() {
|
export default function SettingModule() {
|
||||||
const user = useRecoilValue(UserDataState);
|
const user = useRecoilValue(UserDataState);
|
||||||
|
@ -21,11 +24,13 @@ export default function SettingModule() {
|
||||||
if (!checkAllowAccessSetting()) {
|
if (!checkAllowAccessSetting()) {
|
||||||
navigate('/app');
|
navigate('/app');
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<Flex vertical gap={24}>
|
||||||
<DefaultValue />
|
<DefaultValue />
|
||||||
</div>
|
<SchedulingData />
|
||||||
|
</Flex>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue