diff --git a/Modules/Internal/Http/Controllers/Api/ClaimController.php b/Modules/Internal/Http/Controllers/Api/ClaimController.php index 5b33b40c..a7e214b8 100644 --- a/Modules/Internal/Http/Controllers/Api/ClaimController.php +++ b/Modules/Internal/Http/Controllers/Api/ClaimController.php @@ -34,6 +34,9 @@ use Modules\Internal\Transformers\RequestLogResource; use App\Models\RequestLog; +use ZipArchive; +use File; + use PDF; class ClaimController extends Controller @@ -91,13 +94,13 @@ class ClaimController extends Controller // (SELECT plans.code FROM plans WHERE plans.id = member_plans.plan_id LIMIT 1) AS plan_code // '), DB::raw(' - (SELECT plans.code - FROM plans + (SELECT plans.code + FROM plans WHERE plans.id IN ( - SELECT member_plans.plan_id - FROM member_plans + SELECT member_plans.plan_id + FROM member_plans WHERE member_plans.member_id = claim_requests.member_id - ) + ) AND plans.service_code = claim_requests.service_code) AS plan_code '), DB::raw(' @@ -116,13 +119,103 @@ class ClaimController extends Controller 'claim_requests.status_claim_management as status', ) ->paginate($limit); - + return response()->json(Helper::paginateResources($results)); } - public function downloadTemplate() + public function filesProvider(Request $request) + { + $limit = $request->has('per_page') ? $request->input('per_page') : 50; + $results = DB::table('request_logs') + ->leftJoin('members', 'request_logs.member_id', '=', 'members.id') + ->join('files', 'request_logs.id', '=', 'files.fileable_id') + // ->leftJoin('member_plans', 'member_plans.member_id', '=', 'members.id') + ->when($request->input('search'), function ($query, $search) { + $query->where(function ($query) use ($search) { + $query->orWhere('members.name', 'like', "%" . $search . "%"); + $query->orWhere('request_logs.code', 'like', "%" . $search . "%"); + $query->orWhere('members.member_id', 'like', "%" . $search . "%"); + }); + }) + ->when($request->has('orderBy'), function ($query) use ($request) { + $orderBy = $request->orderBy; + $direction = $request->order ?? 'asc'; + + $query->orderBy($orderBy, $direction); + }) + ->when($request->input('start_date') , function ($query, $start_date) { + $query->where(function ($query) use ($start_date) { + $query->where('request_logs.created_at', '>=', $start_date. ' 00:00:00'); + }); + }) + ->when($request->input('end_date') , function ($query, $end_date) { + $query->where(function ($query) use ($end_date) { + $query->where('request_logs.created_at', '<=', $end_date. ' 23:59:59'); + }); + }) + ->when($request->input('provider') , function ($query, $provider) { + $query->where(function ($query) use ($provider) { + $query->where('request_logs.organization_id', '=', $provider); + }); + }) + ->where('files.fileable_type', '=', 'App\Models\RequestLog') + ->where('request_logs.final_log', '=', '1') + ->where('request_logs.status_final_log', '=', 'approved') + ->select( + 'files.original_name as files', + 'files.id', + 'files.id AS id_log', + 'request_logs.code as code', + 'members.name', + 'request_logs.created_at', + DB::raw(' + (SELECT organizations.name FROM organizations WHERE organizations.id = request_logs.organization_id LIMIT 1) AS provider + '), + 'request_logs.status_final_log as status', + DB::raw("CONCAT('" . env('APP_URL') . "/storage/', path) as path") + ) + ->paginate($limit); + + + + return response()->json(Helper::paginateResources($results)); + } + + public function downloadZip(Request $request) + { + $selectedRows = $request->selectedRows; // asumsi $selectedRows berisi array ID file yang dipilih + $files = []; + + // Ambil path file dari database atau sumber lain sesuai dengan $selectedRows + $data = DB::table('files') + ->whereIn('id', $selectedRows) + ->select('path') + ->get(); + + foreach ($data as $value) { + $files[] = storage_path('app/public/' . $value->path); + } + + $zipFileName = 'downloaded_files.zip'; + $zip = new ZipArchive(); + + if ($zip->open(storage_path('app/public/' . $zipFileName), ZipArchive::CREATE | ZipArchive::OVERWRITE)) { + foreach ($files as $file) { + $zip->addFile($file, basename($file)); + } + + $zip->close(); + + // Mengembalikan response berupa URL file zip + return response()->json(['file_url' => env('APP_URL').Storage::url($zipFileName)], 200); + } else { + return response()->json(['message' => 'Gagal membuat file ZIP.'], 500); + } + } + + public function downloadTemplate() { return Helper::responseJson([ 'file_name' => "Template - Claim - Management.xlsx", @@ -155,7 +248,7 @@ class ClaimController extends Controller 'approval_by_claim_management' => auth()->user()->id, 'approval_date_claim_management' => date('Y-m-d H:i:s'), ]); - + if ($affectedRows === 0) { $check_status = DB::table('claim_requests') ->where('code','=', $row['code']) @@ -183,16 +276,16 @@ class ClaimController extends Controller $row['error'] = $e->getMessage(); if(!$row['code']) { - $row['error'] = 'Kolom Code wajib isi'; + $row['error'] = 'Kolom Code wajib isi'; } if(!$row['qc']) { - $row['error'] = 'Kolom QC wajib isi'; + $row['error'] = 'Kolom QC wajib isi'; } $result_rows[] = $row; $failedRows[] = $row; } - } + } $response = [ 'message' => 'File uploaded and data saved to database', @@ -217,7 +310,7 @@ class ClaimController extends Controller $row[] = $data[0][$i]; $header[] = $data[0][0]; } - + $filed = []; foreach ($header[0] as $value) { @@ -228,18 +321,18 @@ class ClaimController extends Controller $filed[] = $modelColumn; } } - + $result = []; foreach ($row as $subarray) { $trimmedSubarray = []; for ($i = 0; $i < count($filed); $i++) { $trimmedSubarray[$filed[$i]] = $subarray[$i] ? $subarray[$i] : null; } - + $result[] = $trimmedSubarray; } return $result; - } + } public function exportClaimManagement(Request $request) { @@ -314,13 +407,13 @@ class ClaimController extends Controller '), 'claim_requests.created_at', DB::raw(' - (SELECT plans.code - FROM plans + (SELECT plans.code + FROM plans WHERE plans.id IN ( - SELECT member_plans.plan_id - FROM member_plans + SELECT member_plans.plan_id + FROM member_plans WHERE member_plans.member_id = claim_requests.member_id - ) + ) AND plans.service_code = claim_requests.service_code) AS plan_code '), // DB::raw(' @@ -391,7 +484,7 @@ class ClaimController extends Controller ->setCellAlignment(CellAlignment::LEFT) // ->setBackgroundColor(Color::YELLOW) ->build(); - + $footerRow = WriterEntityFactory::createRowFromArray($footer, $style); $writer->addRow($footerRow); @@ -426,10 +519,10 @@ class ClaimController extends Controller $headerRow = WriterEntityFactory::createRowFromArray($header, $style); $writer->addRow($headerRow); // ============================ - + foreach($request->params as $item) { - + $rowData = [ $item['code'], $item['qc'], @@ -461,7 +554,7 @@ class ClaimController extends Controller ->setCellAlignment(CellAlignment::LEFT) // ->setBackgroundColor(Color::YELLOW) ->build(); - + $footerRow = WriterEntityFactory::createRowFromArray($footer, $style); $writer->addRow($footerRow); diff --git a/Modules/Internal/Routes/api.php b/Modules/Internal/Routes/api.php index 320b5501..52bfb748 100644 --- a/Modules/Internal/Routes/api.php +++ b/Modules/Internal/Routes/api.php @@ -238,6 +238,8 @@ Route::prefix('internal')->group(function () { Route::post('claims/{claim_id}/set-final-encounter', [ClaimEncounterController::class, 'setFinalEncounter']); Route::get('claims', [ClaimController::class, 'index']); + Route::get('claims-files-provider', [ClaimController::class, 'filesProvider']); + Route::post('download-zip', [ClaimController::class, 'downloadZip']); Route::get('claims/download-template', [ClaimController::class, 'downloadTemplate']); Route::post('claims/import', [ClaimController::class, 'import']); Route::post('claims/exportFiled/', [ClaimController::class, 'exportFiled']); @@ -281,20 +283,20 @@ Route::prefix('internal')->group(function () { Route::post('customer-service/request/{id}/delete_file', [RequestLogController::class, 'deleteFiles']); Route::post('customer-service/request/final-log', [RequestLogController::class, 'updateFinalLog']); - + // search diagnosis Route::get('diagnosis', [RequestLogController::class, 'diagnosis']); - + // insert benefit Route::post('customer-service/request/insert-benefit', [RequestLogBenefitController::class, 'store']); Route::post('customer-service/request/benefit_data/{id}', [RequestLogBenefitController::class, 'destroy']); Route::put('customer-service/request/benefit_data/{id}', [RequestLogBenefitController::class, 'update']); - + // insert medicine Route::post('customer-service/request/medicine-data', [RequestLogMedicineController::class, 'store']); Route::delete('customer-service/request/medicine-data/{id}', [RequestLogMedicineController::class, 'destroy']); Route::put('customer-service/request/medicine-data/{id}', [RequestLogMedicineController::class, 'update']); - + Route::get('search-organizations', [OrganizationController::class, 'searchOrganization']); Route::get('search-specialities', [SpecialityController::class, 'searchSpeciality']); Route::resource('organizations', OrganizationController::class); diff --git a/Modules/Internal/Transformers/RequestLogShowResource.php b/Modules/Internal/Transformers/RequestLogShowResource.php index 1591701a..89f7e458 100644 --- a/Modules/Internal/Transformers/RequestLogShowResource.php +++ b/Modules/Internal/Transformers/RequestLogShowResource.php @@ -42,7 +42,7 @@ class RequestLogShowResource extends JsonResource $claimCode = $claimRequest->code; $isReversal = false; $isRole = auth()->user()->role_id; - if ($requestLog['status'] == 'approved' && + if ($requestLog['status'] == 'approved' && $requestLog['status_final_log'] == 'approved' && $claimRequest->status == 'approved' && $claimRequest->status_claim_management == 'approved' && @@ -108,7 +108,7 @@ class RequestLogShowResource extends JsonResource ->whereIn('code', $diagnosis) ->select('code', 'name') ->get(); - } + } $data = [ 'id' => $requestLog['id'], diff --git a/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx b/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx index 17334caf..73c6570f 100644 --- a/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx +++ b/frontend/dashboard/src/layouts/dashboard/navbar/NavConfig.tsx @@ -95,6 +95,7 @@ const navConfig = [ { title: 'REPORT', children: [ + { title: 'Files Provider', path: 'report/files-provider'}, { title: 'Letter of Guarantee', path: '/report/logs' }, { title: 'Appointment', path: '/report/appointments' }, { title: 'Live Chat', path: '/report/live-chat' }, diff --git a/frontend/dashboard/src/pages/CustomerService/FinalLog/Detail.tsx b/frontend/dashboard/src/pages/CustomerService/FinalLog/Detail.tsx index 02a158e7..55a6066d 100644 --- a/frontend/dashboard/src/pages/CustomerService/FinalLog/Detail.tsx +++ b/frontend/dashboard/src/pages/CustomerService/FinalLog/Detail.tsx @@ -45,7 +45,7 @@ import DialogHospitalCare from './Components/DialogHospitalCare'; import DialogBenefit from './Components/DialogBenefit'; import DialogMedicine from './Components/DialogMedicine'; import DialogDeleteBenfit from './Components/DialogDeleteBenefit'; -import DialogEditBenefit from './Components/DialogEditBenefit'; +import DialogEditBenefit from './Components/DialogEditBenefit'; import DialogDeleteMedicine from './Components/DialogDeleteMedicine' import MoreMenu from '@/components/MoreMenu'; @@ -69,7 +69,7 @@ export default function Detail() { const { themeStretch } = useSettings(); const [requestLog, setRequestLog] = useState(); const [isReversal, setIsReversal] = useState(false); - + const { id } = useParams(); @@ -111,7 +111,7 @@ export default function Detail() { // Handel Delete Detail Benefit const [idBenefitData, setIdBenefitData] = useState(); const [openDialogDeleteBenefit, setDialogDeleteBenefit] = useState(false) - + const [idMedicineData, setIdMedicineData] = useState(); const [openDialogDeleteMedicine, setDialogDeleteMedicine] = useState(false) @@ -121,7 +121,7 @@ export default function Detail() { const [openDialogEditBenefit, setDialogEditBenefit] = useState(false) const [BenefitConfigurationData, setBenefitConfigurationData] = useState(); - // Buat total data + // Buat total data const totalAmountIncurred = (requestLog?.benefit_data || []).reduce((accumulator, item) => { return accumulator + (item.amount_incurred || 0); }, 0); @@ -134,13 +134,13 @@ export default function Detail() { const totalExcessPaid = (requestLog?.benefit_data || []).reduce((accumulator, item) => { return accumulator + (item.excess_paid || 0); }, 0); - + const total = { totalAmountIncurred : totalAmountIncurred, totalAmountApproved : totalAmountApprove, totalAmountNotApproved : totalAmountNotApprove, totalExcessPaid : totalExcessPaid, - } + } // Handle Delete File LOG const [pathFile, setPathFile] = useState('') const [dialogDeleteFIleLog, setDialogDeleteFileLog] = useState(false) @@ -159,7 +159,7 @@ export default function Detail() { {/* Detail */} - + Detail @@ -180,7 +180,7 @@ export default function Detail() { } /> ) : null } - + Provider @@ -265,16 +265,16 @@ export default function Detail() { {/* Service */} - - + {/* Exclusion */} - {/* */} @@ -297,7 +297,7 @@ export default function Detail() { {requestLog?.benefit_data?.map((item, index) => ( - + @@ -422,14 +422,14 @@ export default function Detail() { - + ))}

