Add PageTemplate with skeletons and apply to Framework list

Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
Émile Ré
2025-03-21 13:42:39 +04:00
parent cee114089a
commit 51e4d7488f
21 changed files with 323 additions and 201 deletions

View File

@@ -12,6 +12,7 @@ import ConsoleLayout from "./layouts/ConsoleLayout";
import AuthLayout from "./layouts/AuthLayout"; import AuthLayout from "./layouts/AuthLayout";
import { RelayEnvironment } from "./RelayEnvironment"; import { RelayEnvironment } from "./RelayEnvironment";
import VisitorErrorBoundary from "./components/VisitorErrorBoundary"; import VisitorErrorBoundary from "./components/VisitorErrorBoundary";
import { FrameworkListPageSkeleton } from "./pages/FrameworkListPage";
posthog.init(process.env.POSTHOG_KEY!, { posthog.init(process.env.POSTHOG_KEY!, {
api_host: process.env.POSTHOG_HOST, api_host: process.env.POSTHOG_HOST,
@@ -145,7 +146,7 @@ function App() {
<Route <Route
path="frameworks" path="frameworks"
element={ element={
<Suspense> <Suspense fallback={<FrameworkListPageSkeleton />}>
<ErrorBoundaryWithLocation> <ErrorBoundaryWithLocation>
<FrameworkListPage /> <FrameworkListPage />
</ErrorBoundaryWithLocation> </ErrorBoundaryWithLocation>

View File

@@ -0,0 +1,26 @@
import { FC, ReactNode } from "react";
import { Helmet } from "react-helmet-async";
export interface PageContainerProps {
children: ReactNode;
title: string;
}
export const PageContainer: FC<PageContainerProps> = ({ children, title }) => {
return (
<>
<Helmet>{`${title} - Probo Console`}</Helmet>
<div className="container">{children}</div>
</>
);
};
export const PageContainerSkeleton: FC<{
title?: string;
children: ReactNode;
}> = ({ children, title }) =>
title ? (
<PageContainer title={title}>{children}</PageContainer>
) : (
<div className="container">{children}</div>
);

View File

@@ -0,0 +1,108 @@
import { cn } from "@/lib/utils";
import { FC, ReactNode } from "react";
export interface PageHeaderProps {
title: ReactNode;
actions?: ReactNode;
description?: ReactNode;
}
export function PageHeaderShell({
className,
title,
actions,
description,
}: PageHeaderProps & { className?: string }) {
return (
<div className={cn("space-y-6", className)}>
{actions ? (
<div className="flex items-center justify-between">
{title}
{actions}
</div>
) : (
title
)}
{description}
</div>
);
}
export function PageHeader({
className,
title,
actions,
description,
}: PageHeaderProps & { className?: string }) {
return (
<PageHeaderShell
className={className}
title={<PageHeading>{title}</PageHeading>}
description={<PageDescription>{description}</PageDescription>}
actions={actions}
/>
);
}
export function PageHeading({
children,
className,
}: {
className?: string;
children: ReactNode;
}) {
return <h1 className={cn("text-3xl font-medium", className)}>{children}</h1>;
}
const PageHeadingSkeleton: FC = () => {
return (
<div className="py-[3px]">
<div className="bg-muted animate rounded-lg w-60 h-7.5" />
</div>
);
};
export function PageDescription({
children,
className,
}: {
className?: string;
children: ReactNode;
}) {
return (
<p className={cn("text-md text-muted-foreground", className)}>{children}</p>
);
}
export function PageDescriptionSkeleton() {
return (
<div className="py-[5px]">
<div className="bg-muted animate rounded-md w-100 h-4.5" />
</div>
);
}
export const PageHeaderSkeleton: FC<{
className?: string;
title?: string;
actions?: ReactNode;
description?: ReactNode;
withDescription?: boolean;
}> = ({ className, title, actions, description, withDescription = false }) => {
return (
<PageHeaderShell
className={className}
title={
title ? <PageHeading>{title}</PageHeading> : <PageHeadingSkeleton />
}
description={
description ? (
<PageDescription>{description}</PageDescription>
) : withDescription ? (
<PageDescriptionSkeleton />
) : null
}
actions={actions}
/>
);
};

View File

@@ -0,0 +1,47 @@
import { FC, ReactNode } from "react";
import {
PageContainer,
PageContainerProps,
PageContainerSkeleton,
} from "./PageContainer";
import { PageHeader, PageHeaderProps, PageHeaderSkeleton } from "./PageHeader";
export const PageTemplate: FC<PageContainerProps & PageHeaderProps> = ({
actions,
title,
description,
children,
}) => {
return (
<PageContainer title={title}>
<PageHeader
className="mb-17"
title={title}
description={description}
actions={actions}
/>
{children}
</PageContainer>
);
};
export const PageTemplateSkeleton: FC<{
title?: string;
description?: ReactNode;
withDescription?: boolean;
actions?: ReactNode;
children: ReactNode;
}> = ({ actions, children, description, withDescription = false, title }) => {
return (
<PageContainerSkeleton title={title}>
<PageHeaderSkeleton
className="mb-17"
title={title}
description={description}
withDescription={withDescription}
actions={actions}
/>
{children}
</PageContainerSkeleton>
);
};

View File

@@ -75,7 +75,7 @@ import type { ControlOverviewPageAssignTaskMutation as ControlOverviewPageAssign
import type { ControlOverviewPageUnassignTaskMutation as ControlOverviewPageUnassignTaskMutationType } from "./__generated__/ControlOverviewPageUnassignTaskMutation.graphql"; import type { ControlOverviewPageUnassignTaskMutation as ControlOverviewPageUnassignTaskMutationType } from "./__generated__/ControlOverviewPageUnassignTaskMutation.graphql";
import type { ControlOverviewPageOrganizationQuery$data } from "./__generated__/ControlOverviewPageOrganizationQuery.graphql"; import type { ControlOverviewPageOrganizationQuery$data } from "./__generated__/ControlOverviewPageOrganizationQuery.graphql";
import type { ControlOverviewPageUpdateControlStateMutation as ControlOverviewPageUpdateControlStateMutationType } from "./__generated__/ControlOverviewPageUpdateControlStateMutation.graphql"; import type { ControlOverviewPageUpdateControlStateMutation as ControlOverviewPageUpdateControlStateMutationType } from "./__generated__/ControlOverviewPageUpdateControlStateMutation.graphql";
import { PageHeader } from "./PageHeader"; import { PageHeader } from "@/components/PageHeader";
// Function to format ISO8601 duration to human-readable format // Function to format ISO8601 duration to human-readable format
const formatDuration = (isoDuration: string): string => { const formatDuration = (isoDuration: string): string => {

View File

@@ -21,7 +21,7 @@ import {
CreateControlPageCreateControlMutation, CreateControlPageCreateControlMutation,
ControlImportance, ControlImportance,
} from "./__generated__/CreateControlPageCreateControlMutation.graphql"; } from "./__generated__/CreateControlPageCreateControlMutation.graphql";
import { PageHeader } from "./PageHeader"; import { PageHeader } from "@/components/PageHeader";
const createControlMutation = graphql` const createControlMutation = graphql`
mutation CreateControlPageCreateControlMutation( mutation CreateControlPageCreateControlMutation(

View File

@@ -10,7 +10,7 @@ import { useToast } from "@/hooks/use-toast";
import { HelpCircle } from "lucide-react"; import { HelpCircle } from "lucide-react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { CreatePeoplePageCreatePeopleMutation } from "./__generated__/CreatePeoplePageCreatePeopleMutation.graphql"; import { CreatePeoplePageCreatePeopleMutation } from "./__generated__/CreatePeoplePageCreatePeopleMutation.graphql";
import { PageHeader } from "./PageHeader"; import { PageHeader } from "@/components/PageHeader";
const createPeopleMutation = graphql` const createPeopleMutation = graphql`
mutation CreatePeoplePageCreatePeopleMutation( mutation CreatePeoplePageCreatePeopleMutation(

View File

@@ -21,7 +21,7 @@ import PeopleSelector from "@/components/PeopleSelector";
import { Suspense } from "react"; import { Suspense } from "react";
import type { CreatePolicyPageMutation } from "./__generated__/CreatePolicyPageMutation.graphql"; import type { CreatePolicyPageMutation } from "./__generated__/CreatePolicyPageMutation.graphql";
import type { CreatePolicyPageQuery as CreatePolicyPageQueryType } from "./__generated__/CreatePolicyPageQuery.graphql"; import type { CreatePolicyPageQuery as CreatePolicyPageQueryType } from "./__generated__/CreatePolicyPageQuery.graphql";
import { PageHeader } from "./PageHeader"; import { PageHeader } from "@/components/PageHeader";
const CreatePolicyQuery = graphql` const CreatePolicyQuery = graphql`
query CreatePolicyPageQuery($organizationId: ID!) { query CreatePolicyPageQuery($organizationId: ID!) {

View File

@@ -10,7 +10,6 @@ import {
import { Card, CardContent } from "@/components/ui/card"; import { Card, CardContent } from "@/components/ui/card";
import { Link, useParams } from "react-router"; import { Link, useParams } from "react-router";
import type { FrameworkListPageQuery as FrameworkListPageQueryType } from "./__generated__/FrameworkListPageQuery.graphql"; import type { FrameworkListPageQuery as FrameworkListPageQueryType } from "./__generated__/FrameworkListPageQuery.graphql";
import { Helmet } from "react-helmet-async";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Plus, Upload } from "lucide-react"; import { Plus, Upload } from "lucide-react";
import { useToast } from "@/hooks/use-toast"; import { useToast } from "@/hooks/use-toast";
@@ -24,7 +23,7 @@ import {
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { FrameworkListPageImportFrameworkMutation as FrameworkListPageImportFrameworkMutationType } from "./__generated__/FrameworkListPageImportFrameworkMutation.graphql"; import { FrameworkListPageImportFrameworkMutation as FrameworkListPageImportFrameworkMutationType } from "./__generated__/FrameworkListPageImportFrameworkMutation.graphql";
import { PageHeader } from "./PageHeader"; import { PageTemplate, PageTemplateSkeleton } from "@/components/PageTemplate";
const FrameworkListPageQuery = graphql` const FrameworkListPageQuery = graphql`
query FrameworkListPageQuery($organizationId: ID!) { query FrameworkListPageQuery($organizationId: ID!) {
@@ -191,13 +190,7 @@ function FrameworkListPageContent({
}; };
return ( return (
<> <PageTemplate
<Helmet>
<title>Frameworks - Probo</title>
</Helmet>
<div className="container">
<PageHeader
className="mb-17"
title="Frameworks" title="Frameworks"
description="Manage your compliance frameworks" description="Manage your compliance frameworks"
actions={ actions={
@@ -218,9 +211,7 @@ function FrameworkListPageContent({
</DialogHeader> </DialogHeader>
<div className="space-y-4 py-4"> <div className="space-y-4 py-4">
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="framework-file"> <Label htmlFor="framework-file">Upload Framework File</Label>
Upload Framework File
</Label>
<Input <Input
id="framework-file" id="framework-file"
type="file" type="file"
@@ -244,7 +235,7 @@ function FrameworkListPageContent({
</Button> </Button>
</div> </div>
} }
/> >
<div className="space-y-6"> <div className="space-y-6">
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-2"> <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-2">
{frameworks.map((framework) => { {frameworks.map((framework) => {
@@ -284,18 +275,22 @@ function FrameworkListPageContent({
})} })}
</div> </div>
</div> </div>
</div> </PageTemplate>
</>
); );
} }
function FrameworkListPageFallback() { export function FrameworkListPageSkeleton() {
return ( return (
<div className="space-y-6"> <PageTemplateSkeleton
<div> title="Frameworks"
<div className="h-8 w-48 bg-muted animate-pulse rounded" /> description="Manage your compliance frameworks"
<div className="h-4 w-96 bg-muted animate-pulse rounded mt-1" /> actions={
<div className="flex gap-4 w-1/3">
<div className="bg-muted animate-pulse h-9 w-1/2 rounded-lg" />
<div className="bg-muted animate-pulse h-9 w-1/2 rounded-lg" />
</div> </div>
}
>
<div className="grid gap-6 md:grid-cols-2"> <div className="grid gap-6 md:grid-cols-2">
{[1, 2].map((i) => ( {[1, 2].map((i) => (
<Card key={i} className="bg-card/50"> <Card key={i} className="bg-card/50">
@@ -310,7 +305,7 @@ function FrameworkListPageFallback() {
</Card> </Card>
))} ))}
</div> </div>
</div> </PageTemplateSkeleton>
); );
} }
@@ -326,13 +321,8 @@ export default function FrameworkListPage() {
}, [loadQuery, organizationId]); }, [loadQuery, organizationId]);
return ( return (
<> <Suspense fallback={<FrameworkListPageSkeleton />}>
<Helmet>
<title>Frameworks - Probo Console</title>
</Helmet>
<Suspense fallback={<FrameworkListPageFallback />}>
{queryRef && <FrameworkListPageContent queryRef={queryRef} />} {queryRef && <FrameworkListPageContent queryRef={queryRef} />}
</Suspense> </Suspense>
</>
); );
} }

View File

@@ -11,7 +11,7 @@ import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import type { FrameworkOverviewPageQuery as FrameworkOverviewPageQueryType } from "./__generated__/FrameworkOverviewPageQuery.graphql"; import type { FrameworkOverviewPageQuery as FrameworkOverviewPageQueryType } from "./__generated__/FrameworkOverviewPageQuery.graphql";
import { Helmet } from "react-helmet-async"; import { Helmet } from "react-helmet-async";
import { PageHeader } from "./PageHeader"; import { PageHeader } from "@/components/PageHeader";
const FrameworkOverviewPageQuery = graphql` const FrameworkOverviewPageQuery = graphql`
query FrameworkOverviewPageQuery($frameworkId: ID!) { query FrameworkOverviewPageQuery($frameworkId: ID!) {

View File

@@ -1,53 +0,0 @@
import { cn } from "@/lib/utils";
import { ReactNode } from "react";
export function PageHeader({
className,
children,
title,
actions,
description,
}: {
className?: string;
children?: ReactNode;
title: string;
actions?: ReactNode;
description?: string;
}) {
return (
<div className={cn("space-y-6", className)}>
{actions ? (
<div className="flex items-center justify-between">
<PageHeading title={title} />
{actions}
</div>
) : (
<PageHeading title={title} />
)}
{description && <PageDescription>{description}</PageDescription>}
{children}
</div>
);
}
export function PageHeading({
title,
className,
}: {
className?: string;
title: string;
}) {
return <h1 className={cn("text-3xl font-medium", className)}>{title}</h1>;
}
export function PageDescription({
children,
className,
}: {
className?: string;
children: ReactNode;
}) {
return (
<p className={cn("text-lg text-muted-foreground", className)}>{children}</p>
);
}

View File

@@ -18,7 +18,7 @@ import type { PeopleListPageQuery as PeopleListPageQueryType } from "./__generat
import type { PeopleListPageDeletePeopleMutation } from "./__generated__/PeopleListPageDeletePeopleMutation.graphql"; import type { PeopleListPageDeletePeopleMutation } from "./__generated__/PeopleListPageDeletePeopleMutation.graphql";
import { PeopleListPagePaginationQuery } from "./__generated__/PeopleListPagePaginationQuery.graphql"; import { PeopleListPagePaginationQuery } from "./__generated__/PeopleListPagePaginationQuery.graphql";
import { PeopleListPage_peoples$key } from "./__generated__/PeopleListPage_peoples.graphql"; import { PeopleListPage_peoples$key } from "./__generated__/PeopleListPage_peoples.graphql";
import { PageHeader } from "./PageHeader"; import { PageHeader } from "@/components/PageHeader";
const ITEMS_PER_PAGE = 25; const ITEMS_PER_PAGE = 25;

View File

@@ -18,7 +18,7 @@ import type { PeopleOverviewPageQuery as PeopleOverviewPageQueryType } from "./_
import { useParams } from "react-router"; import { useParams } from "react-router";
import { Helmet } from "react-helmet-async"; import { Helmet } from "react-helmet-async";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { PageHeader } from "./PageHeader"; import { PageHeader } from "@/components/PageHeader";
const peopleOverviewPageQuery = graphql` const peopleOverviewPageQuery = graphql`
query PeopleOverviewPageQuery($peopleId: ID!) { query PeopleOverviewPageQuery($peopleId: ID!) {

View File

@@ -34,7 +34,7 @@ import {
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { format } from "date-fns"; import { format } from "date-fns";
import type { PolicyListPageQuery as PolicyListPageQueryType } from "./__generated__/PolicyListPageQuery.graphql"; import type { PolicyListPageQuery as PolicyListPageQueryType } from "./__generated__/PolicyListPageQuery.graphql";
import { PageHeader } from "./PageHeader"; import { PageHeader } from "@/components/PageHeader";
const PolicyListPageQuery = graphql` const PolicyListPageQuery = graphql`
query PolicyListPageQuery($organizationId: ID!) { query PolicyListPageQuery($organizationId: ID!) {

View File

@@ -18,7 +18,7 @@ import type { PolicyOverviewPageDeleteMutation } from "./__generated__/PolicyOve
import { Helmet } from "react-helmet-async"; import { Helmet } from "react-helmet-async";
import "../styles/policy-content.css"; import "../styles/policy-content.css";
import { useToast } from "@/hooks/use-toast"; import { useToast } from "@/hooks/use-toast";
import { PageHeader } from "./PageHeader"; import { PageHeader } from "@/components/PageHeader";
const PolicyOverviewPageQuery = graphql` const PolicyOverviewPageQuery = graphql`
query PolicyOverviewPageQuery($policyId: ID!) { query PolicyOverviewPageQuery($policyId: ID!) {
@@ -157,6 +157,32 @@ function PolicyOverviewPageContent({
<PageHeader <PageHeader
className="mb-17" className="mb-17"
title={policy.name ?? ""} title={policy.name ?? ""}
description={
<div className="flex items-center gap-2 text-muted-foreground">
<Badge
variant={policy.status === "ACTIVE" ? "default" : "outline"}
>
{policy.status === "ACTIVE" ? "Active" : "Draft"}
</Badge>
{policy.owner && (
<div className="flex items-center gap-1">
<User className="h-3 w-3" />
<Link
to={`/organizations/${organizationId}/people/${policy.owner.id}`}
className="hover:underline"
>
{policy.owner.fullName}
</Link>
</div>
)}
{policy.reviewDate && (
<div className="flex items-center gap-1">
<Calendar className="h-3 w-3" />
<span>Review: {formatDate(policy.reviewDate)}</span>
</div>
)}
</div>
}
actions={ actions={
<div className="flex gap-2"> <div className="flex gap-2">
<Button variant="outline" size="sm" asChild> <Button variant="outline" size="sm" asChild>
@@ -188,30 +214,7 @@ function PolicyOverviewPageContent({
</Button> </Button>
</div> </div>
} }
> />
<div className="flex items-center gap-2 text-muted-foreground">
<Badge variant={policy.status === "ACTIVE" ? "default" : "outline"}>
{policy.status === "ACTIVE" ? "Active" : "Draft"}
</Badge>
{policy.owner && (
<div className="flex items-center gap-1">
<User className="h-3 w-3" />
<Link
to={`/organizations/${organizationId}/people/${policy.owner.id}`}
className="hover:underline"
>
{policy.owner.fullName}
</Link>
</div>
)}
{policy.reviewDate && (
<div className="flex items-center gap-1">
<Calendar className="h-3 w-3" />
<span>Review: {formatDate(policy.reviewDate)}</span>
</div>
)}
</div>
</PageHeader>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2"> <div className="lg:col-span-2">

View File

@@ -39,7 +39,7 @@ import type { SettingsPageQuery as SettingsPageQueryType } from "./__generated__
import type { SettingsPageUpdateOrganizationMutation as SettingsPageUpdateOrganizationMutationType } from "./__generated__/SettingsPageUpdateOrganizationMutation.graphql"; import type { SettingsPageUpdateOrganizationMutation as SettingsPageUpdateOrganizationMutationType } from "./__generated__/SettingsPageUpdateOrganizationMutation.graphql";
import type { SettingsPageInviteUserMutation as SettingsPageInviteUserMutationType } from "./__generated__/SettingsPageInviteUserMutation.graphql"; import type { SettingsPageInviteUserMutation as SettingsPageInviteUserMutationType } from "./__generated__/SettingsPageInviteUserMutation.graphql";
import type { SettingsPageRemoveUserMutation as SettingsPageRemoveUserMutationType } from "./__generated__/SettingsPageRemoveUserMutation.graphql"; import type { SettingsPageRemoveUserMutation as SettingsPageRemoveUserMutationType } from "./__generated__/SettingsPageRemoveUserMutation.graphql";
import { PageHeader } from "./PageHeader"; import { PageHeader } from "@/components/PageHeader";
const settingsPageQuery = graphql` const settingsPageQuery = graphql`
query SettingsPageQuery($organizationID: ID!) { query SettingsPageQuery($organizationID: ID!) {

View File

@@ -28,7 +28,7 @@ import type {
ControlState, ControlState,
ControlImportance, ControlImportance,
} from "./__generated__/UpdateControlPageUpdateControlMutation.graphql"; } from "./__generated__/UpdateControlPageUpdateControlMutation.graphql";
import { PageHeader } from "./PageHeader"; import { PageHeader } from "@/components/PageHeader";
const updateControlMutation = graphql` const updateControlMutation = graphql`
mutation UpdateControlPageUpdateControlMutation($input: UpdateControlInput!) { mutation UpdateControlPageUpdateControlMutation($input: UpdateControlInput!) {

View File

@@ -18,7 +18,7 @@ import { HelpCircle } from "lucide-react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { UpdateFrameworkPageUpdateFrameworkMutation } from "./__generated__/UpdateFrameworkPageUpdateFrameworkMutation.graphql"; import { UpdateFrameworkPageUpdateFrameworkMutation } from "./__generated__/UpdateFrameworkPageUpdateFrameworkMutation.graphql";
import { UpdateFrameworkPageQuery as UpdateFrameworkPageQueryType } from "./__generated__/UpdateFrameworkPageQuery.graphql"; import { UpdateFrameworkPageQuery as UpdateFrameworkPageQueryType } from "./__generated__/UpdateFrameworkPageQuery.graphql";
import { PageHeader } from "./PageHeader"; import { PageHeader } from "@/components/PageHeader";
const updateFrameworkMutation = graphql` const updateFrameworkMutation = graphql`
mutation UpdateFrameworkPageUpdateFrameworkMutation( mutation UpdateFrameworkPageUpdateFrameworkMutation(

View File

@@ -20,7 +20,7 @@ import PolicyEditor from "@/components/PolicyEditor";
import PeopleSelector from "@/components/PeopleSelector"; import PeopleSelector from "@/components/PeopleSelector";
import type { UpdatePolicyPageQuery as UpdatePolicyPageQueryType } from "./__generated__/UpdatePolicyPageQuery.graphql"; import type { UpdatePolicyPageQuery as UpdatePolicyPageQueryType } from "./__generated__/UpdatePolicyPageQuery.graphql";
import type { UpdatePolicyPageMutation as UpdatePolicyPageMutationType } from "./__generated__/UpdatePolicyPageMutation.graphql"; import type { UpdatePolicyPageMutation as UpdatePolicyPageMutationType } from "./__generated__/UpdatePolicyPageMutation.graphql";
import { PageHeader } from "./PageHeader"; import { PageHeader } from "@/components/PageHeader";
const UpdatePolicyPageQuery = graphql` const UpdatePolicyPageQuery = graphql`
query UpdatePolicyPageQuery($policyId: ID!, $organizationId: ID!) { query UpdatePolicyPageQuery($policyId: ID!, $organizationId: ID!) {

View File

@@ -22,7 +22,7 @@ import { VendorListPageDeleteVendorMutation } from "./__generated__/VendorListPa
import { VendorListPagePaginationQuery } from "./__generated__/VendorListPagePaginationQuery.graphql"; import { VendorListPagePaginationQuery } from "./__generated__/VendorListPagePaginationQuery.graphql";
import { VendorListPage_vendors$key } from "./__generated__/VendorListPage_vendors.graphql"; import { VendorListPage_vendors$key } from "./__generated__/VendorListPage_vendors.graphql";
import { useToast } from "@/hooks/use-toast"; import { useToast } from "@/hooks/use-toast";
import { PageHeader } from "./PageHeader"; import { PageHeader } from "@/components/PageHeader";
const ITEMS_PER_PAGE = 25; const ITEMS_PER_PAGE = 25;

View File

@@ -18,7 +18,7 @@ import type { VendorOverviewPageQuery as VendorOverviewPageQueryType } from "./_
import { useParams } from "react-router"; import { useParams } from "react-router";
import { Helmet } from "react-helmet-async"; import { Helmet } from "react-helmet-async";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { PageHeader } from "./PageHeader"; import { PageHeader } from "@/components/PageHeader";
const vendorOverviewPageQuery = graphql` const vendorOverviewPageQuery = graphql`
query VendorOverviewPageQuery($vendorId: ID!) { query VendorOverviewPageQuery($vendorId: ID!) {