Skip to content

Commit c9d00d4

Browse files
authored
Merge pull request #601 from trycompai/main
[comp] Production Deploy
2 parents 49bfb03 + d797557 commit c9d00d4

File tree

4 files changed

+120
-85
lines changed

4 files changed

+120
-85
lines changed

apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/(overview)/RisksTable.tsx

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,58 +13,54 @@ import { useQueryState } from "nuqs";
1313
import { useMemo } from "react";
1414
import { columns as getColumns } from "./components/table/RiskColumns";
1515

16-
// Define the expected structure of a risk with User as assignee
1716
export type RiskRow = Risk & { assignee: User | null };
1817

1918
export const RisksTable = ({
2019
risks,
2120
assignees,
21+
pageCount,
2222
}: {
2323
risks: RiskRow[];
2424
assignees: (Member & { user: User })[];
25+
pageCount: number;
2526
}) => {
2627
const t = useI18n();
2728
const session = useSession();
2829
const orgId = session?.data?.session?.activeOrganizationId;
29-
const [_, setOpen] = useQueryState("create-risk-sheet");
30+
const [_, setOpenSheet] = useQueryState("create-risk-sheet");
3031

31-
// Define columns for risks table
32-
const columns = useMemo<ColumnDef<RiskRow>[]>(
33-
() => getColumns(orgId ?? ""),
34-
[orgId],
35-
);
32+
const columns = useMemo<ColumnDef<RiskRow>[]>(() => getColumns(orgId ?? ""), [orgId]);
3633

37-
// Set up the risks table
38-
const table = useDataTable({
34+
const { table } = useDataTable({
3935
data: risks,
4036
columns,
41-
pageCount: Math.ceil(risks.length / 10),
37+
pageCount,
4238
getRowId: (row) => row.id,
4339
initialState: {
4440
pagination: {
4541
pageSize: 10,
4642
pageIndex: 0,
4743
},
44+
sorting: [{ id: "title", desc: true }],
45+
columnPinning: { right: ["actions"] },
4846
},
49-
});
50-
51-
const [searchTerm, setSearchTerm] = useQueryState("search", {
52-
defaultValue: "",
47+
shallow: false,
48+
clearOnDefault: true,
5349
});
5450

5551
return (
5652
<>
5753
<DataTable
58-
table={table.table}
54+
table={table}
5955
getRowId={(row) => row.id}
6056
rowClickBasePath={`/${orgId}/risk`}
6157
>
6258
<DataTableToolbar
59+
table={table}
6360
sheet="create-risk-sheet"
6461
action="Create Risk"
65-
table={table.table}
6662
>
67-
<DataTableSortList table={table.table} align="end" />
63+
<DataTableSortList table={table} align="end" />
6864
</DataTableToolbar>
6965
</DataTable>
7066
<CreateRiskSheet assignees={assignees} />
Lines changed: 49 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,86 @@
1-
"use server";
1+
import "server-only";
22

33
import { auth } from "@/utils/auth";
44
import { db } from "@comp/db";
5-
import { type Departments, Prisma, type RiskStatus } from "@comp/db/types";
5+
import { Prisma, type User } from "@comp/db/types";
66
import { headers } from "next/headers";
7+
import type { GetRiskSchema } from "./validations";
78

8-
export async function getRisks({
9-
search,
10-
page,
11-
pageSize,
12-
status,
13-
department,
14-
assigneeId,
15-
}: {
16-
search?: string;
17-
page?: number;
18-
pageSize?: number;
19-
status?: RiskStatus | null;
20-
department?: Departments | null;
21-
assigneeId?: string | null;
22-
}) {
9+
export async function getRisks(input: GetRiskSchema): Promise<{
10+
data: (Omit<
11+
Prisma.RiskGetPayload<{
12+
include: { assignee: { include: { user: true } } };
13+
}>,
14+
"assignee"
15+
> & { assignee: User | null })[];
16+
pageCount: number;
17+
}> {
2318
const session = await auth.api.getSession({
2419
headers: await headers(),
2520
});
2621

27-
if (!session || !session.session.activeOrganizationId) {
28-
return {
29-
success: false,
30-
error: "Unauthorized",
31-
};
22+
if (!session?.session.activeOrganizationId) {
23+
// In case of unauthorized or missing org, return empty data and 0 pageCount
24+
return { data: [], pageCount: 0 };
3225
}
3326

34-
const where = {
27+
const { title, page, perPage, sort, filters, joinOperator } = input;
28+
29+
const orderBy = sort.map((s) => ({
30+
[s.id]: s.desc ? "desc" : "asc",
31+
}));
32+
33+
const filterConditions: Prisma.RiskWhereInput[] = filters.map((filter) => {
34+
// Basic handling, assuming 'eq' or 'in' based on value type for now
35+
// This might need to be more sophisticated based on actual filter operators
36+
const value = Array.isArray(filter.value)
37+
? { in: filter.value }
38+
: filter.value;
39+
return { [filter.id]: value };
40+
});
41+
42+
const where: Prisma.RiskWhereInput = {
3543
organizationId: session.session.activeOrganizationId,
36-
...(search && {
44+
...(title && {
3745
title: {
38-
contains: search,
46+
contains: title,
3947
mode: Prisma.QueryMode.insensitive,
4048
},
4149
}),
42-
...(status ? { status } : {}),
43-
...(department ? { department } : {}),
44-
...(assigneeId ? { assigneeId } : {}),
50+
...(filterConditions.length > 0 && {
51+
[joinOperator.toUpperCase()]: filterConditions,
52+
}),
4553
};
4654

47-
const skip = ((page ?? 1) - 1) * (pageSize ?? 10);
55+
const skip = (page - 1) * perPage;
56+
const take = perPage;
4857

49-
const risks = await db.risk.findMany({
58+
const risksData = await db.risk.findMany({
5059
where,
5160
skip,
52-
take: pageSize,
61+
take,
5362
include: {
5463
assignee: {
5564
include: {
5665
user: true,
5766
},
5867
},
5968
},
60-
orderBy: {
61-
createdAt: "desc",
62-
},
69+
orderBy: orderBy.length > 0 ? orderBy : [{ createdAt: "desc" }],
6370
});
6471

65-
// Transform the data to match the expected structure by RiskRegisterTable
66-
const transformedRisks = risks.map((risk) => ({
72+
const totalRisks = await db.risk.count({ where });
73+
74+
const pageCount = Math.ceil(totalRisks / perPage);
75+
76+
// Transform the data to match the expected structure (assignee as User | null)
77+
const transformedRisks = risksData.map((risk) => ({
6778
...risk,
6879
assignee: risk.assignee ? risk.assignee.user : null,
6980
}));
7081

7182
return {
72-
risks: transformedRisks,
83+
data: transformedRisks,
84+
pageCount,
7385
};
7486
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { getFiltersStateParser, getSortingStateParser } from "@/lib/parsers";
2+
import { Risk } from "@comp/db/types";
3+
import {
4+
createSearchParamsCache,
5+
parseAsArrayOf,
6+
parseAsInteger,
7+
parseAsString,
8+
parseAsStringEnum,
9+
} from "nuqs/server";
10+
import * as z from "zod";
11+
12+
export const searchParamsCache = createSearchParamsCache({
13+
page: parseAsInteger.withDefault(1),
14+
perPage: parseAsInteger.withDefault(10),
15+
sort: getSortingStateParser<Risk>().withDefault([
16+
{ id: "title", desc: true },
17+
]),
18+
title: parseAsString.withDefault(""),
19+
lastUpdated: parseAsArrayOf(z.coerce.date()).withDefault([]),
20+
// advanced filter
21+
filters: getFiltersStateParser().withDefault([]),
22+
joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"),
23+
});
24+
25+
export type GetRiskSchema = Awaited<ReturnType<typeof searchParamsCache.parse>>;

apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/(overview)/page.tsx

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,47 +11,43 @@ import { headers } from "next/headers";
1111
import { cache } from "react";
1212
import { RisksTable } from "./RisksTable";
1313
import { getRisks } from "./data/getRisks";
14+
import { searchParamsCache } from "./data/validations";
15+
import { getValidFilters } from "@/lib/data-table";
1416

15-
export default async function RiskRegisterPage({
16-
params,
17-
}: {
18-
params: Promise<{
19-
orgId: string;
20-
locale: string;
17+
export default async function RiskRegisterPage(props: {
18+
params: Promise<{ locale: string; orgId: string }>;
19+
searchParams: Promise<{
2120
search: string;
22-
page: number;
23-
pageSize: number;
24-
status: RiskStatus | null;
25-
department: Departments | null;
26-
assigneeId: string | null;
21+
page: string;
22+
perPage: string;
23+
status: string;
24+
department: string;
25+
assigneeId: string;
2726
}>;
2827
}) {
29-
const {
30-
orgId,
31-
locale,
32-
search,
33-
page,
34-
pageSize,
35-
status,
36-
department,
37-
assigneeId,
38-
} = await params;
28+
const { params } = props;
29+
const { orgId, locale } = await params;
30+
31+
const searchParams = await props.searchParams;
32+
const search = searchParamsCache.parse(searchParams);
33+
const validFilters = getValidFilters(search.filters);
3934

4035
setStaticParamsLocale(locale);
4136
const t = await getI18n();
4237

43-
const risks = await getRisks({
44-
search: search,
45-
page: page || 1,
46-
pageSize: pageSize || 10,
47-
status: status || null,
48-
department: department || null,
49-
assigneeId: assigneeId || null,
38+
const risksResult = await getRisks({
39+
...search,
40+
filters: validFilters,
5041
});
5142

5243
const assignees = await getAssignees();
5344

54-
if (risks.risks?.length === 0) {
45+
if (
46+
risksResult.data?.length === 0 &&
47+
search.page === 1 &&
48+
search.title === "" &&
49+
validFilters.length === 0
50+
) {
5551
return (
5652
<>
5753
<AppOnboarding
@@ -98,9 +94,15 @@ export default async function RiskRegisterPage({
9894

9995
return (
10096
<PageWithBreadcrumb
101-
breadcrumbs={[{ label: "Risks", href: `/${orgId}/risk`, current: true }]}
97+
breadcrumbs={[
98+
{ label: "Risks", href: `/${orgId}/risk`, current: true },
99+
]}
102100
>
103-
<RisksTable risks={risks?.risks || []} assignees={assignees} />
101+
<RisksTable
102+
risks={risksResult?.data || []}
103+
pageCount={risksResult.pageCount}
104+
assignees={assignees}
105+
/>
104106
</PageWithBreadcrumb>
105107
);
106108
}

0 commit comments

Comments
 (0)