969 lines
49 KiB
TypeScript
Executable File
969 lines
49 KiB
TypeScript
Executable File
/* ---------------------------------- @mui ---------------------------------- */
|
|
import { styled } from '@mui/material/styles';
|
|
import {
|
|
Paper,
|
|
Table as TableContent,
|
|
TableBody,
|
|
TableCell,
|
|
TableContainer,
|
|
TableHead,
|
|
TableRow,
|
|
TextField,
|
|
Button,
|
|
TableSortLabel,
|
|
Box,
|
|
Card,
|
|
Checkbox,
|
|
Grid,
|
|
FormControl,
|
|
InputLabel,
|
|
Select,
|
|
MenuItem,
|
|
SelectChangeEvent,
|
|
Stack,
|
|
Typography,
|
|
LinearProgress,
|
|
linearProgressClasses,
|
|
Collapse,
|
|
Divider,
|
|
IconButton,
|
|
Modal,
|
|
CircularProgress
|
|
} from '@mui/material';
|
|
|
|
import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material';
|
|
import { visuallyHidden } from '@mui/utils';
|
|
|
|
import { DatePicker, LocalizationProvider, MobileDatePicker } from '@mui/x-date-pickers';
|
|
|
|
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
|
|
|
|
import { fDate, fDateSuffix, fDateTime, fDateTimeWithAge } from '../utils/formatTime';
|
|
/* ---------------------------------- axios --------------------------------- */
|
|
import axios from '../utils/axios';
|
|
/* ---------------------------------- react --------------------------------- */
|
|
import { Fragment, useContext, useEffect, useState } from 'react';
|
|
import { useSearchParams } from 'react-router-dom';
|
|
/* -------------------------------- component ------------------------------- */
|
|
import BaseTablePagination from './BaseTablePagination';
|
|
/* ---------------------------------- theme --------------------------------- */
|
|
import palette from '../theme/palette';
|
|
/* ---------------------------------- utils --------------------------------- */
|
|
import { UserCurrentCorporateContext } from '../contexts/UserCurrentCorporate';
|
|
import { fSplit } from '../utils/formatNumber';
|
|
import { Download, Search as SearchIcon, Upload } from '@mui/icons-material';
|
|
/* ---------------------------------- types --------------------------------- */
|
|
import { DivisionDataProps, Order, PaginationTableProps, TableListProps } from '../@types/table';
|
|
import { InputAdornment } from '@mui/material';
|
|
import GetAppIcon from '@mui/icons-material/GetApp';
|
|
import { LanguageContext } from '@/contexts/LanguageContext';
|
|
import CancelIcon from '@mui/icons-material/Cancel';
|
|
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
|
import CloseIcon from '@mui/icons-material/Close';
|
|
import InfoIcon from '@mui/icons-material/Info';
|
|
import { enqueueSnackbar } from 'notistack';
|
|
import useAuth from '@/hooks/useAuth';
|
|
|
|
/* --------------------------------- styled --------------------------------- */
|
|
const BorderLinearProgress = styled(LinearProgress)(({ theme }) => ({
|
|
height: 10,
|
|
borderRadius: 6,
|
|
[`&.${linearProgressClasses.colorPrimary}`]: {
|
|
backgroundColor: '#D1F1F1',
|
|
},
|
|
[`& .${linearProgressClasses.bar}`]: {
|
|
borderRadius: 6,
|
|
backgroundColor: theme.palette.primary.main,
|
|
},
|
|
}));
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
export default function Table<T>({
|
|
headCells,
|
|
rows,
|
|
paginations,
|
|
orders,
|
|
loadings,
|
|
params,
|
|
filters,
|
|
filterStatus,
|
|
filterStartDate,
|
|
filterEndDate,
|
|
searchs,
|
|
exportReport,
|
|
selected,
|
|
openRowId, // Receive the currently opened row ID
|
|
setOpenRowId, // Receive the function to set the opened row ID
|
|
reloadData,
|
|
}: TableListProps<T>) {
|
|
/* ------------------------------- handle sort ------------------------------ */
|
|
const handleRequestSort = async (event: React.MouseEvent<unknown>, property: string) => {
|
|
const isAsc = orders?.orderBy === property && orders?.order === 'asc';
|
|
|
|
orders?.setOrder(isAsc ? 'desc' : 'asc');
|
|
orders?.setOrderBy(property);
|
|
const parameters = Object.fromEntries([
|
|
...params.searchParams.entries(),
|
|
['order', isAsc ? 'desc' : 'asc'],
|
|
['orderBy', property],
|
|
]);
|
|
params.setAppliedParams(parameters);
|
|
};
|
|
|
|
const { localeData }: any = useContext(LanguageContext);
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
/* -------------------------- enchanced table head -------------------------- */
|
|
const EnhancedTableHead = () => {
|
|
const createSortHandler = (property: string) => (event: React.MouseEvent<unknown>) => {
|
|
handleRequestSort(event, property);
|
|
};
|
|
|
|
return (
|
|
<TableHead>
|
|
<TableRow>
|
|
{selected.useSelected && selected.selectedRows.length > 0 ? (
|
|
<>
|
|
<TableCell style={{ backgroundColor: '#D1F1F1', }} align="left" colSpan={selected.totRows} sx={{ padding: 2 }}>
|
|
<Grid container alignItems="center" justifyContent="space-between">
|
|
<Grid item>
|
|
<Stack direction="row" alignItems="center">
|
|
<Checkbox checked={selected.selectAll} onChange={selected.handleSelectAll} />
|
|
<Typography variant='subtitle2'>
|
|
{selected.selectedRows.length > 0 ? selected.selectedRows.length : '0'} {localeData.txtSelected}
|
|
</Typography>
|
|
</Stack>
|
|
</Grid>
|
|
<Grid item>
|
|
<Stack direction="row" spacing={2}>
|
|
{selected.useDecline ? (
|
|
<Button variant="text" color="error" startIcon={<CancelIcon />} onClick={() => {selected.setOpenDialogSubmit(true);selected.setValDialog('decline');}}>
|
|
<Typography variant='subtitle2'>{selected.txtDecline}</Typography>
|
|
</Button>
|
|
):''}
|
|
<Button variant="text" color="primary" startIcon={<CheckCircleIcon />} onClick={() => {selected.setOpenDialogSubmit(true);selected.setValDialog('approve');}}>
|
|
<Typography variant='subtitle2'>{selected.txtApprove}</Typography>
|
|
</Button>
|
|
</Stack>
|
|
</Grid>
|
|
</Grid>
|
|
</TableCell>
|
|
</>
|
|
):(
|
|
<>
|
|
{selected.useSelected ? (
|
|
<TableCell>
|
|
<Checkbox checked={selected.selectAll} onChange={selected.handleSelectAll} />
|
|
</TableCell>
|
|
):''}
|
|
{headCells &&
|
|
headCells.map((headCell, index) => (
|
|
<TableCell
|
|
key={index}
|
|
sortDirection={orders?.orderBy === headCell.id ? orders.order : false}
|
|
// @ts-ignore
|
|
align={headCell.align}
|
|
sx={{ padding: 2 }}
|
|
width={headCell.width ? headCell.width : 'auto'}
|
|
>
|
|
{headCell.isSort ? (
|
|
<TableSortLabel
|
|
active={orders?.orderBy === headCell.id}
|
|
direction={orders?.orderBy === headCell.id ? orders.order : 'asc'}
|
|
onClick={createSortHandler(headCell.id)}
|
|
>
|
|
{headCell.label}
|
|
{orders?.orderBy === headCell.id ? (
|
|
<Box component="span" sx={visuallyHidden}>
|
|
{orders.order === 'desc' ? 'sorted descending' : 'sorted ascending'}
|
|
</Box>
|
|
) : null}
|
|
</TableSortLabel>
|
|
) : (
|
|
headCell.label
|
|
)}
|
|
</TableCell>
|
|
))}
|
|
</>
|
|
|
|
)}
|
|
|
|
|
|
</TableRow>
|
|
</TableHead>
|
|
);
|
|
};
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
/* ------------------------ button change pagination ------------------------ */
|
|
const onPageChangeHandle = async (
|
|
event: React.MouseEvent<HTMLButtonElement> | null,
|
|
newPage: number
|
|
) => {
|
|
const parameters = Object.fromEntries([
|
|
...params.searchParams.entries(),
|
|
['page', newPage + 1],
|
|
['per_page', paginations.rowsPerPage]
|
|
]);
|
|
paginations.setPage(newPage);
|
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
params.setAppliedParams(parameters);
|
|
};
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
/* --------------------------- row page per limit --------------------------- */
|
|
const onRowsPerPageChangeHandle = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
params.searchParams.delete('page');
|
|
const parameters = Object.fromEntries([
|
|
...params.searchParams.entries(),
|
|
['per_page', parseInt(event.target.value, 10)],
|
|
]);
|
|
|
|
paginations.setPage(0);
|
|
paginations.setRowsPerPage(parseInt(event.target.value, 10));
|
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
params.setAppliedParams(parameters);
|
|
};
|
|
/* -------------------------------------------------------------------------- */
|
|
//============================== APOTEK =======================================//
|
|
const {user} = useAuth();
|
|
const formattedRoleName = user?.role.name;
|
|
// List of statuses for 'apotek'
|
|
const allowedStatusesForApotek = ['waiting_pharmacy', 'order_prepared'];
|
|
const allowedStatusesForCSLMS = ['ready', 'waiting_for_courir', 'package_picked_up', 'package_on_delivery'];
|
|
|
|
const [open, setOpen] = useState(false);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
const handleClick = () => {
|
|
// handleClickKonfirmasi(row); // Call the function passed from parent
|
|
setOpen(true); // Show modal
|
|
setLoading(true); // Show loading animation
|
|
|
|
// Simulate finding driver (3 seconds delay)
|
|
setTimeout(() => {
|
|
setLoading(false); // Hide loading after 3 seconds
|
|
}, 3000);
|
|
};
|
|
|
|
|
|
|
|
const [openDialogStatus, setOpenDialogStatus] = useState(false);
|
|
const [dialogIDRow, setDialogIDRow] = useState<number | null>(null);
|
|
const [dialogIDRowDriver, setDialogIDRowDriver] = useState<number | null>(null);
|
|
const [txtStatusDriver, setTxtStatusDriver] = useState('');
|
|
const [txtIDDriver, setTxtIDDriver] = useState('');
|
|
const handleClose = (row:any) => {
|
|
setDialogIDRowDriver(row.id === dialogIDRowDriver ? null : row.id);
|
|
if (reloadData) {
|
|
reloadData();
|
|
}
|
|
};
|
|
const handleCloseDialogUpdate = () => {
|
|
setOpenDialogStatus(false);
|
|
}
|
|
const handleEditDataStatus = (data: any) => {
|
|
setOpenDialogStatus(true);
|
|
}
|
|
const [isDisabled, setIsDisabled] = useState(false);
|
|
const handleClickKonfirmasi = (row: any) => {
|
|
setTxtStatusDriver('');
|
|
setTxtIDDriver('');
|
|
if(row.sStatus === 'ready')
|
|
{
|
|
//close
|
|
setDialogIDRow(row.id === dialogIDRow ? null : row.id);
|
|
//get driver
|
|
setDialogIDRowDriver(row.id === dialogIDRowDriver ? null : row.id);
|
|
// setOpen(true); // Show modal
|
|
setLoading(true); // Show loading animation
|
|
|
|
// Simulate finding driver (3 seconds delay)
|
|
// setTimeout(() => {
|
|
// setLoading(false); // Hide loading after 3 seconds
|
|
// }, 3000);
|
|
|
|
const updateData = {
|
|
sStatus: row.sStatus
|
|
};
|
|
|
|
axios
|
|
.put(`/put-driver-prescription-orders/${row.nID_orders}`, updateData)
|
|
.then((response) => {
|
|
setTxtStatusDriver(response?.data?.data?.status);
|
|
setTxtIDDriver(response?.data?.data?.deliveryID);
|
|
setLoading(false);
|
|
// enqueueSnackbar(response?.data?.meta?.message, { variant: 'success' });
|
|
|
|
// Call reloadData to refresh the table
|
|
|
|
})
|
|
.catch((error) => {
|
|
const errorMessage = error.response?.data?.meta?.message || 'Failed to update status';
|
|
enqueueSnackbar(errorMessage, { variant: 'error' });
|
|
setLoading(false);
|
|
setIsDisabled(false); // Re-enable the button after success
|
|
});
|
|
}
|
|
else
|
|
{
|
|
putPrescriptionOrders(row);
|
|
}
|
|
}
|
|
const putPrescriptionOrders = (row: any) => {
|
|
setIsDisabled(true); // Disable button after clicking
|
|
const updateData = {
|
|
sStatus: row.sStatus
|
|
};
|
|
axios
|
|
.put(`/put-prescription-orders/${row.nID_orders}`, updateData)
|
|
.then((response) => {
|
|
enqueueSnackbar(response?.data?.meta?.message, { variant: 'success' });
|
|
setDialogIDRow(row.id === dialogIDRow ? null : row.id);
|
|
setIsDisabled(false); // Re-enable the button after success
|
|
|
|
// Call reloadData to refresh the table
|
|
if (reloadData) {
|
|
reloadData();
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
const errorMessage = error.response?.data?.meta?.message || 'Failed to update status';
|
|
enqueueSnackbar(errorMessage, { variant: 'error' });
|
|
setIsDisabled(false); // Re-enable the button after success
|
|
});
|
|
}
|
|
return (
|
|
// <Card>
|
|
<Grid container>
|
|
{/* Field 1 */}
|
|
<Grid item xs={12} paddingX="24px" paddingY="20px">
|
|
<Grid container spacing={2}>
|
|
{filters && filters.useFilter ? (
|
|
<Fragment>
|
|
<Grid item xs={12} lg={3} xl={2}>
|
|
<FormControl fullWidth>
|
|
<InputLabel id="simple-division-select-lable">Division</InputLabel>
|
|
<Select
|
|
labelId="simple-division-select-lable"
|
|
id="division-select-lable"
|
|
value={filters.config.divisionValue}
|
|
label="Division"
|
|
onChange={filters.config.handleDivisionChange}
|
|
>
|
|
<MenuItem value="all">All</MenuItem>
|
|
{filters.config.divisionData.map((row: DivisionDataProps, index) => (
|
|
<MenuItem key={index} value={row.id}>
|
|
{row.name}
|
|
</MenuItem>
|
|
))}
|
|
</Select>
|
|
</FormControl>
|
|
</Grid>
|
|
<Grid item xs={12} lg={9} xl={10}>
|
|
<form onSubmit={searchs.handleSearchSubmit}>
|
|
<TextField
|
|
id="search-input"
|
|
label="Search"
|
|
variant="outlined"
|
|
onChange={(event) => searchs.setSearchText(event.target.value)}
|
|
value={searchs.searchText}
|
|
fullWidth
|
|
/>
|
|
</form>
|
|
</Grid>
|
|
</Fragment>
|
|
) : null }
|
|
|
|
{searchs && searchs.useSearchs ? (
|
|
<Fragment>
|
|
{filterStatus && filterStatus.useFilter ? (
|
|
<Grid item xs={12} lg={10} xl={10}>
|
|
<form onSubmit={searchs.handleSearchSubmit}>
|
|
<TextField
|
|
id="search-input"
|
|
variant="outlined"
|
|
onChange={(event) => searchs.setSearchText(event.target.value)}
|
|
value={searchs.searchText}
|
|
fullWidth
|
|
InputProps={{
|
|
startAdornment: (
|
|
<InputAdornment position="start">
|
|
<SearchIcon />
|
|
</InputAdornment>
|
|
),
|
|
}}
|
|
placeholder={localeData.txtSearch}
|
|
/>
|
|
</form>
|
|
</Grid>
|
|
) :
|
|
<Grid item xs={12} lg={6} xl={6}>
|
|
<form onSubmit={searchs.handleSearchSubmit}>
|
|
<TextField
|
|
id="search-input"
|
|
variant="outlined"
|
|
onChange={(event) => searchs.setSearchText(event.target.value)}
|
|
value={searchs.searchText}
|
|
fullWidth
|
|
InputProps={{
|
|
startAdornment: (
|
|
<InputAdornment position="start">
|
|
<SearchIcon />
|
|
</InputAdornment>
|
|
),
|
|
}}
|
|
placeholder={localeData.txtSearch}
|
|
/>
|
|
</form>
|
|
</Grid>
|
|
}
|
|
|
|
</Fragment>
|
|
) : null }
|
|
|
|
{/* Start date */}
|
|
{filterStartDate && filterStartDate.useFilter ? (
|
|
<Grid item xs={12} lg={2} xl={2}>
|
|
{/* <form onChange={(event) => filterStartDate.handleStartDateChange(event)}>
|
|
<TextField
|
|
id="date-input"
|
|
type="date"
|
|
variant="outlined"
|
|
value={filterStartDate.startDate}
|
|
fullWidth
|
|
label="Start Date"
|
|
InputLabelProps={{
|
|
shrink: true,
|
|
}}
|
|
/>
|
|
</form> */}
|
|
<LocalizationProvider dateAdapter={AdapterDateFns}>
|
|
<DatePicker
|
|
label={localeData.txtStartDate}
|
|
value={filterStartDate.startDate}
|
|
onChange={(newValue:any) => {
|
|
filterStartDate.setStartDate( (newValue));
|
|
}}
|
|
inputFormat="dd-MM-yyyy"
|
|
renderInput={(params) => <TextField sx={{width:'40%'}} {...params} required/>}
|
|
/>
|
|
</LocalizationProvider>
|
|
</Grid>
|
|
) : null }
|
|
|
|
{/* End Date */}
|
|
|
|
{filterEndDate && filterEndDate.useFilter ? (
|
|
<Grid item xs={12} lg={2} xl={2}>
|
|
{/* <form onChange={(event) => filterEndDate.handleEndDateChange(event)}>
|
|
<TextField
|
|
id="date-input"
|
|
type="date"
|
|
variant="outlined"
|
|
value={filterEndDate.endDate}
|
|
fullWidth
|
|
label="End Date"
|
|
InputLabelProps={{
|
|
shrink: true,
|
|
}}
|
|
/>
|
|
</form> */}
|
|
<LocalizationProvider dateAdapter={AdapterDateFns}>
|
|
<DatePicker
|
|
label={localeData.txtEndDate}
|
|
value={filterEndDate.endDate}
|
|
onChange={(newValue:any) => {
|
|
filterEndDate.setEndDate( (newValue));
|
|
}}
|
|
inputFormat="dd-MM-yyyy"
|
|
renderInput={(params) => <TextField sx={{width:'40%'}} {...params} required/>}
|
|
/>
|
|
</LocalizationProvider>
|
|
</Grid>
|
|
) : null }
|
|
|
|
{/* Filter status */}
|
|
{filterStatus && filterStatus.useFilter ? (
|
|
<Grid item xs={12} lg={2} xl={2}>
|
|
<FormControl fullWidth>
|
|
<InputLabel id="simple-status-select-lable">Status</InputLabel>
|
|
<Select
|
|
labelId="simple-status-select-lable"
|
|
id="status-select-lable"
|
|
value={filterStatus.config.statusValue}
|
|
label="Status"
|
|
onChange={filterStatus.config.handleStatusChange}
|
|
>
|
|
<MenuItem value="all">{localeData.txtAll}</MenuItem>
|
|
{filterStatus.config.filterData.map((row: StatusDataProps, index) => (
|
|
<MenuItem key={index} value={row.id}>
|
|
{row.name}
|
|
</MenuItem>
|
|
))}
|
|
</Select>
|
|
</FormControl>
|
|
</Grid>
|
|
) : null }
|
|
|
|
{/* Export Report */}
|
|
|
|
{exportReport && exportReport.useExport ? (
|
|
<Grid item xs={12} lg={2} xl={2}>
|
|
<FormControl fullWidth>
|
|
<Button variant='contained' sx={{p:2}}>
|
|
<Download />
|
|
<Typography variant='inherit' sx={{marginLeft: 1}}>Export</Typography>
|
|
</Button>
|
|
</FormControl>
|
|
</Grid>
|
|
) : null }
|
|
|
|
</Grid>
|
|
</Grid>
|
|
{/* End Field 1 */}
|
|
{/* Field 2 */}
|
|
<Grid item xs={12}>
|
|
{/* Table */}
|
|
<TableContainer component={Paper}>
|
|
<TableContent aria-label="collapsible table" size="small">
|
|
{/* Table Header */}
|
|
<EnhancedTableHead />
|
|
{/* End Table Header */}
|
|
{/* Table Body */}
|
|
<TableBody>
|
|
{loadings.isLoading ? (
|
|
<TableRow>
|
|
<TableCell colSpan={headCells?.length} align="center">
|
|
Loading . . .
|
|
</TableCell>
|
|
</TableRow>
|
|
) : rows && rows.length >= 1 ? (
|
|
rows.map((row, rowIndex) => (
|
|
<>
|
|
<TableRow key={rowIndex}>
|
|
{!selected.useSelected ? (
|
|
''
|
|
): (selected.useSelected && row.check_status === 'approved' && !row.check_claim ? (
|
|
<TableCell>
|
|
<Checkbox
|
|
checked={selected.selectedRows.includes(row.id)}
|
|
onChange={() => selected.handleCheckboxChange(row.id)}
|
|
/>
|
|
</TableCell>
|
|
):(
|
|
<TableCell>
|
|
|
|
</TableCell>
|
|
))}
|
|
{headCells &&
|
|
//@ts-ignore
|
|
headCells.map((head, headIndex) => (
|
|
//@ts-ignore
|
|
<TableCell align={head.align} key={headIndex}>
|
|
{row[head.id]}
|
|
</TableCell>
|
|
))}
|
|
</TableRow>
|
|
{/* COLLAPSIBLE ROW */}
|
|
<TableRow
|
|
sx={{ cursor: 'pointer' }} // Use pointer cursor always, or conditionally based on your preference
|
|
>
|
|
<TableCell colSpan={6}>
|
|
<Collapse in={openRowId === row.id} timeout="auto" unmountOnExit>
|
|
<Card sx={{padding:2}}>
|
|
{/* Icon inside a Box for spacing and alignment */}
|
|
<Stack direction="row" padding={2} justifyContent="space-between" alignItems="center">
|
|
<Stack direction="row">
|
|
<Box sx={{ display: 'flex', alignItems: 'center', marginRight: 1 }}>
|
|
<InfoIcon sx={{ color: row.sStatus == 'waiting_pharmacy' ? '#D3D3D3' : '#00E676', fontSize: 24 }} /> {/* Adjust size and color */}
|
|
</Box>
|
|
<Typography variant='subtitle2' sx={{ color: '#00E676' }}>
|
|
{row.status}
|
|
</Typography>
|
|
</Stack>
|
|
|
|
{row.nDeliveryID && (
|
|
<Box sx={{ ml: 'auto' }}>
|
|
<Typography variant='subtitle2'>
|
|
Grab Delivery ID: {row.nDeliveryID}
|
|
</Typography>
|
|
</Box>
|
|
)}
|
|
</Stack>
|
|
|
|
<Box onClick={() => {setOpenRowId(openRowId === row.id ? null : row.id);}} sx={{ padding: '20px', maxWidth: '1200px', margin: '0 auto', backgroundColor: '#ffffff', borderRadius: '8px' }}>
|
|
<Grid container spacing={2}>
|
|
|
|
{/* Row 1 */}
|
|
<Grid item xs={12} md={6}>
|
|
<Typography variant="h6" fontWeight="bold">{localeData.txtProviderDoctorInformation}</Typography>
|
|
<Grid container>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtNamaDokter} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.nama_dokter}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtSpesialisasiDokter} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.spesialis}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">SIP :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.sip}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtNoPonsel} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.no_ponsel_dokter}</strong></Typography>
|
|
</Grid>
|
|
</Grid>
|
|
</Grid>
|
|
|
|
<Grid item xs={12} md={6}>
|
|
<Typography variant="h6" fontWeight="bold">{localeData.txtInformasiPasien}</Typography>
|
|
<Grid container>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtNamaPasien} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.pasien}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtTanggalLahirUmur} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.tgl_lahir_pasien ? fDateTimeWithAge(row.tgl_lahir_pasien) : ''}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtJenisKelamin} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.jenis_kelamin_pasien}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtTinggi} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.tinggi_berat}</strong></Typography>
|
|
</Grid>
|
|
</Grid>
|
|
</Grid>
|
|
|
|
{/* Divider */}
|
|
<Grid item xs={12}>
|
|
<Divider />
|
|
</Grid>
|
|
|
|
<Grid item xs={12} md={6}>
|
|
<Typography variant="h6" fontWeight="bold">{localeData.txtInformasiAsuransi}</Typography>
|
|
<Grid container>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtNomorKartu} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.no_polis}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtAsuransi} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.perusahaan_asuransi}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtPerusahaan} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.nama_perusahaan}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtTipeAsuransi} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.kode_produk}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtKelasAsuransi} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.kelas_asuransi}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtTipeMember} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.tipe_member}</strong></Typography>
|
|
</Grid>
|
|
</Grid>
|
|
</Grid>
|
|
|
|
<Grid item xs={12} md={6}>
|
|
<Typography variant="h6" fontWeight="bold">{localeData.txtInformasiOrder}</Typography>
|
|
<Grid container>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtNamaPenerima} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.pasien}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtAlamatPenerima} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.alamat_penerima}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtPengiriman} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.pengiriman}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtTotal} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.total_kirim}</strong></Typography>
|
|
</Grid>
|
|
</Grid>
|
|
</Grid>
|
|
|
|
{/* Divider */}
|
|
<Grid item xs={12}>
|
|
<Divider />
|
|
</Grid>
|
|
|
|
{/* Row 2 */}
|
|
<Grid item xs={12} md={6}>
|
|
<Typography variant="h6" fontWeight="bold">{localeData.txtInformasiResep}</Typography>
|
|
<Grid container>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtNomorResep} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.no_resep}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtNomorRefDokter} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.noref_dokter}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtTanggalTerbitResep} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.tanggal}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtTanggalKedaluwarsa} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.valid_tanggal}</strong></Typography>
|
|
</Grid>
|
|
</Grid>
|
|
</Grid>
|
|
|
|
<Grid item xs={12} md={6}>
|
|
<Typography variant="h6" fontWeight="bold">{localeData.txtInformasiKonsultasi}</Typography>
|
|
<Grid container>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtNomorPenjamin} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.nomor_penjamin}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtTanggalKonsultasi} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.tgl_livechat}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtAlergi} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.alergi_desc}</strong></Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2">{localeData.txtDiagnosis} :</Typography>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<Typography variant="body2"><strong>{row.diagnosa}</strong></Typography>
|
|
</Grid>
|
|
</Grid>
|
|
</Grid>
|
|
|
|
</Grid>
|
|
</Box>
|
|
|
|
<Box onClick={() => {setOpenRowId(openRowId === row.id ? null : row.id);}} sx={{ padding: '20px', maxWidth: '1200px', margin: '20px auto', backgroundColor: '#ffffff', borderRadius: '8px' }}>
|
|
<TableHead>
|
|
<TableRow>
|
|
<TableCell>{localeData.txtObat}</TableCell>
|
|
<TableCell align="left">{localeData.txtSigna}</TableCell>
|
|
<TableCell align="left">{localeData.txtWaktu}</TableCell>
|
|
<TableCell align="left">{localeData.txtDurasi}</TableCell>
|
|
<TableCell align="left">{localeData.txtJumlah}</TableCell>
|
|
<TableCell align="left">{localeData.txtCatatanObat}</TableCell>
|
|
</TableRow>
|
|
</TableHead>
|
|
<TableBody>
|
|
{row.prescription_items ?
|
|
(
|
|
row.prescription_items.map((row : any, rowIndex: any) => (
|
|
<TableRow key={rowIndex}>
|
|
<TableCell>{row.sItemName}</TableCell>
|
|
<TableCell align="left">{row.sSigna}</TableCell>
|
|
<TableCell align="left">{row.sTiming}</TableCell>
|
|
<TableCell align="left">{row.sDuration}</TableCell>
|
|
<TableCell align="left">{row.nQty}</TableCell>
|
|
<TableCell align="left">{row.sNote}</TableCell>
|
|
</TableRow>
|
|
))
|
|
) : (
|
|
<TableRow>
|
|
<TableCell colSpan={headCells?.length} align="center">
|
|
{localeData.txtDataNotFound}
|
|
</TableCell>
|
|
</TableRow>
|
|
)}
|
|
</TableBody>
|
|
</Box>
|
|
|
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', padding: '20px', maxWidth: '1200px', margin: '0 auto' }}>
|
|
{/* Close Button on the Left */}
|
|
<Button variant="outlined" color="inherit" onClick={() => setOpenRowId(null)}>
|
|
{localeData.txtButtonClose}
|
|
</Button>
|
|
{/* Accept Button on the Right */}
|
|
{row.button_accept && formattedRoleName === 'admin-apotek' && allowedStatusesForApotek.includes(row.sStatus) ? (
|
|
<Button variant="contained" color="primary" onClick={() => setDialogIDRow(row.id === dialogIDRow ? null : row.id)}>
|
|
{row.button_accept}
|
|
</Button>
|
|
) : ''}
|
|
{row.button_accept && formattedRoleName === 'cs-lms' && allowedStatusesForCSLMS.includes(row.sStatus) ? (
|
|
<Button variant="contained" color="primary" onClick={() => setDialogIDRow(row.id === dialogIDRow ? null : row.id)}>
|
|
{row.button_accept}
|
|
</Button>
|
|
) : ''}
|
|
</Box>
|
|
|
|
|
|
|
|
{/* Dialog Update Status */}
|
|
<Dialog open={dialogIDRow === row.id} fullWidth={true}>
|
|
<DialogTitle sx={{ backgroundColor: '#19BBBB', color: '#FFF', padding: 2 }}>
|
|
<Stack direction="row" alignItems="center" justifyContent="space-between">
|
|
<Stack direction="row" alignItems='center' spacing={1}>
|
|
<Typography variant="h6">{localeData.txtConfirmation}</Typography>
|
|
</Stack>
|
|
<IconButton sx={{ color: '#FFF' }} onClick={() => setDialogIDRow(row.id === dialogIDRow ? null : row.id)}>
|
|
<CloseIcon />
|
|
</IconButton>
|
|
</Stack>
|
|
</DialogTitle>
|
|
<DialogContent>
|
|
<Stack spacing={2} padding={2}>
|
|
<Typography variant='body1'>{localeData.txtDialogConfirmation}</Typography>
|
|
<Card sx={{padding:2}} >
|
|
<Stack direction='row' spacing={2}>
|
|
<Typography variant='subtitle2' sx={{color: '#919EAB', width: '50%'}}>{localeData.txtNomorResep}</Typography>
|
|
<Typography variant='subtitle2' sx={{width: '50%'}}>{row.no_resep}</Typography>
|
|
</Stack>
|
|
<Stack direction='row' spacing={2}>
|
|
<Typography variant='subtitle2' sx={{color: '#919EAB', width: '50%'}}>{localeData.txtTanggalTerbitResep}</Typography>
|
|
<Typography variant='subtitle2' sx={{width: '50%'}}>{row.tanggal}</Typography>
|
|
</Stack>
|
|
</Card>
|
|
</Stack>
|
|
</DialogContent>
|
|
<DialogActions>
|
|
<Button sx={{backgroundColor: '#19BBBB'}} variant="contained" onClick={() => handleClickKonfirmasi(row)} disabled={isDisabled}>{localeData.txtOK}</Button>
|
|
</DialogActions>
|
|
</Dialog>
|
|
{/* Modal for fullscreen display */}
|
|
<Modal open={dialogIDRowDriver === row.id} onClose={() => handleClose(row)}>
|
|
<Box
|
|
sx={{
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
height: '100vh',
|
|
// backgroundColor: 'rgba(0, 0, 0, 0.8)', // semi-transparent background
|
|
color: '#fff',
|
|
textAlign: 'center',
|
|
}}
|
|
>
|
|
{loading ? (
|
|
<>
|
|
<CircularProgress color="inherit" />
|
|
<Typography variant="h6" sx={{ mt: 2 }}>
|
|
{localeData.txtFindingDriver}
|
|
</Typography>
|
|
</>
|
|
) : (
|
|
<>
|
|
<Typography variant="h4">Info!</Typography>
|
|
<Typography variant="h6" sx={{ mt: 2 }}>
|
|
{txtIDDriver ? (
|
|
`${localeData.txtDriverFound} ${txtIDDriver} status ${txtStatusDriver}.`
|
|
) : (
|
|
// You can add an alternative UI or message here, or leave it empty
|
|
`Failed to get driver, please check the message info.`
|
|
)}
|
|
|
|
|
|
</Typography>
|
|
<Button
|
|
sx={{ mt: 4, backgroundColor: '#19BBBB' }}
|
|
variant="contained"
|
|
onClick={() => handleClose(row)}
|
|
>
|
|
{localeData.txtOK}
|
|
</Button>
|
|
</>
|
|
)}
|
|
</Box>
|
|
</Modal>
|
|
</Card>
|
|
</Collapse>
|
|
</TableCell>
|
|
</TableRow>
|
|
</>
|
|
))
|
|
) : (
|
|
<TableRow>
|
|
<TableCell colSpan={headCells?.length} align="center">
|
|
{localeData.txtDataNotFound}
|
|
</TableCell>
|
|
</TableRow>
|
|
)}
|
|
</TableBody>
|
|
{/* End Table Body */}
|
|
</TableContent>
|
|
</TableContainer>
|
|
{/* End Table */}
|
|
|
|
{/* Pagination */}
|
|
<BaseTablePagination
|
|
count={paginations.paginationTable.total}
|
|
onPageChange={onPageChangeHandle}
|
|
page={paginations.page}
|
|
rowsPerPage={paginations.rowsPerPage}
|
|
onRowsPerPageChange={onRowsPerPageChangeHandle}
|
|
/>
|
|
{/* End Pagination */}
|
|
</Grid>
|
|
{/* End Field 2 */}
|
|
</Grid>
|
|
// </Card>
|
|
);
|
|
}
|