diff --git a/apps/compliance-portal/src/pages/PlaceholderPage.tsx b/apps/compliance-portal/src/components/HeaderBand/HeaderBand.tsx similarity index 57% rename from apps/compliance-portal/src/pages/PlaceholderPage.tsx rename to apps/compliance-portal/src/components/HeaderBand/HeaderBand.tsx index a9b3c0e29..b724a5024 100644 --- a/apps/compliance-portal/src/pages/PlaceholderPage.tsx +++ b/apps/compliance-portal/src/components/HeaderBand/HeaderBand.tsx @@ -12,19 +12,20 @@ // OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. -import { Heading } from "@probo/ui/src/v2/typography/Heading"; -import { useLocation } from "react-router"; +import type { PropsWithChildren } from "react"; -// Temporary stub for the Trust Center sections so the top-bar nav links resolve -// and the active state renders. Real pages replace these per section. -export default function PlaceholderPage() { - const { pathname } = useLocation(); - const segment = pathname.replace(/^\//, "").split("/")[0] ?? ""; - const title = segment.charAt(0).toUpperCase() + segment.slice(1); +import { headerBand } from "./variants"; + +export type HeaderBandProps = PropsWithChildren; + +// Pure layout shell: the white band + centered content column. Consumers (Hero, +// PageHeader) supply a single content column and own its internal spacing. +export function HeaderBand({ children }: HeaderBandProps) { + const { band, inner } = headerBand(); return ( -
- {title} -
+
+
{children}
+
); } diff --git a/apps/compliance-portal/src/components/HeaderBand/variants.ts b/apps/compliance-portal/src/components/HeaderBand/variants.ts new file mode 100644 index 000000000..b57ff80d1 --- /dev/null +++ b/apps/compliance-portal/src/components/HeaderBand/variants.ts @@ -0,0 +1,25 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { tv } from "tailwind-variants/lite"; + +// The white header band that sits over the grey body: full-width surface with a +// bottom border and a centered max-w-5xl content column. Shared by the landing +// Hero and the page headers so the band is defined once. +export const headerBand = tv({ + slots: { + band: "flex w-full flex-col items-center border-b border-sand-6 bg-sand-1 px-8 py-8", + inner: "w-full max-w-5xl", + }, +}); diff --git a/apps/compliance-portal/src/components/Hero/Hero.tsx b/apps/compliance-portal/src/components/Hero/Hero.tsx new file mode 100644 index 000000000..e851983a8 --- /dev/null +++ b/apps/compliance-portal/src/components/Hero/Hero.tsx @@ -0,0 +1,53 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { Heading } from "@probo/ui/src/v2/typography/Heading"; +import { Text } from "@probo/ui/src/v2/typography/Text"; +import type { ReactNode } from "react"; + +import { HeaderBand } from "#/components/HeaderBand/HeaderBand"; + +import { hero } from "./variants"; + +export interface HeroProps { + title: ReactNode; + description?: ReactNode; + children?: ReactNode; +} + +// Landing hero (home): a size-8 title (+ optional description) in the shared +// white band, plus an optional bottom slot for page-specific content (the org +// contact row). The slot content owns its own divider/spacing so it disappears +// cleanly when empty. +export function Hero({ title, description, children }: HeroProps) { + const { content, section } = hero(); + + return ( + +
+
+ + {title} + + {description != null && description !== "" && ( + + {description} + + )} +
+ {children} +
+
+ ); +} diff --git a/apps/compliance-portal/src/components/Hero/HeroSkeleton.tsx b/apps/compliance-portal/src/components/Hero/HeroSkeleton.tsx new file mode 100644 index 000000000..5feb14088 --- /dev/null +++ b/apps/compliance-portal/src/components/Hero/HeroSkeleton.tsx @@ -0,0 +1,47 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { HeadingSkeleton } from "@probo/ui/src/v2/typography/HeadingSkeleton"; +import { TextSkeleton } from "@probo/ui/src/v2/typography/TextSkeleton"; + +import { HeaderBand } from "#/components/HeaderBand/HeaderBand"; + +import { hero, organizationContactInfo } from "./variants"; + +const CONTACT_ITEM_KEYS = ["website", "email", "location"] as const; + +// Loading placeholder paired with Hero: reuses the same layout slots with +// skeleton primitives. Imports no Relay, so it renders instantly. +export function HeroSkeleton() { + const { content, section } = hero(); + const { root, item } = organizationContactInfo(); + + return ( + +
+
+ + +
+
+ {CONTACT_ITEM_KEYS.map(key => ( +
+ +
+ ))} +
+
+
+ ); +} diff --git a/apps/compliance-portal/src/components/Hero/OrganizationContactInfo.tsx b/apps/compliance-portal/src/components/Hero/OrganizationContactInfo.tsx new file mode 100644 index 000000000..7e2f85db4 --- /dev/null +++ b/apps/compliance-portal/src/components/Hero/OrganizationContactInfo.tsx @@ -0,0 +1,85 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { EnvelopeIcon, GlobeSimpleIcon, MapPinSimpleIcon } from "@phosphor-icons/react"; +import { Text } from "@probo/ui/src/v2/typography/Text"; +import { graphql, useFragment } from "react-relay"; + +import { hostnameOf } from "#/lib/url/hostname"; + +import type { OrganizationContactInfo_organization$key } from "./__generated__/OrganizationContactInfo_organization.graphql"; +import { organizationContactInfo } from "./variants"; + +const organizationContactInfoFragment = graphql` + fragment OrganizationContactInfo_organization on Organization { + websiteUrl + email + headquarterAddress + } +`; + +interface OrganizationContactInfoProps { + organizationKey: OrganizationContactInfo_organization$key; +} + +// Organization contact details (website, email, HQ) rendered as an icon + label +// row. Owns its fragment so it can be reused wherever the org is in scope. +export function OrganizationContactInfo({ organizationKey }: OrganizationContactInfoProps) { + const organization = useFragment(organizationContactInfoFragment, organizationKey); + + const hasWebsite = organization.websiteUrl != null && organization.websiteUrl !== ""; + const hasEmail = organization.email != null && organization.email !== ""; + const hasAddress = organization.headquarterAddress != null && organization.headquarterAddress !== ""; + + // Nothing to show — render no row (and therefore no divider) at all. + if (!hasWebsite && !hasEmail && !hasAddress) { + return null; + } + + const { root, item, link } = organizationContactInfo(); + + return ( +
+ {hasWebsite && ( + + + + {hostnameOf(organization.websiteUrl)} + + + )} + {hasEmail && ( + + + + {organization.email} + + + )} + {hasAddress && ( +
+ + + {organization.headquarterAddress} + +
+ )} +
+ ); +} diff --git a/apps/compliance-portal/src/components/Hero/variants.ts b/apps/compliance-portal/src/components/Hero/variants.ts new file mode 100644 index 000000000..8a9a6ed16 --- /dev/null +++ b/apps/compliance-portal/src/components/Hero/variants.ts @@ -0,0 +1,37 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { tv } from "tailwind-variants/lite"; + +// Landing hero content rendered inside the shared HeaderBand: a centered +// title/description section above an optional bottom slot (the contact row). +// Slots are shared by the live Hero and its skeleton. +export const hero = tv({ + slots: { + content: "flex w-full flex-col gap-10", + section: "flex w-full flex-col gap-4", + }, +}); + +// Organization contact block: a horizontal row of icon + label items, with a +// top divider so it reads as the hero's bottom section. Self-contained so the +// divider only appears when there is contact info to show. +export const organizationContactInfo = tv({ + slots: { + // Only a top divider gap; the band's py-8 provides the bottom spacing. + root: "flex w-full items-center gap-6 border-t border-sand-6 pt-4", + item: "flex items-center gap-2 text-sand-11 [&_svg]:size-5", + link: "flex items-center gap-2 text-sand-11 hover:underline [&_svg]:size-5", + }, +}); diff --git a/apps/compliance-portal/src/components/PageHeader/PageHeader.tsx b/apps/compliance-portal/src/components/PageHeader/PageHeader.tsx new file mode 100644 index 000000000..1ba9f2cd5 --- /dev/null +++ b/apps/compliance-portal/src/components/PageHeader/PageHeader.tsx @@ -0,0 +1,51 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { Heading } from "@probo/ui/src/v2/typography/Heading"; +import type { ReactNode } from "react"; + +import { HeaderBand } from "#/components/HeaderBand/HeaderBand"; + +import { pageHeader } from "./variants"; + +export interface PageHeaderProps { + title: ReactNode; + // Optional muted item count appended to the title (e.g. "Documents (3)"). + count?: number; + // Right-aligned controls on the title line (e.g. a "New Request" button). + actions?: ReactNode; + // Optional toolbar (tabs / filters / search) rendered below the title. + children?: ReactNode; +} + +// Page header for the Trust Center nav pages: a size-7 title in the shared white +// band, with an optional count, inline actions, and a toolbar slot below. +export function PageHeader({ title, count, actions, children }: PageHeaderProps) { + const { content, titleRow, count: countSlot } = pageHeader(); + + return ( + +
+
+ + {title} + {count != null && {` (${count})`}} + + {actions} +
+ {children} +
+
+ ); +} diff --git a/apps/compliance-portal/src/components/PageHeader/variants.ts b/apps/compliance-portal/src/components/PageHeader/variants.ts new file mode 100644 index 000000000..cd1de99ff --- /dev/null +++ b/apps/compliance-portal/src/components/PageHeader/variants.ts @@ -0,0 +1,26 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { tv } from "tailwind-variants/lite"; + +// Page header content rendered inside the shared HeaderBand: a size-7 title row +// (with optional count and right-aligned actions) above an optional toolbar. +export const pageHeader = tv({ + slots: { + content: "flex w-full flex-col gap-2", + titleRow: "flex w-full items-center justify-between gap-4", + // Muted item count appended to the title (e.g. "Documents (3)"). + count: "font-light text-sand-8", + }, +}); diff --git a/apps/compliance-portal/src/components/TopBar/variants.ts b/apps/compliance-portal/src/components/TopBar/variants.ts index 5a1dcfef4..44232604c 100644 --- a/apps/compliance-portal/src/components/TopBar/variants.ts +++ b/apps/compliance-portal/src/components/TopBar/variants.ts @@ -19,7 +19,7 @@ import { tv } from "tailwind-variants/lite"; export const topBar = tv({ slots: { bar: "flex h-14 items-center bg-sand-1 px-8", - inner: "mx-auto flex w-full max-w-[1024px] items-center gap-10", + inner: "mx-auto flex w-full max-w-5xl items-center gap-10", brand: "flex items-center gap-2", logo: "shrink-0", spacer: "h-px flex-1", diff --git a/apps/compliance-portal/src/lib/url/hostname.ts b/apps/compliance-portal/src/lib/url/hostname.ts new file mode 100644 index 000000000..6b7e69696 --- /dev/null +++ b/apps/compliance-portal/src/lib/url/hostname.ts @@ -0,0 +1,23 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +// Show only the hostname for a URL (e.g. "https://blaxel.ai/x" -> "blaxel.ai"), +// falling back to the raw value when it cannot be parsed. +export function hostnameOf(url: string): string { + try { + return new URL(url).host; + } catch { + return url; + } +} diff --git a/apps/compliance-portal/src/pages/DocumentsPage.tsx b/apps/compliance-portal/src/pages/DocumentsPage.tsx new file mode 100644 index 000000000..5c4ef0fd6 --- /dev/null +++ b/apps/compliance-portal/src/pages/DocumentsPage.tsx @@ -0,0 +1,21 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { PageHeader } from "#/components/PageHeader/PageHeader"; + +// Toolbar (All/Public/Private tabs, framework filter, search) and the document +// count are deferred until the v2 Tabs/Select/TextField components exist. +export default function DocumentsPage() { + return ; +} diff --git a/apps/compliance-portal/src/pages/HomePage.tsx b/apps/compliance-portal/src/pages/HomePage.tsx index 2c8b3f407..55cdd36d9 100644 --- a/apps/compliance-portal/src/pages/HomePage.tsx +++ b/apps/compliance-portal/src/pages/HomePage.tsx @@ -12,10 +12,37 @@ // OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. -export default function HomePage() { +import type { PreloadedQuery } from "react-relay"; +import { graphql, usePreloadedQuery } from "react-relay"; + +import { Hero } from "#/components/Hero/Hero"; +import { OrganizationContactInfo } from "#/components/Hero/OrganizationContactInfo"; + +import type { HomePageQuery } from "./__generated__/HomePageQuery.graphql"; + +export const homePageQuery = graphql` + query HomePageQuery { + currentTrustCenter @required(action: THROW) { + organization { + name + description + ...OrganizationContactInfo_organization + } + } + } +`; + +interface HomePageProps { + queryRef: PreloadedQuery; +} + +export function HomePage({ queryRef }: HomePageProps) { + const data = usePreloadedQuery(homePageQuery, queryRef); + const { organization } = data.currentTrustCenter; + return ( -
-

