diff --git a/frontend/client-portal/.env.development b/frontend/client-portal/.env.development index 52e237c2..d7d23df0 100644 --- a/frontend/client-portal/.env.development +++ b/frontend/client-portal/.env.development @@ -2,6 +2,6 @@ GENERATE_SOURCEMAP=false 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" diff --git a/frontend/client-portal/package.json b/frontend/client-portal/package.json index 92b2650a..b9acad50 100644 --- a/frontend/client-portal/package.json +++ b/frontend/client-portal/package.json @@ -52,6 +52,7 @@ "@mui/utils": "^5.11.13", "@mui/x-data-grid": "^5.17.26", "@mui/x-date-pickers": "5.0.0-beta.2", + "@reduxjs/toolkit": "^1.9.7", "@vitejs/plugin-react": "^1.3.2", "apexcharts": "^3.37.2", "axios": "^0.27.2", @@ -78,6 +79,7 @@ "react-lazy-load-image-component": "^1.5.6", "react-number-format": "^5.1.4", "react-quill": "2.0.0-beta.4", + "react-redux": "^8.1.3", "react-router": "^6.9.0", "react-router-dom": "^6.9.0", "simplebar": "^5.3.9", diff --git a/frontend/client-portal/pnpm-lock.yaml b/frontend/client-portal/pnpm-lock.yaml index 1df57c98..587278ef 100644 --- a/frontend/client-portal/pnpm-lock.yaml +++ b/frontend/client-portal/pnpm-lock.yaml @@ -47,6 +47,9 @@ dependencies: '@mui/x-date-pickers': 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) + '@reduxjs/toolkit': + specifier: ^1.9.7 + version: 1.9.7(react-redux@8.1.3)(react@17.0.2) '@vitejs/plugin-react': specifier: ^1.3.2 version: 1.3.2 @@ -125,6 +128,9 @@ dependencies: react-quill: specifier: 2.0.0-beta.4 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: specifier: ^6.9.0 version: 6.9.0(react@17.0.2) @@ -2336,6 +2342,25 @@ packages: resolution: {integrity: sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==} 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: resolution: {integrity: sha512-BJ9SxXux8zAg991UmT8slpwpsd31K1dHHbD3Ba4VzD+liLQ4WAMSxQp2d2ZPRPfN0jN2NPRowcSSoM7lCaF08Q==} engines: {node: '>=14'} @@ -2572,6 +2597,13 @@ packages: '@types/range-parser': 1.2.4 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: resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} dev: true @@ -2619,7 +2651,6 @@ packages: resolution: {integrity: sha512-PiYG40pnQRdPHnlf7tZnp0aQ6q9tspYr72vD61saO6zFCybLfMqwUCN0va1/P+86DXn18ZWeW30Bk7xlC5eEAQ==} dependencies: '@types/react': 17.0.53 - dev: true /@types/react-is@17.0.3: resolution: {integrity: sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==} @@ -2668,6 +2699,10 @@ packages: resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==} 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): resolution: {integrity: sha512-ZNW37Ccl3oMZkzxrYDUX4o7cnuPgU+YrcaYXzsRtLB16I1FR5SHMqga3zGsaSliZADCWo2v8qHWqAYIj8nWCCg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4467,6 +4502,10 @@ packages: engines: {node: '>= 4'} dev: true + /immer@9.0.21: + resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} + dev: false + /import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -5341,6 +5380,40 @@ packages: react-dom: 17.0.2(react@17.0.2) 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: resolution: {integrity: sha512-XP8A9BT0CpRBD+NYLLeIhld/RqG9+gktUjW1FkE+Vm7OCinbG1SshcK5tb9ls4kzvjZr9mOQc7HYgBngEyPAXg==} engines: {node: '>=0.10.0'} @@ -5391,6 +5464,20 @@ packages: object-assign: 4.1.1 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: resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==} engines: {node: '>=4'} @@ -5447,6 +5534,10 @@ packages: resolution: {integrity: sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==} dev: false + /reselect@4.1.8: + resolution: {integrity: sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==} + dev: false + /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -6009,6 +6100,14 @@ packages: punycode: 2.3.0 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): resolution: {integrity: sha512-pSiFHmnJGMQJJL8aJzQ8SaraZBSBPMGvGUkCNzheIq9UQCEk/eP3UmANNmS9eupuhIpTK8AdxTOHcaMcAqAbCA==} peerDependencies: diff --git a/frontend/client-portal/src/App.tsx b/frontend/client-portal/src/App.tsx index 8ff04cf4..38581096 100644 --- a/frontend/client-portal/src/App.tsx +++ b/frontend/client-portal/src/App.tsx @@ -9,27 +9,31 @@ import { ProgressBarStyle } from './components/ProgressBar'; import ThemeColorPresets from './components/ThemeColorPresets'; import MotionLazyContainer from './components/animate/MotionLazyContainer'; import { SnackbarProvider } from 'notistack'; +import { Provider } from 'react-redux'; +import store from './store'; // ---------------------------------------------------------------------- export default function App() { return ( - - - - - - - {/* */} - - - - - - - + + + + + + + + {/* */} + + + + + + + + ); } diff --git a/frontend/client-portal/src/pages/ClaimSubmit/DialogDetailClaim.tsx b/frontend/client-portal/src/pages/ClaimSubmit/DialogDetailClaim.tsx index ace7af39..0f0536bc 100644 --- a/frontend/client-portal/src/pages/ClaimSubmit/DialogDetailClaim.tsx +++ b/frontend/client-portal/src/pages/ClaimSubmit/DialogDetailClaim.tsx @@ -14,6 +14,7 @@ import { Stack, Grid, Avatar, + ButtonBase, } from '@mui/material'; import { Add } from '@mui/icons-material'; // components @@ -23,10 +24,17 @@ import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos'; // theme import palette from '../../theme/palette'; // React -import { ReactElement, useRef, useState } from 'react'; +import { Fragment, ReactElement, useEffect, useRef, useState } from 'react'; import { useSearchParams, useNavigate, Link } from 'react-router-dom'; import { fPostFormat } from '../../utils/formatTime'; 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 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 = { title?: { name?: string; @@ -69,188 +95,435 @@ const BorderLinearProgress = styled(LinearProgress)(({ theme }) => ({ })); /* -------------------------------------------------------------------------- */ - const steps = ['Review', 'Approval', 'Disbursement']; const DialogDetailClaim = ({ title, openDialog, setOpenDialog, data }: MuiDialogProps) => { - function clickHandler(arg0: string) { - throw new Error('Function not implemented.'); - } - 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([]); - // ); + 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 ( <> - + {/* Field 1 */} - navigate(`/corporate`)} sx={{ cursor: "pointer" }} /> - Claim Submission - Submission Date - + navigate(`/claim-submit`)} + sx={{ cursor: 'pointer' }} + /> + + Claim Submission{' '} + + + Submission Date{' '} + + {fPostFormat(new Date(), 'dd MMM yyyy')} - - - - - - - - - - - - {'Alexandra Rhea Putranto'} - {'KM002-01'} - - - - Total Limit - - - - {fCurrency(8000000)} / {fCurrency(100000)} - - - - - + {dataContent.map((row, index) => { + return ( + + + + + + + + + + + + + + + {row.personName} + + {row.personID} + + + + + Total Limit + + + + {fCurrency(8000000)} / {fCurrency(100000)} + + + + + + {/* REAL INVOICE */} + + + + Real Invoice + + {row.fileRealInvoice && + row.fileRealInvoice.map((file, fileIndex) => ( + + + {file.name} + { + handleRemoveFile(row, 'invoice', fileIndex); + }} + /> + + + ))} + + + + + + + + + {/* DOCTOR'S PRESCRIPTION AND ANOTHER DOCUMENTS */} + + + + + Doctor's Prescription and Another Documents + + + {row.anotherDocument && + row.anotherDocument.map((file, fileIndex) => ( + + + {file.name} + { + handleRemoveFile(row, 'another', fileIndex); + }} + /> + + + ))} + + + + + + + + + {/* LABORATORY RESULTS */} + + + + Laboraroty Results + + {row.laboratoryResult && + row.laboratoryResult.map((file, fileIndex) => ( + + + {file.name} + { + handleRemoveFile(row, 'lab', fileIndex); + }} + /> + + + ))} + + + + + + + + + + + ); + })} + + + Claim Submit + + - - - 17 Mei 2022 - - - - - - {/* Item 1 */} - - - 09:10 WIB - - Approval - - - - - - Details : mohon melengkapi kekurangan dokumen - - - Lab pemeriksaan darah - - - - - {/* Item 2 */} - - - 09:00 WIB - - Approval - - - - - - Details : Penilaian Dokter - - - - {/* Item 3 */} - - - 08:00 WIB - - Review - - - - - - Details : Klaim Diajukan - - - - - - // ); }; +// let temp = [ +// { +// member: "", +// result_file: [ +// "file.pdf", +// "file2.pdf" +// ] +// } +// ] + 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(null); + + return ( + ref.current?.click()}> + + + + Add Invoice + + + handle(event, row, type)} + /> + + ); +}; diff --git a/frontend/client-portal/src/pages/ClaimSubmit/List.tsx b/frontend/client-portal/src/pages/ClaimSubmit/List.tsx index 5685cea5..620ec685 100644 --- a/frontend/client-portal/src/pages/ClaimSubmit/List.tsx +++ b/frontend/client-portal/src/pages/ClaimSubmit/List.tsx @@ -106,7 +106,6 @@ export default function List() { handleSearchSubmit: handleSearchSubmit, }; - /* ------------------------------------------------------------------------- */ /*-------------------------------- handlle checkbox ------------------------ */ const handleCheckboxChange = async (event: React.FormEvent) => { @@ -122,18 +121,11 @@ export default function List() { } }; - /* -------------------------------- headCell -------------------------------- */ - return ( - + ); } diff --git a/frontend/client-portal/src/sections/claim-submit/DialogClaimSubmitMember.tsx b/frontend/client-portal/src/sections/claim-submit/DialogClaimSubmitMember.tsx index 668310ec..d69969e4 100644 --- a/frontend/client-portal/src/sections/claim-submit/DialogClaimSubmitMember.tsx +++ b/frontend/client-portal/src/sections/claim-submit/DialogClaimSubmitMember.tsx @@ -26,6 +26,9 @@ import { useSearchParams, useNavigate, Link } from 'react-router-dom'; import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate'; import { fSplit } from '../../utils/formatNumber'; 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 ---------------------------------- */ const [data, setData] = useState([]); + + const dispatch = useDispatch(); + const selectedData = useSelector((state: RootState) => state.claims.data); + const [dataMemberClaim, setDataMemberClaim] = useState({ id: 0, fullName: '', @@ -108,7 +115,6 @@ export default function DialogClaimSubmitMember({ }; /* -------------------------------------------------------------------------- */ - /* ------------------------------ Icon On Click ----------------------------- */ const clickHandler = ({ id, fullName, memberId, limit, avatar }: DataContentType) => { 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(() => { @@ -140,6 +155,10 @@ export default function DialogClaimSubmitMember({ })(); }, [corporateValue, openDialog, appliedParams]); + useEffect(() => { + dispatch(claimSubmitAction.dispatch()); + }, [dispatch]); + const getContent = () => ( @@ -147,47 +166,54 @@ export default function DialogClaimSubmitMember({ - clickHandler({ - id: row.id, - fullName: row.fullName, - memberId: row.memberId, - limit: { - current: row.limit.current, - total: row.limit.total, - percentage: row.limit.percentage, - }, - }) - } + // onClick={() => + // clickHandler({ + // id: row.id, + // fullName: row.fullName, + // memberId: row.memberId, + // limit: { + // current: row.limit.current, + // total: row.limit.total, + // percentage: row.limit.percentage, + // }, + // }) + // } > - - + +
} + control={ handleCheck(row, e.target.checked)} />} label="" labelPlacement="end" - sx={{marginLeft: '20px'}} + sx={{ marginLeft: '20px' }} />
-
- user-profile -
- +
+ user-profile +
+ {row.fullName} {row.memberId} - + - + LIMIT - - {fSplit(row.limit && row.limit.current)} + + {fSplit(row.limit && row.limit.current)} - - / {fSplit(row.limit && row.limit.total)} + + / {fSplit(row.limit && row.limit.total)} - - + + - navigate(`/claim-request/${row.id}`)} > + 0} + sx={{ marginLeft: '10px' }} + onClick={() => { + dispatch(claimSubmitAction.patch([row])); + navigate(`/claim-request/${row.id}`); + }} + > @@ -225,7 +264,6 @@ export default function DialogClaimSubmitMember({ ))}
- ); return ( @@ -254,13 +292,15 @@ export default function DialogClaimSubmitMember({ navigate('/claim-request/bulk')} > Claim Submit Selected
- ) + ); } diff --git a/frontend/client-portal/src/store/claimSubmit.ts b/frontend/client-portal/src/store/claimSubmit.ts new file mode 100644 index 00000000..8b0c522d --- /dev/null +++ b/frontend/client-portal/src/store/claimSubmit.ts @@ -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; diff --git a/frontend/client-portal/src/store/index.ts b/frontend/client-portal/src/store/index.ts new file mode 100644 index 00000000..4b863f89 --- /dev/null +++ b/frontend/client-portal/src/store/index.ts @@ -0,0 +1,12 @@ +import { configureStore } from '@reduxjs/toolkit'; +import claimSubmit from './claimSubmit'; + +const store = configureStore({ + reducer: { + claims: claimSubmit, + }, +}); + +export type RootState = ReturnType; + +export default store;