Controls
diff --git a/apps/console/src/pages/PageHeader.tsx b/apps/console/src/pages/PageHeader.tsx
new file mode 100644
index 000000000..3d197fae0
--- /dev/null
+++ b/apps/console/src/pages/PageHeader.tsx
@@ -0,0 +1,50 @@
+import { cn } from "@/lib/utils";
+import { ReactNode } from "react";
+
+export function PageHeader({
+ className,
+ title,
+ actions,
+ description,
+}: {
+ className?: string;
+ title: string;
+ actions?: ReactNode;
+ description: string;
+}) {
+ return (
+
+ {actions ? (
+
+ ) : (
+
+ )}
+
{description}
+
+ );
+}
+
+export function PageHeading({
+ title,
+ className,
+}: {
+ className?: string;
+ title: string;
+}) {
+ return
{title} ;
+}
+
+export function PageDescription({
+ children,
+ className,
+}: {
+ className?: string;
+ children: ReactNode;
+}) {
+ return (
+
{children}
+ );
+}
diff --git a/apps/console/src/pages/PeopleListPage.tsx b/apps/console/src/pages/PeopleListPage.tsx
index ef8bca8e9..7c5b78fb2 100644
--- a/apps/console/src/pages/PeopleListPage.tsx
+++ b/apps/console/src/pages/PeopleListPage.tsx
@@ -18,6 +18,7 @@ import type { PeopleListPageQuery as PeopleListPageQueryType } from "./__generat
import type { PeopleListPageDeletePeopleMutation } from "./__generated__/PeopleListPageDeletePeopleMutation.graphql";
import { PeopleListPagePaginationQuery } from "./__generated__/PeopleListPagePaginationQuery.graphql";
import { PeopleListPage_peoples$key } from "./__generated__/PeopleListPage_peoples.graphql";
+import { PageHeader } from "./PageHeader";
const ITEMS_PER_PAGE = 25;
@@ -168,124 +169,127 @@ function PeopleListContent({
const pageInfo = peoplesConnection.peoples.pageInfo;
return (
-
-
-
Employees
-
- Keep track of your company{"'"}s workforce and their progress towards
- completing tasks assigned to them.
-
-
+ <>
+
+ People - Probo
+
+
+
+
+
+ Add a person
+
+
+ }
+ />
-
-
-
-
- Add a people
-
-
-
-
-
- {peoples.map((person) => (
-
-
-
-
- {person?.fullName?.[0]}
-
+
+ {peoples.map((person) => (
+
+
+
+
+ {person?.fullName?.[0]}
+
+
+
{person?.fullName}
+ {person?.primaryEmailAddress && (
+ <>
+
•
+
+ {person.primaryEmailAddress}
+
+ >
+ )}
+
+
-
{person?.fullName}
- {person?.primaryEmailAddress && (
- <>
-
•
-
- {person.primaryEmailAddress}
-
- >
- )}
+
+ {person?.kind === "EMPLOYEE"
+ ? "Employee"
+ : person?.kind === "CONTRACTOR"
+ ? "Contractor"
+ : "Vendor"}
+
+
{
+ e.preventDefault();
+ if (
+ window.confirm(
+ "Are you sure you want to delete this person?"
+ )
+ ) {
+ deletePeople({
+ variables: {
+ connections: [peoplesConnection.peoples.__id],
+ input: {
+ peopleId: person.id,
+ },
+ },
+ });
+ }
+ }}
+ >
+
+
+
-
-
- {person?.kind === "EMPLOYEE"
- ? "Employee"
- : person?.kind === "CONTRACTOR"
- ? "Contractor"
- : "Vendor"}
-
- {
- e.preventDefault();
- if (
- window.confirm(
- "Are you sure you want to delete this person?"
- )
- ) {
- deletePeople({
- variables: {
- connections: [peoplesConnection.peoples.__id],
- input: {
- peopleId: person.id,
- },
- },
- });
- }
- }}
- >
-
-
-
-
-
-
- ))}
-
+
+ ))}
+
-
{
- startTransition(() => {
- setSearchParams((prev) => {
- prev.set("before", pageInfo?.startCursor || "");
- prev.delete("after");
- return prev;
+ {
+ startTransition(() => {
+ setSearchParams((prev) => {
+ prev.set("before", pageInfo?.startCursor || "");
+ prev.delete("after");
+ return prev;
+ });
+ loadPrevious(ITEMS_PER_PAGE);
});
- loadPrevious(ITEMS_PER_PAGE);
- });
- }}
- />
- {
- startTransition(() => {
- setSearchParams((prev) => {
- prev.set("after", pageInfo?.endCursor || "");
- prev.delete("before");
- return prev;
+ }}
+ />
+ {
+ startTransition(() => {
+ setSearchParams((prev) => {
+ prev.set("after", pageInfo?.endCursor || "");
+ prev.delete("before");
+ return prev;
+ });
+ loadNext(ITEMS_PER_PAGE);
});
- loadNext(ITEMS_PER_PAGE);
- });
- }}
- />
-
+ }}
+ />
+
+ >
);
}
diff --git a/apps/console/src/pages/PolicyListPage.tsx b/apps/console/src/pages/PolicyListPage.tsx
index 424474eba..cc7cd6761 100644
--- a/apps/console/src/pages/PolicyListPage.tsx
+++ b/apps/console/src/pages/PolicyListPage.tsx
@@ -34,6 +34,7 @@ import {
import { Badge } from "@/components/ui/badge";
import { format } from "date-fns";
import type { PolicyListPageQuery as PolicyListPageQueryType } from "./__generated__/PolicyListPageQuery.graphql";
+import { PageHeader } from "./PageHeader";
const PolicyListPageQuery = graphql`
query PolicyListPageQuery($organizationId: ID!) {
@@ -223,21 +224,20 @@ function PolicyListPageContent({
Policies - Probo
-
-
-
-
Policies
-
- Manage your organization{"'"}s policies
-
-
-
-
-
- Create Policy
-
-
-
+
+
+
+
+ Create Policy
+
+
+ }
+ />
{/* Search and filter controls */}
diff --git a/apps/console/src/pages/SettingsPage.tsx b/apps/console/src/pages/SettingsPage.tsx
index 52c73b571..c164d8021 100644
--- a/apps/console/src/pages/SettingsPage.tsx
+++ b/apps/console/src/pages/SettingsPage.tsx
@@ -39,6 +39,7 @@ import type { SettingsPageQuery as SettingsPageQueryType } from "./__generated__
import type { SettingsPageUpdateOrganizationMutation as SettingsPageUpdateOrganizationMutationType } from "./__generated__/SettingsPageUpdateOrganizationMutation.graphql";
import type { SettingsPageInviteUserMutation as SettingsPageInviteUserMutationType } from "./__generated__/SettingsPageInviteUserMutation.graphql";
import type { SettingsPageRemoveUserMutation as SettingsPageRemoveUserMutationType } from "./__generated__/SettingsPageRemoveUserMutation.graphql";
+import { PageHeader } from "./PageHeader";
const settingsPageQuery = graphql`
query SettingsPageQuery($organizationID: ID!) {
@@ -290,13 +291,12 @@ function SettingsPageContent({
return (
<>
-
-
-
Settings
-
- Manage your details and personal preferences here.
-
-
+
+
diff --git a/apps/console/src/pages/VendorListPage.tsx b/apps/console/src/pages/VendorListPage.tsx
index 4d4c3c80d..5ec7dca70 100644
--- a/apps/console/src/pages/VendorListPage.tsx
+++ b/apps/console/src/pages/VendorListPage.tsx
@@ -22,6 +22,7 @@ import { VendorListPageDeleteVendorMutation } from "./__generated__/VendorListPa
import { VendorListPagePaginationQuery } from "./__generated__/VendorListPagePaginationQuery.graphql";
import { VendorListPage_vendors$key } from "./__generated__/VendorListPage_vendors.graphql";
import { useToast } from "@/hooks/use-toast";
+import { PageHeader } from "./PageHeader";
const ITEMS_PER_PAGE = 25;
@@ -234,183 +235,190 @@ function VendorListContent({
});
return (
-
-
-
Vendors
-
- Vendors are third-party services that your company uses. Add them to
- keep track of their risk and compliance status.
-
-
+ <>
+
+ Vendors - Probo
+
+
+
-
-
-
-
Add a vendor
-
-
-
{
- const value = e.target.value;
- setSearchTerm(value);
- if (value.trim() === "") {
- setFilteredVendors([]);
- } else {
- const results = fuse.search(value).map((result) => result.item);
- setFilteredVendors(results);
- }
- }}
- />
-
- {searchTerm.trim() !== "" && filteredVendors.length > 0 && (
-
+
+
+
Add a vendor
+
+
+
- {filteredVendors.map((vendor: VendorItem) => (
- {
- createVendor({
- variables: {
- connections: [vendorsConnection.vendors.__id],
- input: {
- organizationId: data.organization.id,
- name: vendor.name,
- description: "",
- serviceStartAt: new Date().toISOString(),
- serviceCriticality: "LOW",
- riskTier: "GENERAL",
- },
- },
- onCompleted() {
- setSearchTerm("");
- setFilteredVendors([]);
- toast({
- title: "Vendor added",
- description: "The vendor has been added successfully",
- });
- },
- });
- }}
- >
- {vendor.name}
-
- ))}
-
- )}
-
-
+ onChange={(e) => {
+ const value = e.target.value;
+ setSearchTerm(value);
+ if (value.trim() === "") {
+ setFilteredVendors([]);
+ } else {
+ const results = fuse
+ .search(value)
+ .map((result) => result.item);
+ setFilteredVendors(results);
+ }
+ }}
+ />
-
- {vendors.map((vendor) => (
-
-
-
-
- {vendor?.name?.[0]}
-
-
-
{vendor?.name}
- {vendor?.description && (
- <>
-
•
-
- {vendor.description}
-
- >
- )}
-
-
-
-
- {vendor.riskTier}
-
-
{
- e.preventDefault(); // Prevent navigation
- if (
- window.confirm(
- "Are you sure you want to delete this vendor?"
- )
- ) {
- deleteVendor({
+ {searchTerm.trim() !== "" && filteredVendors.length > 0 && (
+
+ {filteredVendors.map((vendor: VendorItem) => (
+ {
+ createVendor({
variables: {
connections: [vendorsConnection.vendors.__id],
input: {
- vendorId: vendor.id,
+ organizationId: data.organization.id,
+ name: vendor.name,
+ description: "",
+ serviceStartAt: new Date().toISOString(),
+ serviceCriticality: "LOW",
+ riskTier: "GENERAL",
},
},
onCompleted() {
+ setSearchTerm("");
+ setFilteredVendors([]);
toast({
- title: "Vendor deleted",
+ title: "Vendor added",
description:
- "The vendor has been deleted successfully",
+ "The vendor has been added successfully",
});
},
});
- }
- }}
- >
-
-
-
+ }}
+ >
+ {vendor.name}
+
+ ))}
-
-
- ))}
-
+ )}
+
+
-
{
- startTransition(() => {
- setSearchParams((prev) => {
- prev.set("before", pageInfo?.startCursor || "");
- prev.delete("after");
- return prev;
+
+ {vendors.map((vendor) => (
+
+
+
+
+ {vendor?.name?.[0]}
+
+
+
{vendor?.name}
+ {vendor?.description && (
+ <>
+
•
+
+ {vendor.description}
+
+ >
+ )}
+
+
+
+
+ {vendor.riskTier}
+
+ {
+ e.preventDefault(); // Prevent navigation
+ if (
+ window.confirm(
+ "Are you sure you want to delete this vendor?"
+ )
+ ) {
+ deleteVendor({
+ variables: {
+ connections: [vendorsConnection.vendors.__id],
+ input: {
+ vendorId: vendor.id,
+ },
+ },
+ onCompleted() {
+ toast({
+ title: "Vendor deleted",
+ description:
+ "The vendor has been deleted successfully",
+ });
+ },
+ });
+ }
+ }}
+ >
+
+
+
+
+
+
+ ))}
+
+
+ {
+ startTransition(() => {
+ setSearchParams((prev) => {
+ prev.set("before", pageInfo?.startCursor || "");
+ prev.delete("after");
+ return prev;
+ });
+ loadPrevious(ITEMS_PER_PAGE);
});
- loadPrevious(ITEMS_PER_PAGE);
- });
- }}
- />
- {
- startTransition(() => {
- setSearchParams((prev) => {
- prev.set("after", pageInfo?.endCursor || "");
- prev.delete("before");
- return prev;
+ }}
+ />
+ {
+ startTransition(() => {
+ setSearchParams((prev) => {
+ prev.set("after", pageInfo?.endCursor || "");
+ prev.delete("before");
+ return prev;
+ });
+ loadNext(ITEMS_PER_PAGE);
});
- loadNext(ITEMS_PER_PAGE);
- });
- }}
- />
-
+ }}
+ />
+
+ >
);
}