Skip to content

Commit

Permalink
Pagination & uniqBrand
Browse files Browse the repository at this point in the history
  • Loading branch information
OlenaIa committed Nov 29, 2023
1 parent 2920ac1 commit 9944d9b
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 107 deletions.
20 changes: 8 additions & 12 deletions src/components/CarItem/CarItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,24 @@ import { selectFavoriteCars } from "redux/selectors";


export const CarItem = ({ car, index }) => {
const dispatch = useDispatch();
const favoriteIdArr = useSelector(selectFavoriteCars);
console.log('favoriteIdArr', favoriteIdArr);


const dispatch = useDispatch();
const favoriteCarsId = useSelector(selectFavoriteCars);

const { id, make, model, year, img, rentalPrice, rentalCompany, type, functionalities, address } = car;
const cityCountry = address.split(', ').slice(-2);
const cityCountry = address?.split(', ').slice(-2);

const [isCarFavorite, setIsCarFavorite] = useState(false);

useEffect(() => {
if (favoriteIdArr?.some(item => item === id)) {
setIsCarFavorite(true);
} else {setIsCarFavorite(false)}
}, [favoriteIdArr, id]);
if (favoriteCarsId?.some(car => car.id === id)) {
setIsCarFavorite(true);
} else { setIsCarFavorite(false) }
}, [favoriteCarsId, id]);

const onClickHeart = () => {
isCarFavorite ? dispatch(deleteFavoriteCar(id)) : dispatch(addFavoriteCar(id));
isCarFavorite ? dispatch(deleteFavoriteCar(id)) : dispatch(addFavoriteCar(car));
}


