Skip to content

Commit d5c38bf

Browse files
committed
add driver arrival and driver name
1 parent 52a0156 commit d5c38bf

File tree

6 files changed

+270
-908
lines changed

6 files changed

+270
-908
lines changed

services/frontend/react_app/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@
1313
"@chakra-ui/react": "^2.8.2",
1414
"@emotion/react": "^11.11.4",
1515
"@emotion/styled": "^11.11.0",
16+
"@faker-js/faker": "^9.3.0",
1617
"framer-motion": "^11.0.8",
1718
"geojson-path-finder": "^2.0.2",
1819
"leaflet": "^1.9.4",
1920
"leaflet-routing-machine": "^3.2.12",
2021
"pigeon-maps": "^0.21.4",
2122
"react": "^18.2.0",
23+
"react-countdown": "^2.3.6",
2224
"react-dom": "^18.2.0",
2325
"react-leaflet": "^4.2.1"
2426
},
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import {Log, LogEntry} from "./useLogs.tsx";
2+
import {useEffect, useState} from "react";
3+
import { faker } from "@faker-js/faker";
4+
5+
export const useGetRequestArrival = (logs: Log[]) => {
6+
const [driverArrival, setDriverArrival] = useState<number | undefined>();
7+
const [driverName, setDriverName] = useState("");
8+
9+
const parseDriverLogService = (entry: LogEntry) => {
10+
if (entry.service !== 'driver') return;
11+
12+
const timeRegex = /(\d+)m(\d+)s/;
13+
const match = entry.status.match(timeRegex);
14+
15+
if (!match) return;
16+
17+
const minutes = parseInt(match[1], 10);
18+
const seconds = parseInt(match[2], 10);
19+
20+
return minutes * 60 + seconds;
21+
};
22+
23+
useEffect(() => {
24+
if (logs.length === 0) return;
25+
26+
const lastRequestDrive = logs[0];
27+
28+
setDriverArrival(undefined);
29+
30+
if (!lastRequestDrive) {
31+
setDriverArrival(undefined);
32+
return;
33+
}
34+
35+
const driverEntries = lastRequestDrive.entries.filter((e) => e.service === 'driver');
36+
const parsedTime = driverEntries
37+
.map((e) => parseDriverLogService(e))
38+
.find((e) => e !== undefined);
39+
40+
setDriverName(faker.person.fullName());
41+
setDriverArrival(parsedTime);
42+
}, [logs]);
43+
44+
45+
return {
46+
driverArrival,
47+
driverName,
48+
};
49+
};

