setting, session and profile

This commit is contained in:
debu-2 2026-10-07 03:19:09 +05:30
parent 48eea5d201
commit 4a563f4f34
31 changed files with 1797 additions and 159 deletions

View file

@ -12,7 +12,6 @@ import {
LogOut,
Mail,
Menu,
PanelLeftOpen,
HandHelping,
Plug,
Send,
@ -24,10 +23,17 @@ import {
Trash2,
Users,
UsersRound,
UserRound,
X,
} from "lucide-react";
import { useCallback, useEffect, useState } from "react";
import { getCurrentAccount, getMyCompanyDomain } from "../api";
import {
AUTH_ACCOUNT_KEY,
AUTH_TOKEN_KEY,
clearSession,
getAccessToken,
} from "../auth";
import Brand from "./Brand";
import MobileChrome from "./MobileChrome";
import { ShellModeContext } from "../shellMode";
@ -43,6 +49,8 @@ import CompanyOverviewSetup, { isOrgSetupComplete } from "./CompanyOverviewSetup
import ChangePasswordModal from "./ChangePasswordModal";
import ComposeDock, { triggerOpenCompose } from "./ComposeDock";
import HumanHandoff from "./HumanHandoff";
import AccountProfile from "./AccountProfile";
import AccountSettings from "./AccountSettings";
import MailboxView from "./MailboxView";
const mailItems = [
@ -87,11 +95,6 @@ const manageNavItems = [
[Settings, "Settings"],
];
function clearSession() {
sessionStorage.removeItem("agmail_access_token");
sessionStorage.removeItem("agmail_account");
}
function SidebarSection({ title, children, className = "" }) {
return (
<section className={`dashboard-sidebar-section ${className}`}>
@ -112,7 +115,10 @@ export default function DashboardPage() {
const [needsDnsSetup, setNeedsDnsSetup] = useState(false);
const [domainError, setDomainError] = useState("");
const [active, setActive] = useState("Inbox");
const [menuOpen, setMenuOpen] = useState(false);
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const [sidebarExpanded, setSidebarExpanded] = useState(
() => typeof window !== "undefined" && window.matchMedia("(min-width: 1200px)").matches,
);
const [sheet, setSheet] = useState(null);
const [notice, setNotice] = useState("");
const [loading, setLoading] = useState(true);
@ -134,7 +140,7 @@ export default function DashboardPage() {
const handleStats = useCallback((stats) => setMailStats(stats), []);
useEffect(() => {
const token = sessionStorage.getItem("agmail_access_token");
const token = getAccessToken();
if (!token) {
window.location.replace("/login");
return;
@ -142,7 +148,7 @@ export default function DashboardPage() {
getCurrentAccount(token)
.then(async (currentAccount) => {
sessionStorage.setItem("agmail_account", JSON.stringify(currentAccount));
sessionStorage.setItem(AUTH_ACCOUNT_KEY, JSON.stringify(currentAccount));
setAccount(currentAccount);
setMustChangePassword(Boolean(currentAccount.must_change_password));
if (currentAccount.account_type === "company" && currentAccount.is_domain_owner) {
@ -157,6 +163,7 @@ export default function DashboardPage() {
setLoading(false);
})
.catch(() => {
if (!getAccessToken()) return;
clearSession();
window.location.replace("/login");
});
@ -176,10 +183,24 @@ export default function DashboardPage() {
function closeMobileMenu() {
if (window.matchMedia("(max-width: 767.98px)").matches) {
setMenuOpen(false);
setMobileMenuOpen(false);
}
}
function toggleSidebar() {
if (window.matchMedia("(max-width: 767.98px)").matches) {
setMobileMenuOpen(false);
return;
}
setSidebarExpanded((open) => !open);
}
const sidebarClasses = [
"dashboard-sidebar",
mobileMenuOpen ? "open" : "",
sidebarExpanded ? "expanded" : "",
].filter(Boolean).join(" ");
function selectCompanyItem(label) {
setCompanyActive(label);
setAgentNav(null);
@ -251,6 +272,19 @@ export default function DashboardPage() {
triggerOpenCompose(context);
}
function openProfile() {
setCompanyActive(null);
setActive("Profile");
setAgentNav(null);
closeMobileMenu();
setSheet(null);
}
function updateAccount(next) {
setAccount(next);
sessionStorage.setItem("agmail_account", JSON.stringify(next));
}
function openExternalThread(threadId) {
setCompanyActive(null);
setActive("Inbox");
@ -323,22 +357,24 @@ export default function DashboardPage() {
data-onboarding={isOrgOnboarding ? "true" : undefined}
>
<header className="dashboard-mobile-header">
<Brand />
<button aria-label="Open navigation" type="button" onClick={() => { setSheet(null); setMenuOpen(true); }}>
<Brand forceHome />
<button aria-label="Open navigation" type="button" onClick={() => { setSheet(null); setMobileMenuOpen(true); }}>
<Menu size={21} />
</button>
</header>
{menuOpen && <button className="dashboard-scrim" aria-label="Close navigation" onClick={() => setMenuOpen(false)} />}
<aside className={menuOpen ? "dashboard-sidebar open" : "dashboard-sidebar"}>
{mobileMenuOpen && (
<button className="dashboard-scrim" aria-label="Close navigation" onClick={() => setMobileMenuOpen(false)} />
)}
<aside className={sidebarClasses}>
<div className="dashboard-brand-row">
<Brand />
<Brand forceHome />
<button
aria-label={menuOpen ? "Collapse navigation" : "Expand navigation"}
aria-label={(mobileMenuOpen || sidebarExpanded) ? "Collapse navigation" : "Expand navigation"}
type="button"
onClick={() => setMenuOpen((open) => !open)}
onClick={toggleSidebar}
>
{menuOpen ? <X size={19} /> : <PanelLeftOpen size={19} />}
{(mobileMenuOpen || sidebarExpanded) ? <X size={19} /> : <Menu size={19} />}
</button>
</div>
@ -452,8 +488,13 @@ export default function DashboardPage() {
</div>
<div className="dashboard-profile">
<span>{account.first_name[0]}{account.last_name[0]}</span>
{account.profile_picture_url ? (
<img src={account.profile_picture_url} alt="" className="dashboard-profile-photo" />
) : (
<span>{account.first_name[0]}{account.last_name[0]}</span>
)}
<div><strong>{account.first_name} {account.last_name}</strong><small>{account.email}</small></div>
<button aria-label="Open profile" title="Profile" type="button" onClick={openProfile}><UserRound size={17} /></button>
<button aria-label="Log out" title="Log out" type="button" onClick={logout}><LogOut size={17} /></button>
</div>
</aside>
@ -485,6 +526,8 @@ export default function DashboardPage() {
initialThreadId={openThreadId}
onLogout={logout}
onOpenSettings={() => selectMailItem("Settings")}
onOpenProfile={openProfile}
onAccountUpdate={updateAccount}
onCompose={openCompose}
onStats={handleStats}
/>
@ -497,6 +540,8 @@ export default function DashboardPage() {
account={account}
onLogout={logout}
onOpenSettings={() => selectMailItem("Settings")}
onOpenProfile={openProfile}
onAccountUpdate={updateAccount}
onCompose={openCompose}
/>
)}
@ -508,9 +553,14 @@ export default function DashboardPage() {
account={account}
onLogout={logout}
onOpenSettings={() => selectMailItem("Settings")}
onOpenProfile={openProfile}
onAccountUpdate={updateAccount}
onCompose={openCompose}
/>
)}
{!companyActive && active === "Profile" && (
<AccountProfile account={account} onUpdated={updateAccount} />
)}
{companyActive === "Overview" && isDomainOwner && !isOrgSetupComplete(account.id) && (
<CompanyOverviewSetup
account={account}
@ -556,7 +606,10 @@ export default function DashboardPage() {
<p>Company {companyActive.toLowerCase()} controls will appear here.</p>
</section>
)}
{!companyActive && !["Inbox", "Outbox", "Trash"].includes(active) && (
{!companyActive && active === "Settings" && (
<AccountSettings />
)}
{!companyActive && !["Inbox", "Outbox", "Trash", "Settings"].includes(active) && (
<section className="dashboard-empty">
<span><Sparkles size={24} /></span>
<h2>{active} is ready for you</h2>