Skip to content

Commit b74884c

Browse files
committed
feat: Implemented view, edit, and delete functionality for customer bookings - ViewBookings Tab
- Added EditBookingForm component for editing bookings. - Enhanced CustomerViewBookings to handle booking edits and deletions. - Implemented fetchBookings to refresh the booking list after updates. - Improved UI with edit and delete buttons for each booking.
1 parent 3d517d2 commit b74884c

File tree

3 files changed

+204
-32
lines changed

3 files changed

+204
-32
lines changed

components/CustomerViewBookings.tsx

+74-28
Original file line numberDiff line numberDiff line change
@@ -3,47 +3,76 @@ import React, { useEffect, useState } from 'react';
33
import { Booking } from '../types/appwrite.type';
44
import { databases } from '../lib/appwrite.config';
55
import * as sdk from 'node-appwrite';
6+
import EditBookingForm from './EditBookingForm';
67

78
const CustomerViewBookings = () => {
89
const [bookings, setBookings] = useState<Booking[]>([]);
10+
const [selectedBooking, setSelectedBooking] = useState<Booking | null>(null);
11+
const [isEditing, setIsEditing] = useState(false);
912
const userId = JSON.parse(localStorage.getItem('appwriteSession') || '{}').userId;
1013

14+
const fetchBookings = async () => {
15+
try {
16+
const response = await databases.listDocuments(
17+
process.env.DATABASE_ID!,
18+
process.env.BOOKING_COLLECTION_ID!,
19+
[sdk.Query.equal('consumerId', userId)]
20+
);
21+
22+
const bookingsData: Booking[] = response.documents.map((doc: sdk.Models.Document) => ({
23+
$id: doc.$id,
24+
$permissions: doc.$permissions,
25+
bookingId: doc.$id,
26+
$collectionId: doc.$collectionId,
27+
$databaseId: doc.$databaseId,
28+
$createdAt: doc.$createdAt,
29+
$updatedAt: doc.$updatedAt,
30+
consumerId: doc.consumerId,
31+
providerId: doc.providerId,
32+
serviceId: doc.serviceId,
33+
date: new Date(doc.date),
34+
status: doc.status,
35+
address: doc.address,
36+
city: doc.city,
37+
state: doc.state,
38+
zipcode: doc.zipcode,
39+
}));
40+
41+
setBookings(bookingsData);
42+
} catch (error) {
43+
console.error('Error fetching bookings:', error);
44+
}
45+
};
46+
1147
useEffect(() => {
12-
const fetchBookings = async () => {
48+
fetchBookings();
49+
}, [userId]);
50+
51+
const handleEditClick = (booking: Booking) => {
52+
setSelectedBooking(booking);
53+
setIsEditing(true);
54+
};
55+
56+
const handleDelete = async (bookingId: string) => {
57+
if (confirm('Are you sure you want to delete this booking?')) {
1358
try {
14-
const response = await databases.listDocuments(
59+
await databases.deleteDocument(
1560
process.env.DATABASE_ID!,
1661
process.env.BOOKING_COLLECTION_ID!,
17-
[sdk.Query.equal('consumerId', userId)]
62+
bookingId
1863
);
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);
64+
setBookings((prevBookings) => prevBookings.filter((booking) => booking.bookingId !== bookingId));
4065
} catch (error) {
41-
console.error('Error fetching bookings:', error);
66+
console.error('Error deleting booking:', error);
4267
}
43-
};
68+
}
69+
};
4470

45-
fetchBookings();
46-
}, [userId]);
71+
const handleSave = async () => {
72+
setIsEditing(false);
73+
setSelectedBooking(null);
74+
await fetchBookings(); // Fetch the bookings again to get the updated list
75+
};
4776

4877
return (
4978
<div>
@@ -55,11 +84,28 @@ const CustomerViewBookings = () => {
5584
<p><strong>Date:</strong> {new Date(booking.date).toLocaleDateString()}</p>
5685
<p><strong>Status:</strong> {booking.status}</p>
5786
<p><strong>Address:</strong> {booking.address}, {booking.city}, {booking.state}, {booking.zipcode}</p>
87+
<div className="flex space-x-4">
88+
<button
89+
onClick={() => handleEditClick(booking)}
90+
className="bg-yellow-500 text-white py-2 px-4 rounded"
91+
>
92+
Edit
93+
</button>
94+
<button
95+
onClick={() => handleDelete(booking.bookingId)}
96+
className="bg-red-500 text-white py-2 px-4 rounded"
97+
>
98+
Delete
99+
</button>
100+
</div>
58101
</div>
59102
))
60103
) : (
61104
<p>No bookings found.</p>
62105
)}
106+
{isEditing && selectedBooking && (
107+
<EditBookingForm booking={selectedBooking} onClose={() => setIsEditing(false)} onSave={handleSave} />
108+
)}
63109
</div>
64110
);
65111
};

