source: CookCraft-FrontEnd/CookCraft-FrontEnd-master/cookcraft-app/src/components/DeliveryView.jsx@ f08e256

Last change on this file since f08e256 was d7b7f00, checked in by Gorazd Biskoski <gorazdbiskoskii@…>, 4 weeks ago

Add project

  • Property mode set to 100644
File size: 12.0 KB
RevLine 
[d7b7f00]1import React, { useState, useEffect, useCallback } from 'react';
2import { useNavigate } from 'react-router-dom';
3import Modal from 'react-modal';
4import { FaArrowLeft } from 'react-icons/fa';
5import styles from '../css/DeliveryViewCss/delivery-view.module.css';
6
7Modal.setAppElement('#root');
8
9const DeliveryView = () => {
10 const [activeOrders, setActiveOrders] = useState([]);
11 const [ongoingOrder, setOngoingOrder] = useState(null);
12 const [orderHistory, setOrderHistory] = useState([]);
13 const [selectedOrder, setSelectedOrder] = useState(null);
14 const [productOrders, setProductOrders] = useState([]);
15 const [loading, setLoading] = useState(true);
16 const [error, setError] = useState(null);
17 const navigate = useNavigate();
18
19 const fetchProductOrdersByOrderId = useCallback(async (orderId) => {
20 const token = localStorage.getItem('token');
21 try {
22 const response = await fetch(`http://localhost:8080/api/productOrders/order/${orderId}`, {
23 method: 'GET',
24 headers: {
25 'Authorization': `Bearer ${token}`,
26 'Content-Type': 'application/json',
27 },
28 });
29
30 if (response.ok) {
31 const productOrdersData = await response.json();
32
33 const productOrdersWithNames = await Promise.all(
34 productOrdersData.map(async (productOrder) => {
35 const productName = await fetchProductName(productOrder.productId);
36 return {
37 ...productOrder,
38 name: productName,
39 };
40 })
41 );
42
43 setProductOrders(productOrdersWithNames);
44 } else {
45 alert('Failed to fetch product orders for the selected order.');
46 }
47 } catch (error) {
48 console.error('Error fetching product orders:', error);
49 }
50 }, []);
51
52 const fetchProductName = async (productId) => {
53 const token = localStorage.getItem('token');
54 try {
55 const response = await fetch(`http://localhost:8080/api/products/${productId}`, {
56 method: 'GET',
57 headers: {
58 'Authorization': `Bearer ${token}`,
59 'Content-Type': 'application/json',
60 },
61 });
62
63 if (response.ok) {
64 const productData = await response.json();
65 return productData.name;
66 } else {
67 return 'Unknown Product';
68 }
69 } catch (error) {
70 console.error('Error fetching product name:', error);
71 return 'Unknown Product';
72 }
73 };
74
75 const fetchUserData = async (userId) => {
76 const token = localStorage.getItem('token');
77 try {
78 const response = await fetch(`http://localhost:8080/api/users/${userId}`, {
79 method: 'GET',
80 headers: {
81 'Authorization': `Bearer ${token}`,
82 'Content-Type': 'application/json',
83 },
84 });
85
86 if (response.ok) {
87 return await response.json();
88 } else {
89 console.error('Failed to fetch user details.');
90 return null;
91 }
92 } catch (error) {
93 console.error('Error fetching user details:', error);
94 return null;
95 }
96 };const fetchDeliveryData = useCallback(async () => {
97 try {
98 const token = localStorage.getItem('token');
99 if (!token) {
100 alert('You need to be logged in to access this page.');
101 navigate('/login');
102 return;
103 }
104
105 const ongoingOrderData = await fetchOrderData('http://localhost:8080/api/deliveryperson/ongoing', token);
106 if (ongoingOrderData) {
107 const userData = await fetchUserData(ongoingOrderData.userId);
108 setOngoingOrder({ ...ongoingOrderData, user: userData });
109 await fetchProductOrdersByOrderId(ongoingOrderData.id);
110 } else {
111 const activeOrdersData = await fetchOrderData('http://localhost:8080/api/orders/activeOrders', token);
112 if (activeOrdersData) {
113 setActiveOrders(activeOrdersData);
114 }
115 }
116
117 const historyData = await fetchOrderData('http://localhost:8080/api/orders/history', token);
118 if (historyData) {
119 const historyWithDetails = await Promise.all(
120 historyData.map(async (order) => {
121 const userData = await fetchUserData(order.userId);
122 const productOrders = await fetchProductOrdersByOrderId(order.id);
123 return { ...order, user: userData, productOrders };
124 })
125 );
126 setOrderHistory(historyWithDetails);
127 }
128 } catch (err) {
129 console.error('Error fetching delivery data:', err);
130 setError('Failed to fetch delivery data.');
131 } finally {
132 setLoading(false);
133 }
134}, [navigate, fetchProductOrdersByOrderId]);
135
136 useEffect(() => {
137 fetchDeliveryData();
138 }, [fetchProductOrdersByOrderId, fetchDeliveryData]);
139
140 const fetchOrderData = async (url, token) => {
141 const response = await fetch(url, {
142 method: 'GET',
143 headers: {
144 'Authorization': `Bearer ${token}`,
145 'Content-Type': 'application/json',
146 },
147 });
148 if (response.ok) {
149 const text = await response.text();
150 if (!text) {
151 return null;
152 }
153 try {
154 return JSON.parse(text);
155 } catch (error) {
156 console.error('Error parsing JSON:', error);
157 return null;
158 }
159 } else if (response.status === 204) {
160 return null;
161 } else {
162 throw new Error('Failed to fetch data');
163 }
164 };
165 const acceptOrder = async (orderId) => {
166 try {
167 const token = localStorage.getItem('token');
168 const response = await fetch(`http://localhost:8080/api/orders/accept/${orderId}`, {
169 method: 'POST',
170 headers: {
171 'Authorization': `Bearer ${token}`,
172 'Content-Type': 'application/json',
173 },
174 });
175
176 if (response.ok) {
177 const acceptedOrder = activeOrders.find(order => order.id === orderId);
178 const userData = await fetchUserData(acceptedOrder.userId);
179 setOngoingOrder({ ...acceptedOrder, user: userData });
180
181 setActiveOrders(prevOrders =>
182 prevOrders.map(order => (order.id === orderId ? { ...order, accepted: true } : order))
183 );
184 setSelectedOrder(acceptedOrder);
185 await fetchProductOrdersByOrderId(orderId);
186 } else {
187 alert('Order has already been accepted by another Delivery Person.');
188 }
189 } catch (error) {
190 console.error('Error accepting order:', error);
191 }
192 };
193
194
195 const finishOrder = async () => {
196 try {
197 const token = localStorage.getItem('token');
198 const response = await fetch(`http://localhost:8080/api/orders/finish/${ongoingOrder.id}`, {
199 method: 'PUT',
200 headers: {
201 'Authorization': `Bearer ${token}`,
202 'Content-Type': 'application/json',
203 },
204 });
205
206 if (response.ok) {
207 setOngoingOrder(null);
208 await fetchDeliveryData();
209 } else {
210 alert('Failed to mark the order as finished.');
211 }
212 } catch (error) {
213 console.error('Error finishing the order:', error);
214 }
215 };
216
217 const openOrderDetails = async (order) => {
218 const userData = await fetchUserData(order.userId);
219 setSelectedOrder({ ...order, user: userData });
220 await fetchProductOrdersByOrderId(order.id);
221 };
222
223
224 const splitAddress = (address) => {
225 const [street = '', number = '', floor = ''] = address.split(';');
226 return { street, number, floor };
227 };
228
229 const closeModal = () => {
230 setSelectedOrder(null);
231 };
232
233 const handleBackClick = () => {
234 navigate(-1);
235 };
236
237 if (loading) {
238 return <p>Loading...</p>;
239 }
240
241 if (error) {
242 return <p>{error}</p>;
243 }
244
245 return (
246 <div className={styles.container}>
247 <h1>Delivery Dashboard</h1>
248 <div className={styles.backArrow} onClick={handleBackClick}>
249 <FaArrowLeft />
250 </div>
251 {ongoingOrder && (
252 <section className={styles.section}>
253 <h2>Ongoing Delivery</h2>
254 <div className={styles.card}>
255 <h3>Order #{ongoingOrder.id}</h3>
256 <p><strong>Street:</strong> {splitAddress(ongoingOrder.address).street}</p>
257 <p><strong>Number:</strong> {splitAddress(ongoingOrder.address).number}</p>
258 <p><strong>Floor:</strong> {splitAddress(ongoingOrder.address).floor}</p>
259 {ongoingOrder.user && (
260 <>
261 <p><strong>Phone Number:</strong> {ongoingOrder.user.phoneNumber}</p>
262 <p><strong>Name:</strong> {ongoingOrder.user.userName} {ongoingOrder.user.userSurname}</p>
263 </>
264 )}
265 <button className={styles.button} onClick={finishOrder}>
266 Mark as Finished
267 </button>
268 <button className={styles.button} onClick={() => openOrderDetails(ongoingOrder)}>
269 View Details
270 </button>
271 </div>
272 </section>
273)}
274 {!ongoingOrder && (
275 <section className={styles.section}>
276 <h2>Active Orders</h2>
277 <div className={styles.cardsContainer}>
278 {activeOrders.length === 0 ? (
279 <p>No active orders at the moment.</p>
280 ) : (
281 activeOrders.map(order => {
282 const { street, number, floor } = splitAddress(order.address);
283 return (
284 <div key={order.id} className={styles.card}>
285 <h3>Order #{order.id}</h3>
286 <p><strong>Street: </strong>{street}</p>
287 <p><strong>Number: </strong>{number}</p>
288 <p><strong>Floor: </strong>{floor}</p>
289 {!order.accepted && (
290 <button className={styles.button} onClick={() => acceptOrder(order.id)}>
291 Accept Order
292 </button>
293 )}
294 </div>
295 );
296 })
297 )}
298 </div>
299 </section>
300 )}
301 <section className={styles.section}>
302 <h2>Order History</h2>
303 <div className={styles.cardsContainer}>
304 {orderHistory.length === 0 ? (
305 <p>No order history available.</p>
306 ) : (
307 orderHistory.map(order => {
308 const { street, number, floor } = splitAddress(order.address);
309 const { user } = order;
310 return (
311 <div key={order.id} className={styles.card}>
312 <h3>Order #{order.id}</h3>
313 <p><strong>Street:</strong> {street}</p>
314 <p><strong>Number:</strong> {number}</p>
315 <p><strong>Floor:</strong> {floor}</p>
316 {user && (
317 <>
318 <p><strong>Phone Number:</strong> {user.phoneNumber}</p>
319 <p><strong>Name:</strong> {user.userName} {user.userSurname}</p>
320 </>
321 )}
322 <button className={styles.button} onClick={() => openOrderDetails(order)}>
323 View Details
324 </button>
325 </div>
326 );
327 })
328 )}
329 </div>
330 </section>
331 {selectedOrder && (
332 <Modal
333 isOpen={!!selectedOrder}
334 onRequestClose={closeModal}
335 contentLabel="Order Details"
336 className={styles.modal}
337 overlayClassName={styles.overlay}
338 >
339 <h2>Order Details - #{selectedOrder.id}</h2>
340
341 {selectedOrder.address && (() => {
342 const [street = '', number = '', floor = ''] = selectedOrder.address.split(';');
343 return (
344 <>
345 <p><strong>Street:</strong> {street}</p>
346 <p><strong>Number:</strong> {number}</p>
347 <p><strong>Floor:</strong> {floor}</p>
348 </>
349 );
350 })()}
351
352 <p><strong>Products:</strong></p>
353 <ul>
354 {productOrders.length > 0 ? (
355 productOrders.map(productOrder => (
356 <li key={productOrder.id}>
357 {productOrder.name} - {productOrder.quantity} grams
358 </li>
359 ))
360 ) : (
361 <li>No products available.</li>
362 )}
363 </ul>
364 <button className={styles.button} onClick={closeModal}>Close</button>
365 </Modal>
366 )}
367 </div>
368 );
369};
370
371export default DeliveryView;
Note: See TracBrowser for help on using the repository browser.