From 5e97a5fecb901f935ba1e5ca2e7fca70c4659ab2 Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Tue, 25 Mar 2025 17:24:12 -0400 Subject: [PATCH] stuff --- .../components/EmployeeDetails.tsx | 5 +- .../people/{ => all}/actions/get-employees.ts | 0 .../{ => all}/components/EmployeesList.tsx | 0 .../components/EmployeesListSkeleton.tsx | 0 .../components/table/EmployeesTable.tsx | 0 .../{ => all}/components/table/columns.tsx | 0 .../table/components/filterCategories.tsx | 0 .../table/hooks/useEmployeesTableContext.tsx | 0 .../{ => all}/components/table/types.ts | 0 .../people/{ => all}/hooks/useEmployee.ts | 9 +- .../people/{ => all}/hooks/useEmployees.ts | 0 .../[orgId]/people/{ => all}/page.tsx | 11 +- .../[orgId]/people/{ => all}/types/index.ts | 0 .../people/{ => all}/types/search-params.ts | 0 .../components/EmployeeCompletionChart.tsx | 274 ++++++++++++++++++ .../components/EmployeesOverview.tsx | 80 +++++ .../[orgId]/people/dashboard/page.tsx | 30 ++ .../(dashboard)/[orgId]/people/layout.tsx | 8 +- apps/app/src/components/main-menu.tsx | 2 +- .../components/sheets/invite-user-sheet.tsx | 2 +- apps/app/src/locales/en.ts | 46 +-- apps/app/src/locales/features/people.ts | 13 + 22 files changed, 437 insertions(+), 43 deletions(-) rename apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/{ => all}/actions/get-employees.ts (100%) rename apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/{ => all}/components/EmployeesList.tsx (100%) rename apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/{ => all}/components/EmployeesListSkeleton.tsx (100%) rename apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/{ => all}/components/table/EmployeesTable.tsx (100%) rename apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/{ => all}/components/table/columns.tsx (100%) rename apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/{ => all}/components/table/components/filterCategories.tsx (100%) rename apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/{ => all}/components/table/hooks/useEmployeesTableContext.tsx (100%) rename apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/{ => all}/components/table/types.ts (100%) rename apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/{ => all}/hooks/useEmployee.ts (80%) rename apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/{ => all}/hooks/useEmployees.ts (100%) rename apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/{ => all}/page.tsx (70%) rename apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/{ => all}/types/index.ts (100%) rename apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/{ => all}/types/search-params.ts (100%) create mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/dashboard/components/EmployeeCompletionChart.tsx create mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/dashboard/components/EmployeesOverview.tsx create mode 100644 apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/dashboard/page.tsx diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/[employeeId]/components/EmployeeDetails.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/[employeeId]/components/EmployeeDetails.tsx index 010309b3b3..1211c71c00 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/[employeeId]/components/EmployeeDetails.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/[employeeId]/components/EmployeeDetails.tsx @@ -2,8 +2,6 @@ import { redirect, useParams } from "next/navigation"; import { Card, CardContent, CardHeader, CardTitle } from "@bubba/ui/card"; -import { useI18n } from "@/locales/client"; -import { useEmployeeDetails } from "../../hooks/useEmployee"; import { Skeleton } from "@bubba/ui/skeleton"; import { AlertCircle, CheckCircle2 } from "lucide-react"; import { Alert, AlertDescription, AlertTitle } from "@bubba/ui/alert"; @@ -12,6 +10,7 @@ import { formatDate } from "@/utils/format"; import { Button } from "@bubba/ui/button"; import { EditableDepartment } from "./EditableDepartment"; import type { Departments } from "@bubba/db/types"; +import { useEmployeeDetails } from "../../all/hooks/useEmployee"; interface EmployeeDetailsProps { employeeId: string; @@ -22,7 +21,7 @@ export function EmployeeDetails({ employeeId }: EmployeeDetailsProps) { const { orgId } = useParams<{ orgId: string }>(); if (error) { - if (error.code === "NOT_FOUND") { + if (error.code === "UNEXPECTED_ERROR") { redirect(`/${orgId}/people`); } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/actions/get-employees.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/actions/get-employees.ts similarity index 100% rename from apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/actions/get-employees.ts rename to apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/actions/get-employees.ts diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/components/EmployeesList.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/components/EmployeesList.tsx similarity index 100% rename from apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/components/EmployeesList.tsx rename to apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/components/EmployeesList.tsx diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/components/EmployeesListSkeleton.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/components/EmployeesListSkeleton.tsx similarity index 100% rename from apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/components/EmployeesListSkeleton.tsx rename to apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/components/EmployeesListSkeleton.tsx diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/components/table/EmployeesTable.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/components/table/EmployeesTable.tsx similarity index 100% rename from apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/components/table/EmployeesTable.tsx rename to apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/components/table/EmployeesTable.tsx diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/components/table/columns.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/components/table/columns.tsx similarity index 100% rename from apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/components/table/columns.tsx rename to apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/components/table/columns.tsx diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/components/table/components/filterCategories.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/components/table/components/filterCategories.tsx similarity index 100% rename from apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/components/table/components/filterCategories.tsx rename to apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/components/table/components/filterCategories.tsx diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/components/table/hooks/useEmployeesTableContext.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/components/table/hooks/useEmployeesTableContext.tsx similarity index 100% rename from apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/components/table/hooks/useEmployeesTableContext.tsx rename to apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/components/table/hooks/useEmployeesTableContext.tsx diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/components/table/types.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/components/table/types.ts similarity index 100% rename from apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/components/table/types.ts rename to apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/components/table/types.ts diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/hooks/useEmployee.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/hooks/useEmployee.ts similarity index 80% rename from apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/hooks/useEmployee.ts rename to apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/hooks/useEmployee.ts index d82297ddae..a028133b4d 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/hooks/useEmployee.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/hooks/useEmployee.ts @@ -1,11 +1,12 @@ "use client"; import useSWR from "swr"; -import { getEmployeeDetails } from "../[employeeId]/actions/get-employee-details"; -import type { EmployeeDetails, AppError } from "../[employeeId]/types"; +import type { EmployeeDetails } from "../../[employeeId]/types"; +import { getEmployeeDetails } from "../../[employeeId]/actions/get-employee-details"; +import type { AppError } from "../types"; async function fetchEmployeeDetails( - employeeId: string, + employeeId: string ): Promise { const result = await getEmployeeDetails({ employeeId }); @@ -35,7 +36,7 @@ export function useEmployeeDetails(employeeId: string) { { revalidateOnFocus: false, revalidateOnReconnect: false, - }, + } ); return { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/hooks/useEmployees.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/hooks/useEmployees.ts similarity index 100% rename from apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/hooks/useEmployees.ts rename to apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/hooks/useEmployees.ts diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/page.tsx similarity index 70% rename from apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/page.tsx rename to apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/page.tsx index 99b308721d..0feb87ddbe 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/page.tsx @@ -1,11 +1,9 @@ -import { auth } from "@/auth"; import { getI18n } from "@/locales/server"; import type { Metadata } from "next"; import { setStaticParamsLocale } from "next-international/server"; -import { redirect } from "next/navigation"; import { EmployeesList } from "./components/EmployeesList"; -export default async function PeoplePage({ +export default async function AllPeoplePage({ params, }: { params: Promise<{ locale: string }>; @@ -13,13 +11,6 @@ export default async function PeoplePage({ const { locale } = await params; setStaticParamsLocale(locale); - const session = await auth(); - const organizationId = session?.user.organizationId; - - if (!organizationId) { - return redirect("/"); - } - return ; } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/types/index.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/types/index.ts similarity index 100% rename from apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/types/index.ts rename to apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/types/index.ts diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/types/search-params.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/types/search-params.ts similarity index 100% rename from apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/types/search-params.ts rename to apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/all/types/search-params.ts diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/dashboard/components/EmployeeCompletionChart.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/dashboard/components/EmployeeCompletionChart.tsx new file mode 100644 index 0000000000..a22d6833ed --- /dev/null +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/dashboard/components/EmployeeCompletionChart.tsx @@ -0,0 +1,274 @@ +"use client"; + +import * as React from "react"; +import { + Card, + CardContent, + CardHeader, + CardFooter, + CardTitle, +} from "@bubba/ui/card"; +import { + ChartContainer, + ChartTooltip, + type ChartConfig, +} from "@bubba/ui/chart"; +import { useI18n } from "@/locales/client"; +import { Bar, BarChart, XAxis, YAxis, ResponsiveContainer } from "recharts"; +import type { TooltipProps } from "recharts"; + +// Use correct types from the database +import type { PortalUser } from "@prisma/client"; +import type { + OrganizationPolicy, + OrganizationTrainingVideos, +} from "@prisma/client"; +import { employeeDetailsInputSchema } from "../../[employeeId]/types"; + +interface EmployeeCompletionData { + id: string; + name: string; + total: number; + policiesCompleted: number; + policiesPending: number; + trainingsCompleted: number; + trainingsPending: number; +} + +interface EmployeeCompletionChartProps { + employees: PortalUser[]; + policies: OrganizationPolicy[]; + trainingVideos: OrganizationTrainingVideos[]; +} + +const CHART_COLORS = { + policiesCompleted: "hsl(var(--chart-positive))", // green + policiesPending: "hsl(var(--chart-neutral))", // yellow + trainingsCompleted: "hsl(var(--chart-other))", // blue + trainingsPending: "hsl(var(--chart-warning))", // gray +}; + +// Custom tooltip component with better spacing +const CustomTooltip = ({ + active, + payload, + label, +}: TooltipProps) => { + if (!active || !payload || !payload.length) { + return null; + } + + return ( +
+
{label}
+
+ {payload.map((entry) => ( +
+
+
+ {entry.name} + + {entry.value} + +
+
+ ))} +
+
+ ); +}; + +export function EmployeeCompletionChart({ + employees, + policies, + trainingVideos, +}: EmployeeCompletionChartProps) { + const t = useI18n(); + + const completionData = React.useMemo(() => { + return employees.map((employee) => { + // Count policies completed by this employee + const policiesCompletedCount = policies.filter((policy) => + policy.signedBy.includes(employee.id), + ).length; + + // Count policies pending for this employee + const policiesPendingCount = policies.length - policiesCompletedCount; + + // Count training videos completed by this employee + const trainingsCompletedCount = trainingVideos.filter( + (video) => + video.completedBy && + Array.isArray(video.completedBy) && + video.completedBy.includes(employee.id), + ).length; + + // Count training videos pending for this employee + const trainingsPendingCount = + trainingVideos.length - trainingsCompletedCount; + + const totalCompleted = policiesCompletedCount + trainingsCompletedCount; + + return { + id: employee.id, + name: employee.name || employee.email.split("@")[0], + email: employee.email, + policiesCompleted: policiesCompletedCount, + policiesPending: policiesPendingCount, + trainingsCompleted: trainingsCompletedCount, + trainingsPending: trainingsPendingCount, + total: totalCompleted, + }; + }); + }, [employees, policies, trainingVideos]); + + // Check for empty data scenarios + if (!employees.length) { + return ( + + + + {t("people.dashboard.employee_task_completion")} + + + +

+ {t("people.dashboard.no_data")} +

+
+
+ ); + } + + // Check if there are any tasks to complete + if (policies.length === 0 && trainingVideos.length === 0) { + return ( + + + + {t("people.dashboard.employee_task_completion")} + + + +

+ {t("people.dashboard.no_tasks_available")} +

+
+
+ ); + } + + // Sort and limit to top 5 employees by total completion + const sortedData = React.useMemo(() => { + return [...completionData] + .sort((a, b) => b.total - a.total) + .slice(0, 5) + .reverse(); + }, [completionData]); + + const chartData = sortedData.map((item) => ({ + name: item.name, + email: item.email, + policiesCompleted: item.policiesCompleted, + policiesPending: item.policiesPending, + trainingsCompleted: item.trainingsCompleted, + trainingsPending: item.trainingsPending, + })); + + const chartConfig = { + policiesCompleted: { + label: t("people.dashboard.policies_completed"), + color: CHART_COLORS.policiesCompleted, + }, + policiesPending: { + label: t("people.dashboard.policies_pending"), + color: CHART_COLORS.policiesPending, + }, + trainingsCompleted: { + label: t("people.dashboard.trainings_completed"), + color: CHART_COLORS.trainingsCompleted, + }, + trainingsPending: { + label: t("people.dashboard.trainings_pending"), + color: CHART_COLORS.trainingsPending, + }, + } satisfies ChartConfig; + + return ( + + + {t("people.dashboard.employee_task_completion")} + + + + + + + value} + /> + } /> + + + + + + + + + +
+ {Object.entries(chartConfig).map(([key, config]) => ( +
+
+ {config.label} +
+ ))} +
+ + + ); +} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/dashboard/components/EmployeesOverview.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/dashboard/components/EmployeesOverview.tsx new file mode 100644 index 0000000000..894084fa7c --- /dev/null +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/dashboard/components/EmployeesOverview.tsx @@ -0,0 +1,80 @@ +import { auth } from "@/auth"; +import { db } from "@bubba/db"; +import { EmployeeCompletionChart } from "./EmployeeCompletionChart"; + +export async function EmployeesOverview() { + const employees = await getEmployees(); + const policies = await getEmployeePolicies(); + const trainingVideos = await getEmployeeTrainingVideos(); + + console.log({ employees, policies, trainingVideos }); + + return ( +
+ + {/* Add more dashboard components here as needed */} +
+ ); +} + +const getEmployees = async () => { + const session = await auth(); + const orgId = session?.user.organizationId; + + if (!orgId) { + return []; + } + + const employees = await db.portalUser.findMany({ + where: { + organizationId: orgId, + }, + }); + + return employees; +}; + +const getEmployeePolicies = async () => { + const session = await auth(); + const orgId = session?.user.organizationId; + + if (!orgId) { + return []; + } + + const policies = await db.organizationPolicy.findMany({ + where: { + organizationId: orgId, + isRequiredToSign: true, + }, + include: { + policy: true, + }, + }); + + return policies; +}; + +const getEmployeeTrainingVideos = async () => { + const session = await auth(); + const orgId = session?.user.organizationId; + + if (!orgId) { + return []; + } + + const trainingVideos = await db.organizationTrainingVideos.findMany({ + where: { + organizationId: orgId, + }, + include: { + trainingVideo: true, + }, + }); + + return trainingVideos; +}; diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/dashboard/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/dashboard/page.tsx new file mode 100644 index 0000000000..5d164e4e98 --- /dev/null +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/dashboard/page.tsx @@ -0,0 +1,30 @@ +import { getI18n } from "@/locales/server"; +import type { Metadata } from "next"; +import { setStaticParamsLocale } from "next-international/server"; +import { EmployeesOverview } from "./components/EmployeesOverview"; + +export default async function PeopleOverviewPage({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + setStaticParamsLocale(locale); + + return ; +} + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}): Promise { + const { locale } = await params; + + setStaticParamsLocale(locale); + const t = await getI18n(); + + return { + title: t("sidebar.people"), + }; +} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/layout.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/layout.tsx index b101e64580..096de6d291 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/layout.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/people/layout.tsx @@ -15,7 +15,13 @@ export default async function Layout({ return (
{children}
diff --git a/apps/app/src/components/main-menu.tsx b/apps/app/src/components/main-menu.tsx index eb8f84f1fd..f6d9e1254f 100644 --- a/apps/app/src/components/main-menu.tsx +++ b/apps/app/src/components/main-menu.tsx @@ -222,7 +222,7 @@ export function MainMenu({ }, { id: "people", - path: "/:organizationId/people", + path: "/:organizationId/people/dashboard", name: t("sidebar.people"), disabled: false, icon: Icons.Peolple, diff --git a/apps/app/src/components/sheets/invite-user-sheet.tsx b/apps/app/src/components/sheets/invite-user-sheet.tsx index 476717e51c..2b9d11a870 100644 --- a/apps/app/src/components/sheets/invite-user-sheet.tsx +++ b/apps/app/src/components/sheets/invite-user-sheet.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEmployees } from "@/app/[locale]/(app)/(dashboard)/[orgId]/people/hooks/useEmployees"; +import { useEmployees } from "@/app/[locale]/(app)/(dashboard)/[orgId]/people/all/hooks/useEmployees"; import { useI18n } from "@/locales/client"; import { Button } from "@bubba/ui/button"; import { Input } from "@bubba/ui/input"; diff --git a/apps/app/src/locales/en.ts b/apps/app/src/locales/en.ts index a50985109f..e8704d6b62 100644 --- a/apps/app/src/locales/en.ts +++ b/apps/app/src/locales/en.ts @@ -1,31 +1,31 @@ // Core translations used across the application -import { common } from './core/common' -import { errors } from './core/errors' -import { language, languages } from './core/language' +import { common } from "./core/common"; +import { errors } from "./core/errors"; +import { language, languages } from "./core/language"; // Auth & onboarding related translations -import { auth } from './auth/auth' -import { onboarding } from './auth/onboarding' +import { auth } from "./auth/auth"; +import { onboarding } from "./auth/onboarding"; // Layout & navigation translations -import { header } from './layout/header' -import { not_found } from './layout/not-found' -import { sidebar } from './layout/sidebar' -import { theme } from './layout/theme' -import { user_menu } from './layout/user-menu' +import { header } from "./layout/header"; +import { not_found } from "./layout/not-found"; +import { sidebar } from "./layout/sidebar"; +import { theme } from "./layout/theme"; +import { user_menu } from "./layout/user-menu"; // Feature translations -import { evidence, evidence_tasks } from './features/evidence' -import { frameworks } from './features/frameworks' -import { overview } from './features/overview' -import { people } from './features/people' -import { policies } from './features/policies' -import { risk } from './features/risk' -import { tests } from './features/tests' -import { vendors } from './features/vendors' +import { evidence, evidence_tasks } from "./features/evidence"; +import { frameworks } from "./features/frameworks"; +import { overview } from "./features/overview"; +import { people } from "./features/people"; +import { policies } from "./features/policies"; +import { risk } from "./features/risk"; +import { tests } from "./features/tests"; +import { vendors } from "./features/vendors"; // Settings translations -import { settings } from './settings/settings' +import { settings } from "./settings/settings"; export const translations = { // Core @@ -34,7 +34,7 @@ export const translations = { language, languages, - // Auth & Onboarding + // Auth & Onboarding auth, onboarding, @@ -58,7 +58,7 @@ export const translations = { // Settings settings, -} as const +} as const; -export type Translations = typeof translations -export default translations +export type Translations = typeof translations; +export default translations; diff --git a/apps/app/src/locales/features/people.ts b/apps/app/src/locales/features/people.ts index 1b082198ed..2b24e3178f 100644 --- a/apps/app/src/locales/features/people.ts +++ b/apps/app/src/locales/features/people.ts @@ -1,5 +1,7 @@ export const people = { title: "People", + all: "All Employees", + details: { title: "Employee Details", tasks: "Tasks", @@ -57,4 +59,15 @@ export const people = { success: "Employee added successfully", error: "Failed to add employee", }, + dashboard: { + title: "Dashboard", + employee_task_completion: "Employee Task Completion", + policies_completed: "Policies Completed", + policies_pending: "Policies Pending", + trainings_completed: "Trainings Completed", + trainings_pending: "Trainings Pending", + no_data: "No employee data available", + no_tasks_completed: "No tasks have been completed yet", + no_tasks_available: "No tasks available to complete", + }, } as const;