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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/app/public/onboarding/risk-management.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/app/public/onboarding/vendor-management.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { auth } from "@/auth";
import { AppOnboarding } from "@/components/app-onboarding";
import { getI18n } from "@/locales/server";
import { db } from "@bubba/db";
import { SecondaryMenu } from "@bubba/ui/secondary-menu";
import { cache, Suspense } from "react";
import { EmployeeInviteSheet } from "@/components/sheets/add-employee-sheet";

export default async function Layout({
children,
}: {
children: React.ReactNode;
}) {
const t = await getI18n();
const session = await auth();
const user = session?.user;
const orgId = user?.organizationId;

const overview = await getEmployeesOverview();

if (overview.length === 0) {
return (
<div className="max-w-[1200px] m-auto">
<Suspense fallback={<div>Loading...</div>}>
<div className="mt-8">
<AppOnboarding
title={t("app_onboarding.employees.title")}
description={t("app_onboarding.employees.description")}
cta={t("app_onboarding.employees.cta")}
imageSrc="/onboarding/people-management.webp"
imageAlt="Employee Management"
sheetName="invite-user-sheet"
faqs={[
{
questionKey: t("app_onboarding.employees.faqs.question_1"),
answerKey: t("app_onboarding.employees.faqs.answer_1"),
},
{
questionKey: t("app_onboarding.employees.faqs.question_2"),
answerKey: t("app_onboarding.employees.faqs.answer_2"),
},
{
questionKey: t("app_onboarding.employees.faqs.question_3"),
answerKey: t("app_onboarding.employees.faqs.answer_3"),
},
{
questionKey: t("app_onboarding.employees.faqs.question_4"),
answerKey: t("app_onboarding.employees.faqs.answer_4"),
},
]}
/>
<EmployeeInviteSheet />
</div>
</Suspense>
</div>
);
}


return (
<div className="max-w-[1200px] m-auto">
<SecondaryMenu
items={[
{
path: `/${orgId}/employees`,
label: t("people.dashboard.title"),
},
{ path: `/${orgId}/employees/all`, label: t("people.all") },
]}
/>

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

const getEmployeesOverview = cache(async () => {
const session = await auth();
const orgId = session?.user.organizationId;

const employees = await db.employee.findMany({
where: {
organizationId: orgId,
},
});

return employees;
});
Comment on lines +77 to +88

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling in getEmployeesOverview function

The function doesn't handle cases where the session might be null or organizationId is undefined, which could lead to runtime errors.

const getEmployeesOverview = cache(async () => {
  const session = await auth();
-  const orgId = session?.user.organizationId;
+  const orgId = session?.user?.organizationId;
+  
+  if (!orgId) {
+    return []; // Return empty array if no organization ID is found
+  }

  const employees = await db.employee.findMany({
    where: {
      organizationId: orgId,
    },
  });

  return employees;
});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const getEmployeesOverview = cache(async () => {
const session = await auth();
const orgId = session?.user.organizationId;
const employees = await db.employee.findMany({
where: {
organizationId: orgId,
},
});
return employees;
});
const getEmployeesOverview = cache(async () => {
const session = await auth();
const orgId = session?.user?.organizationId;
if (!orgId) {
return []; // Return empty array if no organization ID is found
}
const employees = await db.employee.findMany({
where: {
organizationId: orgId,
},
});
return employees;
});

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { auth } from "@/auth";
import { getI18n } from "@/locales/server";
import { SecondaryMenu } from "@bubba/ui/secondary-menu";

export default async function Layout({
children,
}: {
children: React.ReactNode;
}) {
const t = await getI18n();
const session = await auth();
const user = session?.user;
const orgId = user?.organizationId;

return (
<div className="max-w-[1200px] m-auto">
<SecondaryMenu
items={[
{
path: `/${orgId}/employees`,
label: t("people.dashboard.title"),
},
{ path: `/${orgId}/employees/all`, label: t("people.all") },
]}
/>

<main className="mt-8">{children}</main>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { auth } from "@/auth";
import { getI18n } from "@/locales/server";
import { SecondaryMenu } from "@bubba/ui/secondary-menu";

export default async function Layout({
children,
}: {
children: React.ReactNode;
}) {
const t = await getI18n();
const session = await auth();
const user = session?.user;
const orgId = user?.organizationId;
Comment on lines +10 to +13

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for session data

The code currently doesn't handle cases where the session or user might be null, which could lead to runtime errors when accessing organizationId.

  const t = await getI18n();
  const session = await auth();
  const user = session?.user;
- const orgId = user?.organizationId;
+ const orgId = user?.organizationId ?? ""; // Provide a fallback or handle the case when organizationId is undefined
+ 
+ if (!orgId) {
+   // Handle missing organization ID (redirect or show error message)
+ }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const t = await getI18n();
const session = await auth();
const user = session?.user;
const orgId = user?.organizationId;
const t = await getI18n();
const session = await auth();
const user = session?.user;
const orgId = user?.organizationId ?? ""; // Provide a fallback or handle the case when organizationId is undefined
if (!orgId) {
// Handle missing organization ID (redirect or show error message)
}


return (
<div className="max-w-[1200px] m-auto">
<SecondaryMenu
items={[
{
path: `/${orgId}/employees`,
label: t("people.dashboard.title"),
},
{ path: `/${orgId}/employees/all`, label: t("people.all") },
]}
/>

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

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,27 +1,95 @@
import { getI18n } from "@/locales/server";
import { SecondaryMenu } from "@bubba/ui/secondary-menu";
import { auth } from "@/auth";
import { AppOnboarding } from "@/components/app-onboarding";
import { db } from "@bubba/db";
import { cache, Suspense } from "react";
import { CreateRiskSheet } from "@/components/sheets/create-risk-sheet";

export default async function Layout({
children,
children,
}: {
children: React.ReactNode;
children: React.ReactNode;
}) {
const t = await getI18n();
const session = await auth();
const user = session?.user;
const orgId = user?.organizationId;

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

<main className="mt-8">{children}</main>
</div>
);
const t = await getI18n();
const session = await auth();
const user = session?.user;
const orgId = user?.organizationId;

const overview = await getRiskOverview();

if (overview?.risks === 0) {
return (
<div className="max-w-[1200px] m-auto">
<Suspense fallback={<div>Loading...</div>}>
<div className="mt-8">
<AppOnboarding
title={t("app_onboarding.risk_management.title")}
description={t("app_onboarding.risk_management.description")}
cta={t("app_onboarding.risk_management.cta")}
imageSrc="/onboarding/risk-management.webp"
imageAlt="Risk Management"
sheetName="create-risk-sheet"
faqs={[
{
questionKey: t("app_onboarding.risk_management.faqs.question_1"),
answerKey: t("app_onboarding.risk_management.faqs.answer_1"),
},
{
questionKey: t("app_onboarding.risk_management.faqs.question_2"),
answerKey: t("app_onboarding.risk_management.faqs.answer_2"),
},
{
questionKey: t("app_onboarding.risk_management.faqs.question_3"),
answerKey: t("app_onboarding.risk_management.faqs.answer_3"),
},
{
questionKey: t("app_onboarding.risk_management.faqs.question_4"),
answerKey: t("app_onboarding.risk_management.faqs.answer_4"),
},
]}
/>
<CreateRiskSheet />
</div>
</Suspense>
</div>
);
}

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

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

const getRiskOverview = cache(
async () => {
const session = await auth();

if (!session || !session.user.organizationId) {
return { risks: 0 };
}

return await db.$transaction(async (tx) => {
const [risks] = await Promise.all([
tx.risk.count({
where: { organizationId: session.user.organizationId },
}),
]);

return {
risks,
};
});
},
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Button } from "@bubba/ui/button";
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@bubba/ui/card";
import { Input } from "@bubba/ui/input";
import { getI18n } from "@/locales/server";

export default async function Loading() {
const t = await getI18n();

return (
<div className="space-y-12 grid grid-cols-1 md:grid-cols-2 gap-4">
<Card>
<CardHeader>
<CardTitle>{t("settings.general.org_name")}</CardTitle>
<CardDescription>
{t("settings.general.org_name_description")}
</CardDescription>
</CardHeader>
<CardContent>
<Input type="text" placeholder="Loading..." className="max-w-[300px]" />
</CardContent>
<CardFooter className="flex justify-between">
<div>{t("settings.general.org_name_tip")}</div>
<Button disabled aria-label={t("common.actions.save")}>{t("common.actions.save")}</Button>
</CardFooter>
</Card>

<Card>
<CardHeader>
<CardTitle>{t("settings.general.org_website")}</CardTitle>
<CardDescription>
{t("settings.general.org_website_description")}
</CardDescription>
</CardHeader>
<CardContent>
<Input type="url" placeholder="Loading..." className="max-w-[300px]" />
</CardContent>
<CardFooter className="flex justify-between">
<div>{t("settings.general.org_website_tip")}</div>
<Button disabled aria-label={t("common.actions.save")}>{t("common.actions.save")}</Button>
</CardFooter>
</Card>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ import { auth } from "@/auth";
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 { redirect } from "next/navigation";
import { cache } from "react";

export default async function RiskManagement({
params,
Expand All @@ -21,11 +19,6 @@ export default async function RiskManagement({
}

setStaticParamsLocale(locale);
const overview = await getRiskOverview();

if (overview?.risks === 0) {
redirect(`/${session.user.organizationId}/risk/register`);
}

return (
<div className="space-y-4 sm:space-y-8">
Expand All @@ -40,28 +33,6 @@ export default async function RiskManagement({
);
}

const getRiskOverview = cache(
async () => {
const session = await auth();

if (!session || !session.user.organizationId) {
return { risks: 0 };
}

return await db.$transaction(async (tx) => {
const [risks] = await Promise.all([
tx.risk.count({
where: { organizationId: session.user.organizationId },
}),
]);

return {
risks,
};
});
},
);

export async function generateMetadata({
params,
}: {
Expand Down
Loading