Fix organizations page layout + search input display logic

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-01-19 17:17:07 +04:00
parent edb68671ec
commit 63390db416
8 changed files with 75 additions and 35 deletions

View File

@@ -107,16 +107,14 @@ export function MembershipsPage(props: {
{__("Your organizations")}
</h2>
)}
{memberships.length > 3 && (
<div className="w-full">
<Input
icon={IconMagnifyingGlass}
placeholder={__("Search organizations...")}
value={search}
onValueChange={setSearch}
/>
</div>
)}
<div className="w-full">
<Input
icon={IconMagnifyingGlass}
placeholder={__("Search organizations...")}
value={search}
onValueChange={setSearch}
/>
</div>
{memberships.length === 0 ? (
<div className="text-center text-txt-secondary py-4">
{__("No organizations found")}

View File

@@ -1,6 +1,6 @@
import { graphql, usePreloadedQuery, type PreloadedQuery } from "react-relay";
import { Outlet } from "react-router";
import { CenteredLayout, Layout, Skeleton } from "@probo/ui";
import { Layout, Skeleton } from "@probo/ui";
import type { ViewerLayoutQuery } from "/__generated__/iam/ViewerLayoutQuery.graphql";
import { Suspense } from "react";
import { ViewerDropdown } from "./_components/ViewerDropdown";
@@ -34,9 +34,7 @@ export function ViewerLayout(props: {
</div>
}
>
<CenteredLayout>
<Outlet />
</CenteredLayout>
<Outlet />
</Layout>
);
}

View File

@@ -1,9 +1,9 @@
import { useQueryLoader } from "react-relay";
import { Suspense, useEffect } from "react";
import { CenteredLayoutSkeleton } from "@probo/ui";
import type { ViewerLayoutQuery } from "/__generated__/iam/ViewerLayoutQuery.graphql";
import { ViewerLayout, viewerLayoutQuery } from "./ViewerLayout";
import { IAMRelayProvider } from "/providers/IAMRelayProvider";
import { ViewerLayoutLoading } from "./ViewerLayoutLoading";
function ViewerLayoutLoader() {
const [queryRef, loadQuery] =
@@ -14,11 +14,11 @@ function ViewerLayoutLoader() {
}, [loadQuery]);
if (!queryRef) {
return <CenteredLayoutSkeleton />;
return <ViewerLayoutLoading />;
}
return (
<Suspense fallback={<CenteredLayoutSkeleton />}>
<Suspense fallback={<ViewerLayoutLoading />}>
<ViewerLayout queryRef={queryRef} />
</Suspense>
);

View File

@@ -0,0 +1,16 @@
import { Layout, Skeleton } from "@probo/ui";
import { Outlet } from "react-router";
export function ViewerLayoutLoading() {
return (
<Layout
headerTrailing={
<div className="ml-auto">
<Skeleton className="w-32 h-8" />
</div>
}
>
<Outlet />
</Layout>
);
}

View File

@@ -1,8 +1,15 @@
import { useTranslate } from "@probo/i18n";
import { Button, Card, Field, PageHeader, useToast } from "@probo/ui";
import {
Button,
Card,
Field,
IconChevronLeft,
PageHeader,
useToast,
} from "@probo/ui";
import { graphql, useMutation } from "react-relay";
import type { FormEventHandler } from "react";
import { useNavigate } from "react-router";
import { Link, useLocation, useNavigate } from "react-router";
import { formatError } from "@probo/helpers";
import type { NewOrganizationPageMutation } from "/__generated__/iam/NewOrganizationPageMutation.graphql";
import { IAMRelayProvider } from "/providers/IAMRelayProvider";
@@ -19,6 +26,7 @@ const createOrganizationMutation = graphql`
`;
function NewOrganizationPage() {
const location = useLocation();
const navigate = useNavigate();
const { toast } = useToast();
const { __ } = useTranslate();
@@ -75,6 +83,13 @@ function NewOrganizationPage() {
return (
<div className="space-y-6">
<Link
to={location.state?.from ?? "/"}
className="mb-4 inline-flex gap-2 items-center"
>
<IconChevronLeft size={16} />
{__("Back")}
</Link>
<PageHeader
title={__("Create Organization")}
description={__(

View File

@@ -15,7 +15,7 @@ import {
import { Suspense, useCallback, useState } from "react";
import { useTranslate } from "@probo/i18n";
import type { MembershipsDropdownMenuQuery } from "/__generated__/iam/MembershipsDropdownMenuQuery.graphql";
import { Link } from "react-router";
import { Link, useLocation } from "react-router";
import type { MembershipsDropdown_organizationFragment$key } from "/__generated__/iam/MembershipsDropdown_organizationFragment.graphql";
import type { MembershipsDropdown_viewerFragment$key } from "/__generated__/iam/MembershipsDropdown_viewerFragment.graphql";
import {
@@ -42,6 +42,7 @@ export function MembershipsDropdown(props: {
}) {
const { organizationFKey, viewerFKey } = props;
const location = useLocation();
const { __ } = useTranslate();
const [search, setSearch] = useState("");
@@ -119,7 +120,7 @@ export function MembershipsDropdown(props: {
</DropdownItem>
)}
<DropdownItem asChild>
<Link to="/organizations/new">
<Link to="/organizations/new" state={{ from: location.pathname }}>
<IconPlusLarge size={16} />
{__("Add organization")}
</Link>

View File

@@ -4,7 +4,6 @@ import {
redirect,
useRouteError,
} from "react-router";
import { CenteredLayoutSkeleton } from "@probo/ui";
import { PageSkeleton } from "./components/skeletons/PageSkeleton.tsx";
import { riskRoutes } from "./routes/riskRoutes.ts";
import { measureRoutes } from "./routes/measureRoutes.ts";
@@ -36,6 +35,8 @@ import {
} from "@probo/relay";
import { CurrentUser } from "./providers/CurrentUser.tsx";
import { use } from "react";
import { ViewerLayoutLoading } from "./pages/iam/memberships/ViewerLayoutLoading.tsx";
import { CenteredLayout } from "@probo/ui";
/**
* Top level error boundary
@@ -104,7 +105,7 @@ const routes = [
{
path: "/",
Component: lazy(() => import("./pages/iam/memberships/ViewerLayoutLoader")),
Fallback: CenteredLayoutSkeleton,
Fallback: ViewerLayoutLoading,
ErrorBoundary: ErrorBoundary,
children: [
{
@@ -114,18 +115,27 @@ const routes = [
),
},
{
path: "organizations/new",
Component: lazy(
() => import("./pages/iam/organizations/NewOrganizationPage"),
),
},
{
path: "documents/signing-requests",
Component: lazy(() => import("./pages/DocumentSigningRequestsPage")),
},
{
path: "me/api-keys",
Component: lazy(() => import("./pages/iam/apiKeys/APIKeysPageLoader")),
Component: CenteredLayout,
children: [
{
path: "organizations/new",
Component: lazy(
() => import("./pages/iam/organizations/NewOrganizationPage"),
),
},
{
path: "documents/signing-requests",
Component: lazy(
() => import("./pages/DocumentSigningRequestsPage"),
),
},
{
path: "me/api-keys",
Component: lazy(
() => import("./pages/iam/apiKeys/APIKeysPageLoader"),
),
},
],
},
],
},