{requestLog?.benefit_data && requestLog.benefit_data.length > 0 ? ( - + @@ -438,7 +438,7 @@ export default function Detail() { Total Benefit - + @@ -511,13 +511,13 @@ export default function Detail() { - + - ) + ) : ( null - )} + )} {/* PR Buat pindahin ke componen */} @@ -530,7 +530,7 @@ export default function Detail() { requestLog={requestLog} openDialog={openDialogBenefit} setOpenDialog={setDialogBenefit} - + /> {/* Dialog Edit */} {/* Dialog Delete */} - {/* Dialog Edit Detai; */} - ) : null } - + {requestLog?.files?.map((documentType, index) => ( @@ -640,7 +640,7 @@ export default function Detail() { ) : null } - + ))} @@ -696,7 +696,7 @@ export default function Detail() { ) : null} - + diff --git a/frontend/dashboard/src/pages/Report/FilesProvider/Index.tsx b/frontend/dashboard/src/pages/Report/FilesProvider/Index.tsx new file mode 100644 index 00000000..d3de2a44 --- /dev/null +++ b/frontend/dashboard/src/pages/Report/FilesProvider/Index.tsx @@ -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 Index() { + const { themeStretch } = useSettings(); + + const { id } = useParams(); + + const pageTitle = 'Files Provider'; + return ( + + + + + + + + ); +} diff --git a/frontend/dashboard/src/pages/Report/FilesProvider/List.tsx b/frontend/dashboard/src/pages/Report/FilesProvider/List.tsx new file mode 100644 index 00000000..6dffa607 --- /dev/null +++ b/frontend/dashboard/src/pages/Report/FilesProvider/List.tsx @@ -0,0 +1,999 @@ +// @mui +import { + Box, + Grid, + Button, + Card, + Collapse, + IconButton, + MenuItem, + Table, + TableBody, + TableCell, + TableRow, + TextField, + Typography, + Stack, + Menu, + ButtonGroup, + Tooltip, + TableHead, + Checkbox, + InputAdornment, + TableSortLabel, + FormControl + } from '@mui/material'; + import { visuallyHidden } from '@mui/utils'; + + import { DesktopDatePicker, LocalizationProvider } from '@mui/x-date-pickers'; + import { fDateOnly } from '@/utils/formatTime'; + + import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; + import FindInPageOutlinedIcon from '@mui/icons-material/FindInPageOutlined'; + import AssessmentIcon from '@mui/icons-material/Assessment'; + // hooks + import React, { ChangeEvent, useEffect, useRef, useState } from 'react'; + import { Link, Navigate, useNavigate, useSearchParams } from 'react-router-dom'; + + import { LoadingButton } from '@mui/lab'; + // components + import axios from '../../../utils/axios'; + import { LaravelPaginatedData, LaravelPaginatedDataDefault } from '../../../@types/paginated-data'; + import DataTable from '../../../components/LaravelTable'; + import { fCurrency } from '../../utils/formatNumber'; + import EditRoundedIcon from '@mui/icons-material/EditRounded'; + import { Chip } from '@mui/material'; + import Iconify from '@/components/Iconify'; + import { enqueueSnackbar } from 'notistack'; + import { fDate, fDateTime } from '../../../utils/formatTime'; + import { Claims } from '@/@types/claims'; + import Label from '@/components/Label'; + import { capitalizeFirstLetter } from '@/utils/formatString'; + import TableMoreMenu from '@/components/table/TableMoreMenu'; + import Edit from '@mui/icons-material/Edit'; + import { Download } from '@mui/icons-material'; + import { Add, Search } from '@mui/icons-material'; + import Autocomplete from '@mui/material/Autocomplete'; + + import DownloadIcon from '@mui/icons-material/Download'; + + import UploadIcon from '@mui/icons-material/Upload'; + import CancelIcon from '@mui/icons-material/Cancel'; + import CheckCircleIcon from '@mui/icons-material/CheckCircle'; + + import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material'; + import CloseIcon from '@mui/icons-material/Close'; + + + export default function List() { + const [selectAll, setSelectAll] = useState(false); + const [selectedRows, setSelectedRows] = useState([]); + const [providers, setProviders] = useState(null); + // const [searchText, setSearchText] = useState(''); + const [order, setOrder] = useState('desc'); + const [orderBy, setOrderBy] = useState('created_at'); + const [perPage, setPerPage] = useState(0); + + const handleChange = (event, newValue) => { + // Jika newValue tidak undefined, atur nilai dataProvider + if (newValue !== undefined) { + setDataProvider(newValue.service_code); + } else { + // Jika tidak ada yang dipilih, set dataProvider menjadi string kosong + setDataProvider(null); + } + }; + // Dummy data + const dummyServices = [ + { service_code: '1', name: 'Service 1' }, + { service_code: '2', name: 'Service 2' }, + { service_code: '3', name: 'Service 3' }, + // tambahkan data lain sesuai kebutuhan + ]; + + + + const handleSelectAll = () => { + setSelectAll(!selectAll); + if (!selectAll) { + const requestedIds = dataTableData.data + .filter(row => row.status === 'approved') // Memfilter baris dengan status 'requested' + .map(row => row.id); // Mengambil hanya ID dari baris-baris yang memenuhi kondisi + setSelectedRows(requestedIds); + } else { + setSelectedRows([]); + } + }; + + const handleRowSelect = (id) => { + if (selectedRows.includes(id)) { + setSelectedRows(selectedRows.filter(rowId => rowId !== id)); + } else { + setSelectedRows([...selectedRows, id]); + } + }; + + const [searchParams, setSearchParams] = useSearchParams(); + const [startDate, setStartDate] = useState(null); + const [searchText, setSearchText] = useState(''); + const [endDate, setEndDate] = useState(null); + const navigate = useNavigate(); + const [dataProvider, setDataProvider] = useState(null); + + useEffect(() => { + if (startDate !== null || endDate !== null || dataProvider !== null + || order !== null || orderBy !== null || perPage !== 0) { + loadDataTableData(); + getProvider(); + } + }, [startDate, endDate, dataProvider, order, orderBy, perPage]); + + const [isLoading, setIsLoading] = useState(false); + const [isLoadingImport, setIsLoadingImport] = useState(false); + const handleExportReport = async () => { + + + const year = startDate?.getFullYear(); + const month = (startDate?.getMonth() + 1).toString().padStart(2, '0'); // Tambahkan 1 karena bulan dimulai dari 0, dan padStart untuk memastikan 2 digit + const day = startDate?.getDate().toString().padStart(2, '0'); // padStart untuk memastikan 2 digit + + const formattedDate = year && month && day ? `${year}-${month}-${day}` : ''; + + const year1 = endDate?.getFullYear(); + const month1 = (endDate?.getMonth() + 1).toString().padStart(2, '0'); // Tambahkan 1 karena bulan dimulai dari 0, dan padStart untuk memastikan 2 digit + const day1 = endDate?.getDate().toString().padStart(2, '0'); // padStart untuk memastikan 2 digit + + const formattedDate1 = year1 && month1 && day1 ? `${year1}-${month1}-${day1}` : ''; + + + + var filter = Object.fromEntries([...searchParams.entries()]); + setIsLoading(true) + await axios + .get('/claims/export-claim-management',{ + params: { + search: searchText, + start_date: formattedDate ? formattedDate : null, + end_date:formattedDate1, + provider: dataProvider, + order: order, + orderBy: orderBy, + page: perPage, + } + }) + .then((res) => { + enqueueSnackbar('Data berhasil di Export', { + variant: 'success', + anchorOrigin: { horizontal: 'right', vertical: 'top' }, + }); + setIsLoading(false) + + document.location.href = res.data.data.file_url; + }) + .catch((err) => + enqueueSnackbar('Data Gagal di Export', { + variant: 'error', + anchorOrigin: { horizontal: 'right', vertical: 'top' }, + }) + + ); + }; + + + function SearchInput(props: any) { + // SEARCH + const searchInput = useRef(null); + + + + const handleSearchChange = (event: any) => { + const newSearchText = event.target.value ?? ''; + setSearchText(newSearchText); + }; + + const handleSearchSubmit = (event: any) => { + event.preventDefault(); + props.onSearch({ search: searchText }); // Trigger to Parent + }; + + const handleGetData = (type :string) => { + axios.get(`claims/1/data-claim`) + .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(); + }) + } + + useEffect(() => { + // Trigger First Search + // setSearchText(searchParams.get('search') ?? ''); + }, []); + + return ( +
+ + + + +
+ ); + } + + function ImportForm(props: any) { + // IMPORT + // Create Button Menu + const [anchorEl, setAnchorEl] = React.useState(null); + + return ( +
+ + + {/* */} + +
+ ); + } + + const searchInput = useRef(null); + + + //handle search + const handleSearchChange = (event: any) => { + const newSearchText = event.target.value ?? ''; + setSearchText(newSearchText); + }; + + const handleSearchSubmit = (event: any) => { + event.preventDefault(); + loadDataTableData(); + }; + + + + useEffect(() => { + // Trigger First Search + //setSearchText(searchText); + }, []); + + const item = [ + { + id: '', + value: '', + name: 'Semua', + }, + ]; + + // const handleClick = () => { + + // } + + + + // Dummy Default Data + const [dataTableIsLoading, setDataTableLoading] = useState(true); + const [dataTableData, setDataTableData] = useState( + LaravelPaginatedDataDefault + ); + + + + const loadDataTableData = async (appliedFilter: any | null = null) => { + setDataTableLoading(true); + const year = startDate?.getFullYear(); + const month = (startDate?.getMonth() + 1).toString().padStart(2, '0'); // Tambahkan 1 karena bulan dimulai dari 0, dan padStart untuk memastikan 2 digit + const day = startDate?.getDate().toString().padStart(2, '0'); // padStart untuk memastikan 2 digit + + const formattedDate = year && month && day ? `${year}-${month}-${day}` : ''; + + const year1 = endDate?.getFullYear(); + const month1 = (endDate?.getMonth() + 1).toString().padStart(2, '0'); // Tambahkan 1 karena bulan dimulai dari 0, dan padStart untuk memastikan 2 digit + const day1 = endDate?.getDate().toString().padStart(2, '0'); // padStart untuk memastikan 2 digit + + const formattedDate1 = year1 && month1 && day1 ? `${year1}-${month1}-${day1}` : ''; + + const filter = appliedFilter ? appliedFilter : Object.fromEntries([...searchParams.entries()]); + const response = await axios.get('/claims-files-provider', { + params: { + search: searchText, + start_date: formattedDate ? formattedDate : null, + end_date:formattedDate1, + provider: dataProvider, + order: order, + orderBy: orderBy, + page: perPage, + } + }); + + setDataTableLoading(false); + + setDataTableData(response.data); + }; + + const getProvider = async () => { + const response = await axios.get('/claims/get-provider'); + setProviders(response.data) + } + + const applyFilter = async (searchFilter: { search: string }) => { + await loadDataTableData(searchFilter); + setSearchParams(searchFilter); + }; + + const handlePageChange = (event: ChangeEvent, value: number): void => { + setPerPage(value); + }; + + const [openDialogSubmit, setOpenDialogSubmit] = useState(false); + const handleCloseDialogSubmit = () => { + setOpenDialogSubmit(false); + } + + function toTitleCase(str: string | null) { + return str.replace(/\w\S*/g, function(txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); + }); + } + + const [approve, setApprove] = useState(''); + + const [reasonDecline, setReasonDecline] = useState(''); + + const handleReasonDeclineChange = (event) => { + setReasonDecline(event.target.value); + // Tambahkan logika yang diperlukan di sini + }; + + const handleSubmitData = async () => { + try { + const response = await axios.post('download-zip', { selectedRows: selectedRows }); + const fileUrl = response.data.file_url; // Perbaikan disini + enqueueSnackbar('Data berhasil di download', { variant: 'success' }); + window.open(fileUrl, '_blank'); + setOpenDialogSubmit(false); + setTimeout(() => { + window.location.reload(); + }, 5000); // Reload the page after 5 seconds + } catch (error) { + enqueueSnackbar('Data Gagal di download', { variant: 'error' }); + } + }; + + const handleSubmitData1 = () => { + //approve or decline + if (!reasonDecline && approve == 'decline') { + enqueueSnackbar('Mohon isi alasan', { variant: 'warning' }); + return false; + } + Promise.all(selectedRows.map(send_bulk)) + .then(() => { + enqueueSnackbar('All requests processed successfully', { variant: 'success' }); + setOpenDialogSubmit(false); + setTimeout(() => { + window.location.reload(); + }, 5000); // Reload the page after 5 seconds + }) + .catch((error) => { + enqueueSnackbar(error.response?.data?.message ?? 'Something went wrong!', { variant: 'error' }); + }); + }; + + function send_bulk(id) { + return axios.post(`claims/${id}/${approve}`, { reasonDecline: reasonDecline }); + } + + + const [anchorEl, setAnchorEl] = React.useState(null); + const createMenu = Boolean(anchorEl); + const importClaimManagement = useRef(null); + const [currentImportFileName, setCurrentImportFileName] = useState(null); + const [importLoading, setImportLoading] = useState(false); + const [importResult, setImportResult] = useState(null); + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + const handleClose = () => { + setAnchorEl(null); + }; + const handleImportButton = () => { + if (importClaimManagement?.current) { + handleClose(); + importClaimManagement.current ? importClaimManagement.current.click() : console.log('No File selected'); + } else { + alert('No file selected'); + } + }; + const handleCancelImportButton = () => { + if(importClaimManagement.current) + { + importClaimManagement.current.value = ''; + importClaimManagement.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(importClaimManagement.current && importClaimManagement.current.files) + { + if (importClaimManagement.current?.files.length) { + const formData = new FormData(); + formData.append('file', importClaimManagement.current?.files[0]); + setImportLoading(true); + axios + .post('claims/import', formData) + .then((response) => { + handleCancelImportButton(); + loadDataTableData(); + setImportResult(response.data); + setImportLoading(false); + enqueueSnackbar('Success Import Claim Managemenet', { variant: 'success' }); + }) + .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('claims/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(); + }); + + + }; + + const handleExportReportFiled = async () => { + + await axios + .post('claims/exportFiled', { params: importResult?.data.result_rows }) + .then((res) => { + enqueueSnackbar('Data berhasil di Export', { + variant: 'success', + anchorOrigin: { horizontal: 'right', vertical: 'top' }, + }); + setIsLoading(false) + + document.location.href = res.data.data.file_url; + }) + .catch((err) => + enqueueSnackbar('Data Gagal di Export', { + variant: 'error', + anchorOrigin: { horizontal: 'right', vertical: 'top' }, + }) + + ); + }; + + + // useEffect(() => { + // loadDataTableData(); + // getProvider(); + // }, []); + + const headStyle = { + fontWeight: 'bold', + }; + const headCells = [ + { + id: 'created_at', + align: 'left', + label: 'Date Submission', + isSort: true, + }, + { + id: 'code', + align: 'left', + label: 'Code', + isSort: true, + }, + { + id: 'name', + align: 'left', + label: 'Name', + isSort: false, + }, + { + id: 'provider', + align: 'left', + label: 'Provider', + isSort: false, + }, + { + id: 'files', + align: 'left', + label: 'Nama File', + isSort: false, + }, + ]; + + const orders = { + order: order, + setOrder: setOrder, + orderBy: orderBy, + setOrderBy: setOrderBy, + }; + const createSortHandler = (property: string) => (event: React.MouseEvent) => { + handleRequestSort(event, property); + }; + const handleRequestSort = async (event: React.MouseEvent, property: string) => { + const isAsc = orders?.orderBy === property && orders?.order === 'asc'; + + orders?.setOrder(isAsc ? 'desc' : 'asc'); + orders?.setOrderBy(property); + }; + // Called on every row to map the data to the columns + function createData(data: Claims): Claims { + return { + ...data, + }; + } + + { + /* ------------------ TABLE ROW ------------------ */ + } + function Row(props: { row: ReturnType, isSelected: boolean, onSelect: (id: string) => void }) { + const { row, isSelected, onSelect } = props; + // Memperbaiki destrukturisasi props + + const handleRowCheckboxChange = () => { + onSelect(row.id); // Panggil fungsi onSelect dari komponen induk dengan id baris saat checkbox di baris diklik + }; + + const [open, setOpen] = React.useState(false); + + const test = 1000; + + return ( + + *': { borderBottom: 'unset' } }}> + {/* + setOpen(!open)}> + {open ? : } + + */} + + + + {row?.created_at ? fDateTime(row?.created_at) : ''} + {row?.code} + {/* {row.code} */} + {row?.name} + {row?.provider} + + + {row.files ? row.files : '-'} + + + + {/* COLLAPSIBLE ROW */} + + + + {/* + + Description : {row.description} + + */} + + + + + ); + } + { + /* ------------------ END TABLE ROW ------------------ */ + } + + + + function TableContent() { + return ( + + {/* ------------------ TABLE HEADER ------------------ */} + + + {selectedRows.length > 0 ? ( + <> + + + + {selectedRows.length > 0 ? selectedRows.length : '0'}  Selected + + + + + + {/* + + */} + + + + + + ) : ( + <> + + + + {headCells && + headCells.map((headCell, index) => ( + + {headCell.isSort ? ( + + {headCell.label} + {orders?.orderBy === headCell.id ? ( + + {orders.order === 'desc' ? 'sorted descending' : 'sorted ascending'} + + ) : null} + + ) : ( + headCell.label + )} + + ))} + + + )} + + + + + {/* ------------------ END TABLE HEADER ------------------ */} + + {/* ------------------ TABLE ROW ------------------ */} + {dataTableIsLoading ? ( + + + + Loading + + + + ) : dataTableData.data.length === 0 ? ( + + + + No Data + + + + ) : ( + + {dataTableData.data.map((row) => ( + + ))} + + )} + {/* ------------------ END TABLE ROW ------------------ */} +
+ ); + } + + return ( + + + +
+ + + {!currentImportFileName && ( + <> + + { + if (event.key === 'Enter') { + handleSearchSubmit(event); + } + }} + InputProps={{ + startAdornment: ( + + + + ), + placeholder: 'Search Code or Name', + }} + /> + + + + { + + // loadDataTableData(); + setStartDate(value); + }} + renderInput={(params) => } + /> + + + + { + setEndDate(value); + }} + renderInput={(params) => ( + + )} + /> + + + + { + providers ? ( + option.name || ''} + value={providers.find((item) => item.id === dataProvider) || null} + onChange={(event, value) => { + if (value) { + setDataProvider(value.id); + } else { + setDataProvider(null); + } + }} + renderInput={(params) => ( + + )} + /> + ):( + <> + Loading... + + ) + } + + {/* + + } + sx={{ p: 1.8 }} + loading={isLoadingImport} + onClick={handleClick} + > + + Import + + + + + Import + + { + handleGetTemplate(); + }} + > + Download Template + + + + + } + sx={{ p: 1.8 }} + onClick={handleExportReport} + loading={isLoading} + > + + Export + + + + */} + + )} + {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'}] + ))} */} +  Report: +  Download Data Result Import + + + )} + +
+
+
+ + } + /> + + + + + Confirmation + + + + + + + + + + Are you sure to Download this files selected ? + {approve == "decline" ? ( + + + + ): ''} + + + + + + + +
+ ); + } diff --git a/frontend/dashboard/src/routes/index.tsx b/frontend/dashboard/src/routes/index.tsx index c6534bfa..a1e4c8ae 100644 --- a/frontend/dashboard/src/routes/index.tsx +++ b/frontend/dashboard/src/routes/index.tsx @@ -418,6 +418,10 @@ export default function Router() { path: 'report/appointments/:id/edit', element: , }, + { + path: 'report/files-provider', + element: , + }, { path: 'report/live-chat', element: , @@ -630,7 +634,7 @@ const InpatientMonitoring = Loadable(lazy(() => import('../pages/CaseManagement/ /** * Customer Service */ -// Request +// Request const RequestLog = Loadable(lazy(() => import('../pages/CustomerService/Request/Index'))) const RequestLogDetail = Loadable(lazy(() => import('../pages/CustomerService/Request/Detail'))) // Final LOG @@ -662,6 +666,8 @@ const Appointment = Loadable(lazy(() => import('../pages/Report/Appointments/Ind const AppointmentCreate = Loadable(lazy(() => import('../pages/Report/Appointments/Create'))); const AppointmentShow = Loadable(lazy(() => import('../pages/Report/Appointments/Show'))); +const FilesProvider = Loadable(lazy(() => import('../pages/Report/FilesProvider/Index'))); + const Livechat = Loadable(lazy(() => import('../pages/Report/Livechat/Index'))); const LivechatCreate = Loadable(lazy(() => import('../pages/Report/Livechat/Create'))); const LivechatShow = Loadable(lazy(() => import('../pages/Report/Livechat/Show')));