source: frontend/src/pages/billing/BillingList.js@ a64c772

Last change on this file since a64c772 was a64c772, checked in by MBK <marija.karapandzova@…>, 4 months ago

Fix doctor authorization and prevent canceling other doctors appointments and restrict them from billing access

  • Property mode set to 100644
File size: 3.9 KB
Line 
1import React, { useState, useEffect } from 'react';
2import { Link, useSearchParams } from 'react-router-dom';
3import { billingService } from '../../services/billingService';
4import Loading from '../../components/Loading';
5import ErrorAlert from '../../components/ErrorAlert';
6
7function BillingList() {
8 const [billings, setBillings] = useState([]);
9 const [loading, setLoading] = useState(true);
10 const [error, setError] = useState(null);
11 const [searchParams] = useSearchParams();
12 const patientId = searchParams.get('patientId');
13 const user = JSON.parse(localStorage.getItem('user') || '{}');
14
15 const fetchBillings = async () => {
16 try {
17 setLoading(true);
18 let response;
19 if (patientId) {
20 response = await billingService.getBillingHistoryForPatient(patientId);
21 } else if (user.role === 'PATIENT') {
22 response = await billingService.getBillingHistoryForPatient(user.patientId);
23 } else {
24 response = await billingService.getAllBillings();
25 }
26 setBillings(response.data);
27 } catch (err) {
28 setError('Failed to fetch billing records');
29 console.error(err);
30 } finally {
31 setLoading(false);
32 }
33 };
34
35 useEffect(() => {
36 fetchBillings();
37 }, [patientId]);
38
39 // Prevent unauthorized access to billing
40 if (user.role === 'DOCTOR' || user.role === 'LAB_TECHNICIAN') {
41 return (
42 <div style={{ padding: '20px', textAlign: 'center' }}>
43 <h1 className="text-2xl font-bold" style={{ color: '#7c3aed', marginBottom: '10px' }}>Access Denied</h1>
44 <p style={{ color: 'var(--color-neutral-600)' }}>You do not have permission to access billing records.</p>
45 </div>
46 );
47 }
48
49 if (loading) return <Loading />;
50
51 return (
52 <div>
53 <h1 className="text-3xl font-bold mb-6" style={{ color: '#7c3aed' }}>{patientId ? 'Patient Billing History' : 'Billing Records'}</h1>
54
55 {error && <ErrorAlert message={error} onClose={() => setError(null)} />}
56
57 <div className="bg-white rounded-lg shadow overflow-hidden">
58 <table className="w-full">
59 <thead className="bg-gray-100">
60 <tr>
61 <th className="px-6 py-3 text-left text-sm font-semibold">Patient</th>
62 <th className="px-6 py-3 text-left text-sm font-semibold">Total Cost</th>
63 <th className="px-6 py-3 text-left text-sm font-semibold">Payment Status</th>
64 <th className="px-6 py-3 text-left text-sm font-semibold">Payment Date</th>
65 <th className="px-6 py-3 text-left text-sm font-semibold">Actions</th>
66 </tr>
67 </thead>
68 <tbody>
69 {billings.map(billing => (
70 <tr key={billing.billId} className="border-t hover:bg-gray-50">
71 <td className="px-6 py-3">{billing.patientName}</td>
72 <td className="px-6 py-3">${billing.totalCost}</td>
73 <td className="px-6 py-3">
74 <span className={`px-3 py-1 rounded text-sm font-semibold ${
75 billing.paymentStatus === 'PENDING' ? 'bg-yellow-100 text-yellow-800' :
76 billing.paymentStatus === 'PAID' ? 'bg-green-100 text-green-800' :
77 'bg-red-100 text-red-800'
78 }`}>
79 {billing.paymentStatus}
80 </span>
81 </td>
82 <td className="px-6 py-3">{billing.paymentDate || 'Not paid'}</td>
83 <td className="px-6 py-3">
84 <Link to={`/billing/${billing.billId}`} style={{ color: '#7c3aed', textDecoration: 'none', fontWeight: '400' }} onMouseEnter={(e) => e.currentTarget.style.textDecoration = 'underline'} onMouseLeave={(e) => e.currentTarget.style.textDecoration = 'none'}>
85 View
86 </Link>
87 </td>
88 </tr>
89 ))}
90 </tbody>
91 </table>
92 </div>
93 </div>
94 );
95}
96
97export default BillingList;
Note: See TracBrowser for help on using the repository browser.