Update comp to use cat

Signed-off-by: gearnode <bryan@frimin.fr>
This commit is contained in:
gearnode
2025-02-12 18:00:07 -08:00
parent 72d4b097c2
commit dea502f5ca
2 changed files with 29 additions and 49 deletions

View File

@@ -39,6 +39,7 @@ const FrameworkOverviewPageQuery = graphql`
name name
description description
state state
category
} }
} }
} }
@@ -56,49 +57,22 @@ function FrameworkOverviewPageContent({
const framework = data.node; const framework = data.node;
const controls = framework.controls?.edges.map((edge) => edge?.node) ?? []; const controls = framework.controls?.edges.map((edge) => edge?.node) ?? [];
const controlsByCategory = { // Group controls by their category
office: controls.filter((c) => c?.name.toLowerCase().includes("office")), const controlsByCategory = controls.reduce((acc, control) => {
computer: controls.filter((c) => if (!control?.category) return acc;
c?.name.toLowerCase().includes("computer"), if (!acc[control.category]) {
), acc[control.category] = [];
employees: controls.filter((c) => }
c?.name.toLowerCase().includes("employee"), acc[control.category].push(control);
), return acc;
email: controls.filter((c) => c?.name.toLowerCase().includes("email")), }, {} as Record<string, typeof controls>);
code: controls.filter((c) => c?.name.toLowerCase().includes("code")),
infrastructure: controls.filter((c) =>
c?.name.toLowerCase().includes("infrastructure"),
),
network: controls.filter((c) => c?.name.toLowerCase().includes("network")),
data: controls.filter((c) => c?.name.toLowerCase().includes("data")),
logging: controls.filter((c) => c?.name.toLowerCase().includes("log")),
incidents: controls.filter((c) =>
c?.name.toLowerCase().includes("incident"),
),
vendors: controls.filter((c) => c?.name.toLowerCase().includes("vendor")),
sharing: controls.filter((c) => c?.name.toLowerCase().includes("share")),
};
const controlCards = [ const controlCards = Object.entries(controlsByCategory).map(([category, controls]) => ({
{ title: category,
icon: <Building2 className="w-4 h-4" />, controls,
title: "Secure your offices and internet access", completed: controls.filter((c) => c?.state === "IMPLEMENTED").length,
controls: controlsByCategory.office, total: controls.length,
completed: controlsByCategory.office.filter( }));
(c) => c?.state === "IMPLEMENTED",
).length,
total: controlsByCategory.office.length,
},
{
icon: <Computer className="w-4 h-4" />,
title: "Manage your computers",
controls: controlsByCategory.computer,
completed: controlsByCategory.computer.filter(
(c) => c?.state === "IMPLEMENTED",
).length,
total: controlsByCategory.computer.length,
},
];
const totalImplemented = controls.filter( const totalImplemented = controls.filter(
(c) => c?.state === "IMPLEMENTED", (c) => c?.state === "IMPLEMENTED",
@@ -106,7 +80,6 @@ function FrameworkOverviewPageContent({
return ( return (
<div className="min-h-screen bg-background p-6"> <div className="min-h-screen bg-background p-6">
{/* Header */}
<div className="space-y-4 mb-8"> <div className="space-y-4 mb-8">
<h1 className="text-2xl font-semibold">{framework.name}</h1> <h1 className="text-2xl font-semibold">{framework.name}</h1>
<p className="text-muted-foreground max-w-3xl"> <p className="text-muted-foreground max-w-3xl">
@@ -114,7 +87,6 @@ function FrameworkOverviewPageContent({
</p> </p>
</div> </div>
{/* Timeline */}
<div className="mb-8 space-y-4"> <div className="mb-8 space-y-4">
<div className="flex items-center gap-2 text-sm"> <div className="flex items-center gap-2 text-sm">
<div className="bg-primary/10 text-primary px-3 py-1 rounded-md flex items-center gap-2"> <div className="bg-primary/10 text-primary px-3 py-1 rounded-md flex items-center gap-2">
@@ -150,7 +122,7 @@ function FrameworkOverviewPageContent({
<Card key={index}> <Card key={index}>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium flex items-center gap-2"> <CardTitle className="text-sm font-medium flex items-center gap-2">
{card.icon} <Shield className="w-4 h-4" />
{card.title} {card.title}
</CardTitle> </CardTitle>
<Avatar className="h-6 w-6"> <Avatar className="h-6 w-6">

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<f9715593419cda898b34a0056729d77c>> * @generated SignedSource<<27e925c9f55d555878de5cbe0c131d44>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -18,6 +18,7 @@ export type FrameworkOverviewPageQuery$data = {
readonly controls?: { readonly controls?: {
readonly edges: ReadonlyArray<{ readonly edges: ReadonlyArray<{
readonly node: { readonly node: {
readonly category: string;
readonly description: string; readonly description: string;
readonly id: string; readonly id: string;
readonly name: string; readonly name: string;
@@ -109,6 +110,13 @@ v5 = {
"kind": "ScalarField", "kind": "ScalarField",
"name": "state", "name": "state",
"storageKey": null "storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "category",
"storageKey": null
} }
], ],
"storageKey": null "storageKey": null
@@ -176,16 +184,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "4190ee685492e95820ecb106f2dc7e3c", "cacheID": "c02ad61a9b6ce13a83576ad58aa0a7f4",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "FrameworkOverviewPageQuery", "name": "FrameworkOverviewPageQuery",
"operationKind": "query", "operationKind": "query",
"text": "query FrameworkOverviewPageQuery(\n $frameworkId: ID!\n) {\n node(id: $frameworkId) {\n __typename\n id\n ... on Framework {\n name\n description\n controls {\n edges {\n node {\n id\n name\n description\n state\n }\n }\n }\n }\n }\n}\n" "text": "query FrameworkOverviewPageQuery(\n $frameworkId: ID!\n) {\n node(id: $frameworkId) {\n __typename\n id\n ... on Framework {\n name\n description\n controls {\n edges {\n node {\n id\n name\n description\n state\n category\n }\n }\n }\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "25fb6b72c598d19767825ac648654fcf"; (node as any).hash = "3103fb6eba6ddf2625aa5b50bcdb43f6";
export default node; export default node;