From 4091307e74ad65876add66b1750d00d9b2e4be79 Mon Sep 17 00:00:00 2001 From: arifal Date: Thu, 14 Aug 2025 21:58:28 +0700 Subject: [PATCH] fix revision hide menu and test case --- src/components/Sidebar.tsx | 504 ++++---- src/pages/Dashboard.tsx | 896 ++++++------- src/pages/medical-records/Administrative.tsx | 1109 +++++++++-------- .../medical-records/BPJSCodeification.tsx | 920 +++++++------- test-cases-medical-records.txt | 500 ++++---- 5 files changed, 1991 insertions(+), 1938 deletions(-) diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 9cd5f24..488948d 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -1,274 +1,274 @@ import { useState } from "react"; import { Link, useLocation } from "react-router-dom"; import { - LayoutDashboard, - Users, - FileText, - ChevronLeft, - ChevronRight, - UserCog, - Lock, - Database, - Shield, - TrendingUp, + LayoutDashboard, + Users, + FileText, + ChevronLeft, + ChevronRight, + // UserCog, + // Lock, + Database, + Shield, + TrendingUp, } from "lucide-react"; import { clsx } from "clsx"; import claimGuardLogo from "../assets/claim-guard.jpeg"; interface SidebarProps { - isCollapsed?: boolean; - onToggleCollapse?: () => void; + isCollapsed?: boolean; + onToggleCollapse?: () => void; } export default function Sidebar({ - isCollapsed = false, - onToggleCollapse, + isCollapsed = false, + onToggleCollapse, }: SidebarProps) { - const location = useLocation(); + const location = useLocation(); - const menuItems = [ - { - title: "Dashboard", - icon: LayoutDashboard, - path: "/dashboard", - color: "text-blue-600", - }, - { - title: "Integrasi Data", - icon: Database, - color: "text-blue-600", - submenu: [ - { - title: "Sinkronisasi BPJS", - icon: Shield, - path: "/integration/bpjs-sync", - }, - { - title: "Sinkronisasi Rekam Medis", - icon: FileText, - path: "/integration/medical-record-sync", - }, - ], - }, - { - title: "Rekam Medis", - icon: Users, - color: "text-blue-600", - submenu: [ - { - title: "Klinis", - icon: FileText, - path: "/medical-records/clinical", - }, - { - title: "Administratif", - icon: FileText, - path: "/medical-records/administrative", - }, - { - title: "Rekomendasi Biaya", - icon: TrendingUp, - path: "/medical-records/cost-recommendation", - }, - { - title: "Kodefikasi BPJS", - icon: FileText, - path: "/medical-records/bpjs-codification", - }, - ], - }, - { - title: "Administrasi Sistem", - icon: UserCog, - color: "text-blue-600", - submenu: [ - { - title: "Pengguna", - icon: Users, - path: "/system-administration/user", - }, - { - title: "Peran", - icon: Lock, - path: "/system-administration/role", - }, - ], - }, - ]; + const menuItems = [ + { + title: "Dashboard", + icon: LayoutDashboard, + path: "/dashboard", + color: "text-blue-600", + }, + { + title: "Integrasi Data", + icon: Database, + color: "text-blue-600", + submenu: [ + { + title: "Sinkronisasi BPJS", + icon: Shield, + path: "/integration/bpjs-sync", + }, + { + title: "Sinkronisasi Rekam Medis", + icon: FileText, + path: "/integration/medical-record-sync", + }, + ], + }, + { + title: "Rekam Medis", + icon: Users, + color: "text-blue-600", + submenu: [ + { + title: "Klinis", + icon: FileText, + path: "/medical-records/clinical", + }, + { + title: "Administratif", + icon: FileText, + path: "/medical-records/administrative", + }, + { + title: "Rekomendasi Biaya", + icon: TrendingUp, + path: "/medical-records/cost-recommendation", + }, + { + title: "Kodefikasi BPJS", + icon: FileText, + path: "/medical-records/bpjs-codification", + }, + ], + }, + // { + // title: "Administrasi Sistem", + // icon: UserCog, + // color: "text-blue-600", + // submenu: [ + // { + // title: "Pengguna", + // icon: Users, + // path: "/system-administration/user", + // }, + // { + // title: "Peran", + // icon: Lock, + // path: "/system-administration/role", + // }, + // ], + // }, + ]; - const [expandedMenu, setExpandedMenu] = useState(null); + const [expandedMenu, setExpandedMenu] = useState(null); - const toggleSubmenu = (title: string) => { - setExpandedMenu(expandedMenu === title ? null : title); - }; + const toggleSubmenu = (title: string) => { + setExpandedMenu(expandedMenu === title ? null : title); + }; - const isActive = (path: string) => location.pathname === path; + const isActive = (path: string) => location.pathname === path; - return ( -
- {/* Header */} -
-
- {!isCollapsed ? ( - <> -
-
- ClaimGuard Logo -
-
-

- ClaimGuard -

-

Hospital Management

-
-
- {onToggleCollapse && ( - - )} - - ) : ( -
- -
- )} -
-
+ return ( +
+ {/* Header */} +
+
+ {!isCollapsed ? ( + <> +
+
+ ClaimGuard Logo +
+
+

+ ClaimGuard +

+

Hospital Management

+
+
+ {onToggleCollapse && ( + + )} + + ) : ( +
+ +
+ )} +
+
- {/* Navigation */} - + {/* Divider */} +
+
+
+ - {/* Footer space */} -
-
- ); + {/* Footer space */} +
+
+ ); } diff --git a/src/pages/Dashboard.tsx b/src/pages/Dashboard.tsx index a80e521..a97ce9f 100644 --- a/src/pages/Dashboard.tsx +++ b/src/pages/Dashboard.tsx @@ -1,472 +1,472 @@ import { - Users, - TrendingUp, - AlertTriangle, - Shield, - Database, - RefreshCw, - FileText, - Search, - Bell, - CheckCircle, - XCircle, - Clock, - ArrowRight, - Code, - Stethoscope, + Users, + TrendingUp, + AlertTriangle, + Shield, + Database, + RefreshCw, + FileText, + Search, + Bell, + CheckCircle, + XCircle, + Clock, + ArrowRight, + Code, + Stethoscope, } from "lucide-react"; export default function Dashboard() { - // Stats berdasarkan fitur project yang ada - const stats = [ - { - title: "BPJS Sync Status", - value: "18/25", - change: "72% berhasil", - changeColor: "text-green-600", - icon: RefreshCw, - color: "text-blue-600", - subtitle: "Sync hari ini", - }, - { - title: "Medical Records", - value: "89", - change: "+12 hari ini", - changeColor: "text-green-600", - icon: FileText, - color: "text-green-600", - subtitle: "Record tersinkron", - }, - { - title: "ICD Recommendations", - value: "23", - change: "87% confidence", - changeColor: "text-blue-600", - icon: Code, - color: "text-purple-600", - subtitle: "Generated today", - }, - { - title: "Active Users", - value: "28/30", - change: "24 login hari ini", - changeColor: "text-green-600", - icon: Users, - color: "text-orange-600", - subtitle: "System users", - }, - ]; + // Stats berdasarkan fitur project yang ada + const stats = [ + { + title: "BPJS Sync Status", + value: "18/25", + change: "72% berhasil", + changeColor: "text-green-600", + icon: RefreshCw, + color: "text-blue-600", + subtitle: "Sync hari ini", + }, + { + title: "Medical Records", + value: "89", + change: "+12 hari ini", + changeColor: "text-green-600", + icon: FileText, + color: "text-green-600", + subtitle: "Record tersinkron", + }, + { + title: "ICD Recommendations", + value: "23", + change: "87% confidence", + changeColor: "text-blue-600", + icon: Code, + color: "text-purple-600", + subtitle: "Generated today", + }, + { + title: "Active Users", + value: "28/30", + change: "24 login hari ini", + changeColor: "text-green-600", + icon: Users, + color: "text-orange-600", + subtitle: "System users", + }, + ]; - return ( -
-
- {/* Welcome Section */} -
-

- Dashboard ClaimGuard -

-

- Monitor BPJS operations, medical records, ICD recommendations, dan - sistem management secara real-time. -

-
+ return ( +
+
+ {/* Welcome Section */} +
+

+ Dashboard ClaimGuard +

+

+ Monitor BPJS operations, medical records, ICD recommendations, dan + sistem management secara real-time. +

+
- {/* Alert/Warning Section */} -
-
-

- - Peringatan & Notifikasi -

- Real-time alerts -
-
-
-
-
-
- - - Overclaim Detected - -
-

- 7 kasus interval < 30 hari -

-

- ICD: I10, E11, J18.9 -

-
- -
-
+ {/* Alert/Warning Section */} +
+
+

+ + Peringatan & Notifikasi +

+ Real-time alerts +
+
+
+
+
+
+ + + Overclaim Detected + +
+

+ 7 kasus interval < 30 hari +

+

+ ICD: I10, E11, J18.9 +

+
+ +
+
-
-
-
-
- - - Inconsistent Visits - -
-

- 3 kontrol tidak konsisten -

-

- Tipe vs alasan tidak sesuai -

-
- -
-
+
+
+
+
+ + + Inconsistent Visits + +
+

+ 3 kontrol tidak konsisten +

+

+ Tipe vs alasan tidak sesuai +

+
+ +
+
-
-
-
-
- - - Sync Failures - -
-

- 5 BPJS sync gagal -

-

- Perlu retry manual -

-
- -
-
-
-
+
+
+
+
+ + + Sync Failures + +
+

+ 5 BPJS sync gagal +

+

+ Perlu retry manual +

+
+ +
+
+
+
- {/* Stats Grid */} -
- {stats.map((stat, index) => ( -
-
-
- -
- - {stat.change} - -
-
-

- {stat.value} -

-

- {stat.title} -

-

{stat.subtitle}

-
-
- ))} -
+ {/* Stats Grid */} +
+ {stats.map((stat, index) => ( +
+
+
+ +
+ + {stat.change} + +
+
+

+ {stat.value} +

+

+ {stat.title} +

+

{stat.subtitle}

+
+
+ ))} +
- {/* Main Grid */} -
- {/* BPJS Operations */} -
-
-

- - BPJS Operations -

- -
+ {/* Main Grid */} +
+ {/* BPJS Operations */} +
+
+

+ + BPJS Operations +

+ +
-
-
-
-
- - - Sync Status - -
-

Berhasil: 18/25 (72%)

-

- Last sync: 15 Jan 2024 14:30 -

-
-
-
18
-
Sukses hari ini
-
-
+
+
+
+
+ + + Sync Status + +
+

Berhasil: 18/25 (72%)

+

+ Last sync: 15 Jan 2024 14:30 +

+
+
+
18
+
Sukses hari ini
+
+
-
-
-
- - - Active Codes - -
-

156 kode BPJS aktif

-

- 8 kode baru bulan ini -

-
-
-
156
-
Total kode
-
-
+
+
+
+ + + Active Codes + +
+

156 kode BPJS aktif

+

+ 8 kode baru bulan ini +

+
+
+
156
+
Total kode
+
+
-
-
-
- - - Assist Coding - -
-

- 45 coding assistance -

-

12 queries hari ini

-
-
-
45
-
Total assist
-
-
-
-
+
+
+
+ + + Assist Coding + +
+

+ 45 coding assistance +

+

12 queries hari ini

+
+
+
45
+
Total assist
+
+
+
+
- {/* Medical Record Operations */} -
-
-

- - Medical Records -

- -
+ {/* Medical Record Operations */} +
+
+

+ + Medical Records +

+ +
-
-
-
-
- - - Sync Records - -
-

- 1,250 records tersinkron -

-

89 records hari ini

-
-
-
89
-
Hari ini
-
-
+
+
+
+
+ + + Sync Records + +
+

+ 1,250 records tersinkron +

+

89 records hari ini

+
+
+
89
+
Hari ini
+
+
-
-
-
- - - Patient Search - -
-

45 pencarian hari ini

-

84% success rate

-
-
-
45
-
Searches
-
-
+
+
+
+ + + Patient Search + +
+

45 pencarian hari ini

+

84% success rate

+
+
+
45
+
Searches
+
+
-
-
-
- - - Latest Records - -
-

- 30 records dalam 30 hari -

-

Filter aktif

-
-
-
30
-
Records
-
-
-
-
-
+
+
+
+ + + Latest Records + +
+

+ 30 records dalam 30 hari +

+

Filter aktif

+
+
+
30
+
Records
+
+
+
+
+
- {/* Second Row */} -
- {/* ICD Recommendations & Cost */} -
-
-

- - ICD & Cost Management -

- -
+ {/* Second Row */} +
+ {/* ICD Recommendations & Cost */} +
+
+

+ + ICD & Cost Management +

+ +
-
- {[ - { - title: "ICD Recommendations", - value: "23", - subtitle: "Generated today", - detail: "87% avg confidence", - color: "text-purple-600", - bgColor: "bg-purple-50", - icon: Code, - }, - { - title: "BPJS Mappings", - value: "19/23", - subtitle: "Successfully mapped", - detail: "83% mapping rate", - color: "text-blue-600", - bgColor: "bg-blue-50", - icon: Shield, - }, - { - title: "Cost Analysis", - value: "12", - subtitle: "Exports today", - detail: "JSON format", - color: "text-green-600", - bgColor: "bg-green-50", - icon: TrendingUp, - }, - ].map((item, index) => ( -
-
-
- - - {item.title} - -
-

- {item.subtitle} -

-

{item.detail}

-
-
-
- {item.value} -
-
-
- ))} -
-
+
+ {[ + { + title: "ICD Recommendations", + value: "23", + subtitle: "Generated today", + detail: "87% avg confidence", + color: "text-purple-600", + bgColor: "bg-purple-50", + icon: Code, + }, + { + title: "BPJS Mappings", + value: "19/23", + subtitle: "Successfully mapped", + detail: "83% mapping rate", + color: "text-blue-600", + bgColor: "bg-blue-50", + icon: Shield, + }, + { + title: "Cost Analysis", + value: "12", + subtitle: "Exports today", + detail: "JSON format", + color: "text-green-600", + bgColor: "bg-green-50", + icon: TrendingUp, + }, + ].map((item, index) => ( +
+
+
+ + + {item.title} + +
+

+ {item.subtitle} +

+

{item.detail}

+
+
+
+ {item.value} +
+
+
+ ))} +
+
- {/* System Management */} -
-
-

- - System Management -

- -
+ {/* System Management */} +
+
+

+ + System Management +

+ +
-
-
-
-
- - - User Management - -
-

28/30 active users

-

24 login hari ini

-
-
-
28
-
Active
-
-
+
+
+
+
+ + + User Management + +
+

28/30 active users

+

24 login hari ini

+
+
+
28
+
Active
+
+
-
-
-
- - - Role Management - -
-

25 roles configured

-

- 2 permissions updated -

-
-
-
25
-
Roles
-
-
+
+
+
+ + + Role Management + +
+

25 roles configured

+

+ 2 permissions updated +

+
+
+
25
+
Roles
+
+
-
-
-
- - - System Health - -
-

99.8% uptime

-

2.1% error rate

-
-
-
99.8%
-
Uptime
-
-
-
-
-
-
-
- ); +
+
+
+ + + System Health + +
+

99.8% uptime

+

2.1% error rate

+
+
+
99.8%
+
Uptime
+
+
+
+
+
+
+
+ ); } diff --git a/src/pages/medical-records/Administrative.tsx b/src/pages/medical-records/Administrative.tsx index 85f5dcf..774d7c6 100644 --- a/src/pages/medical-records/Administrative.tsx +++ b/src/pages/medical-records/Administrative.tsx @@ -1,15 +1,15 @@ import { useState } from "react"; import { - FileText, - Search, - User, - Calendar, - CreditCard, - Shield, - CheckCircle, - Clock, - AlertTriangle, - X, + FileText, + Search, + User, + Calendar, + CreditCard, + Shield, + CheckCircle, + Clock, + AlertTriangle, + X, } from "lucide-react"; import DatePicker from "react-datepicker"; import "react-datepicker/dist/react-datepicker.css"; @@ -17,24 +17,24 @@ import { registerLocale, setDefaultLocale } from "react-datepicker"; import { id } from "date-fns/locale"; interface PatientAdministrative { - name: string; - birthDate: string; - medicalRecordNumber: string; - bpjsNumber: string; - lastVisit: { - date: string; - department: string; - doctor: string; - visitType: string; - }; - claimStatus: "approved" | "pending" | "rejected" | "under_review"; - paymentStatus: "paid" | "pending" | "partial" | "overdue"; - insuranceType: string; - totalCost: number; - paidAmount: number; - outstandingAmount: number; - admissionType: "outpatient" | "inpatient" | "emergency"; - roomClass?: string; + name: string; + birthDate: string; + medicalRecordNumber: string; + bpjsNumber: string; + lastVisit: { + date: string; + department: string; + doctor: string; + visitType: string; + }; + claimStatus: "approved" | "pending" | "rejected" | "under_review"; + paymentStatus: "paid" | "pending" | "partial" | "overdue"; + insuranceType: string; + totalCost: number; + paidAmount: number; + outstandingAmount: number; + admissionType: "outpatient" | "inpatient" | "emergency"; + roomClass?: string; } // Register Indonesian locale for DatePicker @@ -42,541 +42,560 @@ registerLocale("id", id); setDefaultLocale("id"); export default function Administrative() { - const [searchQuery, setSearchQuery] = useState(""); - const [birthDate, setBirthDate] = useState(null); - const [searchResults, setSearchResults] = - useState(null); - const [isSearching, setIsSearching] = useState(false); + const [searchQuery, setSearchQuery] = useState(""); + const [birthDate, setBirthDate] = useState(null); + const [searchResults, setSearchResults] = + useState(null); + const [isSearching, setIsSearching] = useState(false); - const formatDate = (dateString: string) => { - const date = new Date(dateString); - return date.toLocaleDateString("id-ID", { - day: "2-digit", - month: "short", - year: "numeric", - }); - }; + const formatDate = (dateString: string) => { + const date = new Date(dateString); + return date.toLocaleDateString("id-ID", { + day: "2-digit", + month: "short", + year: "numeric", + }); + }; - const formatCurrency = (amount: number) => { - return new Intl.NumberFormat("id-ID", { - style: "currency", - currency: "IDR", - minimumFractionDigits: 0, - }).format(amount); - }; + const formatCurrency = (amount: number) => { + return new Intl.NumberFormat("id-ID", { + style: "currency", + currency: "IDR", + minimumFractionDigits: 0, + }).format(amount); + }; - const calculateAge = (birthDate: string) => { - const birth = new Date(birthDate); - const today = new Date(); - let age = today.getFullYear() - birth.getFullYear(); - const monthDiff = today.getMonth() - birth.getMonth(); - if ( - monthDiff < 0 || - (monthDiff === 0 && today.getDate() < birth.getDate()) - ) { - age--; - } - return age; - }; + const calculateAge = (birthDate: string) => { + const birth = new Date(birthDate); + const today = new Date(); + let age = today.getFullYear() - birth.getFullYear(); + const monthDiff = today.getMonth() - birth.getMonth(); + if ( + monthDiff < 0 || + (monthDiff === 0 && today.getDate() < birth.getDate()) + ) { + age--; + } + return age; + }; - const getClaimStatusColor = (status: string) => { - switch (status) { - case "approved": - return "bg-green-100 text-green-800"; - case "pending": - return "bg-yellow-100 text-yellow-800"; - case "rejected": - return "bg-red-100 text-red-800"; - case "under_review": - return "bg-blue-100 text-blue-800"; - default: - return "bg-gray-100 text-gray-800"; - } - }; + const getClaimStatusColor = (status: string) => { + switch (status) { + case "approved": + return "bg-green-100 text-green-800"; + case "pending": + return "bg-yellow-100 text-yellow-800"; + case "rejected": + return "bg-red-100 text-red-800"; + case "under_review": + return "bg-blue-100 text-blue-800"; + default: + return "bg-gray-100 text-gray-800"; + } + }; - const getPaymentStatusColor = (status: string) => { - switch (status) { - case "paid": - return "bg-green-100 text-green-800"; - case "pending": - return "bg-yellow-100 text-yellow-800"; - case "partial": - return "bg-orange-100 text-orange-800"; - case "overdue": - return "bg-red-100 text-red-800"; - default: - return "bg-gray-100 text-gray-800"; - } - }; + const getPaymentStatusColor = (status: string) => { + switch (status) { + case "paid": + return "bg-green-100 text-green-800"; + case "pending": + return "bg-yellow-100 text-yellow-800"; + case "partial": + return "bg-orange-100 text-orange-800"; + case "overdue": + return "bg-red-100 text-red-800"; + default: + return "bg-gray-100 text-gray-800"; + } + }; - const getClaimStatusIcon = (status: string) => { - switch (status) { - case "approved": - return ; - case "pending": - return ; - case "rejected": - return ; - case "under_review": - return ; - default: - return ; - } - }; + const getClaimStatusIcon = (status: string) => { + switch (status) { + case "approved": + return ; + case "pending": + return ; + case "rejected": + return ; + case "under_review": + return ; + default: + return ; + } + }; - const getClaimStatusText = (status: string) => { - switch (status) { - case "approved": - return "Disetujui"; - case "pending": - return "Menunggu"; - case "rejected": - return "Ditolak"; - case "under_review": - return "Sedang Ditinjau"; - default: - return status; - } - }; + const getClaimStatusText = (status: string) => { + switch (status) { + case "approved": + return "Disetujui"; + case "pending": + return "Menunggu"; + case "rejected": + return "Ditolak"; + case "under_review": + return "Sedang Ditinjau"; + default: + return status; + } + }; - const getPaymentStatusText = (status: string) => { - switch (status) { - case "paid": - return "Lunas"; - case "pending": - return "Menunggu"; - case "partial": - return "Sebagian"; - case "overdue": - return "Terlambat"; - default: - return status; - } - }; + const getPaymentStatusText = (status: string) => { + switch (status) { + case "paid": + return "Lunas"; + case "pending": + return "Menunggu"; + case "partial": + return "Sebagian"; + case "overdue": + return "Terlambat"; + default: + return status; + } + }; - // Mock administrative data - const mockAdministrativeData: PatientAdministrative[] = [ - { - name: "Ahmad Budi Santoso", - birthDate: "1985-05-10", - medicalRecordNumber: "MRN2024001", - bpjsNumber: "0001234567890", - lastVisit: { - date: "2024-07-18", - department: "Poli Penyakit Dalam", - doctor: "Dr. Anya Wijaya", - visitType: "Kontrol Rutin", - }, - claimStatus: "approved", - paymentStatus: "paid", - insuranceType: "BPJS Kesehatan", - totalCost: 2500000, - paidAmount: 2500000, - outstandingAmount: 0, - admissionType: "outpatient", - }, - { - name: "Siti Aminah", - birthDate: "1990-11-22", - medicalRecordNumber: "MRN2024002", - bpjsNumber: "0009876543210", - lastVisit: { - date: "2024-07-19", - department: "Poli Paru", - doctor: "Dr. Bima Sakti", - visitType: "Kunjungan Baru", - }, - claimStatus: "under_review", - paymentStatus: "pending", - insuranceType: "BPJS Kesehatan", - totalCost: 1800000, - paidAmount: 0, - outstandingAmount: 1800000, - admissionType: "outpatient", - }, - { - name: "Roberto Silva", - birthDate: "1978-03-15", - medicalRecordNumber: "MRN2024003", - bpjsNumber: "0003456789012", - lastVisit: { - date: "2024-07-17", - department: "IGD", - doctor: "Dr. Linda Sari", - visitType: "Emergency", - }, - claimStatus: "pending", - paymentStatus: "partial", - insuranceType: "BPJS Kesehatan", - totalCost: 5200000, - paidAmount: 3000000, - outstandingAmount: 2200000, - admissionType: "inpatient", - roomClass: "Kelas 2", - }, - ]; + // Mock administrative data + const mockAdministrativeData: PatientAdministrative[] = [ + { + name: "Ahmad Budi Santoso", + birthDate: "1985-05-10", + medicalRecordNumber: "MRN2024001", + bpjsNumber: "0001234567890", + lastVisit: { + date: "2024-07-18", + department: "Poli Penyakit Dalam", + doctor: "Dr. Anya Wijaya", + visitType: "Kontrol Rutin", + }, + claimStatus: "approved", + paymentStatus: "paid", + insuranceType: "BPJS Kesehatan", + totalCost: 2500000, + paidAmount: 2500000, + outstandingAmount: 0, + admissionType: "outpatient", + }, + { + name: "Siti Aminah", + birthDate: "1990-11-22", + medicalRecordNumber: "MRN2024002", + bpjsNumber: "0009876543210", + lastVisit: { + date: "2024-07-19", + department: "Poli Paru", + doctor: "Dr. Bima Sakti", + visitType: "Kunjungan Baru", + }, + claimStatus: "under_review", + paymentStatus: "pending", + insuranceType: "BPJS Kesehatan", + totalCost: 1800000, + paidAmount: 0, + outstandingAmount: 1800000, + admissionType: "outpatient", + }, + { + name: "Roberto Silva", + birthDate: "1978-03-15", + medicalRecordNumber: "MRN2024003", + bpjsNumber: "0003456789012", + lastVisit: { + date: "2024-07-17", + department: "IGD", + doctor: "Dr. Linda Sari", + visitType: "Emergency", + }, + claimStatus: "pending", + paymentStatus: "partial", + insuranceType: "BPJS Kesehatan", + totalCost: 5200000, + paidAmount: 3000000, + outstandingAmount: 2200000, + admissionType: "inpatient", + roomClass: "Kelas 2", + }, + ]; - const handleSearch = () => { - setIsSearching(true); - setSearchResults(null); + const handleSearch = () => { + setIsSearching(true); + setSearchResults(null); - setTimeout(() => { - const query = searchQuery.toLowerCase(); - const foundPatient = mockAdministrativeData.find( - (patient) => - patient.name.toLowerCase().includes(query) || - patient.medicalRecordNumber.toLowerCase().includes(query) || - patient.bpjsNumber.includes(query) - ); + setTimeout(() => { + const query = searchQuery.toLowerCase().trim(); - if (foundPatient) { - // Further filter by birth date if provided - if (birthDate) { - const patientBirthDate = new Date(foundPatient.birthDate); - if ( - patientBirthDate.getDate() === birthDate.getDate() && - patientBirthDate.getMonth() === birthDate.getMonth() && - patientBirthDate.getFullYear() === birthDate.getFullYear() - ) { - setSearchResults(foundPatient); - } else { - setSearchResults(null); - } - } else { - setSearchResults(foundPatient); - } - } else { - setSearchResults(null); - } - setIsSearching(false); - }, 1000); - }; + if (!query) { + setSearchResults(null); + setIsSearching(false); + return; + } - const handleClear = () => { - setSearchQuery(""); - setBirthDate(null); - setSearchResults(null); - }; + const foundPatient = mockAdministrativeData.find((patient) => { + // Normalize patient data to lowercase for case-insensitive search + const patientName = patient.name.toLowerCase(); + const patientMRN = patient.medicalRecordNumber.toLowerCase(); + const patientBPJS = patient.bpjsNumber.toLowerCase(); - return ( -
- {/* Header */} -
-
- -
-
-

