feat(freight:auth): show real user profile in top bar and fix logout

- DashboardLayout now accepts userName, userEmail, userInitials, onLogout
  props; computes initials from name; replaces hardcoded "John Doe" values
- Portal App.tsx pulls display name and email from useAuth user object and
  passes them to DashboardLayout
- handleLogout performs unconditional local cleanup (cookies + localStorage
  + hard redirect to /auth) so a failed API call never leaves the user stuck
- main.tsx purges cookies whose value is the literal string "undefined",
  clearing stale tokens written before the envelope interceptor fix

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Michael Abebe
2026-05-18 11:52:03 +03:00
parent 07c7b70cd0
commit 2478b0278b
3 changed files with 68 additions and 15 deletions

View File

@@ -27,7 +27,12 @@ import TrackingPage from "./pages/tracking/TrackingPage";
import BillingPage from "./pages/billing/BillingPage";
import TrainsPage from "./pages/trains/TrainsPage";
import DashboardPage from "./pages/dashboard/DashboardPage";
import { IamLoginPage, LoadingScreen, useAuth } from "@tria-plc/iamui-common";
import {
IamLoginPage,
LoadingScreen,
useAuth,
useAuthUser,
} from "@tria-plc/iamui-common";
import CustomersPage from "./pages/customers/CustomersPage";
import CustomerDetailPage from "./pages/customers/CustomerDetailPage";
import NewCustomerPage from "./pages/customers/NewCustomerPage";
@@ -50,6 +55,7 @@ const App = () => {
const navigate = useNavigate();
const location = useLocation();
const { user, loading } = useAuth();
const { logout } = useAuthUser();
if (loading) {
return <LoadingScreen />;
@@ -64,9 +70,19 @@ const App = () => {
);
}
if (location.pathname === "/auth") {
return <Navigate to="/" replace />;
}
const displayName = user?.name?.en || user?.username || user?.email || "User";
const userEmail = user?.email;
const handleLogout = () => {
// Best-effort server-side session invalidation; local cleanup always runs
// so a failed API call (e.g. expired token) never leaves the user stuck.
logout();
["auth-token", "refresh-token"].forEach((name) => {
document.cookie = `${name}=; Max-Age=0; path=/`;
});
localStorage.clear();
window.location.replace("/auth");
};
return (
<DashboardLayout
@@ -75,6 +91,9 @@ const App = () => {
activeHref={location.pathname}
onNavigate={navigate}
enableThemeToggle
userName={displayName}
userEmail={userEmail}
onLogout={handleLogout}
>
<Routes>
<Route path="/" element={<DashboardPage />} />

View File

@@ -13,6 +13,19 @@ import {
axiosInstance,
} from "@tria-plc/iamui-common";
// Purge cookies that were stored as the literal string "undefined" before the
// envelope interceptor fix. Without this, stale sessions would keep sending
// "Authorization: Bearer undefined" and get 401 JsonWebTokenError forever.
["auth-token", "refresh-token"].forEach((name) => {
const entry = document.cookie
.split("; ")
.find((c) => c.startsWith(`${name}=`));
const value = entry?.split("=").slice(1).join("=");
if (value === "undefined" || value === "null" || value === "") {
document.cookie = `${name}=; Max-Age=0; path=/`;
}
});
const queryClient = new QueryClient();
window.__IAM_CONFIG__ = {
apiUrl: `${import.meta.env.VITE_BASE_API_URL}/api`,