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

Feature: 리스트 생성 Ver3.0 #273

Merged
merged 36 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4bcef1e
Refactor: ver3.0 리스트생성 폴더 생성 및 공용헤더 ver3.0 디자인 적용
seoyoung-min Sep 18, 2024
0c91ca5
Feat: 리스트생성 1단계 페이지 생성
seoyoung-min Oct 3, 2024
d8866ea
design: 리스트 생성 step1 디자인 입히기
seoyoung-min Oct 3, 2024
0762da4
Feat: step1 글자수세기 및 조건 검사 기능 추가
seoyoung-min Oct 25, 2024
07e8f00
refactor: 카테고리 유효성 검사 추가 및 오류 시 비활성 버튼 css 수정
seoyoung-min Oct 25, 2024
ce04ed2
design: 리스트 소개 textarea 스크롤바 없애기
seoyoung-min Oct 25, 2024
62ec505
refactor: 불필요 코드 삭제 및 todo 추가
seoyoung-min Oct 27, 2024
5cf192e
refactor: step 단계별 이동 리팩토링
seoyoung-min Oct 27, 2024
2065d1f
Chore: 아이콘 파일 추가
seoyoung-min Oct 27, 2024
f592860
Feat: 리스트생성 step2 아코디언, dnd 구현
seoyoung-min Oct 27, 2024
4c2d450
Design: 아이템 리스트 rank 사이즈 스타일 변경
seoyoung-min Oct 30, 2024
51de8b4
Feature: step3 헤더 삽입
seoyoung-min Oct 30, 2024
1205907
Fix: 중복 theme color 제거
seoyoung-min Oct 30, 2024
756eafd
Feat: step3 태그 기능 전체 구현
seoyoung-min Oct 30, 2024
482abf5
Feat: step3 배경색상 및 공개여부 기능 구현
seoyoung-min Nov 3, 2024
3a9978b
Feat: step2 이미지 업로드 기능 추가
seoyoung-min Nov 3, 2024
a985d2b
Feat: step2 링크 첨부 기능 추가
seoyoung-min Nov 10, 2024
2f8fc72
refactor: 라벨(태그) 에러처리에 개별 리액트훅폼 적용
seoyoung-min Nov 10, 2024
5413264
Fix: Step3 라벨 에러 재입력시 사라지도록 수정
seoyoung-min Nov 10, 2024
4162326
Fix: 헤더 컴포넌트 이전 코드로 돌아간 것 다시 복구
seoyoung-min Nov 10, 2024
13c7bbc
Refactor: 코드리뷰 반영(isComposing, chip이름 구체화, 카테고리 staleTime추가)
seoyoung-min Nov 10, 2024
4ca2c9d
Fix: 타입오류 해결
seoyoung-min Nov 10, 2024
76f25c2
Refactor: 리스트 수정 페이지 ver3.0 적용
seoyoung-min Nov 10, 2024
c51998d
Refactor: 이전 리스트 수정 페이지 삭제
seoyoung-min Nov 10, 2024
1143f19
Refactor: 이전 리스트 생성 페이지 삭제
seoyoung-min Nov 10, 2024
277ffd0
Fix: 색상명칭 변경 미적용건 수정
seoyoung-min Nov 10, 2024
8ce5d2a
Refactor: StepOne 불필요 코드 삭제, 타이틀 길이 및 카테고리 선택 스타일링 오류 개선(코드리뷰반영)
seoyoung-min Nov 17, 2024
7cd2729
Refactor: 아코디언 확장/축소 아이콘 범위 확대(코드리뷰반영)
seoyoung-min Nov 17, 2024
dd75857
Feature: 아이템 최소 갯수 3개가 안될 경우 다음으로 이동 불가 및 안내 메시지 노출
seoyoung-min Nov 18, 2024
cf581f2
Refactor: 드래그앤드롭 라이브러리 교체
seoyoung-min Nov 18, 2024
83a276e
Refactor: 태그 스페이스 등록 오류 해결
seoyoung-min Nov 18, 2024
f018cbb
Refactor: 태그 입력 방법에 콤마 추가
seoyoung-min Nov 18, 2024
18037b7
Feature: 선택배경색상 프리뷰 기능 추가
seoyoung-min Nov 18, 2024
0c103ec
Fix: 리액트 타입 패키지 재설치로 타입에러 해결
seoyoung-min Nov 18, 2024
6a1b58b
Refactor: react-beautiful-dnd 라이브러리 제거
seoyoung-min Nov 18, 2024
b24870f
Fix: 리스트 수정 타이틀 검사 타이밍 조정
seoyoung-min Nov 18, 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
11 changes: 5 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
},
"dependencies": {
"@egjs/react-grid": "^1.16.0",
"@hello-pangea/dnd": "^17.0.0",
"@mui/material": "^5.15.9",
"@next/third-parties": "^14.1.0",
"@tanstack/react-query": "^5.17.12",
Expand All @@ -45,11 +46,10 @@
"next": "14.0.4",
"next-pwa": "^5.6.0",
"open-graph": "^0.2.6",
"react": "^18",
"react": "^18.3.1",
"react-apexcharts": "^1.4.1",
"react-beautiful-dnd": "^13.1.1",
"react-cookie": "^7.0.2",
"react-dom": "^18",
"react-dom": "^18.3.1",
"react-hook-form": "^7.50.0",
"react-ios-pwa-prompt": "^1.8.4",
"react-lottie": "^1.2.4",
Expand All @@ -73,9 +73,8 @@
"@types/jest": "^29.5.11",
"@types/node": "^20",
"@types/open-graph": "^0.2.5",
"@types/react": "^18",
"@types/react-beautiful-dnd": "^13.1.8",
"@types/react-dom": "^18",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"eslint": "^8",
"eslint-config-next": "14.0.4",
"eslint-config-prettier": "^9.1.0",
Expand Down
2 changes: 1 addition & 1 deletion public/icons/add.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/icons/check_white.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/icons/close_button.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/icons/collapse.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion public/icons/dnd.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/icons/expand.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions public/icons/image.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion public/icons/link.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { ListDetailType } from '@/lib/types/listType';
import Header from '@/app/list/[listId]/_components/ListDetailInner/Header';
import RankList from '@/app/list/[listId]/_components/ListDetailInner/RankList';
import Footer from '@/app/list/[listId]/_components/ListDetailInner/Footer';
import { BACKGROUND_COLOR_PALETTE_TYPE, BACKGROUND_COLOR_READ } from '@/styles/Color';
import { BACKGROUND_COLOR_READ } from '@/styles/Color';

interface OptionsProps {
value: string;
Expand Down
183 changes: 100 additions & 83 deletions src/app/list/[listId]/edit/page.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,45 @@
'use client';

import { useEffect, useState } from 'react';
import { FieldErrors, FormProvider, useForm } from 'react-hook-form';
import { FormProvider, useForm } from 'react-hook-form';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useRouter, useParams } from 'next/navigation';
import { useParams, useRouter } from 'next/navigation';

import CreateItem from '@/app/list/create/_components/CreateItem';
import CreateList from '@/app/list/create/_components/CreateList';
import { ItemImagesType, ListCreateType, ListDetailType, ListEditType } from '@/lib/types/listType';
import { CategoryType } from '@/lib/types/categoriesType';
import { QUERY_KEYS } from '@/lib/constants/queryKeys';
import toasting from '@/lib/utils/toasting';
import toastMessage from '@/lib/constants/toastMessage';
import { useLanguage } from '@/store/useLanguage';
import { useUser } from '@/store/useUser';

import updateList from '@/app/_api/list/updateList';
import getListDetail from '@/app/_api/list/getListDetail';
import getCategories from '@/app/_api/category/getCategories';
import { QUERY_KEYS } from '@/lib/constants/queryKeys';
import { ItemImagesType, ListDetailType, ListEditType } from '@/lib/types/listType';
import { CategoryType } from '@/lib/types/categoriesType';
import { useUser } from '@/store/useUser';
import updateList from '@/app/_api/list/updateList';

export type FormErrors = FieldErrors<ListEditType>;
import StepOne from '@/app/list/create/_components/StepOne';
import StepThree from '@/app/list/create/_components/StepThree';
import StepTwo from '@/app/list/create/_components/StepTwo';

export default function EditPage() {
const router = useRouter();
const { user } = useUser();
const { language } = useLanguage();
const queryClient = useQueryClient();
const param = useParams<{ listId: string }>();
const { user } = useUser();

const [step, setStep] = useState<'list' | 'item'>('list');
/** step 관리 */
const [step, setStep] = useState(1);

const { data: listDetailData } = useQuery<ListDetailType>({
queryKey: [QUERY_KEYS.getListDetail, param?.listId],
queryFn: () => getListDetail(Number(param?.listId)),
});

const { data: categories } = useQuery<CategoryType[]>({
queryKey: [QUERY_KEYS.getCategories],
queryFn: () => getCategories(),
});
const handleNext = () => setStep((prev) => prev + 1);
const handleBack = () => setStep((prev) => prev - 1);

const methods = useForm<ListEditType>({
/** React Hook Form */
//-- 초기세팅
const methods = useForm<ListCreateType>({
mode: 'onChange',
defaultValues: {
category: 'culture',
category: '',
labels: [],
collaboratorIds: [],
title: '',
Expand All @@ -51,8 +51,47 @@ export default function EditPage() {
},
});

//request용 데이터 만드는 함수.
//--- 기존 데이터 불러오기
//기존 리스트 데이터
const { data: listDetailData } = useQuery<ListDetailType>({
queryKey: [QUERY_KEYS.getListDetail, param?.listId],
queryFn: () => getListDetail(Number(param?.listId)),
});

// 카테고리 목록
const { data: categories } = useQuery<CategoryType[]>({
queryKey: [QUERY_KEYS.getCategories],
queryFn: () => getCategories(),
});

//데이터 채워넣기
useEffect(() => {
if (listDetailData) {
methods.reset({
category: categories?.find((category) => category.korName === listDetailData.categoryKorName)?.engName,
labels: listDetailData.labels.map((obj) => obj.name),
collaboratorIds: listDetailData.collaborators.filter((c) => c.id !== user.id).map((c) => c.id),
title: listDetailData.title,
description: listDetailData.description,
isPublic: listDetailData.isPublic,
backgroundPalette: listDetailData.backgroundPalette,
backgroundColor: listDetailData.backgroundColor,
items: listDetailData.items.map(({ id, rank, title, comment, link, imageUrl }) => {
return {
rank: rank,
id: id,
title: title,
comment: comment ? comment : '',
link: link ? link : '',
imageUrl: typeof imageUrl === 'string' ? imageUrl : '',
};
}),
});
}
}, [listDetailData, categories, methods]);

/** Request 보내기 */
//--- 포맷 맞추기
const formatData = () => {
const originData = methods.getValues();

Expand Down Expand Up @@ -80,6 +119,7 @@ export default function EditPage() {
}),
};

//이미지rank,extension & 이미지파일 배열
const imageData: ItemImagesType = {
listId: Number(param?.listId),
extensionRanks: originData.items
Expand All @@ -100,46 +140,16 @@ export default function EditPage() {
return { listData, imageData, imageFileList };
};

const handleStepChange = (step: 'list' | 'item') => {
setStep(step);
//--아이템 중복 확인
const getIsAllUnique = () => {
const allTitles = methods.getValues().items.map((item, itemIndex) => {
return item.title === '' ? itemIndex : item.title;
}); //TODO: 필요한 코드인지 다시 확인하기
const isAllUnique = new Set(allTitles).size === allTitles.length;
return isAllUnique;
};

const handleSubmit = () => {
const { listData, imageData, imageFileList } = formatData();
const updateData = {
listId: Number(param?.listId) || 0,
listData: listData,
imageData: imageData,
imageFileList: imageFileList,
};
updateListMutation(updateData);
};

useEffect(() => {
if (listDetailData) {
methods.reset({
category: categories?.find((c) => c.korName === listDetailData.categoryKorName)?.engName || 'culture',
labels: listDetailData.labels.map((obj) => obj.name),
collaboratorIds: listDetailData.collaborators.filter((c) => c.id !== user.id).map((c) => c.id),
title: listDetailData.title,
description: listDetailData.description,
isPublic: listDetailData.isPublic,
backgroundPalette: listDetailData.backgroundPalette,
backgroundColor: listDetailData.backgroundColor,
items: listDetailData.items.map(({ id, rank, title, comment, link, imageUrl }) => {
return {
rank: rank,
id: id,
title: title,
comment: comment ? comment : '',
link: link ? link : '',
imageUrl: typeof imageUrl === 'string' ? imageUrl : '',
};
}),
});
}
}, [listDetailData, categories, methods]);

//--- 리스트 수정하기
const {
mutate: updateListMutation,
isPending: isUpdatingList,
Expand All @@ -154,27 +164,34 @@ export default function EditPage() {
},
});

//--- 제출
const handleSubmit = () => {
if (getIsAllUnique()) {
const { listData, imageData, imageFileList } = formatData();
const updateData = {
listId: Number(param?.listId) || 0,
listData: listData,
imageData: imageData,
imageFileList: imageFileList,
};
updateListMutation(updateData);
} else {
toasting({ type: 'error', txt: toastMessage[language].duplicatedItemError });
}
};

return (
<>
<FormProvider {...methods}>
{step === 'list' ? (
<CreateList
onNextClick={() => {
handleStepChange('item');
}}
type="edit"
/>
) : (
<CreateItem
onBackClick={() => {
handleStepChange('list');
}}
onSubmitClick={handleSubmit}
isSubmitting={isUpdatingList || isSuccess}
type="edit"
/>
)}
</FormProvider>
</>
<FormProvider {...methods}>
{step === 1 && <StepOne onNextClick={handleNext} type="edit" />}
{step === 2 && <StepTwo onBeforeClick={handleBack} onNextClick={handleNext} type="edit" />}
{step === 3 && (
<StepThree
onBeforeClick={handleBack}
onNextClick={handleSubmit}
isSubmitting={isUpdatingList || isSuccess}
type="edit"
/>
)}
</FormProvider>
);
}
32 changes: 0 additions & 32 deletions src/app/list/create/_components/CreateItem.css.ts

This file was deleted.

Loading