idfind api 적용1

This commit is contained in:
2025-11-25 22:51:12 +09:00
parent 4c52627c2c
commit 6bfa2f367d
2 changed files with 77 additions and 16 deletions

View File

@@ -49,17 +49,17 @@ export default function IdFindDone({
</p>
</div>
<div className="mt-[60px]">
<div className="bg-[#f9fafb] border border-neutral-40 rounded-[16px] py-[24px]">
<div className="bg-[#f9fafb] border border-neutral-40 rounded-[16px] py-[24px] min-h-[108px]">
{userId && (
<p className="text-[18px] font-semibold text-neutral-700">
{userId}
</p>
)}
{joinedAtText && (
{/* {joinedAtText && (
<p className="text-[16px] text-[#6c7682] mt-2">
({joinedAtText})
</p>
)}
)} */}
</div>
</div>
<div className="mt-[24px] flex gap-3">

View File

@@ -10,6 +10,7 @@ export default function FindIdPage() {
const [isDoneOpen, setIsDoneOpen] = useState(false);
const [isFailedOpen, setIsFailedOpen] = useState(false);
const [foundUserId, setFoundUserId] = useState<string | undefined>(undefined);
const [joinedAt, setJoinedAt] = useState<string | undefined>(undefined);
const [name, setName] = useState("");
const [phone, setPhone] = useState("");
const [focused, setFocused] = useState<Record<string, boolean>>({});
@@ -19,6 +20,22 @@ export default function FindIdPage() {
const isPhoneValid = useMemo(() => /^\d{9,11}$/.test(phone), [phone]);
const canSubmit = useMemo(() => isNameValid && isPhoneValid, [isNameValid, isPhoneValid]);
function formatPhoneNumber(value: string): string {
const numbers = value.replace(/[^0-9]/g, "");
if (numbers.length <= 3) return numbers;
if (numbers.length <= 7) return `${numbers.slice(0, 3)}-${numbers.slice(3)}`;
if (numbers.length <= 11) return `${numbers.slice(0, 3)}-${numbers.slice(3, 7)}-${numbers.slice(7)}`;
return `${numbers.slice(0, 3)}-${numbers.slice(3, 7)}-${numbers.slice(7, 11)}`;
}
// function formatJoinedAt(dateString: string | Date): string {
// const date = typeof dateString === 'string' ? new Date(dateString) : dateString;
// const year = date.getFullYear();
// const month = date.getMonth() + 1;
// const day = date.getDate();
// return `${year}년 ${month}월 ${day}일`;
// }
function validateAll() {
const next: Record<string, string> = {};
if (!isNameValid) next.name = "이름을 입력해 주세요.";
@@ -65,7 +82,21 @@ export default function FindIdPage() {
}
const data = await response.json();
// body의 emails 배열에서 첫 번째 이메일 가져오기
if (data.emails && Array.isArray(data.emails) && data.emails.length > 0) {
setFoundUserId(data.emails[0]);
} else if (data.email) {
setFoundUserId(data.email);
}
// 가입일 정보는 API 응답에 없음
// // header의 date 값 가져오기
// const headerDate = response.headers.get('date');
// if (headerDate) {
// setJoinedAt(formatJoinedAt(headerDate));
// }
setIsDoneOpen(true);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : '네트워크 오류가 발생했습니다.';
@@ -79,6 +110,7 @@ export default function FindIdPage() {
<IdFindDone
on={isDoneOpen}
userId={foundUserId}
// joinedAtText={joinedAt ? `가입일: ${joinedAt}` : undefined}
onClose={() => setIsDoneOpen(false)}
/>
<IdFindFailed
@@ -86,6 +118,7 @@ export default function FindIdPage() {
onClose={() => setIsFailedOpen(false)}
/>
<div className="flex-1 flex items-center justify-center w-full py-6">
<div className="rounded-xl bg-white max-w-[560px] px-[40px] w-full relative">
<div className="my-15 flex flex-col items-center">
@@ -97,7 +130,7 @@ export default function FindIdPage() {
</p>
</div>
<form onSubmit={handleSubmit} className="space-y-6">
<form onSubmit={handleSubmit}>
<div className="space-y-2">
<label htmlFor="name" className="text-[15px] font-semibold text-[#6c7682]">
@@ -107,11 +140,24 @@ export default function FindIdPage() {
id="name"
name="name"
value={name}
onChange={(e) => setName(e.target.value)}
onChange={(e) => {
setName(e.target.value);
if (errors.name) {
setErrors((prev) => {
const next = { ...prev };
delete next.name;
return next;
});
}
}}
onFocus={() => setFocused((p) => ({ ...p, name: true }))}
onBlur={() => setFocused((p) => ({ ...p, name: false }))}
placeholder="이름을 입력해 주세요."
className="h-[40px] px-[12px] py-[7px] w-full rounded-[8px] mt-3 border border-neutral-40 focus:outline-none focus:border-neutral-700 text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px]"
className={`h-[40px] px-[12px] py-[7px] w-full rounded-[8px] mt-3 border focus:outline-none text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px] ${
errors.name
? "border-error focus:border-error"
: "border-neutral-40 focus:border-neutral-700"
}`}
/>
{name.trim().length > 0 && focused.name && (
<button
@@ -121,7 +167,7 @@ export default function FindIdPage() {
setName("");
}}
aria-label="입력 지우기"
className="absolute right-3 top-1/2 -translate-y-1/2 cursor-pointer">
className="absolute right-3 top-[32px] -translate-y-1/2 cursor-pointer flex items-center justify-center">
<LoginInputSvg />
</button>
)}
@@ -129,7 +175,7 @@ export default function FindIdPage() {
{errors.name && <p className="text-error text-[13px] leading-tight">{errors.name}</p>}
</div>
<div className="space-y-2">
<div className="space-y-2 mt-6">
<label htmlFor="phone" className="text-[15px] font-semibold text-[#6c7682]">
</label>
@@ -139,14 +185,28 @@ export default function FindIdPage() {
name="phone"
type="tel"
inputMode="numeric"
value={phone}
onChange={(e) => setPhone(e.target.value.replace(/[^0-9]/g, ""))}
value={formatPhoneNumber(phone)}
onChange={(e) => {
const numbersOnly = e.target.value.replace(/[^0-9]/g, "");
setPhone(numbersOnly);
if (errors.phone) {
setErrors((prev) => {
const next = { ...prev };
delete next.phone;
return next;
});
}
}}
onFocus={() => setFocused((p) => ({ ...p, phone: true }))}
onBlur={() => setFocused((p) => ({ ...p, phone: false }))}
placeholder="-없이 입력해 주세요."
className="h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border mt-3 border-neutral-40 focus:outline-none focus:border-neutral-700 text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px]"
className={`h-[40px] px-[12px] py-[7px] w-full rounded-[8px] border mt-3 focus:outline-none text-[18px] text-neutral-700 placeholder:text-input-placeholder-text pr-[40px] ${
errors.phone
? "border-error focus:border-error"
: "border-neutral-40 focus:border-neutral-700"
}`}
/>
{phone.trim().length > 0 && focused.phone && (
{phone.length > 0 && focused.phone && (
<button
type="button"
onMouseDown={(e) => {
@@ -154,7 +214,7 @@ export default function FindIdPage() {
setPhone("");
}}
aria-label="입력 지우기"
className="absolute right-3 top-1/2 -translate-y-1/2 cursor-pointer">
className="absolute right-3 top-[32px] -translate-y-1/2 cursor-pointer flex items-center justify-center">
<LoginInputSvg />
</button>
)}
@@ -164,13 +224,14 @@ export default function FindIdPage() {
<button
type="submit"
className={`h-[56px] w-full rounded-[12px] text-[18px] mt-[30px] font-semibold text-white hover:bg-[#1F2B91] ${canSubmit ? "bg-active-button" : "bg-inactive-button"} cursor-pointer`}>
className={`h-[56px] w-full rounded-lg text-[16px] font-semibold text-white transition-opacity cursor-pointer mb-3 hover:bg-[#1F2B91] mt-[60px] ${canSubmit ? "bg-active-button" : "bg-inactive-button"}`}>
</button>
</form>
</div>
</div>
<FindIdOption
doneEnabled={isDoneOpen}