implement claim submit
This commit is contained in:
@@ -2,6 +2,6 @@ GENERATE_SOURCEMAP=false
|
|||||||
|
|
||||||
PORT=8083
|
PORT=8083
|
||||||
|
|
||||||
REACT_APP_HOST_API_URL="http://aso.test"
|
REACT_APP_HOST_API_URL="https://aso-api.linksehat.dev/api/client"
|
||||||
|
|
||||||
VITE_API_URL="http://aso.test/api/client"
|
VITE_API_URL="https://aso-api.linksehat.dev/api/client"
|
||||||
|
|||||||
@@ -52,6 +52,7 @@
|
|||||||
"@mui/utils": "^5.11.13",
|
"@mui/utils": "^5.11.13",
|
||||||
"@mui/x-data-grid": "^5.17.26",
|
"@mui/x-data-grid": "^5.17.26",
|
||||||
"@mui/x-date-pickers": "5.0.0-beta.2",
|
"@mui/x-date-pickers": "5.0.0-beta.2",
|
||||||
|
"@reduxjs/toolkit": "^1.9.7",
|
||||||
"@vitejs/plugin-react": "^1.3.2",
|
"@vitejs/plugin-react": "^1.3.2",
|
||||||
"apexcharts": "^3.37.2",
|
"apexcharts": "^3.37.2",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
@@ -78,6 +79,7 @@
|
|||||||
"react-lazy-load-image-component": "^1.5.6",
|
"react-lazy-load-image-component": "^1.5.6",
|
||||||
"react-number-format": "^5.1.4",
|
"react-number-format": "^5.1.4",
|
||||||
"react-quill": "2.0.0-beta.4",
|
"react-quill": "2.0.0-beta.4",
|
||||||
|
"react-redux": "^8.1.3",
|
||||||
"react-router": "^6.9.0",
|
"react-router": "^6.9.0",
|
||||||
"react-router-dom": "^6.9.0",
|
"react-router-dom": "^6.9.0",
|
||||||
"simplebar": "^5.3.9",
|
"simplebar": "^5.3.9",
|
||||||
|
|||||||
101
frontend/client-portal/pnpm-lock.yaml
generated
101
frontend/client-portal/pnpm-lock.yaml
generated
@@ -47,6 +47,9 @@ dependencies:
|
|||||||
'@mui/x-date-pickers':
|
'@mui/x-date-pickers':
|
||||||
specifier: 5.0.0-beta.2
|
specifier: 5.0.0-beta.2
|
||||||
version: 5.0.0-beta.2(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@mui/material@5.11.14)(@mui/system@5.11.14)(date-fns@2.29.3)(react-dom@17.0.2)(react@17.0.2)
|
version: 5.0.0-beta.2(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@mui/material@5.11.14)(@mui/system@5.11.14)(date-fns@2.29.3)(react-dom@17.0.2)(react@17.0.2)
|
||||||
|
'@reduxjs/toolkit':
|
||||||
|
specifier: ^1.9.7
|
||||||
|
version: 1.9.7(react-redux@8.1.3)(react@17.0.2)
|
||||||
'@vitejs/plugin-react':
|
'@vitejs/plugin-react':
|
||||||
specifier: ^1.3.2
|
specifier: ^1.3.2
|
||||||
version: 1.3.2
|
version: 1.3.2
|
||||||
@@ -125,6 +128,9 @@ dependencies:
|
|||||||
react-quill:
|
react-quill:
|
||||||
specifier: 2.0.0-beta.4
|
specifier: 2.0.0-beta.4
|
||||||
version: 2.0.0-beta.4(react-dom@17.0.2)(react@17.0.2)
|
version: 2.0.0-beta.4(react-dom@17.0.2)(react@17.0.2)
|
||||||
|
react-redux:
|
||||||
|
specifier: ^8.1.3
|
||||||
|
version: 8.1.3(@types/react-dom@17.0.19)(@types/react@17.0.53)(react-dom@17.0.2)(react@17.0.2)(redux@4.2.1)
|
||||||
react-router:
|
react-router:
|
||||||
specifier: ^6.9.0
|
specifier: ^6.9.0
|
||||||
version: 6.9.0(react@17.0.2)
|
version: 6.9.0(react@17.0.2)
|
||||||
@@ -2336,6 +2342,25 @@ packages:
|
|||||||
resolution: {integrity: sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==}
|
resolution: {integrity: sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@reduxjs/toolkit@1.9.7(react-redux@8.1.3)(react@17.0.2):
|
||||||
|
resolution: {integrity: sha512-t7v8ZPxhhKgOKtU+uyJT13lu4vL7az5aFi4IdoDs/eS548edn2M8Ik9h8fxgvMjGoAUVFSt6ZC1P5cWmQ014QQ==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.9.0 || ^17.0.0 || ^18
|
||||||
|
react-redux: ^7.2.1 || ^8.0.2
|
||||||
|
peerDependenciesMeta:
|
||||||
|
react:
|
||||||
|
optional: true
|
||||||
|
react-redux:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
immer: 9.0.21
|
||||||
|
react: 17.0.2
|
||||||
|
react-redux: 8.1.3(@types/react-dom@17.0.19)(@types/react@17.0.53)(react-dom@17.0.2)(react@17.0.2)(redux@4.2.1)
|
||||||
|
redux: 4.2.1
|
||||||
|
redux-thunk: 2.4.2(redux@4.2.1)
|
||||||
|
reselect: 4.1.8
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@remix-run/router@1.4.0:
|
/@remix-run/router@1.4.0:
|
||||||
resolution: {integrity: sha512-BJ9SxXux8zAg991UmT8slpwpsd31K1dHHbD3Ba4VzD+liLQ4WAMSxQp2d2ZPRPfN0jN2NPRowcSSoM7lCaF08Q==}
|
resolution: {integrity: sha512-BJ9SxXux8zAg991UmT8slpwpsd31K1dHHbD3Ba4VzD+liLQ4WAMSxQp2d2ZPRPfN0jN2NPRowcSSoM7lCaF08Q==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
@@ -2572,6 +2597,13 @@ packages:
|
|||||||
'@types/range-parser': 1.2.4
|
'@types/range-parser': 1.2.4
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@types/hoist-non-react-statics@3.3.2:
|
||||||
|
resolution: {integrity: sha512-YIQtIg4PKr7ZyqNPZObpxfHsHEmuB8dXCxd6qVcGuQVDK2bpsF7bYNnBJ4Nn7giuACZg+WewExgrtAJ3XnA4Xw==}
|
||||||
|
dependencies:
|
||||||
|
'@types/react': 17.0.53
|
||||||
|
hoist-non-react-statics: 3.3.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@types/json-schema@7.0.11:
|
/@types/json-schema@7.0.11:
|
||||||
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
|
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -2619,7 +2651,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-PiYG40pnQRdPHnlf7tZnp0aQ6q9tspYr72vD61saO6zFCybLfMqwUCN0va1/P+86DXn18ZWeW30Bk7xlC5eEAQ==}
|
resolution: {integrity: sha512-PiYG40pnQRdPHnlf7tZnp0aQ6q9tspYr72vD61saO6zFCybLfMqwUCN0va1/P+86DXn18ZWeW30Bk7xlC5eEAQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/react': 17.0.53
|
'@types/react': 17.0.53
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/react-is@17.0.3:
|
/@types/react-is@17.0.3:
|
||||||
resolution: {integrity: sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==}
|
resolution: {integrity: sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==}
|
||||||
@@ -2668,6 +2699,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==}
|
resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/use-sync-external-store@0.0.3:
|
||||||
|
resolution: {integrity: sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@typescript-eslint/eslint-plugin@5.56.0(@typescript-eslint/parser@5.56.0)(eslint@8.36.0)(typescript@4.9.5):
|
/@typescript-eslint/eslint-plugin@5.56.0(@typescript-eslint/parser@5.56.0)(eslint@8.36.0)(typescript@4.9.5):
|
||||||
resolution: {integrity: sha512-ZNW37Ccl3oMZkzxrYDUX4o7cnuPgU+YrcaYXzsRtLB16I1FR5SHMqga3zGsaSliZADCWo2v8qHWqAYIj8nWCCg==}
|
resolution: {integrity: sha512-ZNW37Ccl3oMZkzxrYDUX4o7cnuPgU+YrcaYXzsRtLB16I1FR5SHMqga3zGsaSliZADCWo2v8qHWqAYIj8nWCCg==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
@@ -4467,6 +4502,10 @@ packages:
|
|||||||
engines: {node: '>= 4'}
|
engines: {node: '>= 4'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/immer@9.0.21:
|
||||||
|
resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/import-fresh@3.3.0:
|
/import-fresh@3.3.0:
|
||||||
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
|
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@@ -5341,6 +5380,40 @@ packages:
|
|||||||
react-dom: 17.0.2(react@17.0.2)
|
react-dom: 17.0.2(react@17.0.2)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/react-redux@8.1.3(@types/react-dom@17.0.19)(@types/react@17.0.53)(react-dom@17.0.2)(react@17.0.2)(redux@4.2.1):
|
||||||
|
resolution: {integrity: sha512-n0ZrutD7DaX/j9VscF+uTALI3oUPa/pO4Z3soOBIjuRn/FzVu6aehhysxZCLi6y7duMf52WNZGMl7CtuK5EnRw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': ^16.8 || ^17.0 || ^18.0
|
||||||
|
'@types/react-dom': ^16.8 || ^17.0 || ^18.0
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||||
|
react-native: '>=0.59'
|
||||||
|
redux: ^4 || ^5.0.0-beta.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
react-dom:
|
||||||
|
optional: true
|
||||||
|
react-native:
|
||||||
|
optional: true
|
||||||
|
redux:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.21.0
|
||||||
|
'@types/hoist-non-react-statics': 3.3.2
|
||||||
|
'@types/react': 17.0.53
|
||||||
|
'@types/react-dom': 17.0.19
|
||||||
|
'@types/use-sync-external-store': 0.0.3
|
||||||
|
hoist-non-react-statics: 3.3.2
|
||||||
|
react: 17.0.2
|
||||||
|
react-dom: 17.0.2(react@17.0.2)
|
||||||
|
react-is: 18.2.0
|
||||||
|
redux: 4.2.1
|
||||||
|
use-sync-external-store: 1.2.0(react@17.0.2)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/react-refresh@0.13.0:
|
/react-refresh@0.13.0:
|
||||||
resolution: {integrity: sha512-XP8A9BT0CpRBD+NYLLeIhld/RqG9+gktUjW1FkE+Vm7OCinbG1SshcK5tb9ls4kzvjZr9mOQc7HYgBngEyPAXg==}
|
resolution: {integrity: sha512-XP8A9BT0CpRBD+NYLLeIhld/RqG9+gktUjW1FkE+Vm7OCinbG1SshcK5tb9ls4kzvjZr9mOQc7HYgBngEyPAXg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -5391,6 +5464,20 @@ packages:
|
|||||||
object-assign: 4.1.1
|
object-assign: 4.1.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/redux-thunk@2.4.2(redux@4.2.1):
|
||||||
|
resolution: {integrity: sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==}
|
||||||
|
peerDependencies:
|
||||||
|
redux: ^4
|
||||||
|
dependencies:
|
||||||
|
redux: 4.2.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/redux@4.2.1:
|
||||||
|
resolution: {integrity: sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==}
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.21.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/regenerate-unicode-properties@10.1.0:
|
/regenerate-unicode-properties@10.1.0:
|
||||||
resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==}
|
resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@@ -5447,6 +5534,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==}
|
resolution: {integrity: sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/reselect@4.1.8:
|
||||||
|
resolution: {integrity: sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/resolve-from@4.0.0:
|
/resolve-from@4.0.0:
|
||||||
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
|
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@@ -6009,6 +6100,14 @@ packages:
|
|||||||
punycode: 2.3.0
|
punycode: 2.3.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/use-sync-external-store@1.2.0(react@17.0.2):
|
||||||
|
resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
|
dependencies:
|
||||||
|
react: 17.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/vite-plugin-pwa@0.12.8(vite@3.2.5)(workbox-build@6.5.4)(workbox-window@6.5.4):
|
/vite-plugin-pwa@0.12.8(vite@3.2.5)(workbox-build@6.5.4)(workbox-window@6.5.4):
|
||||||
resolution: {integrity: sha512-pSiFHmnJGMQJJL8aJzQ8SaraZBSBPMGvGUkCNzheIq9UQCEk/eP3UmANNmS9eupuhIpTK8AdxTOHcaMcAqAbCA==}
|
resolution: {integrity: sha512-pSiFHmnJGMQJJL8aJzQ8SaraZBSBPMGvGUkCNzheIq9UQCEk/eP3UmANNmS9eupuhIpTK8AdxTOHcaMcAqAbCA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|||||||
@@ -9,27 +9,31 @@ import { ProgressBarStyle } from './components/ProgressBar';
|
|||||||
import ThemeColorPresets from './components/ThemeColorPresets';
|
import ThemeColorPresets from './components/ThemeColorPresets';
|
||||||
import MotionLazyContainer from './components/animate/MotionLazyContainer';
|
import MotionLazyContainer from './components/animate/MotionLazyContainer';
|
||||||
import { SnackbarProvider } from 'notistack';
|
import { SnackbarProvider } from 'notistack';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
import store from './store';
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<ThemeProvider>
|
<Provider store={store}>
|
||||||
<SnackbarProvider
|
<ThemeProvider>
|
||||||
autoHideDuration={2000}
|
<SnackbarProvider
|
||||||
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
|
autoHideDuration={2000}
|
||||||
>
|
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
|
||||||
<ThemeColorPresets>
|
>
|
||||||
<RtlLayout>
|
<ThemeColorPresets>
|
||||||
<MotionLazyContainer>
|
<RtlLayout>
|
||||||
<ProgressBarStyle />
|
<MotionLazyContainer>
|
||||||
{/* <Settings /> */}
|
<ProgressBarStyle />
|
||||||
<ScrollToTop />
|
{/* <Settings /> */}
|
||||||
<Router />
|
<ScrollToTop />
|
||||||
</MotionLazyContainer>
|
<Router />
|
||||||
</RtlLayout>
|
</MotionLazyContainer>
|
||||||
</ThemeColorPresets>
|
</RtlLayout>
|
||||||
</SnackbarProvider>
|
</ThemeColorPresets>
|
||||||
</ThemeProvider>
|
</SnackbarProvider>
|
||||||
|
</ThemeProvider>
|
||||||
|
</Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Grid,
|
Grid,
|
||||||
Avatar,
|
Avatar,
|
||||||
|
ButtonBase,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { Add } from '@mui/icons-material';
|
import { Add } from '@mui/icons-material';
|
||||||
// components
|
// components
|
||||||
@@ -23,10 +24,17 @@ import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
|
|||||||
// theme
|
// theme
|
||||||
import palette from '../../theme/palette';
|
import palette from '../../theme/palette';
|
||||||
// React
|
// React
|
||||||
import { ReactElement, useRef, useState } from 'react';
|
import { Fragment, ReactElement, useEffect, useRef, useState } from 'react';
|
||||||
import { useSearchParams, useNavigate, Link } from 'react-router-dom';
|
import { useSearchParams, useNavigate, Link } from 'react-router-dom';
|
||||||
import { fPostFormat } from '../../utils/formatTime';
|
import { fPostFormat } from '../../utils/formatTime';
|
||||||
import { fCurrency } from '../../utils/formatNumber';
|
import { fCurrency } from '../../utils/formatNumber';
|
||||||
|
import { LoadingButton } from '@mui/lab';
|
||||||
|
import Iconify from '../../components/Iconify';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import { RootState } from '../../store';
|
||||||
|
import { makeFormData } from '../../utils/jsonToFormData';
|
||||||
|
import { useSnackbar } from 'notistack';
|
||||||
|
import axiosInstance from '../../utils/axios';
|
||||||
|
|
||||||
// -------------------------------- type --------------------------------------
|
// -------------------------------- type --------------------------------------
|
||||||
type DataContentType = {
|
type DataContentType = {
|
||||||
@@ -44,6 +52,24 @@ type DataContentType = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type ClaimSubmission = {
|
||||||
|
id: number;
|
||||||
|
personID: string;
|
||||||
|
personName: string;
|
||||||
|
typePatient: string;
|
||||||
|
limit: {
|
||||||
|
current: number;
|
||||||
|
total: number;
|
||||||
|
percentage: number;
|
||||||
|
};
|
||||||
|
avatar: {
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
fileRealInvoice: any[];
|
||||||
|
anotherDocument: any[];
|
||||||
|
laboratoryResult: any[];
|
||||||
|
};
|
||||||
|
|
||||||
type MuiDialogProps = {
|
type MuiDialogProps = {
|
||||||
title?: {
|
title?: {
|
||||||
name?: string;
|
name?: string;
|
||||||
@@ -69,188 +95,435 @@ const BorderLinearProgress = styled(LinearProgress)(({ theme }) => ({
|
|||||||
}));
|
}));
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
const steps = ['Review', 'Approval', 'Disbursement'];
|
const steps = ['Review', 'Approval', 'Disbursement'];
|
||||||
|
|
||||||
const DialogDetailClaim = ({ title, openDialog, setOpenDialog, data }: MuiDialogProps) => {
|
const DialogDetailClaim = ({ title, openDialog, setOpenDialog, data }: MuiDialogProps) => {
|
||||||
function clickHandler(arg0: string) {
|
|
||||||
throw new Error('Function not implemented.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [serviceCode, setServiceCode] = useState('IP');
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
|
|
||||||
// const getContent = () => (
|
const [submitLoading, setSubmitLoading] = useState(false);
|
||||||
|
const selectedData = useSelector((state: RootState) => state.claims.data);
|
||||||
|
const [dataContent, setDataContent] = useState<ClaimSubmission[]>([]);
|
||||||
|
|
||||||
// );
|
useEffect(() => {
|
||||||
|
if (selectedData.length > 0) {
|
||||||
|
let temp: ClaimSubmission[] = selectedData.map((item) => ({
|
||||||
|
id: item.id,
|
||||||
|
avatar: {
|
||||||
|
url: '',
|
||||||
|
},
|
||||||
|
limit: item.limit,
|
||||||
|
personID: item.memberId,
|
||||||
|
personName: item.fullName,
|
||||||
|
typePatient: 'IP',
|
||||||
|
anotherDocument: [],
|
||||||
|
fileRealInvoice: [],
|
||||||
|
laboratoryResult: [],
|
||||||
|
}));
|
||||||
|
|
||||||
|
setDataContent(temp);
|
||||||
|
} else {
|
||||||
|
navigate('/claim-submit', { replace: true });
|
||||||
|
}
|
||||||
|
}, [selectedData]);
|
||||||
|
|
||||||
|
const handleServiceCode = (data: ClaimSubmission, index?: number) => {
|
||||||
|
let temp = dataContent.map((item) => {
|
||||||
|
if (item.personID === data.personID) {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
typePatient: item.typePatient === 'IP' ? 'OP' : 'IP',
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setDataContent(temp);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInputFile = (
|
||||||
|
event: any,
|
||||||
|
data: ClaimSubmission,
|
||||||
|
typeFile: 'invoice' | 'another' | 'lab'
|
||||||
|
) => {
|
||||||
|
if (event.target.files[0]) {
|
||||||
|
let temp = dataContent.map((item) => {
|
||||||
|
if (item.personID === data.personID) {
|
||||||
|
if (typeFile === 'invoice') {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
fileRealInvoice: [...item.fileRealInvoice, event.target.files[0]],
|
||||||
|
};
|
||||||
|
} else if (typeFile === 'another') {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
anotherDocument: [...item.anotherDocument, event.target.files[0]],
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
laboratoryResult: [...item.laboratoryResult, event.target.files[0]],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setDataContent(temp);
|
||||||
|
} else {
|
||||||
|
console.log('NO FILE');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRemoveFile = (
|
||||||
|
data: ClaimSubmission,
|
||||||
|
typeFile: 'invoice' | 'another' | 'lab',
|
||||||
|
index: number
|
||||||
|
) => {
|
||||||
|
let temp = dataContent.map((item) => {
|
||||||
|
if (item.personID === data.personID) {
|
||||||
|
if (typeFile === 'invoice') {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
fileRealInvoice: item.fileRealInvoice.filter((file, fileIndex) => fileIndex != index),
|
||||||
|
};
|
||||||
|
} else if (typeFile === 'another') {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
anotherDocument: item.anotherDocument.filter((file, fileIndex) => fileIndex != index),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
laboratoryResult: item.laboratoryResult.filter((file, fileIndex) => fileIndex != index),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setDataContent(temp);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = () => {
|
||||||
|
setSubmitLoading(true);
|
||||||
|
const mapArrayToFormData = (claims: ClaimSubmission[]): FormData => {
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
|
claims.forEach((claim, index) => {
|
||||||
|
formData.append(`member_id[${index}]`, claim.id.toString());
|
||||||
|
formData.append(`service_code[${index}]`, claim.typePatient);
|
||||||
|
|
||||||
|
claim.laboratoryResult.forEach((file, fileIndex) => {
|
||||||
|
formData.append(`laboratorium[${index}][${fileIndex}]`, file);
|
||||||
|
});
|
||||||
|
|
||||||
|
claim.anotherDocument.forEach((file, fileIndex) => {
|
||||||
|
formData.append(`prescription[${index}][${fileIndex}]`, file);
|
||||||
|
});
|
||||||
|
|
||||||
|
claim.fileRealInvoice.forEach((file, fileIndex) => {
|
||||||
|
formData.append(`invoice[${index}][${fileIndex}]`, file);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return formData;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formData = mapArrayToFormData(dataContent);
|
||||||
|
|
||||||
|
axiosInstance
|
||||||
|
.post('/claim-requests', formData)
|
||||||
|
.then((response) => {
|
||||||
|
enqueueSnackbar(response.data.message ?? 'Berhasil membuat data', { variant: 'success' });
|
||||||
|
navigate('/claim-submit', { replace: true });
|
||||||
|
})
|
||||||
|
.catch(({ response }) => {
|
||||||
|
enqueueSnackbar(response.data.message ?? 'Something Went Wrong', { variant: 'error' });
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setSubmitLoading(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Grid container>
|
<Grid container spacing={8}>
|
||||||
{/* Field 1 */}
|
{/* Field 1 */}
|
||||||
<Grid item xs={12} paddingX="24px" paddingY="20px">
|
<Grid item xs={12} paddingX="24px" paddingY="20px">
|
||||||
<Stack direction="row" alignItems="center">
|
<Stack direction="row" alignItems="center">
|
||||||
<ArrowBackIosIcon onClick={() => navigate(`/corporate`)} sx={{ cursor: "pointer" }} />
|
<ArrowBackIosIcon
|
||||||
<Typography variant="h5" sx={{ flexGrow: 1 }}>Claim Submission </Typography>
|
onClick={() => navigate(`/claim-submit`)}
|
||||||
<Typography variant="inherit" sx={{ textAlign: "center", flexBasis: "15%" }}>Submission Date </Typography>
|
sx={{ cursor: 'pointer' }}
|
||||||
<Typography textAlign={'right'} variant="h6" sx={{ textAlign: "right" }}>
|
/>
|
||||||
|
<Typography variant="h5" sx={{ flexGrow: 1 }}>
|
||||||
|
Claim Submission{' '}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="inherit" sx={{ textAlign: 'center', flexBasis: '15%' }}>
|
||||||
|
Submission Date{' '}
|
||||||
|
</Typography>
|
||||||
|
<Typography textAlign={'right'} variant="h6" sx={{ textAlign: 'right' }}>
|
||||||
{fPostFormat(new Date(), 'dd MMM yyyy')}
|
{fPostFormat(new Date(), 'dd MMM yyyy')}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} paddingX="24px" paddingY="20px">
|
{dataContent.map((row, index) => {
|
||||||
<Stack direction="row" spacing={4}>
|
return (
|
||||||
<Button
|
<Grid item xs={12} key={index}>
|
||||||
sx={{ padding: 2, width: '50%', border: serviceCode === 'OP' ? '1px solid #919EAB52' : '1px solid #19BBBB' }}
|
<Card sx={{ p: 3 }}>
|
||||||
variant={serviceCode == 'IP' ? 'outlined' : ''}
|
<Grid container spacing={4} key={index}>
|
||||||
onClick={() => {
|
<Grid item xs={12} paddingX="24px" paddingY="20px">
|
||||||
setServiceCode('IP');
|
<Stack direction="row" spacing={4}>
|
||||||
}}
|
<Button
|
||||||
>
|
sx={{
|
||||||
Inpatient
|
padding: 2,
|
||||||
</Button>
|
width: '50%',
|
||||||
<Button
|
border:
|
||||||
sx={{ padding: 2, width: '50%',border: serviceCode === 'IP' ? '1px solid #919EAB52' : '1px solid #19BBBB' }}
|
row.typePatient === 'OP' ? '1px solid #919EAB52' : '1px solid #19BBBB',
|
||||||
variant={serviceCode == 'OP' ? 'outlined' : ''}
|
}}
|
||||||
onClick={() => {
|
variant="outlined"
|
||||||
setServiceCode('OP');
|
color={row.typePatient === 'IP' ? 'primary' : 'inherit'}
|
||||||
}}
|
onClick={() => {
|
||||||
>
|
handleServiceCode(row);
|
||||||
Outpatient
|
}}
|
||||||
</Button>
|
>
|
||||||
</Stack>
|
Inpatient
|
||||||
</Grid>
|
</Button>
|
||||||
<Grid item xs={12}>
|
<Button
|
||||||
<Card sx={{ p: 2, marginBottom: 2 }}>
|
sx={{
|
||||||
<Stack direction="row" alignContent={'center'}>
|
padding: 2,
|
||||||
<Avatar
|
width: '50%',
|
||||||
src="https://minimal-assets-api.vercel.app/assets/images/avatars/avatar_5.jpg"
|
border:
|
||||||
alt={'test'}
|
row.typePatient === 'IP' ? '1px solid #919EAB52' : '1px solid #19BBBB',
|
||||||
sx={{ margin: 1, width: 56, height: 56 }}
|
}}
|
||||||
/>
|
variant="outlined"
|
||||||
<Stack sx={{ p: 1 }}>
|
color={row.typePatient === 'OP' ? 'primary' : 'inherit'}
|
||||||
<Typography variant='h5'>{'Alexandra Rhea Putranto'}</Typography>
|
onClick={() => {
|
||||||
<Typography variant='subtitle1' color={'#637381'}>{'KM002-01'}</Typography>
|
handleServiceCode(row);
|
||||||
</Stack>
|
}}
|
||||||
<Stack sx={{ p: 1 }}>
|
>
|
||||||
<Typography variant="body1" sx={{ marginBottom: 1, fontWeight: 600 }}>
|
Outpatient
|
||||||
Total Limit
|
</Button>
|
||||||
</Typography>
|
</Stack>
|
||||||
<BorderLinearProgress variant="determinate" value={80} />
|
</Grid>
|
||||||
<Typography sx={{ textAlign: 'right', marginTop: 1 }}>
|
<Grid item xs={12}>
|
||||||
{fCurrency(8000000)} / {fCurrency(100000)}
|
<Card sx={{ p: 2 }}>
|
||||||
</Typography>
|
<Stack direction="row" alignContent={'center'}>
|
||||||
</Stack>
|
<Avatar
|
||||||
</Stack>
|
src="https://minimal-assets-api.vercel.app/assets/images/avatars/avatar_5.jpg"
|
||||||
</Card>
|
alt={'test'}
|
||||||
</Grid>
|
sx={{ margin: 1, width: 56, height: 56 }}
|
||||||
|
/>
|
||||||
|
<Stack sx={{ p: 1 }}>
|
||||||
|
<Typography variant="h5">{row.personName}</Typography>
|
||||||
|
<Typography variant="subtitle1" color="#637381">
|
||||||
|
{row.personID}
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
<Stack sx={{ p: 1 }}>
|
||||||
|
<Typography variant="body1" sx={{ marginBottom: 1, fontWeight: 600 }}>
|
||||||
|
Total Limit
|
||||||
|
</Typography>
|
||||||
|
<BorderLinearProgress
|
||||||
|
variant="determinate"
|
||||||
|
value={row.limit && row.limit.percentage}
|
||||||
|
sx={{ mb: 1 }}
|
||||||
|
/>
|
||||||
|
<Typography sx={{ textAlign: 'right', marginTop: 1 }}>
|
||||||
|
{fCurrency(8000000)} / {fCurrency(100000)}
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* REAL INVOICE */}
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Typography variant="h6">Real Invoice</Typography>
|
||||||
|
</Grid>
|
||||||
|
{row.fileRealInvoice &&
|
||||||
|
row.fileRealInvoice.map((file, fileIndex) => (
|
||||||
|
<Grid item xs={12} key={fileIndex}>
|
||||||
|
<Stack direction="row" justifyContent={'space-between'}>
|
||||||
|
<Typography sx={{ color: 'text.secondary' }}>{file.name}</Typography>
|
||||||
|
<Iconify
|
||||||
|
icon="eva:trash-2-outline"
|
||||||
|
color={'darkred'}
|
||||||
|
onClick={() => {
|
||||||
|
handleRemoveFile(row, 'invoice', fileIndex);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
placeContent: 'center',
|
||||||
|
placeItems: 'center',
|
||||||
|
border: '2px dashed #F9FAFB',
|
||||||
|
bgcolor: '#919EAB52',
|
||||||
|
borderRadius: '8px',
|
||||||
|
p: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Buttons handle={handleInputFile} row={row} type="invoice" />
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* DOCTOR'S PRESCRIPTION AND ANOTHER DOCUMENTS */}
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Typography variant="h6">
|
||||||
|
Doctor's Prescription and Another Documents
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
{row.anotherDocument &&
|
||||||
|
row.anotherDocument.map((file, fileIndex) => (
|
||||||
|
<Grid item xs={12} key={fileIndex}>
|
||||||
|
<Stack direction="row" justifyContent={'space-between'}>
|
||||||
|
<Typography sx={{ color: 'text.secondary' }}>{file.name}</Typography>
|
||||||
|
<Iconify
|
||||||
|
icon="eva:trash-2-outline"
|
||||||
|
color={'darkred'}
|
||||||
|
onClick={() => {
|
||||||
|
handleRemoveFile(row, 'another', fileIndex);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
placeContent: 'center',
|
||||||
|
placeItems: 'center',
|
||||||
|
border: '2px dashed #F9FAFB',
|
||||||
|
bgcolor: '#919EAB52',
|
||||||
|
borderRadius: '8px',
|
||||||
|
p: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Buttons handle={handleInputFile} row={row} type="another" />
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* LABORATORY RESULTS */}
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Typography variant="h6">Laboraroty Results</Typography>
|
||||||
|
</Grid>
|
||||||
|
{row.laboratoryResult &&
|
||||||
|
row.laboratoryResult.map((file, fileIndex) => (
|
||||||
|
<Grid item xs={12} key={fileIndex}>
|
||||||
|
<Stack direction="row" justifyContent={'space-between'}>
|
||||||
|
<Typography sx={{ color: 'text.secondary' }}>{file.name}</Typography>
|
||||||
|
<Iconify
|
||||||
|
icon="eva:trash-2-outline"
|
||||||
|
color={'darkred'}
|
||||||
|
onClick={() => {
|
||||||
|
handleRemoveFile(row, 'lab', fileIndex);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
placeContent: 'center',
|
||||||
|
placeItems: 'center',
|
||||||
|
border: '2px dashed #F9FAFB',
|
||||||
|
bgcolor: '#919EAB52',
|
||||||
|
borderRadius: '8px',
|
||||||
|
p: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Buttons handle={handleInputFile} row={row} type="lab" />
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Card>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<LoadingButton
|
||||||
|
variant="contained"
|
||||||
|
sx={{ marginTop: 2, p: 2, margin: '10px' }}
|
||||||
|
fullWidth
|
||||||
|
onClick={onSubmit}
|
||||||
|
loading={submitLoading}
|
||||||
|
>
|
||||||
|
Claim Submit
|
||||||
|
</LoadingButton>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Stack marginTop={2}>
|
|
||||||
<Typography variant="subtitle1" paddingY={2}>
|
|
||||||
17 Mei 2022
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
|
||||||
<Stack direction="row" spacing={2}>
|
|
||||||
<Divider orientation="vertical" flexItem sx={{ borderStyle: 'dashed' }} />
|
|
||||||
<Stack spacing={2} sx={{ flex: 1, maxWidth: '100%' }}>
|
|
||||||
{/* Item 1 */}
|
|
||||||
<Card sx={{ paddingY: 2, paddingX: 3 }}>
|
|
||||||
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
|
||||||
<Typography variant="body1">09:10 WIB</Typography>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
backgroundColor: palette.light.warning.lighter,
|
|
||||||
color: palette.light.warning.dark,
|
|
||||||
borderColor: palette.light.warning.dark,
|
|
||||||
border: '1px solid',
|
|
||||||
borderRadius: '6px',
|
|
||||||
padding: 1,
|
|
||||||
}}
|
|
||||||
variant="caption"
|
|
||||||
>
|
|
||||||
Approval
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
|
||||||
<Divider sx={{ marginY: 2 }} />
|
|
||||||
<Stack>
|
|
||||||
<Typography variant="subtitle2" color="#404040">
|
|
||||||
Details : mohon melengkapi kekurangan dokumen
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="caption" color="#757575" sx={{ marginTop: 2, marginBottom: 1 }}>
|
|
||||||
Lab pemeriksaan darah
|
|
||||||
</Typography>
|
|
||||||
<Button
|
|
||||||
variant="outlined"
|
|
||||||
startIcon={<Add />}
|
|
||||||
fullWidth
|
|
||||||
sx={{ typography: 'subtitle2', borderColor: '#F5F5F5' }}
|
|
||||||
// onClick={() => clickHandler('topUpLimit')}
|
|
||||||
>
|
|
||||||
Hasil Pemeriksaan Laboratorium
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
</Card>
|
|
||||||
{/* Item 2 */}
|
|
||||||
<Card sx={{ flex: 1, maxWidth: '100%', paddingY: 2, paddingX: 3 }}>
|
|
||||||
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
|
||||||
<Typography variant="body1">09:00 WIB</Typography>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
backgroundColor: palette.light.warning.lighter,
|
|
||||||
color: palette.light.warning.dark,
|
|
||||||
borderColor: palette.light.warning.dark,
|
|
||||||
border: '1px solid',
|
|
||||||
borderRadius: '6px',
|
|
||||||
padding: 1,
|
|
||||||
}}
|
|
||||||
variant="caption"
|
|
||||||
>
|
|
||||||
Approval
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
|
||||||
<Divider sx={{ marginY: 2 }} />
|
|
||||||
<Stack>
|
|
||||||
<Typography variant="subtitle2" color="#404040">
|
|
||||||
Details : Penilaian Dokter
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
|
||||||
</Card>
|
|
||||||
{/* Item 3 */}
|
|
||||||
<Card sx={{ flex: 1, maxWidth: '100%', paddingY: 2, paddingX: 3 }}>
|
|
||||||
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
|
||||||
<Typography variant="body1">08:00 WIB</Typography>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
backgroundColor: '#F5F5F5',
|
|
||||||
color: '#757575',
|
|
||||||
borderColor: '#757575',
|
|
||||||
border: '1px solid',
|
|
||||||
borderRadius: '6px',
|
|
||||||
padding: 1,
|
|
||||||
}}
|
|
||||||
variant="caption"
|
|
||||||
>
|
|
||||||
Review
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
|
||||||
<Divider sx={{ marginY: 2 }} />
|
|
||||||
<Stack>
|
|
||||||
<Typography variant="subtitle2" color="#404040">
|
|
||||||
Details : Klaim Diajukan
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
|
||||||
</Card>
|
|
||||||
</Stack>
|
|
||||||
</Stack>
|
|
||||||
</>
|
</>
|
||||||
// <MuiDialog
|
|
||||||
// title={title}
|
|
||||||
// openDialog={openDialog}
|
|
||||||
// setOpenDialog={setOpenDialog}
|
|
||||||
// content={getContent()}
|
|
||||||
// />
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// let temp = [
|
||||||
|
// {
|
||||||
|
// member: "",
|
||||||
|
// result_file: [
|
||||||
|
// "file.pdf",
|
||||||
|
// "file2.pdf"
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
|
||||||
export default DialogDetailClaim;
|
export default DialogDetailClaim;
|
||||||
|
|
||||||
|
type ButtonIProp = {
|
||||||
|
row: ClaimSubmission;
|
||||||
|
type: 'invoice' | 'another' | 'lab';
|
||||||
|
handle: (event: any, row: any, type: any) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Buttons = ({ handle, row, type }: ButtonIProp) => {
|
||||||
|
const ref = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ButtonBase sx={{ p: 4 }} onClick={() => ref.current?.click()}>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
placeItems: 'center',
|
||||||
|
gap: 1,
|
||||||
|
placeContent: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Iconify icon="icon-park-outline:upload-one" fontSize="3em" />
|
||||||
|
<Typography variant="body1" fontWeight="bold">
|
||||||
|
Add Invoice
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<input
|
||||||
|
ref={ref}
|
||||||
|
hidden
|
||||||
|
accept="application/pdf"
|
||||||
|
type="file"
|
||||||
|
name="file"
|
||||||
|
multiple
|
||||||
|
onChange={(event) => handle(event, row, type)}
|
||||||
|
/>
|
||||||
|
</ButtonBase>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
@@ -106,7 +106,6 @@ export default function List() {
|
|||||||
handleSearchSubmit: handleSearchSubmit,
|
handleSearchSubmit: handleSearchSubmit,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
/*-------------------------------- handlle checkbox ------------------------ */
|
/*-------------------------------- handlle checkbox ------------------------ */
|
||||||
const handleCheckboxChange = async (event: React.FormEvent<HTMLFormElement>) => {
|
const handleCheckboxChange = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||||
@@ -122,18 +121,11 @@ export default function List() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------- headCell -------------------------------- */
|
/* -------------------------------- headCell -------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack>
|
<Stack>
|
||||||
<CardClaimSubmit
|
<CardClaimSubmit rows={data} loadings={loadings} params={params} searchs={searchs} />
|
||||||
rows={data}
|
|
||||||
loadings={loadings}
|
|
||||||
params={params}
|
|
||||||
searchs={searchs}
|
|
||||||
/>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ import { useSearchParams, useNavigate, Link } from 'react-router-dom';
|
|||||||
import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate';
|
import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate';
|
||||||
import { fSplit } from '../../utils/formatNumber';
|
import { fSplit } from '../../utils/formatNumber';
|
||||||
import { LoadingButton } from '@mui/lab';
|
import { LoadingButton } from '@mui/lab';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { RootState } from '../../store';
|
||||||
|
import { claimSubmitAction, claimSubmitType } from '../../store/claimSubmit';
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -80,6 +83,10 @@ export default function DialogClaimSubmitMember({
|
|||||||
|
|
||||||
/* ---------------------------------- data ---------------------------------- */
|
/* ---------------------------------- data ---------------------------------- */
|
||||||
const [data, setData] = useState([]);
|
const [data, setData] = useState([]);
|
||||||
|
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const selectedData = useSelector((state: RootState) => state.claims.data);
|
||||||
|
|
||||||
const [dataMemberClaim, setDataMemberClaim] = useState<DataContentType>({
|
const [dataMemberClaim, setDataMemberClaim] = useState<DataContentType>({
|
||||||
id: 0,
|
id: 0,
|
||||||
fullName: '',
|
fullName: '',
|
||||||
@@ -108,7 +115,6 @@ export default function DialogClaimSubmitMember({
|
|||||||
};
|
};
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------ Icon On Click ----------------------------- */
|
/* ------------------------------ Icon On Click ----------------------------- */
|
||||||
const clickHandler = ({ id, fullName, memberId, limit, avatar }: DataContentType) => {
|
const clickHandler = ({ id, fullName, memberId, limit, avatar }: DataContentType) => {
|
||||||
setDataMemberClaim({
|
setDataMemberClaim({
|
||||||
@@ -126,6 +132,15 @@ export default function DialogClaimSubmitMember({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCheck = (data: DataContentType, isChecked: boolean) => {
|
||||||
|
if (isChecked) {
|
||||||
|
dispatch(claimSubmitAction.patch([...selectedData, data]));
|
||||||
|
} else {
|
||||||
|
let temp = selectedData.filter((row) => row.memberId !== data.memberId);
|
||||||
|
dispatch(claimSubmitAction.patch(temp));
|
||||||
|
}
|
||||||
|
};
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -140,6 +155,10 @@ export default function DialogClaimSubmitMember({
|
|||||||
})();
|
})();
|
||||||
}, [corporateValue, openDialog, appliedParams]);
|
}, [corporateValue, openDialog, appliedParams]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(claimSubmitAction.dispatch());
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
const getContent = () => (
|
const getContent = () => (
|
||||||
<Stack>
|
<Stack>
|
||||||
<Stack marginTop={2} spacing={1}>
|
<Stack marginTop={2} spacing={1}>
|
||||||
@@ -147,47 +166,54 @@ export default function DialogClaimSubmitMember({
|
|||||||
<Card
|
<Card
|
||||||
key={key}
|
key={key}
|
||||||
sx={{ paddingY: 1, paddingX: 2 }}
|
sx={{ paddingY: 1, paddingX: 2 }}
|
||||||
onClick={() =>
|
// onClick={() =>
|
||||||
clickHandler({
|
// clickHandler({
|
||||||
id: row.id,
|
// id: row.id,
|
||||||
fullName: row.fullName,
|
// fullName: row.fullName,
|
||||||
memberId: row.memberId,
|
// memberId: row.memberId,
|
||||||
limit: {
|
// limit: {
|
||||||
current: row.limit.current,
|
// current: row.limit.current,
|
||||||
total: row.limit.total,
|
// total: row.limit.total,
|
||||||
percentage: row.limit.percentage,
|
// percentage: row.limit.percentage,
|
||||||
},
|
// },
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
>
|
>
|
||||||
<Stack direction="row" alignItems="center" >
|
<Stack direction="row" alignItems="center">
|
||||||
<Grid item xs={1} lg={1} xl={1} >
|
<Grid item xs={1} lg={1} xl={1}>
|
||||||
<form>
|
<form>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
value="end"
|
value="end"
|
||||||
control={<Checkbox />}
|
control={<Checkbox onChange={(e) => handleCheck(row, e.target.checked)} />}
|
||||||
label=""
|
label=""
|
||||||
labelPlacement="end"
|
labelPlacement="end"
|
||||||
sx={{marginLeft: '20px'}}
|
sx={{ marginLeft: '20px' }}
|
||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
</Grid>
|
</Grid>
|
||||||
<div style={{ position: 'relative', flex: 'none', height: 'fit-content', margin: '15px'}}>
|
<div
|
||||||
<img
|
style={{
|
||||||
width={52}
|
position: 'relative',
|
||||||
height={52}
|
flex: 'none',
|
||||||
src="/images/user-profile.png"
|
height: 'fit-content',
|
||||||
alt="user-profile"
|
margin: '15px',
|
||||||
style={{ borderRadius: '50%' }}
|
}}
|
||||||
/>
|
>
|
||||||
</div>
|
<img
|
||||||
<Grid item xs={7} lg={7} xl={7} >
|
width={52}
|
||||||
|
height={52}
|
||||||
|
src="/images/user-profile.png"
|
||||||
|
alt="user-profile"
|
||||||
|
style={{ borderRadius: '50%' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Grid item xs={7} lg={7} xl={7}>
|
||||||
<Typography variant="subtitle1">{row.fullName}</Typography>
|
<Typography variant="subtitle1">{row.fullName}</Typography>
|
||||||
<Typography color="#637381" variant="body2" sx={{ fontWeight: 500 }}>
|
<Typography color="#637381" variant="body2" sx={{ fontWeight: 500 }}>
|
||||||
{row.memberId}
|
{row.memberId}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={3} lg={3} xl={3} >
|
<Grid item xs={3} lg={3} xl={3}>
|
||||||
<BorderLinearProgress
|
<BorderLinearProgress
|
||||||
variant="determinate"
|
variant="determinate"
|
||||||
value={row.limit && row.limit.percentage}
|
value={row.limit && row.limit.percentage}
|
||||||
@@ -196,27 +222,40 @@ export default function DialogClaimSubmitMember({
|
|||||||
/>
|
/>
|
||||||
<Stack direction={'row'}>
|
<Stack direction={'row'}>
|
||||||
<Grid item xs={3}>
|
<Grid item xs={3}>
|
||||||
<Typography variant='overline' sx={{textAlign:'left'}}>
|
<Typography variant="overline" sx={{ textAlign: 'left' }}>
|
||||||
LIMIT
|
LIMIT
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={7} sx={{ display: 'flex', justifyContent: 'flex-end' }}>
|
<Grid item xs={7} sx={{ display: 'flex', justifyContent: 'flex-end' }}>
|
||||||
<Stack direction={'row'}>
|
<Stack direction={'row'}>
|
||||||
<Typography variant='overline'>
|
<Typography variant="overline">
|
||||||
{fSplit(row.limit && row.limit.current)}
|
{fSplit(row.limit && row.limit.current)}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant='overline'>
|
<Typography variant="overline">
|
||||||
/ {fSplit(row.limit && row.limit.total)}
|
/ {fSplit(row.limit && row.limit.total)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={2} lg={2} xl={2} style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
<Grid
|
||||||
<IconButton >
|
item
|
||||||
|
xs={2}
|
||||||
|
lg={2}
|
||||||
|
xl={2}
|
||||||
|
style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}
|
||||||
|
>
|
||||||
|
<IconButton>
|
||||||
<Iconify icon="ic:history" />
|
<Iconify icon="ic:history" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton sx={{marginLeft: '10px'}} onClick={() => navigate(`/claim-request/${row.id}`)} >
|
<IconButton
|
||||||
|
disabled={selectedData.length > 0}
|
||||||
|
sx={{ marginLeft: '10px' }}
|
||||||
|
onClick={() => {
|
||||||
|
dispatch(claimSubmitAction.patch([row]));
|
||||||
|
navigate(`/claim-request/${row.id}`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Iconify icon="ic:round-chevron-right" />
|
<Iconify icon="ic:round-chevron-right" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Grid>
|
</Grid>
|
||||||
@@ -225,7 +264,6 @@ export default function DialogClaimSubmitMember({
|
|||||||
))}
|
))}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -254,13 +292,15 @@ export default function DialogClaimSubmitMember({
|
|||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<LoadingButton
|
<LoadingButton
|
||||||
variant="contained"
|
variant="contained"
|
||||||
sx={{ marginTop: 2, p: 2, margin: '10px', color:'#212B36', backgroundColor:'#DFE3E8' }}
|
// sx={{ marginTop: 2, p: 2, margin: '10px', color: '#212B36', backgroundColor: '#DFE3E8' }}
|
||||||
|
sx={{ marginTop: 2, p: 2, margin: '10px' }}
|
||||||
fullWidth
|
fullWidth
|
||||||
|
disabled={selectedData.length === 0}
|
||||||
|
onClick={() => navigate('/claim-request/bulk')}
|
||||||
>
|
>
|
||||||
Claim Submit Selected
|
Claim Submit Selected
|
||||||
</LoadingButton>
|
</LoadingButton>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
37
frontend/client-portal/src/store/claimSubmit.ts
Normal file
37
frontend/client-portal/src/store/claimSubmit.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { createSlice } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
|
export type claimSubmitType = {
|
||||||
|
id: number;
|
||||||
|
fullName: string;
|
||||||
|
memberId: string;
|
||||||
|
limit: {
|
||||||
|
current: number;
|
||||||
|
total: number;
|
||||||
|
percentage: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type initState = {
|
||||||
|
data: claimSubmitType[];
|
||||||
|
};
|
||||||
|
|
||||||
|
let initState: initState = {
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const claimSubmitSlice = createSlice({
|
||||||
|
name: 'claimsubmit',
|
||||||
|
initialState: initState,
|
||||||
|
reducers: {
|
||||||
|
patch(state, action) {
|
||||||
|
state.data = action.payload;
|
||||||
|
},
|
||||||
|
dispatch(state) {
|
||||||
|
state.data = [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const claimSubmitAction = claimSubmitSlice.actions;
|
||||||
|
|
||||||
|
export default claimSubmitSlice.reducer;
|
||||||
12
frontend/client-portal/src/store/index.ts
Normal file
12
frontend/client-portal/src/store/index.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { configureStore } from '@reduxjs/toolkit';
|
||||||
|
import claimSubmit from './claimSubmit';
|
||||||
|
|
||||||
|
const store = configureStore({
|
||||||
|
reducer: {
|
||||||
|
claims: claimSubmit,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export type RootState = ReturnType<typeof store.getState>;
|
||||||
|
|
||||||
|
export default store;
|
||||||
Reference in New Issue
Block a user