- Rekam Medis Administratif -

-

- Cari dan kelola informasi administrasi dan tagihan pasien -

-
-
+ // For name search, check if all words in query exist in patient name + const queryWords = query.split(/\s+/).filter((word) => word.length > 0); + const nameMatch = queryWords.every((word) => + patientName.includes(word) + ); - {/* Search Section */} -
-

- Cari Rekam Medis Administratif Pasien -

-
-
- -
- - setSearchQuery(e.target.value)} - /> -
-
-
- - setBirthDate(date)} - dateFormat="dd MMMM yyyy" - showYearDropdown - showMonthDropdown - dropdownMode="select" - placeholderText="Pilih tanggal lahir" - className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" - locale="id" - /> -
-
- - -
-
-
+ // For MRN and BPJS, use simple includes + const mrnMatch = patientMRN.includes(query); + const bpjsMatch = patientBPJS.includes(query); - {/* Administrative Results Section */} - {searchResults ? ( -
-

- Informasi Administratif untuk {searchResults.name} -

+ return nameMatch || mrnMatch || bpjsMatch; + }); -
- {/* Patient Basic Information */} -
-
-

- Informasi Pasien -

-
-
- - Nama Pasien: - -

- {searchResults.name} -

-
-
- - Tanggal Lahir: - -

