From 8caff91a434bda4dc27899e6d1ee4aa9844a30e8 Mon Sep 17 00:00:00 2001 From: ghdtnals Date: Thu, 11 Dec 2025 13:42:08 +0900 Subject: [PATCH 01/10] =?UTF-8?q?chore:=20swiper=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 20 -------------------- package.json | 1 - 2 files changed, 21 deletions(-) diff --git a/package-lock.json b/package-lock.json index a877bec..ec00cf0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,6 @@ "next": "^16.0.7", "react": "19.1.0", "react-dom": "19.1.0", - "swiper": "^12.0.2", "tailwind-merge": "^3.3.1", "zustand": "^5.0.8" }, @@ -12263,25 +12262,6 @@ "url": "https://opencollective.com/svgo" } }, - "node_modules/swiper": { - "version": "12.0.3", - "resolved": "https://registry.npmjs.org/swiper/-/swiper-12.0.3.tgz", - "integrity": "sha512-BHd6U1VPEIksrXlyXjMmRWO0onmdNPaTAFduzqR3pgjvi7KfmUCAm/0cj49u2D7B0zNjMw02TSeXfinC1hDCXg==", - "funding": [ - { - "type": "patreon", - "url": "https://www.patreon.com/swiperjs" - }, - { - "type": "open_collective", - "url": "http://opencollective.com/swiper" - } - ], - "license": "MIT", - "engines": { - "node": ">= 4.7.0" - } - }, "node_modules/synckit": { "version": "0.11.11", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", diff --git a/package.json b/package.json index 6b23f48..de85bd2 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "next": "^16.0.7", "react": "19.1.0", "react-dom": "19.1.0", - "swiper": "^12.0.2", "tailwind-merge": "^3.3.1", "zustand": "^5.0.8" }, From 888667d9f154ea8c4f4c3c6b8ac83a77834f51da Mon Sep 17 00:00:00 2001 From: ghdtnals Date: Thu, 11 Dec 2025 13:48:52 +0900 Subject: [PATCH 02/10] =?UTF-8?q?feat:=20=EB=AA=A8=EB=8B=AC=20=EB=A1=9C?= =?UTF-8?q?=EB=94=A9=20=EC=95=A0=EB=8B=88=EB=A9=94=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/PostCreateModal/PostCreateModal.tsx | 92 ++++++------ src/features/editPost/ui/PostEditModal.tsx | 135 ++++++++---------- .../ui/ProfileEditModal/ProfileEditModal.tsx | 10 +- .../ProfileImageChangeInput.tsx | 2 +- src/shared/ui/ConfirmModal/ConfirmModal.tsx | 3 +- 5 files changed, 111 insertions(+), 131 deletions(-) diff --git a/src/features/createPost/ui/PostCreateModal/PostCreateModal.tsx b/src/features/createPost/ui/PostCreateModal/PostCreateModal.tsx index b438c7a..48d27d8 100644 --- a/src/features/createPost/ui/PostCreateModal/PostCreateModal.tsx +++ b/src/features/createPost/ui/PostCreateModal/PostCreateModal.tsx @@ -7,11 +7,7 @@ import { TextBox } from "@/shared/ui/TextBox/TextBox"; import { DropDown } from "@/shared/ui/DropDown/DropDown"; import Button from "@/shared/ui/Button/Button"; import Image from "next/image"; -import { Swiper, SwiperSlide } from "swiper/react"; -import { Navigation } from "swiper/modules"; -import "swiper/css"; -import "swiper/css/navigation"; -import "swiper/css/pagination"; +import { LoadingDots } from "@/shared/ui/Loading/LoadingDots"; import { apiFetch } from "@/shared/api/fetcher"; import { uploadImage } from "@/shared/api/uploadImage"; @@ -56,7 +52,7 @@ export const PostCreateModal = ({ const selected = Array.from(files); setImages((prev) => [...prev, ...selected]); - e.target.value = ""; // input 값 초기화 + e.target.value = ""; }; const handleRemoveImage = (index: number) => { @@ -102,51 +98,10 @@ export const PostCreateModal = ({ const widthClass = "w-[290px] md:w-[510px] xl:w-[540px]"; - const imageSwiper = useMemo( - () => ( - - {images.map((file, idx) => ( - -
- {`preview-${idx}`} - -
-
- ))} -
- ), - [images], - ); - return (
게시물 추가 -
+
+ - {images.length > 0 && imageSwiper} +
+ {images.map((file, idx) => ( +
+ {`preview-${idx}`} + + +
+ ))} +
- {isLoading ? "추가 중 ..." : "추가하기"} + {isLoading ? ( + + 추가 중 + + ) : ( + "추가하기" + )}
diff --git a/src/features/editPost/ui/PostEditModal.tsx b/src/features/editPost/ui/PostEditModal.tsx index 5856317..4f89661 100644 --- a/src/features/editPost/ui/PostEditModal.tsx +++ b/src/features/editPost/ui/PostEditModal.tsx @@ -7,45 +7,35 @@ import { TextBox } from "@/shared/ui/TextBox/TextBox"; import { DropDown } from "@/shared/ui/DropDown/DropDown"; import Button from "@/shared/ui/Button/Button"; import Image from "next/image"; -import { Swiper, SwiperSlide } from "swiper/react"; -import { Navigation } from "swiper/modules"; -import "swiper/css"; -import "swiper/css/navigation"; -import "swiper/css/pagination"; +import { LoadingDots } from "@/shared/ui/Loading/LoadingDots"; import { apiFetch } from "@/shared/api/fetcher"; import { uploadImage } from "@/shared/api/uploadImage"; -const ImageSwiperSlide = ( +const ImageItem = ( idx: number, url: string, - onRemoveButtonClick: (idx: number) => void, + onRemove: (idx: number) => void, ) => { return ( - -
- {`preview-${idx}`} - -
-
+ {`preview-${idx}`} + + + ); }; @@ -80,9 +70,10 @@ export const PostEditModal = ({ const [price, setPrice] = useState(initPrice); const [category, setCategory] = useState(initCategory); const [content, setContent] = useState(initContent); - const [isLoading, setIsLoading] = useState(false); + const [isLoading, setIsLoading] = useState(false); const inputRef = useRef(null); + const categoryOptions = [ "전자제품/가전제품", "식료품", @@ -98,37 +89,31 @@ export const PostEditModal = ({ const handleFileSelect = (e: React.ChangeEvent) => { const files = e.currentTarget.files; - if (!files || files.length == 0) return; + if (!files || files.length === 0) return; - const selected = Array.from(files); - setImages((prev) => [...prev, ...selected]); - e.target.value = ""; // input 값 초기화 + setImages((prev) => [...prev, ...Array.from(files)]); + e.target.value = ""; }; - const handleRemoveImageUrl = (index: number) => { - setImageUrls((prev) => prev.filter((_, i) => i !== index)); + const handleRemoveImageUrl = (idx: number) => { + setImageUrls((prev) => prev.filter((_, i) => i !== idx)); }; - const handleRemoveImage = (index: number) => { - setImages((prev) => prev.filter((_, i) => i !== index)); + + const handleRemoveImage = (idx: number) => { + setImages((prev) => prev.filter((_, i) => i !== idx)); }; const handleSubmit = async () => { try { - if ( - !title || - !price || - !category || - !content || - (imageUrls.length === 0 && images.length === 0) - ) - return; + if (!title || !price || !category || !content) return; + if (imageUrls.length === 0 && images.length === 0) return; + setIsLoading(true); - // 새로 추가한 이미지 URL 배열 생성 const uploadedImageUrlArray: string[] = []; for (const file of images) { - const uploadedImageUrl = await uploadImage(file); - uploadedImageUrlArray.push(uploadedImageUrl); + const url = await uploadImage(file); + uploadedImageUrlArray.push(url); } const body = { @@ -139,15 +124,13 @@ export const PostEditModal = ({ images: [...imageUrls, ...uploadedImageUrlArray], }; - const res = await apiFetch(`/api/postings/${postId}`, { + await apiFetch(`/api/postings/${postId}`, { method: "PATCH", body: JSON.stringify(body), }); - console.log("게시글 수정 성공! : ", res); onEdit?.(); } catch (error) { - console.error("게시글 수정 실패 : ", error); const message = error instanceof Error ? error.message : String(error); onError?.(message); } finally { @@ -156,30 +139,11 @@ export const PostEditModal = ({ }; const widthClass = "w-[290px] md:w-[510px] xl:w-[540px]"; - const imageSwiper = useMemo( - () => ( - - {imageUrls.map((url, idx) => - ImageSwiperSlide(idx, url, handleRemoveImageUrl), - )} - {images.map((file, idx) => - ImageSwiperSlide(idx, URL.createObjectURL(file), handleRemoveImage), - )} - - ), - [imageUrls, images], - ); return (
+ - {(imageUrls.length > 0 || images.length > 0) && imageSwiper} + {(imageUrls.length > 0 || images.length > 0) && ( +
+ {imageUrls.map((url, idx) => + ImageItem(idx, url, handleRemoveImageUrl), + )} + + {images.map((file, idx) => + ImageItem( + idx + imageUrls.length, + URL.createObjectURL(file), + handleRemoveImage, + ), + )} +
+ )}
- {isLoading ? "수정 중 ... " : "수정하기"} + {isLoading ? ( + + 수정 중 + + ) : ( + "수정하기" + )} diff --git a/src/features/editProfile/ui/ProfileEditModal/ProfileEditModal.tsx b/src/features/editProfile/ui/ProfileEditModal/ProfileEditModal.tsx index ee6ac7d..cf691b1 100644 --- a/src/features/editProfile/ui/ProfileEditModal/ProfileEditModal.tsx +++ b/src/features/editProfile/ui/ProfileEditModal/ProfileEditModal.tsx @@ -7,6 +7,8 @@ import { Input } from "@/entities/user/ui/Input/Input"; import { TextBox } from "@/shared/ui/TextBox/TextBox"; import { DropDown } from "@/shared/ui/DropDown/DropDown"; import Button from "@/shared/ui/Button/Button"; +import { LoadingDots } from "@/shared/ui/Loading/LoadingDots"; + import { apiFetch } from "@/shared/api/fetcher"; import { uploadImage } from "@/shared/api/uploadImage"; @@ -156,7 +158,13 @@ export const ProfileEditModal = ({ disabled={loading} onClick={handleSave} > - {loading ? "저장 중..." : "저장하기"} + {loading ? ( + + 저장 중 + + ) : ( + "저장하기" + )} diff --git a/src/features/editProfile/ui/ProfileImageChangeInput/ProfileImageChangeInput.tsx b/src/features/editProfile/ui/ProfileImageChangeInput/ProfileImageChangeInput.tsx index 762cac2..052b257 100644 --- a/src/features/editProfile/ui/ProfileImageChangeInput/ProfileImageChangeInput.tsx +++ b/src/features/editProfile/ui/ProfileImageChangeInput/ProfileImageChangeInput.tsx @@ -38,7 +38,7 @@ export const ProfileImageChangeInput = ({ return (