fix(app): show loader during protected boot
Some checks failed
Frontend CI/CD / build (push) Has been cancelled
Frontend CI/CD / deploy (push) Has been cancelled

This commit is contained in:
2026-06-20 19:55:11 +03:30
parent f7238d1767
commit 1aa45beba4
4 changed files with 80 additions and 70 deletions

View File

@@ -5,12 +5,13 @@ import { Button } from "./ui/button"
import { SettingsMenu } from "./SettingsMenu"
import { FlaskConical, LogOut, User, Moon, Sun, Globe, Command, Menu, RefreshCcw } from "lucide-react"
import { useTheme } from "./ThemeProvider"
import { logoutUser, getUserProfile } from "../api/users"
import { logoutUser } from "../api/users"
import { WorkspaceSelector } from "./WorkspaceSelector"
import { toast } from "sonner"
import { NotificationBell } from "./notifications/NotificationBell"
import { clearSessionTokens, getAccessToken, getRefreshToken, setDemoSessionMeta, setSessionTokens } from "../lib/session"
import { clearSessionTokens, getRefreshToken, setDemoSessionMeta, setSessionTokens } from "../lib/session"
import { startDemo } from "../api/demo"
import { useAppContext } from "../context/AppContext"
type NavbarProps = {
onOpenSidebar?: () => void
@@ -19,12 +20,12 @@ type NavbarProps = {
export function Navbar({ onOpenSidebar }: NavbarProps) {
const { t, lang, setLanguage } = useTranslation()
const { theme, setTheme } = useTheme()
const { user, isLoadingUser, setUser } = useAppContext()
const navigate = useNavigate()
const [showLogoutModal, setShowLogoutModal] = useState(false)
const [isDropdownOpen, setIsDropdownOpen] = useState(false)
const [isResettingDemo, setIsResettingDemo] = useState(false)
const [user, setUser] = useState<any>(null)
const dropdownRef = useRef<HTMLDivElement>(null)
@@ -40,33 +41,6 @@ export function Navbar({ onOpenSidebar }: NavbarProps) {
}).format(new Date(user.demo_expires_at))
: null
useEffect(() => {
const handleProfileUpdated = ((e: CustomEvent) => {
if (e.detail) {
setUser((prev: any) => (prev ? { ...prev, ...e.detail } : e.detail))
}
}) as EventListener
window.addEventListener("profile_updated", handleProfileUpdated)
return () => window.removeEventListener("profile_updated", handleProfileUpdated)
}, [])
useEffect(() => {
const fetchUser = async () => {
const token = getAccessToken()
if (!token) return
try {
const userData = await getUserProfile()
setUser(userData)
} catch (error) {
console.error("Failed to fetch user profile:", error)
}
}
void fetchUser()
}, [])
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
@@ -279,7 +253,7 @@ export function Navbar({ onOpenSidebar }: NavbarProps) {
)}
</div>
</>
) : (
) : isLoadingUser ? null : (
<>
<SettingsMenu />

View File

@@ -1,4 +1,4 @@
import { useEffect, useState } from "react"
import { useState } from "react"
import { NavLink, useNavigate } from "react-router-dom"
import {
Users,
@@ -28,9 +28,10 @@ import { canWorkspace, WORKSPACE_LOGS_VIEW } from "../lib/permissions"
import { WorkspaceSelector } from "./WorkspaceSelector"
import { SettingsMenu } from "./SettingsMenu"
import { Button } from "./ui/button"
import { getUserProfile, logoutUser } from "../api/users"
import { clearSessionTokens, getAccessToken, getRefreshToken, setDemoSessionMeta, setSessionTokens } from "../lib/session"
import { logoutUser } from "../api/users"
import { clearSessionTokens, getRefreshToken, setDemoSessionMeta, setSessionTokens } from "../lib/session"
import { startDemo } from "../api/demo"
import { useAppContext } from "../context/AppContext"
type SidebarProps = {
mobileOpen?: boolean
@@ -41,7 +42,7 @@ export const Sidebar = ({ mobileOpen = false, onMobileClose }: SidebarProps) =>
const [isCollapsed, setIsCollapsed] = useState(false)
const [showLogoutModal, setShowLogoutModal] = useState(false)
const [isResettingDemo, setIsResettingDemo] = useState(false)
const [user, setUser] = useState<any>(null)
const { user, isLoadingUser, setUser } = useAppContext()
const navigate = useNavigate()
const { t, lang, setLanguage } = useTranslation()
@@ -67,33 +68,6 @@ export const Sidebar = ({ mobileOpen = false, onMobileClose }: SidebarProps) =>
? PanelLeftOpen
: PanelLeftClose
useEffect(() => {
const handleProfileUpdated = ((e: CustomEvent) => {
if (e.detail) {
setUser((prev: any) => (prev ? { ...prev, ...e.detail } : e.detail))
}
}) as EventListener
window.addEventListener("profile_updated", handleProfileUpdated)
return () => window.removeEventListener("profile_updated", handleProfileUpdated)
}, [])
useEffect(() => {
const fetchUser = async () => {
const token = getAccessToken()
if (!token) return
try {
const userData = await getUserProfile()
setUser(userData)
} catch (error) {
console.error("Failed to fetch user profile:", error)
}
}
void fetchUser()
}, [])
const handleLogout = async () => {
try {
const refreshToken = getRefreshToken()
@@ -245,7 +219,7 @@ export const Sidebar = ({ mobileOpen = false, onMobileClose }: SidebarProps) =>
}
const renderMobileFooterSection = () => {
if (!user) {
if (!user && !isLoadingUser) {
return (
<div className="border-t border-slate-200 p-4 dark:border-slate-800">
<button
@@ -272,6 +246,10 @@ export const Sidebar = ({ mobileOpen = false, onMobileClose }: SidebarProps) =>
)
}
if (!user) {
return null
}
return (
<div className="space-y-1 p-4">
<button