Merge remote-tracking branch 'origin/staging' into origin/production

This commit is contained in:
Linksehat Staging Server
2023-09-04 15:07:09 +07:00
206 changed files with 29759 additions and 24113 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -64,6 +64,7 @@
"notistack": "^3.0.1",
"nprogress": "^0.2.0",
"numeral": "^2.0.6",
"pnpm": "^8.6.9",
"pusher-js": "^8.0.2",
"react": "^17.0.2",
"react-apexcharts": "^1.4.0",

View File

@@ -38,6 +38,10 @@ import {
const steps = ['Review', 'Approval', 'Disbursement'];
const DialogDetailClaim = ({ title, openDialog, setOpenDialog, data }: MuiDialogProps) => {
function clickHandler(arg0: string) {
throw new Error('Function not implemented.');
}
// const getContent = () => (
// );
@@ -108,6 +112,7 @@ import {
fullWidth
sx={{ typography: 'subtitle2', borderColor: '#F5F5F5' }}
>
onClick={() => clickHandler('topUpLimit')}
Hasil Pemeriksaan Laboratorium
</Button>
</Stack>

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,6 @@ GENERATE_SOURCEMAP=false
PORT=8083
REACT_APP_HOST_API_URL="http://127.0.0.1:8000"
REACT_APP_HOST_API_URL="http://lms.test"
VITE_API_URL="http://127.0.0.1:8000/api/internal"

File diff suppressed because it is too large Load Diff

View File

@@ -39,79 +39,80 @@
},
"dependencies": {
"@ajoelp/json-to-formdata": "^1.5.0",
"@date-io/date-fns": "^2.16.0",
"@emotion/cache": "^11.10.5",
"@emotion/react": "^11.10.5",
"@emotion/styled": "^11.10.5",
"@hookform/resolvers": "^2.9.10",
"@date-io/date-fns": "^2.17.0",
"@emotion/cache": "^11.11.0",
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@hookform/resolvers": "^2.9.11",
"@iconify/react": "^3.2.2",
"@mui/icons-material": "^5.11.0",
"@mui/icons-material": "^5.14.6",
"@mui/lab": "5.0.0-alpha.80",
"@mui/material": "^5.11.5",
"@mui/system": "^5.11.5",
"@mui/x-data-grid": "^5.17.19",
"@mui/material": "^5.14.6",
"@mui/system": "^5.14.6",
"@mui/x-data-grid": "^5.17.26",
"@mui/x-date-pickers": "5.0.0-beta.2",
"@vitejs/plugin-react": "^1.3.2",
"apexcharts": "^3.36.3",
"apexcharts": "^3.42.0",
"axios": "^0.27.2",
"change-case": "^4.1.2",
"csstype": "^3.1.1",
"date-fns": "^2.29.3",
"esbuild": "^0.17.18",
"csstype": "^3.1.2",
"date-fns": "^2.30.0",
"esbuild": "^0.17.19",
"framer-motion": "^6.5.1",
"highlight.js": "^11.7.0",
"highlight.js": "^11.8.0",
"history": "^5.3.0",
"jsx-runtime": "^1.2.0",
"lodash": "^4.17.21",
"notistack": "3.0.0-alpha.11",
"nprogress": "^0.2.0",
"numeral": "^2.0.6",
"pnpm": "^8.6.12",
"react": "^17.0.2",
"react-apexcharts": "^1.4.0",
"react-apexcharts": "^1.4.1",
"react-dom": "^17.0.2",
"react-dropzone": "^14.2.3",
"react-helmet-async": "^1.3.0",
"react-hook-form": "^7.42.1",
"react-hook-form": "^7.45.4",
"react-intersection-observer": "^8.34.0",
"react-lazy-load-image-component": "^1.5.6",
"react-lazy-load-image-component": "^1.6.0",
"react-quill": "2.0.0-beta.4",
"react-router": "^6.7.0",
"react-router-dom": "^6.7.0",
"react-router": "^6.15.0",
"react-router-dom": "^6.15.0",
"simplebar": "^5.3.9",
"simplebar-react": "^2.4.3",
"stylis": "^4.1.3",
"stylis": "^4.3.0",
"stylis-plugin-rtl": "^2.1.1",
"vite": "^3.2.5",
"vite": "^3.2.7",
"vite-plugin-svgr": "^2.4.0",
"yup": "^0.32.11"
},
"devDependencies": {
"@babel/core": "^7.20.12",
"@babel/eslint-parser": "^7.19.1",
"@babel/plugin-syntax-flow": "^7.18.6",
"@babel/plugin-transform-react-jsx": "^7.20.7",
"@types/lodash": "^4.14.191",
"@babel/core": "^7.22.11",
"@babel/eslint-parser": "^7.22.11",
"@babel/plugin-syntax-flow": "^7.22.5",
"@babel/plugin-transform-react-jsx": "^7.22.5",
"@types/lodash": "^4.14.197",
"@types/nprogress": "^0.2.0",
"@types/react": "^17.0.53",
"@types/react-dom": "^17.0.18",
"@types/react-lazy-load-image-component": "^1.5.2",
"@types/stylis": "^4.0.2",
"@typescript-eslint/eslint-plugin": "^5.48.2",
"@typescript-eslint/parser": "^5.48.2",
"eslint": "^8.32.0",
"@types/react": "^17.0.65",
"@types/react-dom": "^17.0.20",
"@types/react-lazy-load-image-component": "^1.5.3",
"@types/stylis": "^4.2.0",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"eslint": "^8.48.0",
"eslint-config-airbnb": "19.0.4",
"eslint-config-airbnb-typescript": "^16.2.0",
"eslint-config-prettier": "^8.6.0",
"eslint-config-prettier": "^8.10.0",
"eslint-config-react-app": "7.0.0",
"eslint-import-resolver-typescript": "^2.7.1",
"eslint-plugin-flowtype": "^8.0.3",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-jsx-a11y": "6.5.1",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.32.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "4.3.0",
"prettier": "^2.8.3",
"typescript": "^4.9.4",
"prettier": "^2.8.8",
"typescript": "^4.9.5",
"vite-plugin-pwa": "^0.12.8"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -60,8 +60,8 @@ export default function RHFDatepicker({ name, ...other }: IProps & TextFieldProp
<DesktopDatePicker
value={field.value}
// inputFormat="dd/MM/yyyy"
inputFormat="yyyy-MM-dd"
inputFormat="dd/MMM/yyyy"
// inputFormat="dd - MMM - yyyy"
onChange={(value) => {
field.onChange(value);
}}

View File

@@ -86,6 +86,8 @@ const navConfig = [
{ title: 'Live Chat', path: '/report/live-chat' },
{ title: 'Linksehat Payment', path: '/report/linksehat-payments' },
{ title: 'Prescription', path: '/report/prescription' },
{ title: 'Doctor Rating', path: '/report/doctorrating' },
],
},
{

View File

@@ -69,7 +69,7 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop
enqueueSnackbar('Division created successfully', { variant: 'success' });
})
.then((res) => {
navigate('/corporates/' + corporate_id + '/divisions', { replace: true });
navigate('/corporate/' + corporate_id + '/divisions', { replace: true });
})
.catch(({ response }) => {
if (response.status === 422) {
@@ -89,7 +89,7 @@ export default function CorporatePlanForm({ isEdit, currentCorporatePlan }: Prop
enqueueSnackbar('Division updated successfully', { variant: 'success' });
})
.then((res) => {
navigate('/corporates/' + corporate_id + '/divisions/' , { replace: true });
navigate('/corporate/' + corporate_id + '/divisions/' , { replace: true });
})
.catch(({ response }) => {
enqueueSnackbar('Update Failed : '+ response.data.message, { variant: 'error' });

View File

@@ -62,7 +62,6 @@ type Props = {
};
export default function CorporateForm({ isEdit, currentCorporate }: Props) {
const navigate = useNavigate();
const [corporate_groups, setCorporateGroups] = useState([]);
@@ -70,7 +69,7 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
const { enqueueSnackbar } = useSnackbar();
let NewCorporateSchema = null;
if (isEdit){
if (isEdit) {
NewCorporateSchema = Yup.object().shape({
isEdited: Yup.boolean(),
name: Yup.string().required('Name is required'),
@@ -81,36 +80,36 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
help_text: Yup.string().required('Help Text is required'),
// policy_code: Yup.string().required('Policy Code is required'),
policy_start: Yup.date().required('Start Date is required'),
policy_end: Yup.date().required('End Date is required').min(Yup.ref('policy_start'), "end date can't be before start date"),
policy_end: Yup.date()
.required('End Date is required')
.min(Yup.ref('policy_start'), "end date can't be before start date"),
policy_total_premi: Yup.number().required('Deposit Initial Fund is required').min(0),
// linking_rules: Yup.string().required('Link Rules is required'),
policy_minimal_deposit_percentage:
Yup.number()
.typeError("Please enter a valid number")
.required('Percentage Deposit is required')
.min(0, "Minimum atleast 0")
.max(100, "Allowed maximum is 100"),
policy_minimal_alert_percentage:
Yup.number()
.typeError("Please enter a valid number")
.required('Percentage Alert is required')
.min(0, "Minimum atleast 0")
.max(100, "Allowed maximum is 100"),
policy_stop_service_percentage:
Yup.number()
.typeError("Please enter a valid number")
.min(0, "Minimum atleast 0")
.required('Percentage Stop is required')
.test("max", "Total should not exceed 100 %", function(value) {
const { policy_minimal_alert_percentage } = this.parent;
const { policy_minimal_deposit_percentage } = this.parent;
return value == 100 - policy_minimal_alert_percentage- policy_minimal_deposit_percentage;
}),
policy_minimal_deposit_percentage: Yup.number()
.typeError('Please enter a valid number')
.required('Percentage Deposit is required')
.min(0, 'Minimum atleast 0')
.max(100, 'Allowed maximum is 100'),
policy_minimal_alert_percentage: Yup.number()
.typeError('Please enter a valid number')
.required('Percentage Alert is required')
.min(0, 'Minimum atleast 0')
.max(100, 'Allowed maximum is 100'),
policy_stop_service_percentage: Yup.number()
.typeError('Please enter a valid number')
.min(0, 'Minimum atleast 0')
.max(100, 'Allowed maximum is 100')
.required('Percentage Stop is required'),
// .test('max', 'Total should not exceed 100 %', function (value) {
// const { policy_minimal_alert_percentage } = this.parent;
// const { policy_minimal_deposit_percentage } = this.parent;
// return value == 100 - policy_minimal_alert_percentage - policy_minimal_deposit_percentage;
// }),
parent_id: Yup.string().when('type', {
is: 'subcorporate',
then: Yup.string().required('Corporate is required because type is Sub Corporate'),
}),
reason: Yup.string().required('Reason for update is required when editing data'),
});
} else {
@@ -118,108 +117,105 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
NewCorporateSchema = Yup.object().shape({
isEdited: Yup.boolean(),
name: Yup.string().required('Name is required'),
code: Yup.string().required('Corporate Code is required').test(
'unique-code',
'Code must be unique',
async function (value) {
code: Yup.string()
.required('Corporate Code is required')
.test('unique-code', 'Code must be unique', async function (value) {
const existingCodes = await getExistingCodes();
return !existingCodes.includes(value);
}
),
}),
active: Yup.boolean().required('Corporate Status is required'),
type: Yup.string().required('Type is required'),
welcome_message: Yup.string().required('Welcome Message is required'),
help_text: Yup.string().required('Help Text is required'),
// policy_code: Yup.string().required('Policy Code is required'),
policy_start: Yup.date().required('Start Date is required'),
policy_end: Yup.date().required('End Date is required').min(Yup.ref('policy_start'), "end date can't be before start date"),
policy_end: Yup.date()
.required('End Date is required')
.min(Yup.ref('policy_start'), "end date can't be before start date"),
policy_total_premi: Yup.number().required('Deposit Initial Fund is required').min(0),
// linking_rules: Yup.string().required('Link Rules is required'),
policy_minimal_deposit_percentage:
Yup.number()
.typeError("Please enter a valid number")
.required('Percentage Deposit is required')
.min(0, "Minimum atleast 0")
.max(100, "Allowed maximum is 100"),
policy_minimal_alert_percentage:
Yup.number()
.typeError("Please enter a valid number")
.required('Percentage Alert is required')
.min(0, "Minimum atleast 0")
.max(100, "Allowed maximum is 100"),
policy_stop_service_percentage:
Yup.number()
.typeError("Please enter a valid number")
.min(0, "Minimum atleast 0")
.required('Percentage Stop is required')
.test("max", "Total should not exceed 100 %", function(value) {
const { policy_minimal_alert_percentage } = this.parent;
const { policy_minimal_deposit_percentage } = this.parent;
return value == 100 - policy_minimal_alert_percentage- policy_minimal_deposit_percentage;
}),
policy_minimal_deposit_percentage: Yup.number()
.typeError('Please enter a valid number')
.required('Percentage Deposit is required')
.min(0, 'Minimum atleast 0')
.max(100, 'Allowed maximum is 100'),
policy_minimal_alert_percentage: Yup.number()
.typeError('Please enter a valid number')
.required('Percentage Alert is required')
.min(0, 'Minimum atleast 0')
.max(100, 'Allowed maximum is 100'),
policy_stop_service_percentage: Yup.number()
.typeError('Please enter a valid number')
.min(0, 'Minimum atleast 0')
.max(100, 'Allowed maximum is 100')
.required('Percentage Stop is required'),
// .test('max', 'Total should not exceed 100 %', function (value) {
// const { policy_minimal_alert_percentage } = this.parent;
// const { policy_minimal_deposit_percentage } = this.parent;
// return value == 100 - policy_minimal_alert_percentage - policy_minimal_deposit_percentage;
// }),
parent_id: Yup.string().when('type', {
is: 'subcorporate',
then: Yup.string().required('Corporate is required because type is Sub Corporate'),
}),
});
}
async function getExistingCodes() {
// axios
// .get('/corporates/create')
// .then((res) => {
// setCorporateGroups(res.data.corporate_groups);
// })
// .catch((err) => {
// enqueueSnackbar('Opps, failed to get Corporate Group List', { variant: 'error' });
// });
// .get('/corporates/create')
// .then((res) => {
// setCorporateGroups(res.data.corporate_groups);
// })
// .catch((err) => {
// enqueueSnackbar('Opps, failed to get Corporate Group List', { variant: 'error' });
// });
try {
let response = await axios.get('/corporates/1/code'); // get data all corporate
let codeCurrent = ""
if (isEdit){
let responseCodeCurrent = await axios.get(`/corporates/${currentCorporate?.id}/edit`); // get data current corporate
codeCurrent = responseCodeCurrent.data.code; // get data code corporate current
}
// console.log(response.data);
let existingCodes = response.data.map(item => item); // get data code corporate all
let filteredArray = existingCodes.filter(e => e != codeCurrent)
return filteredArray;
} catch (error) {
console.error(error);
enqueueSnackbar('Failed to fetch existing codes', { variant: 'error' });
try {
let response = await axios.get('/corporates/1/code'); // get data all corporate
let codeCurrent = '';
if (isEdit) {
let responseCodeCurrent = await axios.get(`/corporates/${currentCorporate?.id}/edit`); // get data current corporate
codeCurrent = responseCodeCurrent.data.code; // get data code corporate current
}
// console.log(response.data);
let existingCodes = response.data.map((item) => item); // get data code corporate all
let filteredArray = existingCodes.filter((e) => e != codeCurrent);
return filteredArray;
} catch (error) {
console.error(error);
enqueueSnackbar('Failed to fetch existing codes', { variant: 'error' });
}
}
async function getExistingPayorId() {
// axios
// .get('/corporates/create')
// .then((res) => {
// setCorporateGroups(res.data.corporate_groups);
// })
// .catch((err) => {
// enqueueSnackbar('Opps, failed to get Corporate Group List', { variant: 'error' });
// });
// .get('/corporates/create')
// .then((res) => {
// setCorporateGroups(res.data.corporate_groups);
// })
// .catch((err) => {
// enqueueSnackbar('Opps, failed to get Corporate Group List', { variant: 'error' });
// });
try {
let response = await axios.get('/corporates/1/code'); // get data all corporate
let codeCurrent = ""
if (isEdit){
let responseCodeCurrent = await axios.get(`/corporates/${currentCorporate?.id}/edit`); // get data current corporate
codeCurrent = responseCodeCurrent.data.payor_id; // get data code corporate current
}
// console.log(response.data);
let existingCodes = response.data.map(item => item); // get data code corporate all
let filteredArray = existingCodes.filter(e => e != codeCurrent)
console.log(filteredArray);
return filteredArray;
} catch (error) {
console.error(error);
enqueueSnackbar('Failed to fetch existing codes', { variant: 'error' });
try {
let response = await axios.get('/corporates/1/code'); // get data all corporate
let codeCurrent = '';
if (isEdit) {
let responseCodeCurrent = await axios.get(`/corporates/${currentCorporate?.id}/edit`); // get data current corporate
codeCurrent = responseCodeCurrent.data.payor_id; // get data code corporate current
}
// console.log(response.data);
let existingCodes = response.data.map((item) => item); // get data code corporate all
let filteredArray = existingCodes.filter((e) => e != codeCurrent);
console.log(filteredArray);
return filteredArray;
} catch (error) {
console.error(error);
enqueueSnackbar('Failed to fetch existing codes', { variant: 'error' });
}
}
const defaultValues = useMemo(
@@ -323,7 +319,6 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
formData.append('policy_end', fPostFormat(data.policy_end));
formData.append('linking_rules', data.linking_rules);
// console.log('MOTHERFUCKER', data.linking_rules)
if (!isEdit) {
@@ -479,7 +474,7 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
id: 'Lilili',
},
];
const [isDisabled, setIsDisabled] = useState(isEdit);
const [isDisabled, setIsDisabled] = useState(isEdit);
const handleTypeChange = (event: SelectChangeEvent) => {
setValue('type', event.target.value);
};
@@ -520,19 +515,16 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
</option>
))}
</RHFSelect>
)}
)}
<RHFTextField name="code" label="Corporate Code" disabled={isDisabled} />
<RHFTextField name="name" label="Corporate Name" disabled={isDisabled} />
<RHFTextField name="payor_id" label="Payor ID" disabled={isDisabled} />
{isEdit && (
// <RHFTextField name="reason" label="Reason for update" />
<RHFSelect
name="reason"
label="Reason for update"
>
<RHFSelect name="reason" label="Reason for update">
<option value=""></option>
<option value="Agreement changed">Agreement changed</option>
<option value="Endorsement">Endorsement</option>
@@ -575,13 +567,10 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
<Grid item xs={12} md={4}>
<Stack spacing={3}>
<Card sx={{ p: 3 }}>
{JSON.stringify(values.active)}
<RHFSwitch name="active" label="Is Company Active" />
{JSON.stringify(values.automatic_linking)}
<RHFSwitch name="automatic_linking" label="Is Company Automatic Linking" />
<Stack spacing={3} mt={2} alignItems="center">
<Typography align="center">Company Logo</Typography>
{/* <RHFUploadAvatar
<Stack spacing={3} mt={2}>
<Stack spacing={3} alignItems="center">
<Typography align="center">Company Logo</Typography>
{/* <RHFUploadAvatar
name="logo"
showPreview
accept="image/*"
@@ -589,7 +578,22 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
onDrop={handleDrop}
onRemove={handleRemove}
/> */}
<UploadImage setFile={setFile} currentImage={currentImage} />
<UploadImage setFile={setFile} currentImage={currentImage} />
</Stack>
<Box>
<Box
sx={{ display: 'flex', placeContent: 'space-between', placeItems: 'center' }}
>
<Typography>Company Active</Typography>
<RHFSwitch name="active" label="" labelPlacement="start" />
</Box>
<Box
sx={{ display: 'flex', placeContent: 'space-between', placeItems: 'center' }}
>
<Typography>Company Automatic Linking</Typography>
<RHFSwitch name="automatic_linking" label="" labelPlacement="start" />
</Box>
</Box>
</Stack>
</Card>
<Card sx={{ p: 3 }}>
@@ -598,7 +602,6 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
Linking Rules
</Typography>
<Stack>
{JSON.stringify(getValues('linking_rules'))}
<RHFCustomMultiCheckbox name="linking_rules" options={linking_tools} />
</Stack>
</Stack>
@@ -611,14 +614,12 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
{/* <Card sx={{ p:3, mb:3, background: 'gray', color: 'white' }}><Typography>Policy Detail</Typography></Card> */}
<Card sx={{ p: 3 }}>
<Stack spacing={3} mt={2}>
<Grid item xs={12}>
<Typography variant="h5">Policy Detail</Typography>
</Grid>
<Typography variant="h5">Policy Detail</Typography>
<input type="hidden" name="policy_id" />
<Stack spacing={1}>
<RHFTextField name="policy_code" label="Policy Number"/>
<RHFTextField name="policy_code" label="Policy Number" />
{!currentCorporate?.id && (
<Typography variant="caption">Will be generated if empty</Typography>
)}
@@ -627,10 +628,10 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
{/* <Typography>Minimal Deposit Policy Level</Typography> */}
<Stack direction="row" spacing={2}>
<Grid item xs={12} md={6}>
<RHFDatepicker name="policy_start" label="Start Date (YYYY-MM-DD)" />
<RHFDatepicker name="policy_start" label="Start Date" />
</Grid>
<Grid item xs={12} md={6}>
<RHFDatepicker name="policy_end" label="End Date (YYYY-MM-DD)" />
<RHFDatepicker name="policy_end" label="End Date" />
</Grid>
</Stack>
@@ -639,11 +640,13 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
label={'Deposit Intial Fund (' + fCurrency(values.policy_total_premi) + ')'}
/>
<Stack spacing={1}>
<Typography variant="subtitle2" sx={{ color: 'text.secondary' }}>
Minimal Deposit Policy Level
</Typography>
<Grid container>
<Grid item xs={12}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Typography variant="subtitle2" sx={{ color: 'text.secondary' }}>
Minimal Deposit Policy Level
</Typography>
</Grid>
<Grid item xs={12} md={3}>
<RHFTextField
name="policy_minimal_deposit_percentage"
@@ -659,13 +662,15 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
/>
</Grid>
</Grid>
</Stack>
</Grid>
<Stack spacing={1}>
<Typography variant="subtitle2" sx={{ color: 'text.secondary' }}>
Minimal Alert Level
</Typography>
<Grid container>
<Grid item xs={12}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Typography variant="subtitle2" sx={{ color: 'text.secondary' }}>
Minimal Alert Level
</Typography>
</Grid>
<Grid item xs={12} md={3}>
<RHFTextField
name="policy_minimal_alert_percentage"
@@ -681,13 +686,15 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
/>
</Grid>
</Grid>
</Stack>
</Grid>
<Stack spacing={1}>
<Typography variant="subtitle2" sx={{ color: 'text.secondary' }}>
Stop Service Level
</Typography>
<Grid container>
<Grid item xs={12}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Typography variant="subtitle2" sx={{ color: 'text.secondary' }}>
Stop Service Level
</Typography>
</Grid>
<Grid item xs={12} md={3}>
<RHFTextField
name="policy_stop_service_percentage"
@@ -703,7 +710,7 @@ export default function CorporateForm({ isEdit, currentCorporate }: Props) {
/>
</Grid>
</Grid>
</Stack>
</Grid>
</Stack>
</Card>
</Grid>

View File

@@ -46,6 +46,7 @@ import HeaderBreadcrumbs from '../../components/HeaderBreadcrumbs';
import BasePagination from '../../components/BasePagination';
import { fCurrency } from '../../utils/formatNumber';
import { enqueueSnackbar } from 'notistack';
import { fDate } from '@/utils/formatTime';
export default function Corporates() {
const { themeStretch } = useSettings();
@@ -341,7 +342,7 @@ export default function Corporates() {
</Button>
</Link>
<Link to={`/corporate/${row.id}/corporate-history`}>
<HistoryIcon />
<HistoryIcon />
</Link>
</Stack>
</TableCell>
@@ -379,36 +380,67 @@ export default function Corporates() {
</Grid>
<Grid item xs={6}>
<Grid Grid container>
<Grid container>
<Grid item xs={6}>
Period
</Grid>
<Grid item xs={6}>
: {row.current_policy?.start} - {row.current_policy?.end}
<Box sx={{ display: 'flex', placeContent: 'space-between' }}>
<span>: {fDate(row.current_policy?.start)}</span>-
<span>{fDate(row.current_policy?.end)}</span>
</Box>
</Grid>
<Grid item xs={6}>
Total Premi
</Grid>
<Grid item xs={6}>
: {row.current_policy ? fCurrency(row.current_policy?.total_premi) : '-'}
{row.current_policy ? (
<Box sx={{ display: 'flex', placeContent: 'space-between' }}>
<span>
: {fCurrency(row.current_policy?.total_premi).split(' ')[0]}
</span>
<span>{fCurrency(row.current_policy?.total_premi).split(' ')[1]}</span>
</Box>
) : (
'-'
)}
</Grid>
<Grid item xs={6}>
Minimal Deposit
</Grid>
<Grid item xs={6}>
:{' '}
{row.current_policy
? fCurrency(row.current_policy?.minimal_deposit_net)
: '-'}
{row.current_policy ? (
<Box sx={{ display: 'flex', placeContent: 'space-between' }}>
<span>
: {fCurrency(row.current_policy?.minimal_deposit_net).split(' ')[0]}
</span>
<span>
{fCurrency(row.current_policy?.minimal_deposit_net).split(' ')[1]}
</span>
</Box>
) : (
'-'
)}
</Grid>
<Grid item xs={6}>
Corporate Limit
</Grid>
<Grid item xs={6}>
: {row.current_policy ? fCurrency(row.current_policy?.limit_balance) : '-'}
{row.current_policy ? (
<Box sx={{ display: 'flex', placeContent: 'space-between' }}>
<span>
: {fCurrency(row.current_policy?.limit_balance).split(' ')[0]}
</span>
<span>
{fCurrency(row.current_policy?.limit_balance).split(' ')[1]}
</span>
</Box>
) : (
'-'
)}
</Grid>
</Grid>
</Grid>

View File

@@ -560,6 +560,12 @@ export default function CorporatePlanList({handleSubmitSuccess}) {
<Grid item xs={6}>
: {row.email ?? '-'}
</Grid>
<Grid item xs={6}>
Phone
</Grid>
<Grid item xs={6}>
: {row.person?.phone ?? '-'}
</Grid>
</Grid>
</Grid>
<Grid item xs={6}>

View File

@@ -0,0 +1,37 @@
import { Card, Grid, Container } from '@mui/material';
import { useParams } from 'react-router-dom';
import HeaderBreadcrumbs from '@/components/HeaderBreadcrumbs';
import Page from '@/components/Page';
import useSettings from '@/hooks/useSettings';
import List from '../Prescription/List';
export default function DoctorRating(){
const { themeStretch } = useSettings();
const { id } = useParams();
const pageTitle = 'Doctor Rating';
return(
<Page title = {pageTitle}>
<Container maxWidth = {themeStretch ? false : 'xl'}>
<HeaderBreadcrumbs heading= {pageTitle}
links={[
{
name: 'Report',
href: '/report',
},
{
name: 'Doctor Rating',
href: '/doctorrating',
},
]}
/>
<List/>
</Container>
</Page>
);
}

View File

@@ -0,0 +1,427 @@
import {
Box,
Button,
Card,
Collapse,
Paper,
Select,
SelectChangeEvent,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
TextField,
Typography,
Stack,
ButtonGroup,
Grid,
Chip,
Dialog,
DialogContent,
DialogContentText,
DialogActions,
FormControl,
Autocomplete,
InputAdornment,
IconButton,
} from '@mui/material';
import {
Link,
NavLink as RouterLink,
useSearchParams,
useNavigate,
useParams,
} from 'react-router-dom';
// hooks
import React, { ChangeEvent, Component, useEffect, useRef, useState } from 'react';
import useSettings from '../../../hooks/useSettings';
// components
import axios from '../../../utils/axios';
import { LaravelPaginatedData } from '../../../@types/paginated-data';
import { Icd } from '../../../@types/diagnosis';
import BasePagination from '../../../components/BasePagination';
import { Practitioner } from '../../../@types/doctor';
import CreateIcon from '@mui/icons-material/Create';
import { Props } from '../../../components/editor/index';
import { red } from '@mui/material/colors';
import { margin, padding } from '@mui/system';
import { enqueueSnackbar } from 'notistack';
import { Controller } from 'react-hook-form';
import SvgIconStyle from '../../../components/SvgIconStyle';
import { GridSearchIcon } from '@mui/x-data-grid';
import { Search } from '@mui/icons-material';
import { Icon } from '@iconify/react';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
export default function List(){
const navigate = useNavigate();
const { organization_id } = useParams();
const [searchParams, setSearchParams] = useSearchParams();
const [searchParamsOrganizations, setSearchParamsOrganizations] = useSearchParams();
const [searchParamsSpecialities, setSearchParamsSpecialities] = useSearchParams();
const [searchParamsFilter, setSearchParamsFilter] = useSearchParams();
function Filter(props: any) {
// SEARCH
const searchInput = useRef<HTMLInputElement>(null);
const [searchText, setSearchText] = useState('');
//handle search
const handleSearchChange = (event: any) => {
const newSearchText = event.target.value ?? '';
setSearchText(newSearchText);
};
const handleSearchSubmit = (event: any) => {
event.preventDefault();
props.onSearch(searchText);
};
useEffect(() => {
// Trigger First Search
setSearchText(searchParams.get('search') ?? '');
}, []);
const item = [
{
id: '',
value: '',
name: 'Semua',
},
];
return (
<form style={{ width: '100%' }}>
<Grid container spacing={2} sx={{ justifyContent: 'space-between', alignItems: 'center' }}>
<Grid item xs={12} sm={12} md={12} lg={12}>
<TextField
id="search-input"
ref={searchInput}
variant="outlined"
fullWidth
onChange={handleSearchChange}
onKeyDown={(event) => {
if (event.key === 'Enter') {
handleSearchSubmit(event);
}
}}
value={searchText}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<Search />
</InputAdornment>
),
placeholder: 'Search',
}}
/>
</Grid>
</Grid>
</form>
);
}
function FilterForm(props: any) {
return(
<Grid
container
spacing={2}
sx={{ p: 2, justifyContent: 'space-between', alignItems: 'center' }}
>
<Grid item xs={12} md={12} lg={12}>
<Filter onSearch={applyItems} />
</Grid>
</Grid>
);
}
function createData(doctor: Practitioner): Practitioner {
return {
...doctor,
/* user: doctor.user ? new User(doctor.user) : null; */
};
}
function Row(props: { row: ReturnType<typeof createData> }) {
const { row } = props;
const [open, setOpen] = React.useState(false);
const [openDialog, setOpenDialog] = React.useState(false);
return (
<React.Fragment>
<TableRow>
<TableCell>
<IconButton aria-label="expand row" size="small" onClick={() => setOpen(!open)}>
{open ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />}
</IconButton>
</TableCell>
<TableCell align="left">{row.user ? row.user.sFirstName : '-'}</TableCell>
<TableCell align="left">{row.nIDDokter ? row.nIDDokter : '-'}</TableCell>
<TableCell align="left">{row.nRating ? row.nRating : '-'}</TableCell>
<TableCell align="left">{row.sNotes ? row.sNotes : '-'}</TableCell>
<TableCell align="left">{row.dCreateOn ? row.dCreateOn : '-'}</TableCell>
{/* <TableCell align="center">
<ButtonGroup variant="text" aria-label="text button group">
<Link to={'/report/prescription/' + row.id + '/show'}>
<Button>
<Icon icon="ph:eye-bold" style={{ width: '24px', height: '24px' }} />
</Button>
</Link>
</ButtonGroup>
</TableCell> */}
</TableRow>
{/* COLLAPSIBLE ROW */}
<TableRow>
<TableCell
style={{ paddingBottom: 0, paddingTop: 0, backgroundColor: 'rgba(244, 246, 248, 0.5)' }}
colSpan={6}
>
{/* <Collapse in={open} timeout="auto" unmountOnExit>
<Box sx={{ margin: 1, pb: 2, pl: 4 }}>
<Grid container>
<Grid item xs={12} sx={{ padding: 2 }}>
<Grid container>
<Grid item xs={6}>
Metode Pembayaran
</Grid>
<Grid item xs={6}>
: {row.payment_method ? row.payment_method : '-'}
</Grid>
<Grid item xs={6}>
Jenis Benefit
</Grid>
<Grid item xs={6}>
: -
</Grid>
<Grid item xs={6}>
Durasi
</Grid>
<Grid item xs={6}>
: {row.duration ? row.duration : '-'}
</Grid>
</Grid>
</Grid>
</Grid>
</Box>
</Collapse> */}
</TableCell>
</TableRow>
{/* END COLLAPSIBLE ROW */}
<Dialog
open={openDialog}
onClose={() => {
setOpenDialog(false);
}}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogContent sx={{ p: 5 }}>
<Icon
icon="eva:trash-2-outline"
style={{
width: '100px',
height: '100px',
color: '#FF0000',
margin: 'auto',
display: 'block',
marginBottom: '20px',
alignContent: 'center',
}}
/>
<DialogContentText sx={{ fontWeight: 'bold', pb: 1 }} id="alert-dialog-title">
Apakah anda yakin ingin menghapus
</DialogContentText>
<Typography sx={{ fontWeight: 'bold' }} id="alert-dialog-title">
{row.name}?
</Typography>
</DialogContent>
<DialogActions>
<Button
onClick={() => {
setOpenDialog(false);
}}
color="primary"
>
Batal
</Button>
{/* <Button
onClick={() => {
handleDelete(row.id);
}}
color="primary"
autoFocus
>
Hapus
</Button> */}
</DialogActions>
</Dialog>
</React.Fragment>
);
}
const headStyle = {
fontWeight: 'bold',
};
// Dummy Default Data
const [dataTableIsLoading, setDataTableLoading] = useState(true);
const [dataTableLastRequest, setDataTableLastRequest] = useState(0);
const [dataTableResponseState, setDataTableResponseState] = useState('idle');
const [dataTableData, setDataTableData] = useState<LaravelPaginatedData>({
current_page: 1,
data: [],
path: '',
first_page_url: '',
last_page: 1,
last_page_url: '',
next_page_url: '',
prev_page_url: '',
per_page: 10,
from: 0,
to: 0,
total: 0,
});
const [dataTablePage, setDataTablePage] = useState(5);
const loadDataTableData = async (appliedFilter: any | null = null) => {
setDataTableLoading(true);
const filter = appliedFilter ? appliedFilter : Object.fromEntries([...searchParams.entries()]);
const response = await axios.get('/doctorrating ', {
params: filter,
});
setDataTableLoading(false);
setDataTableData(response.data);
};
// const applyFilter = async (searchFilter: string) => {
// await loadDataTableData({ search: searchFilter });
// setSearchParams({ search: searchFilter });
// };
const applyItems = async (
searchFilter: string,
searchFilterOrganization: string,
searchFilterSpecialities: string
) => {
await loadDataTableData({
search: searchFilter,
organization_id: searchFilterOrganization,
speciality_id: searchFilterSpecialities,
});
setSearchParamsFilter({
search: searchFilter,
organization_id: searchFilterOrganization,
speciality_id: searchFilterSpecialities,
});
};
const handlePageChange = (event: ChangeEvent, value: number) => {
const filter = Object.fromEntries([...searchParams.entries(), ['page', value]]);
loadDataTableData(filter);
setSearchParams(filter);
};
useEffect(() => {
loadDataTableData();
}, []);
return (
<Stack>
{/* <Ambulace /> */}
<Card sx={{ marginTop: '30px' }}>
<FilterForm sx={{ marginTop: '100px' }} />
{/* The Main Table */}
<TableContainer component={Paper}>
<Table>
<TableBody>
<TableRow>
{/* <TableCell colSpan={8} rowSpan={1} align="center" /> */}
<TableCell style={headStyle} align="left" />
<TableCell style={headStyle} rowSpan={2} align="left">
Nama User
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
ID Dokter
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
Rating
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
Notes
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
Created On
</TableCell>
</TableRow>
{/* <TableRow>
<TableCell style={headStyle} align="left" />
<TableCell style={headStyle} align="left">
Tanggal Booking
</TableCell>
<TableCell style={headStyle} align="left">
Tanggal Appointment
</TableCell>
<TableCell style={headStyle} align="left">
Faskes
</TableCell>
<TableCell style={headStyle} align="left">
Nama Dokter
</TableCell>
<TableCell style={headStyle} align="left">
Spesialisasi
</TableCell>
<TableCell style={headStyle} align="left">
Pasien
</TableCell>
<TableCell style={headStyle} align="left">
Dokter
</TableCell>
</TableRow> */}
</TableBody>
{dataTableIsLoading ? (
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">
Loading
</TableCell>
</TableRow>
</TableBody>
) : (dataTableData.data && dataTableData.data.length === 0) ? (
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">
No Data
</TableCell>
</TableRow>
</TableBody>
) : (
<TableBody>
{dataTableData && dataTableData.map((row) => (
<Row key={row.id} row={row} />
))}
</TableBody>
)}
</Table>
</TableContainer>
<BasePagination paginationData={dataTableData} onPageChange={handlePageChange} />
</Card>
</Stack>
);
}

View File

@@ -0,0 +1,38 @@
import { Card, Grid, Container } from '@mui/material';
import { useParams } from 'react-router-dom';
import HeaderBreadcrumbs from '@/components/HeaderBreadcrumbs';
import Page from '@/components/Page';
import useSettings from '@/hooks/useSettings';
import List from './List_2';
export default function DoctorRating(){
const { themeStretch } = useSettings();
const { id } = useParams();
const pageTitle = 'Doctor Rating';
return(
<Page title = {pageTitle}>
<Container maxWidth = {themeStretch ? false : 'xl'}>
<HeaderBreadcrumbs heading= {pageTitle}
links={[
{
name: 'Report',
href: '/report',
},
{
name: 'Doctor Rating',
href: '/doctorrating',
},
]}
/>
<List/>
</Container>
</Page>
);
}

View File

@@ -63,7 +63,7 @@ import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
import { DesktopDatePicker, LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { MenuItem } from '@mui/material';
import { fPostFormat } from '@/utils/formatTime';
import { fDateOnly } from '@/utils/formatTime';
import AutocompleteLinksehatHealthcare from '@/components/autocomplete/AutocompleteLinksehatHealthcare';
// ----------------------------------------------------------------------
@@ -81,12 +81,10 @@ export default function List() {
const [searchParamsFilter, setSearchParamsFilter] = useSearchParams();
useEffect(() => {
// axios.get(`/search-organizations`).then((response) => {
// setOrganizationOptions(response.data);
// });
}, [])
}, []);
function Filter(props: any) {
// SEARCH
@@ -123,17 +121,17 @@ export default function List() {
];
const paymentStatusOptions = {
'settlement' : 'Diterima',
'expired' : 'Kadaluarsa',
'capture' : 'Captured',
'deny' : 'Ditolak',
'pending' : 'Menunggu Pembayaran',
'cancel' : 'Dibatalkan',
'refund' : 'Dikembalikan',
'expire' : 'Kadaluarsa',
'cod' : 'COD',
'FAILED' : 'Gagal',
'COMPLETED' : 'Complete',
settlement: 'Diterima',
expired: 'Kadaluarsa',
capture: 'Captured',
deny: 'Ditolak',
pending: 'Menunggu Pembayaran',
cancel: 'Dibatalkan',
refund: 'Dikembalikan',
expire: 'Kadaluarsa',
cod: 'COD',
FAILED: 'Gagal',
COMPLETED: 'Complete',
};
const dataOrganizations = [];
@@ -151,10 +149,13 @@ export default function List() {
onKeyDown={(event) => {
if (event.key === 'Enter') {
// handleSearchSubmit(event);
const filter = Object.fromEntries([...searchParams.entries(), ['search', searchText]]);
setSearchParams(filter)
loadDataTableData(filter)
const filter = Object.fromEntries([
...searchParams.entries(),
['search', searchText],
]);
setSearchParams(filter);
loadDataTableData(filter);
}
}}
label="Search"
@@ -170,44 +171,55 @@ export default function List() {
/>
</Grid>
<Grid item md={2}>
<FormControl fullWidth>
<InputLabel>
Payment Status
</InputLabel>
<Select
value={searchParams.get('payment_status') ?? 'semua'}
label="Payment Status"
onChange={(el) => {
// console.log(el.target.value)
const filter = Object.fromEntries([...searchParams.entries(), ['payment_status', el.target.value]]);
setSearchParams(filter)
loadDataTableData(filter)
}}
>
<MenuItem value={'semua'}>Semua</MenuItem>
{Object.entries(paymentStatusOptions).map((option, index) => (
<MenuItem value={option[0]} key={index}>{option[1]}</MenuItem>
))}
</Select>
<FormControl fullWidth>
<InputLabel>Payment Status</InputLabel>
<Select
value={searchParams.get('payment_status') ?? 'semua'}
label="Payment Status"
onChange={(el) => {
// console.log(el.target.value)
const filter = Object.fromEntries([
...searchParams.entries(),
['payment_status', el.target.value],
]);
setSearchParams(filter);
loadDataTableData(filter);
}}
>
<MenuItem value={'semua'}>Semua</MenuItem>
{Object.entries(paymentStatusOptions).map((option, index) => (
<MenuItem value={option[0]} key={index}>
{option[1]}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
<Grid item md={2}>
<AutocompleteLinksehatHealthcare
onChange={(value) => {
if (value) {
const filter = Object.fromEntries([...searchParams.entries(), ['healthcare_id', value.nID ?? '']]);
setSearchParams(filter)
loadDataTableData(filter)
setOrganizationOptions([value])
const filter = Object.fromEntries([
...searchParams.entries(),
['healthcare_id', value.nID ?? ''],
]);
setSearchParams(filter);
loadDataTableData(filter);
setOrganizationOptions([value]);
} else {
const filter = Object.fromEntries([...searchParams.entries(), ['healthcare_id', '']]);
setSearchParams(filter)
loadDataTableData(filter)
setOrganizationOptions([])
const filter = Object.fromEntries([
...searchParams.entries(),
['healthcare_id', ''],
]);
setSearchParams(filter);
loadDataTableData(filter);
setOrganizationOptions([]);
}
}}
currentOptions={organizationOptions}
currentValue={organizationOptions?.find((org) => org?.nID == searchParams.get('healthcare_id'))}
currentValue={organizationOptions?.find(
(org) => org?.nID == searchParams.get('healthcare_id')
)}
textLabel="Rumah Sakit"
placeholder="Nama"
/>
@@ -219,30 +231,21 @@ export default function List() {
value={searchParams.get('appointment_start')}
inputFormat="dd/MM/yyyy"
onChange={(value) => {
try {
if (value && !!Date.parse(value)) {
const date = value ? fDateOnly(value) : '';
var entries = [...searchParams.entries(), ['appointment_start', date ?? '']];
if (!searchParams.get('appointment_end')) {
entries = [...entries, ['appointment_end', date ?? '']];
}
const filter = Object.fromEntries(entries);
const date = value ? fPostFormat(value) : ''
var entries = [...searchParams.entries(), ['appointment_start', date ?? '']];
if (!searchParams.get('appointment_end')) {
entries = [...entries, ['appointment_end', date ?? '']];
}
const filter = Object.fromEntries(entries);
setSearchParams(filter)
loadDataTableData(filter)
}
} catch (e) {}
setSearchParams(filter);
loadDataTableData(filter);
}
} catch (e) {}
}}
renderInput={(params) => (
<TextField
{...params}
fullWidth
label="Start"
/>
)}
renderInput={(params) => <TextField {...params} fullWidth label="Start" />}
/>
</LocalizationProvider>
</Grid>
@@ -254,18 +257,16 @@ export default function List() {
inputFormat="dd/MM/yyyy"
onChange={(value) => {
try {
if (value && !!Date.parse(value)) {
const date = fPostFormat(value)
const date = fDateOnly(value);
var entries = [...searchParams.entries(), ['appointment_end', date ?? '']];
if (!searchParams.get('appointment_start')) {
entries = [...entries, ['appointment_start', date ?? '']];
}
const filter = Object.fromEntries(entries);
setSearchParams(filter)
loadDataTableData(filter)
setSearchParams(filter);
loadDataTableData(filter);
}
} catch (e) {}
}}
@@ -488,12 +489,9 @@ export default function List() {
const loadDataTableData = async (appliedFilter: any | null = null) => {
setDataTableLoading(true);
const filter = appliedFilter ? appliedFilter : Object.fromEntries([...searchParams.entries()]);
const response = await axios.get(
'/linksehat/payments',
{
params: filter,
}
);
const response = await axios.get('/linksehat/payments', {
params: filter,
});
setDataTableLoading(false);
setDataTableData(response.data.data);
};
@@ -508,7 +506,7 @@ export default function List() {
searchFilterOrganization: string,
searchFilterPaymentStatus: string,
searchFilterAppointmentStart: string,
searchFilterAppointmentEnd: string,
searchFilterAppointmentEnd: string
) => {
await loadDataTableData({
search: searchFilter,

View File

@@ -27,7 +27,6 @@ export default function Doctor() {
},
]}
/>
<List />
</Container>
</Page>

View File

@@ -53,10 +53,14 @@ import { Controller } from 'react-hook-form';
import SvgIconStyle from '../../../components/SvgIconStyle';
import { GridSearchIcon } from '@mui/x-data-grid';
import { Search } from '@mui/icons-material';
import { Add, Search } from '@mui/icons-material';
import { Icon } from '@iconify/react';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
import { RHFDatepicker } from '@/components/hook-form';
import { DesktopDatePicker, LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { fDateOnly } from '@/utils/formatTime';
// ----------------------------------------------------------------------
@@ -103,7 +107,7 @@ export default function List() {
return (
<form style={{ width: '100%' }}>
<Grid container spacing={2} sx={{ justifyContent: 'space-between', alignItems: 'center' }}>
<Grid item xs={12} sm={12} md={12} lg={12}>
<Grid item xs={12} md={6}>
<TextField
id="search-input"
ref={searchInput}
@@ -126,6 +130,74 @@ export default function List() {
}}
/>
</Grid>
<Grid item xs={12} md={2}>
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DesktopDatePicker
value={searchParams.get('startDate')}
inputFormat="dd/MM/yyyy"
onChange={(value) => {
try {
if (value && !!Date.parse(value)) {
const date = value ? fDateOnly(value) : '';
var entries = [...searchParams.entries(), ['startDate', date ?? '']];
if (!searchParams.get('endDate')) {
entries = [...entries, ['endDate', date ?? '']];
}
const filter = Object.fromEntries(entries);
setSearchParams(filter);
loadDataTableData(filter);
}
} catch (e) {}
}}
renderInput={(params) => <TextField {...params} fullWidth label="Start" />}
/>
</LocalizationProvider>
</Grid>
<Grid item xs={12} md={2}>
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DesktopDatePicker
value={searchParams.get('endDate')}
inputFormat="dd/MM/yyyy"
onChange={(value) => {
try {
if (value && !!Date.parse(value)) {
const date = fDateOnly(value);
var entries = [...searchParams.entries(), ['endDate', date ?? '']];
if (!searchParams.get('startDate')) {
entries = [...entries, ['startDate', date ?? '']];
}
const filter = Object.fromEntries(entries);
setSearchParams(filter);
loadDataTableData(filter);
}
} catch (e) {}
}}
renderInput={(params) => (
<TextField
{...params}
fullWidth
label="End"
// error={!!error}
// helperText={error?.message}
// {...other}
/>
)}
/>
</LocalizationProvider>
</Grid>
<Grid item xs={12} md={2}>
<Button
variant="outlined"
fullWidth
startIcon={<Add />}
sx={{ p: 1.8 }}
onClick={exportExcel}
>
Export
</Button>
</Grid>
</Grid>
</form>
);
@@ -188,6 +260,8 @@ export default function List() {
<TableCell align="left">{row.health_care ? row.health_care : '-'}</TableCell>
<TableCell align="left">{row.doctor_name ? row.doctor_name : '-'}</TableCell>
<TableCell align="left">{row.speciality ? row.speciality : '-'}</TableCell>
<TableCell align="left">{row.pasien_name ? row.pasien_name : '-'}</TableCell>
<TableCell align="left">{row.pasien_phone ? row.pasien_phone : '-'}</TableCell>
<TableCell align="left">{row.appointment_media ? row.appointment_media : '-'}</TableCell>
<TableCell align="left">{row.patient_media ? row.patient_media : '-'}</TableCell>
<TableCell align="left">{row.doctor_media ? row.doctor_media : '-'}</TableCell>
@@ -329,6 +403,27 @@ export default function List() {
setDataTableData(response.data);
};
const exportExcel = async () => {
var filter = Object.fromEntries([...searchParams.entries()]);
await axios
.get('live-chat/export', { params: filter })
.then((res) => {
enqueueSnackbar('Data berhasil di Export', {
variant: 'success',
anchorOrigin: { horizontal: 'right', vertical: 'top' },
});
document.location.href = res.data.data.file_url;
})
.catch((err) =>
enqueueSnackbar('Data Gagal di Export', {
variant: 'error',
anchorOrigin: { horizontal: 'right', vertical: 'top' },
})
);
};
// const applyFilter = async (searchFilter: string) => {
// await loadDataTableData({ search: searchFilter });
// setSearchParams({ search: searchFilter });
@@ -390,6 +485,12 @@ export default function List() {
<TableCell style={headStyle} rowSpan={2} align="left">
Spesialisasi
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
Nama Pasien
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
No Telepon Pasien
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
Appointment Via App/Website
</TableCell>
@@ -411,20 +512,20 @@ export default function List() {
<TableRow>
<TableCell style={headStyle} align="left" />
{/* <TableCell style={headStyle} align="left">
Tanggal Booking
</TableCell>
<TableCell style={headStyle} align="left">
Tanggal Appointment
</TableCell>
<TableCell style={headStyle} align="left">
Faskes
</TableCell>
<TableCell style={headStyle} align="left">
Nama Dokter
</TableCell>
<TableCell style={headStyle} align="left">
Spesialisasi
</TableCell> */}
Tanggal Booking
</TableCell>
<TableCell style={headStyle} align="left">
Tanggal Appointment
</TableCell>
<TableCell style={headStyle} align="left">
Faskes
</TableCell>
<TableCell style={headStyle} align="left">
Nama Dokter
</TableCell>
<TableCell style={headStyle} align="left">
Spesialisasi
</TableCell> */}
<TableCell style={headStyle} align="left">
Pasien
</TableCell>

View File

@@ -1,440 +1,428 @@
import {
Box,
Button,
Card,
Collapse,
Paper,
Select,
SelectChangeEvent,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
TextField,
Typography,
Stack,
ButtonGroup,
Grid,
Chip,
Dialog,
DialogContent,
DialogContentText,
DialogActions,
FormControl,
Autocomplete,
InputAdornment,
IconButton,
} from '@mui/material';
Box,
Button,
Card,
Collapse,
Paper,
Select,
SelectChangeEvent,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
TextField,
Typography,
Stack,
ButtonGroup,
Grid,
Chip,
Dialog,
DialogContent,
DialogContentText,
DialogActions,
FormControl,
Autocomplete,
InputAdornment,
IconButton,
} from '@mui/material';
import {
Link,
NavLink as RouterLink,
useSearchParams,
useNavigate,
useParams,
} from 'react-router-dom';
// hooks
import React, { ChangeEvent, Component, useEffect, useRef, useState } from 'react';
import useSettings from '../../../hooks/useSettings';
// components
import axios from '../../../utils/axios';
import { LaravelPaginatedData } from '../../../@types/paginated-data';
import { Icd } from '../../../@types/diagnosis';
import BasePagination from '../../../components/BasePagination';
import { Practitioner } from '../../../@types/doctor';
import CreateIcon from '@mui/icons-material/Create';
import { Props } from '../../../components/editor/index';
import { red } from '@mui/material/colors';
import { margin, padding } from '@mui/system';
import { enqueueSnackbar } from 'notistack';
import { Controller } from 'react-hook-form';
import { User } from '../../../Models/User';
import SvgIconStyle from '../../../components/SvgIconStyle';
import { GridSearchIcon } from '@mui/x-data-grid';
import { Search } from '@mui/icons-material';
import { Icon } from '@iconify/react';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
export default function List(){
const navigate = useNavigate();
const { organization_id } = useParams();
const [searchParams, setSearchParams] = useSearchParams();
const [searchParamsOrganizations, setSearchParamsOrganizations] = useSearchParams();
const [searchParamsSpecialities, setSearchParamsSpecialities] = useSearchParams();
const [searchParamsFilter, setSearchParamsFilter] = useSearchParams();
function Filter(props: any) {
// SEARCH
const searchInput = useRef<HTMLInputElement>(null);
const [searchText, setSearchText] = useState('');
import {
Link,
NavLink as RouterLink,
useSearchParams,
useNavigate,
useParams,
} from 'react-router-dom';
// hooks
import React, { ChangeEvent, Component, useEffect, useRef, useState } from 'react';
import useSettings from '../../../hooks/useSettings';
// components
import axios from '../../../utils/axios';
import { LaravelPaginatedData } from '../../../@types/paginated-data';
import { Icd } from '../../../@types/diagnosis';
import BasePagination from '../../../components/BasePagination';
import { Practitioner } from '../../../@types/doctor';
import CreateIcon from '@mui/icons-material/Create';
import { Props } from '../../../components/editor/index';
import { red } from '@mui/material/colors';
import { margin, padding } from '@mui/system';
import { enqueueSnackbar } from 'notistack';
import { Controller } from 'react-hook-form';
//handle search
const handleSearchChange = (event: any) => {
const newSearchText = event.target.value ?? '';
setSearchText(newSearchText);
};
import SvgIconStyle from '../../../components/SvgIconStyle';
import { GridSearchIcon } from '@mui/x-data-grid';
import { Search } from '@mui/icons-material';
import { Icon } from '@iconify/react';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
const handleSearchSubmit = (event: any) => {
event.preventDefault();
props.onSearch(searchText);
};
export default function List(){
const navigate = useNavigate();
const { organization_id } = useParams();
const [searchParams, setSearchParams] = useSearchParams();
const [searchParamsOrganizations, setSearchParamsOrganizations] = useSearchParams();
const [searchParamsSpecialities, setSearchParamsSpecialities] = useSearchParams();
const [searchParamsFilter, setSearchParamsFilter] = useSearchParams();
function Filter(props: any) {
// SEARCH
const searchInput = useRef<HTMLInputElement>(null);
const [searchText, setSearchText] = useState('');
useEffect(() => {
// Trigger First Search
setSearchText(searchParams.get('search') ?? '');
}, []);
//handle search
const handleSearchChange = (event: any) => {
const newSearchText = event.target.value ?? '';
setSearchText(newSearchText);
};
const handleSearchSubmit = (event: any) => {
event.preventDefault();
props.onSearch(searchText);
};
const item = [
{
id: '',
value: '',
name: 'Semua',
},
];
useEffect(() => {
// Trigger First Search
setSearchText(searchParams.get('search') ?? '');
}, []);
const item = [
{
id: '',
value: '',
name: 'Semua',
},
];
return (
<form style={{ width: '100%' }}>
<Grid container spacing={2} sx={{ justifyContent: 'space-between', alignItems: 'center' }}>
<Grid item xs={12} sm={12} md={12} lg={12}>
<TextField
id="search-input"
ref={searchInput}
variant="outlined"
fullWidth
onChange={handleSearchChange}
onKeyDown={(event) => {
if (event.key === 'Enter') {
handleSearchSubmit(event);
}
}}
value={searchText}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<Search />
</InputAdornment>
),
placeholder: 'Search',
}}
/>
</Grid>
</Grid>
</form>
);
}
function FilterForm(props: any) {
return(
<Grid
container
spacing={2}
sx={{ p: 2, justifyContent: 'space-between', alignItems: 'center' }}
>
<Grid item xs={12} md={12} lg={12}>
<Filter onSearch={applyItems} />
</Grid>
return (
<form style={{ width: '100%' }}>
<Grid container spacing={2} sx={{ justifyContent: 'space-between', alignItems: 'center' }}>
<Grid item xs={12} sm={12} md={12} lg={12}>
<TextField
id="search-input"
ref={searchInput}
variant="outlined"
fullWidth
onChange={handleSearchChange}
onKeyDown={(event) => {
if (event.key === 'Enter') {
handleSearchSubmit(event);
}
}}
value={searchText}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<Search />
</InputAdornment>
),
placeholder: 'Search',
}}
/>
</Grid>
</Grid>
</form>
);
}
function FilterForm(props: any) {
return(
<Grid
container
spacing={2}
sx={{ p: 2, justifyContent: 'space-between', alignItems: 'center' }}
>
<Grid item xs={12} md={12} lg={12}>
<Filter onSearch={applyItems} />
</Grid>
);
}
</Grid>
);
}
function createData(doctor: Practitioner): Practitioner {
return {
...doctor,
};
}
function createData(doctor: Practitioner): Practitioner {
return {
...doctor,
/* user: doctor.user ? new User(doctor.user) : null; */
};
}
function Row(props: { row: ReturnType<typeof createData> }) {
const { row } = props;
const [open, setOpen] = React.useState(false);
const [openDialog, setOpenDialog] = React.useState(false);
function Row(props: { row: ReturnType<typeof createData> }) {
const { row } = props;
const [open, setOpen] = React.useState(false);
const [openDialog, setOpenDialog] = React.useState(false);
return (
<React.Fragment>
<TableRow>
<TableCell>
<IconButton aria-label="expand row" size="small" onClick={() => setOpen(!open)}>
{open ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />}
</IconButton>
</TableCell>
<TableCell align="left">{row.nID ? row.nID : '-'}</TableCell>
<TableCell align="left">
{row.nIDUser ? row.nIDUser : '-'}
</TableCell>
<TableCell align="left">{row.nIDDokter ? row.nIDDokter : '-'}</TableCell>
<TableCell align="left">{row.sDokterName ? row.sDokterName : '-'}</TableCell>
<TableCell align="left">{row.dTanggalResep ? row.dTanggalResep : '-'}</TableCell>
<TableCell align="left">{row.sSource ? row.sSource : '-'}</TableCell>
<TableCell align="left">{row.sKodeResep ? row.sKodeResep : '-'}</TableCell>
<TableCell align="left">{row.sDiagnose ? row.sDiagnose : '-'}</TableCell>
<TableCell align="left">{row.sStatus ? row.sStatus : '-'}</TableCell>
{/* <TableCell align="center">
<ButtonGroup variant="text" aria-label="text button group">
<Link to={'/report/prescription/' + row.id + '/show'}>
<Button>
<Icon icon="ph:eye-bold" style={{ width: '24px', height: '24px' }} />
</Button>
</Link>
</ButtonGroup>
</TableCell> */}
</TableRow>
{/* COLLAPSIBLE ROW */}
<TableRow>
<TableCell
style={{ paddingBottom: 0, paddingTop: 0, backgroundColor: 'rgba(244, 246, 248, 0.5)' }}
colSpan={6}
>
return (
<React.Fragment>
<TableRow>
<TableCell>
<IconButton aria-label="expand row" size="small" onClick={() => setOpen(!open)}>
{open ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />}
</IconButton>
</TableCell>
<TableCell align="left">{row.user ? row.user.sFirstName : '-'}</TableCell>
<TableCell align="left">{row.nIDDokter ? row.nIDDokter : '-'}</TableCell>
<TableCell align="left">{row.nRating ? row.nRating : '-'}</TableCell>
<TableCell align="left">{row.sNotes ? row.sNotes : '-'}</TableCell>
<TableCell align="left">{row.dCreateOn ? row.dCreateOn : '-'}</TableCell>
{/* <TableCell align="center">
<ButtonGroup variant="text" aria-label="text button group">
<Link to={'/report/prescription/' + row.id + '/show'}>
<Button>
<Icon icon="ph:eye-bold" style={{ width: '24px', height: '24px' }} />
</Button>
</Link>
</ButtonGroup>
</TableCell> */}
</TableRow>
{/* COLLAPSIBLE ROW */}
<TableRow>
<TableCell
style={{ paddingBottom: 0, paddingTop: 0, backgroundColor: 'rgba(244, 246, 248, 0.5)' }}
colSpan={6}
>
{/* <Collapse in={open} timeout="auto" unmountOnExit>
<Box sx={{ margin: 1, pb: 2, pl: 4 }}>
<Grid container>
<Grid item xs={12} sx={{ padding: 2 }}>
<Grid container>
<Grid item xs={6}>
Metode Pembayaran
</Grid>
<Grid item xs={6}>
: {row.payment_method ? row.payment_method : '-'}
</Grid>
<Box sx={{ margin: 1, pb: 2, pl: 4 }}>
<Grid container>
<Grid item xs={12} sx={{ padding: 2 }}>
<Grid container>
<Grid item xs={6}>
Metode Pembayaran
</Grid>
<Grid item xs={6}>
: {row.payment_method ? row.payment_method : '-'}
</Grid>
<Grid item xs={6}>
Jenis Benefit
</Grid>
<Grid item xs={6}>
: -
</Grid>
<Grid item xs={6}>
Durasi
</Grid>
<Grid item xs={6}>
: {row.duration ? row.duration : '-'}
</Grid>
<Grid item xs={6}>
Jenis Benefit
</Grid>
<Grid item xs={6}>
: -
</Grid>
<Grid item xs={6}>
Durasi
</Grid>
<Grid item xs={6}>
: {row.duration ? row.duration : '-'}
</Grid>
</Grid>
</Grid>
</Box>
</Collapse> */}
</TableCell>
</TableRow>
</Grid>
</Box>
</Collapse> */}
</TableCell>
</TableRow>
{/* END COLLAPSIBLE ROW */}
<Dialog
open={openDialog}
onClose={() => {
setOpenDialog(false);
}}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogContent sx={{ p: 5 }}>
<Icon
icon="eva:trash-2-outline"
style={{
width: '100px',
height: '100px',
color: '#FF0000',
margin: 'auto',
display: 'block',
marginBottom: '20px',
alignContent: 'center',
}}
/>
<DialogContentText sx={{ fontWeight: 'bold', pb: 1 }} id="alert-dialog-title">
Apakah anda yakin ingin menghapus
</DialogContentText>
<Typography sx={{ fontWeight: 'bold' }} id="alert-dialog-title">
{row.name}?
</Typography>
</DialogContent>
<DialogActions>
<Button
onClick={() => {
setOpenDialog(false);
}}
color="primary"
>
Batal
</Button>
{/* <Button
onClick={() => {
handleDelete(row.id);
}}
color="primary"
autoFocus
>
Hapus
</Button> */}
</DialogActions>
</Dialog>
</React.Fragment>
);
}
const headStyle = {
fontWeight: 'bold',
};
// Dummy Default Data
const [dataTableIsLoading, setDataTableLoading] = useState(true);
const [dataTableLastRequest, setDataTableLastRequest] = useState(0);
const [dataTableResponseState, setDataTableResponseState] = useState('idle');
const [dataTableData, setDataTableData] = useState<LaravelPaginatedData>({
current_page: 1,
data: [],
path: '',
first_page_url: '',
last_page: 1,
last_page_url: '',
next_page_url: '',
prev_page_url: '',
per_page: 10,
from: 0,
to: 0,
total: 0,
{/* END COLLAPSIBLE ROW */}
<Dialog
open={openDialog}
onClose={() => {
setOpenDialog(false);
}}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogContent sx={{ p: 5 }}>
<Icon
icon="eva:trash-2-outline"
style={{
width: '100px',
height: '100px',
color: '#FF0000',
margin: 'auto',
display: 'block',
marginBottom: '20px',
alignContent: 'center',
}}
/>
<DialogContentText sx={{ fontWeight: 'bold', pb: 1 }} id="alert-dialog-title">
Apakah anda yakin ingin menghapus
</DialogContentText>
<Typography sx={{ fontWeight: 'bold' }} id="alert-dialog-title">
{row.name}?
</Typography>
</DialogContent>
<DialogActions>
<Button
onClick={() => {
setOpenDialog(false);
}}
color="primary"
>
Batal
</Button>
{/* <Button
onClick={() => {
handleDelete(row.id);
}}
color="primary"
autoFocus
>
Hapus
</Button> */}
</DialogActions>
</Dialog>
</React.Fragment>
);
}
const headStyle = {
fontWeight: 'bold',
};
// Dummy Default Data
const [dataTableIsLoading, setDataTableLoading] = useState(true);
const [dataTableLastRequest, setDataTableLastRequest] = useState(0);
const [dataTableResponseState, setDataTableResponseState] = useState('idle');
const [dataTableData, setDataTableData] = useState<LaravelPaginatedData>({
current_page: 1,
data: [],
path: '',
first_page_url: '',
last_page: 1,
last_page_url: '',
next_page_url: '',
prev_page_url: '',
per_page: 10,
from: 0,
to: 0,
total: 0,
});
const [dataTablePage, setDataTablePage] = useState(5);
const loadDataTableData = async (appliedFilter: any | null = null) => {
setDataTableLoading(true);
const filter = appliedFilter ? appliedFilter : Object.fromEntries([...searchParams.entries()]);
const response = await axios.get('/doctorrating ', {
params: filter,
});
const [dataTablePage, setDataTablePage] = useState(5);
setDataTableLoading(false);
setDataTableData(response.data);
};
const loadDataTableData = async (appliedFilter: any | null = null) => {
setDataTableLoading(true);
const filter = appliedFilter ? appliedFilter : Object.fromEntries([...searchParams.entries()]);
const response = await axios.get('/prescription', {
params: filter,
});
setDataTableLoading(false);
setDataTableData(response.data);
};
// const applyFilter = async (searchFilter: string) => {
// await loadDataTableData({ search: searchFilter });
// setSearchParams({ search: searchFilter });
// };
// const applyFilter = async (searchFilter: string) => {
// await loadDataTableData({ search: searchFilter });
// setSearchParams({ search: searchFilter });
// };
const applyItems = async (
searchFilter: string,
searchFilterOrganization: string,
searchFilterSpecialities: string
) => {
await loadDataTableData({
search: searchFilter,
organization_id: searchFilterOrganization,
speciality_id: searchFilterSpecialities,
});
setSearchParamsFilter({
search: searchFilter,
organization_id: searchFilterOrganization,
speciality_id: searchFilterSpecialities,
});
};
const applyItems = async (
searchFilter: string,
searchFilterOrganization: string,
searchFilterSpecialities: string
) => {
await loadDataTableData({
search: searchFilter,
organization_id: searchFilterOrganization,
speciality_id: searchFilterSpecialities,
});
setSearchParamsFilter({
search: searchFilter,
organization_id: searchFilterOrganization,
speciality_id: searchFilterSpecialities,
});
};
const handlePageChange = (event: ChangeEvent, value: number) => {
const filter = Object.fromEntries([...searchParams.entries(), ['page', value]]);
loadDataTableData(filter);
setSearchParams(filter);
};
const handlePageChange = (event: ChangeEvent, value: number) => {
const filter = Object.fromEntries([...searchParams.entries(), ['page', value]]);
loadDataTableData(filter);
setSearchParams(filter);
};
useEffect(() => {
loadDataTableData();
}, []);
useEffect(() => {
loadDataTableData();
}, []);
return (
<Stack>
{/* <Ambulace /> */}
return (
<Stack>
{/* <Ambulace /> */}
<Card sx={{ marginTop: '30px' }}>
<FilterForm sx={{ marginTop: '100px' }} />
<Card sx={{ marginTop: '30px' }}>
<FilterForm sx={{ marginTop: '100px' }} />
{/* The Main Table */}
<TableContainer component={Paper}>
<Table>
<TableBody>
<TableRow>
{/* <TableCell colSpan={8} rowSpan={1} align="center" /> */}
<TableCell style={headStyle} align="left" />
<TableCell style={headStyle} rowSpan={2} align="left">
Nama User
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
ID Dokter
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
Rating
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
Notes
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
Created On
</TableCell>
{/* The Main Table */}
<TableContainer component={Paper}>
<Table>
</TableRow>
{/* <TableRow>
<TableCell style={headStyle} align="left" />
<TableCell style={headStyle} align="left">
Tanggal Booking
</TableCell>
<TableCell style={headStyle} align="left">
Tanggal Appointment
</TableCell>
<TableCell style={headStyle} align="left">
Faskes
</TableCell>
<TableCell style={headStyle} align="left">
Nama Dokter
</TableCell>
<TableCell style={headStyle} align="left">
Spesialisasi
</TableCell>
<TableCell style={headStyle} align="left">
Pasien
</TableCell>
<TableCell style={headStyle} align="left">
Dokter
</TableCell>
</TableRow> */}
</TableBody>
{dataTableIsLoading ? (
<TableBody>
<TableRow>
{/* <TableCell colSpan={8} rowSpan={1} align="center" /> */}
<TableCell style={headStyle} align="left" />
<TableCell style={headStyle} rowSpan={2} align="left">
ID Booking
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
ID User
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
ID Dokter
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
Nama Dokter
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
Tanggal Resep
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
Source
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
Kode Resep
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
Diagnosa
</TableCell>
<TableCell style={headStyle} rowSpan={2} align="left">
Status
<TableCell colSpan={8} align="center">
Loading
</TableCell>
</TableRow>
{/* <TableRow>
<TableCell style={headStyle} align="left" />
<TableCell style={headStyle} align="left">
Tanggal Booking
</TableCell>
<TableCell style={headStyle} align="left">
Tanggal Appointment
</TableCell>
<TableCell style={headStyle} align="left">
Faskes
</TableCell>
<TableCell style={headStyle} align="left">
Nama Dokter
</TableCell>
<TableCell style={headStyle} align="left">
Spesialisasi
</TableCell>
<TableCell style={headStyle} align="left">
Pasien
</TableCell>
<TableCell style={headStyle} align="left">
Dokter
</TableCell>
</TableRow> */}
</TableBody>
{dataTableIsLoading ? (
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">
Loading
</TableCell>
</TableRow>
</TableBody>
) : (dataTableData.data && dataTableData.data.length === 0) ? (
) : (dataTableData.data && dataTableData.data.length === 0) ? (
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">
No Data
</TableCell>
</TableRow>
</TableBody>
) : (
<TableBody>
{dataTableData && dataTableData.map((row) => (
<Row key={row.id} row={row} />
))}
</TableBody>
)}
</Table>
</TableContainer>
<TableBody>
<TableRow>
<TableCell colSpan={8} align="center">
No Data
</TableCell>
</TableRow>
</TableBody>
) : (
<TableBody>
{dataTableData && dataTableData.map((row) => (
<Row key={row.id} row={row} />
))}
</TableBody>
)}
</Table>
</TableContainer>
<BasePagination paginationData={dataTableData} onPageChange={handlePageChange} />
</Card>
</Stack>
);
<BasePagination paginationData={dataTableData} onPageChange={handlePageChange} />
</Card>
</Stack>
);
}

View File

@@ -13,6 +13,7 @@ import { AuthProvider } from '../contexts/LaravelAuthContext';
import AuthGuard from '../guards/AuthGuard';
import { Link, useParams, useSearchParams } from 'react-router-dom';
import Prescription from '@/pages/Report/Prescription/Index';
import DoctorRating from '@/pages/Report/DoctorRating/Index';
// ----------------------------------------------------------------------
@@ -290,6 +291,10 @@ export default function Router() {
path: 'report/prescription',
element: <Prescription/>,
},
{
path: 'report/doctorrating',
element: <DoctorRating/>,
},
{
path: 'report/linksehat-payments',
element: <LinksehatPayment />,

View File

@@ -20,11 +20,14 @@ export function fDateTimeSuffix(date: Date | string | number) {
export function fToNow(date: Date | string | number) {
return formatDistanceToNow(new Date(date), {
addSuffix: true
addSuffix: true,
});
}
export function fPostFormat(date: Date | string | number) {
return format(new Date(date), 'yyyy-MM-dd HH:mm:ss');
}
export function fDateOnly(date: Date | string | number) {
return format(new Date(date), 'yyyy-MM-dd');
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
{
"greeting": "Hello",
"buttonText": "Click Me",
"infoLogin": "Enter the registered account",
"txtLogin1" : "Sign in to Hospital Portal",
"txtLogin2" : "Enter your details below",
"txtCardSearchMember1" : "Guarantee Submission",
"txtCardSearchMember2" : "Find Member",
"txtCardSearchMember3" : "Date Birth",
"txtCardSearchMember4" : "Member ID",
"txtCardSearchMember5" : "Member",
"txtDialogMember1" : "Benefit Summary",
"txtDialogMember2" : "Request LOG",
"txtDialogMember3" : "Member Detail"
}

View File

@@ -0,0 +1,18 @@
<svg height="20" viewBox="0 0 28 20" width="28" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs><rect id="a" height="20" rx="3" width="28"/>
<mask id="b" fill="#fff">
<use fill="#fff" fill-rule="evenodd" xlink:href="#a"/>
</mask>
</defs>
<g fill="none" fill-rule="evenodd">
<use fill="#0a17a7" xlink:href="#a"/>
<path d="m29.2824692-1.91644623 1.4911811 2.21076686-9.4483006 6.37223314 6.6746503.0001129v6.66666663l-6.6746503-.0007795 9.4483006 6.3731256-1.4911811 2.2107668-11.9501195-8.0608924.0009836 7.4777795h-6.6666666l-.000317-7.4777795-11.9488189 8.0608924-1.49118107-2.2107668 9.448-6.3731256-6.67434973.0007795v-6.66666663l6.67434973-.0001129-9.448-6.37223314 1.49118107-2.21076686 11.9488189 8.06.000317-7.4768871h6.6666666l-.0009836 7.4768871z" fill="#fff" mask="url(#b)"/>
<g stroke="#db1f35" stroke-linecap="round" stroke-width=".667">
<path d="m18.668 6.332 12.665-8.332" mask="url(#b)"/>
<path d="m20.013 21.35 11.354-7.652" mask="url(#b)" transform="matrix(1 0 0 -1 0 35.048)"/>
<path d="m8.006 6.31-11.843-7.981" mask="url(#b)"/>
<path d="m9.29 22.31-13.127-8.705" mask="url(#b)" transform="matrix(1 0 0 -1 0 35.915)"/>
</g>
<path d="m0 12h12v8h4v-8h12v-4h-12v-8h-4v8h-12z" fill="#e6273e" mask="url(#b)"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,9 @@
<svg height="20" viewBox="0 0 28 20" width="28" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<rect id="a" height="10" rx="0" width="28"/>
</defs>
<g fill="none" fill-rule="evenodd">
<use fill="#D82028" xlink:href="#a"/>
<use fill="#FFF" xlink:href="#a" y="10"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 334 B

View File

@@ -0,0 +1,15 @@
{
"greeting": "Halo",
"buttonText": "Klik Saya",
"infoLogin": "Masukan akun yang telah terdaftar",
"txtLogin1" : "Masuk ke Hospital Portal",
"txtLogin2" : "Masukkan detail Anda di bawah ini",
"txtCardSearchMember1" : "Pengajuan Jaminan",
"txtCardSearchMember2" : "Cari Anggota",
"txtCardSearchMember3" : "Tanggal Lahir",
"txtCardSearchMember4" : "Member ID",
"txtCardSearchMember5" : "Member",
"txtDialogMember1" : "Ringkasan Manfaat",
"txtDialogMember2" : "Request LOG",
"txtDialogMember3" : "Detail Member"
}

View File

@@ -0,0 +1,9 @@
<svg height="20" viewBox="0 0 28 20" width="28" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<rect id="a" height="10" rx="0" width="28"/>
</defs>
<g fill="none" fill-rule="evenodd">
<use fill="#D82028" xlink:href="#a"/>
<use fill="#FFF" xlink:href="#a" y="10"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 334 B

View File

@@ -1,5 +1,5 @@
const getLocalizedData = async (locale) => {
const response = await fetch(`../public/lang/${locale}.json`); // Mengambil file lokal berdasarkan bahasa yang dipilih
const response = await fetch(`../public/image/${locale}.json`); // Mengambil file lokal berdasarkan bahasa yang dipilih
const data = await response.json();
return data;
};

View File

@@ -17,7 +17,7 @@ export default function Logo({ disabledLink = false, sx }: Props) {
const logo = (
<Box sx={{ width: 40, height: 40, ...sx }}>
<img src="/logo/logo-linksehat.png" alt="LinkSehat" />
<img src="/logo/logo_single.svg" alt="LinkSehat" />
</Box>
);

View File

@@ -13,12 +13,12 @@ const LANGS = [
{
label: 'Bahasa Indonesia',
value: 'id-ID',
icon: '/icons/ic_flag_id.svg',
icon: '/image/ic_flag_id.svg',
},
{
label: 'English',
value: 'en-US',
icon: '/icons/ic_flag_en.svg',
icon: '/image/ic_flag_en.svg',
},
];
@@ -53,7 +53,23 @@ export default function LanguagePopover() {
...(open && { bgcolor: 'action.selected' }),
}}
>
<Image disabledEffect src={!localStorage.getItem('currentLocale') ? LANGS[0].icon : (localStorage.getItem('currentLocale') === 'id-ID' ? LANGS[0].icon : LANGS[1].icon)} alt={!localStorage.getItem('currentLocale') ? LANGS[0].label : (localStorage.getItem('currentLocale') === 'id-ID' ? LANGS[0].label : LANGS[1].label)} />
<Image
disabledEffect
src={(
!localStorage.getItem('currentLocale')
? LANGS[0].icon
: localStorage.getItem('currentLocale') === 'id-ID'
? LANGS[0].icon
: LANGS[1].icon
)}
alt={
!localStorage.getItem('currentLocale')
? LANGS[0].label
: localStorage.getItem('currentLocale') === 'id-ID'
? LANGS[0].label
: LANGS[1].label
}
/>
</IconButtonAnimate>

View File

@@ -10,6 +10,14 @@ export default defineConfig({
// comment this out if that isn't relevant for your project
build: {
outDir: 'build',
chunkSizeWarningLimit: 100,
rollupOptions: {
onwarn(warning, warn) {
if (warning.code === 'MODULE_LEVEL_DIRECTIVE') {
return
}
warn(warning)
}}
},
plugins: [
react(),

File diff suppressed because it is too large Load Diff