Skip to content

Commit

Permalink
add fav logic, clearFilters
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikolaus-B committed Mar 24, 2024
1 parent 4713d19 commit af6bc7f
Show file tree
Hide file tree
Showing 16 changed files with 227 additions and 18 deletions.
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"react-modal": "^3.16.1",
"react-redux": "^9.1.0",
"react-router-dom": "^6.22.3",
"redux-persist": "^6.0.0",
"styled-components": "^6.1.8",
"uid": "^2.0.2",
"yup": "^1.4.0"
Expand Down
19 changes: 18 additions & 1 deletion src/components/Car/Car.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
CarImage,
CarItem,
Desctiption,
FavouriteButton,
HeadInfo,
HeadInfocontainer,
LocationAndRating,
Expand All @@ -13,9 +14,13 @@ import {
import { CarModal } from "../CarModal/CarModal";
import { useState } from "react";
import { Details } from "../Details/Details";
import { useDispatch } from "react-redux";
import { toggleFavourite } from "../../redux/cars/carsSlice";
import { useIsFavourite } from "../../hooks/useIsFavourite";

export const Car = ({ car }) => {
const [modalIsOpen, setIsOpen] = useState(false);
const dispatch = useDispatch();

function openModal() {
setIsOpen(true);
Expand All @@ -25,6 +30,12 @@ export const Car = ({ car }) => {
setIsOpen(false);
}

const toogleFavouriteCar = (id) => {
dispatch(toggleFavourite(id));
};

const isFavourite = useIsFavourite(car._id);

return (
<CarItem>
<CarImage
Expand All @@ -38,7 +49,13 @@ export const Car = ({ car }) => {
<HeadInfo>{car.name}</HeadInfo>
<PriceContainer>
<HeadInfo>{car.price}.00</HeadInfo>
<Icon width={24} height={24} iconId={"heart"} />
<FavouriteButton onClick={() => toogleFavouriteCar(car._id)}>
<Icon
width={24}
height={24}
iconId={isFavourite ? "heart-red" : "heart"}
/>
</FavouriteButton>
</PriceContainer>
</HeadInfocontainer>
<LocationAndRating>
Expand Down
5 changes: 5 additions & 0 deletions src/components/Car/Car.styled.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ export const HeadInfo = styled.p`
font-weight: ${(p) => p.theme.fonts.bold};
`;

export const FavouriteButton = styled.button`
border: none;
background-color: transparent;
`;

export const LocationAndRating = styled.div`
display: flex;
gap: 16px;
Expand Down
4 changes: 0 additions & 4 deletions src/components/CarsList/CarsList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@ import { Car } from "../Car/Car";
import { CarList, ListContainer, LoadMore } from "./CarsList.styled";

export const CarsList = () => {
// const cars = useSelector(selectCars);
const filteredCars = useSelector(selectFilteredCars);

// const equip = useSelector(selectfilteredCarsByEquipment);
// const type = useSelector(selectFilteredByType);

return (
<ListContainer>
<CarList>
Expand Down
80 changes: 80 additions & 0 deletions src/components/FavouriteCar/FavouriteCar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { useState } from "react";
import {
CarImage,
Desctiption,
FavouriteButton,
HeadInfo,
HeadInfocontainer,
LocationAndRating,
PriceContainer,
ShowMoreBtn,
TagsContainer,
} from "../Car/Car.styled";
import { Icon } from "../Icon/Icon";
import { CarModal } from "../CarModal/CarModal";
import { Details } from "../Details/Details";
import { useDispatch } from "react-redux";
import { toggleFavourite } from "../../redux/cars/carsSlice";
import { useIsFavourite } from "../../hooks/useIsFavourite";

export const FavouriteCar = ({ favCar }) => {
const [modalIsOpen, setIsOpen] = useState(false);
const dispatch = useDispatch();

function openModal() {
setIsOpen(true);
}

function closeModal() {
setIsOpen(false);
}

const toogleFavouriteCar = (id) => {
dispatch(toggleFavourite(id));
};

const isFavourite = useIsFavourite(favCar._id);

return (
<li>
<CarImage
$bgImage={
favCar.gallery[0] ||
"https://t4.ftcdn.net/jpg/04/70/29/97/360_F_470299797_UD0eoVMMSUbHCcNJCdv2t8B2g1GVqYgs.jpg"
}
></CarImage>
<div>
<HeadInfocontainer>
<HeadInfo>{favCar.name}</HeadInfo>
<PriceContainer>
<HeadInfo>{favCar.price}.00</HeadInfo>
<FavouriteButton onClick={() => toogleFavouriteCar(favCar._id)}>
<Icon
width={24}
height={24}
iconId={isFavourite ? "heart-red" : "heart"}
/>
</FavouriteButton>
</PriceContainer>
</HeadInfocontainer>
<LocationAndRating>
<p>
{favCar.rating} <span>{favCar.reviews.length || 0} Reviews</span>
</p>
<p>{favCar.location}</p>
</LocationAndRating>
<Desctiption>{favCar.description}</Desctiption>
<TagsContainer>
<Details details={favCar.details} />
</TagsContainer>
<ShowMoreBtn onClick={() => openModal()}>Show more</ShowMoreBtn>
</div>

<CarModal
modalIsOpen={modalIsOpen}
closeModal={closeModal}
car={favCar}
/>
</li>
);
};
18 changes: 18 additions & 0 deletions src/components/FavouriteList/FavouriteList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useSelector } from "react-redux";
import { selectFavourites } from "../../redux/cars/carsSelectors";

import { Car } from "../Car/Car";
import { FavList } from "./FavouriteList.styled";

export const FavouriteList = () => {
const favouritesCars = useSelector(selectFavourites);
return (
<>
<FavList>
{favouritesCars.map((favouriteCar) => {
return <Car key={favouriteCar.id} car={favouriteCar.car} />;
})}
</FavList>
</>
);
};
8 changes: 8 additions & 0 deletions src/components/FavouriteList/FavouriteList.styled.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import styled from "styled-components";

export const FavList = styled.ul`
display: flex;
flex-direction: column;
gap: 30px;
margin: 0 auto;
`;
8 changes: 8 additions & 0 deletions src/hooks/useIsFavourite.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { useSelector } from "react-redux";
import { selectFavourites } from "../redux/cars/carsSelectors";

export const useIsFavourite = (id) => {
const favourites = useSelector(selectFavourites);

return favourites.some((favorite) => favorite.car._id === id);
};
11 changes: 7 additions & 4 deletions src/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import "./index.css";
import { store } from "./redux/store.js";
import { PersistGate } from "redux-persist/integration/react";
import { persistor, store } from "./redux/store.js";
import { Provider } from "react-redux";
import { BrowserRouter } from "react-router-dom";
import { ThemeProvider } from "styled-components";
Expand All @@ -12,9 +13,11 @@ ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<BrowserRouter basename="/campers">
<Provider store={store}>
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
<PersistGate loading={null} persistor={persistor}>
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
</PersistGate>
</Provider>
</BrowserRouter>
</React.StrictMode>
Expand Down
4 changes: 3 additions & 1 deletion src/pages/FavouritePage.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { FavouriteList } from "../components/FavouriteList/FavouriteList";

export default function FavouritePage() {
return (
<section className="container">
<h1>favourite</h1>
<FavouriteList />
</section>
);
}
8 changes: 8 additions & 0 deletions src/pages/HomePage.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { useDispatch } from "react-redux";
import { CarsList } from "../components/CarsList/CarsList";
import { Filters } from "../components/Filters/Filters";
import { useEffect } from "react";
import { clearFilters } from "../redux/filter/filterSlice";

export default function HomePage() {
const dispatch = useDispatch();
useEffect(() => {
dispatch(clearFilters());
}, [dispatch]);

return (
<section className="container">
<Filters />
Expand Down
2 changes: 2 additions & 0 deletions src/redux/cars/carsSelectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {

export const selectCars = (state) => state.cars.cars;

export const selectFavourites = (state) => state.cars.favourites;

export const selectFilteredCarsByInput = createSelector(
[selectCars, selectInputValue, selectEquipmentFilter],
(cars, inputValue) => {
Expand Down
17 changes: 16 additions & 1 deletion src/redux/cars/carsSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,30 @@ const carsSlice = createSlice({
name: "cars",
initialState: {
cars: [],
favourites: [],
isLoading: false,
error: null,
},
reducers: {},
reducers: {
toggleFavourite: (state, action) => {
const carId = action.payload;
const index = state.favourites.findIndex((car) => car.id === carId);
if (index === -1) {
const carToAdd = state.cars.find((car) => car.id === carId);
if (carToAdd) {
state.favourites.push(carToAdd);
}
} else {
state.favourites.splice(index, 1);
}
},
},
extraReducers: (builder) => {
builder.addCase(fetchCars.fulfilled, (state, action) => {
state.cars = action.payload;
});
},
});

export const { toggleFavourite } = carsSlice.actions;
export const carsReducer = carsSlice.reducer;
13 changes: 11 additions & 2 deletions src/redux/filter/filterSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,18 @@ const filterSlice = createSlice({
state.type.splice(index, 1);
}
},
clearFilters: (state) => {
state.inputValue = "";
state.equipment = [];
state.type = [];
},
},
});

export const { changeInputFilter, toogleEquipmentFilter, toogleTypeFilter } =
filterSlice.actions;
export const {
changeInputFilter,
toogleEquipmentFilter,
toogleTypeFilter,
clearFilters,
} = filterSlice.actions;
export const filterReducer = filterSlice.reducer;
38 changes: 33 additions & 5 deletions src/redux/store.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,38 @@
import { configureStore } from "@reduxjs/toolkit";
import { carsReducer } from "./cars/carsSlice";
import { filterReducer } from "./filter/filterSlice";
import { combineReducers, configureStore } from "@reduxjs/toolkit";
import storage from "redux-persist/lib/storage";
import {
persistStore,
persistReducer,
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
} from "redux-persist";
const persistConfig = {
key: "campers",
storage,
whitelist: ["cars"],
};

const rootReducer = combineReducers({
cars: carsReducer,
filter: filterReducer,
});

const persistedRootReducer = persistReducer(persistConfig, rootReducer);

export const store = configureStore({
reducer: {
cars: carsReducer,
filter: filterReducer,
},
reducer: persistedRootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}),
});

export const persistor = persistStore(store);

0 comments on commit af6bc7f

Please sign in to comment.