1
+ // components/ServiceViewBookings.tsx
2
+ import React , { useEffect , useState } from 'react' ;
3
+ import { Booking } from '../types/appwrite.type' ;
4
+ import { databases } from '../lib/appwrite.config' ;
5
+ import * as sdk from 'node-appwrite' ;
6
+
1
7
const ServiceViewBookings = ( ) => {
2
- return (
3
- < div >
4
- < h2 className = "text-2xl font-bold mb-4" > View Bookings</ h2 >
5
- < p > This is a placeholder for the service provider to view their bookings.</ p >
6
- </ div >
7
- ) ;
8
+ const [ bookings , setBookings ] = useState < Booking [ ] > ( [ ] ) ;
9
+ const userId = JSON . parse ( localStorage . getItem ( 'appwriteSession' ) || '{}' ) . userId ;
10
+
11
+ useEffect ( ( ) => {
12
+ const fetchBookings = async ( ) => {
13
+ try {
14
+ const response = await databases . listDocuments (
15
+ process . env . DATABASE_ID ! ,
16
+ process . env . BOOKING_COLLECTION_ID ! ,
17
+ [ sdk . Query . equal ( 'providerId' , userId ) ]
18
+ ) ;
19
+
20
+ const bookingsData : Booking [ ] = response . documents . map ( ( doc : sdk . Models . Document ) => ( {
21
+ $id : doc . $id ,
22
+ $permissions : doc . $permissions ,
23
+ bookingId : doc . $id ,
24
+ $collectionId : doc . $collectionId ,
25
+ $databaseId : doc . $databaseId ,
26
+ $createdAt : doc . $createdAt ,
27
+ $updatedAt : doc . $updatedAt ,
28
+ consumerId : doc . consumerId ,
29
+ providerId : doc . providerId ,
30
+ serviceId : doc . serviceId ,
31
+ date : new Date ( doc . date ) ,
32
+ status : doc . status ,
33
+ address : doc . address ,
34
+ city : doc . city ,
35
+ state : doc . state ,
36
+ zipcode : doc . zipcode ,
37
+ } ) ) ;
38
+
39
+ setBookings ( bookingsData ) ;
40
+ } catch ( error ) {
41
+ console . error ( 'Error fetching bookings:' , error ) ;
42
+ }
43
+ } ;
44
+
45
+ fetchBookings ( ) ;
46
+ } , [ userId ] ) ;
47
+
48
+ const handleApproval = async ( bookingId : string , status : string ) => {
49
+ const reason = prompt ( 'Please provide a reason for this decision:' ) ;
50
+ if ( ! reason ) {
51
+ alert ( 'A reason is required.' ) ;
52
+ return ;
53
+ }
54
+ try {
55
+ const response = await fetch ( `/api/bookings/update` , {
56
+ method : 'POST' ,
57
+ headers : {
58
+ 'Content-Type' : 'application/json' ,
59
+ } ,
60
+ body : JSON . stringify ( { bookingId, status, reason } ) ,
61
+ } ) ;
62
+
63
+ if ( response . ok ) {
64
+ alert ( 'Booking status updated.' ) ;
65
+ setBookings ( bookings . map ( b => b . bookingId === bookingId ? { ...b , status } : b ) ) ;
66
+ } else {
67
+ console . error ( 'Failed to update booking.' ) ;
68
+ }
69
+ } catch ( error ) {
70
+ console . error ( 'Error updating booking:' , error ) ;
71
+ }
8
72
} ;
9
-
10
- export default ServiceViewBookings ;
11
-
73
+
74
+ return (
75
+ < div >
76
+ < h2 className = "text-2xl font-bold mb-4" > View Bookings</ h2 >
77
+ { bookings . length > 0 ? (
78
+ bookings . map ( ( booking ) => (
79
+ < div key = { booking . bookingId } className = "mb-4 p-4 border rounded shadow" >
80
+ < p > < strong > Service:</ strong > { booking . serviceId } </ p >
81
+ < p > < strong > Date:</ strong > { new Date ( booking . date ) . toLocaleDateString ( ) } </ p >
82
+ < p > < strong > Status:</ strong > { booking . status } </ p >
83
+ < p > < strong > Address:</ strong > { booking . address } , { booking . city } , { booking . state } , { booking . zipcode } </ p >
84
+ { booking . status === 'pending' && (
85
+ < div >
86
+ < button
87
+ onClick = { ( ) => handleApproval ( booking . bookingId , 'approved' ) }
88
+ className = "bg-green-500 text-white py-2 px-4 rounded mr-2"
89
+ >
90
+ Approve
91
+ </ button >
92
+ < button
93
+ onClick = { ( ) => handleApproval ( booking . bookingId , 'rejected' ) }
94
+ className = "bg-red-500 text-white py-2 px-4 rounded"
95
+ >
96
+ Reject
97
+ </ button >
98
+ </ div >
99
+ ) }
100
+ </ div >
101
+ ) )
102
+ ) : (
103
+ < p > No bookings found.</ p >
104
+ ) }
105
+ </ div >
106
+ ) ;
107
+ } ;
108
+
109
+ export default ServiceViewBookings ;
0 commit comments