domain migration

This commit is contained in:
debu-2 2026-10-04 14:40:06 +05:30
parent 192b810eb4
commit c04a6ce6fe
26 changed files with 777 additions and 125 deletions

View file

@ -1,7 +1,12 @@
import {
ChevronDown,
CircleDollarSign,
CircleEllipsis,
Clock3,
Crown,
FileEdit,
Globe,
Home,
Inbox,
ListChecks,
LogOut,
@ -10,16 +15,20 @@ import {
Plug,
Send,
Settings,
Shield,
ShieldAlert,
Sparkles,
Star,
Trash2,
Users,
UsersRound,
X,
} from "lucide-react";
import { useCallback, useEffect, useState } from "react";
import { getCurrentAccount, getMyCompanyDomain } from "../api";
import Brand from "./Brand";
import CompanyDnsSetup from "./CompanyDnsSetup";
import CompanyOverviewSetup, { isOrgSetupComplete } from "./CompanyOverviewSetup";
import ComposeModal from "./ComposeModal";
import MailboxView from "./MailboxView";
@ -49,6 +58,18 @@ const agentItems = [
[Plug, "Integrations", "integrations"],
];
const companyItems = [
[Home, "Overview"],
[Users, "People"],
[UsersRound, "Groups"],
[Globe, "Domains"],
[CircleEllipsis, "Aliases"],
[Shield, "Security"],
[Crown, "Administrators"],
[CircleDollarSign, "Billing"],
[Settings, "Settings"],
];
function clearSession() {
sessionStorage.removeItem("agmail_access_token");
sessionStorage.removeItem("agmail_account");
@ -82,6 +103,7 @@ export default function DashboardPage() {
const [lens, setLens] = useState("all");
const [agentNav, setAgentNav] = useState(null);
const [labelsExpanded, setLabelsExpanded] = useState(false);
const [companyActive, setCompanyActive] = useState(null);
const [mailStats, setMailStats] = useState({
unread: 0,
starred: 0,
@ -103,7 +125,7 @@ export default function DashboardPage() {
.then(async (currentAccount) => {
sessionStorage.setItem("agmail_account", JSON.stringify(currentAccount));
setAccount(currentAccount);
if (currentAccount.account_type === "company") {
if (currentAccount.account_type === "company" && currentAccount.is_domain_owner) {
try {
const domain = await getMyCompanyDomain(token);
setCompanyDomain(domain);
@ -120,12 +142,26 @@ export default function DashboardPage() {
});
}, []);
useEffect(() => {
if (!account?.is_domain_owner || needsDnsSetup) return;
if (!isOrgSetupComplete(account.id)) {
setCompanyActive("Overview");
}
}, [account, needsDnsSetup]);
function logout() {
clearSession();
window.location.assign("/login");
}
function selectCompanyItem(label) {
setCompanyActive(label);
setAgentNav(null);
setMenuOpen(false);
}
function selectMailItem(item) {
setCompanyActive(null);
setAgentNav(null);
if (item === "Starred") {
setActive("Inbox");
@ -141,6 +177,7 @@ export default function DashboardPage() {
}
function selectLabel(name) {
setCompanyActive(null);
setAgentNav(null);
setActive("Inbox");
setLens(name);
@ -148,6 +185,7 @@ export default function DashboardPage() {
}
function selectAgentItem(item, actionKey) {
setCompanyActive(null);
setActive("Inbox");
setLens("all");
setAgentNav(actionKey);
@ -190,6 +228,7 @@ export default function DashboardPage() {
onComplete={() => {
setCompanyDomain({ ...companyDomain, status: "active" });
setNeedsDnsSetup(false);
setCompanyActive("Overview");
}}
onLogout={logout}
/>
@ -200,6 +239,7 @@ export default function DashboardPage() {
const workspaceTitle = account.account_type === "company" && companyDomain
? companyDomain.domain_name
: "Personal workspace";
const isDomainOwner = account.account_type === "company" && account.is_domain_owner;
const mailActive = lens === "starred"
? "Starred"
: active === "Outbox"
@ -236,6 +276,24 @@ export default function DashboardPage() {
</button>
</div>
{isDomainOwner && (
<SidebarSection title="Company" className="dashboard-sidebar-company dashboard-sidebar-first">
<nav aria-label="Company">
{companyItems.map(([ItemIcon, label]) => (
<button
className={`dashboard-nav-item dashboard-company-item${companyActive === label ? " active" : ""}`}
key={label}
type="button"
onClick={() => selectCompanyItem(label)}
>
<ItemIcon size={16} strokeWidth={1.75} />
<span>{label}</span>
</button>
))}
</nav>
</SidebarSection>
)}
<SidebarSection title="Mail" className="dashboard-sidebar-mail">
<nav aria-label="Mail">
{mailItems.map(([ItemIcon, label, countKey]) => (
@ -303,13 +361,19 @@ export default function DashboardPage() {
</aside>
<main className="dashboard-content">
{!["Inbox", "Outbox", "Trash"].includes(active) && (
{companyActive && companyActive !== "Overview" && (
<div className="dashboard-content-heading">
<div><p>{workspaceTitle}</p><h1>{companyActive}</h1></div>
<span className="dashboard-account-pill">{workspaceLabel}</span>
</div>
)}
{!companyActive && !["Inbox", "Outbox", "Trash"].includes(active) && (
<div className="dashboard-content-heading">
<div><p>{workspaceTitle}</p><h1>{active}</h1></div>
<span className="dashboard-account-pill">{workspaceLabel}</span>
</div>
)}
{active === "Inbox" && (
{!companyActive && active === "Inbox" && (
<MailboxView
mailbox="inbox"
title="Inbox"
@ -322,7 +386,7 @@ export default function DashboardPage() {
onStats={handleStats}
/>
)}
{active === "Outbox" && (
{!companyActive && active === "Outbox" && (
<MailboxView
mailbox="sent"
title="Sent"
@ -332,7 +396,7 @@ export default function DashboardPage() {
onOpenSettings={() => selectMailItem("Settings")}
/>
)}
{active === "Trash" && (
{!companyActive && active === "Trash" && (
<MailboxView
mailbox="trash"
title="Trash"
@ -342,7 +406,28 @@ export default function DashboardPage() {
onOpenSettings={() => selectMailItem("Settings")}
/>
)}
{!["Inbox", "Outbox", "Trash"].includes(active) && (
{companyActive === "Overview" && isDomainOwner && (
<CompanyOverviewSetup
account={account}
companyDomain={companyDomain}
onComplete={() => {
setCompanyActive(null);
setActive("Inbox");
}}
/>
)}
{companyActive && companyActive !== "Overview" && (
<section className="dashboard-empty dashboard-company-view">
<span><Sparkles size={24} /></span>
<h2>{companyActive}</h2>
<p>
{companyActive === "Domains" && companyDomain
? `Manage DNS and delivery for ${companyDomain.domain_name}.`
: `Company ${companyActive.toLowerCase()} controls will appear here.`}
</p>
</section>
)}
{!companyActive && !["Inbox", "Outbox", "Trash"].includes(active) && (
<section className="dashboard-empty">
<span><Sparkles size={24} /></span>
<h2>{active} is ready for you</h2>