From 49570613bd734376823b23e6121f586bbb959cba Mon Sep 17 00:00:00 2001 From: Tanmayi Manku Date: Fri, 8 Dec 2023 21:47:36 +0530 Subject: [PATCH 1/7] Implement delete car feature(changes the badge) --- src/components/DeleteCars/DeleteList.js | 58 +++++++++++++++++++- src/components/DeleteCars/EachCarDelete.js | 37 +++++++++++++ src/pages/LandingPage/DeleteCar/DeleteCar.js | 11 ++++ src/redux/cars/carsSlice.js | 57 ++++++++++++++++++- 4 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 src/components/DeleteCars/EachCarDelete.js create mode 100644 src/pages/LandingPage/DeleteCar/DeleteCar.js diff --git a/src/components/DeleteCars/DeleteList.js b/src/components/DeleteCars/DeleteList.js index edc11aa..c52cee8 100644 --- a/src/components/DeleteCars/DeleteList.js +++ b/src/components/DeleteCars/DeleteList.js @@ -1 +1,57 @@ -// delete cars list component +import React from 'react'; +import { useDispatch } from "react-redux"; +import { useSelector } from "react-redux"; +import EachCarDelete from './EachCarDelete'; + +const DeleteList = () => { +// const cars = useSelector((state) => state.cars.cars) + const mockData = [ + { + "id": 3, + "name": "Car1", + "description": "Description for Car1", + "removed": false + }, + { + "id": 4, + "name": "Car1111", + "description": "Description for Car1", + "removed": false + } +]; +const cars = mockData; +// const status = useSelector((state) => state.cars.status) +// const error = useSelector((state) => state.cars.error) + +// if (status) { +// return Loading...; +// } + +// if (error) { +// return Something went wrong!; +// } + + + return ( + <> +
+

Cars List

+ + + + + + + + + {cars.map((car) => ( + + ))} + +
Car TitleStatus
+
+ + ); +}; + +export default DeleteList; \ No newline at end of file diff --git a/src/components/DeleteCars/EachCarDelete.js b/src/components/DeleteCars/EachCarDelete.js new file mode 100644 index 0000000..e3b012d --- /dev/null +++ b/src/components/DeleteCars/EachCarDelete.js @@ -0,0 +1,37 @@ +import PropTypes from 'prop-types'; +import { useDispatch } from "react-redux"; +import { deleteCar } from "../../redux/thunk"; +import { markCarDelete } from "../../redux/cars/carsSlice"; + +const EachCarDelete = ({car}) => { + const { + name, + id, + removed + } = car; + + const dispatch = useDispatch(); + const handleDelete = () => { + dispatch(deleteCar(id)); + if(!removed) { + dispatch(markCarDelete(id)) + } + } + + return ( + + {name} + + + ) +} + +EachCarDelete.propTypes = { + car: PropTypes.shape({ + name: PropTypes.string.isRequired, + id: PropTypes.number.isRequired, + removed: PropTypes.bool.isRequired, + }).isRequired, +}; + +export default EachCarDelete; diff --git a/src/pages/LandingPage/DeleteCar/DeleteCar.js b/src/pages/LandingPage/DeleteCar/DeleteCar.js new file mode 100644 index 0000000..6fe2086 --- /dev/null +++ b/src/pages/LandingPage/DeleteCar/DeleteCar.js @@ -0,0 +1,11 @@ +import React from 'react'; +import DeleteList from '../../../components/DeleteCars/DeleteList'; + +const DeleteCar = () => { + <> +

Delete items list page

+ + +} + +export default DeleteCar; diff --git a/src/redux/cars/carsSlice.js b/src/redux/cars/carsSlice.js index 48e5a9b..566fb2e 100644 --- a/src/redux/cars/carsSlice.js +++ b/src/redux/cars/carsSlice.js @@ -1 +1,56 @@ -// carsSlice File. +import { createSlice } from '@reduxjs/toolkit'; +import { deleteCar, fetchCars } from '../thunk'; + +const initialState = { + cars: [], + status: 'idle', + error: null +}; + + +const carSlice = createSlice({ + name: 'cars', + initialState, + reducers: { + markCarDelete: (state, action) => { + const newState = state.cars.map((car) => (car.carId === action.payload ? ({...car, removed: true}) : car)); + state.cars = newState; + } + }, + extraReducers: (builder) => { + builder + .addCase(fetchCars.pending, (state) => { + state.status = 'loading'; + state.error = null; + }) + .addCase(fetchCars.fulfilled, (state, action) => { + state.status = 'succeeded'; + const fetchedData = []; + action.payload.forEach((car) => { + const data = {...car, removed: false} + fetchedData.push(data); + }) + state.cars = fetchedData; + console.log('the cars: ') + console.log(state.cars); + }) + .addCase(fetchCars.rejected, (state, action) => { + state.status = 'failed'; + state.error = action.error.message; + }) + .addCase(deleteCar.pending, (state) => { + state.status = 'loading'; + state.error = null; + }) + .addCase(deleteCar.fulfilled, (state, action) => { + state.status = 'succeeded'; + state.cars = state.cars.filter((car) => car.carId !== action.payload.id); }) + .addCase(deleteCar.rejected, (state, action) => { + state.status = 'failed'; + state.error = action.payload ? action.payload.error : 'Delete failed'; + }); + }, + }); + + export const {markCarDelete} = carSlice.actions; + export default carSlice.reducer; \ No newline at end of file From e0387eb8cfc660f59711eb563f0503232cf333cd Mon Sep 17 00:00:00 2001 From: Tanmayi Manku Date: Fri, 8 Dec 2023 21:48:02 +0530 Subject: [PATCH 2/7] Add fetch cars and delete car async thunk methods --- src/redux/thunk.js | 50 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/src/redux/thunk.js b/src/redux/thunk.js index 8572991..efd2d39 100644 --- a/src/redux/thunk.js +++ b/src/redux/thunk.js @@ -71,15 +71,19 @@ export const registerUser = createAsyncThunk('auth/register', async (user, thunk export const logoutUser = createAsyncThunk('auth/logout', async (_, thunkAPI) => { try { - const response = await axios.delete(`${baseURL}/users`, { - headers: { Authorization: localStorage.getItem('token') }, + const token = getAuthenticationToken(); + const authToken = token ? token.replace('Bearer ', '') : ''; + console.log('authtoken:',authToken); + + const response = await axios.delete(`${baseURL}/users/sign_out`, { + headers: { Authorization: authToken }, }); const { status, message } = await handleResponse(response); - - if (status === 'succeeded') { - removeAuthenticationToken(); - } + removeAuthenticationToken(); + // console.log('logout async method'); + // if (status === 'succeeded') { + // } return { status, message }; } catch (error) { @@ -125,3 +129,37 @@ export const fetchCarReservations = createAsyncThunk( } }, ); + +export const fetchCars = createAsyncThunk( + 'cars/fetchCars', + async(_, thunkAPI) => { + try { + const token = localStorage.getItem('token'); + const response = await axios.get(`${baseURL}/cars`, { + headers: { + Authorization: token, + }, + }); + return response.data; + } catch (error) { + return thunkAPI.rejectWithValue(error); + } + } +) + +export const deleteCar = createAsyncThunk( + 'cars/deleteCar', + async(carId, thunkAPI) => { + try { + const token = localStorage.getItem('token'); + const response = await axios.delete(`${baseURL}/cars/${carId}`, { + headers: { + Authorization: token, + }, + }); + return response.data; + } catch (error) { + return thunkAPI.rejectWithValue(error); + } + } +); From 98a84b11e4e08f93034cb34fb395d895a3304aa1 Mon Sep 17 00:00:00 2001 From: Tanmayi Manku Date: Fri, 8 Dec 2023 21:48:41 +0530 Subject: [PATCH 3/7] Update the redirection routes for signin, signup. --- src/assets/reserve_page_background.png | Bin 0 -> 82354 bytes .../MyReservations/MyReservationsList.js | 64 ++++++++++++------ src/layout/UsersDashboard/sideNav/Nav.js | 13 +++- .../UsersDashboard/sideNav/navConfig.js | 8 +-- src/pages/Auth/SignIn/SigninForm.js | 7 +- src/pages/Auth/SignUp/SignupForm.js | 3 +- .../DeleteReservation/DeleteReservation.js | 5 -- .../authentication/authenticationSlice.js | 2 + src/redux/reservations/reservationSlice.js | 2 + src/routes/routeConstants.js | 2 +- src/routes/routes.js | 7 +- src/styles/App.css | 18 +++++ 12 files changed, 93 insertions(+), 38 deletions(-) create mode 100644 src/assets/reserve_page_background.png delete mode 100644 src/pages/LandingPage/DeleteReservation/DeleteReservation.js diff --git a/src/assets/reserve_page_background.png b/src/assets/reserve_page_background.png new file mode 100644 index 0000000000000000000000000000000000000000..ee9003d4fa799630339e66c5de41741b7734eeb6 GIT binary patch literal 82354 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�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 literal 0 HcmV?d00001 diff --git a/src/components/MyReservations/MyReservationsList.js b/src/components/MyReservations/MyReservationsList.js index 495b2e4..5d1b809 100644 --- a/src/components/MyReservations/MyReservationsList.js +++ b/src/components/MyReservations/MyReservationsList.js @@ -1,35 +1,59 @@ -import React, {useEffect} from 'react'; +import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { fetchCarReservations } from '../../redux/thunk'; const MyReservationsList = () => { - const dispatch = useDispatch(); - const myReservations = useSelector((state) => state.reservation.reservations); - const status = useSelector((state) => state.reservation.status); - const error = useSelector((state) => state.reservation.error); + const mockData = [ + { + id: 1, + car: { + id: 3, + name: "Car1" + }, + date: "2023-01-02", + city: "No Peace" + }, + { + id: 2, + car: { + id: 4, + name: "Car2" + }, + date: "2023-01-03", + city: "Tranquil Town" + }, + // Add more mock data as needed + ]; + const dispatch = useDispatch(); +// const myReservations = useSelector((state) => state.reservation.reservations); +const myReservations = mockData; + const status = useSelector((state) => state.reservation.status); + const error = useSelector((state) => state.reservation.error); - useEffect(() => { - dispatch(fetchCarReservations()); - }, [dispatch]); + useEffect(() => { + dispatch(fetchCarReservations()); + }, [dispatch]); - if (status === 'loading') { + if (status === 'loading') { return

Loading...

; - } + } - if (status === 'failed') { + if (status === 'failed') { return

Error: {error}

; - } + } - return ( -
-

My Reservations

- {myReservations.map((reservation) => ( -
-

{`Car: ${reservation.car.name}, Date: ${reservation.date}, City: ${reservation.city}`}

+ return ( +
+

My Reservations

+ {myReservations && myReservations.map((reservation) => ( +
+ {`Car: ${reservation.car.name}`} + {`Date: ${reservation.date}`} + {`City: ${reservation.city}`}
- ))} + ))}
- ); + ); }; export default MyReservationsList; diff --git a/src/layout/UsersDashboard/sideNav/Nav.js b/src/layout/UsersDashboard/sideNav/Nav.js index 27ee43b..2cdadd4 100644 --- a/src/layout/UsersDashboard/sideNav/Nav.js +++ b/src/layout/UsersDashboard/sideNav/Nav.js @@ -2,10 +2,19 @@ import React from "react"; import styled from "@emotion/styled"; +import { useDispatch } from "react-redux"; + import navConfig from "./navConfig"; import { NavBoxItem } from "../../../components/Link/Link"; +import { logoutUser } from "../../../redux/thunk"; const Nav = () => { + const dispatch = useDispatch(); + + const handleLogout = () => { + dispatch(logoutUser()); + console.log('log out successful'); + } return ( @@ -15,8 +24,8 @@ const Nav = () => { ))} - - + + Logout diff --git a/src/layout/UsersDashboard/sideNav/navConfig.js b/src/layout/UsersDashboard/sideNav/navConfig.js index e338f1b..59f7578 100644 --- a/src/layout/UsersDashboard/sideNav/navConfig.js +++ b/src/layout/UsersDashboard/sideNav/navConfig.js @@ -3,8 +3,8 @@ import { MY_RESERVATIONS, USERDASHBOARDHOME, ADD_NEW_CAR, - DELETE_RESERVATION, - CONTACT + CONTACT, + DELETE_CAR } from '../../../routes/routeConstants'; const navConfig = [ @@ -33,8 +33,8 @@ const navConfig = [ }, { - title: 'Delete Reservation', - path: DELETE_RESERVATION, + title: 'Delete Car', + path: DELETE_CAR, // icon: PlaneIcon(), }, diff --git a/src/pages/Auth/SignIn/SigninForm.js b/src/pages/Auth/SignIn/SigninForm.js index 445a515..af7bde7 100644 --- a/src/pages/Auth/SignIn/SigninForm.js +++ b/src/pages/Auth/SignIn/SigninForm.js @@ -15,8 +15,11 @@ const SignInForm = () => { const handleSubmit = (values) => { console.log(values); dispatch(loginUser(values)); - console.log('Login successful'); - navigate('/'); + if (getAuthenticationToken()) { + console.log('token status:', getAuthenticationToken()); + console.log('Login successful'); + navigate('/u/dashboard/home'); + } }; return ( diff --git a/src/pages/Auth/SignUp/SignupForm.js b/src/pages/Auth/SignUp/SignupForm.js index 596d165..c1bd856 100644 --- a/src/pages/Auth/SignUp/SignupForm.js +++ b/src/pages/Auth/SignUp/SignupForm.js @@ -14,7 +14,8 @@ const SignUpForm = () => { const handleSubmit = (values) => { console.log(values); dispatch(registerUser(values)); - navigate('/'); + console.log('Sigup successful'); + navigate('/u/dashboard/home'); }; return ( diff --git a/src/pages/LandingPage/DeleteReservation/DeleteReservation.js b/src/pages/LandingPage/DeleteReservation/DeleteReservation.js deleted file mode 100644 index 9be9f07..0000000 --- a/src/pages/LandingPage/DeleteReservation/DeleteReservation.js +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react'; - -const DeleteReservation = () =>

Delete Reservation

; - -export default DeleteReservation; diff --git a/src/redux/authentication/authenticationSlice.js b/src/redux/authentication/authenticationSlice.js index 6209695..ae5e9ba 100644 --- a/src/redux/authentication/authenticationSlice.js +++ b/src/redux/authentication/authenticationSlice.js @@ -49,7 +49,9 @@ const authenticationSlice = createSlice({ }) .addCase(logoutUser.fulfilled, (state, action) => { state.authenticatedUser = {}; + console.log('user has been logged out') state.status = action.payload.status; + console.log('current status is:', state.status) }) .addCase(logoutUser.rejected, (state, action) => { state.status = 'failed'; diff --git a/src/redux/reservations/reservationSlice.js b/src/redux/reservations/reservationSlice.js index 0422aad..b476aa8 100644 --- a/src/redux/reservations/reservationSlice.js +++ b/src/redux/reservations/reservationSlice.js @@ -33,6 +33,8 @@ const reservationSlice = createSlice({ .addCase(fetchCarReservations.fulfilled, (state, action) => { state.status = 'succeeded'; state.reservations = action.payload.data; + console.log('the reservations: ') + console.log(state.reservations); }) .addCase(fetchCarReservations.rejected, (state, action) => { state.status = 'failed'; diff --git a/src/routes/routeConstants.js b/src/routes/routeConstants.js index 8e181ff..0f1ca5f 100644 --- a/src/routes/routeConstants.js +++ b/src/routes/routeConstants.js @@ -9,7 +9,7 @@ export const HOME = '/'; export const MY_RESERVATIONS = 'my-reservations'; export const RESERVE_CARS = 'reserve-cars'; export const ADD_NEW_CAR = 'add-new-car'; -export const DELETE_RESERVATION = 'delete-reservation'; +export const DELETE_CAR = 'delete-car'; export const CONTACT = 'contact' export const ITEMS = 'cars'; export const ITEM_DETAIL = '/u/dashboard/item-details'; diff --git a/src/routes/routes.js b/src/routes/routes.js index fc5989e..0a33f70 100644 --- a/src/routes/routes.js +++ b/src/routes/routes.js @@ -21,7 +21,7 @@ import { USERDASHBOARDHOME, USERS_DASHBOARD, ADD_NEW_CAR, - DELETE_RESERVATION, + DELETE_CAR, ITEM_DETAIL, CONTACT, NOTFOUND, @@ -29,8 +29,9 @@ import { import UsersDashboardLayout from '../layout/UsersDashboard/UsersDashboardLayout'; import DashboardHome from '../pages/UserDashboard/DashboardHome'; import AddNewCar from '../pages/LandingPage/AddNewCar/AddNewCar'; -import DeleteReservation from '../pages/LandingPage/DeleteReservation/DeleteReservation'; +import DeleteCar from '../pages/LandingPage/DeleteCar/DeleteCar'; import Contact from '../pages/LandingPage/Contact/Contact'; +import DeleteList from '../components/DeleteCars/DeleteList'; export default function Router() { return useRoutes([ @@ -52,7 +53,7 @@ export default function Router() { { path: RESERVE_CARS, element: }, { path: ADD_NEW_CAR, element: }, { path: ITEM_DETAIL, element: }, - { path: DELETE_RESERVATION, element: }, + { path: DELETE_CAR, element: }, { path: CONTACT, element: }, { path: NOTFOUND, element: }, diff --git a/src/styles/App.css b/src/styles/App.css index 743ca5e..b3edad1 100644 --- a/src/styles/App.css +++ b/src/styles/App.css @@ -66,3 +66,21 @@ select.css-zdsokt { border-radius: 3rem; min-width: 150px; } + +.my-reservations-inner { + display: flex; + flex-direction: column; + gap: 20px; + align-items: center; +} + +.each-reservation-div { + width: 100%; + padding: 1rem 2rem; + background: #fff; + min-height: 70px; + display: flex; + align-items: center; + gap: 10px; + justify-content: space-between; +} From 0ef9dc4b5616aa41db73ca4e37e1988922ff0857 Mon Sep 17 00:00:00 2001 From: Tanmayi Manku Date: Sun, 10 Dec 2023 02:52:25 +0530 Subject: [PATCH 4/7] Used the api calls data instead of mock data & update --- src/App.js | 15 ++++++- src/components/Card/DisplayCartCard.js | 5 ++- src/components/Card/DisplayItemCard.js | 37 +++++++++++----- src/components/DeleteCars/DeleteList.js | 44 +++++++------------ src/components/DeleteCars/EachCarDelete.js | 5 ++- .../MyReservations/MyReservationsList.js | 19 ++++---- src/components/ReserveCars/ReserveCar.js | 11 ++++- src/components/ReserveCars/ReserveCarForm.js | 44 +++++++++++-------- .../LandingPage/ReserveCars/ReserveCars.js | 26 ++++++++--- src/pages/LoadingText.js | 7 +++ src/pages/UserDashboard/DashboardHome.js | 10 +++-- .../UserDashboard/ItemDetail/ItemDetail.js | 33 +++++++++++--- src/redux/cars/carsSlice.js | 14 +++--- src/redux/reservations/reservationSlice.js | 2 +- src/redux/store.js | 4 +- src/redux/thunk.js | 37 +++++++++++++--- src/routes/routes.js | 16 +++++-- 17 files changed, 221 insertions(+), 108 deletions(-) create mode 100644 src/pages/LoadingText.js diff --git a/src/App.js b/src/App.js index a21ea62..0ff45ea 100644 --- a/src/App.js +++ b/src/App.js @@ -1,8 +1,21 @@ import './styles/App.css'; -import React from 'react'; +import React, {useEffect} from 'react'; import Router from './routes/routes'; +import { useDispatch, useSelector } from 'react-redux'; +import { fetchCarReservations, fetchCars } from './redux/thunk'; function App() { + const authenticationStatus = useSelector((state) => state.authentication.status); + const isAuthenticated = authenticationStatus === 'succeeded'; + const dispatch = useDispatch(); + + useEffect(() => { + if (isAuthenticated) { + dispatch(fetchCars()); + dispatch(fetchCarReservations()); + } + }, [dispatch, isAuthenticated]); + return ( <> diff --git a/src/components/Card/DisplayCartCard.js b/src/components/Card/DisplayCartCard.js index ba685c7..97197fc 100644 --- a/src/components/Card/DisplayCartCard.js +++ b/src/components/Card/DisplayCartCard.js @@ -4,8 +4,8 @@ import styled from '@emotion/styled'; import { FaFacebook, FaTwitter, FaInstagram } from 'react-icons/fa'; import { Link } from 'react-router-dom'; -const DisplayCartCard = ({ imageName, name, shortNote }) => ( - +const DisplayCartCard = ({ id, imageName, name, shortNote }) => ( + {name} {name} @@ -26,6 +26,7 @@ const DisplayCartCard = ({ imageName, name, shortNote }) => ( ); DisplayCartCard.propTypes = { + id: PropTypes.number.isRequired, imageName: PropTypes.string.isRequired, name: PropTypes.string.isRequired, shortNote: PropTypes.string.isRequired, diff --git a/src/components/Card/DisplayItemCard.js b/src/components/Card/DisplayItemCard.js index 43c5de8..68810d5 100644 --- a/src/components/Card/DisplayItemCard.js +++ b/src/components/Card/DisplayItemCard.js @@ -2,10 +2,21 @@ import React, { useState } from 'react'; import PropTypes from 'prop-types'; import styled from '@emotion/styled'; import { FaCog, FaArrowRight, FaSyncAlt } from 'react-icons/fa'; +import { useSelector } from 'react-redux'; +import { useNavigate } from 'react-router-dom'; +import { RESERVE_CARS, USERS_DASHBOARD } from '../../routes/routeConstants'; -const DisplayItemCard = ({ name, imgSrc, amount, description }) => { +const DisplayItemCard = ({ id, name, description, pricePerHr, seating_capacity, imgSrc }) => { + const username = useSelector((state) => state.authentication.authenticatedUser.username); + const navigate = useNavigate(); const [rotation, setRotation] = useState(0); + const handleReserveClick = () => { + navigate(`${USERS_DASHBOARD}/${RESERVE_CARS}`, { + state: { id, username, name } + }); + } + const handleRotate = () => { setRotation((prevRotation) => (prevRotation + 90) % 360); }; @@ -24,20 +35,20 @@ const DisplayItemCard = ({ name, imgSrc, amount, description }) => { - Finance Fee - {amount} + Rent Price per Hour + {pricePerHr} - Opton to purchase fee - {amount} + Seating Capacity + {seating_capacity} - Total amount payable - {amount} + Currently available for booking? + Yes - Duration - {amount} + Minimum Rental Duration + 4 hrs
@@ -46,7 +57,7 @@ const DisplayItemCard = ({ name, imgSrc, amount, description }) => { DISCOVER MORE MODEL - + @@ -60,10 +71,12 @@ const DisplayItemCard = ({ name, imgSrc, amount, description }) => { )}; DisplayItemCard.propTypes = { + id: PropTypes.number.isRequired, name: PropTypes.string.isRequired, - amount: PropTypes.string.isRequired, description: PropTypes.string.isRequired, - imgSrc: PropTypes.string.isRequired, + pricePerHr: PropTypes.number.isRequired, + seating_capacity: PropTypes.number.isRequired, + imgSrc: PropTypes.string.isRequired }; const Container = styled.div` diff --git a/src/components/DeleteCars/DeleteList.js b/src/components/DeleteCars/DeleteList.js index c52cee8..c252642 100644 --- a/src/components/DeleteCars/DeleteList.js +++ b/src/components/DeleteCars/DeleteList.js @@ -1,36 +1,24 @@ import React from 'react'; -import { useDispatch } from "react-redux"; import { useSelector } from "react-redux"; import EachCarDelete from './EachCarDelete'; const DeleteList = () => { -// const cars = useSelector((state) => state.cars.cars) - const mockData = [ - { - "id": 3, - "name": "Car1", - "description": "Description for Car1", - "removed": false - }, - { - "id": 4, - "name": "Car1111", - "description": "Description for Car1", - "removed": false - } -]; -const cars = mockData; -// const status = useSelector((state) => state.cars.status) -// const error = useSelector((state) => state.cars.error) - -// if (status) { -// return Loading...; -// } - -// if (error) { -// return Something went wrong!; -// } - + const cars = useSelector((state) => state.cars.cars) +// const mockData = [ +// { +// "id": 3, +// "name": "Car1", +// "description": "Description for Car1", +// "removed": false +// }, +// { +// "id": 4, +// "name": "Car1111", +// "description": "Description for Car1", +// "removed": false +// } +// ]; +// const cars = mockData; return ( <> diff --git a/src/components/DeleteCars/EachCarDelete.js b/src/components/DeleteCars/EachCarDelete.js index e3b012d..6c81a40 100644 --- a/src/components/DeleteCars/EachCarDelete.js +++ b/src/components/DeleteCars/EachCarDelete.js @@ -1,5 +1,5 @@ import PropTypes from 'prop-types'; -import { useDispatch } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import { deleteCar } from "../../redux/thunk"; import { markCarDelete } from "../../redux/cars/carsSlice"; @@ -9,7 +9,6 @@ const EachCarDelete = ({car}) => { id, removed } = car; - const dispatch = useDispatch(); const handleDelete = () => { dispatch(deleteCar(id)); @@ -18,6 +17,8 @@ const EachCarDelete = ({car}) => { } } + + return ( {name} diff --git a/src/components/MyReservations/MyReservationsList.js b/src/components/MyReservations/MyReservationsList.js index 5d1b809..f36dc5d 100644 --- a/src/components/MyReservations/MyReservationsList.js +++ b/src/components/MyReservations/MyReservationsList.js @@ -1,6 +1,6 @@ import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { fetchCarReservations } from '../../redux/thunk'; +// import { fetchCarReservations, fetchCars } from '../../redux/thunk'; const MyReservationsList = () => { const mockData = [ @@ -24,15 +24,18 @@ const MyReservationsList = () => { }, // Add more mock data as needed ]; - const dispatch = useDispatch(); -// const myReservations = useSelector((state) => state.reservation.reservations); -const myReservations = mockData; + // const dispatch = useDispatch(); + const myReservations = useSelector((state) => state.reservation.reservations); + console.log(myReservations[1]); + console.log(myReservations[1].car.name); +// const myReservations = mockData; const status = useSelector((state) => state.reservation.status); const error = useSelector((state) => state.reservation.error); - useEffect(() => { - dispatch(fetchCarReservations()); - }, [dispatch]); + // useEffect(() => { + // dispatch(fetchCarReservations()); + // dispatch(fetchCars()); + // }, [dispatch]); if (status === 'loading') { return

Loading...

; @@ -47,7 +50,7 @@ const myReservations = mockData;

My Reservations

{myReservations && myReservations.map((reservation) => (
- {`Car: ${reservation.car.name}`} + {`Car: ${reservation.car && reservation.car.name ? reservation.car.name : 'No name'}`} {`Date: ${reservation.date}`} {`City: ${reservation.city}`}
diff --git a/src/components/ReserveCars/ReserveCar.js b/src/components/ReserveCars/ReserveCar.js index 3dfcbe9..2fdab1f 100644 --- a/src/components/ReserveCars/ReserveCar.js +++ b/src/components/ReserveCars/ReserveCar.js @@ -1,7 +1,8 @@ +import PropTypes from 'prop-types'; import React from 'react'; import ReserveCarFrom from './ReserveCarForm'; -const ReserveCar = () => ( +const ReserveCar = ({id, username, name}) => (
@@ -19,10 +20,16 @@ const ReserveCar = () => ( the Vehicle. We have services all over the globe which some include test-riding facilites. To book the car select both City and Date, please use the selector below.

- +
); +ReserveCar.propTypes = { + id: PropTypes.number.isRequired, + username: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, +}; + export default ReserveCar; diff --git a/src/components/ReserveCars/ReserveCarForm.js b/src/components/ReserveCars/ReserveCarForm.js index 384dc86..7bd75d6 100644 --- a/src/components/ReserveCars/ReserveCarForm.js +++ b/src/components/ReserveCars/ReserveCarForm.js @@ -1,30 +1,33 @@ +import PropTypes from 'prop-types'; import React from 'react'; import { format } from 'date-fns'; -// import { useDispatch } from 'react-redux'; +import { useDispatch } from 'react-redux'; import FormComponent from '../Form/FormComponent'; import { ReserveCarSchema, reserveCarInitialValues } from '../../models/reserveCar.model'; import { DateField, SelectField, TextInputField } from '../Form/FormField'; import FormSubmitButton from '../Button/FormSubmitButton'; -// import { reserveCar } from '../../redux/thunk'; +import { postReserveCar } from '../../redux/thunk'; -const ReserveCarFrom = () => { -// const dispatch = useDispatch(); -// const { carId } = useParams(); +const ReserveCarFrom = ({id, username, name}) => { + const dispatch = useDispatch(); const handleSubmit = (values) => { const formattedDate = format(values.selectedDate, 'EEE, dd MMM yyyy'); - // const reservationData = { - // userName: values.userName, - // selectedDate: formattedDate, - // selectedCity: values.selectedCity - // } - // dispatch(reserveCar({carId, data: reservationData})); + const reservationData = { + my_reservation: { + date: formattedDate, + city: values.selectedCity + } + } + console.log('id', id) + dispatch(postReserveCar({ carId: id, reservationData})); console.log('Reservation successful'); - console.log(values); + console.log(reservationData); console.log('Picked date is:', formattedDate); console.log('Picked City is: ', values.selectedCity); - console.log('User name:', values.userName); + console.log('User name:', username); + console.log('car name: ', name) }; const options = [ @@ -35,18 +38,15 @@ const ReserveCarFrom = () => { { value: 'City E', label: 'City E' }, ]; - const testUsername = 'Fill User Name Boo'; - // const testCarname = 'Fill Car Name Booo' - return ( - - + +
@@ -58,4 +58,10 @@ const ReserveCarFrom = () => { ); }; +ReserveCarFrom.propTypes = { + id: PropTypes.number.isRequired, + username: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, +}; + export default ReserveCarFrom; diff --git a/src/pages/LandingPage/ReserveCars/ReserveCars.js b/src/pages/LandingPage/ReserveCars/ReserveCars.js index c980859..f39cce5 100644 --- a/src/pages/LandingPage/ReserveCars/ReserveCars.js +++ b/src/pages/LandingPage/ReserveCars/ReserveCars.js @@ -1,11 +1,23 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import ReserveCar from '../../../components/ReserveCars/ReserveCar'; +import { useLocation } from 'react-router-dom'; -const ReserveCars = () => ( -
-

Reserve car

- -
-); +const ReserveCars = () => { + const location = useLocation(); + const { id,username, name } = location.state || {}; + useEffect(() => { + console.log('Reached ReserveCars component'); + console.log('ID:', id); + console.log('Username:', username); + console.log('Name:', name); + }, [id, username, name]); + + return ( +
+

Reserve car

+ +
+ ) +}; export default ReserveCars; diff --git a/src/pages/LoadingText.js b/src/pages/LoadingText.js new file mode 100644 index 0000000..b45d896 --- /dev/null +++ b/src/pages/LoadingText.js @@ -0,0 +1,7 @@ +import React from 'react'; + +const LoadingText = () => ( +

Loading the app....

+); + +export default LoadingText; diff --git a/src/pages/UserDashboard/DashboardHome.js b/src/pages/UserDashboard/DashboardHome.js index e781ef9..e791b98 100644 --- a/src/pages/UserDashboard/DashboardHome.js +++ b/src/pages/UserDashboard/DashboardHome.js @@ -3,6 +3,7 @@ import React, { useState } from 'react'; import styled from '@emotion/styled'; import DisplayCartCard from '../../components/Card/DisplayCartCard'; import { FaArrowLeft, FaArrowRight } from 'react-icons/fa'; +import { useSelector } from 'react-redux'; const DummyCards = [ { @@ -33,6 +34,7 @@ const DummyCards = [ const DashboardHome = () => { const [currentIndex, setCurrentIndex] = useState(0); + const cars = useSelector((state) => state.cars.cars) const handleNext = () => { setCurrentIndex((prevIndex) => (prevIndex + 3) % DummyCards.length); @@ -53,12 +55,14 @@ const DashboardHome = () => { - {DummyCards.slice(currentIndex, currentIndex + 3).map((data, index) => ( + {cars.slice(currentIndex, currentIndex + 3).map((data, index) => ( ))} diff --git a/src/pages/UserDashboard/ItemDetail/ItemDetail.js b/src/pages/UserDashboard/ItemDetail/ItemDetail.js index f2baac7..232c8c5 100644 --- a/src/pages/UserDashboard/ItemDetail/ItemDetail.js +++ b/src/pages/UserDashboard/ItemDetail/ItemDetail.js @@ -1,15 +1,38 @@ +import PropTypes from 'prop-types'; import React from 'react'; import DisplayItemCard from '../../../components/Card/DisplayItemCard'; - +import { useParams } from 'react-router-dom'; +import img from '../../../components/asset/bike.jpg' +import { useSelector } from 'react-redux'; const ItemDetail = () => { + const { id } = useParams(); + console.log('we are currently in the car details page of id: ', id); + const cars = useSelector((state) => state.cars.cars); + const numericId = parseInt(id, 10); + const car = cars.find((car) => car.id === numericId); + console.log('car is:', car); + const {name, description, pricePerHr, seating_capacity} = car; + return( ) } +ItemDetail.propTypes = { + id: PropTypes.number.isRequired, + name: PropTypes.string.isRequired, + description: PropTypes.string.isRequired, + pricePerHr: PropTypes.number.isRequired, + seating_capacity: PropTypes.number.isRequired, + imgSrc: PropTypes.string.isRequired +}; + export default ItemDetail; diff --git a/src/redux/cars/carsSlice.js b/src/redux/cars/carsSlice.js index 566fb2e..544bcff 100644 --- a/src/redux/cars/carsSlice.js +++ b/src/redux/cars/carsSlice.js @@ -8,15 +8,10 @@ const initialState = { }; -const carSlice = createSlice({ +const carsSlice = createSlice({ name: 'cars', initialState, - reducers: { - markCarDelete: (state, action) => { - const newState = state.cars.map((car) => (car.carId === action.payload ? ({...car, removed: true}) : car)); - state.cars = newState; - } - }, + reducers: {}, extraReducers: (builder) => { builder .addCase(fetchCars.pending, (state) => { @@ -24,6 +19,7 @@ const carSlice = createSlice({ state.error = null; }) .addCase(fetchCars.fulfilled, (state, action) => { + console.log('fetching cars: '); state.status = 'succeeded'; const fetchedData = []; action.payload.forEach((car) => { @@ -52,5 +48,5 @@ const carSlice = createSlice({ }, }); - export const {markCarDelete} = carSlice.actions; - export default carSlice.reducer; \ No newline at end of file + export const {markCarDelete} = carsSlice.actions; + export default carsSlice.reducer; \ No newline at end of file diff --git a/src/redux/reservations/reservationSlice.js b/src/redux/reservations/reservationSlice.js index b476aa8..3520484 100644 --- a/src/redux/reservations/reservationSlice.js +++ b/src/redux/reservations/reservationSlice.js @@ -32,7 +32,7 @@ const reservationSlice = createSlice({ }) .addCase(fetchCarReservations.fulfilled, (state, action) => { state.status = 'succeeded'; - state.reservations = action.payload.data; + state.reservations = action.payload; console.log('the reservations: ') console.log(state.reservations); }) diff --git a/src/redux/store.js b/src/redux/store.js index 1fa3e5f..092fc6f 100644 --- a/src/redux/store.js +++ b/src/redux/store.js @@ -2,10 +2,12 @@ import { configureStore } from '@reduxjs/toolkit'; import logger from 'redux-logger'; import authenticationReducer from './authentication/authenticationSlice'; import reservationReducer from './reservations/reservationSlice'; +import carsReducer from './cars/carsSlice' const store = configureStore({ reducer: { - authencation: authenticationReducer, + authentication: authenticationReducer, + cars: carsReducer, reservation: reservationReducer, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger), diff --git a/src/redux/thunk.js b/src/redux/thunk.js index efd2d39..a2e7ff2 100644 --- a/src/redux/thunk.js +++ b/src/redux/thunk.js @@ -71,16 +71,17 @@ export const registerUser = createAsyncThunk('auth/register', async (user, thunk export const logoutUser = createAsyncThunk('auth/logout', async (_, thunkAPI) => { try { - const token = getAuthenticationToken(); - const authToken = token ? token.replace('Bearer ', '') : ''; - console.log('authtoken:',authToken); + // const token = getAuthenticationToken(); + // const authToken = token ? token.replace('Bearer ', '') : ''; + // console.log('authtoken:',authToken); const response = await axios.delete(`${baseURL}/users/sign_out`, { - headers: { Authorization: authToken }, + headers: { Authorization: localStorage.getItem('token') }, }); - const { status, message } = await handleResponse(response); removeAuthenticationToken(); + const { status, message } = await handleResponse(response); + // console.log('logout async method'); // if (status === 'succeeded') { // } @@ -95,6 +96,7 @@ export const postReserveCar = createAsyncThunk( 'reservations/newReserve', async ({ carId, reservationData }, thunkAPI) => { try { + console.log('the id from the book car method:', carId) const token = localStorage.getItem('token'); const response = await axios.post(`${baseURL}/car/${carId}/new_reserve`, reservationData, { headers: { @@ -123,6 +125,7 @@ export const fetchCarReservations = createAsyncThunk( Authorization: token, }, }); + console.log(`reservations from the fetchCarReservations: `, response.data) return response.data; } catch (error) { return thunkAPI.rejectWithValue(error); @@ -130,6 +133,28 @@ export const fetchCarReservations = createAsyncThunk( }, ); +export const postNewCar = createAsyncThunk( + 'cars/newCar', + async (carData , thunkAPI) => { + try { + const token = localStorage.getItem('token'); + const response = await axios.post(`${baseURL}/cars`, carData, { + headers: { + Authorization: token, + }, + }); + const { data } = await handleResponse(response); + + if (response.status === 200 || response.status === 201) { + return { data, status: 'succeeded' }; + } + return { status: 'failed', error: 'Request failed', message: data.message }; + } catch (error) { + return thunkAPI.rejectWithValue(error); + } + }, +); + export const fetchCars = createAsyncThunk( 'cars/fetchCars', async(_, thunkAPI) => { @@ -140,6 +165,8 @@ export const fetchCars = createAsyncThunk( Authorization: token, }, }); + console.log(`this method is from the fetchCars`); + console.log(response.data); return response.data; } catch (error) { return thunkAPI.rejectWithValue(error); diff --git a/src/routes/routes.js b/src/routes/routes.js index 0a33f70..7a4c5a0 100644 --- a/src/routes/routes.js +++ b/src/routes/routes.js @@ -29,11 +29,16 @@ import { import UsersDashboardLayout from '../layout/UsersDashboard/UsersDashboardLayout'; import DashboardHome from '../pages/UserDashboard/DashboardHome'; import AddNewCar from '../pages/LandingPage/AddNewCar/AddNewCar'; -import DeleteCar from '../pages/LandingPage/DeleteCar/DeleteCar'; import Contact from '../pages/LandingPage/Contact/Contact'; import DeleteList from '../components/DeleteCars/DeleteList'; +import { useSelector } from 'react-redux'; +import LoadingText from '../pages/LoadingText'; export default function Router() { + const authenticationStatus = useSelector((state) => state.authentication.status); + const isAuthenticated = authenticationStatus === 'succeeded'; + const isLoading = authenticationStatus === 'loading'; + return useRoutes([ { path: HOME, @@ -43,7 +48,12 @@ export default function Router() { ], }, - { + isLoading && { + path: USERS_DASHBOARD, + element: + }, + + isAuthenticated && { path: USERS_DASHBOARD, element: , children: [ @@ -52,7 +62,7 @@ export default function Router() { { path: MY_RESERVATIONS, element: }, { path: RESERVE_CARS, element: }, { path: ADD_NEW_CAR, element: }, - { path: ITEM_DETAIL, element: }, + { path: `${ITEM_DETAIL}/:id`, element: }, { path: DELETE_CAR, element: }, { path: CONTACT, element: }, From b6694621cdf7ff47603fa35e50b23006d6c7801e Mon Sep 17 00:00:00 2001 From: Tanmayi Manku Date: Sun, 10 Dec 2023 13:07:53 +0530 Subject: [PATCH 5/7] Update README --- README.md | 310 +++++++++++++++++++++++--- src/assets/CaBooky-logo-1-preview.png | Bin 0 -> 17228 bytes 2 files changed, 274 insertions(+), 36 deletions(-) create mode 100644 src/assets/CaBooky-logo-1-preview.png diff --git a/README.md b/README.md index 58beeac..3208e2c 100644 --- a/README.md +++ b/README.md @@ -1,70 +1,308 @@ -# Getting Started with Create React App +
+ CaBooky-logo +

CaBooky

+
+ + + + + +# 📗 Table of Contents +- [📖 About the Project](#about-project) + - [🛠 Built With](#built-with) + - [Tech Stack](#tech-stack) + - [Key Features](#key-features) + - [📜 Kanban Board](#kanban-board) + - [🎥 Rails Backend](#rails-backend) + - [🎞️ CaBooky Preview](#cabooky-preview) + - [🚀 Live Demo](#live-demo) +- [💻 Getting Started with Create React App](#getting-started-with-create-react-app) +- [💻 Getting Started](#getting-started) + - [Setup](#setup) + - [Prerequisites](#prerequisites) + - [Usage](#usage) + - [Run Tests](#run-tests) + - [Deployment](#deployment) +- [👥 Authors](#authors) +- [🔭 Future Features](#future-features) +- [🤝 Contributing](#contributing) +- [⭐️ Show your support](#support) +- [🙏 Acknowledgements](#acknowledgements) +- [📝 License](#license) + + + +# 📖 CaBooky + +**CaBooky** is Car booking service. This application allows the users to subscribe(sign up) to the app so that the user can add new cars and be able to reserve the cars basing on the date and city. This app uses the external RESTful api endpoints for data accessing. + +## 🛠 Built With + +### Tech Stack + +
+ Client + +
+ + + +### Key Features + +- **A user can add new items (cars)** + +- **Current user can reserve the item basing the date and city.** + +- **JavaScript and Stylelint linters are installed for code implementation improvement** + +- **Uses React Redux middleware to work with async functions for API interactions"** + +- **The application has CRUD operations.** + +

(back to top)

+ + + +## Kanban Board + + +We are a Team of Four, so we used the custom Kanban board to divide tasks and keep track of progress. + +- [Kanban Board Initial version]() +- [Kanban Board Final Version]() + +

(back to top)

+ + + +## Supporting Backend Project + + +- [Vehicle-Booking-App-Backend](https://github.com/tan12082001/hello-rails-back-end) + +

(back to top)

+ + + +## CaBooky Preview + + +

(back to top)

+ + + +## 🚀 Live Demo + + + +- [CaBooky Application ]() + +

(back to top)

+ + + +## Getting Started with Create React App This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). -## Available Scripts +
+ More Information + + ### Available Scripts + + In the project directory, you can run: + + ### `npm start` + + Runs the app in the development mode.\ + Open [http://localhost:3000](http://localhost:3000) to view it in your browser. + + The page will reload when you make changes.\ + You may also see any lint errors in the console. + + ### `npm test` + + Launches the test runner in the interactive watch mode.\ + See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. + + ### `npm run build` + + Builds the app for production to the `build` folder.\ + It correctly bundles React in production mode and optimizes the build for the best performance. + + The build is minified and the filenames include the hashes.\ + Your app is ready to be deployed! + + See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. -In the project directory, you can run: + ### `npm run eject` -### `npm start` + **Note: this is a one-way operation. Once you `eject`, you can't go back!** -Runs the app in the development mode.\ -Open [http://localhost:3000](http://localhost:3000) to view it in your browser. + If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. -The page will reload when you make changes.\ -You may also see any lint errors in the console. + Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. -### `npm test` + You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. -Launches the test runner in the interactive watch mode.\ -See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. + ## Learn More -### `npm run build` + You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). -Builds the app for production to the `build` folder.\ -It correctly bundles React in production mode and optimizes the build for the best performance. + To learn React, check out the [React documentation](https://reactjs.org/). -The build is minified and the filenames include the hashes.\ -Your app is ready to be deployed! + ### Code Splitting -See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. + This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) -### `npm run eject` + ### Analyzing the Bundle Size -**Note: this is a one-way operation. Once you `eject`, you can't go back!** + This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) -If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. + ### Making a Progressive Web App -Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. + This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) -You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. + ### Advanced Configuration -## Learn More + This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) -You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). + ### Deployment -To learn React, check out the [React documentation](https://reactjs.org/). + This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) -### Code Splitting + ### `npm run build` fails to minify -This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) + This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) -### Analyzing the Bundle Size +
-This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) -### Making a Progressive Web App +

(back to top)

-This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) + -### Advanced Configuration +## 💻 Getting Started -This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) +To get a local copy up and running, follow these steps. + +### Prerequisites + +In order to run this project you need: + +- [Node.js and npm](https://nodejs.org/) + +### Setup + +Clone this repository to your desired folder: + +```sh + cd my-folder + + git clone git@github.com:tan12082001/Vehicle-Booking-App-Frontend.git + + npm install +``` + +### Usage + +To run the project, if you are using a Code Editor make use of a live server. +If you are working with webpack you can run the local host with the following command. + +```sh + npm start +``` + +### Run Tests + +To run the test suits: + +```sh + npm test +``` ### Deployment -This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) +You can deploy this project using: + +```sh + gh-pages +``` +This Project is deployed using [Render](https://render.com/) + +

(back to top)

+ + + +## 👥 Authors + +👤 **Deborah Fashoro** + +- GitHub: [@githubhandle](https://github.com/Simpleshaikh1) +- LinkedIn: [LinkedIn](https://www.linkedin.com/in/toyyib-abayomi/) + +👤 **Nweneary Uzochukwu Winnie** + +- GitHub: [@githubhandle](https://github.com/wineshuga) +- LinkedIn: [LinkedIn](https://www.linkedin.com/in/wineshuga/) + +👤 **Suleiman Gacheru** + +- GitHub: [@hetrox8](https://github.com/hetrox8) +- Twitter: [@suleimangacheru](https://twitter.com/SuleimanGacheru) + +👤 **Tanmayi Manku** + +- GitHub: [@tan12082001](https://github.com/tan12082001) +- LinkedIn: [LinkedIn](https://www.linkedin.com/in/tanmayi-manku-99195720a/) + +

(back to top)

+ + + +## 🔭 Future Features + +- [ ] **Apply admin authorization, and restrict the Create new car, delete a car actions unless admin.** + +- [ ] **Add the Delete Reservation Feature.** + +

(back to top)

+ + + +## 🤝 Contributing + +Contributions, issues, and feature requests are welcome! +Feel free to check the GitHub page. + +

(back to top)

+ + + +## ⭐️ Show your support + +If you like this project give it a star. +

(back to top)

+ + + +## 🙏 Acknowledgments + +We would like to thank Microverse for providing the required lessons and tutorials for successfully completing the project. + +We would like to thank [Murat Korkmaz](https://www.behance.net/muratk) for the original Wireframe design of the application [Vespa-Responsive-design](https://www.behance.net/gallery/26425031/Vespa-Responsive-Redesign). + +

(back to top)

+ + + +## 📝 License -### `npm run build` fails to minify +This project is [MIT](./LICENSE) licensed. -This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) +

(back to top)

diff --git a/src/assets/CaBooky-logo-1-preview.png b/src/assets/CaBooky-logo-1-preview.png new file mode 100644 index 0000000000000000000000000000000000000000..d0788e6fa5e3e85ba491dac19200f13c47068411 GIT binary patch literal 17228 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�L5HX-^ zdzv7w-=U=4$d#^Cowj^W`Q?!FLmlS%gL_I<_|VO3u;{JE4IfC&DsqZVE<<{`&ez#L zBN&OXJ!oOmZyn(QaWZWnU5Q?`Hd3 z{`$L(ctHVoa|ZAFo7~DkNLFtz9WK6TUtVgR*TtD3t zz+4Rk9;kx>P8P0mqYkC;UYdBt;gENF0e9GK z*Vq^D6i?RtL(EKjBv6=!IB%>5Kd=RXTJ?4R@_&3Os1Vi60-C@?3(xa2^BjA_a6Xe; zzcla_IP4}=P$?>-3(QL{Ubq#Yu9}M=F{jR;~tn5Ti0VL6p6)2p& z=evArN;RPmZ(qM!c1fv1X6LdNdUpEH+H**{Cea2 z)Ai76PQ(K~c3m5h&OQwa`U+KcR~itjbPOBN2r^DW8IBgG2i)&Bw?_Ls-#QGlA6uqb zmA`~`K3Vh(_Zu*&aG|0=Eaq&u^;{~QYiD@Tx`{LYf@vk9W1NI|e^`}{naFCSAG7v1 z_$2+etrIEp^0RB~1_Sq+Z%FUU`>R5KzA_VC6y3u|KgZ`9L{GVO zelb59>fllSrp~1Fl(i86zNEg&7G{<28m@$d4S5vdJ2TcL2_kD@?`PXSqPC> Date: Sun, 10 Dec 2023 13:22:47 +0530 Subject: [PATCH 6/7] Add kanban board image --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3208e2c..47b4806 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ We are a Team of Four, so we used the custom Kanban board to divide tasks and keep track of progress. -- [Kanban Board Initial version]() +- [Kanban Board Initial version](https://github.com/tan12082001/Vehical-Appointment-App-Backend/assets/81354942/f57bf009-046a-4c8a-817d-5b3cb163421c) - [Kanban Board Final Version]()

(back to top)

From 215509102f38daf648bf4a5313f24082e9071645 Mon Sep 17 00:00:00 2001 From: Tanmayi Manku Date: Sun, 10 Dec 2023 21:53:33 +0530 Subject: [PATCH 7/7] Update changes after check --- .eslintrc.json | 66 +++++------ src/App.js | 4 +- src/components/Card/DisplayCartCard.js | 7 +- src/components/Card/DisplayItemCard.js | 75 ++++++------ src/components/DeleteCars/DeleteList.js | 58 +++++----- src/components/DeleteCars/EachCarDelete.js | 57 +++++----- src/components/Form/FormComponent2.js | 8 +- src/components/Form/FormField.js | 36 +++--- src/components/Form/HideableTextFormField.js | 6 - src/components/Img/Img.js | 4 +- src/components/Link/Link.js | 1 - .../MyReservations/MyReservationsList.js | 49 ++------ src/components/ReserveCars/ReserveCar.js | 2 +- src/components/ReserveCars/ReserveCarForm.js | 29 ++--- src/layout/LandingPage/LandingPageLayout.js | 24 ++-- src/layout/LandingPage/header/Header.js | 5 - .../UsersDashboard/UsersDashboardLayout.js | 16 +-- src/layout/UsersDashboard/sideNav/Nav.js | 21 ++-- .../UsersDashboard/sideNav/navConfig.js | 2 +- src/models/car.model.js | 8 +- src/pages/Auth/SignIn/SignIn.js | 8 +- src/pages/Auth/SignIn/SigninForm.js | 7 +- src/pages/Auth/SignUp/SignUp.js | 8 +- src/pages/LandingPage/DeleteCar/DeleteCar.js | 10 +- src/pages/LandingPage/Home/Home.js | 7 +- .../MyReservation/MyReservation.js | 8 +- .../LandingPage/ReserveCars/ReserveCars.js | 18 +-- .../UserDashboard/AddNewCar/AddNewCar.js | 19 ++-- .../UserDashboard/AddNewCar/AddNewCarForm.js | 36 +++--- src/pages/UserDashboard/DashboardHome.js | 18 +-- .../UserDashboard/ItemDetail/ItemDetail.js | 38 ++----- .../authentication/authenticationSlice.js | 8 +- src/redux/cars/carsSlice.js | 107 ++++++++++-------- src/redux/reservations/reservationSlice.js | 13 ++- src/redux/store.js | 2 +- src/redux/thunk.js | 96 +++++++--------- src/routes/routeConstants.js | 2 +- src/routes/routes.js | 10 +- 38 files changed, 411 insertions(+), 482 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 51f38ce..f782284 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,35 +1,35 @@ { - "env": { - "browser": true, - "es6": true, - "jest": true + "env": { + "browser": true, + "es6": true, + "jest": true + }, + "parser": "@babel/eslint-parser", + "parserOptions": { + "ecmaFeatures": { + "jsx": true }, - "parser": "@babel/eslint-parser", - "parserOptions": { - "ecmaFeatures": { - "jsx": true - }, - "ecmaVersion": 2018, - "sourceType": "module" - }, - "extends": ["plugin:react/recommended", "plugin:react-hooks/recommended"], - "plugins": ["react"], - "rules": { - "react/jsx-filename-extension": ["warn", { "extensions": [".js", ".jsx"] }], - "react/react-in-jsx-scope": "off", - "import/no-unresolved": "off", - "no-shadow": "off" - }, - "overrides": [ - { - // feel free to replace with your preferred file pattern - eg. 'src/**/*Slice.js' or 'redux/**/*Slice.js' - "files": ["src/**/*Slice.js"], - // avoid state param assignment - "rules": { "no-param-reassign": ["error", { "props": false }] } - } - ], - "ignorePatterns": [ - "dist/", - "build/" - ] - } \ No newline at end of file + "ecmaVersion": 2018, + "sourceType": "module" + }, + "extends": ["airbnb", "plugin:react/recommended", "plugin:react-hooks/recommended"], + "plugins": ["react"], + "rules": { + "react/jsx-filename-extension": ["warn", { "extensions": [".js", ".jsx"] }], + "react/react-in-jsx-scope": "off", + "import/no-unresolved": "off", + "no-shadow": "off" + }, + "overrides": [ + { + // feel free to replace with your preferred file pattern - eg. 'src/**/*Slice.js' or 'redux/**/*Slice.js' + "files": ["src/**/*Slice.js"], + // avoid state param assignment + "rules": { "no-param-reassign": ["error", { "props": false }] } + } + ], + "ignorePatterns": [ + "dist/", + "build/" + ] +} \ No newline at end of file diff --git a/src/App.js b/src/App.js index 0ff45ea..5e15ab5 100644 --- a/src/App.js +++ b/src/App.js @@ -1,7 +1,7 @@ import './styles/App.css'; -import React, {useEffect} from 'react'; -import Router from './routes/routes'; +import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; +import Router from './routes/routes'; import { fetchCarReservations, fetchCars } from './redux/thunk'; function App() { diff --git a/src/components/Card/DisplayCartCard.js b/src/components/Card/DisplayCartCard.js index 1fadf12..12e489c 100644 --- a/src/components/Card/DisplayCartCard.js +++ b/src/components/Card/DisplayCartCard.js @@ -4,7 +4,9 @@ import styled from '@emotion/styled'; import { FaFacebook, FaTwitter, FaInstagram } from 'react-icons/fa'; import { Link } from 'react-router-dom'; -const DisplayCartCard = ({ id, imgSrc, name, shortNote }) => ( +const DisplayCartCard = ({ + id, imgSrc, name, shortNote, +}) => ( {name} @@ -26,7 +28,8 @@ const DisplayCartCard = ({ id, imgSrc, name, shortNote }) => ( ); DisplayCartCard.propTypes = { - imageName: PropTypes.string.isRequired, + id: PropTypes.number.isRequired, + imgSrc: PropTypes.string.isRequired, name: PropTypes.string.isRequired, shortNote: PropTypes.string.isRequired, }; diff --git a/src/components/Card/DisplayItemCard.js b/src/components/Card/DisplayItemCard.js index 0ab3200..8bb085b 100644 --- a/src/components/Card/DisplayItemCard.js +++ b/src/components/Card/DisplayItemCard.js @@ -2,86 +2,89 @@ import React, { useState } from 'react'; import PropTypes from 'prop-types'; import styled from '@emotion/styled'; import { FaCog, FaArrowRight, FaSyncAlt } from 'react-icons/fa'; -import colorWheel from '../../components/asset/small_color_wheel.png'; import { useSelector } from 'react-redux'; import { useNavigate } from 'react-router-dom'; +import colorWheel from '../asset/small_color_wheel.png'; import { RESERVE_CARS, USERS_DASHBOARD } from '../../routes/routeConstants'; -const DisplayItemCard = ({ id, name, description, pricePerHr, seating_capacity, imgSrc }) => { +const DisplayItemCard = ({ + id, name, description, pricePerHr, seatingCapacity, imgSrc, +}) => { const username = useSelector((state) => state.authentication.authenticatedUser.username); const navigate = useNavigate(); const [rotation, setRotation] = useState(0); const handleReserveClick = () => { navigate(`${USERS_DASHBOARD}/${RESERVE_CARS}`, { - state: { id, username, name } + state: { id, username, name }, }); - } + }; const handleRotate = () => { setRotation((prevRotation) => (prevRotation + 90) % 360); }; return ( - - - - - - Rotate vehicle - - - - + + + + + + Rotate vehicle + + + + {name} - {description} + {description} - + Rent Price per Hour {pricePerHr} - - + + Seating Capacity - {seating_capacity} - - + {seatingCapacity} + + Currently available for booking? Yes - - + + Minimum Rental Duration 4 hrs - +
- 5.9% APR Representative + 5.9% APR Representative DISCOVER MORE MODEL - Color Wheel + Color Wheel - - + + - - Reserve - + + Reserve + - + -
+
-)}; + ); +}; DisplayItemCard.propTypes = { id: PropTypes.number.isRequired, name: PropTypes.string.isRequired, description: PropTypes.string.isRequired, pricePerHr: PropTypes.number.isRequired, - seating_capacity: PropTypes.number.isRequired, - imgSrc: PropTypes.string.isRequired + seatingCapacity: PropTypes.number.isRequired, + imgSrc: PropTypes.string.isRequired, }; const Container = styled.div` diff --git a/src/components/DeleteCars/DeleteList.js b/src/components/DeleteCars/DeleteList.js index c252642..632a396 100644 --- a/src/components/DeleteCars/DeleteList.js +++ b/src/components/DeleteCars/DeleteList.js @@ -1,45 +1,45 @@ import React from 'react'; -import { useSelector } from "react-redux"; +import { useSelector } from 'react-redux'; import EachCarDelete from './EachCarDelete'; const DeleteList = () => { - const cars = useSelector((state) => state.cars.cars) -// const mockData = [ -// { -// "id": 3, -// "name": "Car1", -// "description": "Description for Car1", -// "removed": false -// }, -// { -// "id": 4, -// "name": "Car1111", -// "description": "Description for Car1", -// "removed": false -// } -// ]; -// const cars = mockData; + const cars = useSelector((state) => state.cars.cars); + // const mockData = [ + // { + // "id": 3, + // "name": "Car1", + // "description": "Description for Car1", + // "removed": false + // }, + // { + // "id": 4, + // "name": "Car1111", + // "description": "Description for Car1", + // "removed": false + // } + // ]; + // const cars = mockData; return ( <>

Cars List

- - - - - - - - {cars.map((car) => ( - - ))} - + + + + + + + + {cars.map((car) => ( + + ))} +
Car TitleStatus
Car TitleStatus
); }; -export default DeleteList; \ No newline at end of file +export default DeleteList; diff --git a/src/components/DeleteCars/EachCarDelete.js b/src/components/DeleteCars/EachCarDelete.js index 6c81a40..b249524 100644 --- a/src/components/DeleteCars/EachCarDelete.js +++ b/src/components/DeleteCars/EachCarDelete.js @@ -1,38 +1,37 @@ import PropTypes from 'prop-types'; -import { useDispatch, useSelector } from "react-redux"; -import { deleteCar } from "../../redux/thunk"; -import { markCarDelete } from "../../redux/cars/carsSlice"; +import { useDispatch } from 'react-redux'; +import { deleteCar } from '../../redux/thunk'; +import { removeMarkStatus } from '../../redux/cars/carsSlice'; -const EachCarDelete = ({car}) => { - const { - name, - id, - removed - } = car; - const dispatch = useDispatch(); - const handleDelete = () => { - dispatch(deleteCar(id)); - if(!removed) { - dispatch(markCarDelete(id)) - } +const EachCarDelete = ({ car }) => { + const { + name, + id, + removed, + } = car; + const dispatch = useDispatch(); + const handleDelete = () => { + if (removed) { + return; } - - - return ( - - {name} - - - ) -} + dispatch(deleteCar(id)); + dispatch(removeMarkStatus(id)); + }; + return ( + + {name} + + + ); +}; EachCarDelete.propTypes = { - car: PropTypes.shape({ - name: PropTypes.string.isRequired, - id: PropTypes.number.isRequired, - removed: PropTypes.bool.isRequired, - }).isRequired, + car: PropTypes.shape({ + name: PropTypes.string.isRequired, + id: PropTypes.number.isRequired, + removed: PropTypes.bool.isRequired, + }).isRequired, }; export default EachCarDelete; diff --git a/src/components/Form/FormComponent2.js b/src/components/Form/FormComponent2.js index 6d1766c..69eb446 100644 --- a/src/components/Form/FormComponent2.js +++ b/src/components/Form/FormComponent2.js @@ -25,17 +25,17 @@ FormComponent2.propTypes = { name: PropTypes.string.isRequired, description: PropTypes.string.isRequired, pricePerHr: PropTypes.string.isRequired, - sitting_capacity: PropTypes.number.isRequired, + seating_capacity: PropTypes.number.isRequired, rental_duration: PropTypes.number.isRequired, - image: PropTypes.string.isRequired, + // image: PropTypes.string.isRequired, }).isRequired, schema: PropTypes.shape({ name: PropTypes.string.isRequired, description: PropTypes.string.isRequired, pricePerHr: PropTypes.string.isRequired, - sitting_capacity: PropTypes.number.isRequired, + seating_capacity: PropTypes.number.isRequired, rental_duration: PropTypes.number.isRequired, - image: PropTypes.string.isRequired, + // image: PropTypes.string.isRequired, }).isRequired, onSubmit: PropTypes.func.isRequired, children: PropTypes.node.isRequired, diff --git a/src/components/Form/FormField.js b/src/components/Form/FormField.js index 1fba652..0a36224 100644 --- a/src/components/Form/FormField.js +++ b/src/components/Form/FormField.js @@ -19,11 +19,16 @@ export const DateField = ({ handleChange(date); }; - console.log('value fromt eh field', field.value); return ( {label} - helpers.setTouched(true)} /> + helpers.setTouched(true)} + /> {meta.touched && meta.error ? ( {meta.error} ) : null} @@ -39,10 +44,9 @@ DateField.propTypes = { }; export const SelectField = ({ - label, lpiSrc, rpiSrc, className, name, id, options, ...props + label, className, name, id, options, ...props }) => { const [field, meta] = useField(name); - console.log('selected city', field.value); return ( @@ -56,8 +60,6 @@ export const SelectField = ({ ))} - {lpiSrc ? : null} - {lpiSrc ? : null} {meta.touched && meta.error ? ( {meta.error} @@ -68,8 +70,6 @@ export const SelectField = ({ SelectField.propTypes = { label: PropTypes.string.isRequired, - lpiSrc: PropTypes.string.isRequired, - rpiSrc: PropTypes.string.isRequired, className: PropTypes.string.isRequired, name: PropTypes.string.isRequired, id: PropTypes.string.isRequired, @@ -77,12 +77,12 @@ SelectField.propTypes = { PropTypes.shape({ value: PropTypes.string.isRequired, label: PropTypes.string.isRequired, - }) + }), ).isRequired, }; export const TextInputField = ({ - label, lpiSrc, rpiSrc, className, name, placeholder, id, ...props + label, className, name, placeholder, id, ...props }) => { const [field, meta] = useField(name); @@ -93,8 +93,6 @@ export const TextInputField = ({ - {lpiSrc ? : null} - {lpiSrc ? : null} {meta.touched && meta.error ? ( {meta.error} @@ -105,8 +103,6 @@ export const TextInputField = ({ TextInputField.propTypes = { label: PropTypes.string.isRequired, - lpiSrc: PropTypes.string.isRequired, - rpiSrc: PropTypes.string.isRequired, className: PropTypes.string.isRequired, name: PropTypes.string.isRequired, placeholder: PropTypes.string.isRequired, @@ -115,8 +111,6 @@ TextInputField.propTypes = { export const TextAreaInputField = ({ label, - lpiSrc, - rpiSrc, className, name, id, @@ -134,8 +128,6 @@ export const TextAreaInputField = ({ className={className || ''} rows={10} /> - {lpiSrc ? : null} - {rpiSrc ? : null} {meta.touched && meta.error ? ( {meta.error} @@ -146,14 +138,14 @@ export const TextAreaInputField = ({ TextAreaInputField.propTypes = { label: PropTypes.string.isRequired, - lpiSrc: PropTypes.string.isRequired, - rpiSrc: PropTypes.string.isRequired, className: PropTypes.string.isRequired, name: PropTypes.string.isRequired, id: PropTypes.string.isRequired, }; -export const FileInputField = ({ id, label, name, className, ...props }) => { +export const FileInputField = ({ + id, label, name, className, ...props +}) => { const [field, meta, helpers] = useField(name); const handleChange = (event) => { @@ -176,7 +168,7 @@ FileInputField.propTypes = { label: PropTypes.string.isRequired, name: PropTypes.string.isRequired, className: PropTypes.string.isRequired, - id: PropTypes.string.isRequired + id: PropTypes.string.isRequired, }; const DateFieldWrapper = styled.div` diff --git a/src/components/Form/HideableTextFormField.js b/src/components/Form/HideableTextFormField.js index 424627e..e9baf7c 100644 --- a/src/components/Form/HideableTextFormField.js +++ b/src/components/Form/HideableTextFormField.js @@ -16,12 +16,9 @@ import { const HideableTextFormField = ({ label, - lpiSrc, - rpiSrc, className, name, id, - // apiKey, ...props }) => { const [field, meta] = useField(name); @@ -60,12 +57,9 @@ const HideableTextFormField = ({ HideableTextFormField.propTypes = { label: PropTypes.string.isRequired, - lpiSrc: PropTypes.string.isRequired, - rpiSrc: PropTypes.string.isRequired, className: PropTypes.string.isRequired, name: PropTypes.string.isRequired, id: PropTypes.string.isRequired, - // apiKey: PropTypes.string, }; const VisibiltyToggleIconsArea = styled.div` diff --git a/src/components/Img/Img.js b/src/components/Img/Img.js index 50fdabf..c27ac09 100644 --- a/src/components/Img/Img.js +++ b/src/components/Img/Img.js @@ -2,9 +2,7 @@ import PropTypes from 'prop-types'; import styled from '@emotion/styled'; import React from 'react'; -const Img = ({ src, alt, className }) => { -return ; -} +const Img = ({ src, alt, className }) => ; const Imgg = styled.img` width: 100%; diff --git a/src/components/Link/Link.js b/src/components/Link/Link.js index ca46a2c..decff9a 100644 --- a/src/components/Link/Link.js +++ b/src/components/Link/Link.js @@ -54,7 +54,6 @@ export const NavigationBoxLink = styled(RouterLink)` `; NavBoxItem.propTypes = { - icon: PropTypes.node.isRequired, path: PropTypes.string.isRequired, children: PropTypes.node.isRequired, }; diff --git a/src/components/MyReservations/MyReservationsList.js b/src/components/MyReservations/MyReservationsList.js index f36dc5d..740a9e9 100644 --- a/src/components/MyReservations/MyReservationsList.js +++ b/src/components/MyReservations/MyReservationsList.js @@ -1,56 +1,31 @@ -import React, { useEffect } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; -// import { fetchCarReservations, fetchCars } from '../../redux/thunk'; +import React from 'react'; +import { useSelector } from 'react-redux'; const MyReservationsList = () => { - const mockData = [ - { - id: 1, - car: { - id: 3, - name: "Car1" - }, - date: "2023-01-02", - city: "No Peace" - }, - { - id: 2, - car: { - id: 4, - name: "Car2" - }, - date: "2023-01-03", - city: "Tranquil Town" - }, - // Add more mock data as needed - ]; - // const dispatch = useDispatch(); const myReservations = useSelector((state) => state.reservation.reservations); - console.log(myReservations[1]); - console.log(myReservations[1].car.name); -// const myReservations = mockData; + const newReservationName = useSelector((state) => state.reservation.newReservationName); const status = useSelector((state) => state.reservation.status); const error = useSelector((state) => state.reservation.error); - // useEffect(() => { - // dispatch(fetchCarReservations()); - // dispatch(fetchCars()); - // }, [dispatch]); - if (status === 'loading') { return

Loading...

; } if (status === 'failed') { - return

Error: {error}

; + return ( +

+ Error: + {error} +

+ ); } return ( -
+

My Reservations

{myReservations && myReservations.map((reservation) => ( -
- {`Car: ${reservation.car && reservation.car.name ? reservation.car.name : 'No name'}`} +
+ {`Car: ${reservation.car && reservation.car.name ? reservation.car.name : newReservationName}`} {`Date: ${reservation.date}`} {`City: ${reservation.city}`}
diff --git a/src/components/ReserveCars/ReserveCar.js b/src/components/ReserveCars/ReserveCar.js index 2fdab1f..0269f5a 100644 --- a/src/components/ReserveCars/ReserveCar.js +++ b/src/components/ReserveCars/ReserveCar.js @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import ReserveCarFrom from './ReserveCarForm'; -const ReserveCar = ({id, username, name}) => ( +const ReserveCar = ({ id, username, name }) => (
diff --git a/src/components/ReserveCars/ReserveCarForm.js b/src/components/ReserveCars/ReserveCarForm.js index 7bd75d6..05ecce6 100644 --- a/src/components/ReserveCars/ReserveCarForm.js +++ b/src/components/ReserveCars/ReserveCarForm.js @@ -1,33 +1,34 @@ import PropTypes from 'prop-types'; import React from 'react'; import { format } from 'date-fns'; -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; +import { useNavigate } from 'react-router-dom'; import FormComponent from '../Form/FormComponent'; import { ReserveCarSchema, reserveCarInitialValues } from '../../models/reserveCar.model'; import { DateField, SelectField, TextInputField } from '../Form/FormField'; - import FormSubmitButton from '../Button/FormSubmitButton'; import { postReserveCar } from '../../redux/thunk'; +import { MY_RESERVATIONS, USERS_DASHBOARD } from '../../routes/routeConstants'; +import { getNewReservationName } from '../../redux/reservations/reservationSlice'; -const ReserveCarFrom = ({id, username, name}) => { +const ReserveCarFrom = ({ id, username, name }) => { const dispatch = useDispatch(); + const navigate = useNavigate(); + const status = useSelector((state) => state.reservation.status); const handleSubmit = (values) => { const formattedDate = format(values.selectedDate, 'EEE, dd MMM yyyy'); const reservationData = { my_reservation: { - date: formattedDate, - city: values.selectedCity - } + date: formattedDate, + city: values.selectedCity, + }, + }; + dispatch(postReserveCar({ carId: id, reservationData })); + if (status === 'succeeded') { + dispatch(getNewReservationName(name)); + navigate(`${USERS_DASHBOARD}/${MY_RESERVATIONS}`); } - console.log('id', id) - dispatch(postReserveCar({ carId: id, reservationData})); - console.log('Reservation successful'); - console.log(reservationData); - console.log('Picked date is:', formattedDate); - console.log('Picked City is: ', values.selectedCity); - console.log('User name:', username); - console.log('car name: ', name) }; const options = [ diff --git a/src/layout/LandingPage/LandingPageLayout.js b/src/layout/LandingPage/LandingPageLayout.js index d9c3599..6794488 100644 --- a/src/layout/LandingPage/LandingPageLayout.js +++ b/src/layout/LandingPage/LandingPageLayout.js @@ -1,20 +1,14 @@ import React from 'react'; import { Outlet } from 'react-router-dom'; +import Header from './header/Header'; -// import Footer from './footer/Footer'; -import Header from './header/Header'; - -const LandingPageLayout = () => { - // eslint-disable-next-line arrow-body-style - return ( - <> -
-
- -
- {/*