From e97dbb11b30d0fe51b2ca1660e9f0d27a99a73e3 Mon Sep 17 00:00:00 2001 From: omagdy7 Date: Fri, 22 Dec 2023 18:59:16 +0200 Subject: Added most of the logic on the driver side --- driver/package.json | 1 + driver/pnpm-lock.yaml | 27 +++++ driver/src/App.tsx | 173 ++------------------------------ driver/src/components/RideDialog.tsx | 110 +++++++++++++++++++++ driver/src/components/ui/avatar.tsx | 48 +++++++++ driver/src/components/ui/badge.tsx | 36 +++++++ driver/src/components/ui/card.tsx | 79 +++++++++++++++ driver/src/main.tsx | 5 + driver/src/pages/Home.tsx | 150 ++++++++++++++++++++++++++++ driver/src/pages/LandingPage.tsx | 45 +++++++++ driver/src/pages/Login.tsx | 92 ++++++++++-------- driver/src/pages/SignUp.tsx | 184 ++++++++++++++++++++++++++--------- driver/src/utils/fetchUserDetails.ts | 27 +++++ 13 files changed, 722 insertions(+), 255 deletions(-) create mode 100644 driver/src/components/RideDialog.tsx create mode 100644 driver/src/components/ui/avatar.tsx create mode 100644 driver/src/components/ui/badge.tsx create mode 100644 driver/src/components/ui/card.tsx create mode 100644 driver/src/pages/Home.tsx create mode 100644 driver/src/pages/LandingPage.tsx create mode 100644 driver/src/utils/fetchUserDetails.ts diff --git a/driver/package.json b/driver/package.json index fd6315d..9853e7c 100644 --- a/driver/package.json +++ b/driver/package.json @@ -10,6 +10,7 @@ "preview": "vite preview" }, "dependencies": { + "@radix-ui/react-avatar": "^1.0.4", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-slot": "^1.0.2", diff --git a/driver/pnpm-lock.yaml b/driver/pnpm-lock.yaml index 64c74ff..21624a2 100644 --- a/driver/pnpm-lock.yaml +++ b/driver/pnpm-lock.yaml @@ -5,6 +5,9 @@ settings: excludeLinksFromLockfile: false dependencies: + '@radix-ui/react-avatar': + specifier: ^1.0.4 + version: 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-dialog': specifier: ^1.0.5 version: 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) @@ -1154,6 +1157,30 @@ packages: '@babel/runtime': 7.23.6 dev: false + /@radix-ui/react-avatar@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-kVK2K7ZD3wwj3qhle0ElXhOjbezIgyl2hVvgwfIdexL3rN6zJmy5AqqIf+D31lxVppdzV8CjAfZ6PklkmInZLw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.18 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.45)(react@18.2.0): resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} peerDependencies: diff --git a/driver/src/App.tsx b/driver/src/App.tsx index 233b96d..9b3bb03 100644 --- a/driver/src/App.tsx +++ b/driver/src/App.tsx @@ -1,176 +1,15 @@ -import { addDoc, collection } from "firebase/firestore" -import { db } from "./firebase/firebase_config" -import { Button } from "@/components/ui/button" -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, - DialogTrigger, -} from "@/components/ui/dialog" -import { Input } from "@/components/ui/input" -import { Label } from "@/components/ui/label" -import { useState } from "react" - -interface RideOrder { - driverName: string - carModel: string - carColor: string - plateNumber: string - status: string - orderTime: Date - fromLocation: string - toLocation: string -} +import RideDialog from "./components/RideDialog" +import Home from "./pages/Home" +import LandingPage from "./pages/LandingPage" function App() { - - const [driverName, setDriverName] = useState() - const [carModel, setCarModel] = useState() - const [carColor, setCarColor] = useState() - const [plateNumber, setPlateNumber] = useState() - const [status, _setStatus] = useState('Pending') - const [orderTime, _setOrderTime] = useState(new Date()) - const [fromLocation, setFromLocation] = useState() - const [toLocation, setToLocation] = useState() - - const [_rideOrder, _setRideOrder] = useState({ - driverName: "Mahmoud", - carModel: "Toyota Corolla", - carColor: "Red", - plateNumber: "ABC-123", - status: "Pending", - orderTime: new Date("2023-12-20"), - fromLocation: "Abdu-Basha", - toLocation: "5th Settlement", - }) - - const addRideOrderToFirestore = async () => { - try { - // Get a reference to the 'rideOrders' collection - const rideOrdersCollection = collection(db, 'Rides'); - - // Add a new document to the 'rideOrders' collection with the data from the RideOrder object - const newRideOrderRef = await addDoc(rideOrdersCollection, { - driverName: driverName, - carModel: carModel, - carColor: carColor, - plateNumber: plateNumber, - status: status, - orderTime: orderTime, - fromLocation: fromLocation, - toLocation: toLocation, - }); - - console.log('Ride order added with ID:', newRideOrderRef.id); - // 'newRideOrderRef.id' will give you the document ID of the added ride order - } catch (error) { - console.error('Error adding ride order:', error); - } - }; - return ( -
- - - - - - - Ride details - - Please enter details about your ride and click submit for the ride to appear to other students! - - -
-
- - setDriverName(e.target.value)} - /> -
-
- - setCarModel(e.target.value)} - /> -
-
- - setToLocation(e.target.value)} - /> -
-
- - setFromLocation(e.target.value)} - /> -
-
- - setCarColor(e.target.value)} - /> -
-
- - setPlateNumber(e.target.value)} - /> -
-
- - - -
-
-
+ + // + // ) } -// interface RideOrder { -// driverName: string -// carModel: string -// carColor: string -// plateNumber: string -// status: string -// orderTime: Date -// fromLocation: string -// toLocation: string -// } export default App diff --git a/driver/src/components/RideDialog.tsx b/driver/src/components/RideDialog.tsx new file mode 100644 index 0000000..da7767b --- /dev/null +++ b/driver/src/components/RideDialog.tsx @@ -0,0 +1,110 @@ +import { addDoc, collection, doc, getDoc } from "firebase/firestore" +import { db } from "../firebase/firebase_config" +import { auth } from "../firebase/firebase_config" +import { Button } from "@/components/ui/button" +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { useState } from "react" + +interface RideOrder { + driverName: string + carBrand: string + carModel: string + carColor: string + plateNumber: string + status: string + orderTime: Date + pickUpLocation: string + dropOffLocation: string +} + + +function RideDialog({ name, brand, model, color, plateNumber }: any) { + + const [status, _setStatus] = useState('Pending') + const [orderTime, _setOrderTime] = useState(new Date()) + const [pickUpLocation, setPickUpLocation] = useState() + const [dropOffLocation, setDropOffLocation] = useState() + + + const addRideOrderToFirestore = async () => { + try { + // Get a reference to the 'rideOrders' collection + const rideOrdersCollection = collection(db, 'Rides'); + + // Add a new document to the 'rideOrders' collection with the data from the RideOrder object + const newRideOrderRef = await addDoc(rideOrdersCollection, { + driverName: name, + carModel: model, + carBrand: brand, + carColor: color, + plateNumber: plateNumber, + status: status, + orderTime: orderTime, + fromLocation: pickUpLocation, + toLocation: dropOffLocation, + }); + + console.log('Ride order added with ID:', newRideOrderRef.id); + // 'newRideOrderRef.id' will give you the document ID of the added ride order + } catch (error) { + console.error('Error adding ride order:', error); + } + }; + + return ( +
+ + + + + + + Ride details + + Please enter details about your ride and click submit for the ride to appear to other students! + + +
+
+ + setDropOffLocation(e.target.value)} + /> +
+
+ + setPickUpLocation(e.target.value)} + /> +
+
+ + + +
+
+
+ ) +} + +export default RideDialog; diff --git a/driver/src/components/ui/avatar.tsx b/driver/src/components/ui/avatar.tsx new file mode 100644 index 0000000..991f56e --- /dev/null +++ b/driver/src/components/ui/avatar.tsx @@ -0,0 +1,48 @@ +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/lib/utils" + +const Avatar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Avatar.displayName = AvatarPrimitive.Root.displayName + +const AvatarImage = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName + +const AvatarFallback = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/driver/src/components/ui/badge.tsx b/driver/src/components/ui/badge.tsx new file mode 100644 index 0000000..f000e3e --- /dev/null +++ b/driver/src/components/ui/badge.tsx @@ -0,0 +1,36 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const badgeVariants = cva( + "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: + "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", + secondary: + "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +export interface BadgeProps + extends React.HTMLAttributes, + VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return ( +
+ ) +} + +export { Badge, badgeVariants } diff --git a/driver/src/components/ui/card.tsx b/driver/src/components/ui/card.tsx new file mode 100644 index 0000000..afa13ec --- /dev/null +++ b/driver/src/components/ui/card.tsx @@ -0,0 +1,79 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Card = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +Card.displayName = "Card" + +const CardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardHeader.displayName = "CardHeader" + +const CardTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardTitle.displayName = "CardTitle" + +const CardDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardDescription.displayName = "CardDescription" + +const CardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardContent.displayName = "CardContent" + +const CardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardFooter.displayName = "CardFooter" + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } diff --git a/driver/src/main.tsx b/driver/src/main.tsx index 300ddc1..ab11de5 100644 --- a/driver/src/main.tsx +++ b/driver/src/main.tsx @@ -5,6 +5,7 @@ import App from './App.tsx' import './index.css' import Login from './pages/Login.tsx' import SignUp from './pages/SignUp.tsx' +import Home from './pages/Home.tsx' @@ -13,6 +14,10 @@ const router = createBrowserRouter([ path: "/", element: }, + { + path: "/home", + element: + }, { path: "/signup", element: diff --git a/driver/src/pages/Home.tsx b/driver/src/pages/Home.tsx new file mode 100644 index 0000000..81f1fb9 --- /dev/null +++ b/driver/src/pages/Home.tsx @@ -0,0 +1,150 @@ +import RideDialog from "@/components/RideDialog" +import { Avatar } from "@/components/ui/avatar" +import { Badge } from "@/components/ui/badge" +import { Button } from "@/components/ui/button" +import { CardTitle, CardHeader, CardContent, Card } from "@/components/ui/card" +import { auth, db } from "@/firebase/firebase_config" +import { fetchUserDetails } from "@/utils/fetchUserDetails" +import { DocumentData, collection, doc, getDoc, getDocs, query, where } from "firebase/firestore" +import { useEffect, useState } from "react" +import { Navigate } from "react-router-dom" + +interface IDriver { + uid: string, + name: string, + phoneNumber: string, + plateNumber: string, + carBrand: string, + carModel: string, + carColor: string, +} + +interface IPassengerRequest { + passengerName: string, + pickUp: string, + dropOff: string, +} + +interface ITrip { + pickUp: string, + dropOff: string, +} + +function PassengerRequestCard({ passengerName, pickUp, dropOff }: IPassengerRequest) { + return ( +
  • +

    + Passenger: {passengerName} +

    +

    + Pickup: {pickUp} +

    +

    + Dropoff: {dropOff} +

    +
    + + +
    +
  • + ) + +} + +export default function Home() { + const [driverData, setDriverData] = useState() + const [currentTrip, setCurrentTrip] = useState() + + + useEffect(() => { + async function fetchData() { + const data: IDriver | null | undefined = await fetchUserDetails(); + setDriverData(data) + } + fetchData() + }, [auth.currentUser, db]); + + return ( + !auth.currentUser ? : + ( +
    +
    +
    +

    Driver Dashboard

    + +

    {driverData?.name}

    + + Active Driver + +
    +
    + +
    +
    +
    + + + Vehicle Details + + +
      +
    • + Brand: {driverData?.carBrand} +
    • +
    • + Model: {driverData?.carModel} +
    • +
    • + License Plate: {driverData?.plateNumber} +
    • +
    +
    +
    + + + Current Trip + + +

    + Pickup: {currentTrip?.pickUp} +

    +

    + Dropoff: {currentTrip?.dropOff} +

    + + + +
    +
    + + + Passenger Requests + + +
      + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + ) + ) +} diff --git a/driver/src/pages/LandingPage.tsx b/driver/src/pages/LandingPage.tsx new file mode 100644 index 0000000..ec8b364 --- /dev/null +++ b/driver/src/pages/LandingPage.tsx @@ -0,0 +1,45 @@ +import { Button } from "@/components/ui/button" +import { CardTitle, CardDescription, CardHeader, CardContent, Card } from "@/components/ui/card" +import { Navigate, redirect } from "react-router-dom"; +import { Badge } from "@/components/ui/badge" + +export default function LandingPage() { + if (true) { + return + } + return ( +
    +
    +

    Carpool

    +
    + + +
    +
    +
    + + + Welcome to Carpool + Join our community and share your journey. + + +

    + Find or offer rides, Made by students for students ❤️ ❤️ +

    +
    +
    +
    + +
    +
    +
    +

    © 2023 Carpool. All rights reserved.

    +
    +
    + ) +} + diff --git a/driver/src/pages/Login.tsx b/driver/src/pages/Login.tsx index 0605dc8..1841d03 100644 --- a/driver/src/pages/Login.tsx +++ b/driver/src/pages/Login.tsx @@ -1,8 +1,10 @@ import { useState } from 'react'; import { auth } from '../firebase/firebase_config'; import { signInWithEmailAndPassword } from 'firebase/auth'; +import { Navigate, redirect } from "react-router-dom"; const Login = () => { + const [isLoggedIn, setIsLoggedIn] = useState(false) const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); @@ -10,7 +12,8 @@ const Login = () => { try { const userCredential = await signInWithEmailAndPassword(auth, email, password); console.log('User logged in:', userCredential.user); - // TODO: redirect the user to another page or perform some other action + setIsLoggedIn(true) + } catch (error) { console.error('Error logging in:', error); // TODO: Handle error messages or display them to the user. @@ -18,48 +21,53 @@ const Login = () => { }; return ( -
    -
    -

    Login

    -
    -
    - - setEmail(e.target.value)} - /> -
    -
    - - setPassword(e.target.value)} - /> -
    -
    - + isLoggedIn ? ( + + ) : + ( +
    +
    +

    Login

    + +
    + + setEmail(e.target.value)} + /> +
    +
    + + setPassword(e.target.value)} + /> +
    +
    + +
    +
    - -
    -
    +
    + ) ); }; diff --git a/driver/src/pages/SignUp.tsx b/driver/src/pages/SignUp.tsx index 3ee09dc..b73d810 100644 --- a/driver/src/pages/SignUp.tsx +++ b/driver/src/pages/SignUp.tsx @@ -1,11 +1,24 @@ +import { Label } from "@/components/ui/label" +import { Input } from "@/components/ui/input" +import { Button } from "@/components/ui/button" import { useState, useEffect } from 'react'; -import { auth } from '../firebase/firebase_config'; +import { auth, db } from '../firebase/firebase_config'; import { createUserWithEmailAndPassword } from 'firebase/auth'; - +import { Navigate, redirect } from "react-router-dom"; +import { addDoc, collection } from "firebase/firestore"; const SignUp = () => { - const [email, setEmail] = useState(''); - const [password, setPassword] = useState(''); + + const [isSignedUp, setIsSignedUp] = useState(false) + + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [name, setName] = useState('') + const [phoneNumber, setPhoneNumber] = useState('') + const [carBrand, setCarBrand] = useState('') + const [carModel, setCarModel] = useState('') + const [carColor, setCarColor] = useState('') + const [plateNumber, setPlateNumber] = useState('') useEffect(() => { const unsubscribe = auth.onAuthStateChanged((user) => { @@ -28,7 +41,20 @@ const SignUp = () => { try { // The onAuthStateChanged listener will handle the signed-in user state. const userCredential = await createUserWithEmailAndPassword(auth, email, password); + const usersCollection = collection(db, 'users'); + const userUid = userCredential.user.uid; // Get the user's UID + console.log(userUid, name, phoneNumber, carBrand, carModel, carColor, plateNumber) + addDoc(usersCollection, { + uid: userUid, + name: name, + phoneNumber: phoneNumber, + carBrand: carBrand, + carModel: carModel, + carColor: carColor, + plateNumber: plateNumber, + }) console.log('User signed up:', userCredential.user); + setIsSignedUp(true) } catch (error) { // TODO: Handle error messages or display them to the user. console.error('Error signing up:', error); @@ -36,48 +62,114 @@ const SignUp = () => { }; return ( -
    -
    -

    Sign Up

    -
    -
    - - setEmail(e.target.value)} - /> -
    -
    - - setPassword(e.target.value)} - /> -
    -
    - -
    -
    -
    -
    + isSignedUp ? + () : + (
    +
    +

    Sign Up

    +
    +
    + + setEmail(e.target.value)} + /> +
    +
    + + setPassword(e.target.value)} + /> +
    +
    + + setName(e.target.value)} + /> +
    +
    + + setPhoneNumber(e.target.value)} + /> +
    +
    + + setCarBrand(e.target.value)} + /> +
    +
    + + setCarModel(e.target.value)} + /> +
    +
    + + setCarColor(e.target.value)} + /> +
    +
    + + setPlateNumber(e.target.value)} + /> +
    +
    + +
    +
    +
    +
    ) ); }; diff --git a/driver/src/utils/fetchUserDetails.ts b/driver/src/utils/fetchUserDetails.ts new file mode 100644 index 0000000..949a4ab --- /dev/null +++ b/driver/src/utils/fetchUserDetails.ts @@ -0,0 +1,27 @@ +import { auth, db } from "@/firebase/firebase_config"; +import { DocumentData, collection, getDocs, query, where } from "firebase/firestore"; + + +export const fetchUserDetails = async () => { + const user = auth.currentUser; + console.log(user) + try { + let data = null + if (user) { + const usersRef = collection(db, "users") + const q = query(usersRef, where("uid", "==", user.uid)) + const querySnapshot = await getDocs(q); + querySnapshot.forEach((doc: DocumentData) => { + data = doc.data() + // setDriverData(doc.data()) + console.log(doc.id, " => ", doc.data()); + }); + return data; + } else { + console.log("There is no user"); + return null; + } + } catch (error) { + console.error('Error fetching user details:', error); + } +}; -- cgit v1.2.3