diff --git a/Modules/Internal/Http/Controllers/Api/DashboardController.php b/Modules/Internal/Http/Controllers/Api/DashboardController.php new file mode 100755 index 00000000..12ee1610 --- /dev/null +++ b/Modules/Internal/Http/Controllers/Api/DashboardController.php @@ -0,0 +1,503 @@ +start_date + ? Carbon::parse($request->start_date)->startOfDay()->toDateTimeString() + : null; + + $end_date = $request->end_date + ? Carbon::parse($request->end_date)->endOfDay()->toDateTimeString() + : null; + + $type = $request->type; // 0 = harian, 1 = mingguan, 2 = bulanan + $status = $request->status; // 0 = semua, 1 = berhasil, 2 = abandon, 3 = gagal + + // Menyesuaikan filter berdasarkan type (harian, mingguan, bulanan) + // if ($type == 1) { + // // Filter mingguan + // $start_date = Carbon::now()->startOfWeek()->toDateTimeString(); + // $end_date = Carbon::now()->endOfWeek()->toDateTimeString(); + + // } elseif ($type == 2) { + // // Filter bulanan + // $start_date = Carbon::now()->startOfMonth()->toDateTimeString(); + // $end_date = Carbon::now()->endOfMonth()->toDateTimeString(); + // } + + // Query awal + $query = Livechat::query(); + + // Filter berdasarkan tanggal + if ($start_date && $end_date) { + $query->whereBetween('dRequestTime', [$start_date, $end_date]); + } + + // Filter berdasarkan status + if ($status == 1) { + $query->where('sStatus', '2'); // Berhasil + } elseif ($status == 2) { + $query->where('sStatus', '1'); // Abandon + } elseif ($status == 3) { + $query->whereNotIn('sStatus', ['1', '2']); // Gagal (selain 1 dan 2) + } + + $liveChat = $query->get(); + + // Mapping status transaksi + $statusMapping = [ + "2" => "Berhasil", + "1" => "Abandon", + ]; + + // Inisialisasi counter status + $statusCount = [ + "Berhasil" => 0, + "Abandon" => 0, + "Gagal" => 0, + ]; + + // Hitung jumlah status + foreach ($liveChat as $chat) { + $statusLabel = isset($statusMapping[$chat->sStatus]) + ? $statusMapping[$chat->sStatus] + : "Gagal"; + $statusCount[$statusLabel]++; + } + + // Format response seperti yang diminta + $transaksiData = [ + ["name" => "Berhasil", "value" => $statusCount["Berhasil"], "color" => "#4CAF50"], + ["name" => "Gagal", "value" => $statusCount["Gagal"], "color" => "#F44336"], + ["name" => "Abandon", "value" => $statusCount["Abandon"], "color" => "#9E9E9E"], + ]; + + return response()->json($transaksiData); + } + + public function listBarChart(Request $request) + { + $start_date = $request->start_date + ? Carbon::parse($request->start_date)->startOfDay() + : Carbon::now()->startOfMonth(); + + $end_date = $request->end_date + ? Carbon::parse($request->end_date)->endOfDay() + : Carbon::now()->endOfMonth(); + + $status = $request->status; // 0 = semua, 1 = berhasil, 2 = abandon, 3 = gagal + $type = $request->type; // 0 = harian, 1 = mingguan, 2 = bulanan + + // Query awal + $query = Livechat::query(); + + // Filter berdasarkan rentang tanggal yang dimasukkan user + $query->whereBetween('dRequestTime', [$start_date, $end_date]); + + // Filter berdasarkan status + if ($status == 1) { + $query->where('sStatus', '2'); // Berhasil + } elseif ($status == 2) { + $query->where('sStatus', '1'); // Abandon + } elseif ($status == 3) { + $query->whereNotIn('sStatus', ['1', '2']); // Gagal (selain 1 dan 2) + } + + $liveChat = $query->get(); + + // Mengelompokkan data berdasarkan tipe request (harian, mingguan, atau bulanan) + $groupedData = []; + + foreach ($liveChat as $chat) { + if ($type == 1) { + // Mingguan (contoh: "01 Jan 2025 - 07 Jan 2025") + $weekStart = Carbon::parse($chat->dRequestTime)->startOfWeek(); + $weekEnd = Carbon::parse($chat->dRequestTime)->endOfWeek(); + $groupKey = $weekStart->format('d M Y') . ' - ' . $weekEnd->format('d M Y'); + } elseif ($type == 2) { + // Bulanan (contoh: "Jan 2025") + $groupKey = Carbon::parse($chat->dRequestTime)->translatedFormat('M Y'); + } else { + // Harian (format "1 Jan 2025 - 2 Feb 2025") + $groupKey = Carbon::parse($chat->dRequestTime)->format('j M Y'); + } + + if (!isset($groupedData[$groupKey])) { + $groupedData[$groupKey] = [ + "date" => $groupKey, + "Berhasil" => 0, + "Abandon" => 0, + "Gagal" => 0, + ]; + } + + if ($chat->sStatus == "2") { + $groupedData[$groupKey]["Berhasil"]++; + } elseif ($chat->sStatus == "1") { + $groupedData[$groupKey]["Abandon"]++; + } else { + $groupedData[$groupKey]["Gagal"]++; + } + } + + // Konversi hasil ke dalam array untuk response JSON + $result = array_values($groupedData); + + return response()->json($result); + } + + + public function listDokter(Request $request) + { + $idDokter = [ + '68268', + '75047', + '75046', + '75045', + '75044', + '75043', + '75027', + '75021', + '75020', + ]; // List dokter + + $listDokters = Dokter::with([])->whereIn('nIDUser', $idDokter)->get(); + + $result = $listDokters->map(function ($dokter) { + return [ + 'id' => $dokter->nIDUser, + 'code' => $dokter->nIDUser, + 'name' => $dokter->user->fullName, + 'online' => $dokter->sStatus, + ]; + }); + + return response()->json($result); + } + public function listPerformaDokter(Request $request) + { + $start_date = $request->start_date + ? Carbon::parse($request->start_date)->startOfDay() + : Carbon::now()->startOfMonth(); + + $end_date = $request->end_date + ? Carbon::parse($request->end_date)->endOfDay() + : Carbon::now()->endOfMonth(); + + $status = $request->status; // 0 = semua, 1 = berhasil, 2 = abandon, 3 = gagal + $type = $request->type; // 0 = harian, 1 = mingguan, 2 = bulanan + + $nIDDokter = $request->nIDDokter; + + // Query awal + $query = Livechat::with('doctor'); + + // Filter berdasarkan rentang tanggal yang dimasukkan user + $query->whereBetween('dRequestTime', [$start_date, $end_date]); + + if (!empty($nIDDokter)) { + $query->whereIn('nIDDokter', $nIDDokter); + } + + // Filter berdasarkan status + if ($status == 1) { + $query->where('sStatus', '2'); // Berhasil + } elseif ($status == 2) { + $query->where('sStatus', '1'); // Abandon + } elseif ($status == 3) { + $query->whereNotIn('sStatus', ['1', '2']); // Gagal + } + + // Ambil data livechat + $liveChats = $query->get(); + + // Data akhir yang akan dikembalikan + $groupedData = []; + + foreach ($liveChats as $chat) { + $dokterId = $chat->nIDDokter; + $dokterName = $chat->doctor->user->fullName ?? 'Unknown'; // Ambil nama dokter dari relasi + if (!isset($groupedData[$dokterId])) { + $groupedData[$dokterId] = [ + "name" => $dokterName, + "Berhasil" => 0, + "Abandon" => 0, + "Gagal" => 0, + ]; + } + + if ($chat->sStatus == "2") { + $groupedData[$dokterId]["Berhasil"]++; + } elseif ($chat->sStatus == "1") { + $groupedData[$dokterId]["Abandon"]++; + } else { + $groupedData[$dokterId]["Gagal"]++; + } + } + + // Konversi hasil ke dalam array untuk response JSON + $result = array_values($groupedData); + + return response()->json($result); + } + + + /** + * 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) + { + // + } + + public function search(Request $request) + { + return Icd::when($request->search ?? null, function($icd, $search) { + $icd->where('name', 'LIKE', '%'.$search.'%') + ->orWhere('code', 'LIKE', '%'.$search.'%'); + })->limit(10)->get(); + } + + public function import(Request $request, $id) + { + $request->validate([ + 'file' => 'required|file|mimes:xls,xlsx,csv,txt', + ]); + $file_name = now()->getPreciseTimestamp(3).'-'.$request->file('file')->getClientOriginalName(); + $file = $request->file('file')->storeAs('temp', $file_name); + + $import = new ImportService(); + $import->read(Storage::path('temp/'.$file_name)); + $import->write(Storage::disk('public')->path('temp/result-'.$file_name), 'xsls'); + + $imported_icd_data = 0; + $failed_icd_data = []; + foreach ($import->sheetsIterator() as $sheetIndex => $sheet) { + $doc_headers_indexes = []; + foreach ($sheet->getRowIterator() as $index => $row) { + if ($index == 1) { // First Row Must be Header + foreach ($row->getCells() as $index => $cell) { + $title = $cell->getValue(); + $title = preg_replace( "/\r|\n/", " ", $title ); + $title = preg_replace('/\xc2\xa0/', " ", $title ); + $title = rtrim($title); + $title = ltrim($title); + $doc_headers_indexes[$index] = $title; + } + + // Write Header to File + $result_headers = array_merge($doc_headers_indexes, ['Ingest Code', 'Ingest Note']); + $import->addArrayToRow($result_headers); + + // TODO Validate if First Row not Header + } else { // Next Row Should be Data + $row_data = []; + $row_map = [ + 0 => 'ICD_Code', + 1 => 'Description', + ]; + + foreach ($row->getCells() as $header_index => $cell) { + if (isset($row_map[$header_index])) { + $value = $cell->getValue(); + $value = preg_replace( "/\r|\n/", " ", $value ); + $value = preg_replace('/\xc2\xa0/', " ", $value ); + $value = rtrim($value); + $value = ltrim($value); + $row_data[$row_map[$header_index]] = $cell->getValue(); + } + } + + try { // Process the Row Data + if ( + empty($row_data['ICD_Code']) && + empty($row_data['Description']) + ) { + continue; + } + + // Save the Row + $icdService = new IcdService(); + $icdService->handleIcdRow($row_data, $id); + + // Write Success Result to File + $import->addArrayToRow(array_merge($row_data, [ + 'Ingest Code' => 200, + 'Ingest Note' => 'Success', + ]), $sheet->getName()); + $imported_icd_data++; + + } catch (ImportRowException $e) { + // Write Data Validation Error to File + $import->addArrayToRow(array_merge($row_data, [ + 'Ingest Code' => $e->getCode(), + 'Ingest Note' => $e->getMessage(), + ]), $sheet->getName()); + $failed_icd_data[] = ['row_number' => $index, 'error' => $e->getMessage(), 'data' => $row_data]; + } catch (\Exception $e) { + throw new \Exception($e); + // Write Server Error to File + $import->addArrayToRow(array_merge($row_data, [ + 'Ingest Code' => 500, + 'Ingest Note' => env('APP_DEBUG') ? $e->getMessage() : 'Server Error', + ]), $sheet->getName()); + $failed_icd_data[] = ['row_number' => $index, 'error' => $e->getMessage(), 'data' => $row_data]; + } + } + } + + break; // Only Read First Row + } + $import->reader->close(); + Storage::delete('temp/'.$file_name); + $import->writer->close(); + + return [ + 'total_successed_row' => $imported_icd_data, + 'total_failed_row' => count($failed_icd_data), + 'failed_row' => $failed_icd_data, + 'result_file' => [ + 'url' => Storage::disk('public')->url('temp/result-'.$file_name), + 'name' => 'result-'.$file_name, + ] + ]; + } + + public function activation(Request $request, $diagnosis_id) + { + $request->validate([ + 'active' => 'required' + ]); + + $Icd = Icd::findOrFail($diagnosis_id); + $Icd->active = $request->active == '1'; + + if ($Icd->save()) { + return response()->json([ + 'icd' => $Icd, + 'message' => 'Status Updated Successfully' + ]); + } + } + + public function generateIcdList(Request $request, $diagnosis_id){ + // Mendapatkan data yang akan diekspor (misalnya, dari database) + $data = Icd::where('icd_template_id', $diagnosis_id)->get()->toArray(); + + // Membuat penulis entitas Spout + $writer = WriterEntityFactory::createXLSXWriter(); + + // Membuka penulis untuk menulis ke file + $writer->openToFile(public_path('files/TemplateICDList.xlsx')); + /** Create a style with the StyleBuilder */ + $style = (new StyleBuilder()) + ->setFontBold() + ->build(); + + // Menulis header kolom + $headers_map_to_table_fields = $this->icdService->listing_doc_headers; + $headerRow = WriterEntityFactory::createRowFromArray($headers_map_to_table_fields, $style); + + $writer->addRow($headerRow); + + // Menulis data + if (!empty($data)) { + foreach ($data as $item) { + $rowData = [ + // $item['rev'], // Rev + // $item['version'], // Version + $item['code'], // Code + // $item['parent_code'], // Parent Code + $item['name'], // Name + // $item['description'], // Description + // $item['active'] == 1 ? 'Active' : 'Inactive', // Status + // $item['type'], // Type + ]; + + $row = WriterEntityFactory::createRowFromArray($rowData); + $writer->addRow($row); + } + } + + // Menutup penulis + $writer->close(); + + // Mengembalikan response untuk mengunduh file + $filePath = public_path('files/TemplateICDList.xlsx'); + + return Helper::responseJson([ + 'file_name' => "Diagnosis ICD List " . date('Y-m-d h:i:s'), + "file_url" => url('files/TemplateICDList.xlsx') + ]); + + } +} diff --git a/Modules/Internal/Routes/api.php b/Modules/Internal/Routes/api.php index 61abb29d..1e0a9ea0 100755 --- a/Modules/Internal/Routes/api.php +++ b/Modules/Internal/Routes/api.php @@ -27,6 +27,7 @@ use Modules\Internal\Http\Controllers\Api\HospitalController; use Modules\Internal\Http\Controllers\Api\DoctorController; use Modules\Internal\Http\Controllers\Api\DoctorRatingController; use Modules\Internal\Http\Controllers\Api\DoctorOnlineController; +use Modules\Internal\Http\Controllers\Api\DashboardController; use Modules\Internal\Http\Controllers\Api\DrugController; use Modules\Internal\Http\Controllers\Api\FormulariumController; use Modules\Internal\Http\Controllers\Api\FormulariumTemplateController; @@ -411,6 +412,11 @@ Route::prefix('internal')->group(function () { // Navigation Route::get('navigations', [NavigationController::class, 'index']); + // Dashboard + Route::get('dashboard/transaksi', [DashboardController::class, 'index']); + Route::get('dashboard/transaksi-bar-chart', [DashboardController::class, 'listBarChart']); + Route::get('dashboard/list-dokter', [DashboardController::class, 'listDokter']); + Route::get('dashboard/list-performa-dokter', [DashboardController::class, 'listPerformaDokter']); }); Route::get('province', [ProvinceController::class, 'index']); diff --git a/database/seeders/NavigationSeeder.php b/database/seeders/NavigationSeeder.php index 7e1cf74b..fcd6cfaa 100755 --- a/database/seeders/NavigationSeeder.php +++ b/database/seeders/NavigationSeeder.php @@ -19,8 +19,14 @@ class NavigationSeeder extends Seeder // DOCTORS & HOSPITALS [ 'title' => 'Dashboard', - 'path' => '/dashboard', - 'permission' => 'dashboard' + 'children' => [ + [ + 'title' => 'Dashboard', + 'path' => '/dashboard', + 'permission' => 'doctor-list' + ], + ], + 'permission' => 'dashboard', ], // DOCTORS & HOSPITALS [ @@ -263,6 +269,11 @@ class NavigationSeeder extends Seeder 'path' => '/alarm-center', 'permission' => 'alarm-center-list-client-portal' ], + [ + 'title' => 'Daily Monitoring', + 'path' => '/daily-monitoring', + 'permission' => 'daily-monitoring-list-client-portal' + ], [ 'title' => 'Formularium', 'path' => '/master/formularium-template-v2', diff --git a/database/seeders/PermissionTableSeeder.php b/database/seeders/PermissionTableSeeder.php index f2d6af41..8291218a 100755 --- a/database/seeders/PermissionTableSeeder.php +++ b/database/seeders/PermissionTableSeeder.php @@ -41,6 +41,7 @@ class PermissionTableSeeder extends Seeder 'formularium-create', 'formularium-edit', 'formularium-delete', + 'dashboard', 'diagnosis-list', 'diagnosis-create', 'diagnosis-edit', @@ -97,6 +98,7 @@ class PermissionTableSeeder extends Seeder 'export-alarm-center-client-portal', 'filter-alarm-center-client-portal', 'benefit-client-portal', + 'daily-monitoring-list-client-portal' ] ], ####################### HOSPITAL PORTAL ######################### diff --git a/frontend/dashboard/src/pages/Dashboard.tsx b/frontend/dashboard/src/pages/Dashboard.tsx index 96a89fb0..07dfcb8d 100755 --- a/frontend/dashboard/src/pages/Dashboard.tsx +++ b/frontend/dashboard/src/pages/Dashboard.tsx @@ -1,66 +1,557 @@ // @mui -import { Button, Container, Grid, styled, Typography, Card, Stack } from '@mui/material'; +import { useEffect, useState } from 'react'; +import { + Button, + Container, + Grid, + styled, + Typography, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Paper, + Card, + TextField, + FormControl, + InputLabel, + Select, + MenuItem, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + Checkbox, + +} from '@mui/material'; // hooks import useSettings from '../hooks/useSettings'; // components +import { PieChart, Pie, Cell, Tooltip, BarChart, Bar, XAxis, YAxis, Legend, ResponsiveContainer } from 'recharts'; import Page from '../components/Page'; import axios from '../utils/axios'; import useAuth from '../hooks/useAuth'; import SomethingUsage from '../sections/dashboard/SomethingUsage'; import { fCurrency } from '../utils/formatNumber'; +import dayjs from "dayjs"; +import {DesktopDatePicker, LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; +import { green, red } from "@mui/material/colors"; +import MuiDialog from '@/components/MuiDialog'; +import SearchIcon from "@mui/icons-material/Search"; // ---------------------------------------------------------------------- +const COLORS = ['#229A16', '#919EAB', '#FF4842']; + +// const performaDokterData = [ +// { name: 'Dr. John', Berhasil: 70, Gagal: 8, Abandon: 4 }, +// { name: 'Dr. Richard', Berhasil: 68, Gagal: 10, Abandon: 2 }, +// { name: 'Dr. Harman', Berhasil: 75, Gagal: 5, Abandon: 3 }, +// { name: 'Dr. Emma', Berhasil: 80, Gagal: 7, Abandon: 1 }, +// { name: 'Dr. tb', Berhasil: 80, Gagal: 7, Abandon: 1 }, +// { name: 'Dr. test', Berhasil: 80, Gagal: 7, Abandon: 1 }, +// { name: 'Dr. yayan', Berhasil: 80, Gagal: 7, Abandon: 1 }, +// { name: 'Dr. intan', Berhasil: 80, Gagal: 7, Abandon: 1 }, +// { name: 'Dr. fajri', Berhasil: 80, Gagal: 7, Abandon: 1 }, +// ]; + +// Custom Tooltip +const CustomTooltip = ({ active, payload, label }) => { + if (active && payload && payload.length) { + const totalPasien = + payload[0].value + payload[1].value + payload[2].value; + return ( +
+

