Compare commits
No commits in common. "main-cloud" and "main" have entirely different histories.
main-cloud
...
main
|
@ -1,5 +1,3 @@
|
||||||
VITE_APP_MODE=production
|
VITE_APP_MODE=production
|
||||||
VITE_BASE_API_URL=http://103.187.147.241:30050/api
|
VITE_BASE_API_URL=http://103.187.147.241:30050/api
|
||||||
VITE_BASE_API_REPORT_URL=http://103.187.147.241:30050/api
|
VITE_BASE_API_REPORT_URL=http://103.187.147.241:30050/api
|
||||||
|
|
||||||
VITE_BASE_API_URL_LOCAL=https://api.sky.eigen.co.id/api
|
|
|
@ -1,5 +1,3 @@
|
||||||
VITE_APP_MODE=production
|
VITE_APP_MODE=production
|
||||||
VITE_BASE_API_URL=https://api.sky.eigen.co.id/api
|
VITE_BASE_API_URL=https://api.sky.eigen.co.id/api
|
||||||
VITE_BASE_API_REPORT_URL=https://api.sky.eigen.co.id/api
|
VITE_BASE_API_REPORT_URL=https://api.sky.eigen.co.id/api
|
||||||
|
|
||||||
VITE_BASE_API_URL_LOCAL=https://api.sky.eigen.co.id/api
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
VITE_APP_MODE=production
|
VITE_APP_MODE=production
|
||||||
VITE_BASE_API_URL=http://172.16.2.101:30050/api
|
VITE_BASE_API_URL=http://172.16.2.101:30050/api
|
||||||
VITE_BASE_API_REPORT_URL=http://172.16.2.101:30050/api
|
VITE_BASE_API_REPORT_URL=http://172.16.2.101:30050/api
|
||||||
|
|
||||||
VITE_BASE_API_URL_LOCAL=http://172.16.2.101:30050/api
|
|
|
@ -1,5 +1,3 @@
|
||||||
VITE_APP_MODE=production
|
VITE_APP_MODE=production
|
||||||
VITE_BASE_API_URL=https://api.office.weplayground.id/api
|
VITE_BASE_API_URL=https://api.office.weplayground.id/api
|
||||||
VITE_BASE_API_REPORT_URL=https://api.office.weplayground.id/api
|
VITE_BASE_API_REPORT_URL=https://api.office.weplayground.id/api
|
||||||
|
|
||||||
VITE_BASE_API_URL_LOCAL=https://api.office.weplayground.id/api
|
|
|
@ -1,144 +0,0 @@
|
||||||
import axios from 'axios';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { App, Button, Col, InputNumber, InputNumberProps, Modal, ModalProps, Row, Slider } from 'antd';
|
|
||||||
import { API_URL, BASE_API_URL_LOCAL } from '@pos/base';
|
|
||||||
|
|
||||||
export default function LocalDataConfiguration(modalProps: ModalProps) {
|
|
||||||
const { modal, notification } = App.useApp();
|
|
||||||
|
|
||||||
const [configData, setConfigData] = useState<any>();
|
|
||||||
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) {
|
|
||||||
setLoadingSave(true);
|
|
||||||
await axios
|
|
||||||
.put(API_URL.EDIT_TRANSACTION_SETTING, { id: configData?.id, value }, { baseURL: BASE_API_URL_LOCAL })
|
|
||||||
.then(() => {
|
|
||||||
notification.success({
|
|
||||||
message: 'Sukses',
|
|
||||||
description: 'Konfigurasi berhasil disimpan',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (modalProps.onCancel) modalProps.onCancel(null as any);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
notification.error({
|
|
||||||
message: 'Gagal',
|
|
||||||
description: err?.message ?? err?.response?.data?.message ?? 'Terjadi kesalahan saat menyimpan konfigurasi',
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
setLoadingSave(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleGetData() {
|
|
||||||
setLoadingGet(true);
|
|
||||||
await axios
|
|
||||||
.get(API_URL.GET_TRANSACTION_SETTING, { baseURL: BASE_API_URL_LOCAL })
|
|
||||||
.then((res) => {
|
|
||||||
const data = res.data.data;
|
|
||||||
const respValue = data?.value;
|
|
||||||
setInputValue(Number(respValue ?? '0'));
|
|
||||||
setConfigData(data);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
notification.error({
|
|
||||||
message: 'Gagal',
|
|
||||||
description: err?.message ?? err?.response?.data?.message ?? 'Terjadi kesalahan saat mengambil konfigurasi',
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
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 { App, Avatar, Dropdown, Flex, Image, Layout } from 'antd';
|
import { Avatar, Flex, Image, Layout, Popconfirm, Tooltip } from 'antd';
|
||||||
import { ReactNode, useState } from 'react';
|
import { ReactNode, useState } from 'react';
|
||||||
import { Content, Header } from 'antd/es/layout/layout';
|
import { Content, Header } from 'antd/es/layout/layout';
|
||||||
import { API_URL, getInitialName, handleLogout, UserDataState } from '@pos/base';
|
import { API_URL, getInitialName, handleLogout, UserDataState } from '@pos/base';
|
||||||
|
@ -6,30 +6,25 @@ import { FaUser } from 'react-icons/fa';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import Logo from '../../../base/presentation/assets/images/we-logo.png';
|
import Logo from '../../../base/presentation/assets/images/we-logo.png';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import LocalDataConfiguration from './components/local-data-configuration';
|
|
||||||
import { LogoutOutlined, SettingOutlined } from '@ant-design/icons';
|
|
||||||
|
|
||||||
interface AdminLayoutProps {
|
interface AdminLayoutProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function AdminLayout(props: AdminLayoutProps) {
|
export default function AdminLayout(props: AdminLayoutProps) {
|
||||||
const { modal } = App.useApp();
|
|
||||||
|
|
||||||
const { children } = props;
|
const { children } = props;
|
||||||
|
const [_loadingLogout, setLoadingLogout] = useState(false);
|
||||||
const user = useRecoilValue(UserDataState);
|
const user = useRecoilValue(UserDataState);
|
||||||
const initialName = getInitialName(user?.name ?? '');
|
const initialName = getInitialName(user?.name ?? '');
|
||||||
|
|
||||||
const [openModalConfig, setOpenModalConfig] = useState(false);
|
|
||||||
const onCancelModalConfig = () => setOpenModalConfig(false);
|
|
||||||
const onOpenModalConfig = () => setOpenModalConfig(true);
|
|
||||||
|
|
||||||
async function handleClickLogout() {
|
async function handleClickLogout() {
|
||||||
|
setLoadingLogout(true);
|
||||||
try {
|
try {
|
||||||
await axios({ url: `${API_URL.LOGOUT}`, method: 'delete' });
|
await axios({ url: `${API_URL.LOGOUT}`, method: 'delete' });
|
||||||
|
setLoadingLogout(false);
|
||||||
await handleLogout();
|
await handleLogout();
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error(err);
|
setLoadingLogout(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +38,7 @@ export default function AdminLayout(props: AdminLayoutProps) {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
// background: token.colorPrimary,
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
borderBottom: '1px solid #ddd',
|
borderBottom: '1px solid #ddd',
|
||||||
}}
|
}}
|
||||||
|
@ -50,52 +46,27 @@ export default function AdminLayout(props: AdminLayoutProps) {
|
||||||
<Flex style={{ width: '100%' }} align="center">
|
<Flex style={{ width: '100%' }} align="center">
|
||||||
<Flex>
|
<Flex>
|
||||||
<Image src={Logo} width={50} preview={false} />
|
<Image src={Logo} width={50} preview={false} />
|
||||||
|
{/* <div style={{ fontWeight: 800, fontSize: 16 }}>WE POS</div> */}
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex style={{ marginLeft: 'auto' }} gap={15} align="center">
|
<Flex style={{ marginLeft: 'auto' }}>
|
||||||
<Dropdown
|
<Popconfirm
|
||||||
trigger={['click']}
|
title="Are you sure want to logout?"
|
||||||
overlayStyle={{ width: 150 }}
|
placement="bottomRight"
|
||||||
menu={{
|
onConfirm={() => handleClickLogout()}
|
||||||
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(),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<Avatar size={35} style={{ cursor: 'pointer' }}>
|
<Tooltip title="Logout" placement="bottom">
|
||||||
{initialName ? (
|
<Avatar size={35}>
|
||||||
<div style={{ fontSize: 13 }}>{initialName?.toUpperCase()}</div>
|
{initialName ? (
|
||||||
) : (
|
<div style={{ fontSize: 13 }}>{initialName?.toUpperCase()}</div>
|
||||||
<FaUser style={{ fontSize: 14 }} />
|
) : (
|
||||||
)}
|
<FaUser style={{ fontSize: 14 }} />
|
||||||
</Avatar>
|
)}
|
||||||
</Dropdown>
|
</Avatar>
|
||||||
|
</Tooltip>
|
||||||
|
</Popconfirm>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Header>
|
</Header>
|
||||||
<LocalDataConfiguration open={openModalConfig} onCancel={onCancelModalConfig} />
|
|
||||||
<Content style={{ overflow: 'initial', background: '#fff', padding: 10 }}>{children}</Content>
|
<Content style={{ overflow: 'initial', background: '#fff', padding: 10 }}>{children}</Content>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Suspense, lazy } from 'react';
|
import { Suspense, lazy } from 'react';
|
||||||
import { RecoilRoot } from 'recoil';
|
import { RecoilRoot } from 'recoil';
|
||||||
import { ConfigProvider, Flex, Spin, App as AntdApp } from 'antd';
|
import { ConfigProvider, Flex, Spin } from 'antd';
|
||||||
import { DebugObserver, ForbiddenAccessPage, NotFoundPage } from '@pos/base';
|
import { DebugObserver, ForbiddenAccessPage, NotFoundPage } from '@pos/base';
|
||||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||||
import { APP_THEME } from '@pos/base/presentation/assets/themes';
|
import { APP_THEME } from '@pos/base/presentation/assets/themes';
|
||||||
|
@ -14,23 +14,21 @@ export default function App() {
|
||||||
<RecoilRoot>
|
<RecoilRoot>
|
||||||
<DebugObserver />
|
<DebugObserver />
|
||||||
<ConfigProvider theme={APP_THEME.LIGHT}>
|
<ConfigProvider theme={APP_THEME.LIGHT}>
|
||||||
<AntdApp>
|
<Suspense
|
||||||
<Suspense
|
fallback={
|
||||||
fallback={
|
<Flex align="center" justify="center" style={{ height: '100vh' }}>
|
||||||
<Flex align="center" justify="center" style={{ height: '100vh' }}>
|
<Spin indicator={<LoadingOutlined style={{ fontSize: 48 }} spin />} />
|
||||||
<Spin indicator={<LoadingOutlined style={{ fontSize: 48 }} spin />} />
|
</Flex>
|
||||||
</Flex>
|
}
|
||||||
}
|
>
|
||||||
>
|
<Routes>
|
||||||
<Routes>
|
<Route path="/auth/*" element={<AuthApp />} />
|
||||||
<Route path="/auth/*" element={<AuthApp />} />
|
<Route path="/app" element={<PrivateApp />} />
|
||||||
<Route path="/app" element={<PrivateApp />} />
|
<Route path="/404" element={<NotFoundPage />} />
|
||||||
<Route path="/404" element={<NotFoundPage />} />
|
<Route path="/403" element={<ForbiddenAccessPage />} />
|
||||||
<Route path="/403" element={<ForbiddenAccessPage />} />
|
<Route path="*" element={<Navigate to="/app" />} />
|
||||||
<Route path="*" element={<Navigate to="/app" />} />
|
</Routes>
|
||||||
</Routes>
|
</Suspense>
|
||||||
</Suspense>
|
|
||||||
</AntdApp>
|
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
</RecoilRoot>
|
</RecoilRoot>
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,7 +5,4 @@ export const API_URL = {
|
||||||
|
|
||||||
REPORT_SUMMARY_INCOME_ITEM: '/v1/report-summary/income-item',
|
REPORT_SUMMARY_INCOME_ITEM: '/v1/report-summary/income-item',
|
||||||
REPORT_SUMMARY_INCOME_ITEM_MASTER: '/v1/report-summary/income-item-master',
|
REPORT_SUMMARY_INCOME_ITEM_MASTER: '/v1/report-summary/income-item-master',
|
||||||
|
|
||||||
EDIT_TRANSACTION_SETTING: '/v1/transaction-setting',
|
|
||||||
GET_TRANSACTION_SETTING: '/v1/transaction-setting/detail',
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,5 +8,3 @@ export const EMBED_DASHBOARD_ID = import.meta.env.VITE_EMBED_DASHBOARD_ID;
|
||||||
export const DOWLOAD_POS_WINDOWS_URL = import.meta.env.VITE_DOWLOAD_POS_WINDOWS_URL;
|
export const DOWLOAD_POS_WINDOWS_URL = import.meta.env.VITE_DOWLOAD_POS_WINDOWS_URL;
|
||||||
export const DOWLOAD_POS_LINUX_DEB_URL = import.meta.env.VITE_DOWLOAD_POS_LINUX_DEB_URL;
|
export const DOWLOAD_POS_LINUX_DEB_URL = import.meta.env.VITE_DOWLOAD_POS_LINUX_DEB_URL;
|
||||||
export const DOWLOAD_POS_LINUX_SNAP_URL = import.meta.env.VITE_DOWLOAD_POS_LINUX_SNAP_URL;
|
export const DOWLOAD_POS_LINUX_SNAP_URL = import.meta.env.VITE_DOWLOAD_POS_LINUX_SNAP_URL;
|
||||||
|
|
||||||
export const BASE_API_URL_LOCAL = import.meta.env.VITE_BASE_API_URL_LOCAL;
|
|
||||||
|
|
Loading…
Reference in New Issue