- {formatDate(searchResults.birthDate)} ( - {calculateAge(searchResults.birthDate)} tahun) -

-
-
- - Nomor Rekam Medis: - -

- {searchResults.medicalRecordNumber} -

-
-
- - Nomor BPJS: - -

- {searchResults.bpjsNumber} -

-
-
-
+ if (foundPatient) { + // Further filter by birth date if provided + if (birthDate) { + const patientBirthDate = new Date(foundPatient.birthDate); + if ( + patientBirthDate.getDate() === birthDate.getDate() && + patientBirthDate.getMonth() === birthDate.getMonth() && + patientBirthDate.getFullYear() === birthDate.getFullYear() + ) { + setSearchResults(foundPatient); + } else { + setSearchResults(null); + } + } else { + setSearchResults(foundPatient); + } + } else { + setSearchResults(null); + } + setIsSearching(false); + }, 1000); + }; - {/* Visit History */} -
-

- Riwayat Kunjungan - Terakhir -

-
-
- - Tanggal Kunjungan: - -

- {formatDate(searchResults.lastVisit.date)} -

-
-
- - Departemen: - -

- {searchResults.lastVisit.department} -

-
-
- - Dokter: - -

- {searchResults.lastVisit.doctor} -

-
-
- - Tipe Kunjungan: - -

- {searchResults.lastVisit.visitType} -

-
-
- - Tipe Rawat: - -

- {searchResults.admissionType === "outpatient" - ? "Rawat Jalan" - : searchResults.admissionType === "inpatient" - ? "Rawat Inap" - : "Gawat Darurat"} - {searchResults.roomClass && - ` - ${searchResults.roomClass}`} -

-
-
-
-
+ const handleClear = () => { + setSearchQuery(""); + setBirthDate(null); + setSearchResults(null); + }; - {/* Status and Financial Information */} -
- {/* Claim Status */} -
-

- Status Klaim -

-
-
- - Jenis Asuransi: - -

- {searchResults.insuranceType} -

-
-
- - Status Klaim: - -
- - {getClaimStatusIcon(searchResults.claimStatus)} - - {getClaimStatusText(searchResults.claimStatus)} - - -
-
-
-
+ return ( +
+ {/* Header */} +
+
+ +
+
+

+ Rekam Medis Administratif +

+

+ Cari dan kelola informasi administrasi dan tagihan pasien +

+
+
- {/* Payment Status */} -
-

- Status Pembayaran -

-
-
- - Total Biaya: - -

- {formatCurrency(searchResults.totalCost)} -

-
-
- - Jumlah Dibayar: - -

- {formatCurrency(searchResults.paidAmount)} -

-
-
- - Sisa Tagihan: - -

0 - ? "text-red-600" - : "text-green-600" - }`} - > - {formatCurrency(searchResults.outstandingAmount)} -

-
-
- - Status Pembayaran: - -
- - {getPaymentStatusText(searchResults.paymentStatus)} - -
-
-
-
-
-
-
- ) : ( -
- -

- {isSearching - ? "Mencari..." - : "Rekam medis administratif tidak ditemukan"} -

-

- {isSearching - ? "Mohon tunggu sementara kami mengambil informasi administratif." - : "Masukkan detail pasien di form pencarian di atas untuk menemukan rekam medis administratif."} -

-
- )} -
- ); + {/* Search Section */} +
+

+ Cari Rekam Medis Administratif Pasien +

+
+
+ +
+ + setSearchQuery(e.target.value)} + /> +
+
+
+ + setBirthDate(date)} + dateFormat="dd MMMM yyyy" + showYearDropdown + showMonthDropdown + dropdownMode="select" + placeholderText="Pilih tanggal lahir" + className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" + locale="id" + /> +
+
+ + +
+
+
+ + {/* Administrative Results Section */} + {searchResults ? ( +
+

+ Informasi Administratif untuk {searchResults.name} +

+ +
+ {/* Patient Basic Information */} +
+
+

+ Informasi Pasien +

+
+
+ + Nama Pasien: + +

+ {searchResults.name} +

+
+
+ + Tanggal Lahir: + +

+ {formatDate(searchResults.birthDate)} ( + {calculateAge(searchResults.birthDate)} tahun) +

+
+
+ + Nomor Rekam Medis: + +

+ {searchResults.medicalRecordNumber} +

+
+
+ + Nomor BPJS: + +

+ {searchResults.bpjsNumber} +

+
+
+
+ + {/* Visit History */} +
+

+ Riwayat Kunjungan + Terakhir +

+
+
+ + Tanggal Kunjungan: + +

+ {formatDate(searchResults.lastVisit.date)} +

+
+
+ + Departemen: + +

+ {searchResults.lastVisit.department} +

+
+
+ + Dokter: + +

+ {searchResults.lastVisit.doctor} +

+
+
+ + Tipe Kunjungan: + +

+ {searchResults.lastVisit.visitType} +

+
+
+ + Tipe Rawat: + +

+ {searchResults.admissionType === "outpatient" + ? "Rawat Jalan" + : searchResults.admissionType === "inpatient" + ? "Rawat Inap" + : "Gawat Darurat"} + {searchResults.roomClass && + ` - ${searchResults.roomClass}`} +

+
+
+
+
+ + {/* Status and Financial Information */} +
+ {/* Claim Status */} +
+

+ Status Klaim +

+
+
+ + Jenis Asuransi: + +

+ {searchResults.insuranceType} +

+
+
+ + Status Klaim: + +
+ + {getClaimStatusIcon(searchResults.claimStatus)} + + {getClaimStatusText(searchResults.claimStatus)} + + +
+
+
+
+ + {/* Payment Status */} +
+

+ Status Pembayaran +

+
+
+ + Total Biaya: + +

+ {formatCurrency(searchResults.totalCost)} +

+
+
+ + Jumlah Dibayar: + +

+ {formatCurrency(searchResults.paidAmount)} +

+
+
+ + Sisa Tagihan: + +

0 + ? "text-red-600" + : "text-green-600" + }`} + > + {formatCurrency(searchResults.outstandingAmount)} +

