From 12e90d0e20eb13cef79c36a1197d471468c40f23 Mon Sep 17 00:00:00 2001 From: cccwon2 Date: Mon, 9 Dec 2024 23:02:46 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20URL=20?= =?UTF-8?q?=EB=B0=8F=20=EB=82=A0=EC=A7=9C=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/card/cardList/AlbaListItem.tsx | 36 +++++++++++++------ src/constants/config.ts | 2 ++ src/utils/workDayFormatter.ts | 5 +++ 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/app/components/card/cardList/AlbaListItem.tsx b/src/app/components/card/cardList/AlbaListItem.tsx index 544ace99..d17d9773 100644 --- a/src/app/components/card/cardList/AlbaListItem.tsx +++ b/src/app/components/card/cardList/AlbaListItem.tsx @@ -9,6 +9,8 @@ import useModalStore from "@/store/modalStore"; import Indicator from "../../pagination/Indicator"; import { FormListType } from "@/types/response/form"; import { useFormScrap } from "@/hooks/queries/form/useFormScap"; +import { MdOutlineImage } from "react-icons/md"; +import { S3_URL } from "@/constants/config"; /** * 알바폼 리스트 아이템 컴포넌트 @@ -81,22 +83,36 @@ const AlbaListItem = ({ }); }; + // S3 URL 체크 함수 + const isValidS3Url = (url: string) => { + return url.startsWith(S3_URL); + }; + return (
{/* 이미지 슬라이더 영역 */}
- {/* 현재 이미지 */} - {imageUrls[currentImageIndex] && ( - {`Recruit + {imageUrls[currentImageIndex] ? ( + isValidS3Url(imageUrls[currentImageIndex]) ? ( + {`Recruit + ) : ( +
+ +
+ ) + ) : ( +
+ +
)} - {/* 이미지 인디케이터 */} - {imageUrls.length > 1 && ( + {/* 이미지 인디케이터 - 유효한 이미지가 2개 이상일 때만 표시 */} + {imageUrls.filter((url) => isValidS3Url(url)).length > 1 && (
{ + // 유효한 Date 객체인지 확인 + if (!(date instanceof Date) || isNaN(date.getTime())) { + return "yyyy.MM.dd"; + } + const year = isMd ? date.getFullYear().toString() : date.getFullYear().toString().slice(2); const month = String(date.getMonth() + 1).padStart(2, "0"); const day = String(date.getDate()).padStart(2, "0"); From 73a45b77a34f2ef3a0d189f191c3c3d1bedbd8b7 Mon Sep 17 00:00:00 2001 From: cccwon2 Date: Tue, 10 Dec 2024 00:14:25 +0900 Subject: [PATCH 2/2] =?UTF-8?q?chore:=20=EC=9E=90=EC=9E=98=ED=95=9C=20UI?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../albaList/components/SearchSection.tsx | 2 +- src/app/(pages)/albaList/layout.tsx | 2 +- src/app/(pages)/albaList/page.tsx | 11 ++-- .../components/card/cardList/AlbaListItem.tsx | 20 +++---- .../card/cardList/ScrapListItem.tsx | 54 ++++++++++++------- src/app/components/chip/Chip.tsx | 6 +-- .../design-system/pages/albaList/page.tsx | 8 +-- src/utils/workDayFormatter.ts | 2 +- 8 files changed, 63 insertions(+), 42 deletions(-) diff --git a/src/app/(pages)/albaList/components/SearchSection.tsx b/src/app/(pages)/albaList/components/SearchSection.tsx index 494eeea7..d5d991bb 100644 --- a/src/app/(pages)/albaList/components/SearchSection.tsx +++ b/src/app/(pages)/albaList/components/SearchSection.tsx @@ -25,7 +25,7 @@ export default function SearchSection() { return (
-
+
) => setKeyword(e.target.value)} diff --git a/src/app/(pages)/albaList/layout.tsx b/src/app/(pages)/albaList/layout.tsx index 900388a3..21c3a7e1 100644 --- a/src/app/(pages)/albaList/layout.tsx +++ b/src/app/(pages)/albaList/layout.tsx @@ -2,7 +2,7 @@ import React, { Suspense } from "react"; export default function AlbaListLayout({ children }: { children: React.ReactNode }) { return ( -
+
diff --git a/src/app/(pages)/albaList/page.tsx b/src/app/(pages)/albaList/page.tsx index ac3fbf4e..f7c74286 100644 --- a/src/app/(pages)/albaList/page.tsx +++ b/src/app/(pages)/albaList/page.tsx @@ -12,6 +12,7 @@ import SearchSection from "./components/SearchSection"; import { useUser } from "@/hooks/queries/user/me/useUser"; import Link from "next/link"; import { IoAdd } from "react-icons/io5"; +import { userRoles } from "@/constants/userRoles"; const FORMS_PER_PAGE = 10; @@ -20,7 +21,7 @@ export default function AlbaList() { const pathname = usePathname(); const searchParams = useSearchParams(); const { user } = useUser(); - const isOwner = user?.role === "owner"; + const isOwner = user?.role === userRoles.OWNER; // URL 쿼리 파라미터에서 필터 상태와 키워드 가져오기 const isRecruiting = searchParams.get("isRecruiting"); @@ -124,10 +125,10 @@ export default function AlbaList() {
{/* 메인 콘텐츠 영역 */} -
+
{/* 폼 만들기 버튼 - 고정 위치 */} {isOwner && ( -
+
등록된 알바 공고가 없습니다.

) : ( -
-
+
+
{data?.pages.map((page) => ( {page.data.map((form) => ( diff --git a/src/app/components/card/cardList/AlbaListItem.tsx b/src/app/components/card/cardList/AlbaListItem.tsx index d17d9773..2db50c33 100644 --- a/src/app/components/card/cardList/AlbaListItem.tsx +++ b/src/app/components/card/cardList/AlbaListItem.tsx @@ -33,6 +33,7 @@ const AlbaListItem = ({ const [showDropdown, setShowDropdown] = useState(false); // 드롭다운 메뉴 표시 상태 const [currentImageIndex, setCurrentImageIndex] = useState(0); // 현재 이미지 인덱스 const dropdownRef = useRef(null); // 드롭다운 메뉴 참조 + const [imageError, setImageError] = useState(false); // 모집 상태 및 D-day 계산 const recruitmentStatus = getRecruitmentStatus(recruitmentEndDate); @@ -89,16 +90,17 @@ const AlbaListItem = ({ }; return ( -
+
{/* 이미지 슬라이더 영역 */} -
- {imageUrls[currentImageIndex] ? ( +
+ {imageUrls[currentImageIndex] && !imageError ? ( isValidS3Url(imageUrls[currentImageIndex]) ? ( {`Recruit setImageError(true)} /> ) : (
@@ -111,8 +113,8 @@ const AlbaListItem = ({
)} - {/* 이미지 인디케이터 - 유효한 이미지가 2개 이상일 때만 표시 */} - {imageUrls.filter((url) => isValidS3Url(url)).length > 1 && ( + {/* 이미지 인디케이터 - 유효한 이미지가 2개 이상이고 에러가 없을 때만 표시 */} + {imageUrls.filter((url) => isValidS3Url(url)).length > 1 && !imageError && (
{/* 콘텐츠 영역 */} -
+
{/* 상단 영역 */}
{/* 상태 표시 영역 (공개여부, 모집상태, 날짜) */} @@ -133,7 +135,7 @@ const AlbaListItem = ({
- + {formatRecruitDate(recruitmentStartDate, true)} ~ {formatRecruitDate(recruitmentEndDate, true)}
@@ -168,11 +170,11 @@ const AlbaListItem = ({
{/* 제목 */} -
{title}
+
{title}
{/* 통계 정보 영역 - mt-auto 제거하고 부모 컨테이너에 justify-between 추가 */} -
+
지원자 {applyCount}명
diff --git a/src/app/components/card/cardList/ScrapListItem.tsx b/src/app/components/card/cardList/ScrapListItem.tsx index 766c0c85..4eea5b64 100644 --- a/src/app/components/card/cardList/ScrapListItem.tsx +++ b/src/app/components/card/cardList/ScrapListItem.tsx @@ -9,6 +9,8 @@ import Indicator from "../../pagination/Indicator"; import { FormListType } from "@/types/response/form"; import { useFormScrap } from "@/hooks/queries/form/useFormScap"; import { useRouter } from "next/navigation"; +import { MdOutlineImage } from "react-icons/md"; +import { S3_URL } from "@/constants/config"; /** * 알바폼 스크랩 리스트 아이템 컴포넌트 @@ -30,6 +32,7 @@ const ScrapListItem = ({ const [showDropdown, setShowDropdown] = useState(false); // 드롭다운 메뉴 표시 상태 const [currentImageIndex, setCurrentImageIndex] = useState(0); // 현재 표시 중인 이미지 인덱스 const dropdownRef = useRef(null); // 드롭다운 메뉴 참조 + const [imageError, setImageError] = useState(false); // 모집 상태 및 D-day 계산 const recruitmentStatus = getRecruitmentStatus(recruitmentEndDate); @@ -80,22 +83,37 @@ const ScrapListItem = ({ }); }; + // S3 URL 체크 함수 추가 + const isValidS3Url = (url: string) => { + return url.startsWith(S3_URL); + }; + return ( -
+
{/* 이미지 슬라이더 영역 */} -
- {/* 현재 이미지 */} - {imageUrls[currentImageIndex] && ( - {`Recruit +
+ {imageUrls[currentImageIndex] && !imageError ? ( + isValidS3Url(imageUrls[currentImageIndex]) ? ( + {`Recruit setImageError(true)} + /> + ) : ( +
+ +
+ ) + ) : ( +
+ +
)} - {/* 이미지 인디케이터 */} - {imageUrls.length > 1 && ( + {/* 이미지 인디케이터 - 유효한 이미지가 2개 이상이고 에러가 없을 때만 표시 */} + {imageUrls.filter((url) => isValidS3Url(url)).length > 1 && !imageError && (
{/* 콘텐츠 영역 */} -
+
{/* 상단 영역 */}
{/* 상태 표시 영역 (공개여부, 모집상태, 날짜) */} @@ -116,7 +134,7 @@ const ScrapListItem = ({
- + {formatRecruitDate(recruitmentStartDate, true)} ~ {formatRecruitDate(recruitmentEndDate, true)}
@@ -133,7 +151,7 @@ const ScrapListItem = ({ {showDropdown && (
{/* 제목 */} -
{title}
+
{title}
- {/* 통계 정보 영역 - mt-auto 제거하고 부모 컨테이너에 justify-between 추가 */} -
+ {/* 통계 정보 영역 */} +
지원자 {applyCount}명
diff --git a/src/app/components/chip/Chip.tsx b/src/app/components/chip/Chip.tsx index 69a5ad19..4c638786 100644 --- a/src/app/components/chip/Chip.tsx +++ b/src/app/components/chip/Chip.tsx @@ -19,12 +19,12 @@ interface ChipProps { const Chip: React.FC = ({ label = "Label", variant, border, icon, textStyle = "" }: ChipProps) => { const wrapperStyle = "rounded flex items-center justify-center min-w-[60px] m-1"; const paddingStyle = icon - ? "px-[10px] py-1 md:px-[14.5px] md:py-1 lg:px-[10px] lg:py-[6px]" - : "px-2 py-1 md:px-[10px] lg:py-[6px] lg:px-3"; + ? "px-[8px] py-1 md:px-[12px] md:py-1 lg:px-[8px] lg:py-[6px]" + : "px-2 py-1 md:px-2 lg:py-[6px] lg:px-2"; const variantStyle = variant === "positive" ? "bg-primary-orange-50 text-primary-orange-300" : "bg-line-100 text-grayscale-200"; const baseTextStyle = - "text-xs leading-[20px] md:leading-[24px] lg:text-base lg:leading-[26px] font-medium tracking-tight"; + "text-xs leading-[18px] md:leading-[20px] lg:text-sm lg:leading-[22px] font-medium tracking-tighter whitespace-nowrap"; const borderStyle = border ? "border border-primary-orange-100" : ""; const iconStyle = "flex items-center justify-center"; diff --git a/src/app/stories/design-system/pages/albaList/page.tsx b/src/app/stories/design-system/pages/albaList/page.tsx index 7c39a915..6ea9a9d3 100644 --- a/src/app/stories/design-system/pages/albaList/page.tsx +++ b/src/app/stories/design-system/pages/albaList/page.tsx @@ -100,9 +100,9 @@ const AlbaList: React.FC = () => {
{/* 메인 콘텐츠 영역 */} -
+
{/* 폼 만들기 버튼 - 고정 위치 */} -
+
= () => {

등록된 알바 공고가 없습니다.

) : ( -
-
+
+
{items.map((form) => (
diff --git a/src/utils/workDayFormatter.ts b/src/utils/workDayFormatter.ts index 33556ff2..0c2be47e 100644 --- a/src/utils/workDayFormatter.ts +++ b/src/utils/workDayFormatter.ts @@ -3,7 +3,7 @@ import { workDayOptions } from "@/constants/workDayOptions"; export const formatRecruitDate = (date: Date, isMd: boolean = false) => { // 유효한 Date 객체인지 확인 if (!(date instanceof Date) || isNaN(date.getTime())) { - return "yyyy.MM.dd"; + return new Date().toLocaleDateString("ko-KR", { year: "numeric", month: "2-digit", day: "2-digit" }); } const year = isMd ? date.getFullYear().toString() : date.getFullYear().toString().slice(2);