update report rujukan online
This commit is contained in:
@@ -0,0 +1,243 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Internal\Http\Controllers\Api\Linksehat;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\OLDLMS\Rujukan;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Contracts\Support\Renderable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Modules\Internal\Transformers\ReportRujukanResource;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Box\Spout\Reader\Common\Creator\ReaderEntityFactory;
|
||||
use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
|
||||
|
||||
class RujukanController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
* @return Renderable
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
// return $request->toArray();
|
||||
$rujukan = Rujukan::query()
|
||||
->with(['livechat', 'livechat.user']);
|
||||
|
||||
if ($request->has('search')) {
|
||||
$search = $request->search;
|
||||
$rujukan->where(function ($query) use ($search) {
|
||||
$query->where('nID', $search)
|
||||
->orWhereHas('user', function ($detail) use ($search) {
|
||||
$detail->where('sFirstName', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('sLastName', 'LIKE', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('healthCare', function ($detail) use ($search) {
|
||||
$detail->where('sHealthCare', 'LIKE', '%' . $search . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (($request->has('rujukan_start') || $request->has('rujukan_end'))
|
||||
&& !empty($request->rujukan_start)
|
||||
&& !empty($request->rujukan_end)
|
||||
) {
|
||||
|
||||
|
||||
$rujukan = $rujukan->where(function($q) use ($request) {
|
||||
$q->where('dCreateOn', '>=', $request->rujukan_start)
|
||||
->where('dCreateOn', '<=', $request->rujukan_end);
|
||||
});
|
||||
}
|
||||
|
||||
if ($request->has('healthcare_id') && !empty($request->healthcare_id)) {
|
||||
$rujukan->where('nIDHealthCare', $request->healthcare_id);
|
||||
}
|
||||
|
||||
$rujukans = $rujukan->orderBy('dUpdateOn', 'DESC')
|
||||
->paginate();
|
||||
|
||||
return Helper::responseJson(Helper::paginateResources(ReportRujukanResource::collection($rujukans)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
* @return Renderable
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('internal::create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
* @param Request $request
|
||||
* @return Renderable
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the specified resource.
|
||||
* @param int $id
|
||||
* @return Renderable
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
return view('internal::show');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
* @param int $id
|
||||
* @return Renderable
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
return view('internal::edit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return Renderable
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
* @param int $id
|
||||
* @return Renderable
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
// Function to determine if a string is serialized
|
||||
private function is_serialized($string) {
|
||||
return ($string == 'b:0;' || @unserialize($string) !== false);
|
||||
}
|
||||
|
||||
// Function to determine if a string is JSON
|
||||
private function is_json($string) {
|
||||
json_decode($string);
|
||||
return (json_last_error() == JSON_ERROR_NONE);
|
||||
}
|
||||
|
||||
// Function to safely process the plan
|
||||
private function processPlan($sPlan) {
|
||||
if ($this->is_serialized($sPlan)) {
|
||||
$unserializedPlan = @unserialize($sPlan);
|
||||
if ($unserializedPlan !== false || $sPlan === 'b:0;') {
|
||||
return $unserializedPlan;
|
||||
}
|
||||
} elseif ($this->is_json($sPlan)) {
|
||||
$jsonPlan = json_decode($sPlan, true);
|
||||
if (json_last_error() == JSON_ERROR_NONE) {
|
||||
return $jsonPlan;
|
||||
}
|
||||
}
|
||||
return $sPlan; // Treat as plain text if not serialized or JSON
|
||||
}
|
||||
|
||||
public function generateExcel(Request $request){
|
||||
Helper::setCustomPHPIniSettings();
|
||||
|
||||
$file_name = 'Data Report Riwayat Rekam Medis';
|
||||
// Membuat penulis entitas Spout
|
||||
$writer = WriterEntityFactory::createXLSXWriter();
|
||||
// Membuka penulis untuk menulis ke file
|
||||
$writer->openToFile(public_path('files/Report-Riwayat-Rekam-Medis.xlsx'));
|
||||
$headerArray = [
|
||||
'Healthcare',
|
||||
'Patient',
|
||||
'Doctor',
|
||||
'Speciality',
|
||||
'Date',
|
||||
'Keluhan (Subjective)',
|
||||
'Pemerikasan Fisik Online (Objective)',
|
||||
'Diagnosa (Assessment)',
|
||||
'Tata Laksana (Plan)',
|
||||
];
|
||||
// Sheet 1
|
||||
$writer->getCurrentSheet()->setName('Data');
|
||||
$headers_map_to_table_fields = $headerArray;
|
||||
$headerRow = WriterEntityFactory::createRowFromArray($headers_map_to_table_fields);
|
||||
$writer->addRow($headerRow);
|
||||
$rujukans = Livechat::query()
|
||||
->with([ 'user', 'doctor', 'doctor.user', 'doctor.user.detail', 'doctor.speciality', 'appointment', 'healthCare', 'summary']);
|
||||
|
||||
if ($request->has('search')) {
|
||||
$search = $request->search;
|
||||
$rujukans->where(function ($query) use ($search) {
|
||||
$query->where('nID', $search)
|
||||
->orWhereHas('user', function ($detail) use ($search) {
|
||||
$detail->where('sFirstName', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('sLastName', 'LIKE', '%' . $search . '%');
|
||||
})
|
||||
->orWhereHas('healthCare', function ($detail) use ($search) {
|
||||
$detail->where('sHealthCare', 'LIKE', '%' . $search . '%');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (($request->has('rujukan_start') || $request->has('rujukan_end'))
|
||||
&& !empty($request->rujukan_start)
|
||||
&& !empty($request->rujukan_end)
|
||||
) {
|
||||
$rujukans = $rujukans->where(function($q) use ($request) {
|
||||
$q->where('dCreateOn', '>=', $request->rujukan_start)
|
||||
->where('dCreateOn', '<=', $request->rujukan_end);
|
||||
});
|
||||
}
|
||||
|
||||
$rujukans = $rujukans->get();
|
||||
|
||||
if ($rujukans){
|
||||
foreach ($rujukans as $index => $row) {
|
||||
$doctor_name = '-';
|
||||
if ($row->doctor && $row->doctor->user && $row->doctor->user->detail) {
|
||||
$doctor_name = $row->doctor->user->detail->sTitlePrefix . ' ' . $row->doctor->user->fullname;
|
||||
}
|
||||
$speciality = $row->doctor->speciality->sSpesialis ?? '-';
|
||||
// Process the plan
|
||||
$plan = '-';
|
||||
if ($row->summary && $row->summary->sPlan) {
|
||||
$plan = $this->processPlan($row->summary->sPlan);
|
||||
}
|
||||
|
||||
$rowData = [
|
||||
$row->healthCare ? $row->healthCare->sHealthCare : '-',
|
||||
$row->user ? $row->user->sFirstName : '-',
|
||||
$doctor_name,
|
||||
$speciality,
|
||||
$row->summary ? Carbon::parse($row->dCreateOn)->format('Y-m-d H:i:s') : '-',
|
||||
$row->summary ? $row->summary->sSubjective : '-',
|
||||
$row->summary ? $row->summary->sObjective : '-',
|
||||
$row->summary ? $row->summary->sAssessment : '-',
|
||||
is_array($plan) ? implode(', ', $plan) : $plan, // Handle arrays from unserialized or JSON data
|
||||
];
|
||||
|
||||
// Create a row from the array and add it to the writer
|
||||
$rowEntity = WriterEntityFactory::createRowFromArray($rowData);
|
||||
$writer->addRow($rowEntity);
|
||||
}
|
||||
}
|
||||
$writer->close();
|
||||
return Helper::responseJson([
|
||||
'file_name' => "Data Riwayat Log " . date('Y-m-d h:i:s'),
|
||||
"file_url" => url('files/Report-Riwayat-Rekam-Medis.xlsx')
|
||||
]);
|
||||
}
|
||||
}
|
||||
46
Modules/Internal/Transformers/ReportRujukanResource.php
Normal file
46
Modules/Internal/Transformers/ReportRujukanResource.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Internal\Transformers;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class ReportRujukanResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
$doctor_name = null;
|
||||
|
||||
if ($this->livechat->doctor && $this->livechat->doctor->user && $this->livechat->doctor->user->detail) {
|
||||
$doctor_name = $this->livechat->doctor->user->detail->sTitlePrefix . ' ' . $this->livechat->doctor->user->fullname;
|
||||
}
|
||||
|
||||
$diagnosis = null;
|
||||
$plan = null;
|
||||
|
||||
if ($this->livechat->summary){
|
||||
$diagnosis = $this->livechat->summary->sAssessment;
|
||||
$plan = $this->livechat->summary->sPlan ? unserialize($this->livechat->summary->sPlan) : $this->livechat->summary->sPlan;
|
||||
}
|
||||
// dd($this->livechat->summary);
|
||||
$data = [
|
||||
'id' => $this->nID,
|
||||
'no_rujukan' => $this->sNoRujukan ? $this->sNoRujukan : null,
|
||||
'patient_name' => $this->livechat ? $this->livechat->user->sFirstName : null,
|
||||
'healthcare' => $this->healthcare ? $this->healthcare->sHealthCare : null,
|
||||
'doctor_name' => $doctor_name,
|
||||
'departement' => $this->sDepartement ? $this->sDepartement : null,
|
||||
'date_rujukan' => $this->dCreatedOn ? Carbon::parse($this->dCreateOn)->format('Y-m-d H:i:s') : null ,
|
||||
'diagnosa' => $diagnosis,
|
||||
'plan' => $plan,
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
52
app/Models/OLDLMS/Rujukan.php
Normal file
52
app/Models/OLDLMS/Rujukan.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\OLDLMS;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Rujukan extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'nIDLivechat',
|
||||
'sNoRujukan',
|
||||
'nIDHealthcare',
|
||||
'sDepartement',
|
||||
];
|
||||
|
||||
|
||||
// public $sStatusNames = [
|
||||
// 0 => 'Menunggu Konfirmasi',
|
||||
// 1 => 'Diterima',
|
||||
// 2 => 'Ditolak',
|
||||
// 3 => 'Selesai',
|
||||
// 4 => 'Expired',
|
||||
// ];
|
||||
|
||||
const CREATED_AT = 'dCreateOn';
|
||||
const UPDATED_AT = 'dUpdateOn';
|
||||
const DELETED_AT = 'dDeleteOn';
|
||||
|
||||
protected $connection = 'oldlms';
|
||||
|
||||
protected $table = 'tx_rujukan';
|
||||
|
||||
protected $primaryKey = 'nID';
|
||||
|
||||
// protected $appends = [
|
||||
// 'status_name',
|
||||
// ];
|
||||
|
||||
public function livechat(){
|
||||
return $this->belongsTo(Livechat::class, 'nIDLivechat', 'nID');
|
||||
}
|
||||
|
||||
public function healthcare(){
|
||||
return $this->belongsTo(Healthcare::class, 'nIDHealthcare', 'nID');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
35
frontend/dashboard/src/pages/Report/Rujukan/Index.tsx
Normal file
35
frontend/dashboard/src/pages/Report/Rujukan/Index.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
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';
|
||||
|
||||
export default function LinksehatPayments() {
|
||||
const { themeStretch } = useSettings();
|
||||
|
||||
const { id } = useParams();
|
||||
|
||||
const pageTitle = 'Rujukan';
|
||||
return (
|
||||
<Page title={pageTitle}>
|
||||
<Container maxWidth={themeStretch ? false : 'xl'}>
|
||||
<HeaderBreadcrumbs
|
||||
heading={pageTitle}
|
||||
links={[
|
||||
{
|
||||
name: 'Report',
|
||||
href: '/report',
|
||||
},
|
||||
{
|
||||
name: 'Rujukan',
|
||||
href: '/report/rujukan',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<List />
|
||||
</Container>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
550
frontend/dashboard/src/pages/Report/Rujukan/List.tsx
Normal file
550
frontend/dashboard/src/pages/Report/Rujukan/List.tsx
Normal file
@@ -0,0 +1,550 @@
|
||||
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,
|
||||
InputLabel,
|
||||
Menu,
|
||||
} 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 AutocompleteHealthcare from '@/components/autocomplete/AutocompleteHealthcare';
|
||||
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 { fNumber } from '@/utils/formatNumber';
|
||||
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';
|
||||
import { DesktopDatePicker, LocalizationProvider } from '@mui/x-date-pickers';
|
||||
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
|
||||
import { MenuItem } from '@mui/material';
|
||||
import { fDateOnly, fDateTime } from '@/utils/formatTime';
|
||||
import AutocompleteLinksehatHealthcare from '@/components/autocomplete/AutocompleteLinksehatHealthcare';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import UploadIcon from '@mui/icons-material/Upload';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export default function List() {
|
||||
// Generate the every row of the table
|
||||
|
||||
const navigate = useNavigate();
|
||||
const { organization_id } = useParams();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const [organizationOptions, setOrganizationOptions] = useState([]);
|
||||
const [searchParamsPaymentStatus, setSearchParamsPaymentStatus] = useSearchParams();
|
||||
const [searchParamsOrganizations, setSearchParamsOrganizations] = useSearchParams();
|
||||
const [searchParamsSpecialities, setSearchParamsSpecialities] = useSearchParams();
|
||||
const [searchParamsFilter, setSearchParamsFilter] = useSearchParams();
|
||||
|
||||
useEffect(() => {
|
||||
// axios.get(`/search-organizations`).then((response) => {
|
||||
// setOrganizationOptions(response.data);
|
||||
// });
|
||||
}, []);
|
||||
|
||||
function Filter(props: any) {
|
||||
// SEARCH
|
||||
const searchInput = useRef<HTMLInputElement>(null);
|
||||
const [searchText, setSearchText] = useState('');
|
||||
const [importLoading, setImportLoading] = useState(false);
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
const createMenu = Boolean(anchorEl);
|
||||
|
||||
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
/* ------------------------------ handle params ----------------------------- */
|
||||
const [appliedParams, setAppliedParams] = useState({});
|
||||
const params = {
|
||||
searchParams: searchParams,
|
||||
setSearchParams: setSearchParams,
|
||||
appliedParams: appliedParams,
|
||||
setAppliedParams: setAppliedParams,
|
||||
};
|
||||
|
||||
const handleGetData = (type :string) => {
|
||||
const parameters =
|
||||
Object.keys(appliedParams).length !== 0
|
||||
? appliedParams
|
||||
: Object.fromEntries([...searchParams.entries()]);
|
||||
setImportLoading(true);
|
||||
axios.get('/linksehat/phr/generate-excel', {
|
||||
params: { ...parameters },
|
||||
}).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();
|
||||
setImportLoading(false);
|
||||
});
|
||||
// axios.get(`report/logs/export`)
|
||||
// .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();
|
||||
// })
|
||||
}
|
||||
|
||||
//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') ?? '');
|
||||
}, []);
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<form style={{ width: '100%' }}>
|
||||
<Grid container spacing={2} sx={{ justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Grid item md={7}>
|
||||
<TextField
|
||||
id="search-input"
|
||||
ref={searchInput}
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
onChange={handleSearchChange}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
// handleSearchSubmit(event);
|
||||
|
||||
const filter = Object.fromEntries([
|
||||
...searchParams.entries(),
|
||||
['search', searchText],
|
||||
]);
|
||||
setSearchParams(filter);
|
||||
loadDataTableData(filter);
|
||||
}
|
||||
}}
|
||||
label="Search"
|
||||
value={searchText}
|
||||
InputProps={{
|
||||
// startAdornment: (
|
||||
// <InputAdornment position="start">
|
||||
// <Search />
|
||||
// </InputAdornment>
|
||||
// ),
|
||||
placeholder: 'Nama Pasien',
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item md={2}>
|
||||
<LocalizationProvider dateAdapter={AdapterDateFns}>
|
||||
<DesktopDatePicker
|
||||
value={searchParams.get('livechat_start')}
|
||||
inputFormat="dd/MM/yyyy"
|
||||
onChange={(value) => {
|
||||
try {
|
||||
if (value && !!Date.parse(value)) {
|
||||
const date = value ? fDateOnly(value) : '';
|
||||
var entries = [...searchParams.entries(), ['livechat_start', date ?? '']];
|
||||
if (!searchParams.get('livechat_end')) {
|
||||
entries = [...entries, ['livechat_end', date ?? '']];
|
||||
}
|
||||
const filter = Object.fromEntries(entries);
|
||||
|
||||
setSearchParams(filter);
|
||||
loadDataTableData(filter);
|
||||
}
|
||||
} catch (e) {}
|
||||
}}
|
||||
renderInput={(params) => <TextField {...params} fullWidth label="Start" />}
|
||||
/>
|
||||
</LocalizationProvider>
|
||||
</Grid>
|
||||
|
||||
<Grid item md={2}>
|
||||
<LocalizationProvider dateAdapter={AdapterDateFns}>
|
||||
<DesktopDatePicker
|
||||
value={searchParams.get('livechat_end')}
|
||||
inputFormat="dd/MM/yyyy"
|
||||
onChange={(value) => {
|
||||
try {
|
||||
if (value && !!Date.parse(value)) {
|
||||
const date = fDateOnly(value);
|
||||
var entries = [...searchParams.entries(), ['livechat_end', date ?? '']];
|
||||
if (!searchParams.get('livechat_start')) {
|
||||
entries = [...entries, ['livechat_start', 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 md={1}>
|
||||
<LoadingButton
|
||||
variant="outlined"
|
||||
startIcon={<UploadIcon />}
|
||||
sx={{ p: 1.8 }}
|
||||
onClick={handleClick}
|
||||
loading={importLoading}
|
||||
>
|
||||
Export
|
||||
</LoadingButton>
|
||||
<Menu
|
||||
id="import-button"
|
||||
anchorEl={anchorEl}
|
||||
open={createMenu}
|
||||
onClose={handleClose}
|
||||
MenuListProps={{
|
||||
'aria-labelledby': 'basic-button',
|
||||
}}
|
||||
>
|
||||
<MenuItem onClick={() => {handleGetData('')}}>Download Excel</MenuItem>
|
||||
</Menu>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
function FilterForm(props: any) {
|
||||
// IMPORT
|
||||
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>
|
||||
);
|
||||
}
|
||||
|
||||
//TODO Create PaymentType
|
||||
function createData(payments: any): any {
|
||||
return {
|
||||
...payments,
|
||||
};
|
||||
}
|
||||
|
||||
function Row(props: { row: ReturnType<typeof createData> }) {
|
||||
const { row } = props;
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const [openDialog, setOpenDialog] = React.useState(false);
|
||||
|
||||
const handleDelete = (model: any) => {
|
||||
axios
|
||||
.delete(`/doctors/${row.id}`)
|
||||
.then((res) => {
|
||||
setDataTableData({
|
||||
...dataTableData,
|
||||
data: dataTableData.data.filter((model) => model.id != row.id),
|
||||
});
|
||||
enqueueSnackbar('Data berhasil dihapus', { variant: 'success' });
|
||||
})
|
||||
.catch((error) => {
|
||||
enqueueSnackbar(
|
||||
error.response.data.message ?? error.message ?? 'Failed Processing Request',
|
||||
{ variant: 'error' }
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<TableRow>
|
||||
<TableCell align="left">{row.healthcare ?? '-'}</TableCell>
|
||||
<TableCell align="left">{row.patient_name ?? '-'}</TableCell>
|
||||
<TableCell align="left">{row.doctor_name ?? '-'}</TableCell>
|
||||
<TableCell align="left">{row.specialis ?? '-' }</TableCell>
|
||||
<TableCell align="left">{row.date_consultation ? fDateTime(row.date_consultation) : '-'}</TableCell>
|
||||
<TableCell align="left">{row.subject ?? '-'}</TableCell>
|
||||
<TableCell align="left">{row.object ?? '-'}</TableCell>
|
||||
<TableCell align="left">{row.assessment ?? '-'}</TableCell>
|
||||
<TableCell align="left">{row.plan ?? '-'}</TableCell>
|
||||
{/* <TableCell align="center">
|
||||
<ButtonGroup variant="text" aria-label="text button group">
|
||||
<Link to={'/report/appointments/' + row.id + '/show'}>
|
||||
<Button>
|
||||
<Icon icon="ph:eye-bold" style={{ width: '24px', height: '24px' }} />
|
||||
</Button>
|
||||
</Link>
|
||||
</ButtonGroup>
|
||||
</TableCell> */}
|
||||
</TableRow>
|
||||
|
||||
<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('/linksehat/phr', {
|
||||
params: filter,
|
||||
});
|
||||
setDataTableLoading(false);
|
||||
setDataTableData(response.data.data);
|
||||
};
|
||||
|
||||
// const applyFilter = async (searchFilter: string) => {
|
||||
// await loadDataTableData({ search: searchFilter });
|
||||
// setSearchParams({ search: searchFilter });
|
||||
// };
|
||||
|
||||
const applyItems = async (
|
||||
searchFilter: string,
|
||||
searchFilterOrganization: string,
|
||||
searchFilterPaymentStatus: string,
|
||||
searchFilterAppointmentStart: string,
|
||||
searchFilterAppointmentEnd: string
|
||||
) => {
|
||||
await loadDataTableData({
|
||||
search: searchFilter,
|
||||
organization_id: searchFilterOrganization,
|
||||
payment_status: searchFilterPaymentStatus,
|
||||
livechat_start: searchFilterAppointmentStart,
|
||||
livechat_end: searchFilterAppointmentEnd,
|
||||
});
|
||||
setSearchParamsFilter({
|
||||
search: searchFilter,
|
||||
organization_id: searchFilterOrganization,
|
||||
payment_status: searchFilterPaymentStatus,
|
||||
livechat_start: searchFilterAppointmentStart,
|
||||
livechat_end: searchFilterAppointmentEnd,
|
||||
});
|
||||
};
|
||||
|
||||
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 style={headStyle} align="left">
|
||||
Healthcare
|
||||
</TableCell>
|
||||
<TableCell style={headStyle} align="left">
|
||||
Patient
|
||||
</TableCell>
|
||||
<TableCell style={headStyle} align="left">
|
||||
Doctor
|
||||
</TableCell>
|
||||
<TableCell style={headStyle} align="left">
|
||||
Speciality
|
||||
</TableCell>
|
||||
<TableCell style={headStyle} align="left">
|
||||
Date
|
||||
</TableCell>
|
||||
<TableCell style={headStyle} align="left">
|
||||
Subjective
|
||||
</TableCell>
|
||||
<TableCell style={headStyle} align="left">
|
||||
Objective
|
||||
</TableCell>
|
||||
<TableCell style={headStyle} align="left">
|
||||
Assessment
|
||||
</TableCell>
|
||||
<TableCell style={headStyle} align="left">
|
||||
Plan
|
||||
</TableCell>
|
||||
|
||||
|
||||
{/* <TableCell style={headStyle} align="center">
|
||||
Aksi
|
||||
</TableCell> */}
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
{dataTableIsLoading ? (
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell colSpan={8} align="center">
|
||||
Loading
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
) : dataTableData.data.length == 0 ? (
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell colSpan={8} align="center">
|
||||
No Data
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
) : (
|
||||
<TableBody>
|
||||
{dataTableData.data.map((row) => (
|
||||
<Row key={row.nID} row={row} />
|
||||
))}
|
||||
</TableBody>
|
||||
)}
|
||||
</Table>
|
||||
</TableContainer>
|
||||
|
||||
<BasePagination paginationData={dataTableData} onPageChange={handlePageChange} />
|
||||
</Card>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user