From a97b0205fe30aef439200f0f5cb74bfdbe50d505 Mon Sep 17 00:00:00 2001 From: yerim Date: Sun, 31 Mar 2024 18:34:56 +0900 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=ED=8F=B4=EB=8D=94=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EC=88=98=EC=A0=95=20Toast=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../saves/[folderId]/_component/SaveFolderHeader.tsx | 9 +++++++++ .../saves/_component/MoChangeFolderNameModal.tsx | 7 +++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/app/(route)/(withLayout)/saves/[folderId]/_component/SaveFolderHeader.tsx b/src/app/(route)/(withLayout)/saves/[folderId]/_component/SaveFolderHeader.tsx index a3e3243f..9e1f3043 100644 --- a/src/app/(route)/(withLayout)/saves/[folderId]/_component/SaveFolderHeader.tsx +++ b/src/app/(route)/(withLayout)/saves/[folderId]/_component/SaveFolderHeader.tsx @@ -8,6 +8,7 @@ import useDeleteSave from '@/app/_hook/api/saves/useDeleteSave' import { useChangeSaveFolderName } from '@/app/_hook/api/saves/useChangeSaveFolderName' import { useSetRecoilState } from 'recoil' import { saveModeState } from '@/app/_atoms/saveModeState' +import renderToast from '@/app/_utils/toast' /** * 찜 폴더 내부 페이지 Header @@ -121,6 +122,14 @@ export namespace SaveFolderHeader { const setMode = useSetRecoilState(saveModeState) const handleChangeName = useCallback(async () => { + if (newFolderName.length > 20 || newFolderName.length === 0) { + renderToast({ + type: 'error', + message: '1-20자로 설정해주세요.', + }) + return + } + await changeName({ folderId, folderName: newFolderName }) router.replace(`/saves/${folderId}?name=${newFolderName}`) setMode(SavePageMode.DEFAULT) diff --git a/src/app/(route)/(withLayout)/saves/_component/MoChangeFolderNameModal.tsx b/src/app/(route)/(withLayout)/saves/_component/MoChangeFolderNameModal.tsx index d9467ca3..b3a8e93f 100644 --- a/src/app/(route)/(withLayout)/saves/_component/MoChangeFolderNameModal.tsx +++ b/src/app/(route)/(withLayout)/saves/_component/MoChangeFolderNameModal.tsx @@ -21,8 +21,11 @@ export default function MoChangeFolderNameModal(props: Props) { const router = useRouter() const handleChangeName = useCallback(async () => { - if (!newFolderName) { - renderToast({ type: 'error', message: '폴더 이름을 입력해주세요.' }) + if (newFolderName.length > 20 || newFolderName.length === 0) { + renderToast({ + type: 'error', + message: '1-20자로 설정해주세요.', + }) return } From 29161a080305531469d188a44ae723fa6e0b617f Mon Sep 17 00:00:00 2001 From: yerim Date: Sun, 31 Mar 2024 18:50:45 +0900 Subject: [PATCH 2/5] =?UTF-8?q?fix:=20=EB=AA=A9=EB=A1=9D=ED=8E=B8=EC=A7=91?= =?UTF-8?q?=20=EB=AA=A8=EB=93=9C=20=EC=9C=A0=EC=A7=80=EB=90=98=EB=8A=94=20?= =?UTF-8?q?=ED=98=84=EC=83=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../saves/_component/SaveComponent.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/app/(route)/(withLayout)/saves/_component/SaveComponent.tsx b/src/app/(route)/(withLayout)/saves/_component/SaveComponent.tsx index 208fdafa..181ff702 100644 --- a/src/app/(route)/(withLayout)/saves/_component/SaveComponent.tsx +++ b/src/app/(route)/(withLayout)/saves/_component/SaveComponent.tsx @@ -1,9 +1,11 @@ 'use client' -import React, { useState } from 'react' -import { SaveFolderType } from '@/app/_types/save.type' +import React, { useEffect, useState } from 'react' +import { SaveFolderType, SavePageMode } from '@/app/_types/save.type' import useSaveList from '@/app/_hook/api/saves/useSavesList' import { cn } from '@/app/_utils/twMerge' +import { useSetRecoilState } from 'recoil' +import { saveModeState } from '@/app/_atoms/saveModeState' import { SaveHeader } from './SaveHeader' import SaveList from './SaveList' @@ -11,9 +13,17 @@ import AddFolderModal from './AddFolderModal' export default function SaveComponent() { const [showAddFolderModal, setShowAddFolderModal] = useState(false) + const setMode = useSetRecoilState(saveModeState) const { saveInfo, isLoading, isError } = useSaveList('all') + useEffect( + function resetMode() { + setMode(SavePageMode.DEFAULT) + }, + [setMode], + ) + if (isLoading) return
...loading
if (isError) return null From 1004a9be16b5f3b27917c43eae592e3ed92a02f7 Mon Sep 17 00:00:00 2001 From: yerim Date: Mon, 1 Apr 2024 13:52:02 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=EB=AA=A8=EB=B0=94=EC=9D=BC?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=B0=9C=20=ED=8F=B4=EB=8D=94=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EB=AA=A8=EB=8B=AC=EC=97=90=20=EB=93=9C=EB=9E=98?= =?UTF-8?q?=EA=B7=B8=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../saves/_component/MoveFolderModal.tsx | 234 +++++++++++------- 1 file changed, 141 insertions(+), 93 deletions(-) diff --git a/src/app/(route)/(withLayout)/saves/_component/MoveFolderModal.tsx b/src/app/(route)/(withLayout)/saves/_component/MoveFolderModal.tsx index 823bc0cb..e0dec4ab 100644 --- a/src/app/(route)/(withLayout)/saves/_component/MoveFolderModal.tsx +++ b/src/app/(route)/(withLayout)/saves/_component/MoveFolderModal.tsx @@ -1,5 +1,4 @@ import { saveModeState } from '@/app/_atoms/saveModeState' -import Modal from '@/app/_components/modal' import useMoveSaveItems, { MoveSaveItemsRequest, } from '@/app/_hook/api/saves/useMoveSaveItems' @@ -8,7 +7,7 @@ import { SaveFolderType, SavePageMode } from '@/app/_types/save.type' import renderToast from '@/app/_utils/toast' import { cn } from '@/app/_utils/twMerge' import Image from 'next/image' -import React, { useCallback, useState } from 'react' +import React, { useCallback, useEffect, useRef, useState } from 'react' import { useSetRecoilState } from 'recoil' interface Props { @@ -26,11 +25,47 @@ export default function MoveFolderModal(props: Props) { setShowMoveFolderModal, setShowAddFolderModal, } = props + const [selectFolderId, setSelectFolderId] = useState(null) const { saveInfo, isLoading, isError } = useSaveList('folder') const { mutateAsync: moveItems } = useMoveSaveItems() const setMode = useSetRecoilState(saveModeState) + const [startY, setStartY] = useState(0) + const [moveY, setMoveY] = useState(0) + const [endY, setEndY] = useState(0) + + const ref: any = useRef(null) + + const onTouchStart = (e: TouchEvent) => { + setStartY(e.touches[0].clientY) + } + + const onTouchMove = (e: TouchEvent) => { + setMoveY(e.targetTouches[0].clientY) + } + + const onTouchEnd = (e: TouchEvent) => { + setEndY(e.changedTouches[0].clientY) + } + + useEffect(() => { + ref.current?.addEventListener('touchstart', onTouchStart) + ref.current?.addEventListener('touchmove', onTouchMove) + ref.current?.addEventListener('touchend', onTouchEnd) + return () => { + ref.current?.removeEventListener('touchstart', onTouchStart) + ref.current?.removeEventListener('touchmove', onTouchMove) + ref.current?.removeEventListener('touchend', onTouchEnd) + } + }, [onTouchEnd, onTouchMove, onTouchStart, ref]) + + useEffect(() => { + if (endY - startY > 50) { + setShowMoveFolderModal(false) + } + }, [endY, startY, setShowMoveFolderModal]) + const handleMoveItems = useCallback(async () => { if (!selectFolderId) return if (currentFolderId === selectFolderId) { @@ -63,107 +98,120 @@ export default function MoveFolderModal(props: Props) { const folderList = saveInfo.favoriteInfos as SaveFolderType[] return ( - +
e.stopPropagation()} > - {/*
-
-

- 폴더 이동 -

-
*/} -
- {/* 닫기 버튼 */} - - - {/* 타이틀 */} -

