Skip to content

Commit

Permalink
feat: 모두의 정원 페이지 (#361)
Browse files Browse the repository at this point in the history
* chore: PetCard -> PetPlantCard 네이밍 변경

* chore: calendar URL 삭제

* chore: 모두의 정원 등록 페이지 URL 추가

* style: 간략화 및 옵션 정렬 변경

* chore: manageLevel 정보없음 포함

* feat: PageDataResponse 추가 및 api.ts로 파일 이름 변경

* chore: 이름 변경내용 적용

* chore: 사용하지 않는 타입 제거

* refactor: PageDataResponse 적용

* design: 날짜 너비 max-content 적용

* design: content 위치 수정

* chore: Image 컴포넌트 적용

* chore: z-index 제거

* feat: 모두의 정원 게시글 데이터 만드는 함수 추가

* feat: 모두의 정원 게시글 모의 API 구현

* feat: 모두의 정원 게시글 API 추가

* chore: 쿼리 key에 파라미터 활용

* design: DaySince, PostingDate에 grayDark적용

* chore: garden 라우팅 추가

* refactor: 길이를 받도록 변경

* refactor: onResultClick에서 id만 보내지 않고 id, name, img 보내도록 확장

* refactor: onResultClick 변경내용 적용

* feat: 검색 결과 리스트를 모달로 변경

* feat: 모두의 정원 게시글 데이터를 페이징으로 받는 커스텀 훅 구현

- useSuspenseInfiniteQuery 적용

* feat: 모두의 정원 페이지 구현

- 헤더에서 사전 식물 필터링 가능
- 무한스크롤로 다음 페이지 렌더링

* chore: Sensor width 제거

* feat: 모두의 정원 게시글 스켈레톤 구현

* feat: 다음 페이지 로딩시 스켈레톤 적용 및 마지막 페이지 표현

* refactor: Suspense 대신 로딩 상태로 스켈레톤 보여주도록 변경

* design: 정원 이름 폰트 크기 늘림

* chore: 페이지에서만 사용하는 파일, 컴포넌트 이동

* refactor: 모두의 정원 헤더 추출

* fix: 모달이 열렸을 때 z-index를 올려서 컨트롤 할 수 있도록 수정

* chore: 주석 제거

* feat: z-index에 dropdownBackdrop추가 및 적용

* chore: transient props 적용

* chore: Skeleton에 ket 적용

* chore: 이벤트 핸들링에 모달 닫기 추가

* chore: 컴포넌트 폴더 밖으로 이동

* fix: 입력값이 없을 때, 포커스해도 결과창이 열리지 않음

* chore: lazy loading 적용

* chore: useDictionaryPlantNavigate로 파일 이름 변경

* fix: 중복 필드 제거

* feat: Tag 영역 가로 스크롤링으로 변경

* style: && 대신 명시적으로 3항연산자 사용

* feat: SearchBox에서 height, fontSize 받을 수 있도록 수정

* design: 필터링 영역 디자인 수정

* feat: 모두의 정원 게시글 MSW 필터링 추가

* chore: 이모지 변경

* refactor: 모달 열기 검증을 함수 대신 상태로 변경

* design: 태그 갭 줄임

* refactor: SearchBox를 제어 컴포넌트로 변경 및 필터 제거 시 검색창 비움

* style: 정렬 순서 변경

* chore: type, aria-label 추가

* refactor: gardenHandler에 통합

* chore: GardenPostList import 추가

* feat: line-arrow-right

* feat: Navbar 대신 뒤로가기 헤더와 등록하기 버튼 추가

* chore: 쿼리 훅 폴더 이동

* feat: 필터링 된 모두의 정원으로 가기 추가

* design: 뒤로가기 헤더에 블러 배경 추가

* feat: 모두의 정원 글쓰기 버튼 추가

* design: height 제거

* chore: aria-label 추가

* feat: 로그인을 안하면 토스트 보여줌

* chore: onEnter가 있을 때 close

* feat: 토스트 보여주는 개수 제한

* chore: BottomSheet로 네이밍 변경

* test: 비로그인 리마인더 비활성화
  • Loading branch information
bassyu authored and hozzijeong committed Sep 20, 2023
1 parent 9d89299 commit 0d9d675
Show file tree
Hide file tree
Showing 48 changed files with 931 additions and 182 deletions.
8 changes: 4 additions & 4 deletions frontend/cypress/e2e/auth.cy.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import login from '../utils/login';

describe('비로그인 상태에서는 로그인 페이지로 이동한다.', () => {
it('리마인더', () => {
cy.visit('/reminder');
cy.get('#toast-root').contains('로그인 후 이용 가능').url().should('match', /login/);
});
// it('리마인더', () => {
// cy.visit('/reminder');
// cy.get('#toast-root').contains('로그인 후 이용 가능').url().should('match', /login/);
// });

it('내 반려 식물 목록', () => {
cy.visit('/pet');
Expand Down
14 changes: 13 additions & 1 deletion frontend/src/apis/garden.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
import type { DictionaryPlant } from 'types/dictionaryPlant';
import type { GardenRegisterForm } from 'types/garden';
import { BASE_URL } from 'constants/index';

export const GARDEN_URL = `${BASE_URL}/garden`;
export const GARDEN_URL = `${BASE_URL}/garden` as const;

const headers = {
'Content-Type': 'application/json',
};

const getList = (dictionaryPlantId: DictionaryPlant['id'] | null, page: number) => {
let url = `${GARDEN_URL}?page=${page}`;

if (dictionaryPlantId) {
url += `&dictionaryPlantId=${dictionaryPlantId}`;
}

return fetch(url);
};

const register = (form: GardenRegisterForm) => {
return fetch(GARDEN_URL, {
method: 'POST',
Expand All @@ -17,6 +28,7 @@ const register = (form: GardenRegisterForm) => {
};

const GardenAPI = {
getList,
register,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export const ContentBox = styled.div<{ $hiddenOver: boolean; $maxHeight: string

export const SeeMoreButtonArea = styled.div`
position: absolute;
z-index: ${(props) => props.theme.zIndex.fixed};
bottom: 0;
display: flex;
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/@common/SvgIcons/SvgFill/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const ICONS = [
'humidity',
'info-circle',
'line-arrow-left',
'line-arrow-right',
'manage-level-정보없음',
'manage-level-초보자',
'manage-level-경험자',
Expand Down
14 changes: 12 additions & 2 deletions frontend/src/components/@common/SvgIcons/SvgSpriteMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ const SvgIcons = () => (
<symbol id="line-arrow-left" viewBox="0 0 24 24">
<path d="M17.51 3.87L15.73 2.1L5.84 12l9.9 9.9l1.77-1.77L9.38 12l8.13-8.13z" />
</symbol>
<symbol id="line-arrow-right" viewBox="0 0 24 24">
<path d="M8.025 22L6.25 20.225L14.475 12L6.25 3.775L8.025 2l10 10l-10 10Z"></path>
</symbol>
<symbol id="manage-level-정보없음" viewBox="0 0 36 36">
<path d="M30 30h-8V4h8zm-6-2h4V6h-4zm-4 2h-8V12h8zm-6-2h4V14h-4zm-4 2H2V18h8zm-6-2h4v-8H4z"></path>
</symbol>
Expand All @@ -99,14 +102,12 @@ const SvgIcons = () => (
<symbol id="manage-level-전문가" viewBox="0 0 36 36">
<path d="M30 30h-8V4h8zm-10 0h-8V12h8zm-10 0H2V18h8z"></path>
</symbol>

<symbol viewBox="0 0 14 14" id="leaf">
<g fill="none" strokeLinecap="round" strokeLinejoin="round">
<path d="M11.51 5.38c2 2.82.47 6.05-.27 7.31a1.42 1.42 0 0 1-1 .66c-1.45.25-5.06.53-7-2.29C1.33 8.4 1.41 3.72 1.58 1.49A1.05 1.05 0 0 1 3 .55c2.15.62 6.63 2.17 8.51 4.83Z"></path>
<path d="M4.77 4.45a52.26 52.26 0 0 1 6 8.73"></path>
</g>
</symbol>

<symbol id="potted-plant" viewBox="0 0 24 24">
<path d="M8.55 22q-.7 0-1.225-.425t-.7-1.1L5.5 16h13l-1.125 4.475q-.175.675-.7 1.1T15.45 22h-6.9ZM12 8q0-2.5 1.75-4.25T18 2q0 2.25-1.425 3.9T13 7.9V10h8v3q0 .825-.588 1.413T19 15H5q-.825 0-1.413-.588T3 13v-3h8V7.9q-2.15-.35-3.575-2T6 2q2.5 0 4.25 1.75T12 8Z" />{' '}
</symbol>
Expand Down Expand Up @@ -182,6 +183,15 @@ const SvgIcons = () => (
<symbol viewBox="0 0 24 24" id="add-circle">
<path d="M11 13v3q0 .425.288.713T12 17q.425 0 .713-.288T13 16v-3h3q.425 0 .713-.288T17 12q0-.425-.288-.713T16 11h-3V8q0-.425-.288-.713T12 7q-.425 0-.713.288T11 8v3H8q-.425 0-.713.288T7 12q0 .425.288.713T8 13h3Zm1 9q-2.075 0-3.9-.788t-3.175-2.137q-1.35-1.35-2.137-3.175T2 12q0-2.075.788-3.9t2.137-3.175q1.35-1.35 3.175-2.137T12 2q2.075 0 3.9.788t3.175 2.137q1.35 1.35 2.138 3.175T22 12q0 2.075-.788 3.9t-2.137 3.175q-1.35 1.35-3.175 2.138T12 22Z"></path>
</symbol>
<symbol viewBox="0 0 24 24" id="plus">
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M5 12h7m7 0h-7m0 0V5m0 7v7"
></path>
</symbol>
</defs>
</Svg>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const ICONS = [
'bulletin-board-line',
'reminder',
'dictionary',
'plus',
] as const;

type IconIds = (typeof ICONS)[number];
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/components/@common/Toast/ToastList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import { ToastListWrapper } from './Toast.style';
import toasts from 'store/atoms/toasts';
import Toast from '.';

const SHOW_TOAST_SIZE = 5;

const ToastList = () => {
const toastList = useRecoilValue(toasts);
const toastList = useRecoilValue(toasts).slice(-SHOW_TOAST_SIZE);
const root = document.getElementById('toast-root') ?? document.body;

return createPortal(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,30 @@ export const HeaderBox = styled.section`
border-bottom: 1px solid ${(props) => props.theme.color.grayLight};
`;

export const Name = styled.p`
font: 900 2.4rem/4rem 'GmarketSans';
color: ${(props) => props.theme.color.sub};
text-align: left;
`;

export const FamilyName = styled.p`
margin-bottom: 4px;
font: 500 1.2rem/1.6rem 'GmarketSans';
color: ${(props) => props.theme.color.sub};
text-align: left;
`;

export const Name = styled.p`
font: 900 2.4rem/4rem 'GmarketSans';
export const GardenButton = styled.button`
display: flex;
column-gap: 4px;
align-items: center;
height: 24px;
margin-top: 16px;
font-size: 1.4rem;
font-weight: 600;
color: ${(props) => props.theme.color.sub};
text-align: left;
`;

export const ContentBox = styled.section`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
import { useNavigate } from 'react-router';
import { useSetRecoilState } from 'recoil';
import SeeMoreContentBox from 'components/@common/SeeMoreContentBox';
import SvgIcons from 'components/@common/SvgIcons/SvgFill';
import SvgFill from 'components/@common/SvgIcons/SvgFill';
import SvgStroke from 'components/@common/SvgIcons/SvgStroke';
import TagBox from 'components/dictionaryPlant/TagBox';
import TagSwitch from 'components/dictionaryPlant/TagSwitch';
import {
Accent,
ContentBox,
FamilyName,
GardenButton,
HeaderBox,
InformationTagBox,
ManageInfoBox,
Name,
PropBox,
PropsBox,
} from './DictionaryPlantContent.style';
import selectedDictionaryPlantAtom from 'store/atoms/garden';
import type { DictionaryPlantExtendCycles } from 'hooks/queries/dictionaryPlant/useDictionaryPlantDetail';
import parseTemperature from 'utils/parseTemperature';
import { NO_INFORMATION } from 'constants/index';
import { NO_INFORMATION, URL_PATH } from 'constants/index';
import theme from 'style/theme.style';

const DictionaryPlantContent = (props: DictionaryPlantExtendCycles) => {
const {
id,
postingPlace,
familyName,
name,
image,
manageLevel,
growSpeed,
requireHumidity,
Expand All @@ -34,6 +42,18 @@ const DictionaryPlantContent = (props: DictionaryPlantExtendCycles) => {
waterOptions,
} = props;

const setSelectedDictionaryPlant = useSetRecoilState(selectedDictionaryPlantAtom);
const navigate = useNavigate();

const goFilteredGarden = () => {
setSelectedDictionaryPlant({
id,
name,
image,
});
navigate(URL_PATH.garden);
};

const place = postingPlace.map((position, idx) => {
const text = position === NO_INFORMATION ? '제공된 정보가 없어요😢' : position;
return <TagBox.Content key={idx}>{text}</TagBox.Content>;
Expand All @@ -47,6 +67,15 @@ const DictionaryPlantContent = (props: DictionaryPlantExtendCycles) => {
<div>
<Name>{name}</Name>
<FamilyName>{familyName}</FamilyName>
<GardenButton type="button" onClick={goFilteredGarden} aria-label="모두의 정원">
<SvgStroke
color={theme.color.fontPrimaryForBackground}
size={16}
icon="bulletin-board-line"
/>
모두의 정원
<SvgFill color={theme.color.sub} size={12} icon="line-arrow-right" />
</GardenButton>
</div>
</HeaderBox>
<ContentBox>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import {
} from './Timeline.style';

interface SkeletonProps {
length: number;
hasYearHeader?: boolean;
}

const Skeleton = ({ hasYearHeader }: SkeletonProps) => (
const TimelineSkeleton = ({ length, hasYearHeader }: SkeletonProps) => (
<>
{hasYearHeader && <YearHeader />}
{Array(10)
{Array(length)
.fill(null)
.map((_, index) => (
<DayArea key={index}>
Expand All @@ -29,4 +30,4 @@ const Skeleton = ({ hasYearHeader }: SkeletonProps) => (
</>
);

export default Skeleton;
export default TimelineSkeleton;
5 changes: 3 additions & 2 deletions frontend/src/components/petPlant/Timeline/converter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { HistoryItem, HistoryResponse } from 'types/history';
import type { PageDataResponse } from 'types/api';
import type { HistoryItem } from 'types/history';

export interface TimelineItem {
type: HistoryItem['type'];
Expand All @@ -15,7 +16,7 @@ type MonthList = [string, DayList][];
export type YearList = [string, MonthList][];

export const convertHistoryResponseListToHistoryItemList = (
historyResponseList: HistoryResponse[]
historyResponseList: PageDataResponse<HistoryItem[]>[]
) =>
historyResponseList.reduce<HistoryItem[]>(
(accWaterDateList, page) => accWaterDateList.concat(page.data),
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/components/petPlant/Timeline/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import useIntersectionRef from 'hooks/useIntersectionRef';
import SproutSvg from 'assets/sprout.svg';
import SproutWebp from 'assets/sprout.webp';
import TimelineItemList from '../TimelineItemList';
import Skeleton from './Skeleton';
import TimelineSkeleton from './TimelineSkeleton';

interface TimelineProps {
petPlantId: PetPlantDetails['id'];
Expand Down Expand Up @@ -76,9 +76,9 @@ const Timeline = ({ petPlantId, filter }: TimelineProps) => {
</YearArea>
))
) : (
<Skeleton hasYearHeader />
<TimelineSkeleton length={10} hasYearHeader />
)}
{isFetchingNextPage ? <Skeleton /> : <Sensor ref={intersectionRef} />}
{isFetchingNextPage ? <TimelineSkeleton length={10} /> : <Sensor ref={intersectionRef} />}
{!hasNextPage && <Earth />}
</Wrapper>
);
Expand Down
Loading

0 comments on commit 0d9d675

Please sign in to comment.