diff --git a/frontend/dashboard/src/pages/Master/Drug/Index.tsx b/frontend/dashboard/src/pages/Master/Drug/Index.tsx index 0e0f9aba..91393b10 100644 --- a/frontend/dashboard/src/pages/Master/Drug/Index.tsx +++ b/frontend/dashboard/src/pages/Master/Drug/Index.tsx @@ -1,7 +1,7 @@ import { Card } from "@mui/material"; import HeaderBreadcrumbs from "../../../components/HeaderBreadcrumbs"; import Page from "../../../components/Page"; -import List from "./List2"; +import List from "./List"; diff --git a/frontend/dashboard/src/pages/Master/Drug/List.tsx b/frontend/dashboard/src/pages/Master/Drug/List.tsx index 95eecc22..4ab5105a 100644 --- a/frontend/dashboard/src/pages/Master/Drug/List.tsx +++ b/frontend/dashboard/src/pages/Master/Drug/List.tsx @@ -1,310 +1,579 @@ // @mui -import { Box, Button, Card, Collapse, IconButton, InputLabel, MenuItem, OutlinedInput, Paper, Select, SelectChangeEvent, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Typography, Badge, Tab, Tabs, CardHeader, Stack, Menu, ButtonGroup, Pagination } from '@mui/material'; -import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; -import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; -import AddIcon from '@mui/icons-material/Add'; -import UploadIcon from '@mui/icons-material/Upload'; -import CancelIcon from '@mui/icons-material/Cancel'; -// hooks -import React, { ChangeEvent, Component, useEffect, useRef, useState } from 'react'; -import useSettings from '../../../hooks/useSettings'; -import { useParams, useSearchParams } from 'react-router-dom'; -// components -import axios from '../../../utils/axios'; -import { LaravelPaginatedData } from '../../../@types/paginated-data'; -import { Icd } from '../../../@types/diagnosis'; -import BasePagination from '../../../components/BasePagination'; -import { enqueueSnackbar } from 'notistack'; +import { + Button, + Card, + IconButton, + MenuItem, + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + TextField, + Typography, + Stack, + Collapse, + Box, + FormControl, + InputLabel, + Select, + FormHelperText, + Menu, + ButtonGroup, + } from '@mui/material'; + import AddIcon from '@mui/icons-material/Add'; + // hooks + import React, { ChangeEvent, useEffect, useRef, useState } from 'react'; + import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; + // components + import axios from '../../../utils/axios'; + import { Drug } from '../../../@types/pharmacy-and-delivery-managements'; + import { LaravelPaginatedData } from '../../../@types/paginated-data'; + import BasePagination from '../../../components/BasePagination'; + import TableMoreMenu from '@/components/table/TableMoreMenu'; + import EditOutlinedIcon from '@mui/icons-material/EditOutlined'; + import HistoryIcon from '@mui/icons-material/History'; + import FindInPageOutlinedIcon from '@mui/icons-material/FindInPageOutlined'; + import CachedOutlinedIcon from '@mui/icons-material/CachedOutlined'; + import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material'; + import CloseIcon from '@mui/icons-material/Close'; + import { enqueueSnackbar } from 'notistack'; + import Label from '../../../components/Label'; + import UploadIcon from '@mui/icons-material/Upload'; + import CancelIcon from '@mui/icons-material/Cancel'; + import DownloadIcon from '@mui/icons-material/Download'; + import { LoadingButton } from '@mui/lab'; + -export default function List() { - const { themeStretch } = useSettings(); + export default function DrugList() { const { corporate_id } = useParams(); const [searchParams, setSearchParams] = useSearchParams(); const [importResult, setImportResult] = useState(null); - + const navigate = useNavigate(); + function SearchInput(props: any) { - // SEARCH - const searchInput = useRef(null); - const [searchText, setSearchText] = useState(""); + // SEARCH + const searchInput = useRef(null); + const [searchText, setSearchText] = useState(''); - const handleSearchChange = (event: any) => { - const newSearchText = event.target.value ?? '' + const handleSearchChange = (event: any) => { + const newSearchText = event.target.value ?? ''; setSearchText(newSearchText); - } + }; - const handleSearchSubmit = (event: any) => { + const handleSubmit = (event: any) => { event.preventDefault(); props.onSearch(searchText); // Trigger to Parent - } + }; - useEffect(() => { // Trigger First Search + useEffect(() => { setSearchText(searchParams.get('search') ?? ''); - }, [searchParams]) + }, [searchParams]); - return ( -
- + return ( + + - ); - } - - function ImportForm(props: any) { - // IMPORT - // Create Button Menu - const [anchorEl, setAnchorEl] = React.useState(null); - const createMenu = Boolean(anchorEl); - const importForm = useRef(null) - const [currentImportFileName, setCurrentImportFileName] = useState(null) - - const handleClick = (event: React.MouseEvent) => { - setAnchorEl(event.currentTarget); - }; - - const handleClose = () => { - setAnchorEl(null); - }; - - const handleImportButton = () => { - if (importForm?.current) { - handleClose(); - importForm.current ? importForm.current.click() : console.log('No File selected'); - } else { - alert('No file selected') - } - } - - const handleCancelImportButton = () => { - importForm.current.value = ""; - importForm.current.dispatchEvent(new Event("change", { bubbles: true })); - } - - const handleImportChange = (event: any) => { - if (event.target.files[0]) { - setCurrentImportFileName(event.target.files[0].name) - } else { - setCurrentImportFileName(null); - } - } - - const handleUpload = () => { - if (importForm.current?.files.length) { - const formData = new FormData(); - formData.append("file", importForm.current?.files[0]) - axios.post(`corporates/${corporate_id}/import-plan-benefit`, formData ) - .then(response => { - handleCancelImportButton(); - loadDataTableData(); - setImportResult(response.data) - // alert('Succesfully read '+ response.data.total_successed_row + ' with ' + response.data.total_failed_row + ' failed rows'); - }) - .catch(response => { - enqueueSnackbar('Looks like something went wrong. Please check your data and try again. ' + response.message, { variant: 'error' }) - }) - } else { - enqueueSnackbar('No File Selected', { variant: 'warning' }) - } - } - - return ( -
- - {( !currentImportFileName && - - - - Import - Download Template - - - )} - - {( currentImportFileName && - - - - - - - - )} - {( importResult && - - Last Import Result Report : {importResult.result_file?.name ?? "-"} - - )} -
- ); + ); } // Called on every row to map the data to the columns - function createData( icd: Icd ): Icd { - return { - ...icd, - } + function createData(drug: Drug): Drug { + return { + ...drug, + }; } + function ImportForm(props: any) { + // IMPORT + // Create Button Menu + const [anchorEl, setAnchorEl] = React.useState(null); + const createMenu = Boolean(anchorEl); + const importPlan = useRef(null); + const [currentImportFileName, setCurrentImportFileName] = useState(null); + const [importLoading, setImportLoading] = useState(false); + + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + + const handleClose = () => { + setAnchorEl(null); + }; + + const handleImportButton = () => { + if (importPlan?.current) { + handleClose(); + importPlan.current ? importPlan.current.click() : console.log('No File selected'); + } else { + alert('No file selected'); + } + }; + + const handleCancelImportButton = () => { + if(importPlan.current) + { + importPlan.current.value = ''; + importPlan.current.dispatchEvent(new Event('change', { bubbles: true })); + } + }; + + const handleImportChange = (event: any) => { + if (event.target.files[0]) { + setCurrentImportFileName(event.target.files[0].name); + } else { + setCurrentImportFileName(null); + } + }; + + const handleUpload = () => { + if(importPlan.current && importPlan.current.files) + { + if (importPlan.current?.files.length) { + const formData = new FormData(); + formData.append('file', importPlan.current?.files[0]); + setImportLoading(true); + axios + .post(`master/drugs/${corporate_id}/import`, formData) + .then((response) => { + handleCancelImportButton(); + loadDataTableData(); + setImportResult(response.data); + console.log(response.data); + setImportLoading(false); + }) + .catch((response) => { + enqueueSnackbar( + 'Looks like something went wrong. Please check your data and try again. ' + + response.message, + { variant: 'error' } + ); + setImportLoading(false); + }); + } else { + enqueueSnackbar('No File Selected', { variant: 'warning' }); + } + } + }; + + const handleGetTemplate = () => { + axios.get('master/drugs/download-template').then((response) => { + const link = document.createElement('a'); + link.href = response.data.data.file_url; + link.setAttribute('download', response.data.data.file_name); + document.body.appendChild(link); + link.click(); + handleClose(); + }); + }; + + return ( +
+ + {!currentImportFileName && ( + + + + + + Import + + { + handleGetTemplate(); + }} + > + Download Template + + {/* + Download ICD + */} + + + )} + + {currentImportFileName && ( + + + + + + + } + sx={{ p: 1.8 }} + onClick={handleUpload} + loading={importLoading} + > + Upload + + + )} + {importResult && ( + + + Last Import Result :{' '} + + {importResult.data.total_success_row ?? 0} + {' '} + Row Processed,{' '} + + {importResult.data.total_failed_row} + {' '} + Failed + {importResult.data.failed_rows.map((row, index) => ( + [Code=>{row.code ? row.code : 'Required'},Name=>{row.name ? row.name : 'Required'}] + ))} + + + )} +
+ ); + } // Generate the every row of the table function Row(props: { row: ReturnType }) { - const { row } = props; - const [open, setOpen] = React.useState(false); + const { row } = props; + const [open, setOpen] = React.useState(false); + const style1 = { + color: '#637381' + } - return ( + return ( - *': { borderBottom: 'unset' } }}> - - setOpen(!open)} - > - {open ? : } - + *': open ? {borderBottom: 'unset'} : {}, cursor: open ? 'pointer' : '' }} onClick={() => {if(open==true) setOpen(!open)}}> + {row.type ? row.type : '-'} + {row.code ? row.code : '-'} + {row.name ? row.name : '-'} + {row.version ? row.version : '-'} + + {row.active === 1 ? ( + + ) : ( + + )} + + + + setOpen(!open)}> + + Details + + {/* handleEditData(row)}> + + Edit + */} + handleEditDataStatus(row)}> + + Update Status + + {/* navigate ('/corporates/'+corporate_id+'/hospitals/'+row.id+'/history')}> + + History + */} + + } + /> - {row.type} - {row.code} - {row.name} - {row.version} - - - - - {/* COLLAPSIBLE ROW */} - - - - - - Description : {row.description} - - - + + {/* COLLAPSIBLE ROW */} + {if(open==true) setOpen(!open)}}> + + + + + Detail + + + Code: + {row.code ? row.code : '-'} + + + Name: + {row.name ? row.name : '-'} + + + + + - + - ); + ); } // Dummy Default Data - const [dataTableIsLoading, setDataTableLoading] = useState(true); - const [dataTableLastRequest, setDataTableLastRequest] = useState(0); - const [dataTableResponseState, setDataTableResponseState] = useState('idle'); - const [dataTableData, setDataTableData] = useState({ - 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 [dataTableIsLoading, setDataTableLoading] = React.useState(true); + const [dataTableData, setDataTableData] = React.useState({ + 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('/master/drugs', { params: filter }); - // console.log(response.data); - setDataTableLoading(false); - - setDataTableData(response.data); - } - - const headStyle = { - fontWeight: 'bold', + const loadDataTableData = async (appliedFilter: any | null = null) => { + setDataTableLoading(true); + const filter = appliedFilter ? appliedFilter : Object.fromEntries([...searchParams.entries()]); + // Get Data Drugs + const response = await axios.get('/master/drugs', { params: filter }); + setDataTableLoading(false); + setDataTableData(response.data); }; - const applyFilter = async (searchFilter: string) => { - await loadDataTableData({ "search" : searchFilter }); - setSearchParams({ "search" : searchFilter }); - } + const applyFilter = async (searchFilter: any) => { + await loadDataTableData({ search: searchFilter }); + setSearchParams({ search: searchFilter }); + }; - 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(); - }, []) - - return ( - - + loadDataTableData(); + }, []); - - {/* The Main Table */} - - - - - - Type - Code - Name - Version - Status - Action - - - {dataTableIsLoading ? - ( - + //validation dialog + const [nameField, setNameField] = useState(''); + const [codeField, setCodeField] = useState(''); + // ID for edit data + const [idField, setIdField] = useState(''); + + const handleAddData = () => { + navigate('/corporates/'+corporate_id+'/hospitals/create'); + } + //Edit data + const handleEditData = (data : any) => { + navigate('/corporates/'+corporate_id+'/hospitals/edit/'+data.id+'/'+data.organization_id); + } + // End dialog for hospitals + + // Dialog for update status hospitals + const [openDialogStatus, setOpenDialogStatus] = useState(false); + const [activeField, setActiveField] = useState(0); + const [reasonUpdate,setReasonUpdate] = useState('Agreement changed'); + + const handleCloseDialogUpdate = () => { + setOpenDialogStatus(false); + setNameField(''); + setCodeField(''); + setIdField(''); + setActiveField(activeField); + } + + const handleSaveUpdateData = () => { + let activeValue = 0; + if(activeField === 1) + { + activeValue = 0; + } + else + { + activeValue = 1; + } + const updateData = { + reason: reasonUpdate, + active : activeValue, + id: idField, + }; + axios + .put('/master/drugs/'+idField+'/activation', updateData) + .then((response) => { + enqueueSnackbar('Data updated successfully', { variant: 'success' }); + loadDataTableData(); + handleCloseDialogUpdate(); + }) + .catch((error) => { + enqueueSnackbar('Failed to add data', { variant: 'error' }); + }); + } + + const handleEditDataStatus = (data: any) => { + setIdField(data.id); + setNameField(data.name); + setCodeField(data.code); + setActiveField(data.active); + setOpenDialogStatus(true); + } + // End dialog for update status devisions + + + + return ( + + + + {/* The Main Table */} + +
+ {/* Table Head */} + - Loading + + Type + + + Code + + + Name + + + Version + + + Status + + + - - ) : ( - dataTableData.data.length == 0 ? - ( + + {/* Condition Table Body */} + {dataTableIsLoading ? ( - - No Data - + + + Loading + + - ) : ( + ) : dataTableData.data.length == 0 ? ( - {dataTableData.data.map(row => ( + + + No Data + + + + ) : ( + + {dataTableData.data.map((row) => ( - ))} + ))} - ) - )} -
-
- - -
-
+ )} + + + {/* Paginations */} + + + {/* Dialog Update Status */} + + + + + Update Status + + + + + + + + + Are you sure to {activeField == 1 ? 'Inactive' : 'Active'} this drug ? + + + Code + {nameField} + + + Name + {codeField} + + + + + Reason for update* + + + Reason for update + + + + + + + + + + + + + ); -} + } \ No newline at end of file