Compliance Portal

-
+ + + ); } diff --git a/apps/compliance-portal/src/pages/HomePageLoader.tsx b/apps/compliance-portal/src/pages/HomePageLoader.tsx new file mode 100644 index 000000000..400b6b114 --- /dev/null +++ b/apps/compliance-portal/src/pages/HomePageLoader.tsx @@ -0,0 +1,34 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { useEffect } from "react"; +import { useQueryLoader } from "react-relay"; + +import type { HomePageQuery } from "./__generated__/HomePageQuery.graphql"; +import { HomePage, homePageQuery } from "./HomePage"; +import { HomePageSkeleton } from "./HomePageSkeleton"; + +export default function HomePageLoader() { + const [queryRef, loadQuery] = useQueryLoader(homePageQuery); + + useEffect(() => { + loadQuery({}); + }, [loadQuery]); + + if (!queryRef) { + return ; + } + + return ; +} diff --git a/apps/compliance-portal/src/pages/HomePageSkeleton.tsx b/apps/compliance-portal/src/pages/HomePageSkeleton.tsx new file mode 100644 index 000000000..e2e694dab --- /dev/null +++ b/apps/compliance-portal/src/pages/HomePageSkeleton.tsx @@ -0,0 +1,19 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { HeroSkeleton } from "#/components/Hero/HeroSkeleton"; + +export function HomePageSkeleton() { + return ; +} diff --git a/apps/compliance-portal/src/pages/MainLayout.tsx b/apps/compliance-portal/src/pages/MainLayout.tsx index a810670ff..7e7303c79 100644 --- a/apps/compliance-portal/src/pages/MainLayout.tsx +++ b/apps/compliance-portal/src/pages/MainLayout.tsx @@ -34,7 +34,7 @@ export function MainLayout({ queryRef }: MainLayoutProps) { const data = usePreloadedQuery(mainLayoutQuery, queryRef); return ( -
+
diff --git a/apps/compliance-portal/src/pages/MainLayoutSkeleton.tsx b/apps/compliance-portal/src/pages/MainLayoutSkeleton.tsx index 74d354850..822be44c8 100644 --- a/apps/compliance-portal/src/pages/MainLayoutSkeleton.tsx +++ b/apps/compliance-portal/src/pages/MainLayoutSkeleton.tsx @@ -16,7 +16,7 @@ import { TopBarSkeleton } from "#/components/TopBar/TopBarSkeleton"; export function MainLayoutSkeleton() { return ( -
+
); diff --git a/apps/compliance-portal/src/pages/RequestsPage.tsx b/apps/compliance-portal/src/pages/RequestsPage.tsx new file mode 100644 index 000000000..bbf084f9d --- /dev/null +++ b/apps/compliance-portal/src/pages/RequestsPage.tsx @@ -0,0 +1,31 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { PlusIcon } from "@phosphor-icons/react"; +import { Button } from "@probo/ui/src/v2/Button/Button"; + +import { PageHeader } from "#/components/PageHeader/PageHeader"; + +export default function RequestsPage() { + return ( + }> + New Request + + )} + /> + ); +} diff --git a/apps/compliance-portal/src/pages/SubprocessorsPage.tsx b/apps/compliance-portal/src/pages/SubprocessorsPage.tsx new file mode 100644 index 000000000..6dc812a07 --- /dev/null +++ b/apps/compliance-portal/src/pages/SubprocessorsPage.tsx @@ -0,0 +1,21 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { PageHeader } from "#/components/PageHeader/PageHeader"; + +// Toolbar (category/region filters, search, Download CSV) and the subprocessor +// count are deferred until the v2 Select/TextField components exist. +export default function SubprocessorsPage() { + return ; +} diff --git a/apps/compliance-portal/src/pages/UpdatesPage.tsx b/apps/compliance-portal/src/pages/UpdatesPage.tsx new file mode 100644 index 000000000..f70e32415 --- /dev/null +++ b/apps/compliance-portal/src/pages/UpdatesPage.tsx @@ -0,0 +1,31 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { BellIcon } from "@phosphor-icons/react"; +import { Button } from "@probo/ui/src/v2/Button/Button"; + +import { PageHeader } from "#/components/PageHeader/PageHeader"; + +export default function UpdatesPage() { + return ( + }> + Subscribe to updates + + )} + /> + ); +} diff --git a/apps/compliance-portal/src/routes.tsx b/apps/compliance-portal/src/routes.tsx index d37a610ee..4e55ece32 100644 --- a/apps/compliance-portal/src/routes.tsx +++ b/apps/compliance-portal/src/routes.tsx @@ -18,6 +18,7 @@ import { createBrowserRouter } from "react-router"; import { PageSkeleton } from "#/components/skeletons/PageSkeleton"; import { getPathPrefix } from "#/lib/http/pathPrefix"; +import { HomePageSkeleton } from "#/pages/HomePageSkeleton"; const routes = [ { @@ -27,23 +28,24 @@ const routes = [ children: [ { index: true, - Component: lazy(() => import("#/pages/HomePage")), + Fallback: HomePageSkeleton, + Component: lazy(() => import("#/pages/HomePageLoader")), }, { path: "documents", - Component: lazy(() => import("#/pages/PlaceholderPage")), + Component: lazy(() => import("#/pages/DocumentsPage")), }, { path: "subprocessors", - Component: lazy(() => import("#/pages/PlaceholderPage")), + Component: lazy(() => import("#/pages/SubprocessorsPage")), }, { path: "updates", - Component: lazy(() => import("#/pages/PlaceholderPage")), + Component: lazy(() => import("#/pages/UpdatesPage")), }, { path: "requests", - Component: lazy(() => import("#/pages/PlaceholderPage")), + Component: lazy(() => import("#/pages/RequestsPage")), }, ], },