From a030b925d30644384b03961aa2bf0cacfc32b799 Mon Sep 17 00:00:00 2001 From: Yared Yemane Date: Thu, 26 Feb 2026 23:12:23 -0800 Subject: [PATCH] default page fixes --- src/App.tsx | 13 +++++++++++++ src/api/http.ts | 6 ++++++ src/layouts/AppLayout.tsx | 7 ++++++- src/pages/auth/LoginPage.tsx | 35 ++++++++++++++++++++++++++++------- 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index ba4b6ed..7835fb1 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,20 @@ +import { useEffect } from 'react' import { Toaster } from 'sonner' import { AppRoutes } from './app/AppRoutes' +const SESSION_KEY = 'yimaru_session_active' + export default function App() { + useEffect(() => { + if (!sessionStorage.getItem(SESSION_KEY)) { + localStorage.removeItem('access_token') + localStorage.removeItem('refresh_token') + localStorage.removeItem('member_id') + localStorage.removeItem('role') + sessionStorage.setItem(SESSION_KEY, '1') + } + }, []) + return ( <> diff --git a/src/api/http.ts b/src/api/http.ts index 3fccbc0..6e9d62f 100644 --- a/src/api/http.ts +++ b/src/api/http.ts @@ -109,6 +109,12 @@ http.interceptors.response.use( } } + // Backend is down (network error, timeout, connection refused) + if (!error.response) { + clearAuthAndRedirect(); + return Promise.reject(error); + } + return Promise.reject(error); } ); diff --git a/src/layouts/AppLayout.tsx b/src/layouts/AppLayout.tsx index 38c74d2..113f260 100644 --- a/src/layouts/AppLayout.tsx +++ b/src/layouts/AppLayout.tsx @@ -1,11 +1,16 @@ import { useState, useCallback } from "react" -import { Outlet } from "react-router-dom" +import { Navigate, Outlet } from "react-router-dom" import { Sidebar } from "../components/sidebar/Sidebar" import { Topbar } from "../components/topbar/Topbar" export function AppLayout() { const [sidebarOpen, setSidebarOpen] = useState(false) + const token = localStorage.getItem("access_token") + if (!token) { + return + } + const handleMenuClick = useCallback(() => { setSidebarOpen(true) }, []) diff --git a/src/pages/auth/LoginPage.tsx b/src/pages/auth/LoginPage.tsx index 518ed9e..2ac84ef 100644 --- a/src/pages/auth/LoginPage.tsx +++ b/src/pages/auth/LoginPage.tsx @@ -71,6 +71,7 @@ export function LoginPage() { const [googleLoading, setGoogleLoading] = useState(false); const [error, setError] = useState(null); const [googleReady, setGoogleReady] = useState(false); + const [fieldErrors, setFieldErrors] = useState<{ email?: string; password?: string }>({}); const googleBtnRef = useRef(null); @@ -156,6 +157,16 @@ export function LoginPage() { const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); + + const errors: { email?: string; password?: string } = {}; + if (!email.trim()) errors.email = "Please enter your email address"; + if (!password) errors.password = "Please enter your password"; + if (Object.keys(errors).length > 0) { + setFieldErrors(errors); + return; + } + setFieldErrors({}); + setError(null); setLoading(true); @@ -309,7 +320,7 @@ export function LoginPage() { )} -
+ {/* Email */}
{/* Password */} @@ -355,9 +371,11 @@ export function LoginPage() { placeholder="••••••••" autoComplete="current-password" value={password} - onChange={(e) => setPassword(e.target.value)} - required - className="h-11 rounded-xl pr-10" + onChange={(e) => { + setPassword(e.target.value); + if (fieldErrors.password) setFieldErrors((prev) => ({ ...prev, password: undefined })); + }} + className={`h-11 rounded-xl pr-10 ${fieldErrors.password ? "border-red-400 focus-visible:ring-red-400/40" : ""}`} /> + {fieldErrors.password && ( +

{fieldErrors.password}

+ )}