create-myexam-app 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/index.js +65 -0
  2. package/package.json +22 -0
  3. package/projects/parking managementt system/Backend/.env +3 -0
  4. package/projects/parking managementt system/Backend/controllers/CarController.js +43 -0
  5. package/projects/parking managementt system/Backend/controllers/ParkingRecordController.js +42 -0
  6. package/projects/parking managementt system/Backend/controllers/ParkingSlotController.js +42 -0
  7. package/projects/parking managementt system/Backend/controllers/PaymentController.js +42 -0
  8. package/projects/parking managementt system/Backend/controllers/UserController.js +71 -0
  9. package/projects/parking managementt system/Backend/db/connectDB.js +11 -0
  10. package/projects/parking managementt system/Backend/models/CarModels.js +9 -0
  11. package/projects/parking managementt system/Backend/models/ParkingRecordModelss.js +10 -0
  12. package/projects/parking managementt system/Backend/models/ParkingSlotModels.js +7 -0
  13. package/projects/parking managementt system/Backend/models/PaymentModels.js +9 -0
  14. package/projects/parking managementt system/Backend/models/UserModels.js +9 -0
  15. package/projects/parking managementt system/Backend/package-lock.json +1526 -0
  16. package/projects/parking managementt system/Backend/package.json +23 -0
  17. package/projects/parking managementt system/Backend/routes/CarRoutes.js +11 -0
  18. package/projects/parking managementt system/Backend/routes/ParkingRecordRoutes.js +9 -0
  19. package/projects/parking managementt system/Backend/routes/ParkingSlotRoutes.js +11 -0
  20. package/projects/parking managementt system/Backend/routes/PaymentRoutes.js +10 -0
  21. package/projects/parking managementt system/Backend/routes/UserRoutes.js +17 -0
  22. package/projects/parking managementt system/Backend/server.js +27 -0
  23. package/projects/parking managementt system/frontend/README.md +16 -0
  24. package/projects/parking managementt system/frontend/eslint.config.js +21 -0
  25. package/projects/parking managementt system/frontend/index.html +13 -0
  26. package/projects/parking managementt system/frontend/package-lock.json +3033 -0
  27. package/projects/parking managementt system/frontend/package.json +31 -0
  28. package/projects/parking managementt system/frontend/public/favicon.svg +1 -0
  29. package/projects/parking managementt system/frontend/public/icons.svg +24 -0
  30. package/projects/parking managementt system/frontend/src/App.css +184 -0
  31. package/projects/parking managementt system/frontend/src/App.jsx +34 -0
  32. package/projects/parking managementt system/frontend/src/assets/hero.png +0 -0
  33. package/projects/parking managementt system/frontend/src/assets/react.svg +1 -0
  34. package/projects/parking managementt system/frontend/src/assets/vite.svg +1 -0
  35. package/projects/parking managementt system/frontend/src/components/Navbar.jsx +27 -0
  36. package/projects/parking managementt system/frontend/src/index.css +1 -0
  37. package/projects/parking managementt system/frontend/src/main.jsx +10 -0
  38. package/projects/parking managementt system/frontend/src/pages/Cars.jsx +116 -0
  39. package/projects/parking managementt system/frontend/src/pages/Dashboard.jsx +45 -0
  40. package/projects/parking managementt system/frontend/src/pages/Login.jsx +63 -0
  41. package/projects/parking managementt system/frontend/src/pages/ParkingRecord.jsx +168 -0
  42. package/projects/parking managementt system/frontend/src/pages/ParkingSlot.jsx +102 -0
  43. package/projects/parking managementt system/frontend/src/pages/Payment.jsx +101 -0
  44. package/projects/parking managementt system/frontend/src/pages/Register.jsx +65 -0
  45. package/projects/parking managementt system/frontend/src/pages/Report.jsx +98 -0
  46. package/projects/parking managementt system/frontend/vite.config.js +10 -0
