Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minor adjustments remove console statements #22

Merged
merged 25 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9a9cb03
Refactor App component to use arrow function syntax
George7h Mar 6, 2024
67ceeb2
Refactor AddReservation component to use arrow function syntax and ad…
George7h Mar 6, 2024
29bd668
Refactor DetailsPage component to use arrow function syntax
George7h Mar 6, 2024
7529c96
Refactor Layout component
George7h Mar 6, 2024
0ae5b87
Refactor MyReservations component
George7h Mar 6, 2024
9009025
Refactor Navigation component
George7h Mar 6, 2024
680f230
Refactor UserAuth component to use arrow function syntax
George7h Mar 6, 2024
18d1e04
Refactor UserSignUp component to use arrow function syntax
George7h Mar 6, 2024
af4c18a
Refactor PlacesList component to use arrow function syntax
George7h Mar 6, 2024
494848f
Refactor AddPlace component to use Redux for state management
George7h Mar 6, 2024
39cb16b
Fix form validation and input constraints
George7h Mar 7, 2024
3a7fd88
Add fetchPlaces action to AddReservation component rather than using …
George7h Mar 7, 2024
f8ec832
Fix price formatting in MyReservations component
George7h Mar 7, 2024
9bf2e04
Fix formatting of price per night in PlaceList component
George7h Mar 7, 2024
e59d604
Add fetchPlaces after adding a new place
George7h Mar 7, 2024
75eb0c2
Add fetchReservations after adding a reservation
George7h Mar 7, 2024
60d34f2
Refactor deleteplace component to render places on loading the compon…
George7h Mar 7, 2024
0daccb0
Add cursor pointer to button and remove cursor pointer from item details
George7h Mar 7, 2024
26ba368
Remove unnecessary comments and improve form validation in AddReserva…
George7h Mar 7, 2024
d8331b7
Remove comment
George7h Mar 7, 2024
b1fa572
Fix formatting of price per night in DetailsPage component
George7h Mar 7, 2024
6ce119b
Add error message for incomplete form submission
George7h Mar 7, 2024
b3405dc
Fix error message display in AddReservation component
George7h Mar 7, 2024
62e99cd
Add confirmation dialog for delete functionality and it's styling
George7h Mar 7, 2024
cc6a844
Change favicon
tsheporamantso Mar 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions public/image.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="icon" href="%PUBLIC_URL%/image.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
Expand Down
4 changes: 2 additions & 2 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import AddPlace from './Components/AddPlace';
import AddReservation from './Components/AddReservation';
import DeletePlace from './Components/DeletePlace';

