diff --git a/Modules/Client/Http/Controllers/Api/BillingSummaryController.php b/Modules/Client/Http/Controllers/Api/BillingSummaryController.php new file mode 100644 index 00000000..d47cd9cd --- /dev/null +++ b/Modules/Client/Http/Controllers/Api/BillingSummaryController.php @@ -0,0 +1,286 @@ +year ?? now()->year; + $status = $request->status; + $bn = $request->bn; + $payorId = $request->payorId; + $service = $request->service; + $billing = $request->billing; + $search = $request->search; + + $rows = DB::table('invoice_payments') + ->join('invoice_payment_details', 'invoice_payment_details.invoice_payment_id', '=', 'invoice_payments.id') + ->join('claim_requests', 'claim_requests.id', '=', 'invoice_payment_details.claim_request_id') + ->join('request_logs', 'request_logs.id', '=', 'claim_requests.request_log_id') + ->join('corporate_employees', 'corporate_employees.member_id', '=', 'request_logs.member_id') + ->join('organizations', 'organizations.id', '=', 'request_logs.organization_id') + ->leftJoin('members', 'members.id', '=', 'request_logs.member_id') + ->whereYear('invoice_payments.created_at', $year) + ->where('corporate_employees.corporate_id', '=', $corporate_id) + // FILTERS + ->when($status, fn ($q) => + $q->where('invoice_payments.status', $status) + ) + ->when($bn, fn ($q) => + $q->where('members.member_id', $bn) + ) + ->when($payorId, fn ($q) => + $q->where('members.payor_id', $payorId) + ) + ->when($service, fn ($q) => + $q->where('claim_requests.service_code', $service) + ) + ->when($billing, fn ($q) => + $q->where('invoice_payments.invoice_number', $billing) + ) + + // 🔍 SEARCH PROVIDER (LIKE) + ->when($search, fn ($q) => + $q->where('organizations.name', 'like', '%' . $search . '%') + ) + + ->selectRaw(" + MONTH(invoice_payments.created_at) as month_number, + organizations.name as provider, + SUM(request_logs.nominal) as total + ") + ->groupBy('month_number', 'organizations.name') + ->orderBy('month_number') + ->get(); + + return response()->json( + $this->formatMonthly($rows) + ); + } + + + protected function formatMonthly($rows): array + { + $months = [ + 1 => 'Januari', 2 => 'Februari', 3 => 'Maret', + 4 => 'April', 5 => 'Mei', 6 => 'Juni', + 7 => 'Juli', 8 => 'Agustus', 9 => 'September', + 10 => 'Oktober', 11 => 'November', 12 => 'Desember', + ]; + + return collect($rows) + ->groupBy('month_number') + ->map(function ($items, $monthNumber) use ($months) { + return [ + 'month' => $months[$monthNumber], + 'total' => $items->sum('total'), + 'items' => $items->map(fn ($item) => [ + 'provider' => $item->provider, + 'total' => (float) $item->total, + ])->values(), + ]; + }) + ->values() + ->toArray(); + } + + public function providerSummary(Request $request, $corporate_id) + { + $year = $request->year ?? now()->year; + $status = $request->status; + $bn = $request->bn; + $payorId = $request->payorId; + $service = $request->service; + $billing = $request->billing; + $search = $request->search; + + $query = DB::table('invoice_payments') + ->join('invoice_payment_details', 'invoice_payment_details.invoice_payment_id', '=', 'invoice_payments.id') + ->join('claim_requests', 'claim_requests.id', '=', 'invoice_payment_details.claim_request_id') + ->join('request_logs', 'request_logs.id', '=', 'claim_requests.request_log_id') + ->join('corporate_employees', 'corporate_employees.member_id', '=', 'request_logs.member_id') + ->join('organizations', 'organizations.id', '=', 'request_logs.organization_id') + ->leftJoin('members', 'members.id', '=', 'request_logs.member_id') + ->whereYear('invoice_payments.created_at', $year) + ->where('corporate_employees.corporate_id', '=', $corporate_id) + // FILTER + ->when($status, fn ($q) => + $q->where('invoice_payments.status', $status) + ) + ->when($bn, fn ($q) => + $q->where('members.member_id', $bn) + ) + ->when($payorId, fn ($q) => + $q->where('members.payor_id', $payorId) + ) + ->when($service, fn ($q) => + $q->where('claim_requests.service_code', $service) + ) + ->when($billing, fn ($q) => + $q->where('invoice_payments.invoice_number', $billing) + ) + ->when($search, fn ($q) => + $q->where('organizations.name', 'like', '%' . $search . '%') + ); + + $items = $query + ->selectRaw(" + organizations.name as provider, + SUM(request_logs.nominal) as total + ") + ->groupBy('organizations.name') + ->orderByDesc('total') + ->get() + ->map(fn ($row) => [ + 'provider' => $row->provider, + 'total' => (float) $row->total, + ]); + + return response()->json([ + 'total' => $items->sum('total'), + 'items' => $items, + ]); + } + + public function topDiagnosis(Request $request, $corporate_id) + { + $year = $request->year ?? now()->year; + $status = $request->status; + $bn = $request->bn; + $payorId = $request->payorId; + $service = $request->service; + $billing = $request->billing; + $search = $request->search; + + $rows = DB::table('invoice_payments') + ->join('invoice_payment_details', 'invoice_payment_details.invoice_payment_id', '=', 'invoice_payments.id') + ->join('claim_requests', 'claim_requests.id', '=', 'invoice_payment_details.claim_request_id') + ->join('request_logs', 'request_logs.id', '=', 'claim_requests.request_log_id') + ->join('corporate_employees', 'corporate_employees.member_id', '=', 'request_logs.member_id') + // 🔥 ICD JOIN + ->leftJoin( + 'icd', + DB::raw("icd.code"), + '=', + DB::raw("SUBSTRING_INDEX(request_logs.diagnosis, ',', 1)") + ) + + ->leftJoin('members', 'members.id', '=', 'request_logs.member_id') + ->where('corporate_employees.corporate_id', '=', $corporate_id) + ->whereYear('invoice_payments.created_at', $year) + + // FILTER + ->when($status, fn ($q) => + $q->where('invoice_payments.status', $status) + ) + ->when($bn, fn ($q) => + $q->where('members.member_id', $bn) + ) + ->when($payorId, fn ($q) => + $q->where('members.payor_id', $payorId) + ) + ->when($service, fn ($q) => + $q->where('claim_requests.service_code', $service) + ) + ->when($billing, fn ($q) => + $q->where('invoice_payments.invoice_number', $billing) + ) + + ->selectRaw(" + SUBSTRING_INDEX(request_logs.diagnosis, ',', 1) as code_diagnosis, + icd.name as diagnosis, + COUNT(request_logs.id) as total_case, + SUM(request_logs.nominal) as total_billing + ") + ->groupBy('code_diagnosis', 'icd.name') + ->orderByDesc('total_case') + ->limit(10) + ->get(); + + return response()->json( + $rows->map(fn ($row) => [ + 'code' => $row->code_diagnosis, + 'diagnosis' => $row->diagnosis ?? '-', + 'total_case' => (int) $row->total_case, + 'total_billing' => (float) $row->total_billing, + ]) + ); + } + + + + /** + * Display a listing of the resource. + * @return Renderable + */ + // public function index() + // { + // return view('client::index'); + // } + + /** + * Show the form for creating a new resource. + * @return Renderable + */ + public function create() + { + return view('client::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('client::show'); + } + + /** + * Show the form for editing the specified resource. + * @param int $id + * @return Renderable + */ + public function edit($id) + { + return view('client::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) + { + // + } +} diff --git a/Modules/Client/Routes/api.php b/Modules/Client/Routes/api.php index 27443755..3ab51edc 100755 --- a/Modules/Client/Routes/api.php +++ b/Modules/Client/Routes/api.php @@ -1,6 +1,7 @@ group(function () { Route::get('corporate', [CorporateCurrentController::class, 'index']); Route::put('corporate-update', [CorporateCurrentController::class, 'update']); Route::get('get-deposits', [CorporateMemberController::class, 'getDeposit']); + Route::get('billing/summary', [BillingSummaryController::class, 'index']); + Route::get('/billing/provider-summary', [BillingSummaryController::class, 'providerSummary']); + Route::get('/billing/top-diagnosis', [BillingSummaryController::class, 'topDiagnosis']); Route::get('get-limits/{member_id}', [CorporateMemberController::class, 'getLimits']); diff --git a/database/migrations/2026_01_20_145951_add_urutan_to_navigations_table.php b/database/migrations/2026_01_20_145951_add_urutan_to_navigations_table.php new file mode 100644 index 00000000..ab01e97b --- /dev/null +++ b/database/migrations/2026_01_20_145951_add_urutan_to_navigations_table.php @@ -0,0 +1,33 @@ +integer('urutan') + ->after('updated_at')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('navigations', function (Blueprint $table) { + $table->dropColumn('urutan'); + }); + } +}; diff --git a/frontend/client-portal/src/pages/Dashboard/BillingFilterCard.tsx b/frontend/client-portal/src/pages/Dashboard/BillingFilterCard.tsx new file mode 100644 index 00000000..2ff20445 --- /dev/null +++ b/frontend/client-portal/src/pages/Dashboard/BillingFilterCard.tsx @@ -0,0 +1,182 @@ +import { + Box, + Grid, + TextField, + Typography, + Autocomplete, + MenuItem, + } from "@mui/material"; + + type InvoiceStatus = { + id: string; + name: string; + }; + + type YearOption = { + id: number; + label: string; + }; + + type ServiceOption = { + id: string; + label: string; + }; + + type BillingFilterProps = { + year: number; + status: string | null; + payorId: string; + bn: string; + service: string; // "OP" | "IP" | "" + billing: string; + search: string; + + onYearChange: (year: number) => void; + onStatusChange: (status: string | null) => void; + onPayorIdChange: (value: string) => void; + onBnChange: (value: string) => void; + onServiceChange: (value: string) => void; + onBillingChange: (value: string) => void; + onSearchChange: (value: string) => void; + title: string; + }; + + + const BillingFilterCard: React.FC = ({ + year, + status, + payorId, + bn, + service, + billing, + search, + onYearChange, + onStatusChange, + onPayorIdChange, + onBnChange, + onServiceChange, + onBillingChange, + onSearchChange, + title, + }) => { + const statusInvoice: InvoiceStatus[] = [ + { id: "submitted", name: "Pengajuan" }, + { id: "accepted", name: "Belum Dibayar" }, + { id: "partial_paid", name: "Bayar Sebagian" }, + { id: "paid", name: "Sudah Dibayar" }, + ]; + + const serviceOptions: ServiceOption[] = [ + { id: "OP", label: "OP (Rawat Jalan)" }, + { id: "IP", label: "IP (Rawat Inap)" }, + ]; + + const currentYear = new Date().getFullYear(); + + const yearOptions: YearOption[] = Array.from({ length: 4 }, (_, i) => { + const y = currentYear - i; + return { id: y, label: y.toString() }; + }); + + return ( + + + {title} + + + + {/* Tahun */} + + o.label} + value={yearOptions.find((y) => y.id === year) || null} + onChange={(_, v) => v && onYearChange(v.id)} + renderInput={(params) => ( + + )} + /> + + + {/* Payor ID */} + + onPayorIdChange(e.target.value)} + /> + + + {/* BN */} + + onBnChange(e.target.value)} + /> + + + {/* Service (OP / IP) */} + + o.label} + value={ + serviceOptions.find((s) => s.id === service) || null + } + onChange={(_, v) => onServiceChange(v ? v.id : "")} + renderInput={(params) => ( + + )} + /> + + + {/* Billing / No Invoice */} + + onBillingChange(e.target.value)} + /> + + + {/* Status */} + + o.name} + value={ + statusInvoice.find((s) => s.id === status) || null + } + onChange={(_, v) => onStatusChange(v ? v.id : null)} + renderInput={(params) => ( + + )} + /> + + + {/* Search Provider */} + + onSearchChange(e.target.value)} + /> + + + + ); + }; + + export default BillingFilterCard; diff --git a/frontend/client-portal/src/pages/Dashboard/BillingProviderList.tsx b/frontend/client-portal/src/pages/Dashboard/BillingProviderList.tsx new file mode 100644 index 00000000..f9e04d24 --- /dev/null +++ b/frontend/client-portal/src/pages/Dashboard/BillingProviderList.tsx @@ -0,0 +1,85 @@ +import { + Box, + Typography, + Divider, + } from "@mui/material"; + + type Item = { + provider: string; + total: number; + }; + + interface Props { + data: Item[]; + } + + const rupiah = (v: number) => + "Rp" + v.toLocaleString("id-ID"); + + const BillingProviderList: React.FC = ({ data }) => { + return ( + + {/* HEADER (FIXED) */} + + + Nama Provider + + + Total Billing + + + + {/* SCROLLABLE LIST */} + + {data.map((item, idx) => ( + + + + {item.provider} + + + {rupiah(item.total)} + + + + + ))} + + {data.length === 0 && ( + + Tidak ada data + + )} + + + ); + }; + + export default BillingProviderList; diff --git a/frontend/client-portal/src/pages/Dashboard/Dashboard.tsx b/frontend/client-portal/src/pages/Dashboard/Dashboard.tsx new file mode 100644 index 00000000..6f53de83 --- /dev/null +++ b/frontend/client-portal/src/pages/Dashboard/Dashboard.tsx @@ -0,0 +1,44 @@ +/* ---------------------------------- @mui ---------------------------------- */ +import { Container, Grid } from '@mui/material'; +/* ------------------------------- components ------------------------------- */ +import Page from '../../components/Page'; +/* ---------------------------------- hooks --------------------------------- */ +import useSettings from '../../hooks/useSettings'; +import HeaderBreadcrumbs from '../../components/HeaderBreadcrumbs'; +import DashboardBilling from './DashboardBilling'; +import DashboardBillingProvider from './DashboardBillingProvider'; +import DashboardBillingDiagnosis from './DashboardBillingDiagnosis'; + +export default function Drugs() { + const { themeStretch } = useSettings(); + + return ( + + + + + + {/* Billing per bulan */} + + + + + {/* Billing per provider */} + + + + + {/* Billing per diagnosis */} + + + + + + + ); +} diff --git a/frontend/client-portal/src/pages/Dashboard/DashboardBilling.tsx b/frontend/client-portal/src/pages/Dashboard/DashboardBilling.tsx new file mode 100644 index 00000000..c2619ca8 --- /dev/null +++ b/frontend/client-portal/src/pages/Dashboard/DashboardBilling.tsx @@ -0,0 +1,125 @@ +import React, { useEffect, useState, useContext } from "react"; +import { + Box, + Card, + CardContent, + Stack, + Typography, +} from "@mui/material"; +import axios from '../../utils/axios'; +import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate'; + +import { MonthlyBilling } from "./billingData"; +import MonthlyBillingCollapse from "./MonthlyBillingCollapse"; +import BillingFilterCard from "./BillingFilterCard"; + +const DashboardBilling: React.FC = () => { + const [billingData, setBillingData] = useState([]); + const [year, setYear] = useState(new Date().getFullYear()); +const [status, setStatus] = useState(null); +const [payorId, setPayorId] = useState(""); +const [bn, setBn] = useState(""); +const [service, setService] = useState(""); +const [billing, setBilling] = useState(""); +const [search, setSearch] = useState(""); + + const [loading, setLoading] = useState(false); + const { corporateValue } = useContext(UserCurrentCorporateContext); + const fetchBilling = async (params: any) => { + setLoading(true); + try { + const response = await axios.get(`${corporateValue}/billing/summary`, { + params, + }); + + setBillingData(response.data); + } catch (error) { + console.error("Failed fetch billing summary", error); + setBillingData([]); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + fetchBilling({ + year, + status, + payorId, + bn, + service, + billing, + search, + }); + }, [year, status, payorId, bn, service, billing, search]); + + + + + + return ( + + + + + {/* FILTER */} + + {/* LIST */} + {loading && ( + + Loading... + + )} + + {!loading && billingData.length === 0 && ( + + Tidak ada data + + )} + + {!loading && + billingData.map((item, index) => ( + + ))} + + + + + + ); +}; + +export default DashboardBilling; diff --git a/frontend/client-portal/src/pages/Dashboard/DashboardBillingDiagnosis.tsx b/frontend/client-portal/src/pages/Dashboard/DashboardBillingDiagnosis.tsx new file mode 100644 index 00000000..e164fc71 --- /dev/null +++ b/frontend/client-portal/src/pages/Dashboard/DashboardBillingDiagnosis.tsx @@ -0,0 +1,138 @@ +import React, { useEffect, useState, useContext } from "react"; +import { + Box, + Card, + CardContent, + Stack, + Typography, +} from "@mui/material"; +import axios from '../../utils/axios'; +import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate'; + +import { MonthlyBilling } from "./billingData"; +import MonthlyBillingCollapse from "./MonthlyBillingCollapse"; +import BillingFilterCard from "./BillingFilterCard"; +import BillingProviderList from "./BillingProviderList"; +import TopDiagnosisList from "./TopDiagnosisList"; +export interface ProviderBillingItem { + provider: string; + total: number; + } + + export interface ProviderBillingResponse { + total: number; + items: ProviderBillingItem[]; + } + + export interface TopDiagnosisItem { + code: string; + diagnosis: string; + total_case: number; + total_billing: number; + } + + const rupiah = (value: number) => + "Rp" + value.toLocaleString("id-ID"); + const DashboardBillingDiagnosis: React.FC = () => { + const [topDiagnosis, setTopDiagnosis] = + useState([]); + + const [year, setYear] = useState(new Date().getFullYear()); + const [status, setStatus] = useState(null); + const [payorId, setPayorId] = useState(""); + const [bn, setBn] = useState(""); + const [service, setService] = useState(""); + const [billing, setBilling] = useState(""); + const [search, setSearch] = useState(""); + + const [loading, setLoading] = useState(false); + const { corporateValue } = useContext(UserCurrentCorporateContext); + const fetchTopDiagnosis = async (params: any) => { + setLoading(true); + try { + const response = await axios.get( + `${corporateValue}/billing/top-diagnosis`, + { params } + ); + setTopDiagnosis(response.data); + } catch (error) { + console.error("Failed fetch top diagnosis", error); + setTopDiagnosis([]); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + fetchTopDiagnosis({ + year, + status, + payorId, + bn, + service, + billing, + search, + }); + }, [year, status, payorId, bn, service, billing, search]); + + + return ( + + + + + + + {loading && ( + + Loading... + + )} + + {!loading && topDiagnosis.length === 0 && ( + + Tidak ada data + + )} + + {!loading && topDiagnosis.length > 0 && ( + <> + + Top 10 Diagnosis + + + + + )} + + + + + ); + }; + + + +export default DashboardBillingDiagnosis; diff --git a/frontend/client-portal/src/pages/Dashboard/DashboardBillingProvider.tsx b/frontend/client-portal/src/pages/Dashboard/DashboardBillingProvider.tsx new file mode 100644 index 00000000..67dd4c73 --- /dev/null +++ b/frontend/client-portal/src/pages/Dashboard/DashboardBillingProvider.tsx @@ -0,0 +1,118 @@ +import React, { useEffect, useState, useContext } from "react"; +import { + Box, + Card, + CardContent, + Stack, + Typography, +} from "@mui/material"; +import axios from '../../utils/axios'; +import { UserCurrentCorporateContext } from '../../contexts/UserCurrentCorporate'; + +import { MonthlyBilling } from "./billingData"; +import MonthlyBillingCollapse from "./MonthlyBillingCollapse"; +import BillingFilterCard from "./BillingFilterCard"; +import BillingProviderList from "./BillingProviderList"; +export interface ProviderBillingItem { + provider: string; + total: number; + } + + export interface ProviderBillingResponse { + total: number; + items: ProviderBillingItem[]; + } + const rupiah = (value: number) => + "Rp" + value.toLocaleString("id-ID"); + const DashboardBillingProvider: React.FC = () => { + const [billingData, setBillingData] = + useState(null); + + const [year, setYear] = useState(new Date().getFullYear()); + const [status, setStatus] = useState(null); + const [payorId, setPayorId] = useState(""); + const [bn, setBn] = useState(""); + const [service, setService] = useState(""); + const [billing, setBilling] = useState(""); + const [search, setSearch] = useState(""); + + const [loading, setLoading] = useState(false); + const { corporateValue } = useContext(UserCurrentCorporateContext); + const fetchBilling = async (params: any) => { + setLoading(true); + try { + const response = await axios.get( + `${corporateValue}/billing/provider-summary`, + { params } + ); + setBillingData(response.data); + } catch { + setBillingData(null); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + fetchBilling({ + year, + status, + payorId, + bn, + service, + billing, + search, + }); + }, [year, status, payorId, bn, service, billing, search]); + + return ( + + + + + + + {loading && ( + + Loading... + + )} + + {!loading && billingData && ( + <> + + TOTAL BILLING OVERALL + + + + {rupiah(billingData.total)} + + + + + )} + + + + + ); + }; + + +export default DashboardBillingProvider; diff --git a/frontend/client-portal/src/pages/Dashboard/MonthlyBillingCollapse.tsx b/frontend/client-portal/src/pages/Dashboard/MonthlyBillingCollapse.tsx new file mode 100644 index 00000000..cdd0b1ba --- /dev/null +++ b/frontend/client-portal/src/pages/Dashboard/MonthlyBillingCollapse.tsx @@ -0,0 +1,131 @@ +import React, { useState } from "react"; +import { + Box, + Typography, + Collapse, + IconButton, + Divider, +} from "@mui/material"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; +import CalendarMonthIcon from "@mui/icons-material/CalendarMonth"; +import PaymentsIcon from "@mui/icons-material/Payments"; +import { MonthlyBilling } from "./billingData"; + +interface Props { + data: MonthlyBilling; +} + +const rupiah = (value: number) => + "Rp" + value.toLocaleString("id-ID"); + +const MonthlyBillingCollapse: React.FC = ({ data }) => { + const [open, setOpen] = useState(false); + + return ( + + {/* HEADER */} + setOpen(!open)} + sx={{ + px: 2, + py: 1.5, + display: "flex", + justifyContent: "space-between", + cursor: "pointer", + }} + > + + {/* ICON */} + + + + {/* TEXT */} + + + {data.month} + + + {rupiah(data.total)} + + + + + + + + + + + {/* BODY */} + + + + + + Nama Provider + + + Total Billing + + + + {data.items.map((item, idx) => ( + + {item.provider} + + {rupiah(item.total)} + + + ))} + + {data.items.length === 0 && ( + + Tidak ada data + + )} + + + + ); +}; + +export default MonthlyBillingCollapse; diff --git a/frontend/client-portal/src/pages/Dashboard/TopDiagnosisList.tsx b/frontend/client-portal/src/pages/Dashboard/TopDiagnosisList.tsx new file mode 100644 index 00000000..9722658f --- /dev/null +++ b/frontend/client-portal/src/pages/Dashboard/TopDiagnosisList.tsx @@ -0,0 +1,87 @@ +import { + Box, + Typography, + Divider, + } from "@mui/material"; + +// import { TopDiagnosisItem } from "./types"; + + const rupiah = (v: number) => + "Rp" + v.toLocaleString("id-ID"); + export interface TopDiagnosisItem { + code: string; + diagnosis: string; + total_case: number; + total_billing: number; + } + interface Props { + data: TopDiagnosisItem[]; + } + + const TopDiagnosisList: React.FC = ({ data }) => { + return ( + + {/* HEADER */} + + No + Kode + Diagnosa + + Jumlah Kasus + + + Total Billing + + + + {/* SCROLLABLE LIST */} + + {data.map((item, idx) => ( + + + {idx + 1} + {item.code} + {item.diagnosis} + + {item.total_case} + + + {rupiah(item.total_billing)} + + + + + ))} + + {data.length === 0 && ( + + Tidak ada data + + )} + + + ); + }; + + export default TopDiagnosisList; diff --git a/frontend/client-portal/src/pages/Dashboard/billingData.ts b/frontend/client-portal/src/pages/Dashboard/billingData.ts new file mode 100644 index 00000000..5d50930f --- /dev/null +++ b/frontend/client-portal/src/pages/Dashboard/billingData.ts @@ -0,0 +1,35 @@ +// billingData.ts +export interface BillingItem { + provider: string; + total: number; + } + + export interface MonthlyBilling { + month: string; + total: number; + items: BillingItem[]; + } + + export const billingData: MonthlyBilling[] = [ + { + month: "Januari", + total: 8884000, + items: [ + { provider: "Klinik Karya Morowali Utama", total: 753000 }, + { provider: "Klinik Karya Morowali Utama", total: 398000 }, + { provider: "Klinik Karya Morowali Utama", total: 753000 }, + { provider: "Klinik Karya Morowali Utama", total: 1425000 }, + { provider: "RS Hermina Kendari", total: 1425000 }, + ], + }, + { + month: "Februari", + total: 8884000, + items: [], + }, + { + month: "Maret", + total: 8884000, + items: [], + }, + ]; diff --git a/frontend/client-portal/src/routes/index.tsx b/frontend/client-portal/src/routes/index.tsx index 59f32953..a7f13440 100644 --- a/frontend/client-portal/src/routes/index.tsx +++ b/frontend/client-portal/src/routes/index.tsx @@ -437,7 +437,7 @@ export default function Router() { const Login = Loadable(lazy(() => import('../pages/auth/Login'))); // Dashboard -const Dashboard = Loadable(lazy(() => import('../pages/Dashboard/Index'))); +const Dashboard = Loadable(lazy(() => import('../pages/Dashboard/Dashboard'))); const NotFound = Loadable(lazy(() => import('../pages/Page404'))); // Employee Data