+
+
+ + Status Pembayaran: + +
+ + {getPaymentStatusText(searchResults.paymentStatus)} + +
+
+
+
+
+
+
+ ) : ( +
+ +

+ {isSearching + ? "Mencari..." + : "Rekam medis administratif tidak ditemukan"} +

+

+ {isSearching + ? "Mohon tunggu sementara kami mengambil informasi administratif." + : "Masukkan detail pasien di form pencarian di atas untuk menemukan rekam medis administratif."} +

+
+ )} +
+ ); } diff --git a/src/pages/medical-records/BPJSCodeification.tsx b/src/pages/medical-records/BPJSCodeification.tsx index aa2b215..fe86e70 100644 --- a/src/pages/medical-records/BPJSCodeification.tsx +++ b/src/pages/medical-records/BPJSCodeification.tsx @@ -1,520 +1,498 @@ import { useState } from "react"; import { - Code, - AlertCircle, - Wand2, - ShieldCheck, - ClipboardList, - FileText, + Code, + AlertCircle, + Wand2, + ShieldCheck, + ClipboardList, + FileText, } from "lucide-react"; interface AssistInput { - clinicalNotes: string; - labResults: string; - procedures: string; + clinicalNotes: string; + procedures: string; } interface ICD10Code { - code: string; - description: string; - reasoning: string; + code: string; + description: string; + reasoning: string; } interface ProcedureCode { - code: string; - description: string; - reasoning: string; + code: string; + description: string; + reasoning: string; } interface BPJSMapping { - ina_cbg_code: string; - description: string; - tariff: number; + ina_cbg_code: string; + description: string; + tariff: number; } interface AssistResult { - icd_10_codes: ICD10Code[]; - procedure_codes: ProcedureCode[]; - bpjs_mapping: BPJSMapping; + icd_10_codes: ICD10Code[]; + procedure_codes: ProcedureCode[]; + bpjs_mapping: BPJSMapping; } export default function BPJSCodeification() { - const [assistInput, setAssistInput] = useState({ - clinicalNotes: "", - labResults: "", - procedures: "", - }); - const [assistLoading, setAssistLoading] = useState(false); - const [assistError, setAssistError] = useState(null); - const [assistResult, setAssistResult] = useState(null); + const [assistInput, setAssistInput] = useState({ + clinicalNotes: "", + procedures: "", + }); + const [assistLoading, setAssistLoading] = useState(false); + const [assistError, setAssistError] = useState(null); + const [assistResult, setAssistResult] = useState(null); - const formatCurrency = (amount: number) => - new Intl.NumberFormat("id-ID", { - style: "currency", - currency: "IDR", - minimumFractionDigits: 0, - }).format(amount); + const formatCurrency = (amount: number) => + new Intl.NumberFormat("id-ID", { + style: "currency", + currency: "IDR", + minimumFractionDigits: 0, + }).format(amount); - // Mock pipeline with improved JSON output format - const preprocessInput = (input: AssistInput): AssistInput => { - const normalize = (s: string) => s.replace(/\s+/g, " ").trim(); - return { - clinicalNotes: normalize(input.clinicalNotes), - labResults: normalize(input.labResults), - procedures: normalize(input.procedures), - }; - }; + // Mock pipeline with improved JSON output format + const preprocessInput = (input: AssistInput): AssistInput => { + const normalize = (s: string) => s.replace(/\s+/g, " ").trim(); + return { + clinicalNotes: normalize(input.clinicalNotes), + procedures: normalize(input.procedures), + }; + }; - const mockAssistPipeline = async ( - input: AssistInput - ): Promise => { - const text = - `${input.clinicalNotes} ${input.labResults} ${input.procedures}`.toLowerCase(); + const mockAssistPipeline = async ( + input: AssistInput + ): Promise => { + const text = `${input.clinicalNotes} ${input.procedures}`.toLowerCase(); - const icd10Codes: ICD10Code[] = []; - const procedureCodes: ProcedureCode[] = []; + const icd10Codes: ICD10Code[] = []; + const procedureCodes: ProcedureCode[] = []; - // ICD-10 Code Detection - if ( - text.includes("pneumonia") || - text.includes("infiltrat") || - text.includes("demam") || - text.includes("batuk") || - text.includes("sesak") - ) { - icd10Codes.push({ - code: "J18.9", - description: "Pneumonia dengan kuman tidak spesifik", - reasoning: - "Gejala demam, batuk, sesak napas, dan hasil pemeriksaan rontgen mengarah pada pneumonia.", - }); - } + // ICD-10 Code Detection + if ( + text.includes("pneumonia") || + text.includes("infiltrat") || + text.includes("demam") || + text.includes("batuk") || + text.includes("sesak") + ) { + icd10Codes.push({ + code: "J18.9", + description: "Pneumonia dengan kuman tidak spesifik", + reasoning: + "Gejala demam, batuk, sesak napas, dan hasil pemeriksaan rontgen mengarah pada pneumonia.", + }); + } - if ( - text.includes("hipertensi") || - text.includes("bp 150/95") || - text.includes("tekanan darah tinggi") || - text.includes("hypertension") - ) { - icd10Codes.push({ - code: "I10", - description: "Hipertensi esensial (primer)", - reasoning: - "Temuan tekanan darah tinggi pada catatan klinis dan pemeriksaan fisik.", - }); - } + if ( + text.includes("hipertensi") || + text.includes("bp 150/95") || + text.includes("tekanan darah tinggi") || + text.includes("hypertension") + ) { + icd10Codes.push({ + code: "I10", + description: "Hipertensi esensial (primer)", + reasoning: + "Temuan tekanan darah tinggi pada catatan klinis dan pemeriksaan fisik.", + }); + } - if ( - text.includes("diabetes") || - text.includes("hba1c") || - text.includes("glukosa") || - text.includes("gula darah") - ) { - icd10Codes.push({ - code: "E11.9", - description: "Diabetes mellitus tipe 2 tanpa komplikasi", - reasoning: - "Hasil laboratorium menunjukkan peningkatan HbA1c dan glukosa darah yang mendukung diagnosis diabetes.", - }); - } + if ( + text.includes("diabetes") || + text.includes("hba1c") || + text.includes("glukosa") || + text.includes("gula darah") + ) { + icd10Codes.push({ + code: "E11.9", + description: "Diabetes mellitus tipe 2 tanpa komplikasi", + reasoning: + "Hasil laboratorium menunjukkan peningkatan HbA1c dan glukosa darah yang mendukung diagnosis diabetes.", + }); + } - if ( - text.includes("gastritis") || - text.includes("nyeri perut") || - text.includes("mual") || - text.includes("muntah") - ) { - icd10Codes.push({ - code: "K29.1", - description: "Gastritis akut lainnya", - reasoning: - "Gejala nyeri perut, mual, muntah mengarah pada gastritis akut.", - }); - } + if ( + text.includes("gastritis") || + text.includes("nyeri perut") || + text.includes("mual") || + text.includes("muntah") + ) { + icd10Codes.push({ + code: "K29.1", + description: "Gastritis akut lainnya", + reasoning: + "Gejala nyeri perut, mual, muntah mengarah pada gastritis akut.", + }); + } - if ( - text.includes("influenza") || - text.includes("flu") || - text.includes("demam") || - text.includes("sakit kepala") - ) { - icd10Codes.push({ - code: "J11.1", - description: - "Influenza dengan virus tidak teridentifikasi disertai manifestasi respiratori", - reasoning: - "Gejala demam, sakit kepala, dan manifestasi respiratori mengarah pada influenza.", - }); - } + if ( + text.includes("influenza") || + text.includes("flu") || + text.includes("demam") || + text.includes("sakit kepala") + ) { + icd10Codes.push({ + code: "J11.1", + description: + "Influenza dengan virus tidak teridentifikasi disertai manifestasi respiratori", + reasoning: + "Gejala demam, sakit kepala, dan manifestasi respiratori mengarah pada influenza.", + }); + } - // Procedure Code Detection - if ( - text.includes("rontgen") || - text.includes("x-ray") || - text.includes("chest x-ray") || - text.includes("foto thorax") - ) { - procedureCodes.push({ - code: "87.44", - description: "Foto Rontgen thorax, proyeksi tunggal", - reasoning: "Tindakan rontgen dada sesuai gejala respiratori.", - }); - } + // Procedure Code Detection + if ( + text.includes("rontgen") || + text.includes("x-ray") || + text.includes("chest x-ray") || + text.includes("foto thorax") + ) { + procedureCodes.push({ + code: "87.44", + description: "Foto Rontgen thorax, proyeksi tunggal", + reasoning: "Tindakan rontgen dada sesuai gejala respiratori.", + }); + } - if ( - text.includes("darah lengkap") || - text.includes("complete blood count") || - text.includes("cbc") || - text.includes("lab darah") - ) { - procedureCodes.push({ - code: "90.59", - description: "Pemeriksaan darah lengkap", - reasoning: "Pemeriksaan darah lengkap untuk mendukung diagnosis.", - }); - } + if ( + text.includes("darah lengkap") || + text.includes("complete blood count") || + text.includes("cbc") || + text.includes("lab darah") + ) { + procedureCodes.push({ + code: "90.59", + description: "Pemeriksaan darah lengkap", + reasoning: "Pemeriksaan darah lengkap untuk mendukung diagnosis.", + }); + } - if ( - text.includes("endoskopi") || - text.includes("endoscopy") || - text.includes("gastroscopy") - ) { - procedureCodes.push({ - code: "45.13", - description: "Esofagogastroduodenoskopi (EGD)", - reasoning: "Tindakan endoskopi lambung untuk evaluasi gastritis.", - }); - } + if ( + text.includes("endoskopi") || + text.includes("endoscopy") || + text.includes("gastroscopy") + ) { + procedureCodes.push({ + code: "45.13", + description: "Esofagogastroduodenoskopi (EGD)", + reasoning: "Tindakan endoskopi lambung untuk evaluasi gastritis.", + }); + } - if ( - text.includes("ekg") || - text.includes("ecg") || - text.includes("elektrokardiogram") - ) { - procedureCodes.push({ - code: "89.52", - description: "Elektrokardiogram (EKG)", - reasoning: "Pemeriksaan EKG untuk evaluasi kardiovaskular.", - }); - } + if ( + text.includes("ekg") || + text.includes("ecg") || + text.includes("elektrokardiogram") + ) { + procedureCodes.push({ + code: "89.52", + description: "Elektrokardiogram (EKG)", + reasoning: "Pemeriksaan EKG untuk evaluasi kardiovaskular.", + }); + } - if ( - text.includes("usg") || - text.includes("ultrasound") || - text.includes("ultrasonografi") - ) { - procedureCodes.push({ - code: "88.76", - description: "USG abdomen dan retroperitoneum diagnostik", - reasoning: "Pemeriksaan USG abdomen untuk evaluasi organ dalam.", - }); - } + if ( + text.includes("usg") || + text.includes("ultrasound") || + text.includes("ultrasonografi") + ) { + procedureCodes.push({ + code: "88.76", + description: "USG abdomen dan retroperitoneum diagnostik", + reasoning: "Pemeriksaan USG abdomen untuk evaluasi organ dalam.", + }); + } - // Default codes if nothing specific detected - if (icd10Codes.length === 0) { - icd10Codes.push({ - code: "R69", - description: "Penyakit tidak spesifik", - reasoning: - "Tidak ada gejala spesifik yang terdeteksi, memerlukan klarifikasi klinis lebih lanjut.", - }); - } + // Default codes if nothing specific detected + if (icd10Codes.length === 0) { + icd10Codes.push({ + code: "R69", + description: "Penyakit tidak spesifik", + reasoning: + "Tidak ada gejala spesifik yang terdeteksi, memerlukan klarifikasi klinis lebih lanjut.", + }); + } - if (procedureCodes.length === 0) { - procedureCodes.push({ - code: "99213", - description: "Kunjungan rawat jalan", - reasoning: "Kunjungan rawat jalan untuk evaluasi medis.", - }); - } + if (procedureCodes.length === 0) { + procedureCodes.push({ + code: "99213", + description: "Kunjungan rawat jalan", + reasoning: "Kunjungan rawat jalan untuk evaluasi medis.", + }); + } - // BPJS Mapping based on primary diagnosis - let bpjsMapping: BPJSMapping; + // BPJS Mapping based on primary diagnosis + let bpjsMapping: BPJSMapping; - const hasPneumonia = icd10Codes.some((code) => code.code.startsWith("J18")); - const hasDiabetes = icd10Codes.some((code) => code.code.startsWith("E11")); - const hasHypertension = icd10Codes.some((code) => - code.code.startsWith("I10") - ); - const hasGastritis = icd10Codes.some((code) => code.code.startsWith("K29")); - const hasInfluenza = icd10Codes.some((code) => code.code.startsWith("J11")); + const hasPneumonia = icd10Codes.some((code) => code.code.startsWith("J18")); + const hasDiabetes = icd10Codes.some((code) => code.code.startsWith("E11")); + const hasHypertension = icd10Codes.some((code) => + code.code.startsWith("I10") + ); + const hasGastritis = icd10Codes.some((code) => code.code.startsWith("K29")); + const hasInfluenza = icd10Codes.some((code) => code.code.startsWith("J11")); - if (hasPneumonia) { - bpjsMapping = { - ina_cbg_code: "B-4-13-I", - description: "Pneumonia tanpa komplikasi", - tariff: 3500000, - }; - } else if (hasDiabetes) { - bpjsMapping = { - ina_cbg_code: "E-4-10-I", - description: "Diabetes Mellitus tanpa komplikasi", - tariff: 2100000, - }; - } else if (hasHypertension) { - bpjsMapping = { - ina_cbg_code: "F-4-13-II", - description: "Hipertensi dengan komplikasi minor", - tariff: 1850000, - }; - } else if (hasGastritis) { - bpjsMapping = { - ina_cbg_code: "G-4-10-I", - description: "Gastritis akut tanpa komplikasi", - tariff: 1200000, - }; - } else if (hasInfluenza) { - bpjsMapping = { - ina_cbg_code: "H-4-11-I", - description: "Influenza tanpa komplikasi", - tariff: 950000, - }; - } else { - bpjsMapping = { - ina_cbg_code: "Z-4-00-I", - description: "Kondisi tidak spesifik", - tariff: 750000, - }; - } + if (hasPneumonia) { + bpjsMapping = { + ina_cbg_code: "B-4-13-I", + description: "Pneumonia tanpa komplikasi", + tariff: 3500000, + }; + } else if (hasDiabetes) { + bpjsMapping = { + ina_cbg_code: "E-4-10-I", + description: "Diabetes Mellitus tanpa komplikasi", + tariff: 2100000, + }; + } else if (hasHypertension) { + bpjsMapping = { + ina_cbg_code: "F-4-13-II", + description: "Hipertensi dengan komplikasi minor", + tariff: 1850000, + }; + } else if (hasGastritis) { + bpjsMapping = { + ina_cbg_code: "G-4-10-I", + description: "Gastritis akut tanpa komplikasi", + tariff: 1200000, + }; + } else if (hasInfluenza) { + bpjsMapping = { + ina_cbg_code: "H-4-11-I", + description: "Influenza tanpa komplikasi", + tariff: 950000, + }; + } else { + bpjsMapping = { + ina_cbg_code: "Z-4-00-I", + description: "Kondisi tidak spesifik", + tariff: 750000, + }; + } - await new Promise((resolve) => setTimeout(resolve, 1500)); // Simulate processing time + await new Promise((resolve) => setTimeout(resolve, 1500)); // Simulate processing time - return { - icd_10_codes: icd10Codes.slice(0, 3), // Limit to top 3 - procedure_codes: procedureCodes.slice(0, 3), // Limit to top 3 - bpjs_mapping: bpjsMapping, - }; - }; + return { + icd_10_codes: icd10Codes.slice(0, 3), // Limit to top 3 + procedure_codes: procedureCodes.slice(0, 3), // Limit to top 3 + bpjs_mapping: bpjsMapping, + }; + }; - const runAssistPipeline = async () => { - setAssistLoading(true); - setAssistError(null); - setAssistResult(null); + const runAssistPipeline = async () => { + setAssistLoading(true); + setAssistError(null); + setAssistResult(null); - try { - const preprocessed = preprocessInput(assistInput); - const result = await mockAssistPipeline(preprocessed); - setAssistResult(result); - } catch (e) { - console.error(e); - setAssistError( - "Gagal menjalankan BPJS Assist Coding. Silakan coba lagi." - ); - } finally { - setAssistLoading(false); - } - }; + try { + const preprocessed = preprocessInput(assistInput); + const result = await mockAssistPipeline(preprocessed); + setAssistResult(result); + } catch (e) { + console.error(e); + setAssistError( + "Gagal menjalankan BPJS Assist Coding. Silakan coba lagi." + ); + } finally { + setAssistLoading(false); + } + }; - return ( -
- {/* Header */} -
-
- -
-
-

- Asisten Kodefikasi BPJS -

-

- Bantuan penentuan kode ICD-10, prosedur, dan mapping INA-CBGs untuk - klaim BPJS -

-
-
+ return ( +
+ {/* Header */} +
+
+ +
+
+

+ Asisten Kodefikasi BPJS +

+

+ Bantuan penentuan kode ICD-10, prosedur, dan mapping INA-CBGs untuk + klaim BPJS +

+
+
- {/* Form Bantuan Kodefikasi */} -
-
-

- - Input Data Klinis -

-
-
- -