From 44b1caf31e3e2d1b0e02c12c006fdbcd144db0df Mon Sep 17 00:00:00 2001 From: Lewis Carhart Date: Thu, 3 Apr 2025 18:08:30 -0400 Subject: [PATCH] chore: update dependencies and improve localization handling - Upgraded AWS SDK clients to version 3.782.0 for S3 and SecurityHub. - Updated Turbo to version 2.5.0 for performance improvements. - Removed unused localization files for Spanish, French, Norwegian, and Portuguese. - Simplified localization setup by removing unnecessary language imports. - Enhanced error handling in email sending functionality. - Refactored various components for improved clarity and consistency in code style. --- .../actions/organization/accept-invitation.ts | 6 +- .../organization/update-member-role.ts | 9 +- .../actions/risk/task/update-task-action.ts | 4 +- apps/app/src/actions/schema.ts | 398 ++--- .../[orgId]/employees/[employeeId]/page.tsx | 241 +-- .../(overview)/hooks/useAssigneeData.ts | 127 +- .../(overview)/hooks/useEvidenceData.ts | 81 +- .../(overview)/hooks/useFrameworkData.ts | 97 +- .../(overview)/hooks/useStatusTranslation.ts | 45 +- .../risk/[riskId]/tasks/[taskId]/page.tsx | 76 +- .../actions/task/create-task-action.ts | 8 +- .../actions/task/update-task-action.ts | 8 +- .../actions/update-vendor-action.ts | 3 +- .../secondary-fields/secondary-fields.tsx | 42 +- .../update-secondary-fields-form.tsx | 338 ++-- .../tasks/create-vendor-task-form.tsx | 410 ++--- .../update-title-and-description-form.tsx | 194 +-- .../[orgId]/vendors/[vendorId]/page.tsx | 406 ++--- .../components/VendorRegisterFilters.tsx | 126 +- apps/app/src/app/api/v1/employees/route.ts | 4 +- apps/app/src/app/api/v1/risks/[id]/route.ts | 13 +- apps/app/src/app/api/v1/risks/route.ts | 11 +- .../forms/policies/update-policy-form.tsx | 270 +-- .../forms/risks/task/update-task-form.tsx | 328 ++-- .../risks/task/update-task-overview-form.tsx | 194 +-- .../forms/risks/update-risk-form.tsx | 198 +-- .../components/modals/create-org-modal.tsx | 555 +++---- .../policies/charts/policies-by-assignee.tsx | 245 --- .../policies/charts/policies-by-framework.tsx | 91 -- .../policies/sheets/policy-archive-sheet.tsx | 266 +-- .../policies/sheets/policy-overview-sheet.tsx | 108 +- .../tables/risk-register/empty-states.tsx | 96 +- .../tables/risk-register/filter-toolbar.tsx | 363 ++-- apps/app/src/data/tools/risks.ts | 2 +- apps/app/src/lib/db/employee.ts | 4 +- apps/app/src/locales/client.ts | 8 - apps/app/src/locales/es.ts | 1454 ----------------- apps/app/src/locales/fr.ts | 1387 ---------------- apps/app/src/locales/no.ts | 1387 ---------------- apps/app/src/locales/pt.ts | 1358 --------------- apps/app/src/locales/server.ts | 4 - bun.lock | 38 +- package.json | 6 +- packages/auth/src/auth.ts | 1 + packages/email/lib/resend.ts | 95 +- turbo.json | 5 +- yarn.lock | 248 ++- 47 files changed, 2715 insertions(+), 8643 deletions(-) delete mode 100644 apps/app/src/components/policies/charts/policies-by-assignee.tsx delete mode 100644 apps/app/src/components/policies/charts/policies-by-framework.tsx delete mode 100644 apps/app/src/locales/es.ts delete mode 100644 apps/app/src/locales/fr.ts delete mode 100644 apps/app/src/locales/no.ts delete mode 100644 apps/app/src/locales/pt.ts diff --git a/apps/app/src/actions/organization/accept-invitation.ts b/apps/app/src/actions/organization/accept-invitation.ts index de174bad55..9c1eb1f927 100644 --- a/apps/app/src/actions/organization/accept-invitation.ts +++ b/apps/app/src/actions/organization/accept-invitation.ts @@ -96,11 +96,15 @@ export const completeInvitation = authActionClient }; } + if (!invitation.role) { + throw new Error("Invitation role is required"); + } + await db.member.create({ data: { userId: user.id, organizationId: invitation.organizationId, - role: invitation.role || "member", + role: invitation.role, department: "none", }, }); diff --git a/apps/app/src/actions/organization/update-member-role.ts b/apps/app/src/actions/organization/update-member-role.ts index b69b50b156..779422e8f6 100644 --- a/apps/app/src/actions/organization/update-member-role.ts +++ b/apps/app/src/actions/organization/update-member-role.ts @@ -68,9 +68,16 @@ export const updateMemberRole = authActionClient }; } + if (!role) { + throw new Error("Role is required"); + } + + // Convert role to a valid role type for the authClient + const validRole = role === "auditor" ? "member" : role; + await authClient.organization.updateMemberRole({ memberId: targetMember.userId, - role: role, + role: validRole as "owner" | "admin" | "member", organizationId: ctx.session.activeOrganizationId ?? "", }); diff --git a/apps/app/src/actions/risk/task/update-task-action.ts b/apps/app/src/actions/risk/task/update-task-action.ts index 1a4a6874b1..5521ad94ec 100644 --- a/apps/app/src/actions/risk/task/update-task-action.ts +++ b/apps/app/src/actions/risk/task/update-task-action.ts @@ -18,7 +18,7 @@ export const updateTaskAction = authActionClient }, }) .action(async ({ parsedInput, ctx }) => { - const { id, dueDate, status, ownerId, title, description } = parsedInput; + const { id, dueDate, status, assigneeId, title, description } = parsedInput; const { session } = ctx; if (!session.activeOrganizationId) { @@ -44,7 +44,7 @@ export const updateTaskAction = authActionClient data: { dueDate: dueDate, status: status as TaskStatus, - userId: ownerId, + assigneeId: assigneeId, title: title, description: description, }, diff --git a/apps/app/src/actions/schema.ts b/apps/app/src/actions/schema.ts index f64088f130..5a32495d8c 100644 --- a/apps/app/src/actions/schema.ts +++ b/apps/app/src/actions/schema.ts @@ -1,292 +1,292 @@ import { - Departments, - FrameworkId, - Frequency, - Impact, - Likelihood, - PolicyStatus, - RiskCategory, - RiskStatus, - TaskStatus, + Departments, + FrameworkId, + Frequency, + Impact, + Likelihood, + PolicyStatus, + RiskCategory, + RiskStatus, + TaskStatus, } from "@comp/db/types"; import { z } from "zod"; export const organizationSchema = z.object({ - name: z.string().min(1, "Organization name is required"), - frameworks: z - .array(z.nativeEnum(FrameworkId)) - .min(1, "Please select at least one framework to get started with"), + name: z.string().min(1, "Organization name is required"), + frameworks: z + .array(z.nativeEnum(FrameworkId)) + .min(1, "Please select at least one framework to get started with"), }); export type OrganizationSchema = z.infer; export const organizationNameSchema = z.object({ - name: z - .string() - .min(1, "Organization name is required") - .max(255, "Organization name cannot exceed 255 characters"), + name: z + .string() + .min(1, "Organization name is required") + .max(255, "Organization name cannot exceed 255 characters"), }); export const subdomainAvailabilitySchema = z.object({ - subdomain: z - .string() - .min(1, "Subdomain is required") - .max(255, "Subdomain cannot exceed 255 characters") - .regex(/^[a-z0-9-]+$/, { - message: - "Subdomain can only contain lowercase letters, numbers, and hyphens", - }), + subdomain: z + .string() + .min(1, "Subdomain is required") + .max(255, "Subdomain cannot exceed 255 characters") + .regex(/^[a-z0-9-]+$/, { + message: + "Subdomain can only contain lowercase letters, numbers, and hyphens", + }), }); export const uploadSchema = z.object({ - file: z.instanceof(File), - organizationId: z.string(), + file: z.instanceof(File), + organizationId: z.string(), }); export const deleteOrganizationSchema = z.object({ - id: z.string(), - organizationId: z.string(), + id: z.string(), + organizationId: z.string(), }); export const sendFeedbackSchema = z.object({ - feedback: z.string(), + feedback: z.string(), }); export const updaterMenuSchema = z.array( - z.object({ - path: z.string(), - name: z.string(), - }) + z.object({ + path: z.string(), + name: z.string(), + }), ); export const organizationWebsiteSchema = z.object({ - website: z.string().url().max(255), + website: z.string().url().max(255), }); // Risks export const createRiskSchema = z.object({ - title: z - .string({ - required_error: "Risk name is required", - }) - .min(1, { - message: "Risk name should be at least 1 character", - }) - .max(100, { - message: "Risk name should be at most 100 characters", - }), - description: z - .string({ - required_error: "Risk description is required", - }) - .min(1, { - message: "Risk description should be at least 1 character", - }) - .max(255, { - message: "Risk description should be at most 255 characters", - }), - category: z.nativeEnum(RiskCategory, { - required_error: "Risk category is required", - }), - department: z.nativeEnum(Departments, { - required_error: "Risk department is required", - }), - assigneeId: z.string().nullable(), + title: z + .string({ + required_error: "Risk name is required", + }) + .min(1, { + message: "Risk name should be at least 1 character", + }) + .max(100, { + message: "Risk name should be at most 100 characters", + }), + description: z + .string({ + required_error: "Risk description is required", + }) + .min(1, { + message: "Risk description should be at least 1 character", + }) + .max(255, { + message: "Risk description should be at most 255 characters", + }), + category: z.nativeEnum(RiskCategory, { + required_error: "Risk category is required", + }), + department: z.nativeEnum(Departments, { + required_error: "Risk department is required", + }), + assigneeId: z.string().nullable(), }); export const updateRiskSchema = z.object({ - id: z.string().min(1, { - message: "Risk ID is required", - }), - title: z.string().min(1, { - message: "Risk title is required", - }), - description: z.string().min(1, { - message: "Risk description is required", - }), - category: z.nativeEnum(RiskCategory, { - required_error: "Risk category is required", - }), - department: z.nativeEnum(Departments, { - required_error: "Risk department is required", - }), - assigneeId: z.string().nullable(), - status: z.nativeEnum(RiskStatus, { - required_error: "Risk status is required", - }), + id: z.string().min(1, { + message: "Risk ID is required", + }), + title: z.string().min(1, { + message: "Risk title is required", + }), + description: z.string().min(1, { + message: "Risk description is required", + }), + category: z.nativeEnum(RiskCategory, { + required_error: "Risk category is required", + }), + department: z.nativeEnum(Departments, { + required_error: "Risk department is required", + }), + assigneeId: z.string().nullable(), + status: z.nativeEnum(RiskStatus, { + required_error: "Risk status is required", + }), }); export const createRiskCommentSchema = z.object({ - riskId: z.string().min(1, { - message: "Risk ID is required", - }), - content: z - .string() - .min(1, { - message: "Comment content is required", - }) - .max(1000, { - message: "Comment content should be at most 1000 characters", - }), + riskId: z.string().min(1, { + message: "Risk ID is required", + }), + content: z + .string() + .min(1, { + message: "Comment content is required", + }) + .max(1000, { + message: "Comment content should be at most 1000 characters", + }), }); export const createTaskSchema = z.object({ - riskId: z.string().min(1, { - message: "Risk ID is required", - }), - title: z.string().min(1, { - message: "Task title is required", - }), - description: z.string().min(1, { - message: "Task description is required", - }), - dueDate: z.date().optional(), - ownerId: z - .string({ - required_error: "You must assign an owner to the task", - }) - .min(1, { - message: "You must assign an owner to the task", - }), + riskId: z.string().min(1, { + message: "Risk ID is required", + }), + title: z.string().min(1, { + message: "Task title is required", + }), + description: z.string().min(1, { + message: "Task description is required", + }), + dueDate: z.date().optional(), + assigneeId: z + .string({ + required_error: "You must assign an owner to the task", + }) + .min(1, { + message: "You must assign an owner to the task", + }), }); export const updateTaskSchema = z.object({ - id: z.string().min(1, { - message: "Task ID is required", - }), - title: z.string().optional(), - description: z.string().optional(), - dueDate: z.date().optional(), - status: z.nativeEnum(TaskStatus, { - required_error: "Task status is required", - }), - ownerId: z.string({ - required_error: "You must assign an owner to the task", - }), + id: z.string().min(1, { + message: "Task ID is required", + }), + title: z.string().optional(), + description: z.string().optional(), + dueDate: z.date().optional(), + status: z.nativeEnum(TaskStatus, { + required_error: "Task status is required", + }), + assigneeId: z.string({ + required_error: "You must assign an owner to the task", + }), }); export const createTaskCommentSchema = z.object({ - riskId: z.string().min(1, { - message: "Risk ID is required", - }), - taskId: z.string().min(1, { - message: "Task ID is required", - }), - content: z - .string() - .min(1, { - message: "Comment content is required", - }) - .max(1000, { - message: "Comment content should be at most 1000 characters", - }), + riskId: z.string().min(1, { + message: "Risk ID is required", + }), + taskId: z.string().min(1, { + message: "Task ID is required", + }), + content: z + .string() + .min(1, { + message: "Comment content is required", + }) + .max(1000, { + message: "Comment content should be at most 1000 characters", + }), }); export const uploadTaskFileSchema = z.object({ - riskId: z.string().min(1, { - message: "Risk ID is required", - }), - taskId: z.string().min(1, { - message: "Task ID is required", - }), + riskId: z.string().min(1, { + message: "Risk ID is required", + }), + taskId: z.string().min(1, { + message: "Task ID is required", + }), }); // Integrations export const deleteIntegrationConnectionSchema = z.object({ - integrationId: z.string().min(1, { - message: "Integration ID is required", - }), + integrationId: z.string().min(1, { + message: "Integration ID is required", + }), }); export const createIntegrationSchema = z.object({ - integrationId: z.string().min(1, { - message: "Integration ID is required", - }), + integrationId: z.string().min(1, { + message: "Integration ID is required", + }), }); // Seed Data export const seedDataSchema = z.object({ - organizationId: z.string(), + organizationId: z.string(), }); export const updateInherentRiskSchema = z.object({ - id: z.string().min(1, { - message: "Risk ID is required", - }), - probability: z.nativeEnum(Likelihood), - impact: z.nativeEnum(Impact), + id: z.string().min(1, { + message: "Risk ID is required", + }), + probability: z.nativeEnum(Likelihood), + impact: z.nativeEnum(Impact), }); export const updateResidualRiskSchema = z.object({ - id: z.string().min(1, { - message: "Risk ID is required", - }), - probability: z.number().min(1).max(10), - impact: z.number().min(1).max(10), + id: z.string().min(1, { + message: "Risk ID is required", + }), + probability: z.number().min(1).max(10), + impact: z.number().min(1).max(10), }); // Policies export const createPolicySchema = z.object({ - title: z.string(), - description: z.string(), - frameworkIds: z.array(z.string()), - controlIds: z.array(z.string()), + title: z.string(), + description: z.string(), + frameworkIds: z.array(z.string()), + controlIds: z.array(z.string()), }); export const updatePolicySchema = z.object({ - id: z.string(), - content: z.any(), + id: z.string(), + content: z.any(), }); export const assistantSettingsSchema = z.object({ - enabled: z.boolean().optional(), + enabled: z.boolean().optional(), }); export const createEmployeeSchema = z.object({ - name: z.string().min(1, "Name is required"), - email: z.string().email("Invalid email address"), - department: z.nativeEnum(Departments, { - required_error: "Department is required", - }), - externalEmployeeId: z.string().optional(), - isActive: z.boolean().default(true), + name: z.string().min(1, "Name is required"), + email: z.string().email("Invalid email address"), + department: z.nativeEnum(Departments, { + required_error: "Department is required", + }), + externalEmployeeId: z.string().optional(), + isActive: z.boolean().default(true), }); export const updatePolicyOverviewSchema = z.object({ - id: z.string(), - title: z.string(), - description: z.string(), - isRequiredToSign: z.enum(["required", "not_required"]).optional(), + id: z.string(), + title: z.string(), + description: z.string(), + isRequiredToSign: z.enum(["required", "not_required"]).optional(), }); export const updatePolicyFormSchema = z.object({ - id: z.string(), - status: z.nativeEnum(PolicyStatus), - assigneeId: z.string().nullable(), - department: z.nativeEnum(Departments), - review_frequency: z.nativeEnum(Frequency), - review_date: z.date(), - isRequiredToSign: z.enum(["required", "not_required"]), + id: z.string(), + status: z.nativeEnum(PolicyStatus), + assigneeId: z.string().nullable(), + department: z.nativeEnum(Departments), + review_frequency: z.nativeEnum(Frequency), + review_date: z.date(), + isRequiredToSign: z.enum(["required", "not_required"]), }); export const apiKeySchema = z.object({ - name: z - .string() - .min(1, { message: "Name is required" }) - .max(64, { message: "Name must be less than 64 characters" }), - expiresAt: z.enum(["30days", "90days", "1year", "never"]), + name: z + .string() + .min(1, { message: "Name is required" }) + .max(64, { message: "Name must be less than 64 characters" }), + expiresAt: z.enum(["30days", "90days", "1year", "never"]), }); export const createPolicyCommentSchema = z.object({ - policyId: z.string().min(1, { - message: "Policy ID is required", - }), - content: z - .string() - .min(1, { - message: "Comment content is required", - }) - .max(1000, { - message: "Comment content should be at most 1000 characters", - }), + policyId: z.string().min(1, { + message: "Policy ID is required", + }), + content: z + .string() + .min(1, { + message: "Comment content is required", + }) + .max(1000, { + message: "Comment content should be at most 1000 characters", + }), }); diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/employees/[employeeId]/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/employees/[employeeId]/page.tsx index 6654404c1b..94c37e518a 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/employees/[employeeId]/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/employees/[employeeId]/page.tsx @@ -1,8 +1,9 @@ import { cache } from "react"; import { auth } from "@comp/auth"; import { getI18n } from "@/locales/server"; -import { trainingVideos as trainingVideosData } from "@comp/data"; +import { trainingVideos as trainingVideosData, TrainingVideo } from "@comp/data"; import { db } from "@comp/db"; +import type { EmployeeTrainingVideoCompletion } from "@comp/db/types"; import type { Metadata } from "next"; import { setStaticParamsLocale } from "next-international/server"; import { notFound, redirect } from "next/navigation"; @@ -10,140 +11,142 @@ import { EmployeeDetails } from "./components/EmployeeDetails"; import { headers } from "next/headers"; export default async function EmployeeDetailsPage({ - params, + params, }: { - params: Promise<{ locale: string; employeeId: string }>; + params: Promise<{ locale: string; employeeId: string }>; }) { - const { locale, employeeId } = await params; - setStaticParamsLocale(locale); - - const session = await auth.api.getSession({ - headers: await headers(), - }); - - const organizationId = session?.session.activeOrganizationId; - - if (!organizationId) { - redirect("/"); - } - - const policies = await getPoliciesTasks(employeeId); - const employeeTrainingVideos = await getTrainingVideos(employeeId); - const employee = await getEmployee(employeeId); - - // If employee doesn't exist, show 404 page - if (!employee) { - notFound(); - } - - return ( - - ); + const { locale, employeeId } = await params; + setStaticParamsLocale(locale); + + const session = await auth.api.getSession({ + headers: await headers(), + }); + + const organizationId = session?.session.activeOrganizationId; + + if (!organizationId) { + redirect("/"); + } + + const policies = await getPoliciesTasks(employeeId); + const employeeTrainingVideos = await getTrainingVideos(employeeId); + const employee = await getEmployee(employeeId); + + // If employee doesn't exist, show 404 page + if (!employee) { + notFound(); + } + + return ( + + ); } export async function generateMetadata({ - params, + params, }: { - params: Promise<{ locale: string; employeeId: string }>; + params: Promise<{ locale: string; employeeId: string }>; }): Promise { - const { locale } = await params; + const { locale } = await params; - setStaticParamsLocale(locale); - const t = await getI18n(); + setStaticParamsLocale(locale); + const t = await getI18n(); - return { - title: t("people.details.title"), - }; + return { + title: t("people.details.title"), + }; } const getEmployee = cache(async (employeeId: string) => { - const session = await auth.api.getSession({ - headers: await headers(), - }); - - const organizationId = session?.session.activeOrganizationId; - - if (!organizationId) { - redirect("/"); - } - - const employee = await db.member.findFirst({ - where: { - id: employeeId, - }, - include: { - user: true, - }, - }); - - return employee; + const session = await auth.api.getSession({ + headers: await headers(), + }); + + const organizationId = session?.session.activeOrganizationId; + + if (!organizationId) { + redirect("/"); + } + + const employee = await db.member.findFirst({ + where: { + id: employeeId, + }, + include: { + user: true, + }, + }); + + return employee; }); const getPoliciesTasks = cache(async (employeeId: string) => { - const session = await auth.api.getSession({ - headers: await headers(), - }); - - const organizationId = session?.session.activeOrganizationId; - - if (!organizationId) { - redirect("/"); - } - - const policies = await db.policy.findMany({ - where: { - organizationId: organizationId, - isRequiredToSign: true, - }, - orderBy: { - name: "asc", - }, - }); - - return policies; + const session = await auth.api.getSession({ + headers: await headers(), + }); + + const organizationId = session?.session.activeOrganizationId; + + if (!organizationId) { + redirect("/"); + } + + const policies = await db.policy.findMany({ + where: { + organizationId: organizationId, + isRequiredToSign: true, + }, + orderBy: { + name: "asc", + }, + }); + + return policies; }); const getTrainingVideos = async (employeeId: string) => { - const session = await auth.api.getSession({ - headers: await headers(), - }); - - const organizationId = session?.session.activeOrganizationId; - - if (!organizationId) { - redirect("/"); - } - - const employeeTrainingVideos = - await db.employeeTrainingVideoCompletion.findMany({ - where: { - memberId: employeeId, - }, - orderBy: { - videoId: "asc", - }, - }); - - console.log({ - employeeTrainingVideos, - }); - - // Map the db records to include the matching metadata from the training videos data - return employeeTrainingVideos.map((dbVideo) => { - // Find the training video metadata with the matching ID - const videoMetadata = trainingVideosData.find( - (metadataVideo) => metadataVideo.id === dbVideo.videoId, - ); - - // Return the combined object with the correct structure - return { - ...dbVideo, - metadata: videoMetadata, - }; - }); + const session = await auth.api.getSession({ + headers: await headers(), + }); + + const organizationId = session?.session.activeOrganizationId; + + if (!organizationId) { + redirect("/"); + } + + const employeeTrainingVideos = + await db.employeeTrainingVideoCompletion.findMany({ + where: { + memberId: employeeId, + }, + orderBy: { + videoId: "asc", + }, + }); + + // Map the db records to include the matching metadata from the training videos data + // Filter out any videos where metadata is not found to ensure type safety + return employeeTrainingVideos + .map((dbVideo) => { + // Find the training video metadata with the matching ID + const videoMetadata = trainingVideosData.find( + (metadataVideo) => metadataVideo.id === dbVideo.videoId, + ); + + // Only return videos that have matching metadata + if (videoMetadata) { + return { + ...dbVideo, + metadata: videoMetadata, + }; + } + return null; + }) + .filter((video): video is (EmployeeTrainingVideoCompletion & { metadata: TrainingVideo }) => video !== null); }; diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/(overview)/hooks/useAssigneeData.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/(overview)/hooks/useAssigneeData.ts index 63594de0f5..a32283a6c7 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/(overview)/hooks/useAssigneeData.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/(overview)/hooks/useAssigneeData.ts @@ -1,84 +1,87 @@ +import { StatusType } from "@/components/status-policies"; import { useI18n } from "@/locales/client"; -import type { StatusType } from "../constants/evidence-status"; -import type { EvidenceWithStatus } from "../data/getEvidenceDashboard"; /** * Interface for the processed assignee data */ export interface AssigneeData { - id: string; - name: string; - totalItems: number; - items: EvidenceWithStatus[]; - statusCounts: Record; + id: string; + name: string; + totalItems: number; + items: any; + statusCounts: Record; } /** * Custom hook for assignee evidence data processing */ export function useAssigneeData() { - const t = useI18n(); + const t = useI18n(); - /** - * Transform raw assignee data into a format suitable for charts - */ - const prepareAssigneeData = ( - byAssignee?: Record, - unassigned: EvidenceWithStatus[] = [] - ): AssigneeData[] => { - const assigneeData: AssigneeData[] = []; + /** + * Transform raw assignee data into a format suitable for charts + */ + const prepareAssigneeData = ( + byAssignee?: Record, + unassigned: any[] = [], + ): AssigneeData[] => { + const assigneeData: AssigneeData[] = []; - // Process assigned evidence - if (byAssignee) { - for (const [assigneeId, items] of Object.entries(byAssignee)) { - const statusCounts: Record = { - empty: 0, - draft: 0, - needsReview: 0, - upToDate: 0, - }; + // Process assigned evidence + if (byAssignee) { + for (const [assigneeId, items] of Object.entries(byAssignee)) { + const statusCounts: Record = { + draft: 0, + published: 0, + archived: 0, + needs_review: 0, + relevant: 0, + "not-relevant": 0, + }; - for (const item of items) { - statusCounts[item.status as StatusType]++; - } + for (const item of items) { + statusCounts[item.status as StatusType]++; + } - assigneeData.push({ - id: assigneeId, - name: assigneeId || "Unassigned", - totalItems: items.length, - items, - statusCounts, - }); - } - } + assigneeData.push({ + id: assigneeId, + name: assigneeId || "Unassigned", + totalItems: items.length, + items, + statusCounts, + }); + } + } - // Process unassigned evidence - if (unassigned.length > 0) { - const statusCounts: Record = { - empty: 0, - draft: 0, - needsReview: 0, - upToDate: 0, - }; + // Process unassigned evidence + if (unassigned.length > 0) { + const statusCounts: Record = { + draft: 0, + needs_review: 0, + relevant: 0, + "not-relevant": 0, + published: 0, + archived: 0, + }; - for (const item of unassigned) { - statusCounts[item.status as StatusType]++; - } + for (const item of unassigned) { + statusCounts[item.status as StatusType]++; + } - assigneeData.push({ - id: "unassigned", - name: "Unassigned", - totalItems: unassigned.length, - items: unassigned, - statusCounts, - }); - } + assigneeData.push({ + id: "unassigned", + name: "Unassigned", + totalItems: unassigned.length, + items: unassigned, + statusCounts, + }); + } - // Sort by count in descending order - return assigneeData.sort((a, b) => b.totalItems - a.totalItems); - }; + // Sort by count in descending order + return assigneeData.sort((a, b) => b.totalItems - a.totalItems); + }; - return { - prepareAssigneeData, - }; + return { + prepareAssigneeData, + }; } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/(overview)/hooks/useEvidenceData.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/(overview)/hooks/useEvidenceData.ts index 744a6a8adf..dc4e254acc 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/(overview)/hooks/useEvidenceData.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/(overview)/hooks/useEvidenceData.ts @@ -1,60 +1,61 @@ import { useI18n } from "@/locales/client"; import type { Departments } from "@prisma/client"; import { DEPARTMENT_NAMES } from "../constants/departments"; -import type { StatusType } from "../constants/evidence-status"; -import type { EvidenceWithStatus } from "../data/getEvidenceDashboard"; +import { StatusType } from "@/components/status-policies"; /** * Interface for the processed department data */ export interface DepartmentData { - id: Departments; - name: string; - totalItems: number; - statusCounts: Record; + id: Departments; + name: string; + totalItems: number; + statusCounts: Record; } /** * Custom hook for evidence data processing and translations */ export function useEvidenceData() { - const t = useI18n(); + const t = useI18n(); - /** - * Transform raw department data into a format suitable for charts - */ - const prepareDepartmentData = ( - byDepartment: Record - ): DepartmentData[] => { - return Object.entries(byDepartment) - .filter(([_, items]) => items.length > 0) - .map(([dept, items]) => { - const department = dept as Departments; - const statusCounts: Record = { - empty: 0, - draft: 0, - needsReview: 0, - upToDate: 0, - }; + /** + * Transform raw department data into a format suitable for charts + */ + const prepareDepartmentData = ( + byDepartment: Record, + ): DepartmentData[] => { + return Object.entries(byDepartment) + .filter(([_, items]) => items.length > 0) + .map(([dept, items]) => { + const department = dept as Departments; + const statusCounts: Record = { + draft: 0, + published: 0, + archived: 0, + needs_review: 0, + relevant: 0, + "not-relevant": 0, + }; - for (const item of items) { - statusCounts[item.status as StatusType]++; - } + for (const item of items) { + statusCounts[item.status as StatusType]++; + } - // Use predefined display name or fallback to department value - const name = DEPARTMENT_NAMES[department] || department; + // Use predefined display name or fallback to department value + const name = DEPARTMENT_NAMES[department] || department; - return { - id: department, - name, - totalItems: items.length, - statusCounts, - }; - }) - .sort((a, b) => b.totalItems - a.totalItems); - }; + return { + id: department, + name, + totalItems: items.length, + statusCounts, + }; + }) + .sort((a, b) => b.totalItems - a.totalItems); + }; - return { - prepareDepartmentData, - }; + return { + prepareDepartmentData, + }; } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/(overview)/hooks/useFrameworkData.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/(overview)/hooks/useFrameworkData.ts index 308e993288..075657b23b 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/(overview)/hooks/useFrameworkData.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/(overview)/hooks/useFrameworkData.ts @@ -1,60 +1,61 @@ -import type { EvidenceWithStatus } from "../data/getEvidenceDashboard"; -import type { StatusType } from "../constants/evidence-status"; +import { StatusType } from "@/components/status-policies"; /** * Interface for the processed framework data */ export interface FrameworkData { - id: string; - name: string; - totalItems: number; - items: EvidenceWithStatus[]; - statusCounts: Record; + id: string; + name: string; + totalItems: number; + items: any[]; + statusCounts: Record; } /** * Custom hook for framework evidence data processing */ export function useFrameworkData() { - /** - * Transform raw framework data into a format suitable for charts - */ - const prepareFrameworkData = ( - byFramework?: Record - ): FrameworkData[] => { - if (!byFramework || Object.keys(byFramework).length === 0) { - return []; - } - - const frameworkData: FrameworkData[] = []; - - // Process framework evidence - for (const [frameworkId, items] of Object.entries(byFramework)) { - const statusCounts: Record = { - empty: 0, - draft: 0, - needsReview: 0, - upToDate: 0, - }; - - for (const item of items) { - statusCounts[item.status as StatusType]++; - } - - frameworkData.push({ - id: frameworkId, - name: frameworkId, - totalItems: items.length, - items, - statusCounts, - }); - } - - // Sort by count in descending order - return frameworkData.sort((a, b) => b.totalItems - a.totalItems); - }; - - return { - prepareFrameworkData, - }; + /** + * Transform raw framework data into a format suitable for charts + */ + const prepareFrameworkData = ( + byFramework?: Record, + ): FrameworkData[] => { + if (!byFramework || Object.keys(byFramework).length === 0) { + return []; + } + + const frameworkData: FrameworkData[] = []; + + // Process framework evidence + for (const [frameworkId, items] of Object.entries(byFramework)) { + const statusCounts: Record = { + draft: 0, + published: 0, + archived: 0, + needs_review: 0, + relevant: 0, + "not-relevant": 0, + }; + + for (const item of items) { + statusCounts[item.status as StatusType]++; + } + + frameworkData.push({ + id: frameworkId, + name: frameworkId, + totalItems: items.length, + items, + statusCounts, + }); + } + + // Sort by count in descending order + return frameworkData.sort((a, b) => b.totalItems - a.totalItems); + }; + + return { + prepareFrameworkData, + }; } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/(overview)/hooks/useStatusTranslation.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/(overview)/hooks/useStatusTranslation.ts index 354098b05a..d49470da81 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/(overview)/hooks/useStatusTranslation.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/(overview)/hooks/useStatusTranslation.ts @@ -1,31 +1,32 @@ import { useI18n } from "@/locales/client"; -import type { StatusType } from "../constants/evidence-status"; + +type StatusType = "upToDate" | "needsReview" | "draft" | "empty"; /** * Custom hook for evidence status translations */ export function useStatusTranslation() { - const t = useI18n(); + const t = useI18n(); - /** - * Get translated status label - */ - const getStatusLabel = (status: StatusType): string => { - switch (status) { - case "upToDate": - return t("evidence.status.up_to_date"); - case "needsReview": - return t("evidence.status.needs_review"); - case "draft": - return t("evidence.status.draft"); - case "empty": - return t("evidence.status.empty"); - default: - return status; - } - }; + /** + * Get translated status label + */ + const getStatusLabel = (status: StatusType): string => { + switch (status) { + case "upToDate": + return t("evidence.status.up_to_date"); + case "needsReview": + return t("evidence.status.needs_review"); + case "draft": + return t("evidence.status.draft"); + case "empty": + return t("evidence.status.empty"); + default: + return status; + } + }; - return { - getStatusLabel, - }; + return { + getStatusLabel, + }; } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/tasks/[taskId]/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/tasks/[taskId]/page.tsx index 83f70569e2..b52723c715 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/tasks/[taskId]/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/risk/[riskId]/tasks/[taskId]/page.tsx @@ -9,59 +9,59 @@ import { headers } from "next/headers"; import { redirect } from "next/navigation"; import { cache } from "react"; interface PageProps { - params: Promise<{ riskId: string; taskId: string }>; + params: Promise<{ riskId: string; taskId: string }>; } export default async function RiskPage({ params }: PageProps) { - const { riskId, taskId } = await params; - const task = await getTask(riskId, taskId); - const users = await useUsers(); + const { riskId, taskId } = await params; + const task = await getTask(riskId, taskId); + const users = await useUsers(); - if (!task) { - redirect("/"); - } + if (!task) { + redirect("/"); + } - return ( -
- -
- ); + return ( +
+ +
+ ); } const getTask = cache(async (riskId: string, taskId: string) => { - const session = await auth.api.getSession({ - headers: await headers(), - }); + const session = await auth.api.getSession({ + headers: await headers(), + }); - if (!session || !session.session.activeOrganizationId) { - redirect("/"); - } + if (!session || !session.session.activeOrganizationId) { + redirect("/"); + } - const task = await db.task.findUnique({ - where: { - relatedId: riskId, - relatedType: "risk", - id: taskId, - organizationId: session.session.activeOrganizationId, - }, - include: { - user: true, - }, - }); + const task = await db.task.findUnique({ + where: { + relatedId: riskId, + relatedType: "risk", + id: taskId, + organizationId: session.session.activeOrganizationId, + }, + include: { + assignee: true, + }, + }); - return task; + return task; }); export async function generateMetadata({ - params, + params, }: { - params: Promise<{ locale: string }>; + params: Promise<{ locale: string }>; }): Promise { - const { locale } = await params; - setStaticParamsLocale(locale); - const t = await getI18n(); + const { locale } = await params; + setStaticParamsLocale(locale); + const t = await getI18n(); - return { - title: t("risk.tasks.task_overview"), - }; + return { + title: t("risk.tasks.task_overview"), + }; } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/actions/task/create-task-action.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/actions/task/create-task-action.ts index 30ddb68c44..71fa7dc8b0 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/actions/task/create-task-action.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/actions/task/create-task-action.ts @@ -17,7 +17,7 @@ export const createVendorTaskAction = authActionClient }, }) .action(async ({ parsedInput, ctx }) => { - const { vendorId, title, description, dueDate, ownerId } = parsedInput; + const { vendorId, title, description, dueDate, assigneeId } = parsedInput; const { session: { activeOrganizationId }, user, @@ -27,13 +27,17 @@ export const createVendorTaskAction = authActionClient throw new Error("Invalid user input"); } + if (!assigneeId) { + throw new Error("Assignee ID is required"); + } + try { await db.task.create({ data: { title, description, dueDate, - userId: user.id, + assigneeId, organizationId: activeOrganizationId, relatedId: vendorId, relatedType: "vendor", diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/actions/task/update-task-action.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/actions/task/update-task-action.ts index c3aee8f88e..274e80370a 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/actions/task/update-task-action.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/actions/task/update-task-action.ts @@ -18,13 +18,17 @@ export const updateVendorTaskAction = authActionClient }, }) .action(async ({ parsedInput, ctx }) => { - const { id, title, description, dueDate, status, userId } = parsedInput; + const { id, title, description, dueDate, status, assigneeId } = parsedInput; const { session } = ctx; if (!session.activeOrganizationId) { throw new Error("Invalid user input"); } + if (!assigneeId) { + throw new Error("Assignee ID is required"); + } + try { const task = await db.task.findUnique({ where: { @@ -49,7 +53,7 @@ export const updateVendorTaskAction = authActionClient description, dueDate, status: status as TaskStatus, - userId, + assigneeId, }, }); diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/actions/update-vendor-action.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/actions/update-vendor-action.ts index a674185729..22a9f279f6 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/actions/update-vendor-action.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/actions/update-vendor-action.ts @@ -17,7 +17,7 @@ export const updateVendorAction = authActionClient }, }) .action(async ({ parsedInput, ctx }) => { - const { id, name, description, category, ownerId, status } = parsedInput; + const { id, name, description, category, status } = parsedInput; const { session } = ctx; if (!session.activeOrganizationId) { @@ -33,7 +33,6 @@ export const updateVendorAction = authActionClient data: { name, description, - ownerId, category, status, }, diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/secondary-fields/secondary-fields.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/secondary-fields/secondary-fields.tsx index 39e1a5779a..6019d4c087 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/secondary-fields/secondary-fields.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/secondary-fields/secondary-fields.tsx @@ -6,28 +6,28 @@ import { Card, CardContent, CardHeader, CardTitle } from "@comp/ui/card"; import { UpdateSecondaryFieldsForm } from "./update-secondary-fields-form"; export function SecondaryFields({ - vendor, - users, + vendor, + users, }: { - vendor: Vendor & { owner: User | null }; - users: User[]; + vendor: Vendor & { owner: User | null }; + users: User[]; }) { - const t = useI18n(); + const t = useI18n(); - return ( -
- - - -
- {t("risk.dashboard.overview")} -
-
-
- - - -
-
- ); + return ( +
+ + + +
+ {t("risk.dashboard.overview")} +
+
+
+ + + +
+
+ ); } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/secondary-fields/update-secondary-fields-form.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/secondary-fields/update-secondary-fields-form.tsx index 2af58c6d9c..4ace1b829d 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/secondary-fields/update-secondary-fields-form.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/secondary-fields/update-secondary-fields-form.tsx @@ -6,19 +6,19 @@ import { useI18n } from "@/locales/client"; import { VendorCategory, type User, type Vendor } from "@comp/db/types"; import { Button } from "@comp/ui/button"; import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, } from "@comp/ui/form"; import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, } from "@comp/ui/select"; import { zodResolver } from "@hookform/resolvers/zod"; import { Loader2 } from "lucide-react"; @@ -30,168 +30,168 @@ import { updateVendorAction } from "../../actions/update-vendor-action"; import { updateVendorSchema } from "../../actions/schema"; export function UpdateSecondaryFieldsForm({ - vendor, - users, + vendor, + users, }: { - vendor: Vendor; - users: User[]; + vendor: Vendor & { owner: User | null }; + users: User[]; }) { - const t = useI18n(); + const t = useI18n(); - const updateVendor = useAction(updateVendorAction, { - onSuccess: () => { - toast.success(t("vendors.form.update_vendor_success")); - }, - onError: () => { - toast.error(t("vendors.form.update_vendor_error")); - }, - }); + const updateVendor = useAction(updateVendorAction, { + onSuccess: () => { + toast.success(t("vendors.form.update_vendor_success")); + }, + onError: () => { + toast.error(t("vendors.form.update_vendor_error")); + }, + }); - const form = useForm>({ - resolver: zodResolver(updateVendorSchema), - defaultValues: { - id: vendor.id, - name: vendor.name, - description: vendor.description, - ownerId: vendor.ownerId ?? undefined, - category: vendor.category, - status: vendor.status, - }, - }); + const form = useForm>({ + resolver: zodResolver(updateVendorSchema), + defaultValues: { + id: vendor.id, + name: vendor.name, + description: vendor.description, + assigneeId: vendor.ownerId ?? undefined, + category: vendor.category, + status: vendor.status, + }, + }); - const onSubmit = (data: z.infer) => { - updateVendor.execute({ - id: data.id, - name: data.name, - description: data.description, - ownerId: data.ownerId, - category: data.category, - status: data.status, - }); - }; + const onSubmit = (data: z.infer) => { + updateVendor.execute({ + id: data.id, + name: data.name, + description: data.description, + assigneeId: data.assigneeId, + category: data.category, + status: data.status, + }); + }; - return ( -
- -
- ( - - {t("common.assignee.label")} - - - - - - )} - /> - ( - - {t("vendors.form.vendor_status")} - - - - - - )} - /> - ( - - {t("vendors.form.vendor_category")} - - - - - - )} - /> -
-
- -
-
- - ); + return ( +
+ +
+ ( + + {t("common.assignee.label")} + + + + + + )} + /> + ( + + {t("vendors.form.vendor_status")} + + + + + + )} + /> + ( + + {t("vendors.form.vendor_category")} + + + + + + )} + /> +
+
+ +
+
+ + ); } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/tasks/create-vendor-task-form.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/tasks/create-vendor-task-form.tsx index c164942e9f..cb33a51829 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/tasks/create-vendor-task-form.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/tasks/create-vendor-task-form.tsx @@ -6,29 +6,29 @@ import { createVendorTaskSchema } from "../../actions/schema"; import { SelectUser } from "@/components/select-user"; import { useI18n } from "@/locales/client"; import { - Accordion, - AccordionContent, - AccordionItem, - AccordionTrigger, + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, } from "@comp/ui/accordion"; import { Button } from "@comp/ui/button"; import { Calendar } from "@comp/ui/calendar"; import { cn } from "@comp/ui/cn"; import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, } from "@comp/ui/form"; import { Input } from "@comp/ui/input"; import { Popover, PopoverContent, PopoverTrigger } from "@comp/ui/popover"; import { - Select, - SelectContent, - SelectTrigger, - SelectValue, + Select, + SelectContent, + SelectTrigger, + SelectValue, } from "@comp/ui/select"; import { Textarea } from "@comp/ui/textarea"; import { zodResolver } from "@hookform/resolvers/zod"; @@ -43,209 +43,209 @@ import { toast } from "sonner"; import type { z } from "zod"; interface User { - id: string; - image?: string | null; - name: string | null; + id: string; + image?: string | null; + name: string | null; } export function CreateVendorTaskForm() { - const t = useI18n(); + const t = useI18n(); - const [users, setUsers] = useState([]); - const [isLoadingUsers, setIsLoadingUsers] = useState(true); - const [_, setCreateVendorTaskSheet] = useQueryState( - "create-vendor-task-sheet", - ); - const params = useParams<{ vendorId: string }>(); + const [users, setUsers] = useState([]); + const [isLoadingUsers, setIsLoadingUsers] = useState(true); + const [_, setCreateVendorTaskSheet] = useQueryState( + "create-vendor-task-sheet", + ); + const params = useParams<{ vendorId: string }>(); - useEffect(() => { - async function loadUsers() { - const result = await getOrganizationUsersAction(); - if (result?.data?.success && result?.data?.data) { - setUsers(result.data.data); - } - setIsLoadingUsers(false); - } + useEffect(() => { + async function loadUsers() { + const result = await getOrganizationUsersAction(); + if (result?.data?.success && result?.data?.data) { + setUsers(result.data.data); + } + setIsLoadingUsers(false); + } - loadUsers(); - }, []); + loadUsers(); + }, []); - const createTask = useAction(createVendorTaskAction, { - onSuccess: () => { - toast.success(t("risk.tasks.form.success")); - setCreateVendorTaskSheet(null); - }, - onError: () => { - toast.error(t("risk.tasks.form.error")); - }, - }); + const createTask = useAction(createVendorTaskAction, { + onSuccess: () => { + toast.success(t("risk.tasks.form.success")); + setCreateVendorTaskSheet(null); + }, + onError: () => { + toast.error(t("risk.tasks.form.error")); + }, + }); - const form = useForm>({ - resolver: zodResolver(createVendorTaskSchema), - defaultValues: { - title: "", - description: "", - dueDate: new Date(), - ownerId: "", - vendorId: params.vendorId, - }, - }); + const form = useForm>({ + resolver: zodResolver(createVendorTaskSchema), + defaultValues: { + title: "", + description: "", + dueDate: new Date(), + assigneeId: "", + vendorId: params.vendorId, + }, + }); - const onSubmit = (data: z.infer) => { - createTask.execute(data); - }; + const onSubmit = (data: z.infer) => { + createTask.execute(data); + }; - return ( -
- -
-
- - - - {t("risk.tasks.form.title")} - - -
- ( - - - {t("risk.tasks.form.task_title")} - - - - - - - )} - /> + return ( + + +
+
+ + + + {t("risk.tasks.form.title")} + + +
+ ( + + + {t("risk.tasks.form.task_title")} + + + + + + + )} + /> - ( - - - {t("risk.tasks.form.description")} - - -