diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/layout.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/layout.tsx
deleted file mode 100644
index 1b3d05dce6..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/layout.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import { auth } from "@comp/auth";
-import { getI18n } from "@/locales/server";
-import { SecondaryMenu } from "@comp/ui/secondary-menu";
-import { headers } from "next/headers";
-
-export default async function Layout({
- children,
-}: {
- children: React.ReactNode;
-}) {
- const t = await getI18n();
- const session = await auth.api.getSession({
- headers: await headers(),
- });
- const user = session?.user;
- const organizationId = session?.session.activeOrganizationId;
-
- return (
-
-
-
- {children}
-
- );
-}
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/loading.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/loading.tsx
deleted file mode 100644
index abe4f9f4b4..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/loading.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton";
-
-export default function Loading() {
- return (
-
- );
-}
-
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/page.tsx
deleted file mode 100644
index 1e2575f6c2..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/page.tsx
+++ /dev/null
@@ -1,53 +0,0 @@
-import { getI18n } from "@/locales/server";
-import type { Metadata } from "next";
-import { setStaticParamsLocale } from "next-international/server";
-import type { SearchParams } from "@/types";
-import { searchParamsCache } from "./data/validations";
-import { getValidFilters } from "@/lib/data-table";
-import { getEvidence } from "./data/queries";
-import { EvidenceTable } from "./components/evidence-table";
-
-interface PolicyTableProps {
- params: Promise<{ locale: string }>;
- searchParams: Promise;
-}
-
-export default async function PoliciesPage({
- params,
- ...props
-}: PolicyTableProps) {
- const { locale } = await params;
- const searchParams = await props.searchParams;
- const search = searchParamsCache.parse(searchParams);
- const validFilters = getValidFilters(search.filters);
-
- setStaticParamsLocale(locale);
-
- const promises = Promise.all([
- getEvidence({
- ...search,
- filters: validFilters,
- }),
- ]);
-
- 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.evidence"),
- };
-}
\ No newline at end of file
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/[id]/layout.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/[id]/layout.tsx
deleted file mode 100644
index 315f4096a3..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/[id]/layout.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { getI18n } from "@/locales/server";
-import { SecondaryMenu } from "@comp/ui/secondary-menu";
-
-interface LayoutProps {
- children: React.ReactNode;
- params: Promise<{ policyId: string; orgId: string }>;
-}
-
-export default async function Layout({ children, params }: LayoutProps) {
- const t = await getI18n();
- const { policyId, orgId } = await params;
-
- return (
-
-
-
- {children}
-
- );
-}
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/[id]/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/[id]/page.tsx
deleted file mode 100644
index 771f5aa40d..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/[id]/page.tsx
+++ /dev/null
@@ -1,88 +0,0 @@
-import { cache } from "react";
-import { PolicyOverview } from "@/components/policies/policy-overview";
-import { getI18n } from "@/locales/server";
-import { db } from "@comp/db";
-import { auth } from "@comp/auth";
-import type { Metadata } from "next";
-import { setStaticParamsLocale } from "next-international/server";
-import { headers } from "next/headers";
-
-export default async function PolicyDetails({
- params,
-}: {
- params: Promise<{ locale: string; policyId: string }>;
-}) {
- const { locale, policyId } = await params;
- setStaticParamsLocale(locale);
- const policy = await getPolicy(policyId);
- const assignees = await getAssignees();
-
- return (
-
- );
-}
-
-export async function generateMetadata({
- params,
-}: {
- params: Promise<{ locale: string; policyId: string }>;
-}): Promise {
- const { locale } = await params;
-
- setStaticParamsLocale(locale);
- const t = await getI18n();
-
- return {
- title: t("policies.overview.title"),
- };
-}
-
-const getPolicy = cache(async (policyId: string) => {
- const session = await auth.api.getSession({
- headers: await headers(),
- });
-
- const organizationId = session?.session.activeOrganizationId;
-
- if (!organizationId) {
- return null;
- }
-
- const policy = await db.policy.findUnique({
- where: { id: policyId, organizationId },
- });
-
- if (!policy) {
- return null;
- }
-
- return policy;
-});
-
-const getAssignees = cache(async () => {
- const session = await auth.api.getSession({
- headers: await headers(),
- });
-
- const organizationId = session?.session.activeOrganizationId;
-
- if (!organizationId) {
- return [];
- }
-
- const assignees = await db.member.findMany({
- where: {
- organizationId,
- role: {
- notIn: ["employee"],
- },
- },
- include: {
- user: true,
- },
- });
-
- return assignees;
-});
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/EvidenceList.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/EvidenceList.tsx
deleted file mode 100644
index ae84b5cdf4..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/EvidenceList.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-"use client";
-
-import { useEvidenceTable } from "../hooks/useEvidenceTableContext";
-import { EvidenceListTable } from "./table/EvidenceListTable";
-
-export function EvidenceList() {
- const { evidenceTasks } = useEvidenceTable();
-
- return ;
-}
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/EvidenceListUIStates.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/EvidenceListUIStates.tsx
deleted file mode 100644
index 93c11e58e7..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/EvidenceListUIStates.tsx
+++ /dev/null
@@ -1,81 +0,0 @@
-import React from "react";
-import { Alert, AlertDescription, AlertTitle } from "@comp/ui/alert";
-import { AlertCircle, FileQuestion, SearchX } from "lucide-react";
-import { useI18n } from "@/locales/client";
-import { Button } from "@comp/ui/button";
-
-interface ErrorStateProps {
- error: Error;
- onRetry?: () => void;
-}
-
-interface EmptyStateProps {
- message?: string;
- hasFilters?: boolean;
- onClearFilters?: () => void;
-}
-
-/**
- * Error state component for the evidence list
- */
-export function EvidenceListError({ error, onRetry }: ErrorStateProps) {
- const t = useI18n();
-
- return (
-
-
- Error
-
- {error.message || "Failed to load evidence tasks"}
- {onRetry && (
-
- )}
-
-
- );
-}
-
-/**
- * Empty state component for the evidence list
- */
-export function EvidenceListEmpty({
- message,
- hasFilters = false,
- onClearFilters,
-}: EmptyStateProps) {
- const t = useI18n();
- const defaultMessage = hasFilters
- ? "No evidence tasks match your current filters"
- : "No evidence tasks found";
-
- return (
-
- {hasFilters ? (
-
- ) : (
-
- )}
-
-
- {hasFilters ? "No Matches Found" : "No Evidence Tasks"}
-
-
-
- {message || defaultMessage}
-
-
- {hasFilters && onClearFilters && (
-
- )}
-
- );
-}
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/EvidenceSummaryCards.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/EvidenceSummaryCards.tsx
deleted file mode 100644
index 983155656c..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/EvidenceSummaryCards.tsx
+++ /dev/null
@@ -1,110 +0,0 @@
-"use client";
-
-import { Card, CardContent, CardHeader, CardTitle } from "@comp/ui/card";
-import { FileX, FileCheck, Clock, CheckCircle } from "lucide-react";
-import { useEvidenceTasksStats } from "../../hooks/useEvidenceTasksStats";
-import { Skeleton } from "@comp/ui/skeleton";
-
-export function EvidenceSummaryCards() {
- const { stats, isLoading, error } = useEvidenceTasksStats();
-
- // Handle loading state
- if (isLoading) {
- return (
-
- {["empty", "draft", "review", "uptodate"].map((type) => (
-
- ))}
-
- );
- }
-
- // Handle error state
- if (error) {
- console.error("Error loading evidence task stats:", error);
- return (
-
- Error loading statistics. Please try again later.
-
- );
- }
-
- // Handle no data state
- if (!stats) {
- return null;
- }
-
- return (
-
-
-
-
- Empty
-
-
-
-
-
- Evidence tasks without files or links
-
-
-
-
-
-
-
- Draft
-
-
-
-
-
- Has content but not published
-
-
-
-
-
-
-
- Needs Review
-
-
-
-
-
{stats.needsReviewCount}
-
-
-
- Published but past due for review
-
-
-
-
-
-
-
- Up to Date
-
-
-
-
-
- {stats.upToDateCount}/{stats.totalCount}
-
-
-
-
- Published and current
-
-
-
-
- );
-}
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/components/evidence-table-columns.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/evidence-table-columns.tsx
similarity index 100%
rename from apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/components/evidence-table-columns.tsx
rename to apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/evidence-table-columns.tsx
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/components/evidence-table.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/evidence-table.tsx
similarity index 91%
rename from apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/components/evidence-table.tsx
rename to apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/evidence-table.tsx
index a4be48faca..9793d06064 100644
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/components/evidence-table.tsx
+++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/evidence-table.tsx
@@ -9,6 +9,7 @@ import { DataTableSortList } from "@/components/data-table/data-table-sort-list"
import { getEvidenceColumns } from "./evidence-table-columns";
import { DataTableToolbar } from "@/components/data-table/data-table-toolbar";
import { CreatePolicySheet } from "@/components/sheets/create-policy-sheet";
+import { useParams } from "next/navigation";
interface EvidenceTableProps {
promises: Promise<[
@@ -18,6 +19,7 @@ interface EvidenceTableProps {
export function EvidenceTable({ promises }: EvidenceTableProps) {
const [{ data, pageCount }] = React.use(promises);
+ const { orgId } = useParams();
const columns = React.useMemo(() => getEvidenceColumns(), []);
@@ -38,7 +40,7 @@ export function EvidenceTable({ promises }: EvidenceTableProps) {
row.id}
- rowClickBasePath="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/evidence/all"
+ rowClickBasePath={`/${orgId}/evidence`}
>
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/index.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/index.ts
deleted file mode 100644
index 81ee91ca32..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export { EvidenceList } from "./EvidenceList";
-export * from "./table/EvidenceFilters";
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/EvidenceFilters/ActiveFilterBadges.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/EvidenceFilters/ActiveFilterBadges.tsx
deleted file mode 100644
index 1dbd3c23a3..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/EvidenceFilters/ActiveFilterBadges.tsx
+++ /dev/null
@@ -1,97 +0,0 @@
-"use client";
-
-import { Badge } from "@comp/ui/badge";
-import { X } from "lucide-react";
-import { useEvidenceTable } from "../../../hooks/useEvidenceTableContext";
-
-export function ActiveFilterBadges() {
- const {
- status,
- setStatus,
- frequency,
- setFrequency,
- department,
- setDepartment,
- assigneeId,
- setAssigneeId,
- relevance,
- setRelevance,
- setPage,
- assignees,
- } = useEvidenceTable();
-
- // Find the assignee name if there's an active assignee filter
- const assigneeName = assigneeId
- ? assignees.find((a) => a.id === assigneeId)?.name || "Unknown"
- : null;
-
- // Only render if there are active filters
- if (!status && !frequency && !department && !assigneeId && !relevance) {
- return null;
- }
-
- return (
-
- {status && (
-
- Status: {status}
- {
- setStatus(null);
- setPage("1");
- }}
- />
-
- )}
- {relevance && (
-
- Relevance: {relevance === "relevant" ? "Relevant" : "Not Relevant"}
- {
- setRelevance(null);
- setPage("1");
- }}
- />
-
- )}
- {frequency && (
-
- Frequency: {frequency}
- {
- setFrequency(null);
- setPage("1");
- }}
- />
-
- )}
- {department && (
-
- Department: {department.replace(/_/g, " ").toUpperCase()}
- {
- setDepartment(null);
- setPage("1");
- }}
- />
-
- )}
- {assigneeId && assigneeName && (
-
- Assignee: {assigneeName}
- {
- setAssigneeId(null);
- setPage("1");
- }}
- />
-
- )}
-
- );
-}
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/EvidenceFilters/index.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/EvidenceFilters/index.ts
deleted file mode 100644
index 15b35e6f3e..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/EvidenceFilters/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { ActiveFilterBadges } from "./ActiveFilterBadges";
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/EvidenceListColumns.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/EvidenceListColumns.tsx
deleted file mode 100644
index f4abe6290c..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/EvidenceListColumns.tsx
+++ /dev/null
@@ -1,184 +0,0 @@
-"use client";
-
-import { calculateNextReview } from "@/lib/utils/calculate-next-review";
-import { Avatar, AvatarFallback, AvatarImage } from "@comp/ui/avatar";
-import { Badge } from "@comp/ui/badge";
-import { cn } from "@comp/ui/cn";
-import type { ColumnDef } from "@tanstack/react-table";
-import { format } from "date-fns";
-import { EVIDENCE_STATUS_HEX_COLORS } from "../../../(overview)/constants/evidence-status";
-import type { EvidenceTaskRow } from "../../types";
-
-export const EvidenceListColumns: ColumnDef[] = [
- {
- id: "name",
- accessorKey: "name",
- header: "Name",
- enableResizing: true,
- enableSorting: true,
- size: 100,
- minSize: 200,
- cell: ({ row }) => (
-
-
{row.original.name}
-
-
- ),
- },
- {
- id: "status",
- accessorKey: "published",
- header: "Status",
- enableResizing: true,
- enableSorting: false,
- size: 150,
- minSize: 120,
- cell: ({ row }) => {
- const status = row.original.status;
-
- return (
-
-
-
- {status
- ?.split("_")
- .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
- .join(" ")}
-
-
- );
- },
- },
- {
- id: "department",
- accessorKey: "department",
- header: "Department",
- size: 150,
- enableResizing: true,
- minSize: 130,
- enableSorting: false,
- cell: ({ row }) => {
- const department = row.original.department;
-
- if (!department || department === "none") {
- return (
-
- None
-
- );
- }
-
- return (
-
-
- {department.replace(/_/g, " ").toUpperCase()}
-
-
- );
- },
- },
- {
- id: "frequency",
- accessorKey: "frequency",
- header: "Frequency",
- size: 150,
- enableResizing: true,
- minSize: 130,
- enableSorting: false,
- cell: ({ row }) => {
- const frequency = row.original.frequency;
- if (!frequency) return null;
-
- return {frequency}
;
- },
- },
- {
- id: "nextReviewDate",
- accessorKey: "nextReviewDate",
- header: "Next Review Date",
- size: 150,
- enableResizing: true,
- minSize: 180,
- enableSorting: false,
- cell: ({ row }) => {
- if (row.original.lastPublishedAt === null) {
- return (
-
- ASAP
-
- );
- }
-
- const reviewInfo = calculateNextReview(
- row.original.lastPublishedAt,
- row.original.frequency,
- );
-
- if (!reviewInfo) return null;
-
- return (
-
- {reviewInfo.daysUntil} days (
- {format(reviewInfo.nextReviewDate, "MM/dd/yyyy")})
-
- );
- },
- },
- {
- id: "assignee",
- accessorKey: "assignee",
- header: "Assignee",
- enableResizing: true,
- enableSorting: false,
- size: 150,
- minSize: 150,
- cell: ({ row }) => {
- const assignee = row.original.assignee;
-
- if (!assignee) {
- return (
-
- Unassigned
-
- );
- }
-
- return (
-
-
-
-
- {assignee.user.name ? assignee.user.name.charAt(0) : "?"}
-
-
-
{assignee.user.name}
-
- );
- },
- },
-];
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/EvidenceListHeader.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/EvidenceListHeader.tsx
deleted file mode 100644
index eddb782be0..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/EvidenceListHeader.tsx
+++ /dev/null
@@ -1,72 +0,0 @@
-"use client";
-
-import type { Table } from "@tanstack/react-table";
-import { TableHead, TableHeader, TableRow } from "@comp/ui/table";
-import { flexRender } from "@tanstack/react-table";
-import type { EvidenceTaskRow } from "../../types";
-import { ArrowDown, ArrowUp, ArrowUpDown } from "lucide-react";
-import { cn } from "@comp/ui/cn";
-
-interface EvidenceListHeaderProps {
- table: Table;
-}
-
-export function EvidenceListHeader({ table }: EvidenceListHeaderProps) {
- return (
-
- {table.getHeaderGroups().map((headerGroup) => (
-
- {headerGroup.headers.map((header) => (
-
- {header.isPlaceholder ? null : (
-
- {flexRender(
- header.column.columnDef.header,
- header.getContext(),
- )}
- {{
- asc:
,
- desc:
,
- }[header.column.getIsSorted() as string] ??
- (header.column.getCanSort() && (
-
- ))}
-
- )}
-
-
- ))}
-
- ))}
-
- );
-}
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/EvidenceListTable.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/EvidenceListTable.tsx
deleted file mode 100644
index 4ede9d928c..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/EvidenceListTable.tsx
+++ /dev/null
@@ -1,118 +0,0 @@
-"use client";
-
-import { DataTable } from "@/components/ui/data-table";
-import { EvidenceListColumns } from "./EvidenceListColumns";
-import type { EvidenceTaskRow } from "../../types";
-import { useParams, useRouter } from "next/navigation";
-import { useEvidenceTable } from "../../hooks/useEvidenceTableContext";
-import { getFilterCategories } from "./components/filterCategories";
-import { useEffect, useMemo, useState } from "react";
-
-export function EvidenceListTable({ data }: { data: EvidenceTaskRow[] }) {
- const router = useRouter();
- const { orgId } = useParams<{ orgId: string }>();
- const [isMobile, setIsMobile] = useState(false);
-
- useEffect(() => {
- const checkIfMobile = () => {
- setIsMobile(window.innerWidth < 768);
- };
-
- // Initial check
- checkIfMobile();
-
- // Add event listener
- window.addEventListener("resize", checkIfMobile);
-
- // Cleanup
- return () => window.removeEventListener("resize", checkIfMobile);
- }, []);
-
- const {
- page,
- setPage,
- pageSize,
- setPageSize,
- pagination,
- search,
- setSearch,
- status,
- setStatus,
- frequency,
- setFrequency,
- department,
- setDepartment,
- assigneeId,
- setAssigneeId,
- frequencies,
- departments,
- assignees,
- hasActiveFilters,
- clearFilters,
- isLoading,
- isSearching,
- } = useEvidenceTable();
-
- const handleRowClick = (evidenceId: string) => {
- router.push(`/${orgId}/evidence/${evidenceId}`);
- };
-
- const activeFilterCount = [status, frequency, department, assigneeId].filter(
- Boolean,
- ).length;
-
- const filterCategories = getFilterCategories({
- status,
- setStatus,
- frequency,
- setFrequency,
- department,
- setDepartment,
- assigneeId,
- setAssigneeId,
- frequencies,
- departments,
- assignees,
- setPage,
- });
-
- // Filter columns for mobile view
- const visibleColumns = useMemo(() => {
- if (isMobile) {
- // On mobile, only show the name and relevance columns
- return EvidenceListColumns.filter((column) => column.id === "name");
- }
- return EvidenceListColumns;
- }, [isMobile]);
-
- return (
- handleRowClick(row.id)}
- emptyMessage="No evidence tasks found."
- isLoading={isLoading || isSearching}
- pagination={{
- page: Number(page),
- pageSize: Number(pageSize),
- totalCount: pagination?.totalCount || 0,
- totalPages: pagination?.totalPages || 0,
- hasNextPage: pagination?.hasNextPage || false,
- hasPreviousPage: pagination?.hasPreviousPage || false,
- }}
- onPageChange={(page) => setPage(page.toString())}
- onPageSizeChange={(pageSize) => setPageSize(pageSize.toString())}
- search={{
- value: search || "",
- onChange: setSearch,
- placeholder: "Search evidence tasks...",
- }}
- filters={{
- categories: filterCategories,
- hasActiveFilters,
- onClearFilters: clearFilters,
- activeFilterCount,
- }}
- />
- );
-}
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/components/AssigneeAvatar.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/components/AssigneeAvatar.tsx
deleted file mode 100644
index 61ad74e1ba..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/components/AssigneeAvatar.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-"use client";
-
-interface AssigneeAvatarProps {
- assignee: {
- name: string | null;
- image: string | null;
- };
-}
-
-export function AssigneeAvatar({ assignee }: AssigneeAvatarProps) {
- if (assignee.image) {
- return (
-
- );
- }
-
- return (
-
- {(assignee.name || "?").charAt(0)}
-
- );
-}
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/components/filterCategories.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/components/filterCategories.tsx
deleted file mode 100644
index 9e86f8bb7c..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/components/filterCategories.tsx
+++ /dev/null
@@ -1,101 +0,0 @@
-"use client";
-
-import { STATUS_FILTERS } from "./filterConfigs";
-import { AssigneeAvatar } from "./AssigneeAvatar";
-import { EVIDENCE_STATUS_HEX_COLORS } from "../../../../(overview)/constants/evidence-status";
-import { cn } from "@comp/ui/cn";
-import { Departments } from "@comp/db/types";
-import { EvidenceStatus } from "@comp/db/types";
-import { Frequency } from "@comp/db/types";
-
-interface FilterCategoriesProps {
- status: EvidenceStatus | null;
- setStatus: (status: EvidenceStatus | null) => void;
- frequency: Frequency | null;
- setFrequency: (frequency: Frequency | null) => void;
- department: Departments | null;
- setDepartment: (department: Departments | null) => void;
- assigneeId: string | null;
- setAssigneeId: (assigneeId: string | null) => void;
- frequencies: Frequency[];
- departments: Departments[];
- assignees: Array<{ id: string; name: string | null; image: string | null }>;
- setPage: (page: string) => void;
-}
-
-export function getFilterCategories({
- status,
- setStatus,
- frequency,
- setFrequency,
- department,
- setDepartment,
- assigneeId,
- setAssigneeId,
- frequencies,
- departments,
- assignees,
- setPage,
-}: FilterCategoriesProps) {
- return [
- {
- label: "Filter by Status",
- items: STATUS_FILTERS.map((filter) => ({
- ...filter,
- checked: status === filter.value,
- icon: (
-
- ),
- onChange: (checked: boolean) => {
- setStatus(checked ? filter.value : null);
- setPage("1");
- },
- })),
- },
- {
- label: "Filter by Frequency",
- items: frequencies.map((freq) => ({
- label: freq,
- value: freq,
- checked: frequency === freq,
- onChange: (checked: boolean) => {
- setFrequency(checked ? freq : null);
- setPage("1");
- },
- })),
- },
- {
- label: "Filter by Department",
- items: departments.map((dept) => ({
- label: dept.replace(/_/g, " ").toUpperCase(),
- value: dept,
- checked: department === dept,
- onChange: (checked: boolean) => {
- setDepartment(checked ? dept : null);
- setPage("1");
- },
- })),
- maxHeight: "150px",
- },
- {
- label: "Filter by Assignee",
- items: assignees.map((assignee) => ({
- label: assignee.name || "Unknown",
- value: assignee.id,
- checked: assigneeId === assignee.id,
- onChange: (checked: boolean) => {
- setAssigneeId(checked ? assignee.id : null);
- setPage("1");
- },
- icon: ,
- })),
- maxHeight: "150px",
- },
- ];
-}
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/components/filterConfigs.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/components/filterConfigs.tsx
deleted file mode 100644
index d7ee2775c7..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/components/filterConfigs.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { CheckCircle2, XCircle, AlertTriangle, Building } from "lucide-react";
-
-export const STATUS_FILTERS = [
- {
- label: "Published",
- value: "published",
- icon: ,
- },
- {
- label: "Draft",
- value: "draft",
- icon: ,
- },
- {
- label: "Not Relevant",
- value: "not_relevant",
- icon: ,
- },
-] as const;
-
-export const DEPARTMENT_ICON = (
-
-);
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/index.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/index.ts
deleted file mode 100644
index 9c70bac4f3..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/components/table/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export { EvidenceListTable } from "./EvidenceListTable";
-export { EvidenceListColumns } from "./EvidenceListColumns";
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/data/queries.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/data/queries.ts
similarity index 100%
rename from apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/data/queries.ts
rename to apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/data/queries.ts
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/data/validations.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/data/validations.ts
similarity index 100%
rename from apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/(overview)/data/validations.ts
rename to apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/data/validations.ts
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/hooks/useEvidenceTableContext.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/hooks/useEvidenceTableContext.tsx
deleted file mode 100644
index 6c9f8bbd2a..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/hooks/useEvidenceTableContext.tsx
+++ /dev/null
@@ -1,281 +0,0 @@
-"use client";
-
-import {
- createContext,
- useContext,
- useMemo,
- useState,
- useRef,
- useEffect,
- type ReactNode,
-} from "react";
-import { useQueryState } from "nuqs";
-import type { Frequency, Departments, EvidenceStatus } from "@comp/db/types";
-import { useOrganizationEvidenceTasks } from "../../hooks/useEvidenceTasks";
-import { ALL_DEPARTMENTS } from "../../constants";
-import { ALL_FREQUENCIES } from "../../constants";
-import type { EvidenceTaskRow } from "../types";
-
-interface Assignee {
- id: string;
- name: string | null;
- image: string | null;
-}
-
-interface Filter {
- label: string;
- value: string;
- checked: boolean;
-}
-
-interface EvidenceTableContextType {
- // State
- search: string;
- status: EvidenceStatus | null;
- frequency: Frequency | null;
- department: Departments | null;
- assigneeId: string | null;
- page: string;
- pageSize: string;
- filters: Filter[];
-
- // Setters
- setSearch: (value: string) => void;
- setStatus: (value: EvidenceStatus | null) => void;
- setFrequency: (value: Frequency | null) => void;
- setDepartment: (value: Departments | null) => void;
- setAssigneeId: (value: string | null) => void;
- setPage: (value: string) => void;
- setPageSize: (value: string) => void;
- setFilters: (filters: Filter[]) => void;
- mutate: () => void;
-
- // Data
- evidenceTasks: EvidenceTaskRow[] | undefined;
- pagination:
- | {
- totalCount: number;
- totalPages: number;
- hasNextPage: boolean;
- hasPreviousPage: boolean;
- }
- | undefined;
- isLoading: boolean;
- isSearching: boolean;
- error: Error | undefined;
-
- // Derived data
- frequencies: Frequency[];
- departments: Departments[];
- assignees: Assignee[];
- hasActiveFilters: boolean;
-
- // Actions
- clearFilters: () => void;
-}
-
-const EvidenceTableContext = createContext<
- EvidenceTableContextType | undefined
->(undefined);
-
-export function EvidenceTableProvider({ children }: { children: ReactNode }) {
- // Local state for search
- const [search, setSearch] = useState("");
-
- // Query state for other filters
- const [statusQuery, setStatusQuery] = useQueryState("status");
- const [frequencyQuery, setFrequencyQuery] = useQueryState("frequency");
- const [departmentQuery, setDepartmentQuery] = useQueryState("department");
- const [assigneeId, setAssigneeId] = useQueryState("assigneeId");
- const [page, setPage] = useQueryState("page", { defaultValue: "1" });
- const [pageSize, setPageSize] = useQueryState("pageSize", {
- defaultValue: "10",
- });
-
- // Type-safe status, frequency, and department
- const status = statusQuery as EvidenceStatus | null;
- const frequency = frequencyQuery as Frequency | null;
- const department = departmentQuery as Departments | null;
-
- // Type-safe setters
- const setStatus = (value: EvidenceStatus | null) => setStatusQuery(value);
- const setFrequency = (value: Frequency | null) => setFrequencyQuery(value);
- const setDepartment = (value: Departments | null) =>
- setDepartmentQuery(value);
-
- // Filter state
- const [filters, setFilters] = useState([
- { label: "Published", value: "published", checked: false },
- { label: "Draft", value: "draft", checked: false },
- { label: "Not Relevant", value: "not_relevant", checked: false },
- ]);
-
- // Track if this is initial load or a search/filter update
- const initialLoadCompleted = useRef(false);
- const [isSearching, setIsSearching] = useState(false);
-
- const currentPage = Number.parseInt(page, 10);
- const currentPageSize = Number.parseInt(pageSize, 10);
-
- // Fetch data
- const {
- data: rawEvidenceTasks,
- pagination,
- isLoading,
- error,
- mutate,
- } = useOrganizationEvidenceTasks({
- search,
- status,
- frequency,
- department,
- assigneeId,
- page: currentPage,
- pageSize: currentPageSize,
- });
-
- // Track when search params change
- useEffect(() => {
- if (initialLoadCompleted.current) {
- setIsSearching(true);
- }
- }, [search, status, frequency, department, assigneeId, page, pageSize]);
-
- // Track when loading changes
- useEffect(() => {
- if (isLoading === false) {
- // Small delay to ensure UI transitions properly
- setTimeout(() => {
- initialLoadCompleted.current = true;
- setIsSearching(false);
- }, 50);
- }
- }, [isLoading]);
-
- // Additional safety reset for isSearching when data changes
- useEffect(() => {
- if (rawEvidenceTasks && isSearching) {
- // If we have data, ensure isSearching is eventually set to false
- const timer = setTimeout(() => {
- setIsSearching(false);
- }, 100);
- return () => clearTimeout(timer);
- }
- }, [rawEvidenceTasks, isSearching]);
-
- // Format data for the table
- const evidenceTasks = useMemo(() => {
- return rawEvidenceTasks?.map((task) => ({
- ...task,
- evidence: {
- name: task.name,
- },
- })) as EvidenceTaskRow[] | undefined;
- }, [rawEvidenceTasks]);
-
- // Predefined frequencies and departments
- const frequencies = useMemo(() => ALL_FREQUENCIES, []);
- const departments = useMemo(() => ALL_DEPARTMENTS, []);
-
- // Get unique assignees for the dropdown
- const assignees = useMemo(() => {
- if (!evidenceTasks) return [];
-
- const uniqueAssignees = new Map<
- string,
- { id: string; name: string | null; image: string | null }
- >();
-
- for (const task of evidenceTasks) {
- if (task.assignee) {
- uniqueAssignees.set(task.assignee.id, {
- id: task.assignee.id,
- name: task.assignee.user.name,
- image: task.assignee.user.image,
- });
- }
- }
-
- return Array.from(uniqueAssignees.values()).sort((a, b) => {
- return (a.name || "").localeCompare(b.name || "");
- });
- }, [evidenceTasks]);
-
- // Check if any filters are active
- const hasActiveFilters = useMemo(() => {
- return (
- status !== null ||
- frequency !== null ||
- department !== null ||
- assigneeId !== null
- );
- }, [status, frequency, department, assigneeId]);
-
- // Clear all filters
- const clearFilters = () => {
- setStatus(null);
- setFrequency(null);
- setDepartment(null);
- setAssigneeId(null);
- setPage("1"); // Reset to first page when clearing filters
- setFilters(filters.map((f) => ({ ...f, checked: false }))); // Reset all filter checkboxes
- setSearch(""); // Clear search
- };
-
- const contextValue: EvidenceTableContextType = {
- // State
- search,
- status,
- frequency,
- department,
- assigneeId,
- page,
- pageSize,
- filters,
-
- // Setters
- setSearch,
- setStatus,
- setFrequency,
- setDepartment,
- setAssigneeId,
- setPage,
- setPageSize,
- setFilters,
- mutate,
-
- // Data
- evidenceTasks,
- pagination,
- isLoading,
- isSearching,
- error,
-
- // Derived data
- frequencies,
- departments,
- assignees,
- hasActiveFilters,
-
- // Actions
- clearFilters,
- };
-
- return (
-
- {children}
-
- );
-}
-
-export function useEvidenceTable() {
- const context = useContext(EvidenceTableContext);
-
- if (context === undefined) {
- throw new Error(
- "useEvidenceTable must be used within an EvidenceTableProvider",
- );
- }
-
- return context;
-}
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/loading.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/loading.tsx
index 9fb4571938..abe4f9f4b4 100644
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/loading.tsx
+++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/loading.tsx
@@ -1,16 +1,21 @@
-import { DataTableSkeleton } from "@/components/ui/data-table";
-import { Card } from "@comp/ui/card";
+import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton";
-export default function EvidenceListLoading() {
- return (
-
-
-
- );
+export default function Loading() {
+ return (
+
+ );
}
+
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/page.tsx
index e286e0b5d6..1e2575f6c2 100644
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/page.tsx
+++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/page.tsx
@@ -1,12 +1,53 @@
-import { EvidenceList } from "./components/EvidenceList";
-import { EvidenceTableProvider } from "./hooks/useEvidenceTableContext";
-import PageWithBreadcrumb from "@/components/pages/PageWithBreadcrumb";
-export default function EvidencePage() {
- return (
-
-
-
-
-
- );
+import { getI18n } from "@/locales/server";
+import type { Metadata } from "next";
+import { setStaticParamsLocale } from "next-international/server";
+import type { SearchParams } from "@/types";
+import { searchParamsCache } from "./data/validations";
+import { getValidFilters } from "@/lib/data-table";
+import { getEvidence } from "./data/queries";
+import { EvidenceTable } from "./components/evidence-table";
+
+interface PolicyTableProps {
+ params: Promise<{ locale: string }>;
+ searchParams: Promise;
}
+
+export default async function PoliciesPage({
+ params,
+ ...props
+}: PolicyTableProps) {
+ const { locale } = await params;
+ const searchParams = await props.searchParams;
+ const search = searchParamsCache.parse(searchParams);
+ const validFilters = getValidFilters(search.filters);
+
+ setStaticParamsLocale(locale);
+
+ const promises = Promise.all([
+ getEvidence({
+ ...search,
+ filters: validFilters,
+ }),
+ ]);
+
+ 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.evidence"),
+ };
+}
\ No newline at end of file
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/types.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/types.ts
deleted file mode 100644
index 070ee45619..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/all/types.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import type { Evidence } from "@comp/db/types";
-
-export type EvidenceTaskRow = Evidence & {
- assignee?: {
- id: string;
- user: {
- name: string | null;
- email: string | null;
- image: string | null;
- };
- } | null;
-};
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/constants.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/constants.ts
deleted file mode 100644
index 954658e719..0000000000
--- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/constants.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import type { Departments, Frequency } from "@comp/db/types";
-
-// Define all available departments from the enum
-export const ALL_DEPARTMENTS: Departments[] = [
- "admin",
- "gov",
- "hr",
- "it",
- "itsm",
- "qms",
-];
-
-// Define all available frequencies from the enum
-export const ALL_FREQUENCIES: Frequency[] = ["monthly", "quarterly", "yearly"];