From dcce0eeacce310d58cceb1425f2a5607e6191097 Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 19 Mar 2025 18:27:09 -0400 Subject: [PATCH] fix routes and remove duplicate files --- .../(home)/components/FrameworkProgress.tsx | 2 +- .../components/RequirementStatusChart.tsx | 305 +++++++------ .../table/FrameworkControlsTableColumns.tsx | 5 +- .../[orgId]/risk/[riskId]/comments/page.tsx | 104 ++--- .../[orgId]/risk/[riskId]/layout.tsx | 2 +- .../[orgId]/risk/[riskId]/page.tsx | 422 +++++++++--------- .../risk/[riskId]/tasks/[taskId]/page.tsx | 102 ++--- .../[orgId]/tests/(overview)/page.tsx | 184 ++++---- .../all/[testId]/actions/createTestComment.ts | 4 +- .../[orgId]/vendors/(overview)/page.tsx | 78 ++-- .../vendors/[riskId]/comments/page.tsx | 86 ---- .../(dashboard)/vendors/[riskId]/layout.tsx | 60 --- .../(dashboard)/vendors/[riskId]/page.tsx | 251 ----------- .../[taskId]/actions/getTaskAttachments.ts | 61 --- .../[taskId]/hooks/useTaskAttachments.ts | 29 -- .../vendors/[riskId]/tasks/[taskId]/page.tsx | 87 ---- .../vendors/[riskId]/tasks/search-params.ts | 14 - .../components/create-risk-comment-form.tsx | 106 ----- .../vendors/components/create-risk-form.tsx | 306 ------------- .../components/create-vendor-sheet.tsx | 55 --- .../vendors/components/inherent-risk-form.tsx | 126 ------ .../vendors/components/residual-risk-form.tsx | 132 ------ .../vendors/components/risk-overview.tsx | 240 ---------- .../task/create-task-comment-form.tsx | 108 ----- .../components/task/create-task-form.tsx | 250 ----------- .../components/task/update-task-form.tsx | 201 --------- .../task/update-task-overview-form.tsx | 124 ----- .../vendors/components/update-risk-form.tsx | 126 ------ .../vendors/register/VendorRegisterTable.tsx | 119 ----- .../components/table/RiskRegisterColumns.tsx | 56 --- .../components/table/RiskRegisterFilters.tsx | 72 --- .../(dashboard)/vendors/register/layout.tsx | 23 - .../(dashboard)/vendors/register/page.tsx | 77 ---- .../vendors/register/search-params.ts | 15 - .../tables/risk-register/columns.tsx | 178 ++++---- .../components/tables/risk-tasks/columns.tsx | 168 +++---- .../tables/risk-tasks/empty-states.tsx | 96 ++-- .../components/tables/tests/empty-states.tsx | 8 +- .../notifications/risk-task-notification.ts | 2 +- 39 files changed, 834 insertions(+), 3550 deletions(-) delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/comments/page.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/layout.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/page.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/tasks/[taskId]/actions/getTaskAttachments.ts delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/tasks/[taskId]/hooks/useTaskAttachments.ts delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/tasks/[taskId]/page.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/tasks/search-params.ts delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/components/create-risk-comment-form.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/components/create-risk-form.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/components/create-vendor-sheet.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/components/inherent-risk-form.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/components/residual-risk-form.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/components/risk-overview.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/components/task/create-task-comment-form.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/components/task/create-task-form.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/components/task/update-task-form.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/components/task/update-task-overview-form.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/components/update-risk-form.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/register/VendorRegisterTable.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/register/components/table/RiskRegisterColumns.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/register/components/table/RiskRegisterFilters.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/register/layout.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/register/page.tsx delete mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/vendors/register/search-params.ts diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/(home)/components/FrameworkProgress.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/(home)/components/FrameworkProgress.tsx index 87cf230595..c9c3b3cee6 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/(home)/components/FrameworkProgress.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/(home)/components/FrameworkProgress.tsx @@ -106,7 +106,7 @@ export function FrameworkProgress({ frameworks }: Props) { {t("frameworks.overview.progress.empty.description")}

diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/(home)/components/RequirementStatusChart.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/(home)/components/RequirementStatusChart.tsx index c875b7a065..13345995f1 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/(home)/components/RequirementStatusChart.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/(home)/components/RequirementStatusChart.tsx @@ -1,178 +1,177 @@ "use client"; import { useI18n } from "@/locales/client"; -import type { - Framework, - OrganizationFramework, -} from "@bubba/db/types"; +import type { Framework, OrganizationFramework } from "@bubba/db/types"; import { Card, CardContent, CardHeader, CardTitle } from "@bubba/ui/card"; import { Progress } from "@bubba/ui/progress"; import Link from "next/link"; import { useMemo } from "react"; import type { OrganizationControlType } from "../overview/frameworks/[frameworkId]/components/table/FrameworkControlsTableColumns"; import { useOrganizationCategories } from "../overview/frameworks/[frameworkId]/hooks/useOrganizationCategories"; +import { useParams } from "next/navigation"; interface Props { - frameworks: (OrganizationFramework & { - framework: Framework; - })[]; + frameworks: (OrganizationFramework & { + framework: Framework; + })[]; } // Helper function to check if a control is compliant based on its requirements const isControlCompliant = (control: OrganizationControlType) => { - // First, check if the control has the direct status of "compliant" - if (control.status === "compliant") { - return true; - } - - // Then check the requirements if they exist - const requirements = control.requirements; - - if (!requirements || requirements.length === 0) { - return false; - } - - const totalRequirements = requirements.length; - const completedRequirements = requirements.filter((req) => { - let isCompleted = false; - - switch (req.type) { - case "policy": - isCompleted = req.organizationPolicy?.status === "published"; - break; - case "file": - isCompleted = !!req.fileUrl; - break; - case "evidence": - isCompleted = req.organizationEvidence?.published === true; - break; - default: - isCompleted = req.published || false; - } - - return isCompleted; - }).length; - - return completedRequirements === totalRequirements; + // First, check if the control has the direct status of "compliant" + if (control.status === "compliant") { + return true; + } + + // Then check the requirements if they exist + const requirements = control.requirements; + + if (!requirements || requirements.length === 0) { + return false; + } + + const totalRequirements = requirements.length; + const completedRequirements = requirements.filter((req) => { + let isCompleted = false; + + switch (req.type) { + case "policy": + isCompleted = req.organizationPolicy?.status === "published"; + break; + case "file": + isCompleted = !!req.fileUrl; + break; + case "evidence": + isCompleted = req.organizationEvidence?.published === true; + break; + default: + isCompleted = req.published || false; + } + + return isCompleted; + }).length; + + return completedRequirements === totalRequirements; }; // Individual FrameworkCard component function FrameworkCard({ - framework, + framework, }: { framework: OrganizationFramework & { framework: Framework } }) { - const { data: organizationCategories, isLoading } = useOrganizationCategories( - framework.framework.id, - ); - - // Transform the organizationCategories into controls - const controls = useMemo(() => { - if (!organizationCategories) return []; - - return organizationCategories.flatMap((category) => - category.organizationControl.map((control) => ({ - code: control.control.code, - description: control.control.description, - name: control.control.name, - status: control.status, - id: control.id, - frameworkId: framework.framework.id, - category: category.name, - requirements: control.OrganizationControlRequirement, - })), - ); - }, [ - organizationCategories, - framework.framework.id, - ]) as OrganizationControlType[]; - - // Calculate framework compliance based on controls - const compliance = useMemo(() => { - if (isLoading || controls.length === 0) return 0; - - const totalControls = controls.length; - const compliantControls = controls.filter(isControlCompliant).length; - - return totalControls > 0 - ? Math.round((compliantControls / totalControls) * 100) - : 0; - }, [controls, isLoading]); - - if (isLoading) { - return ( -
-
-
-
-
-
-
- ); - } - - return ( - -
-
- {framework.framework.name.substring(0, 2).toUpperCase()} -
-
-
-
-

{framework.framework.name}

- - {compliance}% Compliant - -
- -
- - ); + const { data: organizationCategories, isLoading } = useOrganizationCategories( + framework.framework.id, + ); + const { orgId } = useParams<{ orgId: string }>(); + + // Transform the organizationCategories into controls + const controls = useMemo(() => { + if (!organizationCategories) return []; + + return organizationCategories.flatMap((category) => + category.organizationControl.map((control) => ({ + code: control.control.code, + description: control.control.description, + name: control.control.name, + status: control.status, + id: control.id, + frameworkId: framework.framework.id, + category: category.name, + requirements: control.OrganizationControlRequirement, + })), + ); + }, [ + organizationCategories, + framework.framework.id, + ]) as OrganizationControlType[]; + + // Calculate framework compliance based on controls + const compliance = useMemo(() => { + if (isLoading || controls.length === 0) return 0; + + const totalControls = controls.length; + const compliantControls = controls.filter(isControlCompliant).length; + + return totalControls > 0 + ? Math.round((compliantControls / totalControls) * 100) + : 0; + }, [controls, isLoading]); + + if (isLoading) { + return ( +
+
+
+
+
+
+
+ ); + } + + return ( + +
+
+ {framework.framework.name.substring(0, 2).toUpperCase()} +
+
+
+
+

{framework.framework.name}

+ + {compliance}% Compliant + +
+ +
+ + ); } // Main component export function RequirementStatus({ frameworks }: Props) { - const t = useI18n(); - const isLoading = !frameworks; - - return ( - - - {t("frameworks.title")} - - - {isLoading ? ( -
-
-