services/frontend/react_app/src/hooks/useLogs.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ export type LogEntry = {
2020
export const useLogs = () => {
2121
const [logs, setLogs] = useState<Log[]>([]);
2222

23-
2423
const addNewLog = (pickupLocation: Location, dropoffLocation: Location, requestID: number, log: LogEntry) => {
2524
setLogs(prev => [{ pickupLocation, dropoffLocation, requestID, entries: [log]}, ...prev])
2625
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
.drawer {
2+
position: fixed;
3+
top: 0;
4+
right: 0;
5+
width: 700px;
6+
height: 100%;
7+
background: white;
8+
box-shadow: -2px 0 5px rgba(0, 0, 0, 0.1);
9+
transform: translateX(100%);
10+
transition: transform 0.3s ease;
11+
z-index: 999999;
12+
display: flex;
13+
flex-direction: column; /* Ensures vertical stacking */
14+
15+
gap: 1rem;
16+
}
17+
18+
.drawer.open {
19+
transform: translateX(0);
20+
}
21+
22+
.drawer-header {
23+
padding: 1rem;
24+
border-bottom: 1px solid #ddd;
25+
text-align: left;
26+
}
27+
28+
.drawer-body {
29+
flex: 1; /* Fills available space */
30+
padding: 1rem;
31+
overflow-y: auto; /* Allows scrolling when content overflows */
32+
}
33+
34+
.drawer-footer {
35+
padding: 1rem;
36+
border-top: 1px solid #ddd;
37+
background: white;
38+
}
39+
40+
41+
42+
.leaflet-control { z-index: 0 !important}
43+
.leaflet-pane { z-index: 0 !important}
44+
.leaflet-top, .leaflet-bottom {z-index: 0 !important}

services/frontend/react_app/src/pages/home.tsx

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,15 @@ import {
55
Card,
66
CardBody,
77
CardHeader,
8-
Drawer,
9-
DrawerBody,
10-
DrawerContent,
11-
DrawerFooter,
12-
DrawerHeader,
138
Heading,
149
HStack,
1510
Stack,
1611
StackDivider,
12+
Text,
1713
useDisclosure,
1814
useToast,
1915
} from "@chakra-ui/react";
16+
import styles from "./home.module.css";
2017

2118
import {Logs} from "../components/features/logs/logs.tsx";
2219
import {Map} from "../components/features/map/map.tsx";
@@ -27,6 +24,16 @@ import {Locations} from "../types/location.ts";
2724
import {LocationSelect} from "../components/common/locationSelect/locationSelect.tsx";
2825
import {useLogs} from "../hooks/useLogs.tsx";
2926
import {NotificationResponse} from "../types/notifications.ts";
27+
import {useGetRequestArrival} from "../hooks/useGetRequestArrival.tsx";
28+
import Countdown, {CountdownRenderProps} from "react-countdown";
29+
30+
const countdownRenderer = ({minutes, seconds, completed, driverName}: CountdownRenderProps & { driverName: string }) => {
31+
if (completed) {
32+
return <Text>{driverName} arrived</Text>;
33+
} else {
34+
return <Text as="b">The driver {driverName} will arrive in {minutes.toString().padStart(2, "0")}:{seconds.toString().padStart(2, "0")}</Text>;
35+
}
36+
};
3037

3138
export const HomePage = () => {
3239
const session = useSession();
@@ -35,6 +42,7 @@ export const HomePage = () => {
3542

3643
const [selectedLocations, setSelectedLocations] = useState({pickupId: -1, dropoffId: -1});
3744
const {logs, addNewLog, addErrorEntry, addInformationEntry} = useLogs();
45+
const lastRequestedDrive = useGetRequestArrival(logs);
3846

3947
const logsModal = useDisclosure();
4048
const toast = useToast();
@@ -179,39 +187,41 @@ export const HomePage = () => {
179187
>
180188
Request Ride
181189
</Button>
182-
{/*<Text color='gray' mt={4}>The distance between the two points is 40 miles</Text>*/}
183190
</Box>
184191
</Stack>
185192
</CardBody>
186193
</Card>
194+
195+
{lastRequestedDrive.driverArrival &&
196+
<HStack divider={<StackDivider/>} spacing='4' justifyContent="center" alignItems="center"
197+
bg="teal.200" p="1rem" maxW={600} borderRadius={4}>
198+
<Countdown
199+
date={new Date(Date.now()).setSeconds(lastRequestedDrive.driverArrival)}
200+
renderer={(props) => countdownRenderer({
201+
...props,
202+
driverName: lastRequestedDrive.driverName
203+
})}
204+
/>
205+
</HStack>}
187206
</Stack>
188207
<Stack flexGrow={1} justifyContent='space-between' w='50%' h='100%' maxH={'900px'}>
189-
<Drawer
190-
isOpen={logsModal.isOpen}
191-
placement='right'
192-
onClose={() => {
193-
}}
194-
size="lg"
195-
trapFocus={false}
196-
blockScrollOnMount={false}
197-
variant="aside"
198-
>
199-
<DrawerContent>
200-
<DrawerHeader>Notifications logs</DrawerHeader>
201-
202-
<DrawerBody>
203-
<Logs logs={logs}/>
204-
</DrawerBody>
205-
206-
<DrawerFooter>
207-
<Button variant='outline' mr={3} onClick={logsModal.onClose}>
208-
Close
209-
</Button>
210-
</DrawerFooter>
211-
</DrawerContent>
212-
</Drawer>
208+
<div className={`${styles.drawer} ${logsModal.isOpen ? styles.open : ''}`}>
209+
<div className={styles.drawerHeader}>
210+
<Heading size="md">Notifications Logs</Heading>
211+
</div>
212+
<div className={styles.drawerBody}>
213+
<Logs logs={logs}/>
214+
</div>
215+
<div className={styles.drawerFooter}>
216+
<Button variant="outline" onClick={logsModal.onClose}>
217+
Close
218+
</Button>
219+
</div>
220+
</div>
221+
213222
<Stack flexGrow={1} flexShrink={1}>
214-
<Map dropoffLocationID={selectedLocations.dropoffId} pickupLocationID={selectedLocations.pickupId}/>
223+
<Map dropoffLocationID={selectedLocations.dropoffId}
224+
pickupLocationID={selectedLocations.pickupId}/>
215225
</Stack>
216226
<Button variant='outline' size="sm" onClick={logsModal.onToggle}>Show Logs</Button>
217227
</Stack>

0 commit comments

Comments
 (0)