feat: setup config local data
parent
16e2c8fc09
commit
537d574af7
|
@ -0,0 +1,111 @@
|
|||
import { App, Button, Col, InputNumber, InputNumberProps, Modal, ModalProps, Row, Slider } from 'antd';
|
||||
import { set } from 'lodash';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export default function LocalDataConfiguration(modalProps: ModalProps) {
|
||||
const { modal } = App.useApp();
|
||||
|
||||
const [inputValue, setInputValue] = useState(0);
|
||||
const [loadingGet, setLoadingGet] = useState(false);
|
||||
const [loadingSave, setLoadingSave] = useState(false);
|
||||
|
||||
const onChange: InputNumberProps['onChange'] = (newValue) => {
|
||||
setInputValue(newValue as number);
|
||||
};
|
||||
|
||||
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';
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSave(value: number) {
|
||||
console.log('Konfigurasi disimpan:', value);
|
||||
setLoadingSave(true);
|
||||
setLoadingSave(false);
|
||||
}
|
||||
|
||||
async function handleGetData() {
|
||||
console.log('Get data konfigurasi:');
|
||||
setLoadingGet(true);
|
||||
setLoadingGet(false);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (modalProps.open) handleGetData();
|
||||
}, [modalProps.open]);
|
||||
return (
|
||||
<Modal
|
||||
{...modalProps}
|
||||
title="KONFIGURASI TAMPILAN DATA LOKAL"
|
||||
width={800}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={modalProps.onCancel} style={{ width: 100 }} disabled={loadingSave || loadingGet}>
|
||||
Batal
|
||||
</Button>,
|
||||
<Button
|
||||
key="submit"
|
||||
type="primary"
|
||||
disabled={loadingSave || loadingGet}
|
||||
onClick={() => {
|
||||
modal.confirm({
|
||||
title: 'KONFIRMASI',
|
||||
icon: null,
|
||||
cancelText: 'Batal',
|
||||
cancelButtonProps: { style: { width: 100 } },
|
||||
okButtonProps: { style: { width: 100 } },
|
||||
content: (
|
||||
<div>
|
||||
<div>Apakah Anda yakin ingin menyimpan konfigurasi ini?</div>
|
||||
<div className="mb-4">Jumlah data yang akan ditampilkan di aplikasi lokal adalah: </div>
|
||||
<div className={`text-center font-bold text-6xl mb-6 ${makeColorText(inputValue)}`}>
|
||||
{inputValue}%
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
onOk: () => handleSave(inputValue),
|
||||
});
|
||||
}}
|
||||
>
|
||||
Simpan
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<div className="text-gray-600 italic mb-6">{`Gunakan slider atau input number dibawah ini untuk menentukan persentase data yang ingin ditampilkan di aplikasi lokal Anda. Semakin tinggi persentasenya, semakin banyak data yang akan ditampilkan. Sesuaikan dengan kebutuhan untuk memastikan performa aplikasi tetap optimal.`}</div>
|
||||
<div>
|
||||
<Row gutter={[32, 8]}>
|
||||
<Col span={24}>
|
||||
<InputNumber
|
||||
disabled={loadingSave || loadingGet}
|
||||
min={0}
|
||||
max={100}
|
||||
value={inputValue}
|
||||
onChange={onChange}
|
||||
addonAfter="%"
|
||||
/>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Slider
|
||||
min={0}
|
||||
max={100}
|
||||
disabled={loadingSave || loadingGet}
|
||||
onChange={onChange}
|
||||
value={typeof inputValue === 'number' ? inputValue : 0}
|
||||
marks={{
|
||||
0: '0%',
|
||||
25: '25%',
|
||||
50: '50%',
|
||||
75: '75%',
|
||||
100: '100%',
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import { Avatar, Flex, Image, Layout, Popconfirm, Tooltip } from 'antd';
|
||||
import { App, Avatar, Dropdown, Flex, Image, Layout } from 'antd';
|
||||
import { ReactNode, useState } from 'react';
|
||||
import { Content, Header } from 'antd/es/layout/layout';
|
||||
import { API_URL, getInitialName, handleLogout, UserDataState } from '@pos/base';
|
||||
|
@ -6,25 +6,30 @@ import { FaUser } from 'react-icons/fa';
|
|||
import axios from 'axios';
|
||||
import Logo from '../../../base/presentation/assets/images/we-logo.png';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import LocalDataConfiguration from './components/local-data-configuration';
|
||||
import { LogoutOutlined, SettingOutlined } from '@ant-design/icons';
|
||||
|
||||
interface AdminLayoutProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export default function AdminLayout(props: AdminLayoutProps) {
|
||||
const { modal } = App.useApp();
|
||||
|
||||
const { children } = props;
|
||||
const [_loadingLogout, setLoadingLogout] = useState(false);
|
||||
const user = useRecoilValue(UserDataState);
|
||||
const initialName = getInitialName(user?.name ?? '');
|
||||
|
||||
const [openModalConfig, setOpenModalConfig] = useState(false);
|
||||
const onCancelModalConfig = () => setOpenModalConfig(false);
|
||||
const onOpenModalConfig = () => setOpenModalConfig(true);
|
||||
|
||||
async function handleClickLogout() {
|
||||
setLoadingLogout(true);
|
||||
try {
|
||||
await axios({ url: `${API_URL.LOGOUT}`, method: 'delete' });
|
||||
setLoadingLogout(false);
|
||||
await handleLogout();
|
||||
} catch (err: any) {
|
||||
setLoadingLogout(false);
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,7 +43,6 @@ export default function AdminLayout(props: AdminLayoutProps) {
|
|||
width: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
// background: token.colorPrimary,
|
||||
background: '#fff',
|
||||
borderBottom: '1px solid #ddd',
|
||||
}}
|
||||
|
@ -46,27 +50,52 @@ export default function AdminLayout(props: AdminLayoutProps) {
|
|||
<Flex style={{ width: '100%' }} align="center">
|
||||
<Flex>
|
||||
<Image src={Logo} width={50} preview={false} />
|
||||
{/* <div style={{ fontWeight: 800, fontSize: 16 }}>WE POS</div> */}
|
||||
</Flex>
|
||||
<Flex style={{ marginLeft: 'auto' }}>
|
||||
<Popconfirm
|
||||
title="Are you sure want to logout?"
|
||||
placement="bottomRight"
|
||||
onConfirm={() => handleClickLogout()}
|
||||
<Flex style={{ marginLeft: 'auto' }} gap={15} align="center">
|
||||
<Dropdown
|
||||
trigger={['click']}
|
||||
overlayStyle={{ width: 150 }}
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
key: '1',
|
||||
label: 'Settings',
|
||||
icon: <SettingOutlined />,
|
||||
onClick: () => onOpenModalConfig(),
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: 'Logout',
|
||||
icon: <LogoutOutlined />,
|
||||
onClick: () => {
|
||||
modal.confirm({
|
||||
icon: null,
|
||||
cancelText: 'Batal',
|
||||
cancelButtonProps: { style: { width: 100 } },
|
||||
okButtonProps: { style: { width: 100 } },
|
||||
content: <div>Apakah anda yakin ingin keluar dari aplikasi?</div>,
|
||||
onOk: () => handleClickLogout(),
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
}}
|
||||
>
|
||||
<Tooltip title="Logout" placement="bottom">
|
||||
<Avatar size={35}>
|
||||
<Avatar size={35} style={{ cursor: 'pointer' }}>
|
||||
{initialName ? (
|
||||
<div style={{ fontSize: 13 }}>{initialName?.toUpperCase()}</div>
|
||||
) : (
|
||||
<FaUser style={{ fontSize: 14 }} />
|
||||
)}
|
||||
</Avatar>
|
||||
</Tooltip>
|
||||
</Popconfirm>
|
||||
</Dropdown>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Header>
|
||||
<LocalDataConfiguration open={openModalConfig} onCancel={onCancelModalConfig} />
|
||||
<Content style={{ overflow: 'initial', background: '#fff', padding: 10 }}>{children}</Content>
|
||||
</Layout>
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Suspense, lazy } from 'react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { ConfigProvider, Flex, Spin } from 'antd';
|
||||
import { ConfigProvider, Flex, Spin, App as AntdApp } from 'antd';
|
||||
import { DebugObserver, ForbiddenAccessPage, NotFoundPage } from '@pos/base';
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
import { APP_THEME } from '@pos/base/presentation/assets/themes';
|
||||
|
@ -14,6 +14,7 @@ export default function App() {
|
|||
<RecoilRoot>
|
||||
<DebugObserver />
|
||||
<ConfigProvider theme={APP_THEME.LIGHT}>
|
||||
<AntdApp>
|
||||
<Suspense
|
||||
fallback={
|
||||
<Flex align="center" justify="center" style={{ height: '100vh' }}>
|
||||
|
@ -29,6 +30,7 @@ export default function App() {
|
|||
<Route path="*" element={<Navigate to="/app" />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</AntdApp>
|
||||
</ConfigProvider>
|
||||
</RecoilRoot>
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue