+
Sign up
+
Hello there! Register and start managing your application
+
Have an existing account ?
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/DeleteCar/DeleteCar.js b/src/pages/LandingPage/DeleteCar/DeleteCar.js
new file mode 100644
index 0000000..0aaad85
--- /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/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/pages/LandingPage/Home/Home.js b/src/pages/LandingPage/Home/Home.js
index c66aa39..7919121 100644
--- a/src/pages/LandingPage/Home/Home.js
+++ b/src/pages/LandingPage/Home/Home.js
@@ -1,21 +1,20 @@
import React from 'react';
import styled from '@emotion/styled';
-import Img from '../../../components/Img/Img';
import AuthNav from '../../../layout/LandingPage/nav/AuthNav';
-import bicycleImage from '../../../../src/components/asset/bicycle.jpg'
+import bicycleImage from '../../../components/asset/bicycle.jpg';
const Home = () => (
-
+
CarBooky
-)
+);
export default Home;
diff --git a/src/pages/LandingPage/MyReservation/MyReservation.js b/src/pages/LandingPage/MyReservation/MyReservation.js
index cdfd767..6392146 100644
--- a/src/pages/LandingPage/MyReservation/MyReservation.js
+++ b/src/pages/LandingPage/MyReservation/MyReservation.js
@@ -2,10 +2,10 @@ import React from 'react';
import MyReservationsList from '../../../components/MyReservations/MyReservationsList';
const MyReservations = () => (
-
-
My Current Reservations
-
-
+
+
My Current Reservations
+
+
);
export default MyReservations;
diff --git a/src/pages/LandingPage/ReserveCars/ReserveCars.js b/src/pages/LandingPage/ReserveCars/ReserveCars.js
index c980859..8737061 100644
--- a/src/pages/LandingPage/ReserveCars/ReserveCars.js
+++ b/src/pages/LandingPage/ReserveCars/ReserveCars.js
@@ -1,11 +1,17 @@
import React from 'react';
+import { useLocation } from 'react-router-dom';
import ReserveCar from '../../../components/ReserveCars/ReserveCar';
-const ReserveCars = () => (
-
-);
+const ReserveCars = () => {
+ const location = useLocation();
+ const { id, username, name } = location.state || {};
+
+ return (
+
+ );
+};
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/AddNewCar/AddNewCar.js b/src/pages/UserDashboard/AddNewCar/AddNewCar.js
index af7fbf2..c8ad7c5 100644
--- a/src/pages/UserDashboard/AddNewCar/AddNewCar.js
+++ b/src/pages/UserDashboard/AddNewCar/AddNewCar.js
@@ -2,16 +2,14 @@ import React from 'react';
import styled from '@emotion/styled';
import AddNewCarForm from './AddNewCarForm';
-const AddNewCar = () => {
- return(
-
-
- CREATE A VEHICLE
-
-
-
- )
-}
+const AddNewCar = () => (
+
+
+ CREATE A VEHICLE
+
+
+
+);
export default AddNewCar;
@@ -37,4 +35,3 @@ const SignUpContent = styled.div`
const Title = styled.p`
font-size: 1rem;
`;
-
diff --git a/src/pages/UserDashboard/AddNewCar/AddNewCarForm.js b/src/pages/UserDashboard/AddNewCar/AddNewCarForm.js
index e8cece5..6e09b3a 100644
--- a/src/pages/UserDashboard/AddNewCar/AddNewCarForm.js
+++ b/src/pages/UserDashboard/AddNewCar/AddNewCarForm.js
@@ -1,35 +1,39 @@
import React from 'react';
-import { useDispatch } from 'react-redux';
-import FormComponent from '../../../components/Form/FormComponent';
+import { useDispatch, useSelector } from 'react-redux';
+import { useNavigate } from 'react-router-dom';
import { CarSchema, carInitialValues } from '../../../models/car.model';
+import { TextInputField, TextAreaInputField } from '../../../components/Form/FormField';
import FormSubmitButton from '../../../components/Button/FormSubmitButton';
-import { FileInputField, TextAreaInputField, TextInputField } from '../../../components/Form/FormField';
import FormComponent2 from '../../../components/Form/FormComponent2';
-
+import { postNewCar } from '../../../redux/thunk';
+import { USERS_DASHBOARD } from '../../../routes/routeConstants';
const AddNewCarForm = () => {
const dispatch = useDispatch();
-
+ const navigate = useNavigate();
+ const status = useSelector((state) => state.cars.status);
const handleSubmit = (values) => {
- console.log(values);
- dispatch(userSignUp(values));
+ dispatch(postNewCar(values));
};
+ if (status === 'succeeded') {
+ navigate(`${USERS_DASHBOARD}`);
+ }
+
return (
-
-
-
-
-
-
-
- Create
+
+
+
+
+
+
+ Create Car
);
diff --git a/src/pages/UserDashboard/DashboardHome.js b/src/pages/UserDashboard/DashboardHome.js
index c2c3e7a..a8329c5 100644
--- a/src/pages/UserDashboard/DashboardHome.js
+++ b/src/pages/UserDashboard/DashboardHome.js
@@ -1,31 +1,32 @@
import React, { useState } from 'react';
import styled from '@emotion/styled';
-import DisplayCartCard from '../../components/Card/DisplayCartCard';
import { FaArrowLeft, FaArrowRight } from 'react-icons/fa';
-import colorWheel from '../../../src/components/asset/small_color_wheel.png'
+import { useSelector } from 'react-redux';
+import DisplayCartCard from '../../components/Card/DisplayCartCard';
+import colorWheel from '../../components/asset/small_color_wheel.png';
const DummyCards = [
{
- imageName: {colorWheel},
+ imageName: { colorWheel },
name: 'Bicycle',
shortNote:
'The VESPA C20 is a stunning moped with a modern electronic system and more',
},
{
- imageName: {colorWheel},
+ imageName: { colorWheel },
name: 'Bicycle',
shortNote:
'The VESPA C20 is a stunning moped with a modern electronic system and more',
},
{
- imageName: {colorWheel},
+ imageName: { colorWheel },
name: 'Bicycle',
shortNote:
'The VESPA C20 is a stunning moped with a modern electronic system and more',
},
{
- imageName: {colorWheel},
+ imageName: { colorWheel },
name: 'Bicycle',
shortNote:
'The VESPA C20 is a stunning moped with a modern electronic system and more',
@@ -34,6 +35,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);
@@ -54,12 +56,13 @@ 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 5fadb8a..fd53d56 100644
--- a/src/pages/UserDashboard/ItemDetail/ItemDetail.js
+++ b/src/pages/UserDashboard/ItemDetail/ItemDetail.js
@@ -1,26 +1,29 @@
import React from 'react';
+import { useParams } from 'react-router-dom';
+import { useSelector } from 'react-redux';
+import Bike from '../../../components/asset/bike.jpg';
import DisplayItemCard from '../../../components/Card/DisplayItemCard';
-import styled from '@emotion/styled';
-import Bike from '../../../../src/components/asset/bike.jpg'
const ItemDetail = () => {
- return(
-
-
-
- )
-}
+ const { id } = useParams();
+ const cars = useSelector((state) => state.cars.cars);
+ const numericId = parseInt(id, 10);
+ const car = cars.find((car) => car.id === numericId);
+ const {
+ name, description, pricePerHr, seatingCapacity,
+ } = car;
-export default ItemDetail;
+ return (
+
+ );
+};
-const Container = styled.div`
-// border: 1px solid blue;
- margin-right: -5rem;
- margin-bottom: -5rem;
-// margin-top: -3rem;
-`;
\ No newline at end of file
+export default ItemDetail;
diff --git a/src/redux/authentication/authenticationSlice.js b/src/redux/authentication/authenticationSlice.js
index 6209695..30d2d06 100644
--- a/src/redux/authentication/authenticationSlice.js
+++ b/src/redux/authentication/authenticationSlice.js
@@ -26,7 +26,6 @@ const authenticationSlice = createSlice({
})
.addCase(loginUser.pending, (state) => {
state.status = 'loading';
- console.log('Action staus: blahh is', state.status);
})
.addCase(loginUser.fulfilled, (state, action) => {
if (action.payload.status === 'failed') {
@@ -35,9 +34,6 @@ const authenticationSlice = createSlice({
} else {
state.authenticatedUser = action.payload.user;
state.status = action.payload.status || 'succeeded';
- console.log('Action paylod to check if there is a status:', action.payload);
- console.log('Authenticated user is: ', state.authenticatedUser);
- console.log('Authenticated user action status: ', state.status);
}
})
.addCase(loginUser.rejected, (state, action) => {
@@ -49,7 +45,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/cars/carsSlice.js b/src/redux/cars/carsSlice.js
index 48e5a9b..8c06b6e 100644
--- a/src/redux/cars/carsSlice.js
+++ b/src/redux/cars/carsSlice.js
@@ -1 +1,69 @@
-// carsSlice File.
+import { createSlice } from '@reduxjs/toolkit';
+import { deleteCar, fetchCars, postNewCar } from '../thunk';
+
+const initialState = {
+ cars: [],
+ status: 'idle',
+ error: null,
+};
+
+const carsSlice = createSlice({
+ name: 'cars',
+ initialState,
+ reducers: {
+ removeMarkStatus: (state, action) => {
+ const newState = state.cars.map(
+ (car) => (car.id === 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;
+ })
+ .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';
+ const deletedCarId = action.meta.arg; // Access the carId passed to the thunk
+ state.cars = state.cars.filter((car) => car.carId !== deletedCarId);
+ })
+ .addCase(deleteCar.rejected, (state, action) => {
+ state.status = 'failed';
+ state.error = action.payload ? action.payload.error : 'Delete failed';
+ })
+ .addCase(postNewCar.pending, (state) => {
+ state.status = 'loading';
+ state.error = null;
+ })
+ .addCase(postNewCar.fulfilled, (state, action) => {
+ state.status = 'succeeded';
+ state.cars = [...state.cars, action.payload.data];
+ })
+ .addCase(postNewCar.rejected, (state, action) => {
+ state.status = 'failed';
+ state.error = action.payload ? action.payload.error : 'Post new car failed';
+ });
+ },
+});
+
+export const { removeMarkStatus } = carsSlice.actions;
+export default carsSlice.reducer;
diff --git a/src/redux/reservations/reservationSlice.js b/src/redux/reservations/reservationSlice.js
index 0422aad..643b416 100644
--- a/src/redux/reservations/reservationSlice.js
+++ b/src/redux/reservations/reservationSlice.js
@@ -2,8 +2,8 @@ import { createSlice } from '@reduxjs/toolkit';
import { fetchCarReservations, postReserveCar } from '../thunk';
const initialState = {
- reservation: {},
reservations: [],
+ newReservationName: '',
status: 'idle',
error: null,
};
@@ -11,7 +11,11 @@ const initialState = {
const reservationSlice = createSlice({
name: 'reservation',
initialState,
- reducers: {},
+ reducers: {
+ getNewReservationName: (state, action) => {
+ state.newReservationName = action.payload;
+ },
+ },
extraReducers: (builder) => {
builder
.addCase(postReserveCar.pending, (state) => {
@@ -20,7 +24,7 @@ const reservationSlice = createSlice({
})
.addCase(postReserveCar.fulfilled, (state, action) => {
state.status = 'succeeded';
- state.reservation = action.payload.data;
+ state.reservations = [...state.reservations, action.payload.data];
})
.addCase(postReserveCar.rejected, (state, action) => {
state.status = 'failed';
@@ -32,7 +36,7 @@ const reservationSlice = createSlice({
})
.addCase(fetchCarReservations.fulfilled, (state, action) => {
state.status = 'succeeded';
- state.reservations = action.payload.data;
+ state.reservations = action.payload;
})
.addCase(fetchCarReservations.rejected, (state, action) => {
state.status = 'failed';
@@ -41,4 +45,5 @@ const reservationSlice = createSlice({
},
});
+export const { getNewReservationName } = reservationSlice.actions;
export default reservationSlice.reducer;
diff --git a/src/redux/store.js b/src/redux/store.js
index 1fa3e5f..6203cab 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 8572991..3d50f14 100644
--- a/src/redux/thunk.js
+++ b/src/redux/thunk.js
@@ -37,10 +37,6 @@ export const loginUser = createAsyncThunk(
try {
const response = await axios.post(`${baseURL}/users/sign_in`, { user });
const { data, headers } = response;
- console.log('the data from async method:');
- console.log(data);
- console.log('the headers:');
- console.log(headers);
if (response.status === 200 || response.status === 201) {
setAuthenticationToken({ headers });
@@ -71,16 +67,17 @@ 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`, {
+ // const token = getAuthenticationToken();
+ // const authToken = token ? token.replace('Bearer ', '') : '';
+ // console.log('authtoken:',authToken);
+
+ const response = await axios.delete(`${baseURL}/users/sign_out`, {
headers: { Authorization: localStorage.getItem('token') },
});
+ removeAuthenticationToken();
const { status, message } = await handleResponse(response);
- if (status === 'succeeded') {
- removeAuthenticationToken();
- }
-
return { status, message };
} catch (error) {
return thunkAPI.rejectWithValue(error);
@@ -110,18 +107,74 @@ export const postReserveCar = createAsyncThunk(
);
export const fetchCarReservations = createAsyncThunk(
- 'reservations/fetchCarReservations',
- async (_, thunkAPI) => {
- try {
- const token = localStorage.getItem('token');
- const response = await axios.get(`${baseURL}/my_reservations`, {
- headers: {
- Authorization: token,
- },
- });
- return response.data;
- } catch (error) {
- return thunkAPI.rejectWithValue(error);
+ 'reservations/fetchCarReservations',
+ async (_, thunkAPI) => {
+ try {
+ const token = localStorage.getItem('token');
+ const response = await axios.get(`${baseURL}/my_reservations`, {
+ headers: {
+ Authorization: token,
+ },
+ });
+ return response.data;
+ } catch (error) {
+ return thunkAPI.rejectWithValue(error);
+ }
+ },
+);
+
+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) => {
+ 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);
+ }
+ },
);
diff --git a/src/routes/routeConstants.js b/src/routes/routeConstants.js
index 8e181ff..f9a44ec 100644
--- a/src/routes/routeConstants.js
+++ b/src/routes/routeConstants.js
@@ -9,8 +9,8 @@ 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 CONTACT = 'contact'
+export const DELETE_CAR = 'delete-car';
+export const CONTACT = 'contact';
export const ITEMS = 'cars';
export const ITEM_DETAIL = '/u/dashboard/item-details';
export const USERDASHBOARDHOME = 'home';
diff --git a/src/routes/routes.js b/src/routes/routes.js
index 41caca8..f7a56c6 100644
--- a/src/routes/routes.js
+++ b/src/routes/routes.js
@@ -1,5 +1,6 @@
import { Navigate, useRoutes } from 'react-router-dom';
+import { useSelector } from 'react-redux';
import AuthLayout from '../layout/Auth/AuthLayout';
import LandingPageLayout from '../layout/LandingPage/LandingPageLayout';
import ForgotPassword from '../pages/Auth/ForgotPassword/ForgotPassword';
@@ -21,7 +22,7 @@ import {
USERDASHBOARDHOME,
USERS_DASHBOARD,
ADD_NEW_CAR,
- DELETE_RESERVATION,
+ DELETE_CAR,
ITEM_DETAIL,
CONTACT,
NOTFOUND,
@@ -29,10 +30,15 @@ import {
import UsersDashboardLayout from '../layout/UsersDashboard/UsersDashboardLayout';
import DashboardHome from '../pages/UserDashboard/DashboardHome';
import AddNewCar from '../pages/UserDashboard/AddNewCar/AddNewCar';
-import DeleteReservation from '../pages/LandingPage/DeleteReservation/DeleteReservation';
import Contact from '../pages/LandingPage/Contact/Contact';
+import DeleteList from '../components/DeleteCars/DeleteList';
+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,
@@ -42,8 +48,13 @@ export default function Router() {
],
},
- {
- path: USERS_DASHBOARD,
+ isLoading && {
+ path: USERS_DASHBOARD,
+ element:
,
+ },
+
+ isAuthenticated && {
+ path: USERS_DASHBOARD,
element:
,
children: [
{ path: USERS_DASHBOARD, element:
},
@@ -51,13 +62,13 @@ export default function Router() {
{ path: MY_RESERVATIONS, element:
},
{ path: RESERVE_CARS, element:
},
{ path: ADD_NEW_CAR, element:
},
- { path: ITEM_DETAIL, element:
},
- { path: DELETE_RESERVATION, element:
},
+ { path: `${ITEM_DETAIL}/:id`, element:
},
+ { path: DELETE_CAR, element:
},
{ path: CONTACT, element:
},
{ path: NOTFOUND, element:
},
{ path: '*', 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;
+}