Skip to content

Commit

Permalink
Merge pull request #47 from sunnybraille/request
Browse files Browse the repository at this point in the history
feat: Login session connection
  • Loading branch information
jun-brro authored Mar 10, 2024
2 parents 3de0a2e + 35684b2 commit 697b649
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 0 deletions.
9 changes: 9 additions & 0 deletions my-app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ import ConvertComplete from "./pages/ConvertComplete";
import DownloadPage from "./pages/DownloadPage";
import { LanguageProvider } from "./LanguageContext";
import { HighContrastModeProvider } from "./components/HighContrastMode";
import LoginPage from "./components/LoginPage";
import SignUpPage from "./components/SignUpPage";
import { AuthProvider } from "./components/AuthContext";

function App() {
return (
<AuthProvider>
<HighContrastModeProvider>
<LanguageProvider>
<BrowserRouter>
Expand All @@ -29,10 +33,15 @@ function App() {

{/* download page */}
<Route path="/download/*" element={<DownloadPage />} />

<Route path="/login" element={<LoginPage />} />

<Route path="/signup" element={<SignUpPage />} />
</Routes>
</BrowserRouter>
</LanguageProvider>
</HighContrastModeProvider>
</AuthProvider>
);
}

Expand Down
51 changes: 51 additions & 0 deletions my-app/src/components/AuthButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from "react";
import { Link } from "react-router-dom";
import { useAuth } from "./AuthContext";
import { useLanguage } from "../LanguageContext";
import { useHighContrast } from "./HighContrastMode";

const AuthButtons: React.FC = () => {
const { language } = useLanguage();
const textClassName = language === "ko" ? "font-kor" : "font-eng";
const { isLoggedIn, setLoggedIn } = useAuth();
const { isHighContrast } = useHighContrast();

const handleLogout = () => {
setLoggedIn(false);
};

return (
<div className="flex justify-center space-x-4">
{isLoggedIn ? (
<>
<span
className={`${textClassName} ${
isHighContrast ? "text-yellow-300" : "text-neutral-800"
}`}
>
{language === "ko" ? "로그인이 완료되었습니다" : "Login Success"}
</span>
<button
onClick={handleLogout}
className={`${textClassName} ${
isHighContrast ? "text-stone-800" : "text-white"
} `}
>
{language === "ko" ? "로그아웃하기" : "Logout"}
</button>
</>
) : (
<>
<Link to="/login">
<button>{language === "ko" ? "로그인하기" : "Login"}</button>
</Link>
<Link to="/signup">
<button>{language === "ko" ? "회원가입" : "Sign Up"}</button>
</Link>
</>
)}
</div>
);
};

export default AuthButtons;
28 changes: 28 additions & 0 deletions my-app/src/components/AuthContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React, { createContext, useContext, useState } from "react";

interface AuthContextType {
isLoggedIn: boolean;
setLoggedIn: (loggedIn: boolean) => void;
}

export const AuthContext = createContext<AuthContextType | null>(null);

export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({
children,
}) => {
const [isLoggedIn, setLoggedIn] = useState<boolean>(false);

return (
<AuthContext.Provider value={{ isLoggedIn, setLoggedIn }}>
{children}
</AuthContext.Provider>
);
};

export const useAuth = () => {
const context = useContext(AuthContext);
if (!context) {
throw new Error("useAuth must be used within an AuthProvider");
}
return context;
};
10 changes: 10 additions & 0 deletions my-app/src/components/DownloadButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ const DownloadButton = () => {
window.URL.revokeObjectURL(url);
} catch (error) {
console.error("Error downloading file:", error);
const errorMessage =
language === "ko"
? "파일 다운로드 중 오류가 발생했습니다"
: "Error occurred during download";
setDownloadStatus(errorMessage);
}
};

Expand All @@ -68,6 +73,11 @@ const DownloadButton = () => {
setDownloadStatus(message);
} else {
console.error("No file found in URL");
const errorMessage =
language === "ko"
? "파일 다운로드 중 오류가 발생했습니다"
: "Error occurred during download";
setDownloadStatus(errorMessage);
}
};

Expand Down
61 changes: 61 additions & 0 deletions my-app/src/components/LoginPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React, { useState } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";
import { useAuth } from "./AuthContext";

const LoginPage: React.FC = () => {
const [loginId, setLoginId] = useState<string>("");
const [password, setPassword] = useState<string>("");
const [error, setError] = useState<string>("");
const navigate = useNavigate();
const { setLoggedIn } = useAuth();

const handleLogin = async () => {
try {
const response = await axios.post("/login", {
loginId,
password,
});
if (response.status === 200) {
setLoggedIn(true);
navigate("/");
}
} catch (error) {
if (axios.isAxiosError(error) && error.response) {
switch (error.response.status) {
case 401:
setError(
"Authentication failed. Please check your login ID and password."
);
break;
default:
setError("An unexpected error occurred.");
}
} else {
setError("An unexpected error occurred.");
}
console.error("Error during login:", error);
}
};

return (
<div>
<input
type="text"
value={loginId}
onChange={(e) => setLoginId(e.target.value)}
placeholder="Login ID"
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
<button onClick={handleLogin}>Login</button>
{error && <p>{error}</p>}
</div>
);
};

export default LoginPage;
5 changes: 5 additions & 0 deletions my-app/src/components/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { useLanguage } from "../LanguageContext";
import ContrastToggleButton from "./ContrastToggleButton";
import { useHighContrast } from "./HighContrastMode";
import { MdMenu } from "react-icons/md";
import { useAuth } from "./AuthContext";
import AuthButtons from "./AuthButton";

const NavBar = () => {
const isMobile = useMediaQuery({ maxWidth: 800 });
Expand All @@ -16,6 +18,7 @@ const NavBar = () => {
const { isHighContrast } = useHighContrast();
const toggleSidebar = () => setIsOpen(!isOpen);
const [isOpen, setIsOpen] = useState(false);
const { isLoggedIn } = useAuth();

return (
<div
Expand All @@ -27,6 +30,7 @@ const NavBar = () => {
{!isMobile && (
<div>
<div className="absolute right-10 top-[24px] flex items-center gap-4">
<AuthButtons />
<ContrastToggleButton />
<LanguageToggleButton />
<a
Expand Down Expand Up @@ -105,6 +109,7 @@ const NavBar = () => {
}`}
>
<div className="absolute left-5 top-20 flex flex-col items-left gap-4 p-4">
{isLoggedIn && <div>로그인되었습니다</div>}
<Link
to="/product"
className={`${
Expand Down
40 changes: 40 additions & 0 deletions my-app/src/components/SignUpPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, { useState } from "react";
import axios from "axios";

const SignUpPage: React.FC = () => {
const [loginId, setLoginId] = useState<string>("");
const [password, setPassword] = useState<string>("");

const handleSignUp = async () => {
try {
const response = await axios.post("/join", {
loginId,
password,
});
if (response.status === 200) {
}
} catch (error) {
console.error("Error during sign up:", error);
}
};

return (
<div>
<input
type="text"
value={loginId}
onChange={(e) => setLoginId(e.target.value)}
placeholder="Login ID"
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
<button onClick={handleSignUp}>Sign Up</button>
</div>
);
};

export default SignUpPage;

0 comments on commit 697b649

Please sign in to comment.