폴더 이동

-
- {/* 폴더 목록 */} -
- {folderList.map((item) => { - const { favoriteId, originalName, metadata } = item - const { imageUrls } = metadata.folderMetadata - return ( -
{ - if (selectFolderId === favoriteId) setSelectFolderId(null) - else setSelectFolderId(favoriteId) - }} - className={cn( - 'flex cursor-pointer items-center gap-[16px] p-[12px_18px]', - { - 'bg-[#F1F1F1]': selectFolderId === favoriteId, - 'bg-white': selectFolderId !== favoriteId, - }, - )} - > +
+
+

+ 폴더 이동 +

+
+
+ {/* 닫기 버튼 */} + + + {/* 타이틀 */} +

폴더 이동

+
+ {/* 폴더 목록 */} +
+ {folderList.map((item) => { + const { favoriteId, originalName, metadata } = item + const { imageUrls } = metadata.folderMetadata + return (
0 ? `url('${imageUrls[0]}')` : '', + key={favoriteId} + onClick={() => { + if (selectFolderId === favoriteId) setSelectFolderId(null) + else setSelectFolderId(favoriteId) }} - className="h-[52px] w-[52px] rounded-[4px] bg-[#dadada] bg-contain bg-center bg-no-repeat" - /> -
{originalName}
-
- ) - })} -
- - {/* 하단 버튼 */} -
- -
+ + {/* 하단 버튼 */} +
- 이동하기 - -
+ + +
+
- +
) } From ae2c2af14ce77660aa24364381637b0813462d24 Mon Sep 17 00:00:00 2001 From: yerim Date: Mon, 1 Apr 2024 14:00:10 +0900 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20=EC=B0=9C=20=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20validation=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../[folderId]/_component/SaveFolderHeader.tsx | 9 ++------- .../saves/_component/AddFolderModal.tsx | 4 ++++ .../_component/MoChangeFolderNameModal.tsx | 9 ++------- .../(withLayout)/saves/_utils/validation.ts | 17 +++++++++++++++++ 4 files changed, 25 insertions(+), 14 deletions(-) create mode 100644 src/app/(route)/(withLayout)/saves/_utils/validation.ts diff --git a/src/app/(route)/(withLayout)/saves/[folderId]/_component/SaveFolderHeader.tsx b/src/app/(route)/(withLayout)/saves/[folderId]/_component/SaveFolderHeader.tsx index 9e1f3043..fb9a7003 100644 --- a/src/app/(route)/(withLayout)/saves/[folderId]/_component/SaveFolderHeader.tsx +++ b/src/app/(route)/(withLayout)/saves/[folderId]/_component/SaveFolderHeader.tsx @@ -9,6 +9,7 @@ import { useChangeSaveFolderName } from '@/app/_hook/api/saves/useChangeSaveFold import { useSetRecoilState } from 'recoil' import { saveModeState } from '@/app/_atoms/saveModeState' import renderToast from '@/app/_utils/toast' +import { validateSaveFolderName } from '../../_utils/validation' /** * 찜 폴더 내부 페이지 Header @@ -122,13 +123,7 @@ export namespace SaveFolderHeader { const setMode = useSetRecoilState(saveModeState) const handleChangeName = useCallback(async () => { - if (newFolderName.length > 20 || newFolderName.length === 0) { - renderToast({ - type: 'error', - message: '1-20자로 설정해주세요.', - }) - return - } + if (!validateSaveFolderName(newFolderName)) return await changeName({ folderId, folderName: newFolderName }) router.replace(`/saves/${folderId}?name=${newFolderName}`) diff --git a/src/app/(route)/(withLayout)/saves/_component/AddFolderModal.tsx b/src/app/(route)/(withLayout)/saves/_component/AddFolderModal.tsx index ad426af2..1d5eb599 100644 --- a/src/app/(route)/(withLayout)/saves/_component/AddFolderModal.tsx +++ b/src/app/(route)/(withLayout)/saves/_component/AddFolderModal.tsx @@ -1,8 +1,10 @@ import Modal from '@/app/_components/modal' import useAddSaveFolder from '@/app/_hook/api/saves/useAddSaveFolder' +import renderToast from '@/app/_utils/toast' import { cn } from '@/app/_utils/twMerge' import Image from 'next/image' import React, { useCallback, useState } from 'react' +import { validateSaveFolderName } from '../_utils/validation' interface Props { setShowAddFolderModal: React.Dispatch> @@ -14,6 +16,8 @@ export default function AddFolderModal({ setShowAddFolderModal }: Props) { const { mutateAsync: addFolder } = useAddSaveFolder() const handleAddFolder = useCallback(async () => { + if (!validateSaveFolderName(folderName)) return + await addFolder(folderName) setShowAddFolderModal(false) }, [folderName, setShowAddFolderModal, addFolder]) diff --git a/src/app/(route)/(withLayout)/saves/_component/MoChangeFolderNameModal.tsx b/src/app/(route)/(withLayout)/saves/_component/MoChangeFolderNameModal.tsx index b3a8e93f..b609e670 100644 --- a/src/app/(route)/(withLayout)/saves/_component/MoChangeFolderNameModal.tsx +++ b/src/app/(route)/(withLayout)/saves/_component/MoChangeFolderNameModal.tsx @@ -4,6 +4,7 @@ import { cn } from '@/app/_utils/twMerge' import renderToast from '@/app/_utils/toast' import { useChangeSaveFolderName } from '@/app/_hook/api/saves/useChangeSaveFolderName' import { useParams, useRouter } from 'next/navigation' +import { validateSaveFolderName } from '../_utils/validation' interface Props { originFolderName: string @@ -21,13 +22,7 @@ export default function MoChangeFolderNameModal(props: Props) { const router = useRouter() const handleChangeName = useCallback(async () => { - if (newFolderName.length > 20 || newFolderName.length === 0) { - renderToast({ - type: 'error', - message: '1-20자로 설정해주세요.', - }) - return - } + if (!validateSaveFolderName(newFolderName)) return await changeName({ folderId: fId, folderName: newFolderName }) router.replace(`/saves/${fId}?name=${newFolderName}`) diff --git a/src/app/(route)/(withLayout)/saves/_utils/validation.ts b/src/app/(route)/(withLayout)/saves/_utils/validation.ts new file mode 100644 index 00000000..c153f7f5 --- /dev/null +++ b/src/app/(route)/(withLayout)/saves/_utils/validation.ts @@ -0,0 +1,17 @@ +import renderToast from '@/app/_utils/toast' + +export const validateSaveFolderName = (folderName: string): boolean => { + if (folderName === 'default') { + renderToast({ type: 'error', message: '생성 불가능한 이름입니다.' }) + return false + } + if (folderName.length > 20 || folderName.length === 0) { + renderToast({ + type: 'error', + message: '1-20자로 설정해주세요.', + }) + return false + } + + return true +} From bd03960d21e237edf18f20e4d91e943764045a56 Mon Sep 17 00:00:00 2001 From: yerim Date: Mon, 1 Apr 2024 14:29:01 +0900 Subject: [PATCH 5/5] =?UTF-8?q?fix:=20any=20=ED=83=80=EC=9E=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(route)/(withLayout)/saves/_component/MoveFolderModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/(route)/(withLayout)/saves/_component/MoveFolderModal.tsx b/src/app/(route)/(withLayout)/saves/_component/MoveFolderModal.tsx index e0dec4ab..02810bc0 100644 --- a/src/app/(route)/(withLayout)/saves/_component/MoveFolderModal.tsx +++ b/src/app/(route)/(withLayout)/saves/_component/MoveFolderModal.tsx @@ -35,7 +35,7 @@ export default function MoveFolderModal(props: Props) { const [moveY, setMoveY] = useState(0) const [endY, setEndY] = useState(0) - const ref: any = useRef(null) + const ref = useRef(null) const onTouchStart = (e: TouchEvent) => { setStartY(e.touches[0].clientY)