- Loading compliance data... -

-
- ) : frameworks.length === 0 ? ( -
-

- {t("frameworks.overview.empty.description")} -

-
- ) : ( -
- {/* Framework List */} -
- {frameworks.map((framework) => ( - - ))} -
-
- )} - - - ); + const t = useI18n(); + const isLoading = !frameworks; + + return ( + + + {t("frameworks.title")} + + + {isLoading ? ( +
+
+

+ Loading compliance data... +

+
+ ) : frameworks.length === 0 ? ( +
+

+ {t("frameworks.overview.empty.description")} +

+
+ ) : ( +
+ {/* Framework List */} +
+ {frameworks.map((framework) => ( + + ))} +
+
+ )} + + + ); } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/(home)/overview/frameworks/[frameworkId]/components/table/FrameworkControlsTableColumns.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/(home)/overview/frameworks/[frameworkId]/components/table/FrameworkControlsTableColumns.tsx index 03a34c3d78..3407b7eba8 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/(home)/overview/frameworks/[frameworkId]/components/table/FrameworkControlsTableColumns.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/(home)/overview/frameworks/[frameworkId]/components/table/FrameworkControlsTableColumns.tsx @@ -17,7 +17,7 @@ import { TooltipProvider, TooltipTrigger, } from "@bubba/ui/tooltip"; - +import { useParams } from "next/navigation"; export type OrganizationControlType = { code: string; description: string | null; @@ -62,6 +62,7 @@ function getControlStatus( export function FrameworkControlsTableColumns(): ColumnDef[] { const t = useI18n(); + const { orgId } = useParams<{ orgId: string }>(); return [ { @@ -72,7 +73,7 @@ export function FrameworkControlsTableColumns(): ColumnDef {row.original.name} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/comments/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/comments/page.tsx index b1470f9224..27a5060628 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/comments/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/comments/page.tsx @@ -8,79 +8,79 @@ import { unstable_cache } from "next/cache"; import { redirect } from "next/navigation"; interface PageProps { - params: Promise<{ riskId: string }>; + params: Promise<{ riskId: string }>; } export default async function RiskPage({ params }: PageProps) { - const session = await auth(); - const { riskId } = await params; + const session = await auth(); + const { riskId } = await params; - if (!session) { - redirect("/auth"); - } + if (!session) { + redirect("/auth"); + } - if (!session.user.organizationId || !riskId) { - redirect("/"); - } + if (!session.user.organizationId || !riskId) { + redirect("/"); + } - const risk = await getRisk(riskId, session.user.organizationId); + const risk = await getRisk(riskId, session.user.organizationId); - if (!risk) { - redirect("/risk"); - } + if (!risk) { + redirect(`/${session.user.organizationId}/risk`); + } - const users = await getUsers(session.user.organizationId); + const users = await getUsers(session.user.organizationId); - return ( -
- -
- ); + return ( +
+ +
+ ); } const getRisk = unstable_cache( - async (riskId: string, organizationId: string) => { - const risk = await db.risk.findUnique({ - where: { - id: riskId, - organizationId: organizationId, - }, - include: { - owner: true, - comments: { - orderBy: { - createdAt: "desc", - }, - }, - }, - }); + async (riskId: string, organizationId: string) => { + const risk = await db.risk.findUnique({ + where: { + id: riskId, + organizationId: organizationId, + }, + include: { + owner: true, + comments: { + orderBy: { + createdAt: "desc", + }, + }, + }, + }); - return risk; - }, - ["risk-cache"], + return risk; + }, + ["risk-cache"], ); const getUsers = unstable_cache( - async (organizationId: string) => { - const users = await db.user.findMany({ - where: { organizationId: organizationId }, - }); + async (organizationId: string) => { + const users = await db.user.findMany({ + where: { organizationId: organizationId }, + }); - return users; - }, - ["users-cache"], + return users; + }, + ["users-cache"], ); export async function generateMetadata({ - params, + params, }: { - params: Promise<{ locale: string }>; + params: Promise<{ locale: string }>; }): Promise { - const { locale } = await params; - setStaticParamsLocale(locale); - const t = await getI18n(); + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); - return { - title: t("sub_pages.risk.risk_comments"), - }; + return { + title: t("sub_pages.risk.risk_comments"), + }; } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/layout.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/layout.tsx index bf9900e16a..f85b4ce8cc 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/layout.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/layout.tsx @@ -23,7 +23,7 @@ export default async function Layout({ children, params }: LayoutProps) { const risk = await getRisk(riskId.riskId, session.user.organizationId); if (!risk) { - redirect("/risk"); + redirect(`/${session.user.organizationId}/risk`); } const orgId = session.user.organizationId; diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/page.tsx index 763bc54db4..8c558ec1ad 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/page.tsx @@ -6,8 +6,8 @@ import { RiskOverview } from "@/components/risks/risk-overview"; import type { RiskTaskType } from "@/components/tables/risk-tasks/columns"; import { DataTable } from "@/components/tables/risk-tasks/data-table"; import { - NoResults, - NoTasks, + NoResults, + NoTasks, } from "@/components/tables/risk-tasks/empty-states"; import { FilterToolbar } from "@/components/tables/risk-tasks/filter-toolbar"; import { getServerColumnHeaders } from "@/components/tables/risk-tasks/server-columns"; @@ -21,231 +21,231 @@ import { unstable_cache } from "next/cache"; import { redirect } from "next/navigation"; interface PageProps { - searchParams: Promise<{ - search?: string; - status?: string; - sort?: string; - page?: string; - per_page?: string; - }>; - params: Promise<{ riskId: string; locale: string }>; + searchParams: Promise<{ + search?: string; + status?: string; + sort?: string; + page?: string; + per_page?: string; + }>; + params: Promise<{ riskId: string; locale: string }>; } export default async function RiskPage({ searchParams, params }: PageProps) { - const session = await auth(); - const t = await getI18n(); - - const { - search, - status, - sort, - page = "1", - per_page = "5", - } = await searchParams; - - const { riskId } = await params; - const columnHeaders = await getServerColumnHeaders(); - const [column, order] = sort?.split(":") ?? []; - const hasFilters = !!(search || status); - const { tasks: loadedTasks, total } = await getTasks({ - riskId, - search, - status: status as RiskTaskStatus, - column, - order, - page: Number.parseInt(page), - per_page: Number.parseInt(per_page), - }); - - if (!session) { - redirect("/auth"); - } - - if (!session.user.organizationId || !riskId) { - redirect("/"); - } - - const risk = await getRisk(riskId, session.user.organizationId); - - if (!risk) { - redirect("/risk"); - } - - const users = await getUsers(session.user.organizationId); - - return ( -
- - - - - -
- {t("risk.tasks.title")} -
-
-
- -
- - {loadedTasks.length > 0 ? ( - - ) : hasFilters ? ( - - ) : ( - <> - - - - )} -
-
-
- -
- - -
-
- ); + const session = await auth(); + const t = await getI18n(); + + const { + search, + status, + sort, + page = "1", + per_page = "5", + } = await searchParams; + + const { riskId } = await params; + const columnHeaders = await getServerColumnHeaders(); + const [column, order] = sort?.split(":") ?? []; + const hasFilters = !!(search || status); + const { tasks: loadedTasks, total } = await getTasks({ + riskId, + search, + status: status as RiskTaskStatus, + column, + order, + page: Number.parseInt(page), + per_page: Number.parseInt(per_page), + }); + + if (!session) { + redirect("/auth"); + } + + if (!session.user.organizationId || !riskId) { + redirect("/"); + } + + const risk = await getRisk(riskId, session.user.organizationId); + + if (!risk) { + redirect(`/${session.user.organizationId}/risk`); + } + + const users = await getUsers(session.user.organizationId); + + return ( +
+ + + + + +
+ {t("risk.tasks.title")} +
+
+
+ +
+ + {loadedTasks.length > 0 ? ( + + ) : hasFilters ? ( + + ) : ( + <> + + + + )} +
+
+
+ +
+ + +
+
+ ); } const getRisk = unstable_cache( - async (riskId: string, organizationId: string) => { - const risk = await db.risk.findUnique({ - where: { - id: riskId, - organizationId: organizationId, - }, - include: { - owner: true, - }, - }); - - return risk; - }, - ["risk-cache"], + async (riskId: string, organizationId: string) => { + const risk = await db.risk.findUnique({ + where: { + id: riskId, + organizationId: organizationId, + }, + include: { + owner: true, + }, + }); + + return risk; + }, + ["risk-cache"], ); const getTasks = unstable_cache( - async function tasks({ - riskId, - search, - status, - column, - order, - page = 1, - per_page = 10, - }: { - riskId: string; - search?: string; - status?: RiskTaskStatus; - column?: string; - order?: string; - page?: number; - per_page?: number; - }) { - const skip = (page - 1) * per_page; - - const [tasks, total] = await Promise.all([ - db.riskMitigationTask - .findMany({ - where: { - riskId, - AND: [ - search - ? { - OR: [ - { title: { contains: search, mode: "insensitive" } }, - { - description: { contains: search, mode: "insensitive" }, - }, - ], - } - : {}, - status ? { status } : {}, - ], - }, - orderBy: column - ? { - [column]: order === "asc" ? "asc" : "desc", - } - : { - createdAt: "desc", - }, - skip, - take: per_page, - include: { - owner: { - select: { - name: true, - image: true, - }, - }, - }, - }) - .then((tasks) => - tasks.map( - (task) => - ({ - ...task, - dueDate: task.dueDate?.toISOString() ?? "", - owner: { - name: task.owner?.name ?? "", - image: task.owner?.image ?? "", - }, - }) as RiskTaskType, - ), - ), - db.riskMitigationTask.count({ - where: { - riskId, - AND: [ - search - ? { - OR: [ - { title: { contains: search, mode: "insensitive" } }, - { description: { contains: search, mode: "insensitive" } }, - ], - } - : {}, - status ? { status } : {}, - ], - }, - }), - ]); - - return { tasks, total }; - }, - ["tasks-cache"], + async function tasks({ + riskId, + search, + status, + column, + order, + page = 1, + per_page = 10, + }: { + riskId: string; + search?: string; + status?: RiskTaskStatus; + column?: string; + order?: string; + page?: number; + per_page?: number; + }) { + const skip = (page - 1) * per_page; + + const [tasks, total] = await Promise.all([ + db.riskMitigationTask + .findMany({ + where: { + riskId, + AND: [ + search + ? { + OR: [ + { title: { contains: search, mode: "insensitive" } }, + { + description: { contains: search, mode: "insensitive" }, + }, + ], + } + : {}, + status ? { status } : {}, + ], + }, + orderBy: column + ? { + [column]: order === "asc" ? "asc" : "desc", + } + : { + createdAt: "desc", + }, + skip, + take: per_page, + include: { + owner: { + select: { + name: true, + image: true, + }, + }, + }, + }) + .then((tasks) => + tasks.map( + (task) => + ({ + ...task, + dueDate: task.dueDate?.toISOString() ?? "", + owner: { + name: task.owner?.name ?? "", + image: task.owner?.image ?? "", + }, + }) as RiskTaskType, + ), + ), + db.riskMitigationTask.count({ + where: { + riskId, + AND: [ + search + ? { + OR: [ + { title: { contains: search, mode: "insensitive" } }, + { description: { contains: search, mode: "insensitive" } }, + ], + } + : {}, + status ? { status } : {}, + ], + }, + }), + ]); + + return { tasks, total }; + }, + ["tasks-cache"], ); const getUsers = unstable_cache( - async (organizationId: string) => { - const users = await db.user.findMany({ - where: { organizationId: organizationId }, - }); - - return users; - }, - ["users-cache"], + async (organizationId: string) => { + const users = await db.user.findMany({ + where: { organizationId: organizationId }, + }); + + return users; + }, + ["users-cache"], ); export async function generateMetadata({ - params, + params, }: { - params: Promise<{ locale: string }>; + params: Promise<{ locale: string }>; }): Promise { - const { locale } = await params; - setStaticParamsLocale(locale); - const t = await getI18n(); + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); - return { - title: t("sub_pages.risk.risk_overview"), - }; + return { + title: t("sub_pages.risk.risk_overview"), + }; } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/tasks/[taskId]/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/tasks/[taskId]/page.tsx index 532a3335a7..fca0fbf411 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/tasks/[taskId]/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/tasks/[taskId]/page.tsx @@ -10,78 +10,78 @@ import { unstable_cache } from "next/cache"; import { redirect } from "next/navigation"; interface PageProps { - params: Promise<{ riskId: string; taskId: string }>; + params: Promise<{ riskId: string; taskId: string }>; } export default async function RiskPage({ params }: PageProps) { - const session = await auth(); - const { riskId, taskId } = await params; + const session = await auth(); + const { riskId, taskId } = await params; - if (!session) { - redirect("/auth"); - } + if (!session) { + redirect("/auth"); + } - if (!session.user.organizationId || !riskId) { - redirect("/"); - } + if (!session.user.organizationId || !riskId) { + redirect("/"); + } - const task = await getTask(riskId, taskId); + const task = await getTask(riskId, taskId); - if (!task) { - redirect("/risk"); - } + if (!task) { + redirect(`/${session.user.organizationId}/risk`); + } - const users = await getUsers(session.user.organizationId); + const users = await getUsers(session.user.organizationId); - return ( -
- - - -
- ); + return ( +
+ + + +
+ ); } const getTask = unstable_cache( - async (riskId: string, taskId: string) => { - const task = await db.riskMitigationTask.findUnique({ - where: { - riskId: riskId, - id: taskId, - }, - include: { - owner: true, - TaskAttachment: true, - TaskComments: true, - }, - }); + async (riskId: string, taskId: string) => { + const task = await db.riskMitigationTask.findUnique({ + where: { + riskId: riskId, + id: taskId, + }, + include: { + owner: true, + TaskAttachment: true, + TaskComments: true, + }, + }); - return task; - }, - ["risk-cache"], + return task; + }, + ["risk-cache"], ); const getUsers = unstable_cache( - async (organizationId: string) => { - const users = await db.user.findMany({ - where: { organizationId: organizationId }, - }); + async (organizationId: string) => { + const users = await db.user.findMany({ + where: { organizationId: organizationId }, + }); - return users; - }, - ["users-cache"], + return users; + }, + ["users-cache"], ); export async function generateMetadata({ - params, + params, }: { - params: Promise<{ locale: string }>; + params: Promise<{ locale: string }>; }): Promise { - const { locale } = await params; - setStaticParamsLocale(locale); - const t = await getI18n(); + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); - return { - title: t("sub_pages.risk.tasks.task_overview"), - }; + return { + title: t("sub_pages.risk.tasks.task_overview"), + }; } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/(overview)/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/(overview)/page.tsx index aa7a3a6696..fe29230385 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/(overview)/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/(overview)/page.tsx @@ -9,113 +9,113 @@ import { unstable_cache } from "next/cache"; import { redirect } from "next/navigation"; export default async function TestsOverview({ - params, + params, }: { - params: Promise<{ locale: string }>; + params: Promise<{ locale: string }>; }) { - const { locale } = await params; - setStaticParamsLocale(locale); + const { locale } = await params; + setStaticParamsLocale(locale); - const session = await auth(); + const session = await auth(); - if (!session?.user?.organizationId) { - redirect("/onboarding"); - } + if (!session?.user?.organizationId) { + redirect("/onboarding"); + } - const overview = await getTestsOverview(session.user.organizationId); + const overview = await getTestsOverview(session.user.organizationId); - if (overview?.totalTests === 0) { - redirect("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/tests/all"); - } + if (overview?.totalTests === 0) { + redirect(`/${session.user.organizationId}/tests/all`); + } - return ( -
-
- - -
-
- ); + return ( +
+
+ + +
+
+ ); } const getTestsOverview = unstable_cache( - async (organizationId: string) => { - return await db.$transaction(async (tx) => { - const [ - totalTests, - infoSeverityTests, - lowSeverityTests, - mediumSeverityTests, - highSeverityTests, - criticalSeverityTests, - ] = await Promise.all([ - tx.organizationIntegrationResults.count({ - where: { - organizationId, - }, - }), - tx.organizationIntegrationResults.count({ - where: { - organizationId, - label: "INFO", - }, - }), - tx.organizationIntegrationResults.count({ - where: { - organizationId, - label: "LOW", - }, - }), - tx.organizationIntegrationResults.count({ - where: { - organizationId, - label: "MEDIUM", - }, - }), - tx.organizationIntegrationResults.count({ - where: { - organizationId, - label: "HIGH", - }, - }), - tx.organizationIntegrationResults.count({ - where: { - organizationId, - label: "CRITICAL", - }, - }), - ]); + async (organizationId: string) => { + return await db.$transaction(async (tx) => { + const [ + totalTests, + infoSeverityTests, + lowSeverityTests, + mediumSeverityTests, + highSeverityTests, + criticalSeverityTests, + ] = await Promise.all([ + tx.organizationIntegrationResults.count({ + where: { + organizationId, + }, + }), + tx.organizationIntegrationResults.count({ + where: { + organizationId, + label: "INFO", + }, + }), + tx.organizationIntegrationResults.count({ + where: { + organizationId, + label: "LOW", + }, + }), + tx.organizationIntegrationResults.count({ + where: { + organizationId, + label: "MEDIUM", + }, + }), + tx.organizationIntegrationResults.count({ + where: { + organizationId, + label: "HIGH", + }, + }), + tx.organizationIntegrationResults.count({ + where: { + organizationId, + label: "CRITICAL", + }, + }), + ]); - return { - totalTests, - infoSeverityTests, - lowSeverityTests, - mediumSeverityTests, - highSeverityTests, - criticalSeverityTests, - }; - }); - }, - ["tests-overview-cache"], + return { + totalTests, + infoSeverityTests, + lowSeverityTests, + mediumSeverityTests, + highSeverityTests, + criticalSeverityTests, + }; + }); + }, + ["tests-overview-cache"], ); export async function generateMetadata({ - params, + params, }: { - params: Promise<{ locale: string }>; + params: Promise<{ locale: string }>; }): Promise { - const { locale } = await params; - setStaticParamsLocale(locale); - const t = await getI18n(); + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); - return { - title: t("sidebar.tests"), - }; + return { + title: t("sidebar.tests"), + }; } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/[testId]/actions/createTestComment.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/[testId]/actions/createTestComment.ts index 7b820a5ae2..346d2efea3 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/[testId]/actions/createTestComment.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/tests/all/[testId]/actions/createTestComment.ts @@ -31,8 +31,8 @@ export const createTestCommentAction = authActionClient }, }); - revalidatePath(`/tests/${testId}`); + revalidatePath(`/${user.organizationId}/tests/${testId}`); revalidateTag(`test_${user.organizationId}`); return { success: true }; - }); \ No newline at end of file + }); diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/(overview)/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/(overview)/page.tsx index 9a6972eeb6..50bff17745 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/(overview)/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/(overview)/page.tsx @@ -9,66 +9,66 @@ import { unstable_cache } from "next/cache"; import { redirect } from "next/navigation"; export default async function RiskManagement({ - params, + params, }: { - params: Promise<{ locale: string }>; + params: Promise<{ locale: string }>; }) { - const { locale } = await params; - setStaticParamsLocale(locale); + const { locale } = await params; + setStaticParamsLocale(locale); - const session = await auth(); + const session = await auth(); - if (!session?.user?.organizationId) { - redirect("/onboarding"); - } + if (!session?.user?.organizationId) { + redirect("/onboarding"); + } - const overview = await getRiskOverview(session.user.organizationId); + const overview = await getRiskOverview(session.user.organizationId); - if (overview?.risks === 0) { - redirect("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/risk/register"); - } + if (overview?.risks === 0) { + redirect(`/${session.user.organizationId}/risk/register`); + } - return ( -
- Coming Soon - {/*
+ return ( +
+ Coming Soon + {/*
*/} -
- ); +
+ ); } const getRiskOverview = unstable_cache( - async (organizationId: string) => { - return await db.$transaction(async (tx) => { - const [risks] = await Promise.all([ - tx.risk.count({ - where: { organizationId }, - }), - ]); + async (organizationId: string) => { + return await db.$transaction(async (tx) => { + const [risks] = await Promise.all([ + tx.risk.count({ + where: { organizationId }, + }), + ]); - return { - risks, - }; - }); - }, - ["risk-overview-cache"], + return { + risks, + }; + }); + }, + ["risk-overview-cache"], ); export async function generateMetadata({ - params, + params, }: { - params: Promise<{ locale: string }>; + params: Promise<{ locale: string }>; }): Promise { - const { locale } = await params; - setStaticParamsLocale(locale); - const t = await getI18n(); + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); - return { - title: t("sidebar.risk"), - }; + return { + title: t("sidebar.risk"), + }; } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/comments/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/comments/page.tsx deleted file mode 100644 index b1470f9224..0000000000 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/comments/page.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { auth } from "@/auth"; -import { RiskComments } from "@/components/risks/risk-comments"; -import { getI18n } from "@/locales/server"; -import { db } from "@bubba/db"; -import type { Metadata } from "next"; -import { setStaticParamsLocale } from "next-international/server"; -import { unstable_cache } from "next/cache"; -import { redirect } from "next/navigation"; - -interface PageProps { - params: Promise<{ riskId: string }>; -} - -export default async function RiskPage({ params }: PageProps) { - const session = await auth(); - const { riskId } = await params; - - if (!session) { - redirect("/auth"); - } - - if (!session.user.organizationId || !riskId) { - redirect("/"); - } - - const risk = await getRisk(riskId, session.user.organizationId); - - if (!risk) { - redirect("/risk"); - } - - const users = await getUsers(session.user.organizationId); - - return ( -
- -
- ); -} - -const getRisk = unstable_cache( - async (riskId: string, organizationId: string) => { - const risk = await db.risk.findUnique({ - where: { - id: riskId, - organizationId: organizationId, - }, - include: { - owner: true, - comments: { - orderBy: { - createdAt: "desc", - }, - }, - }, - }); - - return risk; - }, - ["risk-cache"], -); - -const getUsers = unstable_cache( - async (organizationId: string) => { - const users = await db.user.findMany({ - where: { organizationId: organizationId }, - }); - - return users; - }, - ["users-cache"], -); - -export async function generateMetadata({ - params, -}: { - params: Promise<{ locale: string }>; -}): Promise { - const { locale } = await params; - setStaticParamsLocale(locale); - const t = await getI18n(); - - return { - title: t("sub_pages.risk.risk_comments"), - }; -} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/layout.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/layout.tsx deleted file mode 100644 index f69ab0e564..0000000000 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/layout.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { auth } from "@/auth"; -import { Title } from "@/components/title"; -import { getI18n } from "@/locales/server"; -import { db } from "@bubba/db"; -import { SecondaryMenu } from "@bubba/ui/secondary-menu"; -import { unstable_cache } from "next/cache"; -import { redirect } from "next/navigation"; - -interface LayoutProps { - children: React.ReactNode; - params: Promise<{ riskId: string }>; -} - -export default async function Layout({ children, params }: LayoutProps) { - const t = await getI18n(); - const session = await auth(); - - if (!session || !session.user.organizationId) { - redirect("/"); - } - - const riskId = await params; - const risk = await getRisk(riskId.riskId, session.user.organizationId); - - if (!risk) { - redirect("/risk"); - } - - return ( -
- - -
{children}
-
- ); -} - -const getRisk = unstable_cache( - async (riskId: string, organizationId: string) => { - const risk = await db.risk.findUnique({ - where: { - id: riskId, - organizationId: organizationId, - }, - }); - - return risk; - }, - ["risk-cache"], -); diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/page.tsx deleted file mode 100644 index 763bc54db4..0000000000 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/page.tsx +++ /dev/null @@ -1,251 +0,0 @@ -import { auth } from "@/auth"; -import { Loading } from "@/components/frameworks/loading"; -import { InherentRiskChart } from "@/components/risks/charts/inherent-risk-chart"; -import { ResidualRiskChart } from "@/components/risks/charts/residual-risk-chart"; -import { RiskOverview } from "@/components/risks/risk-overview"; -import type { RiskTaskType } from "@/components/tables/risk-tasks/columns"; -import { DataTable } from "@/components/tables/risk-tasks/data-table"; -import { - NoResults, - NoTasks, -} from "@/components/tables/risk-tasks/empty-states"; -import { FilterToolbar } from "@/components/tables/risk-tasks/filter-toolbar"; -import { getServerColumnHeaders } from "@/components/tables/risk-tasks/server-columns"; -import { getI18n } from "@/locales/server"; -import { db } from "@bubba/db"; -import type { RiskTaskStatus } from "@bubba/db/types"; -import { Card, CardContent, CardHeader, CardTitle } from "@bubba/ui/card"; -import type { Metadata } from "next"; -import { setStaticParamsLocale } from "next-international/server"; -import { unstable_cache } from "next/cache"; -import { redirect } from "next/navigation"; - -interface PageProps { - searchParams: Promise<{ - search?: string; - status?: string; - sort?: string; - page?: string; - per_page?: string; - }>; - params: Promise<{ riskId: string; locale: string }>; -} - -export default async function RiskPage({ searchParams, params }: PageProps) { - const session = await auth(); - const t = await getI18n(); - - const { - search, - status, - sort, - page = "1", - per_page = "5", - } = await searchParams; - - const { riskId } = await params; - const columnHeaders = await getServerColumnHeaders(); - const [column, order] = sort?.split(":") ?? []; - const hasFilters = !!(search || status); - const { tasks: loadedTasks, total } = await getTasks({ - riskId, - search, - status: status as RiskTaskStatus, - column, - order, - page: Number.parseInt(page), - per_page: Number.parseInt(per_page), - }); - - if (!session) { - redirect("/auth"); - } - - if (!session.user.organizationId || !riskId) { - redirect("/"); - } - - const risk = await getRisk(riskId, session.user.organizationId); - - if (!risk) { - redirect("/risk"); - } - - const users = await getUsers(session.user.organizationId); - - return ( -
- - - - - -
- {t("risk.tasks.title")} -
-
-
- -
- - {loadedTasks.length > 0 ? ( - - ) : hasFilters ? ( - - ) : ( - <> - - - - )} -
-
-
- -
- - -
-
- ); -} - -const getRisk = unstable_cache( - async (riskId: string, organizationId: string) => { - const risk = await db.risk.findUnique({ - where: { - id: riskId, - organizationId: organizationId, - }, - include: { - owner: true, - }, - }); - - return risk; - }, - ["risk-cache"], -); - -const getTasks = unstable_cache( - async function tasks({ - riskId, - search, - status, - column, - order, - page = 1, - per_page = 10, - }: { - riskId: string; - search?: string; - status?: RiskTaskStatus; - column?: string; - order?: string; - page?: number; - per_page?: number; - }) { - const skip = (page - 1) * per_page; - - const [tasks, total] = await Promise.all([ - db.riskMitigationTask - .findMany({ - where: { - riskId, - AND: [ - search - ? { - OR: [ - { title: { contains: search, mode: "insensitive" } }, - { - description: { contains: search, mode: "insensitive" }, - }, - ], - } - : {}, - status ? { status } : {}, - ], - }, - orderBy: column - ? { - [column]: order === "asc" ? "asc" : "desc", - } - : { - createdAt: "desc", - }, - skip, - take: per_page, - include: { - owner: { - select: { - name: true, - image: true, - }, - }, - }, - }) - .then((tasks) => - tasks.map( - (task) => - ({ - ...task, - dueDate: task.dueDate?.toISOString() ?? "", - owner: { - name: task.owner?.name ?? "", - image: task.owner?.image ?? "", - }, - }) as RiskTaskType, - ), - ), - db.riskMitigationTask.count({ - where: { - riskId, - AND: [ - search - ? { - OR: [ - { title: { contains: search, mode: "insensitive" } }, - { description: { contains: search, mode: "insensitive" } }, - ], - } - : {}, - status ? { status } : {}, - ], - }, - }), - ]); - - return { tasks, total }; - }, - ["tasks-cache"], -); - -const getUsers = unstable_cache( - async (organizationId: string) => { - const users = await db.user.findMany({ - where: { organizationId: organizationId }, - }); - - return users; - }, - ["users-cache"], -); - -export async function generateMetadata({ - params, -}: { - params: Promise<{ locale: string }>; -}): Promise { - const { locale } = await params; - setStaticParamsLocale(locale); - const t = await getI18n(); - - return { - title: t("sub_pages.risk.risk_overview"), - }; -} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/tasks/[taskId]/actions/getTaskAttachments.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/tasks/[taskId]/actions/getTaskAttachments.ts deleted file mode 100644 index 8da91dda97..0000000000 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/tasks/[taskId]/actions/getTaskAttachments.ts +++ /dev/null @@ -1,61 +0,0 @@ -"use server"; - -import { authActionClient } from "@/actions/safe-action"; -import { db } from "@bubba/db"; -import { z } from "zod"; - -export const getTaskAttachments = authActionClient - .schema( - z.object({ - id: z.string(), - }), - ) - .metadata({ - name: "getTaskAttachments", - track: { - event: "get-task-attachments", - channel: "server", - }, - }) - .action(async ({ ctx, parsedInput }) => { - const { user } = ctx; - const { id } = parsedInput; - - if (!user.organizationId) { - return { - success: false, - error: "Not authorized - no organization found", - }; - } - - try { - const attachments = await db.taskAttachment.findMany({ - where: { - riskMitigationTaskId: id, - organizationId: user.organizationId, - }, - select: { - fileUrl: true, - fileKey: true, - }, - }); - - if (!attachments) { - return { - success: false, - error: "Task attachments not found", - }; - } - - return { - success: true, - data: attachments, - }; - } catch (error) { - console.error("Error fetching task attachments:", error); - return { - success: false, - error: "Failed to fetch task attachments", - }; - } - }); diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/tasks/[taskId]/hooks/useTaskAttachments.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/tasks/[taskId]/hooks/useTaskAttachments.ts deleted file mode 100644 index 9e773bf37d..0000000000 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/tasks/[taskId]/hooks/useTaskAttachments.ts +++ /dev/null @@ -1,29 +0,0 @@ -"use client"; - -import useSWR from "swr"; -import { getTaskAttachments } from "../actions/getTaskAttachments"; - -interface UseTaskAttachmentProps { - id: string; -} - -async function fetchTaskAttachments({ id }: UseTaskAttachmentProps) { - const result = await getTaskAttachments({ id }); - - if (!result || "error" in result) { - throw new Error( - typeof result?.error === "string" - ? result.error - : "Failed to fetch task attachments", - ); - } - - return result.data; -} - -export function useTaskAttachments({ id }: UseTaskAttachmentProps) { - return useSWR(["task-attachments", id], () => fetchTaskAttachments({ id }), { - revalidateOnFocus: false, - revalidateOnReconnect: false, - }); -} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/tasks/[taskId]/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/tasks/[taskId]/page.tsx deleted file mode 100644 index 532a3335a7..0000000000 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/tasks/[taskId]/page.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import { auth } from "@/auth"; -import { TaskComment } from "@/components/risks/tasks/task-comments"; -import { TaskOverview } from "@/components/risks/tasks/task-overview"; -import { TaskAttachments } from "@/components/risks/tasks/task-attachments"; -import { getI18n } from "@/locales/server"; -import { db } from "@bubba/db"; -import type { Metadata } from "next"; -import { setStaticParamsLocale } from "next-international/server"; -import { unstable_cache } from "next/cache"; -import { redirect } from "next/navigation"; - -interface PageProps { - params: Promise<{ riskId: string; taskId: string }>; -} - -export default async function RiskPage({ params }: PageProps) { - const session = await auth(); - const { riskId, taskId } = await params; - - if (!session) { - redirect("/auth"); - } - - if (!session.user.organizationId || !riskId) { - redirect("/"); - } - - const task = await getTask(riskId, taskId); - - if (!task) { - redirect("/risk"); - } - - const users = await getUsers(session.user.organizationId); - - return ( -
- - - -
- ); -} - -const getTask = unstable_cache( - async (riskId: string, taskId: string) => { - const task = await db.riskMitigationTask.findUnique({ - where: { - riskId: riskId, - id: taskId, - }, - include: { - owner: true, - TaskAttachment: true, - TaskComments: true, - }, - }); - - return task; - }, - ["risk-cache"], -); - -const getUsers = unstable_cache( - async (organizationId: string) => { - const users = await db.user.findMany({ - where: { organizationId: organizationId }, - }); - - return users; - }, - ["users-cache"], -); - -export async function generateMetadata({ - params, -}: { - params: Promise<{ locale: string }>; -}): Promise { - const { locale } = await params; - setStaticParamsLocale(locale); - const t = await getI18n(); - - return { - title: t("sub_pages.risk.tasks.task_overview"), - }; -} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/tasks/search-params.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/tasks/search-params.ts deleted file mode 100644 index 55c0834e4e..0000000000 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/[riskId]/tasks/search-params.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { - createSearchParamsCache, - parseAsInteger, - parseAsString, -} from "nuqs/server"; - -export const searchParamsCache = createSearchParamsCache({ - q: parseAsString, - page: parseAsInteger.withDefault(0), - start: parseAsString, - end: parseAsString, - status: parseAsString, - ownerId: parseAsString, -}); diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/components/create-risk-comment-form.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/components/create-risk-comment-form.tsx deleted file mode 100644 index 1ac4951376..0000000000 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/vendors/components/create-risk-comment-form.tsx +++ /dev/null @@ -1,106 +0,0 @@ -"use client"; - -import { createRiskCommentAction } from "@/actions/risk/create-risk-comment"; -import { createRiskCommentSchema } from "@/actions/schema"; -import { useI18n } from "@/locales/client"; -import { - Accordion, - AccordionContent, - AccordionItem, - AccordionTrigger, -} from "@bubba/ui/accordion"; -import { Button } from "@bubba/ui/button"; -import { - Form, - FormControl, - FormField, - FormItem, - FormMessage, -} from "@bubba/ui/form"; -import { Textarea } from "@bubba/ui/textarea"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { ArrowRightIcon } from "lucide-react"; -import { useAction } from "next-safe-action/hooks"; -import { useParams } from "next/navigation"; -import { useQueryState } from "nuqs"; -import { useForm } from "react-hook-form"; -import { toast } from "sonner"; -import type { z } from "zod"; - -export function CreateRiskCommentForm() { - const t = useI18n(); - const [_, setCreateRiskCommentSheet] = useQueryState("risk-comment-sheet"); - const params = useParams<{ riskId: string }>(); - - const createRiskComment = useAction(createRiskCommentAction, { - onSuccess: () => { - toast.success(t("common.comments.success")); - setCreateRiskCommentSheet(null); - }, - onError: () => { - toast.error(t("common.comments.error")); - }, - }); - - const form = useForm>({ - resolver: zodResolver(createRiskCommentSchema), - defaultValues: { - content: "", - riskId: params.riskId, - }, - }); - - const onSubmit = (data: z.infer) => { - createRiskComment.execute(data); - }; - - return ( -
- -
-
- - - {t("common.comments.new")} - -
- ( - - -