/* * 비밀번호 찾기/초기화 — 04_backend_public_auth.md §2·§3. 공개 경로. * 1단계: 이메일로 재설정 코드 요청(항상 200, 사용자 열거 방지). * 2단계: 이메일+코드+새 비밀번호로 초기화. */ import { router } from 'expo-router'; import React, { useState } from 'react'; import { KeyboardAvoidingView, Platform, ScrollView, StyleSheet, Text } from 'react-native'; import { Banner } from '../components/Banner'; import { Button } from '../components/Button'; import { Field } from '../components/Field'; import { ApiRequestError } from '../lib/api'; import { forgotPassword, resetPassword } from '../lib/auth'; import { colors, spacing, type } from '../theme'; export default function ForgotPasswordScreen() { const [step, setStep] = useState<1 | 2>(1); const [email, setEmail] = useState(''); const [code, setCode] = useState(''); const [newPassword, setNewPassword] = useState(''); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [info, setInfo] = useState(null); async function onRequest() { setError(null); setInfo(null); if (!email.trim()) { setError('이메일을 입력해 주세요.'); return; } setLoading(true); try { const res = await forgotPassword(email); setInfo(res.message); setStep(2); } catch (e) { setError(e instanceof ApiRequestError ? e.message : '요청에 실패했습니다.'); } finally { setLoading(false); } } async function onReset() { setError(null); if (!code.trim() || newPassword.length < 8) { setError('재설정 코드와 새 비밀번호(8자 이상)를 확인해 주세요.'); return; } setLoading(true); try { const res = await resetPassword(email, code, newPassword); setInfo(res.message); setTimeout(() => router.replace('/login'), 800); } catch (e) { if (e instanceof ApiRequestError && e.code === 'OTP_INVALID') { setError('재설정 코드가 올바르지 않거나 만료되었습니다.'); } else { setError(e instanceof ApiRequestError ? e.message : '초기화에 실패했습니다.'); } } finally { setLoading(false); } } return ( 비밀번호 재설정 {error ? {error} : null} {info ? {info} : null} {step === 1 ? (