components/EditBookingForm.tsx

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// components/EditBookingForm.tsx
2+
import React, { useState, useEffect } from 'react';
3+
import { Booking } from '../types/appwrite.type';
4+
import { databases } from '../lib/appwrite.config';
5+
6+
interface EditBookingFormProps {
7+
booking: Booking;
8+
onClose: () => void;
9+
onSave: () => void;
10+
}
11+
12+
const EditBookingForm: React.FC<EditBookingFormProps> = ({ booking, onClose, onSave }) => {
13+
const [formData, setFormData] = useState<Booking>({
14+
...booking,
15+
date: new Date(booking.date),
16+
});
17+
18+
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {
19+
const { name, value } = e.target;
20+
setFormData((prevData) => ({
21+
...prevData,
22+
[name]: value,
23+
}));
24+
};
25+
26+
const handleSubmit = async (e: React.FormEvent) => {
27+
e.preventDefault();
28+
try {
29+
await databases.updateDocument(
30+
process.env.DATABASE_ID!,
31+
process.env.BOOKINGS_COLLECTION_ID!,
32+
booking.$id,
33+
{
34+
...formData,
35+
date: formData.date.toISOString(),
36+
}
37+
);
38+
onSave();
39+
} catch (error) {
40+
console.error('Error updating booking:', error);
41+
}
42+
};
43+
44+
return (
45+
<div className="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center">
46+
<div className="bg-white p-6 rounded shadow-md w-96">
47+
<h2 className="text-xl font-bold mb-4">Edit Booking</h2>
48+
<form onSubmit={handleSubmit}>
49+
<div className="mb-4">
50+
<label className="block text-gray-700">Date:</label>
51+
<input
52+
type="date"
53+
name="date"
54+
value={formData.date.toISOString().substring(0, 10)}
55+
onChange={handleChange}
56+
className="w-full p-2 border border-gray-300 rounded"
57+
required
58+
/>
59+
</div>
60+
<div className="mb-4">
61+
<label className="block text-gray-700">Address:</label>
62+
<input
63+
type="text"
64+
name="address"
65+
value={formData.address}
66+
onChange={handleChange}
67+
className="w-full p-2 border border-gray-300 rounded"
68+
required
69+
/>
70+
</div>
71+
<div className="mb-4">
72+
<label className="block text-gray-700">City:</label>
73+
<input
74+
type="text"
75+
name="city"
76+
value={formData.city}
77+
onChange={handleChange}
78+
className="w-full p-2 border border-gray-300 rounded"
79+
required
80+
/>
81+
</div>
82+
<div className="mb-4">
83+
<label className="block text-gray-700">State:</label>
84+
<input
85+
type="text"
86+
name="state"
87+
value={formData.state}
88+
onChange={handleChange}
89+
className="w-full p-2 border border-gray-300 rounded"
90+
required
91+
/>
92+
</div>
93+
<div className="mb-4">
94+
<label className="block text-gray-700">Zipcode:</label>
95+
<input
96+
type="text"
97+
name="zipcode"
98+
value={formData.zipcode}
99+
onChange={handleChange}
100+
className="w-full p-2 border border-gray-300 rounded"
101+
required
102+
/>
103+
</div>
104+
<div className="flex justify-end space-x-4">
105+
<button
106+
type="button"
107+
onClick={onClose}
108+
className="bg-gray-500 text-white py-2 px-4 rounded"
109+
>
110+
Cancel
111+
</button>
112+
<button
113+
type="submit"
114+
className="bg-blue-500 text-white py-2 px-4 rounded"
115+
>
116+
Save
117+
</button>
118+
</div>
119+
</form>
120+
</div>
121+
</div>
122+
);
123+
};
124+
125+
export default EditBookingForm;

pages/api/bookings/update.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@ import { databases } from '../../../lib/appwrite.config';
44

55
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
66
if (req.method === 'POST') {
7-
const { bookingId, status, reason } = req.body;
7+
const { bookingId, ...updatedBooking } = req.body;
88
try {
99
await databases.updateDocument(
1010
process.env.DATABASE_ID!,
1111
process.env.BOOKING_COLLECTION_ID!,
1212
bookingId,
13-
{ status, reason }
13+
updatedBooking
1414
);
15-
res.status(200).json({ message: 'Booking status updated successfully' });
15+
res.status(200).json({ message: 'Booking updated successfully' });
1616
} catch (error) {
17-
res.status(500).json({ error: 'Failed to update booking' });
17+
console.error('Error updating booking:', error);
18+
res.status(500).json({ message: 'Error updating booking', error: (error as Error).message });
1819
}
1920
} else {
2021
res.setHeader('Allow', ['POST']);

0 commit comments

Comments
 (0)