return (
<CarItemStyle key={id}>
<CarCard>
Expand Down
33 changes: 21 additions & 12 deletions src/components/CarsList/CarsList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,36 @@ import { CarItem } from "components/CarItem/CarItem";
import { Container, Section } from "pages/Page.styled";
import { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { getCarsThunk, getFirstCarsThunk } from "redux/cars/fetchCar";
import { selectCars, selectIsLoading } from "redux/selectors";
import { LIMIT, getCarsThunk } from "redux/cars/fetchCar";
import { selectAllCars, selectCars, selectIsLoading } from "redux/selectors";
import { CarsListStyle, LoadMore } from "./CarsList.styled";

export const CarsList = () => {
const cars = useSelector(selectCars);
console.log('cars in List', cars);
const isLoading = useSelector(selectIsLoading);
const dispatch = useDispatch();
console.log(cars.length);
const isLoading = useSelector(selectIsLoading);
const cars = useSelector(selectCars);
const allCars = useSelector(selectAllCars);

const [page, setPage] = useState(0)
const [isLoadMore, setIsLoadMore] = useState(false);

useEffect(() => {
dispatch(getFirstCarsThunk())
}, [dispatch]);
if (page === 0) {
setPage(page + 1);
return;
};

const onClickLoadMore = () => {
dispatch(getCarsThunk());
setIsLoadMore(true);
}
dispatch(getCarsThunk(page))
}, [dispatch, page]);

const totalPage = allCars.length / LIMIT;

const onClickLoadMore = () => {
if (page === totalPage - 1) {
setIsLoadMore(true);
};
setPage(page + 1);
};

return (
<Section>
Expand Down
2 changes: 1 addition & 1 deletion src/components/CarsList/CarsList.styled.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ flex-wrap: wrap;
row-gap: 20px;
column-gap: 15px;
margin-bottom: 100px;
justify-content: center;
@media screen and (min-width: 768px) {
row-gap: 30px;
Expand Down
31 changes: 15 additions & 16 deletions src/components/Filters/Filters.jsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import { useSelector } from "react-redux";
import { selectCars } from "redux/selectors";
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { getAllCarsThunk } from "redux/cars/fetchCar";
import { selectCarBrands } from "redux/selectors";

export const Filters = () => {
const cars = useSelector(selectCars);

const brands = cars?.map(car => car.make);
console.log('brands', brands);
const uniqueBrands = brands.filter(
(brand, index, array) => array.indexOf(brand) === index
);
console.log('brauniqueBrandsnds', uniqueBrands);
const dispatch = useDispatch();
const carBrands = useSelector(selectCarBrands);

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

const pricesArray = [];
for (let index = 30; index < 501; index += 10) {
pricesArray.push(index)
pricesArray.push(index);
};
console.log('pricesArray', pricesArray);

return (
<>
Expand All @@ -25,11 +24,11 @@ export const Filters = () => {
{/* <option value="">Please choose car brand</option> */}
<option value=""
defaultValue="Brand"
// selected="selected"
// hidden="hidden"
// disabled
// selected="selected"
// hidden="hidden"
// disabled
>Please choose car brand</option>
{uniqueBrands?.map((brand) => <option value={brand}>{brand}</option>)}
{carBrands?.map((brand) => <option value={brand}>{brand}</option>)}
</select>
</label>
<label>Price/ 1 hour
Expand Down
27 changes: 26 additions & 1 deletion src/pages/Favorites.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,31 @@
import { CarsListStyle } from "components/CarsList/CarsList.styled";
import { Container, EmptyPage, Section } from "./Page.styled";
import { CarItem } from "components/CarItem/CarItem";
import { useSelector } from "react-redux";
import { selectFavoriteCars } from "redux/selectors";
import { Link } from 'react-router-dom';

const Favorite = () => {
const favoriteCarsId = useSelector(selectFavoriteCars);

return (
<>Favorite</>
<>
<Section>
<Container>
{(favoriteCarsId?.length > 0) ?
<CarsListStyle>
{favoriteCarsId?.map((car, index) =>
<CarItem car={car} key={car.id} index={index} />
)}
</CarsListStyle> :
<EmptyPage>
<p>
Please select your favorite cars in the <Link to="/catalog">Сatalog</Link>.
</p>
</EmptyPage>}
</Container>
</Section>
</>
)
}

Expand Down
18 changes: 18 additions & 0 deletions src/pages/Page.styled.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,21 @@ export const Container = styled.div`
margin-bottom: 50px;
}
`;

export const EmptyPage = styled.div`
display: flex;
height: 100vh;
align-items: center;
/* width: 100%; */
font-weight: 600;
font-size: 40px;
color: var(--color-text-main);
@media screen and (min-width: 768px) {
}
@media screen and (min-width: 1440px) {
}
`;
31 changes: 12 additions & 19 deletions src/redux/cars/carsSlice.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
import { createSlice, isAnyOf } from '@reduxjs/toolkit'
import { getCarsThunk, getFirstCarsThunk } from './fetchCar';
import { getCarsThunk, getAllCarsThunk } from './fetchCar';

const carsInitialState = {
cars: [],
allCars: [],
carsBrands: [],
isLoading: false,
error: null,
// isContactAdd: false,
};

const onPending = (state) => {
state.isLoading = true;
state.error = null;
// state.isContactAdd = false;
};

const onRejected = (state, { payload }) => {
state.isLoading = false;
state.error = payload;
// state.isContactAdd = false;
};

const arrOfActs = [getFirstCarsThunk, getCarsThunk];
const arrOfActs = [getAllCarsThunk, getCarsThunk];

const addStatusToActs = status =>
arrOfActs.map((el) => el[status]);
Expand All @@ -30,27 +29,21 @@ const carsSlice = createSlice({
initialState: carsInitialState,
extraReducers: builder => {
builder
.addCase(getFirstCarsThunk.fulfilled, (state, { payload }) => {
.addCase(getAllCarsThunk.fulfilled, (state, { payload }) => {
state.isLoading = false;
state.cars = payload;
state.allCars = payload;
const brands = payload?.map(car => car.make);
const uniqueBrands = brands.filter(
(brand, index, array) => array.indexOf(brand) === index
);
state.carsBrands = uniqueBrands;
state.error = null;
})
.addCase(getCarsThunk.fulfilled, (state, { payload }) => {
state.isLoading = false;
state.cars = payload;
state.cars = [...state.cars, ...payload];
state.error = null;
})
// .addCase(postContactThunk.fulfilled, (state, { payload }) => {
// state.isLoading = false;
// state.contacts = [...state.contacts, payload]
// state.error = null;
// state.isContactAdd = true;
// })
// .addCase(delContactThunk.fulfilled, (state, { payload }) => {
// state.isLoading = false;
// state.contacts = state.contacts.filter(contact => contact.id !== payload.id)
// state.error = null;
// })
.addMatcher(isAnyOf(...addStatusToActs('pending')), onPending)
.addMatcher(isAnyOf(...addStatusToActs('rejected')), onRejected)
}
Expand Down
56 changes: 11 additions & 45 deletions src/redux/cars/fetchCar.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,74 +3,40 @@ import { createAsyncThunk } from "@reduxjs/toolkit";
// import { Notify } from 'notiflix/build/notiflix-notify-aio';

axios.defaults.baseURL = 'https://64ecb723f9b2b70f2bfad3ff.mockapi.io';
// const url = new URL('https://PROJECT_TOKEN.mockapi.io/tasks');
// url.searchParams.append('completed', false); //https://PROJECT_TOKEN.mockapi.io/tasks?completed=false

export const LIMIT = 12;
// export const options = {
// width: '400px',
// position: 'center-center',
// timeout: 1500,
// fontSize: '20px',
// };

const getFirstCars = async (_, thunkAPI) => {
const getAllCars = async (_, thunkAPI) => {
try {
const response = await axios.get('/adverts?page=1&limit=12');
return response.data;
const response = await axios.get('/adverts');
return response.data;
}
catch (e) {
return thunkAPI.rejectWithValue(e.message);
}
};

const getCars = async (_, thunkAPI) => {
const getCars = async (page, thunkAPI) => {
try {
const response = await axios.get('/adverts');
return response.data;
const response = await axios.get(`/adverts?page=${page}&limit=${LIMIT}`);
return response.data;
}
catch (e) {
return thunkAPI.rejectWithValue(e.message);
}
};

// const postContact = async (newContact, thunkAPI) => {
// try {
// const response = await axios.post('/contacts', newContact);
// Notify.success(`Contact added successfully`, options);
// return response.data;
// }
// catch (e) {
// return thunkAPI.rejectWithValue(e.message);
// }
// };

// const delContact = async (contactId, thunkAPI) => {
// try {
// const response = await axios.delete(`/contacts/${contactId}`);
// Notify.warning(`Contact delete successfully`, options);
// return response.data;
// }
// catch (e) {
// return thunkAPI.rejectWithValue(e.message);
// }
// };

export const getCarsThunk = createAsyncThunk(
'cars/getCars',
getCars
);
export const getFirstCarsThunk = createAsyncThunk(
'cars/getFirstCars',
getFirstCars
);


// export const postContactThunk = createAsyncThunk(
// 'phoneBook/postContact',
// postContact
// );

// export const delContactThunk = createAsyncThunk(
// 'phoneBook/delContact',
// delContact
// );
export const getAllCarsThunk = createAsyncThunk(
'cars/getAllCars',
getAllCars
);
2 changes: 1 addition & 1 deletion src/redux/favoriteCarsSlice/favoriteCarsSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const favoriteCarsSlice = createSlice({
state.favorites.push(payload);
},
deleteFavoriteCar(state, { payload }) {
const index = state.favorites.findIndex(car => car === payload);
const index = state.favorites.findIndex(car => car.id === payload);
state.favorites.splice(index, 1);
}
},
Expand Down
2 changes: 2 additions & 0 deletions src/redux/selectors.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export const selectCars = state => state.cars.cars;
export const selectAllCars = state => state.cars.allCars;
export const selectCarBrands = state => state.cars.carsBrands;
export const selectIsLoading = state => state.cars.isLoading;
export const selectError = state => state.cars.error;
export const selectFavoriteCars = state => state.favoriteCars.favorites;
Expand Down

0 comments on commit 9944d9b

Please sign in to comment.