Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion apps/app/languine.lock
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ files:
sub_pages.frameworks.overview: 04fb5df59766a9852e5dd2d0430ca27e
sub_pages.tests.overview: 107f3983ed2f362df6195c163001fe7b
sub_pages.tests.test_details: cb6255fb6a9fb2ec5de81a7eed81fa21
sub_pages.vendors.overview: dfcc5efe778e6340336015dc02617922
sub_pages.vendors.register: 122b14e8fa33bc9d4f389700439dfc71
auth.title: 4b33d501b99fef8f85f32b942fcd0b1f
auth.description: 1fd4b045f6d46683c611e45b8de4bcf6
auth.options: 4dab36ac83853282fc0d7bae20c19e90
Expand Down Expand Up @@ -702,8 +704,9 @@ files:
evidence.details.review_section: 659514b42799e5982d28793d9e003ae3
evidence.details.content: 393ae95538cd395eb8d1f7521f652b10
vendors.title: dfcc5efe778e6340336015dc02617922
vendors.dashboard.title: 3b878279a04dc47d60932cb294d96259
vendors.register.title: 122b14e8fa33bc9d4f389700439dfc71
vendors.dashboard.title: 003dd1a6f6efb2ac33fa8519c89dedcc
vendors.register.create_new: ef1c7d5e555d7fe288bf0bf16b88723d
dashboard.risk_status: 6ce5e6fa832289748023cb773a4e89ac
dashboard.risks_by_department: 0ef508d7e840bc5f85547c3b25e5d87b
dashboard.vendor_status: 17029fbe5ad4d2af5feaf37bb4604225
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@ import { getI18n } from "@/locales/server";
import { SecondaryMenu } from "@bubba/ui/secondary-menu";

export default async function Layout({
children,
children,
}: {
children: React.ReactNode;
children: React.ReactNode;
}) {
const t = await getI18n();
const t = await getI18n();

return (
<div className="max-w-[1200px] m-auto">
<SecondaryMenu
items={[
{ path: "/vendors", label: t("vendors.dashboard.title") },
// { path: "/vendors/register", label: t("vendors.register.title") },
]}
/>
return (
<div className="max-w-[1200px] m-auto">
<SecondaryMenu
items={[
{ path: "/vendors", label: t("vendors.dashboard.title") },
{ path: "/vendors/register", label: t("vendors.register.title") },
]}
/>

<main className="mt-8">{children}</main>
</div>
);
<main className="mt-8">{children}</main>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,62 +1,74 @@
import { auth } from "@/auth";
import { VendorOverview } from "@/components/vendors/charts/vendors-overview";
import { RiskOverview } from "@/components/risks/charts/risk-overview";
import { RisksAssignee } from "@/components/risks/charts/risks-assignee";
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";

export default async function VendorOverviewPage({
params,
export default async function RiskManagement({
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 getVendorOverview(session.user.organizationId);
const overview = await getRiskOverview(session.user.organizationId);

return (
<div className="space-y-4 sm:space-y-8 w-full px-2 sm:px-4">
<VendorOverview organizationId={session.user.organizationId} />
</div>
);
if (overview?.risks === 0) {
redirect("/risk/register");
}

return (
<div className="space-y-4 sm:space-y-8">
Coming Soon
{/* <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<RiskOverview organizationId={session.user.organizationId} />
</div>

<div className="grid gap-4 grid-cols-1 md:grid-cols-2">
<RisksAssignee organizationId={session.user.organizationId} />
</div> */}
</div>
);
}

const getVendorOverview = unstable_cache(
async (organizationId: string) => {
return await db.$transaction(async (tx) => {
const [vendors] = await Promise.all([
tx.vendor.count({
where: { organizationId },
}),
]);

return {
vendors,
};
});
},
["vendor-overview-cache"],
const getRiskOverview = unstable_cache(
async (organizationId: string) => {
return await db.$transaction(async (tx) => {
const [risks] = await Promise.all([
tx.risk.count({
where: { organizationId },
}),
]);

return {
risks,
};
});
},
["risk-overview-cache"],
);

export async function generateMetadata({
params,
params,
}: {
params: Promise<{ locale: string }>;
params: Promise<{ locale: string }>;
}): Promise<Metadata> {
const { locale } = await params;
setStaticParamsLocale(locale);
const t = await getI18n();
const { locale } = await params;
setStaticParamsLocale(locale);
const t = await getI18n();

return {
title: t("sidebar.vendors"),
};
return {
title: t("sidebar.risk"),
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
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 (
<div className="flex flex-col gap-4">
<RiskComments risk={risk} users={users} />
</div>
);
}

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<Metadata> {
const { locale } = await params;
setStaticParamsLocale(locale);
const t = await getI18n();

return {
title: t("sub_pages.risk.risk_comments"),
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
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 (
<div className="max-w-[1200px] space-y-4 m-auto">
<SecondaryMenu
showBackButton
backButtonHref="/risk/register"
items={[
{ path: `/risk/${riskId.riskId}`, label: t("risk.overview") },
{
path: `/risk/${riskId.riskId}/comments`,
label: t("common.comments.title"),
},
]}
/>

<main className="mt-8">{children}</main>
</div>
);
}

const getRisk = unstable_cache(
async (riskId: string, organizationId: string) => {
const risk = await db.risk.findUnique({
where: {
id: riskId,
organizationId: organizationId,
},
});

return risk;
},
["risk-cache"],
);
Loading