issue #
All checks were successful
Test CI / build (push) Successful in 17s

- 로그인 화면, 회원가입 화면, 비밀번호 초기화 화면 모바일 ui 대비 작업
This commit is contained in:
geonhee-min
2025-12-03 17:06:20 +09:00
parent 069f58075b
commit ea7861b63a
4 changed files with 170 additions and 134 deletions

View File

@@ -1 +1 @@
VITE_API_URL=http://localhost:8080
VITE_API_URL=http://localhost:8088

View File

@@ -17,11 +17,13 @@ import { toast } from 'sonner';
import { useAuthStore } from '@/store/authStore';
import { Checkbox } from '@/components/ui/checkbox';
import { Label } from '@/components/ui/label';
import { useIsMobile } from '@/hooks/use-mobile';
export default function LoginPage() {
const [isLoading, setIsLoading] = useState<boolean>(false);
const [autoLogin, setAutoLogin] = useState<boolean>(false);
const { login } = useAuthStore();
const isMobile = useIsMobile();
const navigate = useNavigate();
const accountNetwork = new AccountNetwork();
const loginForm = useForm<z.infer<typeof LoginSchema>>({
@@ -73,7 +75,7 @@ export default function LoginPage() {
};
login({...data});
moveToHomePage();
return "";
return "로그인 성공";
} else {
throw new Error(res.data.message);
}
@@ -102,7 +104,7 @@ export default function LoginPage() {
return (
<div className="w-full h-full flex flex-col justify-center items-center">
<Card className="w-md pl-2 pr-2">
<Card className={isMobile ? "w-full pl-2 pr-2" : "w-md pl-2 pr-2"}>
<CardHeader>
</CardHeader>

View File

@@ -18,6 +18,8 @@ import { AccountNetwork } from '@/network/AccountNetwork';
import { toast } from 'sonner';
import { useNavigate } from 'react-router-dom';
import { PageRouting } from '@/const/PageRouting';
import { useIsMobile } from '@/hooks/use-mobile';
import { ScrollArea } from '@/components/ui/scroll-area';
export default function SignUpPage() {
const [emailVerificationModalOpen, setEmailVerificationModalOpen] = useState<boolean>(false);
@@ -28,6 +30,7 @@ export default function SignUpPage() {
const accountNetwork = new AccountNetwork();
const navigate = useNavigate();
const isMobile = useIsMobile();
const signUpForm = useForm<z.infer<typeof SignUpSchema>>({
resolver: zodResolver(SignUpSchema),
@@ -119,145 +122,150 @@ export default function SignUpPage() {
}
return (
<div className="w-full h-full flex flex-col justify-center items-center">
<Card className="w-md pl-2 pr-2">
<CardHeader></CardHeader>
<CardContent>
<form id="form-signup">
<FieldGroup>
<Controller
name="accountId"
control={signUpForm.control}
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor="form-signup-account-id"></FieldLabel>
<div id="accountId-group" className="w-full flex flex-row justify-between gap-2.5">
<div className={"w-full h-full flex flex-col justify-center items-center"}>
<Card className={isMobile ? "w-full pl-2 pr-2" : "w-md pl-2 pr-2"}>
<CardHeader></CardHeader>
<ScrollArea className="h-72 [&>div>div:last-child]:hidden">
<CardContent>
<form id="form-signup">
<FieldGroup>
<Controller
name="accountId"
control={signUpForm.control}
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor="form-signup-account-id"></FieldLabel>
<div id="accountId-group" className="w-full flex flex-row justify-between gap-2.5">
<Input
{...field}
id="form-signup-account-id"
aria-invalid={fieldState.invalid}
onInput={handleOnChangeAccountId}
/>
<Button
type="button"
onClick={() => handleDuplicationCheckButtonClick('accountId')}
className="bg-indigo-500 hover:bg-indigo-400"
>
</Button>
</div>
{ isCheckedAccountIdDuplication && <p className="text-green-500 text-sm font-normal"> </p> }
<FieldError errors={[fieldState.error]}/>
</Field>
)}
/>
<Controller
name="name"
control={signUpForm.control}
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor="form-signup-name"></FieldLabel>
<Input
{...field}
id="form-signup-account-id"
id="form-signup-name"
aria-invalid={fieldState.invalid}
onInput={handleOnChangeAccountId}
/>
<Button
type="button"
onClick={() => handleDuplicationCheckButtonClick('accountId')}
className="bg-indigo-500 hover:bg-indigo-400"
>
</Button>
</div>
{ isCheckedAccountIdDuplication && <p className="text-green-500 text-sm font-normal"> </p> }
<FieldError errors={[fieldState.error]}/>
</Field>
)}
/>
<Controller
name="name"
control={signUpForm.control}
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor="form-signup-name"></FieldLabel>
<Input
{...field}
id="form-signup-name"
aria-invalid={fieldState.invalid}
/>
<FieldError errors={[fieldState.error]} />
</Field>
)}
/>
<Controller
name="nickname"
control={signUpForm.control}
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor="form-signup-nickname"></FieldLabel>
<Input
{...field}
id="form-signup-nickname"
aria-invalid={fieldState.invalid}
/>
<FieldError errors={[fieldState.error]} />
</Field>
)}
/>
<Controller
name="email"
control={signUpForm.control}
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor="form-signup-email"></FieldLabel>
<div id="email-group" className="w-full flex flex-row justify-between gap-2.5">
<FieldError errors={[fieldState.error]} />
</Field>
)}
/>
<Controller
name="nickname"
control={signUpForm.control}
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor="form-signup-nickname"></FieldLabel>
<Input
{...field}
id="form-signup-email"
id="form-signup-nickname"
aria-invalid={fieldState.invalid}
placeholder="example@domain.com"
type="email"
onInput={handleOnChangeEmail}
/>
<Button
type="button"
onClick={() => handleDuplicationCheckButtonClick('email')}
className="bg-indigo-500 hover:bg-indigo-400"
>
</Button>
</div>
{ isCheckedEmailDuplication && <p className="text-green-500 text-sm font-normal"> </p> }
<FieldError errors={[fieldState.error]}/>
</Field>
)}
/>
<Controller
name="password"
control={signUpForm.control}
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor="form-signup-password"></FieldLabel>
<Input
{...field}
id="form-signup-password"
aria-invalid={fieldState.invalid}
type="password"
/>
<FieldError errors={[fieldState.error]} />
</Field>
)}
/>
<Controller
name="passwordConfirm"
control={signUpForm.control}
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor="form-signup-password-confirm"> </FieldLabel>
<Input
{...field}
id="form-signup-password-confirm"
aria-invalid={fieldState.invalid}
type="password"
/>
<FieldError errors={[fieldState.error]} />
</Field>
)}
/>
</FieldGroup>
</form>
</CardContent>
<CardFooter>
<EmailVerificationModal
trigger={
<Button type="button" onClick={handleOnSignUpButtonClick} className="0">
</Button>
}
email={duplicationCheckedEmail}
open={emailVerificationModalOpen} // ✅ 부모 상태 연결
setOpen={setEmailVerificationModalOpen} // ✅ 부모 상태 변경 함수 전달
onVerifySuccess={signup} // ✅ 인증 성공 시 signup 호출
/>
</CardFooter>
</Card>
<FieldError errors={[fieldState.error]} />
</Field>
)}
/>
<Controller
name="email"
control={signUpForm.control}
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor="form-signup-email"></FieldLabel>
<div id="email-group" className="w-full flex flex-row justify-between gap-2.5">
<Input
{...field}
id="form-signup-email"
aria-invalid={fieldState.invalid}
placeholder="example@domain.com"
type="email"
onInput={handleOnChangeEmail}
/>
<Button
type="button"
onClick={() => handleDuplicationCheckButtonClick('email')}
className="bg-indigo-500 hover:bg-indigo-400"
>
</Button>
</div>
{ isCheckedEmailDuplication && <p className="text-green-500 text-sm font-normal"> </p> }
<FieldError errors={[fieldState.error]}/>
</Field>
)}
/>
<Controller
name="password"
control={signUpForm.control}
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor="form-signup-password"></FieldLabel>
<Input
{...field}
id="form-signup-password"
aria-invalid={fieldState.invalid}
type="password"
/>
<FieldError errors={[fieldState.error]} />
</Field>
)}
/>
<Controller
name="passwordConfirm"
control={signUpForm.control}
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor="form-signup-password-confirm"> </FieldLabel>
<Input
{...field}
id="form-signup-password-confirm"
aria-invalid={fieldState.invalid}
type="password"
/>
<FieldError errors={[fieldState.error]} />
</Field>
)}
/>
</FieldGroup>
</form>
</CardContent>
</ScrollArea>
<CardFooter>
<EmailVerificationModal
trigger={
<Button type="button" onClick={handleOnSignUpButtonClick} className="0">
</Button>
}
email={duplicationCheckedEmail}
open={emailVerificationModalOpen} // ✅ 부모 상태 연결
setOpen={setEmailVerificationModalOpen} // ✅ 부모 상태 변경 함수 전달
onVerifySuccess={signup} // ✅ 인증 성공 시 signup 호출
/>
</CardFooter>
</Card>
</div>
);
}

View File

@@ -0,0 +1,26 @@
import { Calendar } from "@/components/ui/calendar";
import { DayButton } from "react-day-picker";
export function ScheduleMainPage() {
return (
<div className="w-full h-full flex flex-col justify-start items-center">
<Calendar
mode="single"
className="rounded-lg w-full h-full max-h-10/12 border"
components={{
Weeks: (props) => (
<tbody {...props} className={props.className}></tbody>
),
Week: (props) => (
<tr {...props} className={props.className + " h-1/10"}></tr>
),
Day: (props) => (
<td {...props} className={props.className + " h-1"}></td>
)
}}
>
</Calendar>
</div>
)
}