diff --git a/src/apis/canary.ts b/src/apis/canary.ts
index ca16dea..c022ea3 100644
--- a/src/apis/canary.ts
+++ b/src/apis/canary.ts
@@ -10,7 +10,7 @@ export type CanaryApplyForm = {
gender: boolean;
address: string;
detailAddress: string;
- zip: string;
+ zip: string | number;
certificateFilePath: string;
latitude: number;
longitude: number;
diff --git a/src/assets/images/no-challenger-medal.png b/src/assets/images/no-challenger-medal.png
new file mode 100644
index 0000000..632d85c
Binary files /dev/null and b/src/assets/images/no-challenger-medal.png differ
diff --git a/src/components/Challenge/BestChallenger.tsx b/src/components/Challenge/BestChallenger.tsx
index 33c1dc1..4583ca2 100644
--- a/src/components/Challenge/BestChallenger.tsx
+++ b/src/components/Challenge/BestChallenger.tsx
@@ -5,6 +5,7 @@ import Challenger from "./Challenger";
import { getTopParticipants } from "../../apis/challenge";
import { useQuery } from "@tanstack/react-query";
import { BestChallengerProps } from "../../@types/challenge";
+import NoChallenger from "../Common/NoChallenger";
export const scroll = keyframes`
from {
@@ -29,25 +30,31 @@ const BestChallenger = () => {
title="베스트 챌린저"
desc="금주의 베스트 챌린저! 베스트 챌린저는 어떤 챌린지에 참여했을까요?"
/>
-
- {topChallengersData.data.map(
- (challenger: BestChallengerProps, index: number) => (
-
- )
- )}
-
+ {topChallengersData.length > 0 ? (
+
+ {topChallengersData.data.map(
+ (challenger: BestChallengerProps, index: number) => (
+
+ )
+ )}
+
+ ) : (
+
+ )}
);
};
diff --git a/src/components/ChallengeDetail/Challengers.tsx b/src/components/ChallengeDetail/Challengers.tsx
index 47b1f6c..9a5952f 100644
--- a/src/components/ChallengeDetail/Challengers.tsx
+++ b/src/components/ChallengeDetail/Challengers.tsx
@@ -7,6 +7,7 @@ import { scroll } from "../Challenge/BestChallenger";
import { useQuery } from "@tanstack/react-query";
import { getChallengeParticipants } from "../../apis/challenge";
import { BestChallengerProps } from "../../@types/challenge";
+import NoChallenger from "../Common/NoChallenger";
type ChallengerProps = {
challengeId?: string;
@@ -60,28 +61,34 @@ const Challengers = ({
/>
)}
-
- {challengerData.data.map(
- (challenger: BestChallengerProps, index: number) => (
-
- )
- )}
-
+ {challengerData.length > 0 ? (
+
+ {challengerData.data.map(
+ (challenger: BestChallengerProps, index: number) => (
+
+ )
+ )}
+
+ ) : (
+
+ )}
);
};
diff --git a/src/components/ChallengeDetail/Header.tsx b/src/components/ChallengeDetail/Header.tsx
index 0c166ff..1436ce6 100644
--- a/src/components/ChallengeDetail/Header.tsx
+++ b/src/components/ChallengeDetail/Header.tsx
@@ -25,12 +25,14 @@ const Header = ({
return (
- {categories?.map((category) => (
-
- {challengeType.find((type) => type.id === category)
- ?.label || category}
-
- ))}
+
+ {categories?.map((category) => (
+
+ {challengeType.find((type) => type.id === category)
+ ?.label || category}
+
+ ))}
+
{title}
{desc}
@@ -80,15 +82,20 @@ const ChallengeInfo = styled.div`
${tw`
w-[1280px] flex flex-col items-start
`}
+ .categories {
+ ${tw`
+ flex gap-[8px] mb-[20px]
+ `}
+ }
.category {
${tw`
text-medium-20 font-medium text-white
- bg-mainColor rounded-[37px] p-[1px 13px]
+ bg-mainColor rounded-[37px] p-[3px 13px] pb-[6px]
`}
}
.title {
${tw`
- text-bold-64 font-bold mt-[6.5px] text-fontColor1
+ text-bold-64 font-bold mt-[-20px] text-fontColor1
`}
}
.desc {
diff --git a/src/components/Common/NoChallenger.tsx b/src/components/Common/NoChallenger.tsx
new file mode 100644
index 0000000..723e696
--- /dev/null
+++ b/src/components/Common/NoChallenger.tsx
@@ -0,0 +1,34 @@
+import styled from "styled-components";
+import tw from "twin.macro";
+import medal from "../../assets/images/no-challenger-medal.png";
+
+type NoChallengerProps = {
+ text: string;
+};
+
+const NoChallenger = ({ text }: NoChallengerProps) => {
+ return (
+
+ 아직 {text} 챌린저가 없어요!
+
+
+ );
+};
+
+export default NoChallenger;
+
+const Container = styled.div`
+ ${tw`
+ w-full h-[415px] flex flex-col gap-[4px] items-center justify-center
+ `}
+ div {
+ ${tw`
+ text-medium-20 font-medium text-fontColor2
+ `}
+ }
+ img {
+ ${tw`
+ opacity-[63%]
+ `}
+ }
+`;
diff --git a/src/components/Common/PageHeader.tsx b/src/components/Common/PageHeader.tsx
index df29bb9..9e05c48 100644
--- a/src/components/Common/PageHeader.tsx
+++ b/src/components/Common/PageHeader.tsx
@@ -2,44 +2,50 @@ import React from "react";
import styled from "styled-components";
import tw from "twin.macro";
interface PageHeaderProps {
- title: string;
- desc: string;
- imgSrc: string;
+ title: string;
+ desc: string;
+ desc2?: string;
+ imgSrc: string;
}
-function PageHeader({ title, desc, imgSrc }: PageHeaderProps) {
- return (
- <>
- {/* 헤더 */}
-
-
- {title}
- {desc}
-
-
-
-
-
- >
- );
+function PageHeader({ title, desc, desc2, imgSrc }: PageHeaderProps) {
+ return (
+ <>
+ {/* 헤더 */}
+
+ >
+ );
}
export default PageHeader;
const Header = styled.div`
- ${tw`flex flex-row mt-20 h-[528px] w-[1280px] m-auto justify-between`}
+ ${tw`flex flex-row mt-20 h-[528px] w-[1280px] m-auto justify-between`}
- .text-wrapper {
- ${tw`flex flex-col w-1/2 mt-36`}
- .title-text {
- ${tw`text-bold-48 font-sans text-fontColor1 font-bold mb-5`}
+ .text-wrapper {
+ ${tw`flex flex-col w-1/2 mt-36`}
+ .title-text {
+ ${tw`text-bold-48 font-sans text-fontColor1 font-bold mb-5`}
+ }
+ .description-text {
+ ${tw`text-medium-20 text-fontColor3 font-sans w-[498px] font-medium `}
+ }
}
- .description-text {
- ${tw`text-medium-20 text-fontColor3 font-sans w-[498px] font-medium `}
+ .image-background {
+ width: 50%;
+ height: 528px;
+ background: radial-gradient(
+ 50% 50% at 50% 50%,
+ #ffd7c0 0%,
+ #faf8f5 100%
+ );
}
- }
- .image-background {
- width: 50%;
- height: 528px;
- background: radial-gradient(50% 50% at 50% 50%, #ffd7c0 0%, #faf8f5 100%);
- }
`;
diff --git a/src/components/MyPage/CanaryModal.tsx b/src/components/MyPage/CanaryModal.tsx
index 5aae49d..4b5d57e 100644
--- a/src/components/MyPage/CanaryModal.tsx
+++ b/src/components/MyPage/CanaryModal.tsx
@@ -9,7 +9,18 @@ import useAuthStore from "../../storage/useAuthStore";
import { getPresignedUrl, uploadImageToS3 } from "../../apis/file-upload";
import { postCanaryApply } from "../../apis/canary";
-const CanaryModal = ({ onClick }: { onClick: () => void }) => {
+interface postCode {
+ address: string;
+ zonecode: number | string;
+ detailAddress?: string;
+}
+
+// prop 타입 정의
+interface CanaryModalProps {
+ onClick: () => void;
+}
+
+const CanaryModal = ({ onClick }: CanaryModalProps) => {
const { userData } = useAuthStore.getState();
const [success, setSuccess] = useState(false);
const [image, setImage] = useState(null);
@@ -28,34 +39,40 @@ const CanaryModal = ({ onClick }: { onClick: () => void }) => {
gender: true,
address: "",
detailAddress: "",
- zip: "",
+ zip: "" as number | string,
certificateFilePath: "",
latitude: 0,
longitude: 0,
});
- const handleApplyData = useCallback(
- (data: any, key: string) => {
- setApplyData({ ...applyData, [key]: data });
- },
- [applyData]
- );
+ const handleApplyData = (value: any, field: any) => {
+ let formattedValue = value;
+
+ // 필드에 따라 포맷팅 처리
+ if (field === "phone") {
+ formattedValue = formatPhoneNumber(value);
+ }
+
+ setApplyData({
+ ...applyData,
+ [field]: formattedValue,
+ });
+ };
+
const handleBirthData = useCallback(
(data: any, key: string) => {
setBirthData({ ...birthData, [key]: data });
},
[birthData]
);
- const handleAddressChange = useCallback(
- (data: any) => {
- setApplyData({
- ...applyData,
- address: data.address,
- detailAddress: data.detailAddress,
- zip: data.zonecode,
- });
- },
- [applyData]
- );
+
+ const handleAddressChange = (data: postCode) => {
+ setApplyData({
+ ...applyData,
+ address: data.address,
+ detailAddress: data.detailAddress!,
+ zip: data.zonecode,
+ });
+ };
const handleImageChange = useCallback(
(e: React.ChangeEvent) => {
@@ -67,6 +84,26 @@ const CanaryModal = ({ onClick }: { onClick: () => void }) => {
[]
);
+ const formatPhoneNumber = (value: any) => {
+ // 숫자만 남기기
+ const numbersOnly = value.replace(/\D/g, "");
+
+ // 3자리, 4자리, 4자리로 나누어 하이픈 추가
+ let formattedNumber = numbersOnly;
+ if (numbersOnly.length > 3 && numbersOnly.length <= 7) {
+ formattedNumber = `${numbersOnly.slice(0, 3)}-${numbersOnly.slice(
+ 3
+ )}`;
+ } else if (numbersOnly.length > 7) {
+ formattedNumber = `${numbersOnly.slice(0, 3)}-${numbersOnly.slice(
+ 3,
+ 7
+ )}-${numbersOnly.slice(7, 11)}`;
+ }
+
+ return formattedNumber;
+ };
+
const convertToISO = (year: number, month: number, day: number): string => {
const date = new Date(year, month - 1, day);
return date.toISOString();
@@ -97,6 +134,9 @@ const CanaryModal = ({ onClick }: { onClick: () => void }) => {
}
}
}, [accesstoken, applyData, image, birthData]);
+
+ console.log(applyData);
+
return (
{
@@ -252,8 +292,9 @@ const ImageInput = styled.div`
`}
span {
${tw`
- absolute left-0 top-0 w-full h-full flex items-center ml-[21px]
- `}
+ absolute left-0 top-0 w-[500px] h-full flex items-center ml-[21px]
+ overflow-hidden whitespace-nowrap
+ `}
}
}
`;
diff --git a/src/components/MyPage/Header.tsx b/src/components/MyPage/Header.tsx
index 3a86b71..2806121 100644
--- a/src/components/MyPage/Header.tsx
+++ b/src/components/MyPage/Header.tsx
@@ -107,7 +107,7 @@ const Profile = styled.div`
.change-name {
${tw`
- text-medium-20 font-medium text-fontColor2 underline underline-offset-4 decoration-1 cursor-pointer
+ text-medium-20 font-medium text-fontColor2 underline underline-offset-4 decoration-1 cursor-pointer mt-[10px]
`}
}
`;
diff --git a/src/components/MyPage/PostalCode.tsx b/src/components/MyPage/PostalCode.tsx
index f3f434a..4d8d131 100644
--- a/src/components/MyPage/PostalCode.tsx
+++ b/src/components/MyPage/PostalCode.tsx
@@ -6,92 +6,100 @@ import { useState, useEffect } from "react";
import DaumPost from "../Common/DaumPost";
interface postCode {
- address: string;
- zonecode: number | string;
- detailAddress?: string;
+ address: string;
+ zonecode: number | string;
+ detailAddress?: string;
}
interface PostalCodeProps {
- initialAddress?: postCode;
- onChange?: (data: postCode) => void;
+ initialAddress?: postCode;
+ onChange?: (data: postCode) => void;
}
const PostalCode = ({ initialAddress, onChange }: PostalCodeProps) => {
- const [popup, setPopup] = useState(false);
+ const [popup, setPopup] = useState(false);
- const [form, setForm] = useState({
- address: "",
- zonecode: "",
- detailAddress: "",
- });
+ const [form, setForm] = useState({
+ address: "",
+ zonecode: "",
+ detailAddress: "",
+ });
- const handlePopup = () => {
- setPopup(!popup);
- };
+ const handlePopup = () => {
+ setPopup(!popup);
+ };
- useEffect(() => {
- if (initialAddress) {
- setForm(initialAddress);
- }
- }, [initialAddress]);
+ useEffect(() => {
+ if (initialAddress) {
+ setForm(initialAddress);
+ }
+ }, [initialAddress]);
- useEffect(() => {
- if (onChange && form.address !== initialAddress?.address) {
- onChange(form);
- }
- }, [form, initialAddress]);
+ useEffect(() => {
+ if (onChange && form.address !== initialAddress?.address) {
+ onChange(form);
+ }
+ }, [form, initialAddress?.address]);
- const handleDetailAddressChange = (
- e: React.ChangeEvent
- ) => {
- setForm((prevForm) => ({ ...prevForm, detailAddress: e.target.value }));
- };
+ useEffect(() => {
+ if (onChange && form.detailAddress !== initialAddress?.detailAddress) {
+ onChange(form);
+ }
+ }, [form.detailAddress, initialAddress?.detailAddress]);
- return (
- <>
-
-
-
-
-
- {popup && }
-
- {popup && (
- {
- handlePopup();
- }}
- />
- )}
- >
- );
+ const handleDetailAddressChange = (
+ e: React.ChangeEvent
+ ) => {
+ setForm((prevForm) => ({ ...prevForm, detailAddress: e.target.value }));
+ };
+
+ return (
+ <>
+
+
+
+
+
+ {popup && (
+
+ )}
+
+ {popup && (
+ {
+ handlePopup();
+ }}
+ />
+ )}
+ >
+ );
};
export default PostalCode;
const Container = styled.div`
- ${tw`
+ ${tw`
flex gap-[23px] items-baseline relative
`}
`;
const Background = styled.div`
- ${tw`
+ ${tw`
absolute w-[100dvw] h-[100dvh] z-40 top-0 left-0
`}
`;
diff --git a/src/pages/Challenge.tsx b/src/pages/Challenge.tsx
index 3f021fc..3d1ab5b 100644
--- a/src/pages/Challenge.tsx
+++ b/src/pages/Challenge.tsx
@@ -19,7 +19,8 @@ const Challenge = () => {
{/* 챌린지 페이지 헤더 */}
diff --git a/src/pages/Sponsor.tsx b/src/pages/Sponsor.tsx
index 3cfcb7f..a87fe70 100644
--- a/src/pages/Sponsor.tsx
+++ b/src/pages/Sponsor.tsx
@@ -10,50 +10,52 @@ import DefaultLayout from "../components/Common/DefaultLayout";
import DeadlinePosts from "../components/Sponsor/DeadlinePosts";
function Sponsor() {
- return (
-
-
- {/* 헤더 */}
-
+ return (
+
+
+ {/* 헤더 */}
+
- {/* 기한 임박 후원글 목록 */}
-
- 기한 임박 후원글
-
- 곧 후원 기간이 끝나는 후원글이에요! 청년들에게 도움의 손길을
- 건네주세요.
-
-
-
+ {/* 기한 임박 후원글 목록 */}
+
+ 기한 임박 후원글
+
+ 곧 후원 기간이 끝나는 후원글이에요! 청년들에게 도움의
+ 손길을 건네주세요.
+
+
+
- {/* 모든 후원글 목록 */}
-
- 후원글 목록
-
- 당신의 작은 도움이 자립준비청년들의 큰 가능성을 열어갑니다.
-
-
-
-
-
- );
+ {/* 모든 후원글 목록 */}
+
+ 후원글 목록
+
+ 당신의 작은 도움이 자립준비청년들의 큰 가능성을
+ 열어갑니다.
+
+
+
+
+
+ );
}
export default Sponsor;
const Wrapper = styled.div`
- ${tw` flex flex-col m-auto items-center`}
+ ${tw` flex flex-col m-auto items-center`}
`;
const ContentWrapper = styled.div`
- ${tw`flex flex-col mt-24 w-[1280px] m-auto`}
- .main-text {
- ${tw`text-bold-36 font-sans font-bold text-fontColor1`}
- }
- .sub-text {
- ${tw`text-medium-20 font-sans font-medium text-fontColor3 mt-1`}
- }
+ ${tw`flex flex-col mt-24 w-[1280px] m-auto`}
+ .main-text {
+ ${tw`text-bold-36 font-sans font-bold text-fontColor1`}
+ }
+ .sub-text {
+ ${tw`text-medium-20 font-sans font-medium text-fontColor3 mt-1`}
+ }
`;