Skip to content

Commit

Permalink
Fix: 리스트 생성 리퀘스트에 imageUrl 빈문자열 추가로 오류 수정 및 에러 토스트, 생성 후 리스트 상세 이동 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
seoyoung-min committed Feb 6, 2024
1 parent 45fc940 commit a034b80
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 28 deletions.
5 changes: 3 additions & 2 deletions src/app/create/_components/CreateItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@ import * as styles from './CreateItem.css';
interface CreateItemProps {
onBackClick: () => void;
onSubmitClick: () => void;
isSubmitting: boolean;
}

export default function CreateItem({ onBackClick, onSubmitClick }: CreateItemProps) {
export default function CreateItem({ onBackClick, onSubmitClick, isSubmitting }: CreateItemProps) {
const {
formState: { isValid },
} = useFormContext();

return (
<div>
<Header onBackClick={onBackClick} isSubmitActive={isValid} onSubmitClick={onSubmitClick} />
<Header onBackClick={onBackClick} isSubmitActive={isValid && !isSubmitting} onSubmitClick={onSubmitClick} />
<div className={styles.article}>
<h3 className={styles.label}>
아이템 추가 <span className={styles.required}>*</span>
Expand Down
15 changes: 8 additions & 7 deletions src/app/create/_components/item/Items.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ export default function Items() {
{(provided) => (
<div className={styles.itemsContainer} ref={provided.innerRef} {...provided.droppableProps}>
{items.map((item, index) => {
const errorMessage = (field: 'title' | 'comment' | 'link' | 'image') =>
const errorMessage = (field: 'title' | 'comment' | 'link' | 'imageUrl') =>
(errors as FormErrors)?.items?.[index]?.[field]?.message;
const titleError = errorMessage('title');
const commentError = errorMessage('comment');
const linkError = errorMessage('link');
// const imageError = errorMessage('image');
// const imageError = errorMessage('imageUrl');
return (
<Draggable key={item.id} draggableId={item.id} index={index}>
{(provided, snapshot) => (
Expand Down Expand Up @@ -138,6 +138,7 @@ export default function Items() {
<div className={styles.linkModalChildren}>
<input
className={styles.linkInput}
type="url"
placeholder={itemPlaceholder.link}
autoComplete="off"
{...register(`items.${index}.link`, itemLinkRules)}
Expand All @@ -154,7 +155,7 @@ export default function Items() {
type="file"
accept=".jpg, .jpeg, .png"
id={`${index}-image`}
{...register(`items.${index}.image`)}
{...register(`items.${index}.imageUrl`)}
/>
}
linkPreview={
Expand All @@ -170,12 +171,12 @@ export default function Items() {
)
}
imagePreview={
watchItems[index]?.image && (
watchItems[index]?.imageUrl !== '' && (
<Preview
type="image"
imageFile={watchItems[index]?.image?.[0]}
imageFile={watchItems[index]?.imageUrl?.[0]}
handleClearButtonClick={() => {
setValue(`items.${index}.image`, '');
setValue(`items.${index}.imageUrl`, '');
}}
/>
)
Expand All @@ -195,7 +196,7 @@ export default function Items() {
title: '',
comment: '',
link: '',
image: null,
imageUrl: '',
})
}
/>
Expand Down
64 changes: 48 additions & 16 deletions src/app/create/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,20 @@ import { useState } from 'react';
import { FieldErrors, FormProvider, useForm } from 'react-hook-form';
import { useMutation } from '@tanstack/react-query';

import { ItemImagesType, ListCreateType } from '@/lib/types/listType';
import CreateItem from '@/app/create/_components/CreateItem';
import CreateList from '@/app/create/_components/CreateList';
import { ItemImagesType, ListCreateType } from '@/lib/types/listType';
import toasting from '@/lib/utils/toasting';
import { createList } from '../_api/list/createList';
import { uploadItemImages } from '../_api/list/uploadItemImages';
import { useRouter } from 'next/navigation';

export type FormErrors = FieldErrors<ListCreateType>;

export default function CreatePage() {
const [step, setStep] = useState<'list' | 'item'>('list');
const [newListId, setNewListId] = useState(0);
const router = useRouter();

const methods = useForm<ListCreateType>({
mode: 'onChange',
Expand All @@ -32,21 +36,21 @@ export default function CreatePage() {
title: '',
comment: '',
link: '',
image: null,
imageUrl: '',
},
{
rank: 0,
title: '',
comment: '',
link: '',
image: null,
imageUrl: '',
},
{
rank: 0,
title: '',
comment: '',
link: '',
image: null,
imageUrl: '',
},
],
},
Expand All @@ -66,44 +70,71 @@ export default function CreatePage() {
});

//데이터 쪼개기
const listData = {
const listData: ListCreateType = {
...originData,
items: originData.items.map(({ image, ...rest }) => rest),
items: originData.items.map(({ imageUrl, ...rest }) => {
return {
...rest,
imageUrl: '',
};
}),
};

const imageData: ItemImagesType = {
ownerId: originData.ownerId,
listId: 0, //temp
extensionRanks: originData.items
.map(({ rank, image }) => {
return { rank: rank, extension: image?.[0]?.type.split('/')[1] as 'jpg' | 'jpeg' | 'png' };
})
.filter(({ extension }) => extension !== null && extension !== undefined),
.filter(({ imageUrl }) => imageUrl !== '')
.map(({ rank, imageUrl }) => {
return {
rank: rank,
extension: imageUrl !== '' ? (imageUrl?.[0]?.type.split('/')[1] as 'jpg' | 'jpeg' | 'png') : '',
};
}),
};

const imageFileList: File[] = originData.items
.map(({ image }) => image?.[0] as File)
.filter((image) => image !== undefined);
.filter(({ imageUrl }) => imageUrl !== '')
.map(({ imageUrl }) => imageUrl?.[0] as File);

return { listData, imageData, imageFileList };
};

const saveImageMutation = useMutation({ mutationFn: uploadItemImages });
const {
mutate: saveImageMutate,
isPending: isUploadingImage,
isSuccess,
data: listId,
} = useMutation({
mutationFn: uploadItemImages,
retry: 3,
retryDelay: 1000,
onError: () => {
toasting({ type: 'error', txt: '이미지를 업로드 하는 중에 오류가 발생했어요. 다시 업로드해주세요.' });
},
onSettled: () => {
router.push(`/user/${formatData().listData.ownerId}/list/${newListId}`);
},
});

const createListMutation = useMutation({
const { mutate: createListMutate, isPending: isCreatingList } = useMutation({
mutationFn: createList,
onSuccess: (data) => {
saveImageMutation.mutate({
setNewListId(data.listId);
saveImageMutate({
listId: data.listId,
imageData: formatData().imageData,
imageFileList: formatData().imageFileList,
});
},
onError: () => {
toasting({ type: 'error', txt: '리스트 생성에 실패했어요. 다시 시도해주세요.' });
},
});

const handleSubmit = () => {
const { listData } = formatData();
createListMutation.mutate(listData);
createListMutate(listData);
};

return (
Expand All @@ -121,6 +152,7 @@ export default function CreatePage() {
handleStepChange('list');
}}
onSubmitClick={handleSubmit}
isSubmitting={isUploadingImage || isCreatingList || isSuccess}
/>
)}
</FormProvider>
Expand Down
3 changes: 3 additions & 0 deletions src/app/user/[userId]/list/[listId]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function ListPage() {
return <div>리스트페이지</div>;
}
4 changes: 2 additions & 2 deletions src/lib/types/listType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export interface ItemCreateType {
title: string;
comment: string | null;
link: string | null;
image?: FileList | null;
imageUrl: FileList | '';
}

// 리스트 생성 타입
Expand All @@ -27,7 +27,7 @@ export interface ListIdType {
// 이미지 생성 타입
export interface ItemImageType {
rank: number;
extension: 'jpg' | 'jpeg' | 'png';
extension: 'jpg' | 'jpeg' | 'png' | '';
}
export interface ItemImagesType {
ownerId: number;
Expand Down
7 changes: 6 additions & 1 deletion src/lib/utils/toasting.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { toast, ToastOptions } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

function toasting({ type = 'default', txt = '' }) {
interface ToastingProps {
type: 'default' | 'success' | 'error' | 'warning';
txt: string;
}

function toasting({ type = 'default', txt = '' }: ToastingProps) {
const toastOption: ToastOptions = {
position: 'bottom-center',
autoClose: 1000,
Expand Down

0 comments on commit a034b80

Please sign in to comment.