@@ -0,0 +1,168 @@
1
+ import { useState,useEffect } from "react";
2
+ import axios from "axios";
3
+
4
+ function ParkingRecord(){
5
+
6
+ const [car, setCar] = useState('')
7
+ const [slot, setSlot] = useState('')
8
+ const [entryTime, setEntryTime] = useState('')
9
+ const [exitTime, setExitTime] = useState('')
10
+ const [duration, setDuration] = useState('')
11
+ const [record, setRecord] = useState([])
12
+ const [editId, setEditId] = useState(null)
13
+
14
+ const getAllRecords = async () => {
15
+ try{
16
+ const res = await axios.get('http://localhost:5000/api/parkingRecords')
17
+ setRecord(res.data)
18
+ }catch(error){
19
+ console.log(error)
20
+ }
21
+ }
22
+ useEffect(() => {
23
+ getAllRecords()
24
+ }, [])
25
+
26
+ const handleSubmit = async (e) => {
27
+ e.preventDefault()
28
+ try{
29
+ if (editId) {
30
+ await axios.put(`http://localhost:5000/api/parkingRecords/${editId}`, {
31
+ car,
32
+ slot,
33
+ entryTime,
34
+ exitTime,
35
+ duration,
36
+
37
+ })
38
+ alert ('record succussefully updated')
39
+ setEditId(null)
40
+ } else {
41
+ await axios.post('http://localhost:5000/api/parkingRecords', {
42
+ car,
43
+ slot,
44
+ entryTime,
45
+ exitTime,
46
+ duration,
47
+ })
48
+ alert ('Record added succussfully')
49
+ }
50
+ setCar('')
51
+ setDuration('')
52
+ setEntryTime('')
53
+ setExitTime('')
54
+ setSlot('')
55
+ getAllRecords()
56
+
57
+ }catch(error){
58
+ alert('failed to record')
59
+ }
60
+
61
+ }
62
+ const handleEdit = (record) => {
63
+ setEditId(record._id)
64
+ setCar(record.car)
65
+ setSlot(record.slot)
66
+ setEntryTime(record.entryTime)
67
+ setDuration(record.duration)
68
+ setExitTime(record.exitTime)
69
+ }
70
+ const handleDelete = async (id) => {
71
+ try{
72
+ await axios.delete(`http://localhost:5000/api/parkingRecords/${id}`)
73
+ alert('deleted successfully')
74
+ getAllRecords()
75
+ }catch(error){
76
+ alert('failed to delete')
77
+ }
78
+ }
79
+ return (
80
+ <div className="bg-amber-50 p-6 min-h-screen">
81
+ <h2 className="text-2xl font-bold text-gray-800 mb-6">ParkingRecord</h2>
82
+ <form onSubmit={handleSubmit} className="bg-white rounded-x1 border border-gray-200
83
+ p-6 mb-8 flex flex-col gap-4 max-w-md m-7">
84
+
85
+ <label className="text-sm font-medium text-gray-600"> Car Id</label>
86
+ <input type="text" value={car}
87
+ onChange={(e) => setCar(e.target.value)} required
88
+ className="border border-gray-300 rounded-lg px-3 py-2 yext-sm focus:outline-none
89
+ focus:border-orange-400"
90
+ />
91
+ <label className="text-sm font-medium text-gray-500">Slot ID</label>
92
+ <input
93
+ type="text"
94
+ value={slot}
95
+ onChange={(e) => setSlot(e.target.value)}
96
+ required
97
+ className="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none
98
+ focus:border-orange-400 "
99
+ />
100
+ <label className="text-sm font-medium text-gray-300">Entry Time</label>
101
+ <input
102
+ type="datetime-local"
103
+ value={entryTime}
104
+ onChange={(e) => setEntryTime(e.target.value)}
105
+ required
106
+ className="border border-gray-500 rounded-lg px-4 py-2 text-sm focus:outline-none
107
+ focus:border-orange-800"
108
+ />
109
+ <label className="text-sm font-medium text-gray-400">Exit Time</label>
110
+ <input
111
+ type="datetime-local"
112
+ value={exitTime}
113
+ onChange={(e) => setExitTime(e.target.value)}
114
+ className="border border-gray-500 text-sm rounded-lg px-4 py-2 focus:outline-none
115
+ focus:border-orange-800"
116
+ />
117
+ <label className="text-sm font-medium border-gray-400">Duration (hours)</label>
118
+ <input
119
+ type="number"
120
+ value={duration}
121
+ onChange={(e) => setDuration(e.target.value)}
122
+ className="border border-gray-400 rounded-lg text-sm px-4 py-2
123
+ focus:outline-none focus:border-orange-800"
124
+ />
125
+ <button type="submit" className="bg-orange-300 text-white font-medium
126
+ py-2 rounded-lg hover:bg-orange-800 transition-colors">
127
+ {editId? 'update Record': 'Add record'}
128
+ </button>
129
+ </form>
130
+
131
+ <h3 className="font-medium text-sm text-gray-500 mb-2">Record list</h3>
132
+ <div className="shadow-sm bg-white rounded-xl border border-gray-400 overflow-hidden">
133
+ <table className="w-full text-sm">
134
+ <thead className="bg-gray-400 text-gray-400 text-left">
135
+ <tr >
136
+ <th className="px-4 py-2 font-medium">Car</th>
137
+ <th className="px-4 py-2 font-medium">Slot</th>
138
+ <th className="px-4 py-2 font-medium">Entry Time</th>
139
+ <th className="px-4 py-2 font-medium">Exit Time</th>
140
+ <th className="px-4 py-2 font-medium">Duration</th>
141
+ <th className="px-4 py-2 font-medium">Actions</th>
142
+ </tr>
143
+ </thead>
144
+ <tbody className="divide-y divide-gray-100">
145
+ {record.map((record) => (
146
+ <tr key={record._id} className="hover:bg-gray-50">
147
+ <td className="px-4 py-2 text-gray-800">{record.car}</td>
148
+ <td className="px-4 py-2 text-gray-800">{record.slot}</td>
149
+ <td className="px-4 py-2 text-gray-800">{record.entryTime}</td>
150
+ <td className="px-4 py-2 text-gray-800">{record.exitTime}</td>
151
+ <td className="px-4 py-2 text-gray-800">{record.duration}</td>
152
+ <td className="px-4 py-2">
153
+ <button onClick={() => handleEdit(record)} className="px-3 py-2 bg-orange-400 text-orange-700
154
+ rounded-lg hover:bg-orange-600 transition-colors"
155
+ >Edit</button>
156
+ <button onClick={() => handleDelete(record._id)} className="px-3 py-2 bg-orange-400 text-orange-500
157
+ rounded-lg hover:bg-orange-500 transition-colors">Delete</button>
158
+ </td>
159
+ </tr>
160
+ ))}
161
+ </tbody>
162
+ </table>
163
+ </div>
164
+ </div>
165
+ )
166
+ }
167
+
168
+ export default ParkingRecord
@@ -0,0 +1,102 @@
1
+ import { useState, useEffect } from "react";
2
+ import axios from "axios";
3
+
4
+ function ParkingSlot() {
5
+ const [slotNumber, setSlotNumber] = useState('');
6
+ // Fix 1: Set default to 'available' so it matches the dropdown
7
+ const [slotStatus, setSlotStatus] = useState('available');
8
+ const [slots, setSlots] = useState([]);
9
+
10
+ const getAllSlots = async () => {
11
+ try {
12
+ const res = await axios.get('http://localhost:5000/api/parkingSlots');
13
+ // Fix 2: Better "Shield" logic. Checks for array OR nested array.
14
+ const data = Array.isArray(res.data) ? res.data : (res.data.slots || []);
15
+ setSlots(data);
16
+ } catch (error) {
17
+ console.log("Fetch error:", error);
18
+ setSlots([]);
19
+ }
20
+ };
21
+
22
+ useEffect(() => {
23
+ getAllSlots();
24
+ }, []);
25
+
26
+ const handleSubmit = async (e) => {
27
+ e.preventDefault();
28
+ try {
29
+ await axios.post('http://localhost:5000/api/parkingSlots', {
30
+ slotNumber,
31
+ slotStatus,
32
+ });
33
+ alert('Slot added successfully');
34
+ setSlotNumber('');
35
+ setSlotStatus('available'); // Reset to default
36
+ getAllSlots();
37
+ } catch (error) {
38
+ alert('Failed to add');
39
+ }
40
+ };
41
+
42
+ return (
43
+ <div className="min-h-screen bg-gray-100 p-6">
44
+ <h2 className="text-2xl font-bold text-gray-600 mb-6">Parking Slot</h2>
45
+
46
+ <form onSubmit={handleSubmit} className="bg-white rounded-xl border border-gray-200 p-6 mb-8 flex flex-col gap-4 max-w-md">
47
+ <div className="flex flex-col gap-2">
48
+ <label className="text-sm font-medium text-gray-600">Slot Number</label>
49
+ <input
50
+ type="text"
51
+ value={slotNumber}
52
+ onChange={(e) => setSlotNumber(e.target.value)}
53
+ className="border border-gray-300 rounded-lg px-4 py-2 text-sm focus:outline-none focus:border-orange-400"
54
+ required
55
+ />
56
+
57
+ <label className="text-sm font-medium text-gray-600">Slot Status</label>
58
+ <select
59
+ value={slotStatus}
60
+ onChange={(e) => setSlotStatus(e.target.value)}
61
+ className="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:border-orange-400"
62
+ >
63
+ <option value="available">Available</option>
64
+ <option value="occupied">Occupied</option>
65
+ </select>
66
+ </div>
67
+ <button
68
+ type="submit"
69
+ className="bg-orange-500 text-white font-medium py-2 rounded-lg hover:bg-orange-600 transition-colors"
70
+ >
71
+ Add Slot
72
+ </button>
73
+ </form>
74
+
75
+ <h2 className="text-lg font-semibold text-gray-700 mb-3">Slots List</h2>
76
+ <div className="bg-white rounded-xl border border-gray-200 overflow-hidden shadow-sm">
77
+ <table className="w-full text-sm">
78
+ <thead className="bg-gray-50 text-gray-600 text-left">
79
+ <tr>
80
+ <th className="px-4 py-3 font-medium">Slot Number</th>
81
+ <th className="px-4 py-3 font-medium">Status</th>
82
+ </tr>
83
+ </thead>
84
+ <tbody className="divide-y divide-gray-100">
85
+ {slots.map((slot) => (
86
+ <tr key={slot._id} className="hover:bg-gray-50 transition-colors">
87
+ <td className="px-4 py-3 text-gray-800">{slot.slotNumber}</td>
88
+ <td className="px-4 py-3">
89
+ <span className={`px-2 py-1 rounded-full text-xs ${slot.slotStatus === 'available' ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'}`}>
90
+ {slot.slotStatus}
91
+ </span>
92
+ </td>
93
+ </tr>
94
+ ))}
95
+ </tbody>
96
+ </table>
97
+ </div>
98
+ </div>
99
+ );
100
+ }
101
+
102
+ export default ParkingSlot;
@@ -0,0 +1,101 @@
1
+ import { useState,useEffect } from "react";
2
+ import axios from "axios";
3
+
4
+ function Payment(){
5
+ const [record, setRecord] = useState('')
6
+ const [amountPaid, setAmountPaid] = useState('')
7
+ const [paymentDate, setPaymentDate] = useState('')
8
+ const [payments, setPayments] = useState([])
9
+
10
+ const getAllPayments = async () => {
11
+ try{
12
+ const res = await axios.get('http://localhost:5000/api/payments')
13
+ setPayments(res.data)
14
+ }catch(error){
15
+ console.log('error')
16
+ }
17
+ }
18
+
19
+ useEffect(() => {
20
+ getAllPayments()
21
+ }, [])
22
+
23
+ const handleSubmit = async (e) => {
24
+ e.preventDefault()
25
+ try{
26
+ await axios.post('http://localhost:5000/api/payments', {
27
+ record,
28
+ amountPaid,
29
+ paymentDate,
30
+ })
31
+ alert ('Payment added successfully')
32
+ setRecord('')
33
+ setPaymentDate('')
34
+ setAmountPaid('')
35
+ getAllPayments()
36
+ }catch(error){
37
+ alert ('failed to add payment')
38
+ }
39
+ }
40
+
41
+ return(
42
+ <div className="min-h-screen bg-gray-400">
43
+ <h2 className="text-2xl font-bold text-gray-800 mb-6"> Paymnet</h2>
44
+ <form onSubmit={handleSubmit} className="bg-white rounded-xl border border-gray-200 p-6
45
+ mb-6 flex flex-col gap-4 max-w-md">
46
+ <div className="flex flex-col gap-1">
47
+ <label className="text-sm font-medium text-gray-600">Record</label>
48
+ <input type="text" value={record}
49
+ onChange={(e) => setRecord(e.target.value)}
50
+ required
51
+ className="border border-gray-400 rounded-lg px-4 py-2 text-sm focus:outline-none
52
+ focus:border-orange-500"
53
+ />
54
+
55
+ <label className="text-sm font-medium text-gray-600">Amount paid </label>
56
+ <input type="number" value={amountPaid}
57
+ onChange={(e) => setAmountPaid(e.target.value)}
58
+ required
59
+ className="border border-gray-400 rounded-lg px-4 py-2 text-sm
60
+ focus:outline-none focus:border-orange-400"
61
+ />
62
+
63
+ <label className="text-sm font-medium text-gray-600">Payment Date</label>
64
+ <input type="date" value={paymentDate}
65
+ onChange={(e) => setPaymentDate(e.target.value)}
66
+ className="border border-gray-600 rounded-lg px-4 py-2 text-sm
67
+ focus:outline-none focus:border-orange-500"
68
+ />
69
+ </div>
70
+ <button type="submit" className="bg-orange-500 text-white font-medium
71
+ py-2 rounded-lg hover:bg-orange-400 transition-colors">Add Payment</button>
72
+ </form>
73
+ <h2 className="text-lg font-semibold text-gray-700 mb-3">Payment List</h2>
74
+ <div className=" bg-white rounded-xl border border-gray-400 overflow-hidden">
75
+ <table className="w-full text-sm">
76
+ <thead className="bg-gray-50 text-gray-400 text-left ">
77
+ <tr>
78
+ <th className="px-4 py-3 font-medium">Record</th>
79
+ <th className="px-4 py-3 font-medium">Amount Paid</th>
80
+ <th className="px-4 py-3 font-medium">Payment Date</th>
81
+ </tr>
82
+ </thead>
83
+
84
+
85
+ <tbody className="divide-y divide-gray-100">
86
+ {payments.map((payment) =>(
87
+ <tr key={payment._id} className="hover:bg-gray-50">
88
+ <td className="px-4 py-2 text-gray-800">{payment.record}</td>
89
+ <td className="px-4 py-2 text-gray-800">{payment.amountPaid}</td>
90
+ <td className="px-4 py-2 text-gray-800">{payment.paymentDate}</td>
91
+ </tr>
92
+ ))}
93
+
94
+ </tbody>
95
+ </table>
96
+ </div>
97
+ </div>
98
+ )
99
+ }
100
+
101
+ export default Payment
@@ -0,0 +1,65 @@
1
+ import { useState } from 'react'
2
+ import { useNavigate, Link } from 'react-router-dom'
3
+ import axios from 'axios'
4
+
5
+ function Register(){
6
+ const navigate = useNavigate()
7
+ const [email, setEmail] = useState('')
8
+ const [userName, setUserName] = useState('')
9
+ const [password, setPassword] = useState('')
10
+ const [error, setError] = useState('')
11
+
12
+ const handleRegister = async (e) => {
13
+ e.preventDefault()
14
+ try{
15
+ await axios.post('http://localhost:5000/api/users/register',{
16
+ email,
17
+ userName,
18
+ password
19
+ });
20
+ navigate('/')
21
+ }catch(error){
22
+ setError('Registration failled. try again')
23
+ }
24
+ }
25
+ return(
26
+ <div className=' min-h-screen bg-gray-100 p-6 '>
27
+
28
+ <h2 className='text-2xl font-bold text-gray-800 mb-1'>Register</h2>
29
+ {error && <p>{error}</p>}
30
+ <form onSubmit={handleRegister}
31
+ className='bg-white rounded-2xl border border-gray-500 p-6 mb-8
32
+ flex flex-col gap-2 w-150 '
33
+ >
34
+ <label className='text-sm font-medium text-gray-600'>Email</label>
35
+ <input type="email" placeholder="enter ur email" onChange={(e) => setEmail(e.target.value)}
36
+ required
37
+ className='border border-black rounded-1g px-20 py-1 text-sm
38
+ focus:outline-none focus:border-orange-400'
39
+ />
40
+ <label className='text-sm font-medium text-gray-600'>Name</label>
41
+ <input type="text" placeholder="enter ur name" onChange={(e) => setUserName(e.target.value)}
42
+ required
43
+ className='text-sm border border-black rounded-1g px-20 py-1
44
+ focus:outline-none focus:border-orange-400'
45
+ />
46
+ <label className='text-sm font-medium text-gray-600'>Password</label>
47
+ <input type="password" placeholder="enter ur password" onChange={(e) => setPassword(e.target.value)}
48
+ required
49
+ className='border border-black rounded-1g px-20 py-1 text-sm
50
+ focus:outline-none focus:border-orange-400'
51
+ />
52
+
53
+ <button type='submit' className='bg-orange-500 text-white font-medium
54
+ py-2 rounded-1g hover:bg-orange-600 transition-colors'>Register</button>
55
+
56
+ </form>
57
+ <p className='text-gray-5 text-sm mt-4 w-50 '>Arleady have an account? <Link to="/"
58
+ className='text-orange-500 font-medium hover:underline'
59
+ >Login</Link> </p>
60
+ </div>
61
+ )
62
+
63
+ }
64
+
65
+ export default Register
@@ -0,0 +1,98 @@
1
+ import { useState,useEffect } from "react";
2
+ import axios from "axios";
3
+
4
+ function Report (){
5
+ const [records, setRecords] = useState([])
6
+ const [payments, setPayments] = useState([])
7
+
8
+ const getAllRecords = async () => {
9
+ try{
10
+
11
+
12
+ const res = await axios.get('http://localhost:5000/api/parkingRecords')
13
+ setRecords(res.data)
14
+ }catch(error){
15
+ console.log('error')
16
+ }
17
+ }
18
+
19
+ const getAllPayments = async () => {
20
+ try{
21
+ const res = await axios.get('http://localhost:5000/api/payments')
22
+ setPayments(res.data)
23
+ }catch(error){
24
+ console.log('erro')
25
+ }
26
+ }
27
+ useEffect(() => {
28
+ getAllPayments()
29
+ getAllRecords()
30
+ }, [])
31
+
32
+ const calculateFee = (duration) => {
33
+ if (!duration || duration <= 0) return 500
34
+ return Math.ceil(duration) * 500
35
+ }
36
+ const today = new Date(). toDateString()
37
+
38
+ const todayPayment = payments.filter((payment) => {
39
+ return new Date(payment.paymentDate). toDateString() === today
40
+ })
41
+
42
+ return(
43
+ <div className="min-h-screen bg-gray-400">
44
+ <h2 className="text-2xl font-bold text-gray-800 mb-6">Payment</h2>
45
+ <h3 className="text-lg font-semibold text-black-500 mb-3">Bill</h3>
46
+ <div className="bg-white rounded-xl border border-gray-200 overflow-hidden mb-8">
47
+ <table className="w-full text-sm flex">
48
+ <thead className="bg-gray-50 text-gray-500 text-left">
49
+ <tr>
50
+ <th className="px-4 py-2">Car</th>
51
+ <th className="px-4 py-2">Entry Time</th>
52
+ <th className="px-4 py-2">Exit Time</th>
53
+ <th className="px-4 py-2">Duration (hrs)</th>
54
+ <th className="px-4 py-2">Amount (Rwf)</th>
55
+ </tr>
56
+ </thead>
57
+ <tbody>
58
+ {records.map((record) => (
59
+ <tr key={record._id} className="border-t">
60
+ <td className="px-4 py-2">{record.car}</td>
61
+ <td className="px-4 py-2">{record.entryTime}</td>
62
+ <td className="px-4 py-2">{record.exitTime}</td>
63
+ <td className="px-4 py-2">{record.duration}</td>
64
+ <td className="px-4 py-2 text-orange-600 font-semibold" >{calculateFee(record.duration)}</td>
65
+ </tr>
66
+ ))}
67
+ </tbody>
68
+ </table>
69
+ </div>
70
+ <h3 className="text-lg font-semibold text-black-100 mb-2">Daily Parking Payment Record</h3>
71
+ <p className="mb-2 text-gray-700">Date:{today}</p>
72
+ <div className="bg-white rounded-xl border border-gray-200 overflow-hidden">
73
+
74
+
75
+ <table className="w-full text-sm">
76
+ <thead className="bg-gray-50 text-gray-500 text-left">
77
+ <tr>
78
+ <td className="px-4 py-2">Record ID</td>
79
+ <td className="px-4 py-2">Amount Paid</td>
80
+ <td className="px-4 py-2">Payment Date</td>
81
+ </tr>
82
+ </thead>
83
+ <tbody>
84
+ {todayPayment.map((payment) => (
85
+ <tr key={payment._id} className="border-t">
86
+ <td className="px-3 py-2">{payment.record}</td>
87
+ <td className="px-3 py-2 text-orange-300 font-semibold">{payment.amountPaid}</td>
88
+ <td className="px-3 py-2">{new Date(payment.paymentDate).toLocaleDateString()}</td>
89
+ </tr>
90
+ ))}
91
+ </tbody>
92
+ </table>
93
+ </div>
94
+ </div>
95
+ )
96
+ }
97
+
98
+ export default Report
@@ -0,0 +1,10 @@
1
+ import { defineConfig } from 'vite'
2
+ import react from '@vitejs/plugin-react'
3
+ import tailwindcss from '@tailwindcss/vite'
4
+
5
+ // https://vite.dev/config/
6
+ export default defineConfig({
7
+ plugins: [react(),
8
+ tailwindcss(),
9
+ ],
10
+ })