{label}

+

Total Pasien: {totalPasien}

+

Berhasil: {payload[0].value}

+

Gagal: {payload[1].value}

+

Abandon: {payload[2].value}

+
+ ); + } + return null; +}; + +// Custom Tooltip +const CustomTooltipPie = ({ active, payload, startDate, endDate }) => { + if (!active || !payload || payload.length === 0) return null; + // Fungsi format tanggal ke "2 Jan 2025" + const formatDate = (date) => { + if (!date) return "N/A"; + return new Date(date).toLocaleDateString("id-ID", { + day: "numeric", + month: "short", + year: "numeric", + }); + }; + return ( +
+

{formatDate(startDate)} - {formatDate(endDate)}

+

Status: {payload[0]?.name || "Tidak ada data"}

+

Jumlah Pasien: {payload[0]?.value || 0}

+
+ ); +}; + + export default function Dashboard() { - const { themeStretch } = useSettings(); - - const { logout } = useAuth(); - const loadSomething = () => { - axios.get('/user') +const transaksiDataDefault = [ + { name: "Berhasil", value: 0, color: "#4CAF50" }, + { name: "Gagal", value: 0, color: "#F44336" }, + { name: "Abandon", value: 0, color: "#9E9E9E" }, +]; + const { themeStretch } = useSettings(); + const [startDate, setStartDate] = useState(dayjs().startOf('month').format('YYYY-MM-DD')); + const [endDate, setEndDate] = useState(dayjs().format('YYYY-MM-DD')); + const [startDateDokter, setStartDateDokter] = useState(dayjs().startOf('month').format('YYYY-MM-DD')); + const [endDateDokter, setEndDateDokter] = useState(dayjs().format('YYYY-MM-DD')); + const [transaksiData, setTransaksiData] = useState(transaksiDataDefault); + const [transaksiDataBar, setTransaksiDataBar] = useState([]); + const [type, setType] = useState(0); + const [status, setStatus] = useState(0); + const [statusDokter, setStatusDokter] = useState(0); + const [view, setView] = useState(["day", "month", "year"]); + const [performaDokterData, setListPerformaDoctors] = useState([]); + const [doctors, setListDoctors] = useState([]); + const [selectedDoctors, setSelectedDoctors] = useState(doctors.map((doctor) => doctor.id)); // State untuk dokter yang dipilih + + + const fetchData = async () => { + try { + const response = await axios.get(`dashboard/transaksi`, { + params: { + start_date: startDate, + end_date: endDate, + type, + status + } + }); + if (response.data) { + setTransaksiData(response.data); + } + if (type === 0) { + setView(["day", "month", "year"]); // Urutan yang benar: day, month, year + } else { + setView(["month"]); // Hanya menampilkan bulan & tahun + } + } catch (error) { + console.error('Error fetching transaksi data:', error); + } }; - const DangerCard = styled(Card)(({ theme }) => ({ - boxShadow: 'none', - padding: theme.spacing(3), - color: theme.palette.error.main, - backgroundColor: theme.palette.error.lighter, - })); + const fetchDataBar = async () => { + try { + const response = await axios.get(`dashboard/transaksi-bar-chart`, { + params: { + start_date: startDate, + end_date: endDate, + type, + status + } + }); + if (response.data) { + setTransaksiDataBar(response.data); + } + if (type === 0) { + setView(["day", "month", "year"]); // Urutan yang benar: day, month, year + } else { + setView(["month"]); // Hanya menampilkan bulan & tahun + } + } catch (error) { + console.error('Error fetching transaksi data:', error); + } + } - const SuccessCard = styled(Card)(({ theme }) => ({ - boxShadow: 'none', - padding: theme.spacing(3), - color: theme.palette.success.darker, - backgroundColor: theme.palette.success.lighter, - })); + const fetchListPerfomaDokter = async () => { + try { + const response = await axios.get(`dashboard/list-performa-dokter`, { + params: { + start_date: startDateDokter, + end_date: endDateDokter, + type, + statusDokter, + nIDDokter: selectedDoctors + } + } ); + if (response.data) { + setListPerformaDoctors(response.data); + } + } catch (error) { + console.error('Error fetching transaksi data:', error); + } + }; + + + const fetchListDokter = async () => { + try { + const response = await axios.get(`dashboard/list-dokter`); + if (response.data) { + setListDoctors(response.data); + } + } catch (error) { + console.error('Error fetching transaksi data:', error); + } + }; + + // Fetch data saat pertama kali halaman dimuat dan ketika filter berubah + useEffect(() => { + fetchData(); + fetchDataBar(); + // fetchListPerfomaDokter(); + }, [startDate, endDate, type, status]); + + // Fetch + useEffect(() => { + fetchListPerfomaDokter(); + }, [selectedDoctors, startDateDokter, endDateDokter]) + + useEffect(() => { + fetchListDokter(); + }, []); + + + // Performa dokter + const [openDialog, setOpenDialog] = useState(false); + const handleOpen = () => setOpenDialog(true); + + + const getContent = () => { + const [search, setSearch] = useState(""); // State untuk pencarian dokter + + // Filter dokter berdasarkan pencarian + const filteredDoctors = doctors.filter((doctor) => + doctor.name.toLowerCase().includes(search.toLowerCase()) + ); + + // Handle pilih satu dokter + const handleSelectDoctor = (id) => { + setSelectedDoctors((prev) => + prev.includes(id) ? prev.filter((docId) => docId !== id) : [...prev, id] + ); + }; + + // Handle pilih semua dokter + const handleSelectAll = () => { + if (selectedDoctors.length === doctors.length) { + setSelectedDoctors([]); + } else { + setSelectedDoctors(doctors.map((doctor) => doctor.id)); + } + }; + + const handleCloseDialog = () => { + setOpenDialog(false); + setSelectedDoctors([]); + } + + const handlePilihDokter = () => { + setOpenDialog(false); + console.log(selectedDoctors); + } + return ( + <> + {/* Search Bar */} + setSearch(e.target.value)} + InputProps={{ + endAdornment: , + }} + sx={{ mb: 2, mt:2 }} + /> + + {/* Table Dokter */} + + + + + + + + Kode + Nama + Status + + + + {filteredDoctors.map((doctor) => ( + + + handleSelectDoctor(doctor.id)} + /> + + {doctor.code} + {doctor.name} + + + {doctor.online === 1 ? "🟢 Online" : "🔴 Offline"} + + + + ))} + +
+
+ + + + + + + + ); + }; + return ( - + Dashboard - - - + {/* Jumlah Transaksi */} + + + Jumlah Transaksi + + + {/* Pilih */} + + + Tipe + + + + + + { + if (!value) return; // Hindari error jika value null atau undefined + if (type == 0) { + setStartDate(value); + } else { + setStartDate(new Date(value.getFullYear(), value.getMonth(), 1)); + } + }} + renderInput={(params) => } + /> + + + + + { + if (!value) return; // Hindari error jika value null atau undefined + if (type == 0) { + setEndDate(value); + } else { + setEndDate(new Date(value.getFullYear(), value.getMonth(), 1)); + } + }} + renderInput={(params) => } + /> + + + {/* Pilih Status */} + + + Status + + + + + + + + `${(percent * 100).toFixed(0)}%`} + > + {transaksiData.map((entry, index) => ( + + ))} + + } /> + + + + + +
+ + + date} + /> + + } /> + + + + + + +
+
- - - - This Month Usages - {fCurrency(15000000)} (57) - - -
- - - Remaining Balance Estimation - November 2022 - - +
+ + {/* Performa Dokter */} + + + Performa Dokter + + + {/* Pilih Dokter*/} + + + + {/* Pilih */} + + + Tipe + + + + + + { + if (!value) return; // Hindari error jika value null atau undefined + if (type == 0) { + setStartDateDokter(value); + } else { + setStartDateDokter(new Date(value.getFullYear(), value.getMonth(), 1)); + } + }} + renderInput={(params) => } + /> + + + + + { + if (!value) return; // Hindari error jika value null atau undefined + if (type == 0) { + setEndDateDokter(value); + } else { + setEndDateDokter(new Date(value.getFullYear(), value.getMonth(), 1)); + } + }} + renderInput={(params) => } + /> + + + {/* Pilih Status */} + + + Status + + + + + + + + + + + + + + + + + -
+ + {/* Dialog Pilih Dokter */} + + +
);