Skip to content

Commit

Permalink
Merge pull request #242 from Lapkipomoshi/dev-shelter-pets-page
Browse files Browse the repository at this point in the history
ShelterPetsPage
  • Loading branch information
karlbelousov committed Jun 7, 2024
2 parents 810bc90 + c4e7602 commit 889ef5e
Show file tree
Hide file tree
Showing 14 changed files with 406 additions and 14 deletions.
4 changes: 2 additions & 2 deletions src/components/PetCard/PetCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import maleIcon from '../../images/icons/ic_male.svg';
import femaleIcon from '../../images/icons/ic_female.svg';

const PetCard = ({
id, shelterId, name, age, sex, gallery,
name, age, sex, gallery, link
}) => {
return (
<Link
className='pet-card'
to={`/shelters/${shelterId}/pets/${id}`}
to={link}
>
<img className='pet-card__photo' src={gallery[0].image} alt={name} />
<div className='pet-card__cover' />
Expand Down
3 changes: 3 additions & 0 deletions src/images/check.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 src/modules/PetModule/styles/pet-module.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.pet-module {
display: flex;
width: 1440px;
width: 100%;

&__pet-part {
display: flex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import ShelterMetricsOverview from '../../components/ShelterMetricsOverview/Shel

const ShelterOwnerStatistics = ({ shelter }) => {
const metrics = [
{ title: 'Количество питомцев: ', valueKey: shelter.count_pets, actionText: 'Посмотреть всех питомцев', path: '/' },
{ title: 'Количество питомцев: ',
valueKey: shelter.count_pets,
actionText: 'Посмотреть всех питомцев',
path: `/profile/my-shelter/${shelter.id}/all-pets` },
{ title: 'Количество вакансий: ', valueKey: shelter.count_vacancies, actionText: 'Посмотреть все вакансии', path: `/shelters/${shelter.id}/vacancies` },
{ title: 'Количество тегов: ', valueKey: shelter.count_pets, actionText: 'Посмотреть все теги', path: '/' },
{ title: 'Количество новостей: ', valueKey: shelter.count_news, actionText: 'Посмотреть новости приюта', path: `/shelters/${shelter.id}/news` },
Expand Down
160 changes: 160 additions & 0 deletions src/modules/ShelterPetsType/ShelterPetsType.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import shelterPetsApi from './api';
import './ShelterPetsType.scss';
import PetCard from '../../components/PetCard/PetCard';
import { Button } from '../../ui';
import DeleteIcon from '../../images/DeleteIcon/DeleteIcon';

const ShelterPetsType = ({ type }) => {
const { id } = useParams();
const [pets, setPets] = useState([]);
const [isChecked, setIsChecked] = useState(false);
const [isSelected, setIsSelected] = useState(false);
const [checkedId, setCheckedId] = useState([]);

useEffect(() => {
shelterPetsApi
.getPetsByShelterId(id, type, 24, 0)
.then((res) => {
setPets(res.results);
})
.catch((err) => {
throw new Error(err);
});
}, []);

let petType;
switch (type.toLowerCase()) {
case 'cat':
petType = 'Кошки';
break;
case 'dog':
petType = 'Собаки';
break;
case 'parrot':
petType = 'Попугаи';
break;
case 'hamster':
petType = 'Хомяки';
break;
default:
petType = '';
}
const handleButtonSelectedClick = () => {
setIsSelected(true);
};
const handleButtonCancelSelectedClick = () => {
setIsSelected(false);
setCheckedId([]);
};
const handleButtonSelectedAllClick = () => {
setIsSelected(true);
setIsChecked(true);
setCheckedId((items) => {
return [...items, ...pets];
});
};
const handleButtonCancelSelectedAllClick = () => {
setIsSelected(false);
setIsChecked(false);
setCheckedId([]);
};
const handleChangePet = (pet) => {
if (!checkedId.includes(pet)) {
setCheckedId((items) => {
return [...items, pet];
});
} else {
setCheckedId (
checkedId.filter((petsId) => {
return !(petsId === pet);
})
);
}
};

return (
<div className='shelter-pets-type'>
<div className='shelter-pets-type__header'>
<h2 className='shelter-pets-type__title'>{petType}</h2>
<div className='shelter-pets-type__controls'>
{checkedId.length !== 0 ? (
<Button theme='tertiary' className='shelter-pets-type__btn-deleted'>
<DeleteIcon />
Удалить
</Button>
) : null}
{pets.length !== 0 ? (
<>
{!isSelected && !isChecked && <Button
theme='tertiary'
className='shelter-pets-type__btn-selected'
onClick={handleButtonSelectedClick}
>
Выбрать
</Button>}
{isSelected && !isChecked && <Button
theme='tertiary'
className='shelter-pets-type__btn-cancel-selected'
onClick={handleButtonCancelSelectedClick}
>
Отменить выбор
</Button>}
{!isChecked && <Button
theme='tertiary'
className='shelter-pets-type__btn-selected'
onClick={handleButtonSelectedAllClick}
>
Выбрать все
</Button>}
{isChecked && <Button
theme='tertiary'
className='shelter-pets-type__btn-cancel-selected'
onClick={handleButtonCancelSelectedAllClick}
>
Отменить выбор
</Button>}
</>
) : (
<Button
theme='tertiary'
>
Удалить
</Button>
)
}
</div>
</div>
{pets.length !== 0 ? (
<ul className='shelter-pets-type__list'>
{pets.map((pet) => {
const isCheckedPet = checkedId.includes(pet);
const className = `${isSelected ? 'shelter-pets-type__input_selected' : ''} ${isCheckedPet ? 'shelter-pets-type__input_checked' : ''}`;
return (
<li className='shelter-pets-type__list-item' key={pet.id}>
<input
className={`shelter-pets-type__input ${className}`}
type='checkbox'
onChange={() => {
handleChangePet(pet);
}}
/>
<PetCard
link={!isSelected ? `../${id}/pets/${pet.id}` : ''}
id={pet.id}
name={pet.name}
age={pet.age}
sex={pet.sex}
gallery={pet.gallery}
/>
</li>
);
})}
</ul>
) : null}
</div>
);
};

export default ShelterPetsType;
111 changes: 111 additions & 0 deletions src/modules/ShelterPetsType/ShelterPetsType.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
.shelter-pets-type {
width: 100%;
margin-bottom: 40px;
}

.shelter-pets-type__header {
display: flex;
justify-content: space-between;
align-items: center;
}

.shelter-pets-type__controls {
width: 646px;
display: flex;
justify-content: flex-end;
align-items: center;
gap: 0 24px;
}

.shelter-pets-type__btn-deleted {
margin-right: auto;
display: flex;
align-items: center;
gap: 0 8px;
color: var(--color-verify-invalid);

svg {
height: 28px;
}
}

.shelter-pets-type__btn-cancel-selected {
position: relative;

&::before {
position: absolute;
content: '';
left: -20px;
top: 4px;
width: 12px;
height: 12px;
border-radius: 50%;
background-color: var(--color-accent-base);
}
}

.shelter-pets-type__title {
font-size: 40px;
line-height: 49px;
font-weight: 600;
margin: 0;
}

.shelter-pets-type__list {
display: flex;
flex-wrap: wrap;
gap: 24px;
margin: 0;
margin-top: 36px;
padding: 0;
list-style-type: none;
}

.shelter-pets-type__list-item {
position: relative;
}

.shelter-pets-type__input {
display: none;
position: absolute;
top: 16px;
right: 16px;
width: 20px;
height: 20px;

&::before {
position: absolute;
content: '';
width: 20px;
height: 20px;
background-color: var(--color-background-additional);
opacity: 0;
z-index: 10;
}

&::after {
position: absolute;
content: '';
width: 20px;
height: 20px;
background-color: var(--color-accent-base);
background-image: url('../../images/check.svg');
background-position: center;
opacity: 0;
z-index: 15;
}
}

.shelter-pets-type__input_selected {
display: block;

&::before {
opacity: 1;
}
}

.shelter-pets-type__input_checked {
&::after {
opacity: 1;
}
}
25 changes: 25 additions & 0 deletions src/modules/ShelterPetsType/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import BaseApi from '../../utils/BaseApi';
import { baseUrl, apiHeaders } from '../../utils/constants';

class ShelterPetsApi extends BaseApi {
constructor({ _baseUrl, _headers }) {
super({ _baseUrl });
this._headers = _headers;
}

getPetsByShelterId(shelterId, animalType, limit, offset) { // offset - начиная с какого питомца по счёту
return fetch(`${this._baseUrl}/v1/shelters/${shelterId}/pets/?animal_type=${animalType}&limit=${limit}&offset=${offset}`, {
headers: this._headers,
})
.then((res) => {
return super._processTheResponse(res);
});
}
}

const shelterPetsApi = new ShelterPetsApi({
_baseUrl: baseUrl,
_headers: apiHeaders,
});

export default shelterPetsApi;
2 changes: 1 addition & 1 deletion src/modules/ShelterSamePets/ShelterSamePets.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const ShelterSamePets = () => {
{pets.map((card) => {
return (
<li className='shelter-same-pets__pets-item' key={card.id}>
<PetCard id={card.id} shelterId={card.shelter} name={card.name} age={card.age} sex={card.sex} gallery={card.gallery} />
<PetCard link={`/shelters/${card.shelter}/pets/${card.id}`} name={card.name} age={card.age} sex={card.sex} gallery={card.gallery} />
</li>
);
})}
Expand Down
4 changes: 3 additions & 1 deletion src/pages/App/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import MyShelterPage from '../MyShelterPage/MyShelterPage';
import MyShelterEdit from '../../modules/MySheelterEdit/MyShelterEdit';
import AddNewsPage from '../AddNewsPage/AddNewsPage';
import ConfirmPopup from '../../components/ConfirmPopup/ConfirmPopup';

import ShelterPetsPage from '../ShelterPetsPage/ShelterPetsPage';

const App = () => {
const navigate = useNavigate();
Expand Down Expand Up @@ -223,6 +223,8 @@ const App = () => {
<Route path='/profile/my-shelter' element={<ProtectedRoute condition={loggedIn} component={MyShelterPage} />}>
<Route index element={<ProtectedRoute condition={loggedIn} component={shelterModules.AboutShelter} />} />
<Route path='edit' element={<ProtectedRoute condition={loggedIn} component={MyShelterEdit} />} />
<Route path=':id/all-pets' element={<ProtectedRoute condition={loggedIn} component={ShelterPetsPage} />} />
<Route path=':id/pets/:petId' element={<ProtectedRoute condition={loggedIn} component={shelterModules.PetModule} />} />
</Route>
<Route path='/profile/edit' element={<ProtectedRoute condition={loggedIn} component={EditProfilePage} onUpdateCurrentUser={setCurrentUser} />} />
<Route path='/profile/sign-out' element={<ProtectedRoute condition={loggedIn} component={SignOutPage} onSignOut={handleSignOut} />} />
Expand Down
13 changes: 9 additions & 4 deletions src/pages/MyShelterPage/MyShelterPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,26 @@ import CurrentUserContext from '../../contexts/CurrentUserContext';
const MyShelterPage = () => {
const curentUser = useContext(CurrentUserContext);
const mySheltersId = curentUser.own_shelter.id;
const [shelter, setShelter] = useState({});
const [shelter, setShelter] = useState({});
const isOwner = true;
const [isLoading, setIsLoading] = useState(true);

const location = useLocation();
const contentText = {
GO_TO_BACK: 'Вернуться назад',
BACK_TO_PROFILE: 'Вернуться в Личный Кабинет',
GO_TO_SHELTER: 'Вернуться к приюту'
};
let linkTo;

let linkTo;
let linkText;
if (location.pathname.includes('edit')) {
if (location.pathname.includes('edit') || location.pathname.includes('pets')) {
linkTo = -1;
linkText = contentText.GO_TO_BACK;
}
else if(location.pathname.includes('all-pets')) {
linkTo = -1;
linkText = contentText.GO_TO_SHELTER;
} else {
linkTo = '/profile';
linkText = contentText.BACK_TO_PROFILE;
Expand Down
Loading

0 comments on commit 889ef5e

Please sign in to comment.