diff --git a/apps/web/src/components/public/public-frame.tsx b/apps/web/src/components/public/public-frame.tsx index 7b1d710..2a76dbc 100644 --- a/apps/web/src/components/public/public-frame.tsx +++ b/apps/web/src/components/public/public-frame.tsx @@ -3,12 +3,13 @@ import type { ReactNode } from "react"; import { CustomCss } from "@/components/branding/custom-css"; import { ThemeSwitch } from "@/components/dashboard-kit/theme-switch"; -import { SignOut } from "@/components/icons"; import { DiscordMark } from "@/components/icons/brand-marks"; +import { accountCopy, dashboardLinks } from "@/components/site/account"; +import { AccountMenu } from "@/components/site/account-menu"; import { LanguagePicker } from "@/components/site/language-picker"; import { getCurrentUser } from "@/lib/auth"; -import { logoutAction } from "@/lib/auth-actions"; import { brandProps, logoUrl } from "@/lib/branding"; +import { requestHostname } from "@/lib/custom-domain"; import { getDict, getLocale } from "@/i18n"; import { PoweredBy } from "./powered-by"; @@ -25,7 +26,8 @@ export interface PublicGuild { * controls, focus); the colour is the customer's, with a readable fallback * per theme (lib/branding.ts). No msk-scripts.de navigation: the page belongs * to the guild, and only a small "Powered by" line on the Free plan says who - * runs it. + * runs it. A signed-in visitor gets the site's account menu, so the way into + * the dashboard is the same here as on the site pages. * * Three layers, each for a reason: * - the outer wrapper carries the accent (`brandProps`), so the bar, the @@ -51,7 +53,12 @@ export async function PublicFrame({ poweredBy?: boolean; children: ReactNode; }) { - const [dict, locale, user] = await Promise.all([getDict(), getLocale(), getCurrentUser()]); + const [dict, locale, user, host] = await Promise.all([ + getDict(), + getLocale(), + getCurrentUser(), + requestHostname(), + ]); const logo = logoUrl(guild.id, guild.branding); // Same-origin login link on every host. The login route is host-aware: on // a custom domain with its own Discord OAuth app it runs the whole flow @@ -90,35 +97,15 @@ export async function PublicFrame({ className="hidden sm:inline-flex" /> {user ? ( -
++ {copy.account} +
+ {user ? ( + <> ++ {copy.signedInAs.replace("{name}", user.username)} +
++ {copy.theme.group} +
+- {copy.account} -
- {user ? ( - <> -- {copy.signedInAs.replace("{name}", user.username)} -
-- {copy.theme.group} -
-