Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/features/auth/model/useLoginRedirect.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,27 @@ import {
readLastEndpoint,
} from "#shared/lib/lastEndpointStorage";

let refreshPromise;

const refreshOnce = async () => {
if (!refreshPromise) {
refreshPromise = authService.refresh().catch((error) => {
refreshPromise = null;
throw error;
});
}

return refreshPromise;
};

export const useLoginRedirect = ({ navigate }) => {
useEffect(() => {
let isMounted = true;

const redirectAfterRefresh = async () => {
let refreshSucceeded = true;
try {
await authService.refresh();
await refreshOnce();
} catch (error) {
refreshSucceeded = false;
console.error("로그인 리다이렉트 실패:", error);
Expand Down
31 changes: 3 additions & 28 deletions src/pages/Login/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,6 @@
text-align: center;
}

.login-title {
margin: 0;
font-size: 28px;
font-weight: 700;
color: #1f2937;
}

.login-subtitle {
margin: 0;
font-size: 15px;
color: #6b7280;
}

.login-status {
margin: 0;
font-size: 14px;
color: #4b5563;
}

.login-actions {
display: flex;
flex-direction: column;
Expand All @@ -59,13 +40,7 @@
justify-content: center;
}

.login-button--disabled {
background: #a5b4fc;
cursor: default;
pointer-events: none;
}

.login-button:not(.login-button--disabled):hover {
.login-button:hover {
background: #4338ca;
}

Expand All @@ -74,7 +49,7 @@
color: #191919;
}

.login-button--kakao:not(.login-button--disabled):hover {
.login-button--kakao:hover {
background: #f5dc00;
}

Expand All @@ -84,6 +59,6 @@
border: 1px solid #e5e7eb;
}

.login-button--google:not(.login-button--disabled):hover {
.login-button--google:hover {
background: #f9fafb;
}
37 changes: 6 additions & 31 deletions src/pages/Login/index.jsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,25 @@
import { useTranslation } from "i18nexus";
import React from "react";
import { useNavigate } from "react-router-dom";
import { useLogin } from "#features/auth";
import "./index.css";
import Logo from "#shared/ui/logo";

const Login = () => {
const { t } = useTranslation();
const navigate = useNavigate();
const {
state: { isChecking },
} = useLogin({ t, navigate });
const baseUrl = import.meta.env.VITE_BASE_URL || "";
const normalizedBaseUrl = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
const kakaoLoginUrl = `${normalizedBaseUrl}/oauth2/authorization/kakao`;
const googleLoginUrl = `${normalizedBaseUrl}/oauth2/authorization/google`;

const handlePreventIfChecking = (event) => {
if (isChecking) {
event.preventDefault();
}
};
const kakaoLoginUrl = `${baseUrl}/oauth2/authorization/kakao`;
const googleLoginUrl = `${baseUrl}/oauth2/authorization/google`;

return (
<div className="login-page">
<div className="login-card">
<h1 className="login-title">Q-Asker</h1>
<p className="login-subtitle">
{t("로그인이 필요합니다.")}
</p>
{isChecking && (
<p className="login-status">{t("로그인 상태 확인 중...")}</p>
)}
<Logo />
<div className="login-actions">
<a
className={`login-button login-button--kakao ${isChecking ? "login-button--disabled" : ""}`}
href={kakaoLoginUrl}
onClick={handlePreventIfChecking}
aria-disabled={isChecking}
>
<a className="login-button login-button--kakao" href={kakaoLoginUrl}>
{t("카카오 로그인")}
</a>
<a
className={`login-button login-button--google ${isChecking ? "login-button--disabled" : ""}`}
className="login-button login-button--google"
href={googleLoginUrl}
onClick={handlePreventIfChecking}
aria-disabled={isChecking}
>
{t("구글 로그인")}
</a>
Expand Down
3 changes: 1 addition & 2 deletions src/shared/lib/lastEndpointStorage.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const STORAGE_KEY = "lastEndpoint";

export const readLastEndpoint = () =>
localStorage.getItem(STORAGE_KEY) || "/";
export const readLastEndpoint = () => localStorage.getItem(STORAGE_KEY) || "/";

export const writeLastEndpoint = (value) => {
localStorage.setItem(STORAGE_KEY, value);
Expand Down
20 changes: 20 additions & 0 deletions src/shared/ui/logo/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.logo {
display: inline-flex;
justify-content: center;
align-items: center;
cursor: pointer;
user-select: none;
}

.logo-icon {
width: 28px;
height: 28px;
margin-right: 8px;
margin-bottom: 5px;
}

.logo-text {
font-size: 24px;
color: #6366f1;
font-weight: bold;
}
1 change: 1 addition & 0 deletions src/shared/ui/logo/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./index.jsx";
15 changes: 15 additions & 0 deletions src/shared/ui/logo/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react";
import "./index.css";

const Logo = ({ className = "" }) => {
const logoClassName = ["logo", className].filter(Boolean).join(" ");

return (
<span className={logoClassName}>
<img src="/favicon-256x256.png" alt="Q-Asker" className="logo-icon" />
<span className="logo-text">Q-Asker</span>
</span>
);
};

export default Logo;
18 changes: 1 addition & 17 deletions src/widgets/header/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,7 @@

.logo-link {
text-decoration: none;
display: flex;
align-items: center;
cursor: pointer;
user-select: none;
}

.logo-icon {
width: 28px;
height: 28px;
margin-right: 8px;
margin-bottom: 5px;
}

.logo-text {
font-size: 24px;
color: #6366f1;
font-weight: bold;
color: inherit;
}

.auth-buttons .text-button {
Expand Down
9 changes: 2 additions & 7 deletions src/widgets/header/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useMemo, useState } from "react";
import { Link } from "react-router-dom";
import { useHeader } from "./model/useHeader";
import { useClickOutside } from "#shared/lib/useClickOutside";
import Logo from "#shared/ui/logo";
import "./index.css";

const Header = ({
Expand Down Expand Up @@ -51,13 +52,7 @@ const Header = ({
</button>
<Link to="/" className="logo-link">
<img
src="/favicon-256x256.png"
alt="Q-Asker"
className="logo-icon"
/>

<div className="logo-text">Q-Asker</div>
<Logo />
</Link>
</div>
<div className="nav-link-area">
Expand Down