function App() {
const App = () => {
const [loggedIn, setLoggedIn] = useState(false);

useEffect(() => {
Expand Down Expand Up @@ -42,6 +42,6 @@ function App() {
</Routes>
</Router>
);
}
};

export default App;
53 changes: 28 additions & 25 deletions src/Components/AddPlace.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import React, { useState } from 'react';
import axios from 'axios';
import { useDispatch, useSelector } from 'react-redux';
import { addPlace } from '../Redux/places/addPlaceSlice';
import { fetchPlaces } from '../Redux/places/placesSlice';
import '../AddPlace.css';

function AddPlace() {
const AddPlace = () => {
const dispatch = useDispatch();
const status = useSelector((state) => state.addPlace.status);
const error = useSelector((state) => state.addPlace.error);

const initialPlaceData = {
description: '',
photo: '',
Expand All @@ -13,51 +19,48 @@ function AddPlace() {
user_id: localStorage.getItem('userId'),
};
const [placeData, setPlaceData] = useState(initialPlaceData);
const [status, setStatus] = useState('idle');
const [error, setError] = useState(null);
const [errorMessage, setErrorMessage] = useState('');

const handleChange = (e) => {
setPlaceData({ ...placeData, [e.target.name]: e.target.value });
};

const handleSubmit = async (e) => {
const handleSubmit = (e) => {
e.preventDefault();
setStatus('loading');

try {
const userId = localStorage.getItem('userId');
await axios.post(`http://localhost:3000/api/v1/users/${userId}/places`, placeData);
setStatus('succeeded');
setPlaceData(initialPlaceData);
} catch (error) {
setStatus('failed');
setError(error.response.data);
const values = Object.values(placeData);
if (values.some((value) => !value)) {
setErrorMessage('Please fill in all fields');
setTimeout(() => {
setErrorMessage('');
}, 5000); // Clear error message after 5 seconds
return;
}
dispatch(addPlace(placeData))
.then(() => dispatch(fetchPlaces()));
};

return (
<div className="form-container">
<h2>Add Place</h2>
<form onSubmit={handleSubmit}>
{errorMessage && <p style={{ color: 'red' }}>{errorMessage}</p>}
<input type="text" name="description" placeholder="Description" value={placeData.description} onChange={handleChange} />
<br />
<input type="text" name="photo" placeholder="Photo URL" value={placeData.photo} onChange={handleChange} />
<br />
<input type="text" name="location" placeholder="Location" value={placeData.location} onChange={handleChange} />
<br />
<input type="number" name="rate" placeholder="Rate" value={placeData.rate} onChange={handleChange} />
<input type="number" name="rate" placeholder="Rate" min="1" max="5" value={placeData.rate} onChange={handleChange} />
<br />
<input type="text" name="address" placeholder="Address" value={placeData.address} onChange={handleChange} />
<br />
<input type="number" name="pricepernight" placeholder="Price per night" value={placeData.pricepernight} onChange={handleChange} />
{' '}
{/* Add address input */}
{status === 'failed' && (
<div className="error-message">
Error:
{' '}
{error}
</div>
<input type="number" name="pricepernight" step="0.01" placeholder="Price per night" value={placeData.pricepernight} onChange={handleChange} />
<br />
{status === 'failed' && error && (
<div className="error-message">
{error}
</div>
)}
{status === 'succeeded' && (
<div className="success-message">
Expand All @@ -68,6 +71,6 @@ function AddPlace() {
</form>
</div>
);
}
};

export default AddPlace;
43 changes: 21 additions & 22 deletions src/Components/AddReservation.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React, { useState, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { addReservation } from '../Redux/reservations/addReservationsSlice';
import { fetchPlaces } from '../Redux/places/placesSlice';
import { fetchReservations } from '../Redux/reservations/myReservationsSlice';
import '../AddReservation.css';

function AddReservation() {
const AddReservation = () => {
const dispatch = useDispatch();
const userId = localStorage.getItem('userId');

Expand All @@ -16,28 +18,18 @@ function AddReservation() {
};

const [reservationData, setReservationData] = useState(initialReservationData);
const [places, setPlaces] = useState([]);
const [selectedPlace, setSelectedPlace] = useState(null);
const [numberOfDays, setNumberOfDays] = useState(0);
const status = useSelector((state) => state.addReservation.status);
const error = useSelector((state) => state.addReservation.error);
const places = useSelector((state) => state.places.places);
const [errorMessage, setErrorMessage] = useState('');

const fetchPlaces = async (userId) => {
try {
const response = await fetch(`http://localhost:3000/api/v1/users/${userId}/places`);
const data = await response.json();
setPlaces(data);
} catch (error) {
setErrorMessage('Invalid Email or password.');
}
};

useEffect(() => {
if (userId) {
fetchPlaces(userId);
dispatch(fetchPlaces(userId));
}
}, [userId]);
}, [userId, dispatch]);

useEffect(() => {
if (reservationData.start_date && reservationData.end_date && selectedPlace) {
Expand All @@ -47,7 +39,7 @@ function AddReservation() {
setNumberOfDays(daysDifference);
setReservationData((prevState) => ({
...prevState,
price: daysDifference * selectedPlace.pricepernight,
price: (daysDifference * parseFloat(selectedPlace.pricepernight)).toFixed(2),
}));
}
}, [reservationData.start_date, reservationData.end_date, selectedPlace, reservationData]);
Expand All @@ -56,7 +48,6 @@ function AddReservation() {
const { name, value } = e.target;
setReservationData({ ...reservationData, [name]: value });

// Find the selected place and update the selectedPlace state
if (name === 'place_id') {
const selected = places.find((place) => place.id === parseInt(value, 10));
setSelectedPlace(selected);
Expand All @@ -65,9 +56,17 @@ function AddReservation() {

const handleSubmit = (e) => {
e.preventDefault();
dispatch(addReservation(reservationData)).then(() => {
setReservationData(initialReservationData);
});

if (!reservationData.start_date || !reservationData.end_date || !reservationData.place_id) {
setErrorMessage('Please fill in all fields');
setTimeout(() => {
setErrorMessage('');
}, 5000);
return;
}

dispatch(addReservation(reservationData))
.then(() => dispatch(fetchReservations()));
};

return (
Expand All @@ -83,9 +82,9 @@ function AddReservation() {
<br />
<input type="date" name="end_date" placeholder="End Date" value={reservationData.end_date} onChange={handleChange} />
<br />
<input type="number" name="price_per_night" placeholder="Price Per Night" value={selectedPlace ? selectedPlace.pricepernight : ''} disabled />
<input type="number" name="price_per_night" placeholder="Price Per Night" value={selectedPlace ? parseFloat(selectedPlace.pricepernight).toFixed(2) : ''} disabled />
<br />
<input type="number" name="price" placeholder="Total Bill" value={reservationData.price || ''} disabled />
<input type="number" name="price" placeholder="Total Bill" value={parseFloat(reservationData.price).toFixed(2) || ''} disabled />
<br />
<select name="place_id" value={reservationData.place_id} onChange={handleChange}>
<option value="">Select a place</option>
Expand Down Expand Up @@ -115,6 +114,6 @@ function AddReservation() {
<button className="link-btn-li" type="submit" onClick={handleSubmit} disabled={status === 'loading'}>Add Reservation</button>
</div>
);
}
};

export default AddReservation;
39 changes: 35 additions & 4 deletions src/Components/DeletePlace.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,38 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { deleteItem } from '../Redux/places/deleteItemSlice';
import { fetchPlaces } from '../Redux/places/placesSlice';
import '../DeleteItem.css';

const DeletePlace = () => {
const dispatch = useDispatch();
const places = useSelector((state) => state.places.places);
const status = useSelector((state) => state.deleteItem.status);
const error = useSelector((state) => state.deleteItem.error);

const [showConfirmation, setShowConfirmation] = useState(false);
const [itemIdToDelete, setItemIdToDelete] = useState(null);

useEffect(() => {
dispatch(fetchPlaces());
}, [dispatch]);

const handleDelete = (id) => {
dispatch(deleteItem(id));
setShowConfirmation(true);
setItemIdToDelete(id);
};

const confirmDelete = () => {
dispatch(deleteItem(itemIdToDelete))
.then(() => {
dispatch(fetchPlaces());
setShowConfirmation(false);
});
};

const cancelDelete = () => {
setShowConfirmation(false);
setItemIdToDelete(null);
};

if (places.length === 0) {
Expand All @@ -24,20 +47,28 @@ const DeletePlace = () => {
return (
<div>
Error:
{status.error}
{error}
</div>
);
}

return (
<div className="delete-place-container">
<h1>Delete Place</h1>

<ul className="delete-place-card">
{places.map((place) => (
<li key={place.id} className="card">
<h3>{place.description}</h3>
<img className="place-img" src={place.photo} alt={place.description} />
<button className="delete" type="submit" onClick={() => handleDelete(place.id)}>Delete</button>
<button className="delete" type="button" onClick={() => handleDelete(place.id)}>Delete</button>
{showConfirmation && (
<div className="confirmation-dialog">
<p>Are you sure?</p>
<button type="button" id="deleteyes" onClick={confirmDelete}>Yes</button>
<button type="button" id="deleteno" onClick={cancelDelete}>No</button>
</div>
)}
</li>
))}
</ul>
Expand Down
8 changes: 3 additions & 5 deletions src/Components/DetailsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { fetchDetailsPage } from '../Redux/places/detailsPageSlice';
import '../Placelist.css';
import '../DetailsPage.css';

function DetailsPage() {
const DetailsPage = () => {
const dispatch = useDispatch();
const { id } = useParams();
const detailsPage = useSelector((state) => state.detailsPage.detailsPage);
Expand Down Expand Up @@ -52,7 +52,7 @@ function DetailsPage() {
</p>
<p className="price-per-night">
Price per night:$
{detailsPage.pricepernight}
{typeof detailsPage.pricepernight === 'string' ? parseFloat(detailsPage.pricepernight).toFixed(2) : detailsPage.pricepernight}
</p>
<Link to="/layout/addReservation">
<button className="add-res-button" type="button">Add Reservation</button>
Expand All @@ -61,9 +61,8 @@ function DetailsPage() {
</div>
</div>
</>

);
}
};

const StarRating = ({ rating }) => {
const stars = Array.from({ length: 5 }, (_, index) => (
Expand All @@ -73,7 +72,6 @@ const StarRating = ({ rating }) => {
return <div>{stars}</div>;
};

// Prop types validation for StarRating component
StarRating.propTypes = {
rating: PropTypes.number.isRequired,
};
Expand Down
17 changes: 6 additions & 11 deletions src/Components/Layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,11 @@ import React from 'react';
import { Outlet } from 'react-router-dom';
import Navigation from './Navigation';

function Layout() {
return (
<div className="container">
<Navigation />
{/* Start of Main Content */}
<Outlet />
{/* End of Main Content */}

</div>
);
}
const Layout = () => (
<div className="container">
<Navigation />
<Outlet />
</div>
);

export default Layout;
6 changes: 3 additions & 3 deletions src/Components/MyReservations.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useSelector, useDispatch } from 'react-redux';
import { fetchReservations, removeReservation } from '../Redux/reservations/myReservationsSlice';
import '../MyReservations.css';

function MyReservations() {
const MyReservations = () => {
const dispatch = useDispatch();
const reservations = useSelector((state) => state.myReservations.reservations);
const status = useSelector((state) => state.myReservations.status);
Expand Down Expand Up @@ -57,7 +57,7 @@ function MyReservations() {
<p>
<strong>Price:$</strong>
{' '}
{reservation.price}
{typeof reservation.price === 'string' ? parseFloat(reservation.price).toFixed(2) : reservation.price}
</p>
<button
type="button"
Expand All @@ -73,6 +73,6 @@ function MyReservations() {
)}
</div>
);
}
};

export default MyReservations;
Loading
Loading