From 7652bdb9e42eb6b2960c0d785e3ec09c9424d384 Mon Sep 17 00:00:00 2001 From: Lewis Carhart Date: Fri, 28 Feb 2025 18:13:56 +0000 Subject: [PATCH] chore: Standardize code formatting and trailing commas across project - Update Biome configuration to enforce consistent formatting - Add trailing commas to multiple TypeScript and JSON files - Normalize indentation and line ending settings - Improve code consistency across various components and actions --- .../framework/get-framework-categories.ts | 9 +- .../framework/select-frameworks-action.ts | 568 +++++++++--------- .../check-subdomain-availability.ts | 10 +- .../create-organization-action.ts | 30 +- .../actions/policies/update-policy-action.ts | 4 +- .../policies/update-policy-form-action.ts | 10 +- apps/app/src/actions/schema.ts | 12 +- .../(home)/components/FrameworksGrid.tsx | 4 +- .../(dashboard)/(home)/hooks/useFrameworks.ts | 2 +- .../[id]/hooks/useOrganizationControl.ts | 2 +- .../hooks/useOrganizationControlProgress.ts | 2 +- .../useOrganizationControlRequirements.ts | 2 +- .../getAllOrganizationControlRequirements.ts | 2 +- .../evidence/Actions/getEvidence.ts | 2 +- .../Actions/getOrganizationEvidence.ts | 2 +- .../Actions/getOrganizationEvidenceTasks.ts | 2 +- .../EvidenceFilters/FilterDropdown.tsx | 4 +- .../data-table/data-table-header.tsx | 4 +- .../evidence/[id]/Actions/assignEvidence.ts | 2 +- .../[id]/Actions/getEvidenceFileUrl.ts | 2 +- .../evidence/[id]/Actions/toggleRelevance.ts | 2 +- .../[id]/Actions/updateEvidenceUrls.ts | 2 +- .../[id]/Actions/uploadEvidenceFile.ts | 2 +- .../[id]/Components/AssigneeSection.tsx | 2 +- .../[id]/Components/DepartmentSection.tsx | 6 +- .../evidence/[id]/Components/FileSection.tsx | 2 +- .../evidence/[id]/Components/FileUpload.tsx | 6 +- .../[id]/Components/FrequencySection.tsx | 4 +- .../evidence/[id]/hooks/useFileDelete.ts | 2 +- .../evidence/[id]/hooks/useFilePreview.ts | 2 +- .../evidence/[id]/hooks/useFileUpload.ts | 4 +- .../[id]/hooks/useOrganizationEvidence.ts | 4 +- .../evidence/[id]/hooks/useUrlManagement.ts | 4 +- .../hooks/useEvidenceTableContext.tsx | 2 +- .../evidence/hooks/useEvidenceTasks.ts | 6 +- .../evidence/hooks/useEvidenceTasksStats.ts | 4 +- .../overview/actions/getEvidenceDashboard.ts | 2 +- .../overview/components/AssigneeBarChart.tsx | 4 +- .../components/DepartmentBarChart.tsx | 2 +- .../overview/components/FrameworkBarChart.tsx | 4 +- .../overview/hooks/useEvidenceDashboard.ts | 2 +- .../Components/FrameworkControls.tsx | 2 +- .../Components/FrameworkOverview.tsx | 6 +- .../hooks/useOrganizationCategories.ts | 2 +- .../hooks/useOrganizationFramework.ts | 6 +- .../(dashboard)/people/hooks/useEmployee.ts | 4 +- .../(dashboard)/people/hooks/useEmployees.ts | 6 +- .../all/(overview)/actions/get-policies.ts | 50 +- .../all/(overview)/hooks/usePolicies.ts | 8 +- .../all/(overview)/hooks/usePolicy.ts | 14 +- .../policies/all/(overview)/types/index.ts | 2 +- .../all/(overview)/types/search-params.ts | 2 +- .../editor/actions/get-policy-details.ts | 7 +- .../editor/actions/update-policy.ts | 9 +- .../all/[policyId]/editor/types/index.ts | 4 +- apps/app/src/components/editor/extensions.ts | 2 +- apps/app/src/components/main-menu.tsx | 12 +- .../components/tables/frameworks/columns.tsx | 4 +- .../tables/frameworks/data-table-header.tsx | 2 +- .../tables/frameworks/data-table.tsx | 2 +- .../tables/people/data-table-header.tsx | 2 +- apps/app/src/hooks/use-mobile.ts | 4 +- apps/app/src/hooks/use-notifications.ts | 32 +- apps/app/src/jobs/seed/policies/change.json | 7 +- .../jobs/seed/policies/classification.json | 7 +- .../tasks/notifications/risk-task-schedule.ts | 25 +- .../tasks/organization/new-organization.ts | 2 +- apps/app/src/lib/domains.ts | 30 +- apps/app/src/lib/operator/actions.ts | 2 +- apps/app/src/lib/operator/browser.ts | 4 +- apps/app/src/lib/operator/dom.ts | 420 ++++++------- apps/app/src/lib/operator/session.ts | 2 +- apps/app/src/lib/utils.ts | 2 +- .../src/lib/utils/calculate-next-review.ts | 2 +- apps/app/src/locales/es.ts | 349 ++++++----- apps/app/src/locales/fr.ts | 370 +++++++----- apps/app/src/locales/no.ts | 330 +++++----- apps/app/src/locales/pt.ts | 344 ++++++----- apps/app/src/styles/globals.css | 2 +- biome.json | 25 +- 80 files changed, 1508 insertions(+), 1340 deletions(-) diff --git a/apps/app/src/actions/framework/get-framework-categories.ts b/apps/app/src/actions/framework/get-framework-categories.ts index 906577bc9d..732aa4fc6d 100644 --- a/apps/app/src/actions/framework/get-framework-categories.ts +++ b/apps/app/src/actions/framework/get-framework-categories.ts @@ -2,14 +2,7 @@ import type { TransformedCategory, - TransformedControl, } from "@/types/framework"; -import type { - ComplianceStatus, - Control, - FrameworkCategory, - OrganizationControl, -} from "@bubba/db"; import { db } from "@bubba/db"; import { z } from "zod"; import { authActionClient } from "../safe-action"; @@ -68,7 +61,7 @@ export const getFrameworkCategoriesAction = authActionClient requiredArtifactTypes: control.requirements?.map((req) => req.type) || [], })), - }) + }), ); return { diff --git a/apps/app/src/actions/framework/select-frameworks-action.ts b/apps/app/src/actions/framework/select-frameworks-action.ts index 5290458007..dfd02d3462 100644 --- a/apps/app/src/actions/framework/select-frameworks-action.ts +++ b/apps/app/src/actions/framework/select-frameworks-action.ts @@ -7,308 +7,308 @@ import type { ActionData } from "../types"; import type { InputJsonValue } from "@prisma/client/runtime/library"; const selectFrameworksSchema = z.object({ - frameworkIds: z.array(z.string()), + frameworkIds: z.array(z.string()), }); export const selectFrameworksAction = authActionClient - .schema(selectFrameworksSchema) - .metadata({ - name: "select-frameworks", - track: { - event: "select-frameworks", - channel: "server", - }, - }) - .action(async ({ parsedInput, ctx }): Promise> => { - const { frameworkIds } = parsedInput; - const { user } = ctx; - - if (!user.organizationId) { - return { - error: "Not authorized - no organization found", - }; - } - - try { - // Create categories - await createOrganizationCategories(user as User, frameworkIds); - - // Create frameworks and controls - const organizationFrameworks = await Promise.all( - frameworkIds.map((frameworkId) => - createOrganizationFramework(user as User, frameworkId) - ) - ); - - // Create policies - await createOrganizationPolicy(user as User, frameworkIds); - - // Create organization evidence first - await createOrganizationEvidence(user as User, frameworkIds); - - // Create control requirements after evidence is created - await createOrganizationControlRequirements( - user as User, - organizationFrameworks.map((framework) => framework.id) - ); - - return { - data: true, - }; - } catch (error) { - console.error("Error selecting frameworks:", error); - return { - error: "Failed to select frameworks", - }; - } - }); + .schema(selectFrameworksSchema) + .metadata({ + name: "select-frameworks", + track: { + event: "select-frameworks", + channel: "server", + }, + }) + .action(async ({ parsedInput, ctx }): Promise> => { + const { frameworkIds } = parsedInput; + const { user } = ctx; + + if (!user.organizationId) { + return { + error: "Not authorized - no organization found", + }; + } + + try { + // Create categories + await createOrganizationCategories(user as User, frameworkIds); + + // Create frameworks and controls + const organizationFrameworks = await Promise.all( + frameworkIds.map((frameworkId) => + createOrganizationFramework(user as User, frameworkId), + ), + ); + + // Create policies + await createOrganizationPolicy(user as User, frameworkIds); + + // Create organization evidence first + await createOrganizationEvidence(user as User, frameworkIds); + + // Create control requirements after evidence is created + await createOrganizationControlRequirements( + user as User, + organizationFrameworks.map((framework) => framework.id), + ); + + return { + data: true, + }; + } catch (error) { + console.error("Error selecting frameworks:", error); + return { + error: "Failed to select frameworks", + }; + } + }); const createOrganizationFramework = async (user: User, frameworkId: string) => { - if (!user.organizationId) { - throw new Error("Not authorized - no organization found"); - } - - // Connect the framework to the organization. - const organizationFramework = await db.organizationFramework.create({ - data: { - organizationId: user.organizationId, - frameworkId, - status: "not_started", - }, - select: { - id: true, - }, - }); - - // Get the framework categories and their corresponding organization categories - const frameworkCategories = await db.frameworkCategory.findMany({ - where: { frameworkId }, - include: { - controls: true, - }, - }); - - // Get the organization categories that were just created - const organizationCategories = await db.organizationCategory.findMany({ - where: { - organizationId: user.organizationId, - frameworkId, - }, - }); - - // Create controls for each category - for (const frameworkCategory of frameworkCategories) { - const organizationCategory = organizationCategories.find( - (oc) => oc.name === frameworkCategory.name - ); - - if (!organizationCategory) continue; - - await db.organizationControl.createMany({ - data: frameworkCategory.controls.map((control) => ({ - organizationFrameworkId: organizationFramework.id, - controlId: control.id, - organizationId: user.organizationId!, - status: "not_started", - organizationCategoryId: organizationCategory.id, - })), - }); - } - - return organizationFramework; + if (!user.organizationId) { + throw new Error("Not authorized - no organization found"); + } + + // Connect the framework to the organization. + const organizationFramework = await db.organizationFramework.create({ + data: { + organizationId: user.organizationId, + frameworkId, + status: "not_started", + }, + select: { + id: true, + }, + }); + + // Get the framework categories and their corresponding organization categories + const frameworkCategories = await db.frameworkCategory.findMany({ + where: { frameworkId }, + include: { + controls: true, + }, + }); + + // Get the organization categories that were just created + const organizationCategories = await db.organizationCategory.findMany({ + where: { + organizationId: user.organizationId, + frameworkId, + }, + }); + + // Create controls for each category + for (const frameworkCategory of frameworkCategories) { + const organizationCategory = organizationCategories.find( + (oc) => oc.name === frameworkCategory.name, + ); + + if (!organizationCategory) continue; + + await db.organizationControl.createMany({ + data: frameworkCategory.controls.map((control) => ({ + organizationFrameworkId: organizationFramework.id, + controlId: control.id, + organizationId: user.organizationId!, + status: "not_started", + organizationCategoryId: organizationCategory.id, + })), + }); + } + + return organizationFramework; }; const createOrganizationPolicy = async (user: User, frameworkIds: string[]) => { - if (!user.organizationId) { - throw new Error("Not authorized - no organization found"); - } - - const policies = await db.policy.findMany(); - const policiesForFrameworks: Policy[] = []; - - for (const policy of policies) { - const usedBy = policy.usedBy; - if (!usedBy) { - continue; - } - - const usedByFrameworkIds = Object.keys(usedBy); - - if ( - usedByFrameworkIds.some((frameworkId) => - frameworkIds.includes(frameworkId) - ) - ) { - policiesForFrameworks.push(policy); - } - } - - const organizationPolicies = await db.organizationPolicy.createMany({ - data: policiesForFrameworks.map((policy) => ({ - organizationId: user.organizationId!, - policyId: policy.id, - status: "draft", - content: policy.content as InputJsonValue[], - frequency: policy.frequency, - })), - }); - - return organizationPolicies; + if (!user.organizationId) { + throw new Error("Not authorized - no organization found"); + } + + const policies = await db.policy.findMany(); + const policiesForFrameworks: Policy[] = []; + + for (const policy of policies) { + const usedBy = policy.usedBy; + if (!usedBy) { + continue; + } + + const usedByFrameworkIds = Object.keys(usedBy); + + if ( + usedByFrameworkIds.some((frameworkId) => + frameworkIds.includes(frameworkId), + ) + ) { + policiesForFrameworks.push(policy); + } + } + + const organizationPolicies = await db.organizationPolicy.createMany({ + data: policiesForFrameworks.map((policy) => ({ + organizationId: user.organizationId!, + policyId: policy.id, + status: "draft", + content: policy.content as InputJsonValue[], + frequency: policy.frequency, + })), + }); + + return organizationPolicies; }; const createOrganizationCategories = async ( - user: User, - frameworkIds: string[] + user: User, + frameworkIds: string[], ) => { - if (!user.organizationId) { - throw new Error("Not authorized - no organization found"); - } - - // For each frameworkCategory we need to get the controls. - const frameworkCategories = await db.frameworkCategory.findMany({ - where: { - frameworkId: { in: frameworkIds }, - }, - }); - - // Create the organization categories. - const organizationCategories = await db.organizationCategory.createMany({ - data: frameworkCategories.map((category) => ({ - name: category.name, - description: category.description, - organizationId: user.organizationId!, - frameworkId: category.frameworkId, - })), - }); - - return organizationCategories; + if (!user.organizationId) { + throw new Error("Not authorized - no organization found"); + } + + // For each frameworkCategory we need to get the controls. + const frameworkCategories = await db.frameworkCategory.findMany({ + where: { + frameworkId: { in: frameworkIds }, + }, + }); + + // Create the organization categories. + const organizationCategories = await db.organizationCategory.createMany({ + data: frameworkCategories.map((category) => ({ + name: category.name, + description: category.description, + organizationId: user.organizationId!, + frameworkId: category.frameworkId, + })), + }); + + return organizationCategories; }; const createOrganizationControlRequirements = async ( - user: User, - organizationFrameworkIds: string[] + user: User, + organizationFrameworkIds: string[], ) => { - if (!user.organizationId) { - throw new Error("Not authorized - no organization found"); - } - - const controls = await db.organizationControl.findMany({ - where: { - organizationId: user.organizationId!, - organizationFrameworkId: { - in: organizationFrameworkIds, - }, - }, - include: { - control: true, - }, - }); - - // Create control requirements for each control - const controlRequirements = await db.controlRequirement.findMany({ - where: { - controlId: { in: controls.map((control) => control.controlId) }, - }, - include: { - policy: true, // Include the policy to get its ID - evidence: true, // Include the evidence to get its ID - }, - }); - - // Get all organization policies for this organization - const organizationPolicies = await db.organizationPolicy.findMany({ - where: { - organizationId: user.organizationId, - }, - }); - - // Get all organization evidences for this organization - const organizationEvidences = await db.organizationEvidence.findMany({ - where: { - organizationId: user.organizationId, - }, - }); - - for (const control of controls) { - const requirements = controlRequirements.filter( - (req) => req.controlId === control.controlId - ); - - await db.organizationControlRequirement.createMany({ - data: requirements.map((requirement) => { - // Find the corresponding organization policy if this is a policy requirement - const policyId = - requirement.type === "policy" ? requirement.policy?.id : null; - const organizationPolicy = policyId - ? organizationPolicies.find((op) => op.policyId === policyId) - : null; - - const evidenceId = - requirement.type === "evidence" ? requirement.evidenceId : null; - - console.log({ - evidenceId, - }); - - const organizationEvidence = evidenceId - ? organizationEvidences.find((e) => e.evidenceId === evidenceId) - : null; - - console.log({ - organizationEvidence, - }); - - return { - organizationControlId: control.id, - controlRequirementId: requirement.id, - type: requirement.type, - description: requirement.description, - organizationPolicyId: organizationPolicy?.id || null, - organizationEvidenceId: organizationEvidence?.id || null, - }; - }), - }); - } - - return controlRequirements; + if (!user.organizationId) { + throw new Error("Not authorized - no organization found"); + } + + const controls = await db.organizationControl.findMany({ + where: { + organizationId: user.organizationId!, + organizationFrameworkId: { + in: organizationFrameworkIds, + }, + }, + include: { + control: true, + }, + }); + + // Create control requirements for each control + const controlRequirements = await db.controlRequirement.findMany({ + where: { + controlId: { in: controls.map((control) => control.controlId) }, + }, + include: { + policy: true, // Include the policy to get its ID + evidence: true, // Include the evidence to get its ID + }, + }); + + // Get all organization policies for this organization + const organizationPolicies = await db.organizationPolicy.findMany({ + where: { + organizationId: user.organizationId, + }, + }); + + // Get all organization evidences for this organization + const organizationEvidences = await db.organizationEvidence.findMany({ + where: { + organizationId: user.organizationId, + }, + }); + + for (const control of controls) { + const requirements = controlRequirements.filter( + (req) => req.controlId === control.controlId, + ); + + await db.organizationControlRequirement.createMany({ + data: requirements.map((requirement) => { + // Find the corresponding organization policy if this is a policy requirement + const policyId = + requirement.type === "policy" ? requirement.policy?.id : null; + const organizationPolicy = policyId + ? organizationPolicies.find((op) => op.policyId === policyId) + : null; + + const evidenceId = + requirement.type === "evidence" ? requirement.evidenceId : null; + + console.log({ + evidenceId, + }); + + const organizationEvidence = evidenceId + ? organizationEvidences.find((e) => e.evidenceId === evidenceId) + : null; + + console.log({ + organizationEvidence, + }); + + return { + organizationControlId: control.id, + controlRequirementId: requirement.id, + type: requirement.type, + description: requirement.description, + organizationPolicyId: organizationPolicy?.id || null, + organizationEvidenceId: organizationEvidence?.id || null, + }; + }), + }); + } + + return controlRequirements; }; const createOrganizationEvidence = async ( - user: User, - frameworkIds: string[] + user: User, + frameworkIds: string[], ) => { - if (!user.organizationId) { - throw new Error("Not authorized - no organization found"); - } - - const evidence = await db.controlRequirement.findMany({ - where: { - type: RequirementType.evidence, - }, - include: { - control: { - include: { - frameworkCategory: { - include: { - framework: true, - }, - }, - }, - }, - }, - }); - - const organizationEvidence = await db.organizationEvidence.createMany({ - data: evidence.map((evidence) => ({ - organizationId: user.organizationId!, - evidenceId: evidence.id, - name: evidence.name, - description: evidence.description, - frequency: evidence.frequency, - frameworkId: evidence.control.frameworkCategory?.framework.id || "", - assigneeId: user.id, - })), - }); - - return organizationEvidence; + if (!user.organizationId) { + throw new Error("Not authorized - no organization found"); + } + + const evidence = await db.controlRequirement.findMany({ + where: { + type: RequirementType.evidence, + }, + include: { + control: { + include: { + frameworkCategory: { + include: { + framework: true, + }, + }, + }, + }, + }, + }); + + const organizationEvidence = await db.organizationEvidence.createMany({ + data: evidence.map((evidence) => ({ + organizationId: user.organizationId!, + evidenceId: evidence.id, + name: evidence.name, + description: evidence.description, + frequency: evidence.frequency, + frameworkId: evidence.control.frameworkCategory?.framework.id || "", + assigneeId: user.id, + })), + }); + + return organizationEvidence; }; diff --git a/apps/app/src/actions/organization/check-subdomain-availability.ts b/apps/app/src/actions/organization/check-subdomain-availability.ts index f7dc4350dc..471b9b664f 100644 --- a/apps/app/src/actions/organization/check-subdomain-availability.ts +++ b/apps/app/src/actions/organization/check-subdomain-availability.ts @@ -20,21 +20,21 @@ export const checkSubdomainAvailability = authActionClient where: { subdomain: { equals: subdomain, - mode: 'insensitive' + mode: "insensitive", }, }, - select: { id: true } + select: { id: true }, }); return { success: true, - data: !subdomainExists + data: !subdomainExists, }; } catch (error) { - console.error('Prisma error:', error); + console.error("Prisma error:", error); return { success: false, - error: "Failed to check subdomain availability" + error: "Failed to check subdomain availability", }; } }); diff --git a/apps/app/src/actions/organization/create-organization-action.ts b/apps/app/src/actions/organization/create-organization-action.ts index cf7f2402fe..2a37ceaf3d 100644 --- a/apps/app/src/actions/organization/create-organization-action.ts +++ b/apps/app/src/actions/organization/create-organization-action.ts @@ -4,7 +4,10 @@ import { createOrganizationAndConnectUser } from "@/auth/org"; import type { createDefaultPoliciesTask } from "@/jobs/tasks/organization/create-default-policies"; -import { addDomainToVercel, removeDomainFromVercelProject } from "@/lib/domains"; +import { + addDomainToVercel, + removeDomainFromVercelProject, +} from "@/lib/domains"; import { db } from "@bubba/db"; import { tasks } from "@trigger.dev/sdk/v3"; import { revalidateTag } from "next/cache"; @@ -31,14 +34,16 @@ export const createOrganizationAction = authActionClient const hasVercelConfig = Boolean( process.env.NEXT_PUBLIC_VERCEL_URL && - process.env.VERCEL_ACCESS_TOKEN && - process.env.VERCEL_TEAM_ID && - process.env.VERCEL_PROJECT_ID + process.env.VERCEL_ACCESS_TOKEN && + process.env.VERCEL_TEAM_ID && + process.env.VERCEL_PROJECT_ID, ); if (hasVercelConfig && subdomain) { try { - await addDomainToVercel(`${subdomain}.${process.env.NEXT_PUBLIC_VERCEL_URL}`); + await addDomainToVercel( + `${subdomain}.${process.env.NEXT_PUBLIC_VERCEL_URL}`, + ); } catch (error) { console.error("Failed to add domain to Vercel:", error); throw new Error("Failed to set up subdomain"); @@ -49,7 +54,7 @@ export const createOrganizationAction = authActionClient await createOrganizationAndConnectUser({ userId, normalizedEmail: ctx.user.email!, - subdomain: hasVercelConfig ? (subdomain || "") : "", + subdomain: hasVercelConfig ? subdomain || "" : "", }); } @@ -76,12 +81,12 @@ export const createOrganizationAction = authActionClient update: { name, website, - subdomain: hasVercelConfig ? (subdomain || "") : "", + subdomain: hasVercelConfig ? subdomain || "" : "", }, create: { name, website, - subdomain: hasVercelConfig ? (subdomain || "") : "", + subdomain: hasVercelConfig ? subdomain || "" : "", }, }); @@ -113,9 +118,14 @@ export const createOrganizationAction = authActionClient } catch (error) { if (hasVercelConfig && subdomain) { try { - await removeDomainFromVercelProject(`${subdomain}.${process.env.NEXT_PUBLIC_VERCEL_URL}`); + await removeDomainFromVercelProject( + `${subdomain}.${process.env.NEXT_PUBLIC_VERCEL_URL}`, + ); } catch (cleanupError) { - console.error("Failed to clean up subdomain after error:", cleanupError); + console.error( + "Failed to clean up subdomain after error:", + cleanupError, + ); } } diff --git a/apps/app/src/actions/policies/update-policy-action.ts b/apps/app/src/actions/policies/update-policy-action.ts index 300162ce41..014b944ae5 100644 --- a/apps/app/src/actions/policies/update-policy-action.ts +++ b/apps/app/src/actions/policies/update-policy-action.ts @@ -17,7 +17,7 @@ interface ContentNode { // Simplified content processor that creates a new plain object function processContent( - content: ContentNode | ContentNode[] + content: ContentNode | ContentNode[], ): ContentNode | ContentNode[] { if (!content) return content; @@ -87,7 +87,7 @@ export const updatePolicyAction = authActionClient // Create a new plain object from the content const processedContent = JSON.parse( - JSON.stringify(processContent(content as ContentNode)) + JSON.stringify(processContent(content as ContentNode)), ); await db.organizationPolicy.update({ diff --git a/apps/app/src/actions/policies/update-policy-form-action.ts b/apps/app/src/actions/policies/update-policy-form-action.ts index 64b201f5f3..2d86f1b8e8 100644 --- a/apps/app/src/actions/policies/update-policy-form-action.ts +++ b/apps/app/src/actions/policies/update-policy-form-action.ts @@ -9,7 +9,10 @@ import { updatePolicyFormSchema } from "../schema"; import { PolicyStatus } from "@bubba/db"; // Helper function to calculate next review date based on frequency -function calculateNextReviewDate(frequency: string, baseDate: Date = new Date()): Date { +function calculateNextReviewDate( + frequency: string, + baseDate: Date = new Date(), +): Date { const nextDate = new Date(baseDate); switch (frequency) { @@ -65,7 +68,10 @@ export const updatePolicyFormAction = authActionClient let lastPublishedAt = undefined; // If status is changing to 'published', calculate next review date based on frequency - if (status === PolicyStatus.published && currentPolicy?.status !== PolicyStatus.published) { + if ( + status === PolicyStatus.published && + currentPolicy?.status !== PolicyStatus.published + ) { reviewDate = calculateNextReviewDate(review_frequency); lastPublishedAt = new Date(); // Set lastPublishedAt to now when publishing } diff --git a/apps/app/src/actions/schema.ts b/apps/app/src/actions/schema.ts index 07ec8e2622..2391da858c 100644 --- a/apps/app/src/actions/schema.ts +++ b/apps/app/src/actions/schema.ts @@ -18,19 +18,21 @@ export const organizationSchema = z.object({ }); export const organizationNameSchema = z.object({ - name: z.string() + name: z + .string() .min(1, "Organization name is required") - .max(255, "Organization name cannot exceed 255 characters") + .max(255, "Organization name cannot exceed 255 characters"), }); export const subdomainAvailabilitySchema = z.object({ - subdomain: z.string() + 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({ @@ -51,7 +53,7 @@ export const updaterMenuSchema = z.array( z.object({ path: z.string(), name: z.string(), - }) + }), ); export const organizationWebsiteSchema = z.object({ diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/(home)/components/FrameworksGrid.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/(home)/components/FrameworksGrid.tsx index 0340305e80..04992349f3 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/(home)/components/FrameworksGrid.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/(home)/components/FrameworksGrid.tsx @@ -71,13 +71,13 @@ export function FrameworkGrid({ frameworks, onSubmit }: FrameworkGridProps) { "relative flex flex-col p-4 rounded-lg border cursor-pointer transition-colors", selectedFrameworks.includes(framework.id) ? "border-primary bg-primary/5" - : "hover:border-muted-foreground/25" + : "hover:border-muted-foreground/25", )} onClick={() => { setSelectedFrameworks((prev) => prev.includes(framework.id) ? prev.filter((id) => id !== framework.id) - : [...prev, framework.id] + : [...prev, framework.id], ); }} > diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/(home)/hooks/useFrameworks.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/(home)/hooks/useFrameworks.ts index 1a7263e284..21eebeb609 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/(home)/hooks/useFrameworks.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/(home)/hooks/useFrameworks.ts @@ -52,7 +52,7 @@ export function useFrameworks() { setIsMutating(false); } }, - [revalidateFrameworks] + [revalidateFrameworks], ); return { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/controls/[id]/hooks/useOrganizationControl.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/controls/[id]/hooks/useOrganizationControl.ts index 4183f3f72b..a747df187d 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/controls/[id]/hooks/useOrganizationControl.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/controls/[id]/hooks/useOrganizationControl.ts @@ -25,7 +25,7 @@ export function useOrganizationControl(controlId: string) { { revalidateOnFocus: false, revalidateOnReconnect: false, - } + }, ); return { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/controls/[id]/hooks/useOrganizationControlProgress.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/controls/[id]/hooks/useOrganizationControlProgress.ts index 0b28787f3f..68093ed887 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/controls/[id]/hooks/useOrganizationControlProgress.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/controls/[id]/hooks/useOrganizationControlProgress.ts @@ -20,7 +20,7 @@ export function useOrganizationControlProgress(controlId: string) { { revalidateOnFocus: false, revalidateOnReconnect: false, - } + }, ); return { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/controls/[id]/hooks/useOrganizationControlRequirements.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/controls/[id]/hooks/useOrganizationControlRequirements.ts index 49180a184b..4b1066999a 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/controls/[id]/hooks/useOrganizationControlRequirements.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/controls/[id]/hooks/useOrganizationControlRequirements.ts @@ -25,7 +25,7 @@ export function useOrganizationControlRequirements(controlId: string) { { revalidateOnFocus: false, revalidateOnReconnect: false, - } + }, ); return { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getAllOrganizationControlRequirements.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getAllOrganizationControlRequirements.ts index 999086fdaa..63fa4e8a3f 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getAllOrganizationControlRequirements.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getAllOrganizationControlRequirements.ts @@ -8,7 +8,7 @@ export const getAllOrganizationControlRequirements = authActionClient .schema( z.object({ search: z.string().optional().nullable(), - }) + }), ) .metadata({ name: "getAllOrganizationControlRequirements", diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getEvidence.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getEvidence.ts index fd1ef21d70..4ced42a0cf 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getEvidence.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getEvidence.ts @@ -8,7 +8,7 @@ export const getEvidence = authActionClient .schema( z.object({ evidenceId: z.string(), - }) + }), ) .metadata({ name: "getEvidence", diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getOrganizationEvidence.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getOrganizationEvidence.ts index 6cf05925b2..1bb583f363 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getOrganizationEvidence.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getOrganizationEvidence.ts @@ -8,7 +8,7 @@ export const getOrganizationEvidenceById = authActionClient .schema( z.object({ id: z.string(), - }) + }), ) .metadata({ name: "getOrganizationEvidenceById", diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getOrganizationEvidenceTasks.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getOrganizationEvidenceTasks.ts index 171c421879..b136c9ec2b 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getOrganizationEvidenceTasks.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getOrganizationEvidenceTasks.ts @@ -31,7 +31,7 @@ export const getOrganizationEvidenceTasks = authActionClient relevance: z.enum(["relevant", "not-relevant"]).optional().nullable(), page: z.number().int().positive().optional().default(1), pageSize: z.number().int().positive().optional().default(10), - }) + }), ) .metadata({ name: "getOrganizationEvidenceTasks", diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/EvidenceFilters/FilterDropdown.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/EvidenceFilters/FilterDropdown.tsx index 14779bdcac..36ae9b690c 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/EvidenceFilters/FilterDropdown.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/EvidenceFilters/FilterDropdown.tsx @@ -107,7 +107,7 @@ export function FilterDropdown() { checked={relevance === "not-relevant"} onCheckedChange={() => { setRelevance( - relevance === "not-relevant" ? null : "not-relevant" + relevance === "not-relevant" ? null : "not-relevant", ); setPage("1"); // Reset to first page when filtering }} @@ -165,7 +165,7 @@ export function FilterDropdown() { checked={assigneeId === assignee.id} onCheckedChange={() => { setAssigneeId( - assigneeId === assignee.id ? null : assignee.id + assigneeId === assignee.id ? null : assignee.id, ); setPage("1"); // Reset to first page when filtering }} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/data-table/data-table-header.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/data-table/data-table-header.tsx index f454901ad5..e02f6cd071 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/data-table/data-table-header.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/data-table/data-table-header.tsx @@ -26,14 +26,14 @@ export function DataTableHeader({ table }: DataTableHeaderProps) {
{flexRender( header.column.columnDef.header, - header.getContext() + header.getContext(), )} {{ asc: , diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/assignEvidence.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/assignEvidence.ts index eeb04334cc..3985eeb201 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/assignEvidence.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/assignEvidence.ts @@ -10,7 +10,7 @@ export const assignEvidence = authActionClient z.object({ id: z.string(), assigneeId: z.string().nullable(), - }) + }), ) .metadata({ name: "assignEvidence", diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/getEvidenceFileUrl.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/getEvidenceFileUrl.ts index 03c313e899..c162a75b54 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/getEvidenceFileUrl.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/getEvidenceFileUrl.ts @@ -100,7 +100,7 @@ export const getEvidenceFileUrl = authActionClient } catch (error) { console.error("S3 Error:", error); throw new Error( - `Failed to access file: ${error instanceof Error ? error.message : "unknown error"}` + `Failed to access file: ${error instanceof Error ? error.message : "unknown error"}`, ); } } catch (error) { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/toggleRelevance.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/toggleRelevance.ts index 3e7d8558e0..c14cbe71f0 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/toggleRelevance.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/toggleRelevance.ts @@ -10,7 +10,7 @@ export const toggleRelevance = authActionClient z.object({ id: z.string(), isNotRelevant: z.boolean(), - }) + }), ) .metadata({ name: "toggleRelevance", diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/updateEvidenceUrls.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/updateEvidenceUrls.ts index 4c2221034e..04f03d60f0 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/updateEvidenceUrls.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/updateEvidenceUrls.ts @@ -9,7 +9,7 @@ export const updateEvidenceUrls = authActionClient z.object({ evidenceId: z.string(), urls: z.array(z.string().url()), - }) + }), ) .metadata({ name: "updateEvidenceUrls", diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/uploadEvidenceFile.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/uploadEvidenceFile.ts index 6b4c1bc773..a6831f0c40 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/uploadEvidenceFile.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/uploadEvidenceFile.ts @@ -24,7 +24,7 @@ export const getUploadUrl = authActionClient evidenceId: z.string(), fileName: z.string(), fileType: z.string(), - }) + }), ) .metadata({ name: "getUploadUrl", diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/AssigneeSection.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/AssigneeSection.tsx index ed428d0565..567eb0f821 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/AssigneeSection.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/AssigneeSection.tsx @@ -27,7 +27,7 @@ export function AssigneeSection({ onSuccess, }: AssigneeSectionProps) { const [assigneeId, setAssigneeId] = useState( - currentAssigneeId || null + currentAssigneeId || null, ); const { data: admins, isLoading, error } = useOrganizationAdmins(); const [selectedAdmin, setSelectedAdmin] = useState(null); diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/DepartmentSection.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/DepartmentSection.tsx index 50bca19200..9dc09a29e5 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/DepartmentSection.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/DepartmentSection.tsx @@ -25,7 +25,7 @@ export function DepartmentSection({ onSuccess, }: DepartmentSectionProps) { const [department, setDepartment] = useState( - currentDepartment || null + currentDepartment || null, ); const { execute: updateDepartment, isExecuting } = useAction( @@ -39,7 +39,7 @@ export function DepartmentSection({ console.error("Error updating department:", error); toast.error("Failed to update department"); }, - } + }, ); useEffect(() => { @@ -53,7 +53,7 @@ export function DepartmentSection({ }; const departmentOptions = Object.values(Departments).filter( - (dept) => dept !== "none" + (dept) => dept !== "none", ); return ( diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FileSection.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FileSection.tsx index 366a6fb540..5f2b3b14b7 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FileSection.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FileSection.tsx @@ -70,7 +70,7 @@ export function FileSection({ })); } }, - [getPreviewUrl, previewStates] + [getPreviewUrl, previewStates], ); // Load all previews when component mounts or when fileUrls change diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FileUpload.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FileUpload.tsx index edb63aac72..da512b6e65 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FileUpload.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FileUpload.tsx @@ -53,7 +53,7 @@ export function FileUpload({ onFileSelect(acceptedFiles[0]); } }, - [onFileSelect] + [onFileSelect], ); const { @@ -82,7 +82,7 @@ export function FileUpload({ isDragActive && "border-primary border-2 bg-primary/5", isDragAccept && "border-green-500 border-2 bg-green-50", isDragReject && "border-red-500 border-2 bg-red-50", - isUploading && "pointer-events-none opacity-60" + isUploading && "pointer-events-none opacity-60", )} > @@ -136,7 +136,7 @@ export function FileUpload({ ? "border-primary/50 bg-primary/5" : "border-muted-foreground/25", isDragReject && "border-destructive/50 bg-destructive/5", - isUploading && "pointer-events-none opacity-60" + isUploading && "pointer-events-none opacity-60", )} > diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FrequencySection.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FrequencySection.tsx index 91cd1965a0..aee8b6087d 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FrequencySection.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FrequencySection.tsx @@ -25,7 +25,7 @@ export function FrequencySection({ onSuccess, }: FrequencySectionProps) { const [frequency, setFrequency] = useState( - currentFrequency || null + currentFrequency || null, ); const { execute: updateFrequency, isExecuting } = useAction( @@ -38,7 +38,7 @@ export function FrequencySection({ onError: () => { toast.error("Failed to update review frequency"); }, - } + }, ); useEffect(() => { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFileDelete.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFileDelete.ts index d85c6bef67..0765c11eab 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFileDelete.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFileDelete.ts @@ -43,7 +43,7 @@ export function useFileDelete({ evidenceId, onSuccess }: UseFileDeleteProps) { }); } }, - [evidenceId, onSuccess, toast] + [evidenceId, onSuccess, toast], ); return { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFilePreview.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFilePreview.ts index f2f7c3bf2c..a82523711d 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFilePreview.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFilePreview.ts @@ -60,7 +60,7 @@ export function useFilePreview({ setIsLoading(false); } }, - [evidenceId, toast] + [evidenceId, toast], ); return { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFileUpload.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFileUpload.ts index c6251fc2db..c57995e42e 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFileUpload.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFileUpload.ts @@ -71,7 +71,7 @@ export function useFileUpload({ onUploadProgress: (progressEvent: AxiosProgressEvent): void => { if (progressEvent.total) { const percentCompleted = Math.round( - (progressEvent.loaded * 100) / progressEvent.total + (progressEvent.loaded * 100) / progressEvent.total, ); console.debug(`Upload progress: ${percentCompleted}%`); } @@ -104,7 +104,7 @@ export function useFileUpload({ setIsUploading(false); } }, - [evidenceId, onSuccess, toast] + [evidenceId, onSuccess, toast], ); return { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useOrganizationEvidence.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useOrganizationEvidence.ts index 46f53b98e5..17a1c175d5 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useOrganizationEvidence.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useOrganizationEvidence.ts @@ -14,7 +14,7 @@ async function fetchOrganizationEvidence({ id }: UseOrganizationEvidenceProps) { throw new Error( typeof result?.error === "string" ? result.error - : "Failed to fetch organization evidence" + : "Failed to fetch organization evidence", ); } @@ -28,6 +28,6 @@ export function useOrganizationEvidence({ id }: UseOrganizationEvidenceProps) { { revalidateOnFocus: false, revalidateOnReconnect: false, - } + }, ); } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useUrlManagement.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useUrlManagement.ts index cfb0974cd5..e53a635654 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useUrlManagement.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useUrlManagement.ts @@ -62,7 +62,7 @@ export function useUrlManagement({ const handleUpdateDraft = useCallback((id: string, url: string) => { setDraftUrls((prev) => - prev.map((draft) => (draft.id === id ? { ...draft, url } : draft)) + prev.map((draft) => (draft.id === id ? { ...draft, url } : draft)), ); }, []); @@ -151,7 +151,7 @@ export function useUrlManagement({ }); } }, - [currentUrls, evidenceId, onSuccess, toast] + [currentUrls, evidenceId, onSuccess, toast], ); return { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTableContext.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTableContext.tsx index 1970bf4813..fad65db559 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTableContext.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTableContext.tsx @@ -206,7 +206,7 @@ export function useEvidenceTable() { if (context === undefined) { throw new Error( - "useEvidenceTable must be used within an EvidenceTableProvider" + "useEvidenceTable must be used within an EvidenceTableProvider", ); } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTasks.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTasks.ts index e3e78d29d9..e6d30ef9f0 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTasks.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTasks.ts @@ -42,7 +42,7 @@ async function fetchEvidenceTasks(props: UseOrganizationEvidenceTasksProps) { if (result.validationErrors) { throw new Error( - result.validationErrors._errors?.join(", ") ?? "Unknown error" + result.validationErrors._errors?.join(", ") ?? "Unknown error", ); } @@ -58,7 +58,7 @@ async function fetchEvidenceTasks(props: UseOrganizationEvidenceTasksProps) { } export function useOrganizationEvidenceTasks( - props: UseOrganizationEvidenceTasksProps = {} + props: UseOrganizationEvidenceTasksProps = {}, ): UseOrganizationEvidenceTasksResult { const { search, @@ -93,7 +93,7 @@ export function useOrganizationEvidenceTasks( relevance, page, pageSize, - }) + }), ); console.log("useOrganizationEvidenceTasks data:", data); diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTasksStats.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTasksStats.ts index e43b83cae0..847c7f4e1e 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTasksStats.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTasksStats.ts @@ -19,7 +19,7 @@ async function fetchEvidenceTasksStats() { if (result.validationErrors) { throw new Error( - result.validationErrors._errors?.join(", ") ?? "Unknown error" + result.validationErrors._errors?.join(", ") ?? "Unknown error", ); } @@ -37,7 +37,7 @@ export function useEvidenceTasksStats() { { revalidateOnFocus: false, revalidateOnReconnect: false, - } + }, ); return { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/actions/getEvidenceDashboard.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/actions/getEvidenceDashboard.ts index 8e7c99e0bd..8d376e492d 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/actions/getEvidenceDashboard.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/actions/getEvidenceDashboard.ts @@ -187,7 +187,7 @@ export const getEvidenceDashboard = authActionClient acc[dept] = []; return acc; }, - {} as Record + {} as Record, ); // Group evidence by department diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/AssigneeBarChart.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/AssigneeBarChart.tsx index 98b2a7eca7..e40c598348 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/AssigneeBarChart.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/AssigneeBarChart.tsx @@ -74,7 +74,7 @@ export function AssigneeBarChart({ if (firstAssignee && firstAssignee.length > 0) { console.log( "First assignee's first item status:", - firstAssignee[0].status + firstAssignee[0].status, ); } } @@ -110,7 +110,7 @@ export function AssigneeBarChart({ items, statusCounts, }; - } + }, ); // Add unassigned items if any diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/DepartmentBarChart.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/DepartmentBarChart.tsx index 5e6e9550f6..2ef003e84a 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/DepartmentBarChart.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/DepartmentBarChart.tsx @@ -81,7 +81,7 @@ export function DepartmentBarChart({ byDepartment }: DepartmentBarChartProps) { if (firstDepartment && firstDepartment.length > 0) { console.log( "First department's first item status:", - firstDepartment[0].status + firstDepartment[0].status, ); } } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/FrameworkBarChart.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/FrameworkBarChart.tsx index 600b321531..3ab4892ac9 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/FrameworkBarChart.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/FrameworkBarChart.tsx @@ -69,7 +69,7 @@ export function FrameworkBarChart({ byFramework }: FrameworkBarChartProps) { if (firstFramework && firstFramework.length > 0) { console.log( "First framework's first item status:", - firstFramework[0].status + firstFramework[0].status, ); } } @@ -105,7 +105,7 @@ export function FrameworkBarChart({ byFramework }: FrameworkBarChartProps) { items, statusCounts, }; - } + }, ); // Sort by count in descending order diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/hooks/useEvidenceDashboard.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/hooks/useEvidenceDashboard.ts index 739df38290..7c114ecf38 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/hooks/useEvidenceDashboard.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/hooks/useEvidenceDashboard.ts @@ -40,7 +40,7 @@ export function useEvidenceDashboard() { { revalidateOnFocus: false, revalidateOnReconnect: false, - } + }, ); // Debug: Log the data in the hook diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/Components/FrameworkControls.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/Components/FrameworkControls.tsx index fccd25bde7..a28beb4338 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/Components/FrameworkControls.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/Components/FrameworkControls.tsx @@ -34,7 +34,7 @@ export function FrameworkControls({ frameworkId }: FrameworkControlsProps) { frameworkId, category: category.name, requirements: control.OrganizationControlRequirement, - })) + })), ); }, [organizationCategories, frameworkId]) as OrganizationControlType[]; diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/Components/FrameworkOverview.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/Components/FrameworkOverview.tsx index e4d7561068..2e0c4959bc 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/Components/FrameworkOverview.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/Components/FrameworkOverview.tsx @@ -27,18 +27,18 @@ export function FrameworkOverview({ frameworkId }: FrameworkOverviewProps) { // Calculate compliance metrics const totalControls = data?.reduce( (acc, cat) => acc + cat.organizationControl.length, - 0 + 0, ); const compliantControls = data?.reduce( (acc, cat) => acc + cat.organizationControl.filter((oc) => oc.status === "compliant").length, - 0 + 0, ); const compliancePercentage = Math.round( - (compliantControls ?? 0 / (totalControls ?? 0)) * 100 + (compliantControls ?? 0 / (totalControls ?? 0)) * 100, ); return ( diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/hooks/useOrganizationCategories.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/hooks/useOrganizationCategories.ts index 88e554d282..d5bd63cd41 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/hooks/useOrganizationCategories.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/hooks/useOrganizationCategories.ts @@ -25,7 +25,7 @@ export function useOrganizationCategories(frameworkId: string) { { revalidateOnFocus: false, revalidateOnReconnect: false, - } + }, ); return { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/hooks/useOrganizationFramework.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/hooks/useOrganizationFramework.ts index 6cdbd1c075..151fe83034 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/hooks/useOrganizationFramework.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/frameworks/[frameworkId]/hooks/useOrganizationFramework.ts @@ -2,12 +2,12 @@ import useSWR from "swr"; import { - FrameworkWithControls, + type FrameworkWithControls, getOrganizationFramework, } from "../Actions/getOrganizationFramework"; async function fetchOrganizationFramework( - frameworkId: string + frameworkId: string, ): Promise { const result = await getOrganizationFramework({ frameworkId }); @@ -30,7 +30,7 @@ export function useOrganizationFramework(frameworkId: string) { { revalidateOnFocus: false, revalidateOnReconnect: false, - } + }, ); return { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/people/hooks/useEmployee.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/people/hooks/useEmployee.ts index 24c29a961e..d82297ddae 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/people/hooks/useEmployee.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/people/hooks/useEmployee.ts @@ -5,7 +5,7 @@ import { getEmployeeDetails } from "../[employeeId]/actions/get-employee-details import type { EmployeeDetails, AppError } from "../[employeeId]/types"; async function fetchEmployeeDetails( - employeeId: string + employeeId: string, ): Promise { const result = await getEmployeeDetails({ employeeId }); @@ -35,7 +35,7 @@ export function useEmployeeDetails(employeeId: string) { { revalidateOnFocus: false, revalidateOnReconnect: false, - } + }, ); return { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/people/hooks/useEmployees.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/people/hooks/useEmployees.ts index aec5d79132..661116e862 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/people/hooks/useEmployees.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/people/hooks/useEmployees.ts @@ -12,7 +12,7 @@ import type { Departments } from "@bubba/db"; /** Fetcher function, same as before */ async function fetchEmployees( - input: EmployeesInput + input: EmployeesInput, ): Promise { const result = await getEmployees(input); @@ -54,7 +54,7 @@ export function useEmployees() { { revalidateOnFocus: false, revalidateOnReconnect: false, - } + }, ); /** Track local mutation (creating an employee) loading state */ @@ -101,7 +101,7 @@ export function useEmployees() { setIsMutating(false); } }, - [revalidateEmployees] + [revalidateEmployees], ); return { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/actions/get-policies.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/actions/get-policies.ts index 2076d9aba5..0bacb833c7 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/actions/get-policies.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/actions/get-policies.ts @@ -12,7 +12,7 @@ function generatePoliciesCacheKey( status?: string, page = 1, per_page = 10, - sort?: string + sort?: string, ) { return `policies-${organizationId}-${search || ""}-${status || ""}-${page}-${per_page}-${sort || ""}`; } @@ -37,18 +37,18 @@ const getCachedPolicies = unstable_cache( const skip = (page - 1) * per_page; const [column, order] = sort?.split(":") ?? []; - let orderByClause: any = { updatedAt: 'desc' }; + let orderByClause: any = { updatedAt: "desc" }; if (column) { if (column === "name") { orderByClause = { policy: { - name: order === "asc" ? "asc" : "desc" - } + name: order === "asc" ? "asc" : "desc", + }, }; } else { orderByClause = { - [column]: order === "asc" ? "asc" : "desc" + [column]: order === "asc" ? "asc" : "desc", }; } } @@ -60,13 +60,15 @@ const getCachedPolicies = unstable_cache( AND: [ search ? { - policy: { - OR: [ - { name: { contains: search, mode: "insensitive" } }, - { description: { contains: search, mode: "insensitive" } }, - ], - }, - } + policy: { + OR: [ + { name: { contains: search, mode: "insensitive" } }, + { + description: { contains: search, mode: "insensitive" }, + }, + ], + }, + } : {}, status ? { status: status as any } : {}, ], @@ -95,13 +97,15 @@ const getCachedPolicies = unstable_cache( AND: [ search ? { - policy: { - OR: [ - { name: { contains: search, mode: "insensitive" } }, - { description: { contains: search, mode: "insensitive" } }, - ], - }, - } + policy: { + OR: [ + { name: { contains: search, mode: "insensitive" } }, + { + description: { contains: search, mode: "insensitive" }, + }, + ], + }, + } : {}, status ? { status: status as any } : {}, ], @@ -113,8 +117,8 @@ const getCachedPolicies = unstable_cache( }, ["policies"], { - tags: ["policies"] - } + tags: ["policies"], + }, ); export const getPolicies = authActionClient @@ -144,7 +148,7 @@ export const getPolicies = authActionClient status, page, per_page, - sort + sort, }); return { @@ -158,4 +162,4 @@ export const getPolicies = authActionClient error: appErrors.UNEXPECTED_ERROR.message, }; } - }); \ No newline at end of file + }); diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/hooks/usePolicies.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/hooks/usePolicies.ts index cea135f4f0..9943a0d04a 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/hooks/usePolicies.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/hooks/usePolicies.ts @@ -7,9 +7,7 @@ import { getPolicies } from "../actions/get-policies"; import type { AppError, PoliciesInput, PoliciesResponse } from "../types"; -async function fetchPolicies( - input: PoliciesInput -): Promise { +async function fetchPolicies(input: PoliciesInput): Promise { const result = await getPolicies(input); if (!result) { @@ -51,7 +49,7 @@ export function usePolicies() { { revalidateOnFocus: false, revalidateOnReconnect: false, - } + }, ); return { @@ -61,4 +59,4 @@ export function usePolicies() { error, revalidatePolicies, }; -} \ No newline at end of file +} diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/hooks/usePolicy.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/hooks/usePolicy.ts index 6ad0f4e1dd..3e66bcedcf 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/hooks/usePolicy.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/hooks/usePolicy.ts @@ -14,12 +14,10 @@ interface ContentNode { [key: string]: any; } -async function fetchPolicyDetails( - policyId: string -): Promise { +async function fetchPolicyDetails(policyId: string): Promise { const result = await getPolicyDetails({ policyId, - _cache: Date.now() + _cache: Date.now(), }); if (!result) { @@ -49,8 +47,8 @@ export function usePolicyDetails(policyId: string) { revalidateOnFocus: false, revalidateOnReconnect: false, revalidateIfStale: true, - dedupingInterval: 0 - } + dedupingInterval: 0, + }, ); const updatePolicyContent = async (updateData: Partial) => { @@ -69,7 +67,7 @@ export function usePolicyDetails(policyId: string) { await mutate(fetchPolicyDetails(policyId), { revalidate: true, populateCache: true, - rollbackOnError: false + rollbackOnError: false, }); return true; @@ -84,7 +82,7 @@ export function usePolicyDetails(policyId: string) { isLoading, error, updatePolicy: updatePolicyContent, - refreshPolicy: () => mutate(fetchPolicyDetails(policyId), true) + refreshPolicy: () => mutate(fetchPolicyDetails(policyId), true), }; } diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/types/index.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/types/index.ts index d68a45d995..b1e82334d9 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/types/index.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/types/index.ts @@ -44,4 +44,4 @@ export const appErrors = { code: "UNEXPECTED_ERROR" as const, message: "An unexpected error occurred", }, -} as const; \ No newline at end of file +} as const; diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/types/search-params.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/types/search-params.ts index aea52eb401..b877ff46f7 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/types/search-params.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/(overview)/types/search-params.ts @@ -8,4 +8,4 @@ export const searchParamsCache = createSearchParamsCache({ q: parseAsString, page: parseAsInteger.withDefault(0), status: parseAsString, -}); \ No newline at end of file +}); diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/[policyId]/editor/actions/get-policy-details.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/[policyId]/editor/actions/get-policy-details.ts index 990d4243e2..dca6882f8a 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/[policyId]/editor/actions/get-policy-details.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/[policyId]/editor/actions/get-policy-details.ts @@ -3,10 +3,7 @@ import { authActionClient } from "@/actions/safe-action"; import { auth } from "@/auth"; import { db } from "@bubba/db"; -import { - appErrors, - policyDetailsInputSchema, -} from "../types"; +import { appErrors, policyDetailsInputSchema } from "../types"; export const getPolicyDetails = authActionClient .schema(policyDetailsInputSchema) @@ -71,4 +68,4 @@ export const getPolicyDetails = authActionClient error: appErrors.UNEXPECTED_ERROR.message, }; } - }); \ No newline at end of file + }); diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/[policyId]/editor/actions/update-policy.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/[policyId]/editor/actions/update-policy.ts index 2597b93221..1c5e416604 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/[policyId]/editor/actions/update-policy.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/[policyId]/editor/actions/update-policy.ts @@ -49,8 +49,13 @@ export const updatePolicy = authActionClient if (content !== undefined) { console.log("CONTENT TYPE:", typeof content); - if (typeof content === 'object' && content !== null) { - if ('type' in content && content.type === 'doc' && 'content' in content && Array.isArray(content.content)) { + if (typeof content === "object" && content !== null) { + if ( + "type" in content && + content.type === "doc" && + "content" in content && + Array.isArray(content.content) + ) { updateData.content = content.content; console.log("Extracted content array from TipTap doc"); } else if (Array.isArray(content)) { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/[policyId]/editor/types/index.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/[policyId]/editor/types/index.ts index 729e8c05de..21ff06d0c5 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/[policyId]/editor/types/index.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/[policyId]/editor/types/index.ts @@ -16,7 +16,7 @@ export const policyDetailsSchema = z.object({ export const policyDetailsInputSchema = z.object({ policyId: z.string(), - _cache: z.number().optional() + _cache: z.number().optional(), }); export const updatePolicySchema = z.object({ @@ -47,4 +47,4 @@ export const appErrors = { code: "UNEXPECTED_ERROR" as const, message: "An unexpected error occurred", }, -} as const; \ No newline at end of file +} as const; diff --git a/apps/app/src/components/editor/extensions.ts b/apps/app/src/components/editor/extensions.ts index 0953516760..6c07977cf8 100644 --- a/apps/app/src/components/editor/extensions.ts +++ b/apps/app/src/components/editor/extensions.ts @@ -42,7 +42,7 @@ export const defaultExtensions = [ openOnClick: false, }), Placeholder.configure({ - placeholder: 'Start writing…', + placeholder: "Start writing…", }), Blockquote, HardBreak, diff --git a/apps/app/src/components/main-menu.tsx b/apps/app/src/components/main-menu.tsx index 222455da0f..f32da81a5d 100644 --- a/apps/app/src/components/main-menu.tsx +++ b/apps/app/src/components/main-menu.tsx @@ -94,7 +94,7 @@ const Item = ({ isActive && "bg-[#F2F1EF] dark:bg-secondary border-[#DCDAD2] dark:border-[#2C2C2C]", isCustomizing && - "bg-background border-[#DCDAD2] dark:border-[#2C2C2C]" + "bg-background border-[#DCDAD2] dark:border-[#2C2C2C]", )} > @@ -214,7 +214,7 @@ export function MainMenu({ initialItems, onSelect }: Props) { const updateMenu = useAction(updateMenuAction); const hiddenItems = defaultItems.filter( - (item) => !items.some((i) => i.path === item.path) + (item) => !items.some((i) => i.path === item.path), ); const onReorder = ( @@ -222,7 +222,7 @@ export function MainMenu({ initialItems, onSelect }: Props) { path: string; name: string; disabled: boolean; - }[] + }[], ) => { setItems(items); }; @@ -248,7 +248,7 @@ export function MainMenu({ initialItems, onSelect }: Props) { }, { cancelOnMovement: 0, - } + }, ); const ref = useClickAway(() => { @@ -312,7 +312,7 @@ export function MainMenu({ initialItems, onSelect }: Props) { className={cn( "border border-transparent w-[45px] h-[45px] flex items-center md:justify-center", "hover:bg-secondary hover:border-[#DCDAD2] hover:dark:border-[#2C2C2C]", - "bg-background border-[#DCDAD2] dark:border-[#2C2C2C]" + "bg-background border-[#DCDAD2] dark:border-[#2C2C2C]", )} >
diff --git a/apps/app/src/components/tables/frameworks/columns.tsx b/apps/app/src/components/tables/frameworks/columns.tsx index 924dc40ceb..82055373aa 100644 --- a/apps/app/src/components/tables/frameworks/columns.tsx +++ b/apps/app/src/components/tables/frameworks/columns.tsx @@ -39,7 +39,7 @@ export type OrganizationControlType = { }; function getControlStatus( - requirements: OrganizationControlType["requirements"] + requirements: OrganizationControlType["requirements"], ): StatusType { if (!requirements || requirements.length === 0) return "not_started"; @@ -131,7 +131,7 @@ export function columns(): ColumnDef[] {

Progress:{" "} {Math.round( - (completedRequirements / totalRequirements) * 100 + (completedRequirements / totalRequirements) * 100, ) || 0} %

diff --git a/apps/app/src/components/tables/frameworks/data-table-header.tsx b/apps/app/src/components/tables/frameworks/data-table-header.tsx index c54fbf9292..70f79a3931 100644 --- a/apps/app/src/components/tables/frameworks/data-table-header.tsx +++ b/apps/app/src/components/tables/frameworks/data-table-header.tsx @@ -45,7 +45,7 @@ export function DataTableHeader({ table, loading }: Props) { router.replace(`${pathname}?${params.toString()}`); }, - [searchParams, router, pathname] + [searchParams, router, pathname], ); const isVisible = (id: string) => diff --git a/apps/app/src/components/tables/frameworks/data-table.tsx b/apps/app/src/components/tables/frameworks/data-table.tsx index 64f4983dce..39d9d1a114 100644 --- a/apps/app/src/components/tables/frameworks/data-table.tsx +++ b/apps/app/src/components/tables/frameworks/data-table.tsx @@ -41,7 +41,7 @@ export function DataTable({ data }: DataTableProps) { {flexRender( cell.column.columnDef.cell, - cell.getContext() + cell.getContext(), )} ))} diff --git a/apps/app/src/components/tables/people/data-table-header.tsx b/apps/app/src/components/tables/people/data-table-header.tsx index adb83d029f..f97e8cb5dd 100644 --- a/apps/app/src/components/tables/people/data-table-header.tsx +++ b/apps/app/src/components/tables/people/data-table-header.tsx @@ -46,7 +46,7 @@ export function DataTableHeader({ table, loading }: Props) { router.replace(`${pathname}?${params.toString()}`); }, - [searchParams, router, pathname] + [searchParams, router, pathname], ); const isVisible = (id: string) => diff --git a/apps/app/src/hooks/use-mobile.ts b/apps/app/src/hooks/use-mobile.ts index b2c278b4ba..004b311cab 100644 --- a/apps/app/src/hooks/use-mobile.ts +++ b/apps/app/src/hooks/use-mobile.ts @@ -4,7 +4,7 @@ const MOBILE_BREAKPOINT = 1024; export function useIsMobile() { const [isMobile, setIsMobile] = React.useState( - undefined + undefined, ); React.useEffect(() => { @@ -18,4 +18,4 @@ export function useIsMobile() { }, []); return !!isMobile; -} \ No newline at end of file +} diff --git a/apps/app/src/hooks/use-notifications.ts b/apps/app/src/hooks/use-notifications.ts index 50d5aaa146..1ca9e69087 100644 --- a/apps/app/src/hooks/use-notifications.ts +++ b/apps/app/src/hooks/use-notifications.ts @@ -15,7 +15,7 @@ interface Notification { from?: string; to?: string; [key: string]: any; // Allow for other payload fields - } + }; } export function useNotifications() { @@ -39,8 +39,8 @@ export function useNotifications() { ); headlessService.markAllMessagesAsRead({ - listener: () => { }, - onError: () => { }, + listener: () => {}, + onError: () => {}, }); } }; @@ -64,8 +64,8 @@ export function useNotifications() { headlessService.markNotificationsAsRead({ messageId: [messageId], - listener: (result) => { }, - onError: (error) => { }, + listener: (result) => {}, + onError: (error) => {}, }); } }; @@ -75,7 +75,7 @@ export function useNotifications() { if (headlessService) { headlessService.fetchNotifications({ - listener: () => { }, + listener: () => {}, onSuccess: (response) => { setLoading(false); setNotifications( @@ -84,8 +84,8 @@ export function useNotifications() { read: msg.read, seen: msg.seen, createdAt: msg.createdAt, - payload: msg.payload || {} // Handle case where payload might be empty - })) + payload: msg.payload || {}, // Handle case where payload might be empty + })), ); }, }); @@ -103,8 +103,8 @@ export function useNotifications() { })), ); headlessService.markAllMessagesAsSeen({ - listener: () => { }, - onError: () => { }, + listener: () => {}, + onError: () => {}, }); } }; @@ -122,7 +122,7 @@ export function useNotifications() { headlessService.listenNotificationReceive({ listener: () => { fetchNotifications(); - } + }, }); } }, [headlessServiceRef.current]); @@ -135,14 +135,14 @@ export function useNotifications() { }); headlessService.initializeSession({ - listener: () => { }, + listener: () => {}, onSuccess: () => { - console.log('Novu session initialized successfully'); + console.log("Novu session initialized successfully"); headlessServiceRef.current = headlessService; fetchNotifications(); }, onError: (error) => { - console.error('Failed to initialize Novu session:', error); + console.error("Failed to initialize Novu session:", error); }, }); } @@ -153,7 +153,9 @@ export function useNotifications() { markAllMessagesAsRead, markMessageAsRead, markAllMessagesAsSeen, - hasUnseenNotifications: notifications.some((notification) => !notification.seen), + hasUnseenNotifications: notifications.some( + (notification) => !notification.seen, + ), notifications, subscriberId, }; diff --git a/apps/app/src/jobs/seed/policies/change.json b/apps/app/src/jobs/seed/policies/change.json index 5ebe8bf61e..8b14042897 100644 --- a/apps/app/src/jobs/seed/policies/change.json +++ b/apps/app/src/jobs/seed/policies/change.json @@ -1,10 +1,7 @@ { "type": "doc", "metadata": { - "controls": [ - "CC8.1", - "CC3.4" - ] + "controls": ["CC8.1", "CC3.4"] }, "content": [ { @@ -497,4 +494,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/apps/app/src/jobs/seed/policies/classification.json b/apps/app/src/jobs/seed/policies/classification.json index c3dd23d79f..547f032b0b 100644 --- a/apps/app/src/jobs/seed/policies/classification.json +++ b/apps/app/src/jobs/seed/policies/classification.json @@ -1,10 +1,7 @@ { "type": "doc", "metadata": { - "controls": [ - "CC9.9", - "CC8.1" - ] + "controls": ["CC9.9", "CC8.1"] }, "content": [ { @@ -764,4 +761,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/apps/app/src/jobs/tasks/notifications/risk-task-schedule.ts b/apps/app/src/jobs/tasks/notifications/risk-task-schedule.ts index 9a1fb167d1..ad93b12969 100644 --- a/apps/app/src/jobs/tasks/notifications/risk-task-schedule.ts +++ b/apps/app/src/jobs/tasks/notifications/risk-task-schedule.ts @@ -37,10 +37,14 @@ export const sendRiskTaskSchedule = schedules.task({ }); const triggerPayloads = tasks - .filter((task): task is (typeof task & { - owner: { id: string; email: string; organizationId: string } - }) => Boolean(task.owner?.email && task.owner.organizationId)) - .map(task => ({ + .filter( + ( + task, + ): task is typeof task & { + owner: { id: string; email: string; organizationId: string }; + } => Boolean(task.owner?.email && task.owner.organizationId), + ) + .map((task) => ({ payload: { task: { id: task.id, @@ -48,16 +52,13 @@ export const sendRiskTaskSchedule = schedules.task({ dueDate: task.dueDate || new Date(), owner: task.owner, riskId: task.riskId, - } - } + }, + }, })); if (triggerPayloads.length > 0) { try { - - await sendRiskTaskNotification.batchTrigger( - triggerPayloads, - ); + await sendRiskTaskNotification.batchTrigger(triggerPayloads); logger.info(`Triggered ${triggerPayloads.length} task notifications`); } catch (error) { @@ -77,5 +78,5 @@ export const sendRiskTaskSchedule = schedules.task({ totalTasks: tasks.length, triggeredTasks: triggerPayloads.length, }; - } -}); \ No newline at end of file + }, +}); diff --git a/apps/app/src/jobs/tasks/organization/new-organization.ts b/apps/app/src/jobs/tasks/organization/new-organization.ts index e52c79a7af..dbcb2a4561 100644 --- a/apps/app/src/jobs/tasks/organization/new-organization.ts +++ b/apps/app/src/jobs/tasks/organization/new-organization.ts @@ -5,7 +5,7 @@ export const newOrganizationTask = schemaTask({ id: "new-organization", schema: z.object({ organizationId: z.string(), - userId: z.string() + userId: z.string(), }), run: async ({ organizationId, userId }) => { logger.info("New organization task started", { diff --git a/apps/app/src/lib/domains.ts b/apps/app/src/lib/domains.ts index 9a25b8f37f..b355045f8f 100644 --- a/apps/app/src/lib/domains.ts +++ b/apps/app/src/lib/domains.ts @@ -6,8 +6,10 @@ import type { export const addDomainToVercel = async (domain: string) => { return await fetch( - `https://api.vercel.com/v10/projects/${process.env.VERCEL_PROJECT_ID - }/domains${process.env.VERCEL_TEAM_ID ? `?teamId=${process.env.VERCEL_TEAM_ID}` : "" + `https://api.vercel.com/v10/projects/${ + process.env.VERCEL_PROJECT_ID + }/domains${ + process.env.VERCEL_TEAM_ID ? `?teamId=${process.env.VERCEL_TEAM_ID}` : "" }`, { method: "POST", @@ -24,8 +26,10 @@ export const addDomainToVercel = async (domain: string) => { export const removeDomainFromVercelProject = async (domain: string) => { return await fetch( - `https://api.vercel.com/v9/projects/${process.env.VERCEL_PROJECT_ID - }/domains/${domain}${process.env.VERCEL_TEAM_ID ? `?teamId=${process.env.VERCEL_TEAM_ID}` : "" + `https://api.vercel.com/v9/projects/${ + process.env.VERCEL_PROJECT_ID + }/domains/${domain}${ + process.env.VERCEL_TEAM_ID ? `?teamId=${process.env.VERCEL_TEAM_ID}` : "" }`, { headers: { @@ -38,7 +42,8 @@ export const removeDomainFromVercelProject = async (domain: string) => { export const removeDomainFromVercelTeam = async (domain: string) => { return await fetch( - `https://api.vercel.com/v6/domains/${domain}${process.env.VERCEL_TEAM_ID ? `?teamId=${process.env.VERCEL_TEAM_ID}` : "" + `https://api.vercel.com/v6/domains/${domain}${ + process.env.VERCEL_TEAM_ID ? `?teamId=${process.env.VERCEL_TEAM_ID}` : "" }`, { headers: { @@ -53,8 +58,10 @@ export const getDomainResponse = async ( domain: string, ): Promise => { return await fetch( - `https://api.vercel.com/v9/projects/${process.env.VERCEL_PROJECT_ID - }/domains/${domain}${process.env.VERCEL_TEAM_ID ? `?teamId=${process.env.VERCEL_TEAM_ID}` : "" + `https://api.vercel.com/v9/projects/${ + process.env.VERCEL_PROJECT_ID + }/domains/${domain}${ + process.env.VERCEL_TEAM_ID ? `?teamId=${process.env.VERCEL_TEAM_ID}` : "" }`, { method: "GET", @@ -72,7 +79,8 @@ export const getConfigResponse = async ( domain: string, ): Promise => { return await fetch( - `https://api.vercel.com/v6/domains/${domain}/config${process.env.VERCEL_TEAM_ID ? `?teamId=${process.env.VERCEL_TEAM_ID}` : "" + `https://api.vercel.com/v6/domains/${domain}/config${ + process.env.VERCEL_TEAM_ID ? `?teamId=${process.env.VERCEL_TEAM_ID}` : "" }`, { method: "GET", @@ -88,8 +96,10 @@ export const verifyDomain = async ( domain: string, ): Promise => { return await fetch( - `https://api.vercel.com/v9/projects/${process.env.VERCEL_PROJECT_ID - }/domains/${domain}/verify${process.env.VERCEL_TEAM_ID ? `?teamId=${process.env.VERCEL_TEAM_ID}` : "" + `https://api.vercel.com/v9/projects/${ + process.env.VERCEL_PROJECT_ID + }/domains/${domain}/verify${ + process.env.VERCEL_TEAM_ID ? `?teamId=${process.env.VERCEL_TEAM_ID}` : "" }`, { method: "POST", diff --git a/apps/app/src/lib/operator/actions.ts b/apps/app/src/lib/operator/actions.ts index 649d9bac3c..54813d2fc0 100644 --- a/apps/app/src/lib/operator/actions.ts +++ b/apps/app/src/lib/operator/actions.ts @@ -204,4 +204,4 @@ export async function goBack(page: Page) { export async function goForward(page: Page) { await page.goForward(); return "Navigated forward"; -} \ No newline at end of file +} diff --git a/apps/app/src/lib/operator/browser.ts b/apps/app/src/lib/operator/browser.ts index 8799ce7d3b..4e4f94ece7 100644 --- a/apps/app/src/lib/operator/browser.ts +++ b/apps/app/src/lib/operator/browser.ts @@ -21,7 +21,7 @@ async function getBrowser(sessionId: string) { } export async function getOrCreateBrowser( - sessionId: string + sessionId: string, ): Promise { const existing = sessions.get(sessionId); if (existing) { @@ -31,4 +31,4 @@ export async function getOrCreateBrowser( const browser = await getBrowser(sessionId); sessions.set(sessionId, browser); return browser; -} \ No newline at end of file +} diff --git a/apps/app/src/lib/operator/dom.ts b/apps/app/src/lib/operator/dom.ts index 9b674b9a81..726a18aabb 100644 --- a/apps/app/src/lib/operator/dom.ts +++ b/apps/app/src/lib/operator/dom.ts @@ -4,34 +4,34 @@ import type { Page } from "playwright-core"; // 1) Standard DOM type definitions // ------------------------------------------------------------------ export interface DOMBaseNode { - type: "TEXT_NODE" | "ELEMENT_NODE"; - isVisible: boolean; - parent?: DOMElementNode; + type: "TEXT_NODE" | "ELEMENT_NODE"; + isVisible: boolean; + parent?: DOMElementNode; } export interface DOMTextNode extends DOMBaseNode { - type: "TEXT_NODE"; - text: string; + type: "TEXT_NODE"; + text: string; } export interface DOMElementNode extends DOMBaseNode { - type: "ELEMENT_NODE"; - tagName: string; - xpath: string; - attributes: Record; - children: DOMBaseNode[]; - isInteractive: boolean; - isTopElement: boolean; - shadowRoot: boolean; - highlightIndex?: number; + type: "ELEMENT_NODE"; + tagName: string; + xpath: string; + attributes: Record; + children: DOMBaseNode[]; + isInteractive: boolean; + isTopElement: boolean; + shadowRoot: boolean; + highlightIndex?: number; } /** * The typed DOM you'll parse on the Node side */ export interface DOMState { - elementTree: DOMElementNode; - selectorMap: Record; + elementTree: DOMElementNode; + selectorMap: Record; } /** @@ -39,8 +39,8 @@ export interface DOMState { * for highlight steps, so we don't have to re-serialize the typed DOMState. */ export interface DomResult { - domState: DOMState; - rawDom: any; // The untyped JSON from the browser + domState: DOMState; + rawDom: any; // The untyped JSON from the browser } // ------------------------------------------------------------------ @@ -208,94 +208,94 @@ const GATHER_DOM_TREE_JS = String.raw` // 3) Local parse logic to create typed DOMState // ------------------------------------------------------------------ function parseNode(nodeData: any, parent?: DOMElementNode): DOMBaseNode | null { - if (!nodeData) return null; - - if (nodeData.type === "TEXT_NODE") { - const textNode: DOMTextNode = { - type: "TEXT_NODE", - text: nodeData.text, - isVisible: !!nodeData.isVisible, - parent, - }; - return textNode; - } - - if (nodeData.type === "ELEMENT_NODE") { - const elementNode: DOMElementNode = { - type: "ELEMENT_NODE", - tagName: nodeData.tagName || "", - xpath: nodeData.xpath || "", - attributes: nodeData.attributes || {}, - children: [], - isVisible: !!nodeData.isVisible, - isInteractive: !!nodeData.isInteractive, - isTopElement: !!nodeData.isTopElement, - shadowRoot: !!nodeData.shadowRoot, - highlightIndex: nodeData.highlightIndex, - parent, - }; - - if (Array.isArray(nodeData.children)) { - const childNodes: DOMBaseNode[] = []; - for (const child of nodeData.children) { - const c = parseNode(child, elementNode); - if (c) childNodes.push(c); - } - elementNode.children = childNodes; - } - return elementNode; - } - - return null; + if (!nodeData) return null; + + if (nodeData.type === "TEXT_NODE") { + const textNode: DOMTextNode = { + type: "TEXT_NODE", + text: nodeData.text, + isVisible: !!nodeData.isVisible, + parent, + }; + return textNode; + } + + if (nodeData.type === "ELEMENT_NODE") { + const elementNode: DOMElementNode = { + type: "ELEMENT_NODE", + tagName: nodeData.tagName || "", + xpath: nodeData.xpath || "", + attributes: nodeData.attributes || {}, + children: [], + isVisible: !!nodeData.isVisible, + isInteractive: !!nodeData.isInteractive, + isTopElement: !!nodeData.isTopElement, + shadowRoot: !!nodeData.shadowRoot, + highlightIndex: nodeData.highlightIndex, + parent, + }; + + if (Array.isArray(nodeData.children)) { + const childNodes: DOMBaseNode[] = []; + for (const child of nodeData.children) { + const c = parseNode(child, elementNode); + if (c) childNodes.push(c); + } + elementNode.children = childNodes; + } + return elementNode; + } + + return null; } function createSelectorMap( - elementTree: DOMElementNode, + elementTree: DOMElementNode, ): Record { - const selectorMap: Record = {}; - - function traverse(node: DOMBaseNode) { - if (node.type === "ELEMENT_NODE") { - const el = node as DOMElementNode; - if (typeof el.highlightIndex === "number") { - selectorMap[el.highlightIndex] = el; - } - for (const child of el.children) { - traverse(child); - } - } - } - traverse(elementTree); - return selectorMap; + const selectorMap: Record = {}; + + function traverse(node: DOMBaseNode) { + if (node.type === "ELEMENT_NODE") { + const el = node as DOMElementNode; + if (typeof el.highlightIndex === "number") { + selectorMap[el.highlightIndex] = el; + } + for (const child of el.children) { + traverse(child); + } + } + } + traverse(elementTree); + return selectorMap; } // ------------------------------------------------------------------ // 4) "Get the DOM" method, separate from highlighting // ------------------------------------------------------------------ export async function getDomState( - page: Page, - highlightElements = true, + page: Page, + highlightElements = true, ): Promise { - // 1) Collect raw JSON from the browser - const rawTree = await page.evaluate( - ({ script, doHighlight }) => { - const fn = eval(script); - return fn(doHighlight); - }, - { script: GATHER_DOM_TREE_JS, doHighlight: highlightElements }, - ); - - if (!rawTree) throw new Error("No DOM returned from browser!"); - - // 2) Parse into typed structure - const elementTree = parseNode(rawTree) as DOMElementNode; - if (!elementTree) throw new Error("Failed to parse root element node!"); - - // 3) Build highlightIndex -> DOMElement map - const selectorMap = createSelectorMap(elementTree); - const domState: DOMState = { elementTree, selectorMap }; - - return { domState, rawDom: rawTree }; + // 1) Collect raw JSON from the browser + const rawTree = await page.evaluate( + ({ script, doHighlight }) => { + const fn = new Function(`return ${script}`)(); + return fn(doHighlight); + }, + { script: GATHER_DOM_TREE_JS, doHighlight: highlightElements }, + ); + + if (!rawTree) throw new Error("No DOM returned from browser!"); + + // 2) Parse into typed structure + const elementTree = parseNode(rawTree) as DOMElementNode; + if (!elementTree) throw new Error("Failed to parse root element node!"); + + // 3) Build highlightIndex -> DOMElement map + const selectorMap = createSelectorMap(elementTree); + const domState: DOMState = { elementTree, selectorMap }; + + return { domState, rawDom: rawTree }; } // ------------------------------------------------------------------ @@ -304,36 +304,36 @@ export async function getDomState( // bigger background for better readability. // ------------------------------------------------------------------ export async function highlightDomElements( - page: Page, - rawDom: any, + page: Page, + rawDom: any, ): Promise { - await page.evaluate((rawData) => { - if (!rawData) return; - - // 1) gather all nodes with highlightIndex - const nodesWithIndex: any[] = []; - function dfs(node: any) { - if (!node) return; - if ( - node.type === "ELEMENT_NODE" && - typeof node.highlightIndex === "number" - ) { - nodesWithIndex.push(node); - } - if (Array.isArray(node.children)) { - for (const c of node.children) { - dfs(c); - } - } - } - dfs(rawData); - - // 2) Insert style if not present - const styleId = "dom-highlighter-style"; - if (!document.getElementById(styleId)) { - const styleEl = document.createElement("style"); - styleEl.id = styleId; - styleEl.textContent = ` + await page.evaluate((rawData) => { + if (!rawData) return; + + // 1) gather all nodes with highlightIndex + const nodesWithIndex: any[] = []; + function dfs(node: any) { + if (!node) return; + if ( + node.type === "ELEMENT_NODE" && + typeof node.highlightIndex === "number" + ) { + nodesWithIndex.push(node); + } + if (Array.isArray(node.children)) { + for (const c of node.children) { + dfs(c); + } + } + } + dfs(rawData); + + // 2) Insert style if not present + const styleId = "dom-highlighter-style"; + if (!document.getElementById(styleId)) { + const styleEl = document.createElement("style"); + styleEl.id = styleId; + styleEl.textContent = ` .dom-highlighter-overlay { position: fixed; font-size: 14px; @@ -357,97 +357,97 @@ export async function highlightDomElements( border: 1px solid rgba(0,0,0,0.2); } `; - document.head.appendChild(styleEl); - } - - // 3) Clear old overlays - for (const el of document.querySelectorAll(".dom-highlighter-overlay")) { - el.remove(); - } - - // 4) Some color rotation - const highlightColors = [ - { border: "#FF5D5D", bg: "#FF5D5D", highlight: "rgba(255,93,93,0.08)" }, - { border: "#4CAF50", bg: "#4CAF50", highlight: "rgba(76,175,80,0.08)" }, - { border: "#2196F3", bg: "#2196F3", highlight: "rgba(33,150,243,0.08)" }, - { border: "#FFC107", bg: "#FFC107", highlight: "rgba(255,193,7,0.08)" }, - { border: "#9C27B0", bg: "#9C27B0", highlight: "rgba(156,39,176,0.08)" }, - ]; - - // 5) For each clickable node, measure & place overlays - for (const nodeObj of nodesWithIndex) { - const highlightIndex = nodeObj.highlightIndex; - const xpath = nodeObj.xpath; - if (!xpath) return; - - const result = document.evaluate( - xpath, - document, - null, - XPathResult.FIRST_ORDERED_NODE_TYPE, - null, - ); - const el = result.singleNodeValue as HTMLElement | null; - if (!el || el.nodeType !== Node.ELEMENT_NODE) return; - - const rect = el.getBoundingClientRect(); - if (rect.width === 0 && rect.height === 0) return; - - const colorStyle = - highlightColors[highlightIndex % highlightColors.length]; - const overlay = document.createElement("div"); - overlay.className = "dom-highlighter-overlay"; - - const numberSpan = document.createElement("span"); - numberSpan.className = "dom-highlighter-number"; - numberSpan.textContent = String(highlightIndex); - numberSpan.style.backgroundColor = colorStyle.bg; - numberSpan.style.color = "white"; - overlay.appendChild(numberSpan); - - overlay.style.top = `${rect.top}px`; - overlay.style.left = `${rect.left}px`; - overlay.style.width = `${rect.width}px`; - overlay.style.height = `${rect.height}px`; - overlay.style.borderColor = colorStyle.border; - overlay.style.backgroundColor = colorStyle.highlight; - - document.body.appendChild(overlay); - } - }, rawDom); + document.head.appendChild(styleEl); + } + + // 3) Clear old overlays + for (const el of document.querySelectorAll(".dom-highlighter-overlay")) { + el.remove(); + } + + // 4) Some color rotation + const highlightColors = [ + { border: "#FF5D5D", bg: "#FF5D5D", highlight: "rgba(255,93,93,0.08)" }, + { border: "#4CAF50", bg: "#4CAF50", highlight: "rgba(76,175,80,0.08)" }, + { border: "#2196F3", bg: "#2196F3", highlight: "rgba(33,150,243,0.08)" }, + { border: "#FFC107", bg: "#FFC107", highlight: "rgba(255,193,7,0.08)" }, + { border: "#9C27B0", bg: "#9C27B0", highlight: "rgba(156,39,176,0.08)" }, + ]; + + // 5) For each clickable node, measure & place overlays + for (const nodeObj of nodesWithIndex) { + const highlightIndex = nodeObj.highlightIndex; + const xpath = nodeObj.xpath; + if (!xpath) return; + + const result = document.evaluate( + xpath, + document, + null, + XPathResult.FIRST_ORDERED_NODE_TYPE, + null, + ); + const el = result.singleNodeValue as HTMLElement | null; + if (!el || el.nodeType !== Node.ELEMENT_NODE) return; + + const rect = el.getBoundingClientRect(); + if (rect.width === 0 && rect.height === 0) return; + + const colorStyle = + highlightColors[highlightIndex % highlightColors.length]; + const overlay = document.createElement("div"); + overlay.className = "dom-highlighter-overlay"; + + const numberSpan = document.createElement("span"); + numberSpan.className = "dom-highlighter-number"; + numberSpan.textContent = String(highlightIndex); + numberSpan.style.backgroundColor = colorStyle.bg; + numberSpan.style.color = "white"; + overlay.appendChild(numberSpan); + + overlay.style.top = `${rect.top}px`; + overlay.style.left = `${rect.left}px`; + overlay.style.width = `${rect.width}px`; + overlay.style.height = `${rect.height}px`; + overlay.style.borderColor = colorStyle.border; + overlay.style.backgroundColor = colorStyle.highlight; + + document.body.appendChild(overlay); + } + }, rawDom); } export async function clearDomHighlights(page: Page): Promise { - await page.evaluate(() => { - for (const el of document.querySelectorAll(".dom-highlighter-overlay")) { - el.remove(); - } - const styleEl = document.getElementById("dom-highlighter-style"); - if (styleEl) styleEl.remove(); - }); + await page.evaluate(() => { + for (const el of document.querySelectorAll(".dom-highlighter-overlay")) { + el.remove(); + } + const styleEl = document.getElementById("dom-highlighter-style"); + if (styleEl) styleEl.remove(); + }); } export async function clickElementByHighlightIndex( - page: Page, - domState: DOMState, - highlightIndex: number, + page: Page, + domState: DOMState, + highlightIndex: number, ) { - const elemNode = domState.selectorMap[highlightIndex]; - if (!elemNode) { - return `No element found for highlightIndex=${highlightIndex}`; - } - - const xpath = elemNode.xpath; - if (!xpath) { - return `Node has no xpath for highlightIndex=${highlightIndex}`; - } - - const locator = page.locator(`xpath=${xpath}`); - const count = await locator.count(); - if (count < 1) { - return `Element not found in DOM for highlightIndex=${highlightIndex}, xpath=${xpath}`; - } - - await locator.first().click(); - return true; + const elemNode = domState.selectorMap[highlightIndex]; + if (!elemNode) { + return `No element found for highlightIndex=${highlightIndex}`; + } + + const xpath = elemNode.xpath; + if (!xpath) { + return `Node has no xpath for highlightIndex=${highlightIndex}`; + } + + const locator = page.locator(`xpath=${xpath}`); + const count = await locator.count(); + if (count < 1) { + return `Element not found in DOM for highlightIndex=${highlightIndex}, xpath=${xpath}`; + } + + await locator.first().click(); + return true; } diff --git a/apps/app/src/lib/operator/session.ts b/apps/app/src/lib/operator/session.ts index afc6fa17ec..ff13797a0a 100644 --- a/apps/app/src/lib/operator/session.ts +++ b/apps/app/src/lib/operator/session.ts @@ -46,4 +46,4 @@ export async function getSessionUrl(sessionId: string) { }); const session = await bb.sessions.debug(sessionId); return session.debuggerFullscreenUrl; -} \ No newline at end of file +} diff --git a/apps/app/src/lib/utils.ts b/apps/app/src/lib/utils.ts index 31c376d87a..4e02437612 100644 --- a/apps/app/src/lib/utils.ts +++ b/apps/app/src/lib/utils.ts @@ -8,4 +8,4 @@ export function getInitials(name: string): string { export function sleep(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); -} \ No newline at end of file +} diff --git a/apps/app/src/lib/utils/calculate-next-review.ts b/apps/app/src/lib/utils/calculate-next-review.ts index c25b9959ff..9aaad3e15e 100644 --- a/apps/app/src/lib/utils/calculate-next-review.ts +++ b/apps/app/src/lib/utils/calculate-next-review.ts @@ -10,7 +10,7 @@ interface ReviewInfo { export function calculateNextReview( lastPublishedAt: Date | null, frequency: Frequency | null, - urgentThresholdDays = 7 + urgentThresholdDays = 7, ): ReviewInfo | null { if (!frequency || !lastPublishedAt) return null; diff --git a/apps/app/src/locales/es.ts b/apps/app/src/locales/es.ts index 1e167a3a6d..0fb3b35e3f 100644 --- a/apps/app/src/locales/es.ts +++ b/apps/app/src/locales/es.ts @@ -2,38 +2,38 @@ export default { language: { title: "Idiomas", description: "Cambia el idioma utilizado en la interfaz de usuario.", - placeholder: "Seleccionar idioma" + placeholder: "Seleccionar idioma", }, languages: { en: "Inglés", no: "Noruego", es: "Español", fr: "Francés", - pt: "Portugués" + pt: "Portugués", }, common: { actions: { save: "Guardar", edit: "Editar", - "delete": "Eliminar", + delete: "Eliminar", cancel: "Cancelar", clear: "Limpiar", create: "Crear", send: "Enviar", - "return": "Regresar", + return: "Regresar", success: "Éxito", error: "Error", next: "Siguiente", complete: "Completar", - addNew: "Agregar Nuevo" + addNew: "Agregar Nuevo", }, assignee: { label: "Asignado a", - placeholder: "Seleccionar asignado" + placeholder: "Seleccionar asignado", }, date: { pick: "Seleccionar una fecha", - due_date: "Fecha de vencimiento" + due_date: "Fecha de vencimiento", }, status: { open: "Abierto", @@ -51,7 +51,7 @@ export default { assessed: "Evaluado", active: "Activo", inactive: "Inactivo", - title: "Estado" + title: "Estado", }, filters: { clear: "Limpiar filtros", @@ -60,8 +60,8 @@ export default { department: "Departamento", owner: { label: "Asignado a", - placeholder: "Filtrar por asignado" - } + placeholder: "Filtrar por asignado", + }, }, table: { title: "Título", @@ -69,7 +69,7 @@ export default { assigned_to: "Asignado a", due_date: "Fecha de vencimiento", last_updated: "Última actualización", - no_results: "No se encontraron resultados" + no_results: "No se encontraron resultados", }, empty_states: { no_results: { @@ -79,12 +79,12 @@ export default { description: "Intenta otra búsqueda o ajusta los filtros", description_filters: "Intenta otra búsqueda o ajusta los filtros", description_no_tasks: "Crea una tarea para comenzar", - description_no_risks: "Crea un riesgo para comenzar" + description_no_risks: "Crea un riesgo para comenzar", }, no_items: { title: "No se encontraron elementos", - description: "Intenta ajustar tu búsqueda o filtros" - } + description: "Intenta ajustar tu búsqueda o filtros", + }, }, pagination: { of: "de", @@ -94,33 +94,36 @@ export default { go_to_first_page: "Ir a la primera página", go_to_previous_page: "Ir a la página anterior", go_to_next_page: "Ir a la siguiente página", - go_to_last_page: "Ir a la última página" + go_to_last_page: "Ir a la última página", }, comments: { title: "Comentarios", - description: "Agrega un comentario utilizando el formulario a continuación.", + description: + "Agrega un comentario utilizando el formulario a continuación.", add: "Nuevo comentario", - "new": "Nuevo Comentario", + new: "Nuevo Comentario", save: "Guardar Comentario", success: "Comentario agregado con éxito", error: "Error al agregar comentario", placeholder: "Escribe tu comentario aquí...", empty: { title: "Sin comentarios aún", - description: "Sé el primero en agregar un comentario" - } + description: "Sé el primero en agregar un comentario", + }, }, attachments: { title: "Adjuntos", description: "Agrega un archivo haciendo clic en 'Agregar Adjunto'.", upload: "Subir archivo adjunto", - upload_description: "Sube un adjunto o agrega un enlace a un recurso externo.", + upload_description: + "Sube un adjunto o agrega un enlace a un recurso externo.", drop: "Suelta los archivos aquí", - drop_description: "Suelta archivos aquí o haz clic para elegir archivos de tu dispositivo.", + drop_description: + "Suelta archivos aquí o haz clic para elegir archivos de tu dispositivo.", drop_files_description: "Los archivos pueden tener un tamaño de hasta ", empty: { title: "Sin adjuntos", - description: "Agrega un archivo haciendo clic en 'Agregar Adjunto'." + description: "Agrega un archivo haciendo clic en 'Agregar Adjunto'.", }, toasts: { error: "Algo salió mal, por favor intenta de nuevo.", @@ -136,18 +139,18 @@ export default { success_uploading_files_single: "Archivo subido con éxito", success_uploading_files_target: "Archivos subidos", uploading_files: "Subiendo {target}...", - remove_file: "Eliminar archivo" - } + remove_file: "Eliminar archivo", + }, }, notifications: { inbox: "Bandeja de entrada", archive: "Archivo", archive_all: "Archivar todo", - no_notifications: "No hay nuevas notificaciones" + no_notifications: "No hay nuevas notificaciones", }, edit: "Editar", errors: { - unexpected_error: "Ocurrió un error inesperado" + unexpected_error: "Ocurrió un error inesperado", }, description: "Descripción", last_updated: "Última actualización", @@ -156,34 +159,35 @@ export default { weekly: "Semanal", monthly: "Mensual", quarterly: "Trimestral", - yearly: "Anual" - } + yearly: "Anual", + }, }, header: { discord: { - button: "Únete a nosotros en Discord" + button: "Únete a nosotros en Discord", }, feedback: { button: "Comentarios", title: "¡Gracias por tus comentarios!", description: "Volveremos contigo lo antes posible", - placeholder: "Ideas para mejorar esta página o problemas que estás experimentando.", + placeholder: + "Ideas para mejorar esta página o problemas que estás experimentando.", success: "¡Gracias por tus comentarios!", error: "Error al enviar comentarios - ¿intentar de nuevo?", - send: "Enviar Comentarios" - } + send: "Enviar Comentarios", + }, }, not_found: { title: "404 - Página no encontrada", description: "La página que buscas no existe.", - "return": "Regresar al panel" + return: "Regresar al panel", }, theme: { options: { light: "Claro", dark: "Oscuro", - system: "Sistema" - } + system: "Sistema", + }, }, sidebar: { overview: "Resumen", @@ -193,11 +197,12 @@ export default { integrations: "Integraciones", settings: "Configuraciones", evidence: "Tareas de Evidencia", - people: "Personas" + people: "Personas", }, auth: { title: "Automatiza el cumplimiento de SOC 2, ISO 27001 y GDPR con IA.", - description: "Crea una cuenta gratuita o inicia sesión con una cuenta existente para continuar.", + description: + "Crea una cuenta gratuita o inicia sesión con una cuenta existente para continuar.", options: "Más opciones", google: "Continuar con Google", email: { @@ -205,12 +210,14 @@ export default { placeholder: "Ingresa la dirección de correo electrónico", button: "Continuar con correo electrónico", magic_link_sent: "Enlace mágico enviado", - magic_link_description: "Revisa tu bandeja de entrada para un enlace mágico.", + magic_link_description: + "Revisa tu bandeja de entrada para un enlace mágico.", magic_link_try_again: "Intenta de nuevo.", success: "Correo enviado - ¡revisa tu bandeja de entrada!", - error: "Error al enviar el correo - ¿intentar de nuevo?" + error: "Error al enviar el correo - ¿intentar de nuevo?", }, - terms: "Al hacer clic en continuar, reconoces que has leído y aceptas los Términos de Servicio y la Política de Privacidad." + terms: + "Al hacer clic en continuar, reconoces que has leído y aceptas los Términos de Servicio y la Política de Privacidad.", }, onboarding: { title: "Crear una organización", @@ -219,35 +226,35 @@ export default { fields: { name: { label: "Nombre de la Organización", - placeholder: "El nombre de tu organización" + placeholder: "El nombre de tu organización", }, website: { label: "Sitio web", - placeholder: "El sitio web de tu organización" + placeholder: "El sitio web de tu organización", }, subdomain: { label: "Subdominio", - placeholder: "ejemplo" + placeholder: "ejemplo", }, fullName: { label: "Tu Nombre", - placeholder: "Tu nombre completo" - } + placeholder: "Tu nombre completo", + }, }, success: "¡Gracias, estás listo!", error: "Algo salió mal, por favor intenta de nuevo.", unavailable: "No disponible", check_availability: "Verificando disponibilidad", - available: "Disponible" + available: "Disponible", }, overview: { title: "Resumen", framework_chart: { - title: "Progreso del Marco" + title: "Progreso del Marco", }, requirement_chart: { - title: "Estado de Cumplimiento" - } + title: "Estado de Cumplimiento", + }, }, policies: { dashboard: { @@ -258,32 +265,32 @@ export default { policies_by_framework: "Políticas por Marco", sub_pages: { overview: "Descripción general", - edit_policy: "Editar política" - } + edit_policy: "Editar política", + }, }, table: { name: "Nombre de la Política", statuses: { draft: "Borrador", published: "Publicado", - archived: "Archivado" + archived: "Archivado", }, filters: { owner: { label: "Asignado", - placeholder: "Filtrar por asignado" - } - } + placeholder: "Filtrar por asignado", + }, + }, }, filters: { search: "Buscar políticas...", - all: "Todas las Políticas" + all: "Todas las Políticas", }, status: { draft: "Borrador", published: "Publicado", needs_review: "Necesita Revisión", - archived: "Archivado" + archived: "Archivado", }, policies: "políticas", title: "Políticas", @@ -304,20 +311,21 @@ export default { title: "Resumen de la Política", form: { update_policy: "Actualizar Política", - update_policy_description: "Actualice el título o la descripción de la política.", + update_policy_description: + "Actualice el título o la descripción de la política.", update_policy_success: "Política actualizada con éxito", update_policy_error: "Error al actualizar la política", update_policy_title: "Nombre de la Política", review_frequency: "Frecuencia de Revisión", review_frequency_placeholder: "Seleccione una frecuencia de revisión", review_date: "Fecha de Revisión", - review_date_placeholder: "Seleccione una fecha de revisión" - } - } + review_date_placeholder: "Seleccione una fecha de revisión", + }, + }, }, evidence_tasks: { evidence_tasks: "Tareas de Evidencia", - overview: "Resumen" + overview: "Resumen", }, risk: { risks: "riesgos", @@ -331,8 +339,10 @@ export default { vendor_status: "Estado del Proveedor", vendor_category: "Categorías de Proveedores", vendors_by_assignee: "Proveedores por Asignado", - inherent_risk_description: "Nivel de riesgo inicial antes de aplicar controles", - residual_risk_description: "Nivel de riesgo restante después de aplicar controles" + inherent_risk_description: + "Nivel de riesgo inicial antes de aplicar controles", + residual_risk_description: + "Nivel de riesgo restante después de aplicar controles", }, register: { title: "Registro de Proveedores", @@ -340,15 +350,17 @@ export default { name: "Nombre", category: "Categoría", status: "Estado", - owner: "Propietario" - } + owner: "Propietario", + }, }, assessment: { title: "Evaluación de Proveedores", - update_success: "Evaluación de riesgo del proveedor actualizada con éxito", - update_error: "Error al actualizar la evaluación de riesgo del proveedor", + update_success: + "Evaluación de riesgo del proveedor actualizada con éxito", + update_error: + "Error al actualizar la evaluación de riesgo del proveedor", inherent_risk: "Riesgo Inherente", - residual_risk: "Riesgo Residual" + residual_risk: "Riesgo Residual", }, form: { vendor_details: "Detalles del Proveedor", @@ -367,38 +379,38 @@ export default { update_vendor: "Actualizar Proveedor", update_vendor_success: "Proveedor actualizado con éxito", update_vendor_error: "Error al actualizar el proveedor", - add_comment: "Agregar Comentario" + add_comment: "Agregar Comentario", }, table: { name: "Nombre", category: "Categoría", status: "Estado", - owner: "Propietario" + owner: "Propietario", }, filters: { search_placeholder: "Buscar proveedores...", status_placeholder: "Filtrar por estado", category_placeholder: "Filtrar por categoría", - owner_placeholder: "Filtrar por propietario" + owner_placeholder: "Filtrar por propietario", }, empty_states: { no_vendors: { title: "Aún no hay proveedores", - description: "Comienza creando tu primer proveedor" + description: "Comienza creando tu primer proveedor", }, no_results: { title: "No se encontraron resultados", description: "No hay proveedores que coincidan con tu búsqueda", - description_with_filters: "Intenta ajustar tus filtros" - } + description_with_filters: "Intenta ajustar tus filtros", + }, }, actions: { - create: "Crear Proveedor" + create: "Crear Proveedor", }, status: { not_assessed: "No Evaluado", in_progress: "En Progreso", - assessed: "Evaluado" + assessed: "Evaluado", }, category: { cloud: "Nube", @@ -408,14 +420,14 @@ export default { marketing: "Marketing", sales: "Ventas", hr: "RRHH", - other: "Otro" + other: "Otro", }, risk_level: { low: "Bajo Riesgo", medium: "Riesgo Medio", high: "Alto Riesgo", - unknown: "Riesgo Desconocido" - } + unknown: "Riesgo Desconocido", + }, }, dashboard: { title: "Tablero", @@ -423,40 +435,47 @@ export default { risk_status: "Estado del Riesgo", risks_by_department: "Riesgos por Departamento", risks_by_assignee: "Riesgos por Asignado", - inherent_risk_description: "El riesgo inherente se calcula como probabilidad * impacto. Calculado antes de aplicar cualquier control.", - residual_risk_description: "El riesgo residual se calcula como probabilidad * impacto. Este es el nivel de riesgo después de aplicar controles.", - risk_assessment_description: "Compara los niveles de riesgo inherente y residual" + inherent_risk_description: + "El riesgo inherente se calcula como probabilidad * impacto. Calculado antes de aplicar cualquier control.", + residual_risk_description: + "El riesgo residual se calcula como probabilidad * impacto. Este es el nivel de riesgo después de aplicar controles.", + risk_assessment_description: + "Compara los niveles de riesgo inherente y residual", }, register: { title: "Registro de Riesgos", table: { - risk: "Riesgo" + risk: "Riesgo", }, empty: { no_risks: { title: "Crea un riesgo para comenzar", - description: "Rastrea y puntúa riesgos, crea y asigna tareas de mitigación para tu equipo, y gestiona tu registro de riesgos todo en una interfaz simple." + description: + "Rastrea y puntúa riesgos, crea y asigna tareas de mitigación para tu equipo, y gestiona tu registro de riesgos todo en una interfaz simple.", }, - create_risk: "Crear un riesgo" - } + create_risk: "Crear un riesgo", + }, }, metrics: { probability: "Probabilidad", impact: "Impacto", inherentRisk: "Riesgo Inherente", - residualRisk: "Riesgo Residual" + residualRisk: "Riesgo Residual", }, form: { update_inherent_risk: "Guardar Riesgo Inherente", - update_inherent_risk_description: "Actualiza el riesgo inherente del riesgo. Este es el nivel de riesgo antes de aplicar cualquier control.", + update_inherent_risk_description: + "Actualiza el riesgo inherente del riesgo. Este es el nivel de riesgo antes de aplicar cualquier control.", update_inherent_risk_success: "Riesgo inherente actualizado con éxito", update_inherent_risk_error: "Error al actualizar el riesgo inherente", update_residual_risk: "Guardar Riesgo Residual", - update_residual_risk_description: "Actualiza el riesgo residual del riesgo. Este es el nivel de riesgo después de aplicar controles.", + update_residual_risk_description: + "Actualiza el riesgo residual del riesgo. Este es el nivel de riesgo después de aplicar controles.", update_residual_risk_success: "Riesgo residual actualizado con éxito", update_residual_risk_error: "Error al actualizar el riesgo residual", update_risk: "Actualizar Riesgo", - update_risk_description: "Actualiza el título o la descripción del riesgo.", + update_risk_description: + "Actualiza el título o la descripción del riesgo.", update_risk_success: "Riesgo actualizado con éxito", update_risk_error: "Error al actualizar el riesgo", create_risk_success: "Riesgo creado con éxito", @@ -471,7 +490,7 @@ export default { risk_department: "Departamento", risk_department_placeholder: "Selecciona un departamento", risk_status: "Estado del Riesgo", - risk_status_placeholder: "Selecciona un estado de riesgo" + risk_status_placeholder: "Selecciona un estado de riesgo", }, tasks: { title: "Tareas", @@ -486,35 +505,41 @@ export default { description: "Descripción", description_description: "Ingresa una descripción para la tarea", due_date: "Fecha de Vencimiento", - due_date_description: "Selecciona la fecha de vencimiento para la tarea", + due_date_description: + "Selecciona la fecha de vencimiento para la tarea", success: "Tarea creada con éxito", - error: "Error al crear la tarea" + error: "Error al crear la tarea", }, sheet: { title: "Crear Tarea", update: "Actualizar Tarea", - update_description: "Actualiza el título o la descripción de la tarea." + update_description: "Actualiza el título o la descripción de la tarea.", }, empty: { - description_create: "Crea una tarea de mitigación para este riesgo, agrega un plan de tratamiento y asígnala a un miembro del equipo." - } - } + description_create: + "Crea una tarea de mitigación para este riesgo, agrega un plan de tratamiento y asígnala a un miembro del equipo.", + }, + }, }, settings: { general: { title: "General", org_name: "Nombre de la organización", - org_name_description: "Este es el nombre visible de tu organización. Debes usar el nombre legal de tu organización.", + org_name_description: + "Este es el nombre visible de tu organización. Debes usar el nombre legal de tu organización.", org_name_tip: "Por favor, usa un máximo de 32 caracteres.", org_website: "Sitio web de la organización", - org_website_description: "Esta es la URL oficial del sitio web de tu organización. Asegúrate de incluir la URL completa con https://.", + org_website_description: + "Esta es la URL oficial del sitio web de tu organización. Asegúrate de incluir la URL completa con https://.", org_website_tip: "Por favor, ingresa una URL válida incluyendo https://", org_website_error: "Error al actualizar el sitio web de la organización", org_website_updated: "Sitio web de la organización actualizado", org_delete: "Eliminar organización", - org_delete_description: "Elimina permanentemente tu organización y todo su contenido de la plataforma Comp AI. Esta acción no es reversible - por favor, continúa con precaución.", + org_delete_description: + "Elimina permanentemente tu organización y todo su contenido de la plataforma Comp AI. Esta acción no es reversible - por favor, continúa con precaución.", org_delete_alert_title: "¿Estás absolutamente seguro?", - org_delete_alert_description: "Esta acción no se puede deshacer. Esto eliminará permanentemente tu organización y eliminará tus datos de nuestros servidores.", + org_delete_alert_description: + "Esta acción no se puede deshacer. Esto eliminará permanentemente tu organización y eliminará tus datos de nuestros servidores.", org_delete_error: "Error al eliminar la organización", org_delete_success: "Organización eliminada", org_name_updated: "Nombre de la organización actualizado", @@ -523,14 +548,14 @@ export default { delete_button: "Eliminar", delete_confirm: "ELIMINAR", delete_confirm_tip: "Escribe ELIMINAR para confirmar.", - cancel_button: "Cancelar" + cancel_button: "Cancelar", }, members: { - title: "Miembros" + title: "Miembros", }, billing: { - title: "Facturación" - } + title: "Facturación", + }, }, user_menu: { theme: "Tema", @@ -539,7 +564,7 @@ export default { account: "Cuenta", support: "Soporte", settings: "Configuraciones", - teams: "Equipos" + teams: "Equipos", }, frameworks: { title: "Marcos", @@ -550,45 +575,47 @@ export default { status: "Estado", control: "Control", artifacts: "Artefactos", - actions: "Acciones" + actions: "Acciones", }, statuses: { not_started: "No iniciado", compliant: "Cumple", non_compliant: "No cumple", completed: "Completado", - in_progress: "En Progreso" - } + in_progress: "En Progreso", + }, }, overview: { error: "Error al cargar los marcos", loading: "Cargando marcos...", empty: { title: "No se han seleccionado marcos", - description: "Seleccione marcos para comenzar su viaje de cumplimiento" + description: "Seleccione marcos para comenzar su viaje de cumplimiento", }, progress: { title: "Progreso del marco", empty: { title: "Aún no hay marcos", - description: "Comience agregando un marco de cumplimiento para rastrear su progreso", - action: "Agregar marco" - } + description: + "Comience agregando un marco de cumplimiento para rastrear su progreso", + action: "Agregar marco", + }, }, grid: { welcome: { title: "Bienvenido a Comp AI", - description: "Comience seleccionando los marcos de cumplimiento que le gustaría implementar. Le ayudaremos a gestionar y rastrear su viaje de cumplimiento a través de múltiples estándares.", - action: "Comenzar" + description: + "Comience seleccionando los marcos de cumplimiento que le gustaría implementar. Le ayudaremos a gestionar y rastrear su viaje de cumplimiento a través de múltiples estándares.", + action: "Comenzar", }, title: "Seleccionar marcos", version: "Versión", actions: { clear: "Borrar", - confirm: "Confirmar selección" - } - } - } + confirm: "Confirmar selección", + }, + }, + }, }, vendor: { title: "Tablero", @@ -599,8 +626,10 @@ export default { vendor_status: "Estado del proveedor", vendor_category: "Categorías de proveedores", vendors_by_assignee: "Proveedores por asignado", - inherent_risk_description: "Nivel de riesgo inicial antes de aplicar controles", - residual_risk_description: "Nivel de riesgo restante después de aplicar controles" + inherent_risk_description: + "Nivel de riesgo inicial antes de aplicar controles", + residual_risk_description: + "Nivel de riesgo restante después de aplicar controles", }, register: { title: "Registro de proveedores", @@ -608,8 +637,8 @@ export default { name: "Nombre", category: "Categoría", status: "Estado", - owner: "Propietario" - } + owner: "Propietario", + }, }, category: { cloud: "Nube", @@ -619,7 +648,7 @@ export default { marketing: "Marketing", sales: "Ventas", hr: "RRHH", - other: "Otro" + other: "Otro", }, vendors: "proveedores", form: { @@ -644,79 +673,79 @@ export default { contact_role: "Rol del contacto", add_contact: "Agregar contacto", new_contact: "Nuevo contacto", - min_one_contact_required: "Un proveedor debe tener al menos un contacto" + min_one_contact_required: "Un proveedor debe tener al menos un contacto", }, empty_states: { no_vendors: { title: "Aún no hay proveedores", - description: "Comienza creando tu primer proveedor" + description: "Comienza creando tu primer proveedor", }, no_results: { title: "No se encontraron resultados", description: "No hay proveedores que coincidan con tu búsqueda", - description_with_filters: "Intenta ajustar tus filtros" - } - } + description_with_filters: "Intenta ajustar tus filtros", + }, + }, }, people: { title: "Personas", details: { taskProgress: "Progreso de la Tarea", tasks: "Tareas", - noTasks: "Aún no hay tareas asignadas" + noTasks: "Aún no hay tareas asignadas", }, description: "Gestiona a los miembros de tu equipo y sus roles.", filters: { search: "Buscar personas...", - role: "Filtrar por rol" + role: "Filtrar por rol", }, actions: { invite: "Agregar empleado", - clear: "Limpiar filtros" + clear: "Limpiar filtros", }, table: { name: "Nombre", email: "Correo electrónico", department: "Departamento", - externalId: "ID externo" + externalId: "ID externo", }, empty: { no_employees: { title: "Aún no hay empleados", - description: "Comienza invitando a tu primer miembro del equipo." + description: "Comienza invitando a tu primer miembro del equipo.", }, no_results: { title: "No se encontraron resultados", description: "No hay empleados que coincidan con tu búsqueda", - description_with_filters: "Intenta ajustar tus filtros" - } + description_with_filters: "Intenta ajustar tus filtros", + }, }, invite: { title: "Agregar empleado", description: "Agrega un empleado a tu organización.", email: { label: "Dirección de correo electrónico", - placeholder: "Ingresa la dirección de correo electrónico" + placeholder: "Ingresa la dirección de correo electrónico", }, role: { label: "Rol", - placeholder: "Selecciona un rol" + placeholder: "Selecciona un rol", }, name: { label: "Nombre", - placeholder: "Ingresa el nombre" + placeholder: "Ingresa el nombre", }, department: { label: "Departamento", - placeholder: "Selecciona un departamento" + placeholder: "Selecciona un departamento", }, submit: "Agregar empleado", success: "Empleado agregado con éxito", - error: "Error al agregar empleado" - } + error: "Error al agregar empleado", + }, }, errors: { - unexpected: "Algo salió mal, por favor intenta de nuevo" + unexpected: "Algo salió mal, por favor intenta de nuevo", }, sub_pages: { risk: { @@ -725,29 +754,29 @@ export default { risk_overview: "Resumen de Riesgos", risk_comments: "Comentarios sobre Riesgos", tasks: { - task_overview: "Resumen de Tareas" - } + task_overview: "Resumen de Tareas", + }, }, policies: { all: "Todas las Políticas", editor: "Editor de Políticas", - policy_details: "Detalles de la política" + policy_details: "Detalles de la política", }, people: { all: "Personas", - employee_details: "Detalles del Empleado" + employee_details: "Detalles del Empleado", }, settings: { - members: "Miembros del Equipo" + members: "Miembros del Equipo", }, frameworks: { - overview: "Marcos" + overview: "Marcos", }, evidence: { title: "Evidencia", list: "Lista de Evidencias", - overview: "Resumen de Evidencias" - } + overview: "Resumen de Evidencias", + }, }, editor: { ai: { @@ -755,23 +784,25 @@ export default { thinking_spinner: "La IA está pensando", edit_or_generate: "Editar o generar...", tell_ai_what_to_do_next: "Dile a la IA qué hacer a continuación", - request_limit_reached: "Has alcanzado tu límite de solicitudes para el día." + request_limit_reached: + "Has alcanzado tu límite de solicitudes para el día.", }, ai_selector: { improve: "Mejorar la redacción", fix: "Corregir la gramática", shorter: "Hacer más corto", longer: "Hacer más largo", - "continue": "Continuar escribiendo", + continue: "Continuar escribiendo", replace: "Reemplazar selección", insert: "Insertar abajo", - discard: "Descartar" - } + discard: "Descartar", + }, }, evidence: { title: "Tareas de Evidencia", - description: "Gestiona y rastrea las tareas de evidencia para tus requisitos de cumplimiento.", + description: + "Gestiona y rastrea las tareas de evidencia para tus requisitos de cumplimiento.", dashboard: "Tablero", - list: "Todas las Evidencias" - } + list: "Todas las Evidencias", + }, } as const; diff --git a/apps/app/src/locales/fr.ts b/apps/app/src/locales/fr.ts index ed024b0889..556324dd6c 100644 --- a/apps/app/src/locales/fr.ts +++ b/apps/app/src/locales/fr.ts @@ -4,36 +4,36 @@ export default { fr: "Français", no: "Norvégien", pt: "Portugais", - en: "Anglais" + en: "Anglais", }, language: { title: "Langues", description: "Changez la langue utilisée dans l'interface utilisateur.", - placeholder: "Sélectionner la langue" + placeholder: "Sélectionner la langue", }, common: { actions: { save: "Enregistrer", edit: "Modifier", - "delete": "Supprimer", + delete: "Supprimer", cancel: "Annuler", clear: "Effacer", create: "Créer", send: "Envoyer", - "return": "Retourner", + return: "Retourner", success: "Succès", error: "Erreur", next: "Suivant", complete: "Terminer", - addNew: "Ajouter Nouveau" + addNew: "Ajouter Nouveau", }, assignee: { label: "Assigné à", - placeholder: "Sélectionner l'assigné" + placeholder: "Sélectionner l'assigné", }, date: { pick: "Choisir une date", - due_date: "Date d'échéance" + due_date: "Date d'échéance", }, status: { open: "Ouvert", @@ -51,7 +51,7 @@ export default { assessed: "Évalué", active: "Actif", inactive: "Inactif", - title: "Statut" + title: "Statut", }, filters: { clear: "Effacer les filtres", @@ -60,8 +60,8 @@ export default { department: "Département", owner: { label: "Assigné à", - placeholder: "Filtrer par assigné" - } + placeholder: "Filtrer par assigné", + }, }, table: { title: "Titre", @@ -69,7 +69,7 @@ export default { assigned_to: "Assigné à", due_date: "Date d'échéance", last_updated: "Dernière mise à jour", - no_results: "Aucun résultat trouvé" + no_results: "Aucun résultat trouvé", }, empty_states: { no_results: { @@ -77,14 +77,15 @@ export default { title_tasks: "Aucune tâche trouvée", title_risks: "Aucun risque trouvé", description: "Essayez une autre recherche ou ajustez les filtres", - description_filters: "Essayez une autre recherche ou ajustez les filtres", + description_filters: + "Essayez une autre recherche ou ajustez les filtres", description_no_tasks: "Créez une tâche pour commencer", - description_no_risks: "Créez un risque pour commencer" + description_no_risks: "Créez un risque pour commencer", }, no_items: { title: "Aucun élément trouvé", - description: "Essayez d'ajuster votre recherche ou vos filtres" - } + description: "Essayez d'ajuster votre recherche ou vos filtres", + }, }, pagination: { of: "de", @@ -94,60 +95,69 @@ export default { go_to_first_page: "Aller à la première page", go_to_previous_page: "Aller à la page précédente", go_to_next_page: "Aller à la page suivante", - go_to_last_page: "Aller à la dernière page" + go_to_last_page: "Aller à la dernière page", }, comments: { title: "Commentaires", - description: "Ajoutez un commentaire en utilisant le formulaire ci-dessous.", + description: + "Ajoutez un commentaire en utilisant le formulaire ci-dessous.", add: "Nouveau commentaire", - "new": "Nouveau commentaire", + new: "Nouveau commentaire", save: "Enregistrer le commentaire", success: "Commentaire ajouté avec succès", error: "Échec de l'ajout du commentaire", placeholder: "Écrivez votre commentaire ici...", empty: { title: "Aucun commentaire pour le moment", - description: "Soyez le premier à ajouter un commentaire" - } + description: "Soyez le premier à ajouter un commentaire", + }, }, attachments: { title: "Pièces jointes", - description: "Ajoutez un fichier en cliquant sur 'Ajouter une pièce jointe'.", + description: + "Ajoutez un fichier en cliquant sur 'Ajouter une pièce jointe'.", upload: "Télécharger une pièce jointe", - upload_description: "Téléchargez une pièce jointe ou ajoutez un lien vers une ressource externe.", + upload_description: + "Téléchargez une pièce jointe ou ajoutez un lien vers une ressource externe.", drop: "Déposez les fichiers ici", - drop_description: "Déposez des fichiers ici ou cliquez pour choisir des fichiers sur votre appareil.", + drop_description: + "Déposez des fichiers ici ou cliquez pour choisir des fichiers sur votre appareil.", drop_files_description: "Les fichiers peuvent aller jusqu'à ", empty: { title: "Aucune pièce jointe", - description: "Ajoutez un fichier en cliquant sur 'Ajouter une pièce jointe'." + description: + "Ajoutez un fichier en cliquant sur 'Ajouter une pièce jointe'.", }, toasts: { error: "Une erreur s'est produite, veuillez réessayer.", - error_uploading_files: "Impossible de télécharger plus d'un fichier à la fois", - error_uploading_files_multiple: "Impossible de télécharger plus de 10 fichiers", + error_uploading_files: + "Impossible de télécharger plus d'un fichier à la fois", + error_uploading_files_multiple: + "Impossible de télécharger plus de 10 fichiers", error_no_files_selected: "Aucun fichier sélectionné", error_file_rejected: "Le fichier {file} a été rejeté", error_failed_to_upload_files: "Échec du téléchargement des fichiers", - error_failed_to_upload_files_multiple: "Échec du téléchargement des fichiers", - error_failed_to_upload_files_single: "Échec du téléchargement du fichier", + error_failed_to_upload_files_multiple: + "Échec du téléchargement des fichiers", + error_failed_to_upload_files_single: + "Échec du téléchargement du fichier", success_uploading_files: "Fichiers téléchargés avec succès", success_uploading_files_multiple: "Fichiers téléchargés avec succès", success_uploading_files_single: "Fichier téléchargé avec succès", success_uploading_files_target: "Fichiers téléchargés", uploading_files: "Téléchargement de {target}...", - remove_file: "Supprimer le fichier" - } + remove_file: "Supprimer le fichier", + }, }, notifications: { inbox: "Boîte de réception", archive: "Archive", archive_all: "Archiver tout", - no_notifications: "Aucune nouvelle notification" + no_notifications: "Aucune nouvelle notification", }, edit: "Modifier", errors: { - unexpected_error: "Une erreur inattendue est survenue" + unexpected_error: "Une erreur inattendue est survenue", }, description: "Description", last_updated: "Dernière mise à jour", @@ -156,34 +166,35 @@ export default { weekly: "Hebdomadaire", monthly: "Mensuel", quarterly: "Trimestriel", - yearly: "Annuel" - } + yearly: "Annuel", + }, }, header: { discord: { - button: "Rejoignez-nous sur Discord" + button: "Rejoignez-nous sur Discord", }, feedback: { button: "Retour d'information", title: "Merci pour vos retours !", description: "Nous reviendrons vers vous dès que possible", - placeholder: "Idées pour améliorer cette page ou problèmes que vous rencontrez.", + placeholder: + "Idées pour améliorer cette page ou problèmes que vous rencontrez.", success: "Merci pour vos retours !", error: "Erreur lors de l'envoi du retour - réessayer ?", - send: "Envoyer un retour" - } + send: "Envoyer un retour", + }, }, not_found: { title: "404 - Page non trouvée", description: "La page que vous recherchez n'existe pas.", - "return": "Retour au tableau de bord" + return: "Retour au tableau de bord", }, theme: { options: { light: "Clair", dark: "Sombre", - system: "Système" - } + system: "Système", + }, }, sidebar: { overview: "Aperçu", @@ -193,11 +204,12 @@ export default { integrations: "Intégrations", settings: "Paramètres", evidence: "Tâches de preuve", - people: "Personnes" + people: "Personnes", }, auth: { title: "Automatisez la conformité SOC 2, ISO 27001 et RGPD avec l'IA.", - description: "Créez un compte gratuit ou connectez-vous avec un compte existant pour continuer.", + description: + "Créez un compte gratuit ou connectez-vous avec un compte existant pour continuer.", options: "Plus d'options", google: "Continuer avec Google", email: { @@ -205,12 +217,14 @@ export default { placeholder: "Entrez l'adresse e-mail", button: "Continuer avec l'e-mail", magic_link_sent: "Lien magique envoyé", - magic_link_description: "Vérifiez votre boîte de réception pour un lien magique.", + magic_link_description: + "Vérifiez votre boîte de réception pour un lien magique.", magic_link_try_again: "Réessayer.", success: "E-mail envoyé - vérifiez votre boîte de réception !", - error: "Erreur lors de l'envoi de l'e-mail - réessayer ?" + error: "Erreur lors de l'envoi de l'e-mail - réessayer ?", }, - terms: "En cliquant sur continuer, vous reconnaissez avoir lu et accepté les Conditions d'utilisation et la Politique de confidentialité." + terms: + "En cliquant sur continuer, vous reconnaissez avoir lu et accepté les Conditions d'utilisation et la Politique de confidentialité.", }, onboarding: { title: "Créer une organisation", @@ -219,35 +233,35 @@ export default { fields: { name: { label: "Nom de l'organisation", - placeholder: "Le nom de votre organisation" + placeholder: "Le nom de votre organisation", }, website: { label: "Site Web", - placeholder: "Le site Web de votre organisation" + placeholder: "Le site Web de votre organisation", }, subdomain: { label: "Sous-domaine", - placeholder: "exemple" + placeholder: "exemple", }, fullName: { label: "Votre Nom", - placeholder: "Votre nom complet" - } + placeholder: "Votre nom complet", + }, }, success: "Merci, vous êtes prêt !", error: "Une erreur s'est produite, veuillez réessayer.", unavailable: "Indisponible", check_availability: "Vérification de la disponibilité", - available: "Disponible" + available: "Disponible", }, overview: { title: "Aperçu", framework_chart: { - title: "Progrès du cadre" + title: "Progrès du cadre", }, requirement_chart: { - title: "État de conformité" - } + title: "État de conformité", + }, }, policies: { dashboard: { @@ -258,32 +272,32 @@ export default { policies_by_framework: "Politiques par cadre", sub_pages: { overview: "Aperçu", - edit_policy: "Modifier la politique" - } + edit_policy: "Modifier la politique", + }, }, table: { name: "Nom de la politique", statuses: { draft: "Brouillon", published: "Publié", - archived: "Archivé" + archived: "Archivé", }, filters: { owner: { label: "Responsable", - placeholder: "Filtrer par responsable" - } - } + placeholder: "Filtrer par responsable", + }, + }, }, filters: { search: "Rechercher des politiques...", - all: "Toutes les politiques" + all: "Toutes les politiques", }, status: { draft: "Brouillon", published: "Publié", needs_review: "Nécessite une révision", - archived: "Archivé" + archived: "Archivé", }, policies: "politiques", title: "Politiques", @@ -304,20 +318,21 @@ export default { title: "Aperçu de la Politique", form: { update_policy: "Mettre à jour la Politique", - update_policy_description: "Mettez à jour le titre ou la description de la politique.", + update_policy_description: + "Mettez à jour le titre ou la description de la politique.", update_policy_success: "Politique mise à jour avec succès", update_policy_error: "Échec de la mise à jour de la politique", update_policy_title: "Nom de la Politique", review_frequency: "Fréquence de Révision", review_frequency_placeholder: "Sélectionnez une fréquence de révision", review_date: "Date de Révision", - review_date_placeholder: "Sélectionnez une date de révision" - } - } + review_date_placeholder: "Sélectionnez une date de révision", + }, + }, }, evidence_tasks: { evidence_tasks: "Tâches de preuve", - overview: "Aperçu" + overview: "Aperçu", }, risk: { risks: "risques", @@ -331,8 +346,10 @@ export default { vendor_status: "État du fournisseur", vendor_category: "Catégories de fournisseurs", vendors_by_assignee: "Fournisseurs par responsable", - inherent_risk_description: "Niveau de risque initial avant l'application de tout contrôle", - residual_risk_description: "Niveau de risque restant après l'application des contrôles" + inherent_risk_description: + "Niveau de risque initial avant l'application de tout contrôle", + residual_risk_description: + "Niveau de risque restant après l'application des contrôles", }, register: { title: "Registre des fournisseurs", @@ -340,15 +357,17 @@ export default { name: "Nom", category: "Catégorie", status: "Statut", - owner: "Propriétaire" - } + owner: "Propriétaire", + }, }, assessment: { title: "Évaluation des fournisseurs", - update_success: "Évaluation du risque fournisseur mise à jour avec succès", - update_error: "Échec de la mise à jour de l'évaluation du risque fournisseur", + update_success: + "Évaluation du risque fournisseur mise à jour avec succès", + update_error: + "Échec de la mise à jour de l'évaluation du risque fournisseur", inherent_risk: "Risque inhérent", - residual_risk: "Risque résiduel" + residual_risk: "Risque résiduel", }, form: { vendor_details: "Détails du fournisseur", @@ -367,38 +386,38 @@ export default { update_vendor: "Mettre à jour le fournisseur", update_vendor_success: "Fournisseur mis à jour avec succès", update_vendor_error: "Échec de la mise à jour du fournisseur", - add_comment: "Ajouter un commentaire" + add_comment: "Ajouter un commentaire", }, table: { name: "Nom", category: "Catégorie", status: "Statut", - owner: "Propriétaire" + owner: "Propriétaire", }, filters: { search_placeholder: "Rechercher des fournisseurs...", status_placeholder: "Filtrer par statut", category_placeholder: "Filtrer par catégorie", - owner_placeholder: "Filtrer par propriétaire" + owner_placeholder: "Filtrer par propriétaire", }, empty_states: { no_vendors: { title: "Aucun fournisseur pour le moment", - description: "Commencez par créer votre premier fournisseur" + description: "Commencez par créer votre premier fournisseur", }, no_results: { title: "Aucun résultat trouvé", description: "Aucun fournisseur ne correspond à votre recherche", - description_with_filters: "Essayez d'ajuster vos filtres" - } + description_with_filters: "Essayez d'ajuster vos filtres", + }, }, actions: { - create: "Créer un fournisseur" + create: "Créer un fournisseur", }, status: { not_assessed: "Non évalué", in_progress: "En cours", - assessed: "Évalué" + assessed: "Évalué", }, category: { cloud: "Cloud", @@ -408,14 +427,14 @@ export default { marketing: "Marketing", sales: "Ventes", hr: "Ressources humaines", - other: "Autre" + other: "Autre", }, risk_level: { low: "Risque faible", medium: "Risque moyen", high: "Risque élevé", - unknown: "Risque inconnu" - } + unknown: "Risque inconnu", + }, }, dashboard: { title: "Tableau de bord", @@ -423,40 +442,47 @@ export default { risk_status: "Statut des risques", risks_by_department: "Risques par département", risks_by_assignee: "Risques par responsable", - inherent_risk_description: "Le risque inhérent est calculé comme probabilité * impact. Calculé avant l'application de tout contrôle.", - residual_risk_description: "Le risque résiduel est calculé comme probabilité * impact. C'est le niveau de risque après l'application des contrôles.", - risk_assessment_description: "Comparer les niveaux de risque inhérent et résiduel" + inherent_risk_description: + "Le risque inhérent est calculé comme probabilité * impact. Calculé avant l'application de tout contrôle.", + residual_risk_description: + "Le risque résiduel est calculé comme probabilité * impact. C'est le niveau de risque après l'application des contrôles.", + risk_assessment_description: + "Comparer les niveaux de risque inhérent et résiduel", }, register: { title: "Registre des risques", table: { - risk: "Risque" + risk: "Risque", }, empty: { no_risks: { title: "Créez un risque pour commencer", - description: "Suivez et évaluez les risques, créez et assignez des tâches d'atténuation à votre équipe, et gérez votre registre des risques dans une interface simple." + description: + "Suivez et évaluez les risques, créez et assignez des tâches d'atténuation à votre équipe, et gérez votre registre des risques dans une interface simple.", }, - create_risk: "Créer un risque" - } + create_risk: "Créer un risque", + }, }, metrics: { probability: "Probabilité", impact: "Impact", inherentRisk: "Risque inhérent", - residualRisk: "Risque résiduel" + residualRisk: "Risque résiduel", }, form: { update_inherent_risk: "Enregistrer le risque inhérent", - update_inherent_risk_description: "Mettez à jour le risque inhérent du risque. C'est le niveau de risque avant l'application de tout contrôle.", + update_inherent_risk_description: + "Mettez à jour le risque inhérent du risque. C'est le niveau de risque avant l'application de tout contrôle.", update_inherent_risk_success: "Risque inhérent mis à jour avec succès", update_inherent_risk_error: "Échec de la mise à jour du risque inhérent", update_residual_risk: "Enregistrer le risque résiduel", - update_residual_risk_description: "Mettez à jour le risque résiduel du risque. C'est le niveau de risque après l'application des contrôles.", + update_residual_risk_description: + "Mettez à jour le risque résiduel du risque. C'est le niveau de risque après l'application des contrôles.", update_residual_risk_success: "Risque résiduel mis à jour avec succès", update_residual_risk_error: "Échec de la mise à jour du risque résiduel", update_risk: "Mettre à jour le risque", - update_risk_description: "Mettez à jour le titre ou la description du risque.", + update_risk_description: + "Mettez à jour le titre ou la description du risque.", update_risk_success: "Risque mis à jour avec succès", update_risk_error: "Échec de la mise à jour du risque", create_risk_success: "Risque créé avec succès", @@ -471,7 +497,7 @@ export default { risk_department: "Département", risk_department_placeholder: "Sélectionnez un département", risk_status: "Statut du risque", - risk_status_placeholder: "Sélectionnez un statut de risque" + risk_status_placeholder: "Sélectionnez un statut de risque", }, tasks: { title: "Tâches", @@ -488,33 +514,40 @@ export default { due_date: "Date d'échéance", due_date_description: "Sélectionnez la date d'échéance pour la tâche", success: "Tâche créée avec succès", - error: "Échec de la création de la tâche" + error: "Échec de la création de la tâche", }, sheet: { title: "Créer une tâche", update: "Mettre à jour la tâche", - update_description: "Mettez à jour le titre ou la description de la tâche." + update_description: + "Mettez à jour le titre ou la description de la tâche.", }, empty: { - description_create: "Créez une tâche d'atténuation pour ce risque, ajoutez un plan de traitement et assignez-le à un membre de l'équipe." - } - } + description_create: + "Créez une tâche d'atténuation pour ce risque, ajoutez un plan de traitement et assignez-le à un membre de l'équipe.", + }, + }, }, settings: { general: { title: "Général", org_name: "Nom de l'organisation", - org_name_description: "Ceci est le nom visible de votre organisation. Vous devez utiliser le nom légal de votre organisation.", + org_name_description: + "Ceci est le nom visible de votre organisation. Vous devez utiliser le nom légal de votre organisation.", org_name_tip: "Veuillez utiliser un maximum de 32 caractères.", org_website: "Site Web de l'organisation", - org_website_description: "Ceci est l'URL du site Web officiel de votre organisation. Assurez-vous d'inclure l'URL complète avec https://.", + org_website_description: + "Ceci est l'URL du site Web officiel de votre organisation. Assurez-vous d'inclure l'URL complète avec https://.", org_website_tip: "Veuillez entrer une URL valide incluant https://", - org_website_error: "Erreur lors de la mise à jour du site Web de l'organisation", + org_website_error: + "Erreur lors de la mise à jour du site Web de l'organisation", org_website_updated: "Site Web de l'organisation mis à jour", org_delete: "Supprimer l'organisation", - org_delete_description: "Supprimez définitivement votre organisation et tout son contenu de la plateforme Comp AI. Cette action n'est pas réversible - veuillez continuer avec prudence.", + org_delete_description: + "Supprimez définitivement votre organisation et tout son contenu de la plateforme Comp AI. Cette action n'est pas réversible - veuillez continuer avec prudence.", org_delete_alert_title: "Êtes-vous absolument sûr ?", - org_delete_alert_description: "Cette action ne peut pas être annulée. Cela supprimera définitivement votre organisation et retirera vos données de nos serveurs.", + org_delete_alert_description: + "Cette action ne peut pas être annulée. Cela supprimera définitivement votre organisation et retirera vos données de nos serveurs.", org_delete_error: "Erreur lors de la suppression de l'organisation", org_delete_success: "Organisation supprimée", org_name_updated: "Nom de l'organisation mis à jour", @@ -523,14 +556,14 @@ export default { delete_button: "Supprimer", delete_confirm: "SUPPRIMER", delete_confirm_tip: "Tapez SUPPRIMER pour confirmer.", - cancel_button: "Annuler" + cancel_button: "Annuler", }, members: { - title: "Membres" + title: "Membres", }, billing: { - title: "Facturation" - } + title: "Facturation", + }, }, user_menu: { theme: "Thème", @@ -539,7 +572,7 @@ export default { account: "Compte", support: "Support", settings: "Paramètres", - teams: "Équipes" + teams: "Équipes", }, frameworks: { title: "Cadres", @@ -550,45 +583,48 @@ export default { status: "Statut", control: "Contrôle", artifacts: "Artifacts", - actions: "Actions" + actions: "Actions", }, statuses: { not_started: "Non commencé", compliant: "Conforme", non_compliant: "Non conforme", completed: "Terminé", - in_progress: "En cours" - } + in_progress: "En cours", + }, }, overview: { error: "Échec du chargement des cadres", loading: "Chargement des cadres...", empty: { title: "Aucun cadre sélectionné", - description: "Sélectionnez des cadres pour commencer votre parcours de conformité" + description: + "Sélectionnez des cadres pour commencer votre parcours de conformité", }, progress: { title: "Progression du cadre", empty: { title: "Aucun cadre pour le moment", - description: "Commencez par ajouter un cadre de conformité pour suivre vos progrès", - action: "Ajouter un cadre" - } + description: + "Commencez par ajouter un cadre de conformité pour suivre vos progrès", + action: "Ajouter un cadre", + }, }, grid: { welcome: { title: "Bienvenue dans Comp AI", - description: "Commencez par sélectionner les cadres de conformité que vous souhaitez mettre en œuvre. Nous vous aiderons à gérer et à suivre votre parcours de conformité à travers plusieurs normes.", - action: "Commencer" + description: + "Commencez par sélectionner les cadres de conformité que vous souhaitez mettre en œuvre. Nous vous aiderons à gérer et à suivre votre parcours de conformité à travers plusieurs normes.", + action: "Commencer", }, title: "Sélectionner des cadres", version: "Version", actions: { clear: "Effacer", - confirm: "Confirmer la sélection" - } - } - } + confirm: "Confirmer la sélection", + }, + }, + }, }, vendor: { title: "Tableau de bord", @@ -599,8 +635,10 @@ export default { vendor_status: "Statut des fournisseurs", vendor_category: "Catégories de fournisseurs", vendors_by_assignee: "Fournisseurs par responsable", - inherent_risk_description: "Niveau de risque initial avant l'application de tout contrôle", - residual_risk_description: "Niveau de risque restant après l'application des contrôles" + inherent_risk_description: + "Niveau de risque initial avant l'application de tout contrôle", + residual_risk_description: + "Niveau de risque restant après l'application des contrôles", }, register: { title: "Registre des fournisseurs", @@ -608,8 +646,8 @@ export default { name: "Nom", category: "Catégorie", status: "Statut", - owner: "Propriétaire" - } + owner: "Propriétaire", + }, }, category: { cloud: "Cloud", @@ -619,7 +657,7 @@ export default { marketing: "Marketing", sales: "Ventes", hr: "RH", - other: "Autre" + other: "Autre", }, vendors: "fournisseurs", form: { @@ -644,79 +682,79 @@ export default { contact_role: "Rôle du contact", add_contact: "Ajouter un contact", new_contact: "Nouveau contact", - min_one_contact_required: "Un fournisseur doit avoir au moins un contact" + min_one_contact_required: "Un fournisseur doit avoir au moins un contact", }, empty_states: { no_vendors: { title: "Aucun fournisseur pour le moment", - description: "Commencez par créer votre premier fournisseur" + description: "Commencez par créer votre premier fournisseur", }, no_results: { title: "Aucun résultat trouvé", description: "Aucun fournisseur ne correspond à votre recherche", - description_with_filters: "Essayez d'ajuster vos filtres" - } - } + description_with_filters: "Essayez d'ajuster vos filtres", + }, + }, }, people: { title: "Personnes", details: { taskProgress: "Progression des tâches", tasks: "Tâches", - noTasks: "Aucune tâche assignée pour le moment" + noTasks: "Aucune tâche assignée pour le moment", }, description: "Gérez vos membres d'équipe et leurs rôles.", filters: { search: "Rechercher des personnes...", - role: "Filtrer par rôle" + role: "Filtrer par rôle", }, actions: { invite: "Ajouter un employé", - clear: "Effacer les filtres" + clear: "Effacer les filtres", }, table: { name: "Nom", email: "Email", department: "Département", - externalId: "ID externe" + externalId: "ID externe", }, empty: { no_employees: { title: "Aucun employé pour le moment", - description: "Commencez par inviter votre premier membre d'équipe." + description: "Commencez par inviter votre premier membre d'équipe.", }, no_results: { title: "Aucun résultat trouvé", description: "Aucun employé ne correspond à votre recherche", - description_with_filters: "Essayez d'ajuster vos filtres" - } + description_with_filters: "Essayez d'ajuster vos filtres", + }, }, invite: { title: "Ajouter un employé", description: "Ajoutez un employé à votre organisation.", email: { label: "Adresse e-mail", - placeholder: "Entrez l'adresse e-mail" + placeholder: "Entrez l'adresse e-mail", }, role: { label: "Rôle", - placeholder: "Sélectionnez un rôle" + placeholder: "Sélectionnez un rôle", }, name: { label: "Nom", - placeholder: "Entrez le nom" + placeholder: "Entrez le nom", }, department: { label: "Département", - placeholder: "Sélectionnez un département" + placeholder: "Sélectionnez un département", }, submit: "Ajouter un employé", success: "Employé ajouté avec succès", - error: "Échec de l'ajout de l'employé" - } + error: "Échec de l'ajout de l'employé", + }, }, errors: { - unexpected: "Une erreur s'est produite, veuillez réessayer" + unexpected: "Une erreur s'est produite, veuillez réessayer", }, sub_pages: { risk: { @@ -725,29 +763,29 @@ export default { risk_overview: "Aperçu des Risques", risk_comments: "Commentaires sur les Risques", tasks: { - task_overview: "Aperçu des Tâches" - } + task_overview: "Aperçu des Tâches", + }, }, policies: { all: "Toutes les Politiques", editor: "Éditeur de Politique", - policy_details: "Détails de la politique" + policy_details: "Détails de la politique", }, people: { all: "Personnes", - employee_details: "Détails de l'Employé" + employee_details: "Détails de l'Employé", }, settings: { - members: "Membres de l'Équipe" + members: "Membres de l'Équipe", }, frameworks: { - overview: "Cadres" + overview: "Cadres", }, evidence: { title: "Preuve", list: "Liste des preuves", - overview: "Aperçu des preuves" - } + overview: "Aperçu des preuves", + }, }, editor: { ai: { @@ -755,23 +793,25 @@ export default { thinking_spinner: "L'IA réfléchit", edit_or_generate: "Modifier ou générer...", tell_ai_what_to_do_next: "Dites à l'IA quoi faire ensuite", - request_limit_reached: "Vous avez atteint votre limite de demandes pour la journée." + request_limit_reached: + "Vous avez atteint votre limite de demandes pour la journée.", }, ai_selector: { improve: "Améliorer l'écriture", fix: "Corriger la grammaire", shorter: "Rendre plus court", longer: "Rendre plus long", - "continue": "Continuer à écrire", + continue: "Continuer à écrire", replace: "Remplacer la sélection", insert: "Insérer ci-dessous", - discard: "Jeter" - } + discard: "Jeter", + }, }, evidence: { title: "Tâches de preuve", - description: "Gérez et suivez les tâches de preuve pour vos exigences de conformité.", + description: + "Gérez et suivez les tâches de preuve pour vos exigences de conformité.", dashboard: "Tableau de bord", - list: "Toutes les preuves" - } + list: "Toutes les preuves", + }, } as const; diff --git a/apps/app/src/locales/no.ts b/apps/app/src/locales/no.ts index ef6c3d6063..2bbb791d8d 100644 --- a/apps/app/src/locales/no.ts +++ b/apps/app/src/locales/no.ts @@ -4,36 +4,36 @@ export default { fr: "Fransk", no: "Norsk", pt: "Portugisisk", - en: "Engelsk" + en: "Engelsk", }, language: { title: "Språk", description: "Endre språket som brukes i brukergrensesnittet.", - placeholder: "Velg språk" + placeholder: "Velg språk", }, common: { actions: { save: "Lagre", edit: "Rediger", - "delete": "Slett", + delete: "Slett", cancel: "Avbryt", clear: "Tøm", create: "Opprett", send: "Send", - "return": "Tilbake", + return: "Tilbake", success: "Suksess", error: "Feil", next: "Neste", complete: "Fullfør", - addNew: "Legg til ny" + addNew: "Legg til ny", }, assignee: { label: "Tildelt", - placeholder: "Velg tildelt" + placeholder: "Velg tildelt", }, date: { pick: "Velg en dato", - due_date: "Forfallsdato" + due_date: "Forfallsdato", }, status: { open: "Åpen", @@ -51,7 +51,7 @@ export default { assessed: "Vurdert", active: "Aktiv", inactive: "Inaktiv", - title: "Status" + title: "Status", }, filters: { clear: "Tøm filtre", @@ -60,8 +60,8 @@ export default { department: "Avdeling", owner: { label: "Tildelt", - placeholder: "Filtrer etter tildelt" - } + placeholder: "Filtrer etter tildelt", + }, }, table: { title: "Tittel", @@ -69,7 +69,7 @@ export default { assigned_to: "Tildelt Til", due_date: "Forfallsdato", last_updated: "Sist oppdatert", - no_results: "Ingen resultater funnet" + no_results: "Ingen resultater funnet", }, empty_states: { no_results: { @@ -79,12 +79,12 @@ export default { description: "Prøv et annet søk, eller juster filtrene", description_filters: "Prøv et annet søk, eller juster filtrene", description_no_tasks: "Opprett en oppgave for å komme i gang", - description_no_risks: "Opprett en risiko for å komme i gang" + description_no_risks: "Opprett en risiko for å komme i gang", }, no_items: { title: "Ingen elementer funnet", - description: "Prøv å justere søket eller filtrene" - } + description: "Prøv å justere søket eller filtrene", + }, }, pagination: { of: "av", @@ -94,33 +94,35 @@ export default { go_to_first_page: "Gå til første side", go_to_previous_page: "Gå til forrige side", go_to_next_page: "Gå til neste side", - go_to_last_page: "Gå til siste side" + go_to_last_page: "Gå til siste side", }, comments: { title: "Kommentarer", description: "Legg til en kommentar ved å bruke skjemaet nedenfor.", add: "Ny kommentar", - "new": "Ny kommentar", + new: "Ny kommentar", save: "Lagre kommentar", success: "Kommentar lagt til", error: "Kunne ikke legge til kommentar", placeholder: "Skriv din kommentar her...", empty: { title: "Ingen kommentarer ennå", - description: "Vær den første til å legge til en kommentar" - } + description: "Vær den første til å legge til en kommentar", + }, }, attachments: { title: "Vedlegg", description: "Legg til en fil ved å klikke på 'Legg til vedlegg'.", upload: "Last opp vedlegg", - upload_description: "Last opp et vedlegg eller legg til en lenke til en ekstern ressurs.", + upload_description: + "Last opp et vedlegg eller legg til en lenke til en ekstern ressurs.", drop: "Slipp filene her", - drop_description: "Slipp filer her eller klikk for å velge filer fra enheten din.", + drop_description: + "Slipp filer her eller klikk for å velge filer fra enheten din.", drop_files_description: "Filer kan være opptil ", empty: { title: "Ingen vedlegg", - description: "Legg til en fil ved å klikke på 'Legg til vedlegg'." + description: "Legg til en fil ved å klikke på 'Legg til vedlegg'.", }, toasts: { error: "Noe gikk galt, vennligst prøv igjen.", @@ -136,18 +138,18 @@ export default { success_uploading_files_single: "Fil lastet opp", success_uploading_files_target: "Filer lastet opp", uploading_files: "Laster opp {target}...", - remove_file: "Fjern fil" - } + remove_file: "Fjern fil", + }, }, notifications: { inbox: "Innboks", archive: "Arkiv", archive_all: "Arkiver alt", - no_notifications: "Ingen nye varsler" + no_notifications: "Ingen nye varsler", }, edit: "Rediger", errors: { - unexpected_error: "En uventet feil oppstod" + unexpected_error: "En uventet feil oppstod", }, description: "Beskrivelse", last_updated: "Sist oppdatert", @@ -156,34 +158,35 @@ export default { weekly: "Ukentlig", monthly: "Månedlig", quarterly: "Kvartalsvis", - yearly: "Årlig" - } + yearly: "Årlig", + }, }, header: { discord: { - button: "Bli med oss på Discord" + button: "Bli med oss på Discord", }, feedback: { button: "Tilbakemelding", title: "Takk for tilbakemeldingen!", description: "Vi kommer tilbake til deg så snart som mulig", - placeholder: "Ideer for å forbedre denne siden eller problemer du opplever.", + placeholder: + "Ideer for å forbedre denne siden eller problemer du opplever.", success: "Takk for tilbakemeldingen!", error: "Feil ved sending av tilbakemelding - prøv igjen?", - send: "Send tilbakemelding" - } + send: "Send tilbakemelding", + }, }, not_found: { title: "404 - Siden ble ikke funnet", description: "Siden du leter etter eksisterer ikke.", - "return": "Gå tilbake til dashbordet" + return: "Gå tilbake til dashbordet", }, theme: { options: { light: "Lys", dark: "Mørk", - system: "System" - } + system: "System", + }, }, sidebar: { overview: "Oversikt", @@ -193,11 +196,12 @@ export default { integrations: "Integrasjoner", settings: "Innstillinger", evidence: "Bevisoppgaver", - people: "Personer" + people: "Personer", }, auth: { title: "Automatiser SOC 2, ISO 27001 og GDPR-overholdelse med AI.", - description: "Opprett en gratis konto eller logg inn med en eksisterende konto for å fortsette.", + description: + "Opprett en gratis konto eller logg inn med en eksisterende konto for å fortsette.", options: "Flere alternativer", google: "Fortsett med Google", email: { @@ -208,9 +212,10 @@ export default { magic_link_description: "Sjekk innboksen din for en magisk lenke.", magic_link_try_again: "Prøv igjen.", success: "E-post sendt - sjekk innboksen din!", - error: "Feil ved sending av e-post - prøv igjen?" + error: "Feil ved sending av e-post - prøv igjen?", }, - terms: "Ved å klikke på fortsett, bekrefter du at du har lest og godtar vilkårene for bruk og personvernerklæringen." + terms: + "Ved å klikke på fortsett, bekrefter du at du har lest og godtar vilkårene for bruk og personvernerklæringen.", }, onboarding: { title: "Opprett en organisasjon", @@ -219,35 +224,35 @@ export default { fields: { name: { label: "Organisasjonsnavn", - placeholder: "Ditt organisasjonsnavn" + placeholder: "Ditt organisasjonsnavn", }, website: { label: "Nettsted", - placeholder: "Ditt organisasjonsnettsted" + placeholder: "Ditt organisasjonsnettsted", }, subdomain: { label: "Underdomene", - placeholder: "eksempel" + placeholder: "eksempel", }, fullName: { label: "Ditt navn", - placeholder: "Ditt fulle navn" - } + placeholder: "Ditt fulle navn", + }, }, success: "Takk, du er klar!", error: "Noe gikk galt, vennligst prøv igjen.", unavailable: "Ikke tilgjengelig", check_availability: "Sjekker tilgjengelighet", - available: "Tilgjengelig" + available: "Tilgjengelig", }, overview: { title: "Oversikt", framework_chart: { - title: "Rammeverk Fremdrift" + title: "Rammeverk Fremdrift", }, requirement_chart: { - title: "Overholdelsesstatus" - } + title: "Overholdelsesstatus", + }, }, policies: { dashboard: { @@ -258,32 +263,32 @@ export default { policies_by_framework: "Retningslinjer etter rammeverk", sub_pages: { overview: "Oversikt", - edit_policy: "Rediger policy" - } + edit_policy: "Rediger policy", + }, }, table: { name: "Retningslinjenavn", statuses: { draft: "Utkast", published: "Publisert", - archived: "Arkivert" + archived: "Arkivert", }, filters: { owner: { label: "Tildelt", - placeholder: "Filtrer etter tildelt" - } - } + placeholder: "Filtrer etter tildelt", + }, + }, }, filters: { search: "Søk etter retningslinjer...", - all: "Alle retningslinjer" + all: "Alle retningslinjer", }, status: { draft: "Utkast", published: "Publisert", needs_review: "Trenger gjennomgang", - archived: "Arkivert" + archived: "Arkivert", }, policies: "retningslinjer", title: "Retningslinjer", @@ -292,7 +297,8 @@ export default { status_filter: "Filtrer etter status", all_statuses: "Alle statuser", no_policies_title: "Ingen retningslinjer ennå", - no_policies_description: "Kom i gang med å opprette din første retningslinje", + no_policies_description: + "Kom i gang med å opprette din første retningslinje", create_first: "Opprett første retningslinje", no_description: "Ingen beskrivelse gitt", last_updated: "Sist oppdatert: {{date}}", @@ -304,20 +310,21 @@ export default { title: "Oversikt over policy", form: { update_policy: "Oppdater policy", - update_policy_description: "Oppdater policyens tittel eller beskrivelse.", + update_policy_description: + "Oppdater policyens tittel eller beskrivelse.", update_policy_success: "Policy oppdatert vellykket", update_policy_error: "Feil ved oppdatering av policy", update_policy_title: "Policy navn", review_frequency: "Gjennomgangsfrekvens", review_frequency_placeholder: "Velg en gjennomgangsfrekvens", review_date: "Gjennomgangsdato", - review_date_placeholder: "Velg en gjennomgangsdato" - } - } + review_date_placeholder: "Velg en gjennomgangsdato", + }, + }, }, evidence_tasks: { evidence_tasks: "Bevisoppgaver", - overview: "Oversikt" + overview: "Oversikt", }, risk: { risks: "risikoer", @@ -331,8 +338,10 @@ export default { vendor_status: "Leverandørstatus", vendor_category: "Leverandørkategorier", vendors_by_assignee: "Leverandører etter tildelt", - inherent_risk_description: "Innledende risikonivå før noen kontroller er anvendt", - residual_risk_description: "Gjenstående risikonivå etter at kontroller er anvendt" + inherent_risk_description: + "Innledende risikonivå før noen kontroller er anvendt", + residual_risk_description: + "Gjenstående risikonivå etter at kontroller er anvendt", }, register: { title: "Leverandørregister", @@ -340,15 +349,15 @@ export default { name: "Navn", category: "Kategori", status: "Status", - owner: "Eier" - } + owner: "Eier", + }, }, assessment: { title: "Leverandørvurdering", update_success: "Leverandørvurdering oppdatert vellykket", update_error: "Feil ved oppdatering av leverandørvurdering", inherent_risk: "Inherent risiko", - residual_risk: "Gjenstående risiko" + residual_risk: "Gjenstående risiko", }, form: { vendor_details: "Leverandørdetaljer", @@ -367,38 +376,38 @@ export default { update_vendor: "Oppdater Leverandør", update_vendor_success: "Leverandør oppdatert", update_vendor_error: "Kunne ikke oppdatere leverandør", - add_comment: "Legg til Kommentar" + add_comment: "Legg til Kommentar", }, table: { name: "Navn", category: "Kategori", status: "Status", - owner: "Eier" + owner: "Eier", }, filters: { search_placeholder: "Søk etter leverandører...", status_placeholder: "Filtrer etter status", category_placeholder: "Filtrer etter kategori", - owner_placeholder: "Filtrer etter eier" + owner_placeholder: "Filtrer etter eier", }, empty_states: { no_vendors: { title: "Ingen leverandører ennå", - description: "Kom i gang med å opprette din første leverandør" + description: "Kom i gang med å opprette din første leverandør", }, no_results: { title: "Ingen resultater funnet", description: "Ingen leverandører matcher søket ditt", - description_with_filters: "Prøv å justere filtrene dine" - } + description_with_filters: "Prøv å justere filtrene dine", + }, }, actions: { - create: "Opprett Leverandør" + create: "Opprett Leverandør", }, status: { not_assessed: "Ikke Vurdert", in_progress: "Under Behandling", - assessed: "Vurdert" + assessed: "Vurdert", }, category: { cloud: "Sky", @@ -408,14 +417,14 @@ export default { marketing: "Markedsføring", sales: "Salg", hr: "HR", - other: "Annet" + other: "Annet", }, risk_level: { low: "Lav Risiko", medium: "Moderat Risiko", high: "Høy Risiko", - unknown: "Ukjent Risiko" - } + unknown: "Ukjent Risiko", + }, }, dashboard: { title: "Dashbord", @@ -423,36 +432,42 @@ export default { risk_status: "Risiko Status", risks_by_department: "Risikoer etter Avdeling", risks_by_assignee: "Risikoer etter Tildelt", - inherent_risk_description: "Inherent risiko beregnes som sannsynlighet * påvirkning. Beregnet før noen kontroller er anvendt.", - residual_risk_description: "Residual risiko beregnes som sannsynlighet * påvirkning. Dette er risikonivået etter at kontroller er anvendt.", - risk_assessment_description: "Sammenlign inherent og residual risikonivåer" + inherent_risk_description: + "Inherent risiko beregnes som sannsynlighet * påvirkning. Beregnet før noen kontroller er anvendt.", + residual_risk_description: + "Residual risiko beregnes som sannsynlighet * påvirkning. Dette er risikonivået etter at kontroller er anvendt.", + risk_assessment_description: + "Sammenlign inherent og residual risikonivåer", }, register: { title: "Risiko Register", table: { - risk: "Risiko" + risk: "Risiko", }, empty: { no_risks: { title: "Opprett en risiko for å komme i gang", - description: "Følg med på og vurder risikoer, opprett og tildel tiltak for teamet ditt, og administrer risiko registeret ditt i ett enkelt grensesnitt." + description: + "Følg med på og vurder risikoer, opprett og tildel tiltak for teamet ditt, og administrer risiko registeret ditt i ett enkelt grensesnitt.", }, - create_risk: "Opprett en risiko" - } + create_risk: "Opprett en risiko", + }, }, metrics: { probability: "Sannsynlighet", impact: "Påvirkning", inherentRisk: "Inherent Risiko", - residualRisk: "Residual Risiko" + residualRisk: "Residual Risiko", }, form: { update_inherent_risk: "Lagre Inherent Risiko", - update_inherent_risk_description: "Oppdater den inherent risikoen for risikoen. Dette er risikonivået før noen kontroller er anvendt.", + update_inherent_risk_description: + "Oppdater den inherent risikoen for risikoen. Dette er risikonivået før noen kontroller er anvendt.", update_inherent_risk_success: "Inherent risiko oppdatert", update_inherent_risk_error: "Kunne ikke oppdatere inherent risiko", update_residual_risk: "Lagre Residual Risiko", - update_residual_risk_description: "Oppdater den residual risikoen for risikoen. Dette er risikonivået etter at kontroller er anvendt.", + update_residual_risk_description: + "Oppdater den residual risikoen for risikoen. Dette er risikonivået etter at kontroller er anvendt.", update_residual_risk_success: "Residual risiko oppdatert", update_residual_risk_error: "Kunne ikke oppdatere residual risiko", update_risk: "Oppdater Risiko", @@ -471,7 +486,7 @@ export default { risk_department: "Avdeling", risk_department_placeholder: "Velg en avdeling", risk_status: "Risiko Status", - risk_status_placeholder: "Velg en risikostatus" + risk_status_placeholder: "Velg en risikostatus", }, tasks: { title: "Oppgaver", @@ -488,33 +503,38 @@ export default { due_date: "Forfallsdato", due_date_description: "Velg forfallsdato for oppgaven", success: "Oppgave opprettet", - error: "Kunne ikke opprette oppgave" + error: "Kunne ikke opprette oppgave", }, sheet: { title: "Opprett Oppgave", update: "Oppdater Oppgave", - update_description: "Oppdater oppgavetittelen eller beskrivelsen." + update_description: "Oppdater oppgavetittelen eller beskrivelsen.", }, empty: { - description_create: "Opprett en tiltakoppgave for denne risikoen, legg til en behandlingsplan, og tildel den til et teammedlem." - } - } + description_create: + "Opprett en tiltakoppgave for denne risikoen, legg til en behandlingsplan, og tildel den til et teammedlem.", + }, + }, }, settings: { general: { title: "Generelt", org_name: "Organisasjonsnavn", - org_name_description: "Dette er organisasjonens synlige navn. Du bør bruke det juridiske navnet på organisasjonen din.", + org_name_description: + "Dette er organisasjonens synlige navn. Du bør bruke det juridiske navnet på organisasjonen din.", org_name_tip: "Vennligst bruk maks 32 tegn.", org_website: "Organisasjonsnettsted", - org_website_description: "Dette er organisasjonens offisielle nettsted-URL. Sørg for å inkludere hele URL-en med https://.", + org_website_description: + "Dette er organisasjonens offisielle nettsted-URL. Sørg for å inkludere hele URL-en med https://.", org_website_tip: "Vennligst skriv inn en gyldig URL inkludert https://", org_website_error: "Feil ved oppdatering av organisasjonsnettsted", org_website_updated: "Organisasjonsnettsted oppdatert", org_delete: "Slett organisasjon", - org_delete_description: "Fjern organisasjonen din og alt innhold permanent fra Comp AI-plattformen. Denne handlingen kan ikke angres - vennligst fortsett med forsiktighet.", + org_delete_description: + "Fjern organisasjonen din og alt innhold permanent fra Comp AI-plattformen. Denne handlingen kan ikke angres - vennligst fortsett med forsiktighet.", org_delete_alert_title: "Er du helt sikker?", - org_delete_alert_description: "Denne handlingen kan ikke angres. Dette vil permanent slette organisasjonen din og fjerne dataene dine fra våre servere.", + org_delete_alert_description: + "Denne handlingen kan ikke angres. Dette vil permanent slette organisasjonen din og fjerne dataene dine fra våre servere.", org_delete_error: "Feil ved sletting av organisasjon", org_delete_success: "Organisasjon slettet", org_name_updated: "Organisasjonsnavn oppdatert", @@ -523,14 +543,14 @@ export default { delete_button: "Slett", delete_confirm: "SLETT", delete_confirm_tip: "Skriv SLETT for å bekrefte.", - cancel_button: "Avbryt" + cancel_button: "Avbryt", }, members: { - title: "Medlemmer" + title: "Medlemmer", }, billing: { - title: "Fakturering" - } + title: "Fakturering", + }, }, user_menu: { theme: "Tema", @@ -539,7 +559,7 @@ export default { account: "Konto", support: "Støtte", settings: "Innstillinger", - teams: "Team" + teams: "Team", }, frameworks: { title: "Rammeverk", @@ -550,45 +570,47 @@ export default { status: "Status", control: "Kontroll", artifacts: "Artefakter", - actions: "Handlinger" + actions: "Handlinger", }, statuses: { not_started: "Ikke startet", compliant: "Samsvarende", non_compliant: "Ikke samsvarende", completed: "Fullført", - in_progress: "Pågår" - } + in_progress: "Pågår", + }, }, overview: { error: "Kunne ikke laste rammeverk", loading: "Laster rammeverk...", empty: { title: "Ingen rammeverk valgt", - description: "Velg rammeverk for å komme i gang med din samsvarsreise" + description: "Velg rammeverk for å komme i gang med din samsvarsreise", }, progress: { title: "Rammeverksprogresjon", empty: { title: "Ingen rammeverk ennå", - description: "Kom i gang ved å legge til et samsvarsrammeverk for å spore fremgangen din", - action: "Legg til rammeverk" - } + description: + "Kom i gang ved å legge til et samsvarsrammeverk for å spore fremgangen din", + action: "Legg til rammeverk", + }, }, grid: { welcome: { title: "Velkommen til Comp AI", - description: "Kom i gang ved å velge samsvarsrammeverkene du ønsker å implementere. Vi hjelper deg med å administrere og spore samsvarsreisen din på tvers av flere standarder.", - action: "Kom i gang" + description: + "Kom i gang ved å velge samsvarsrammeverkene du ønsker å implementere. Vi hjelper deg med å administrere og spore samsvarsreisen din på tvers av flere standarder.", + action: "Kom i gang", }, title: "Velg rammeverk", version: "Versjon", actions: { clear: "Tøm", - confirm: "Bekreft valg" - } - } - } + confirm: "Bekreft valg", + }, + }, + }, }, vendor: { title: "Dashbord", @@ -599,8 +621,10 @@ export default { vendor_status: "Leverandørstatus", vendor_category: "Leverandørkategorier", vendors_by_assignee: "Leverandører etter tildelt", - inherent_risk_description: "Innledende risikonivå før noen kontroller er anvendt", - residual_risk_description: "Gjenstående risikonivå etter at kontroller er anvendt" + inherent_risk_description: + "Innledende risikonivå før noen kontroller er anvendt", + residual_risk_description: + "Gjenstående risikonivå etter at kontroller er anvendt", }, register: { title: "Leverandørregister", @@ -608,8 +632,8 @@ export default { name: "Navn", category: "Kategori", status: "Status", - owner: "Eier" - } + owner: "Eier", + }, }, category: { cloud: "Sky", @@ -619,7 +643,7 @@ export default { marketing: "Markedsføring", sales: "Salg", hr: "HR", - other: "Annet" + other: "Annet", }, vendors: "leverandører", form: { @@ -644,79 +668,79 @@ export default { contact_role: "Kontaktpersonens rolle", add_contact: "Legg til kontakt", new_contact: "Ny kontakt", - min_one_contact_required: "En leverandør må ha minst én kontakt" + min_one_contact_required: "En leverandør må ha minst én kontakt", }, empty_states: { no_vendors: { title: "Ingen leverandører ennå", - description: "Kom i gang med å opprette din første leverandør" + description: "Kom i gang med å opprette din første leverandør", }, no_results: { title: "Ingen resultater funnet", description: "Ingen leverandører samsvarer med søket ditt", - description_with_filters: "Prøv å justere filtrene dine" - } - } + description_with_filters: "Prøv å justere filtrene dine", + }, + }, }, people: { title: "Personer", details: { taskProgress: "Oppgavefremdrift", tasks: "Oppgaver", - noTasks: "Ingen oppgaver tildelt ennå" + noTasks: "Ingen oppgaver tildelt ennå", }, description: "Administrer teammedlemmene dine og deres roller.", filters: { search: "Søk etter personer...", - role: "Filtrer etter rolle" + role: "Filtrer etter rolle", }, actions: { invite: "Legg til ansatt", - clear: "Fjern filtre" + clear: "Fjern filtre", }, table: { name: "Navn", email: "E-post", department: "Avdeling", - externalId: "Ekstern ID" + externalId: "Ekstern ID", }, empty: { no_employees: { title: "Ingen ansatte ennå", - description: "Kom i gang med å invitere ditt første teammedlem." + description: "Kom i gang med å invitere ditt første teammedlem.", }, no_results: { title: "Ingen resultater funnet", description: "Ingen ansatte samsvarer med søket ditt", - description_with_filters: "Prøv å justere filtrene dine" - } + description_with_filters: "Prøv å justere filtrene dine", + }, }, invite: { title: "Legg til ansatt", description: "Legg til en ansatt i organisasjonen din.", email: { label: "E-postadresse", - placeholder: "Skriv inn e-postadresse" + placeholder: "Skriv inn e-postadresse", }, role: { label: "Rolle", - placeholder: "Velg en rolle" + placeholder: "Velg en rolle", }, name: { label: "Navn", - placeholder: "Skriv inn navn" + placeholder: "Skriv inn navn", }, department: { label: "Avdeling", - placeholder: "Velg en avdeling" + placeholder: "Velg en avdeling", }, submit: "Legg til ansatt", success: "Ansatt lagt til", - error: "Kunne ikke legge til ansatt" - } + error: "Kunne ikke legge til ansatt", + }, }, errors: { - unexpected: "Noe gikk galt, vennligst prøv igjen" + unexpected: "Noe gikk galt, vennligst prøv igjen", }, sub_pages: { risk: { @@ -725,29 +749,29 @@ export default { risk_overview: "Risikooversikt", risk_comments: "Risiko-kommentarer", tasks: { - task_overview: "Oppgaveoversikt" - } + task_overview: "Oppgaveoversikt", + }, }, policies: { all: "Alle retningslinjer", editor: "Retningslinje-redigerer", - policy_details: "Policy Detaljer" + policy_details: "Policy Detaljer", }, people: { all: "Personer", - employee_details: "Ansattdetaljer" + employee_details: "Ansattdetaljer", }, settings: { - members: "Teammedlemmer" + members: "Teammedlemmer", }, frameworks: { - overview: "Rammeverk" + overview: "Rammeverk", }, evidence: { title: "Bevis", list: "Bevisliste", - overview: "Oversikt over Bevis" - } + overview: "Oversikt over Bevis", + }, }, editor: { ai: { @@ -755,23 +779,23 @@ export default { thinking_spinner: "AI tenker", edit_or_generate: "Rediger eller generer...", tell_ai_what_to_do_next: "Fortell AI hva den skal gjøre neste gang", - request_limit_reached: "Du har nådd forespørselgrensen for dagen." + request_limit_reached: "Du har nådd forespørselgrensen for dagen.", }, ai_selector: { improve: "Forbedre skriving", fix: "Rett grammatikk", shorter: "Gjør kortere", longer: "Gjør lengre", - "continue": "Fortsett å skrive", + continue: "Fortsett å skrive", replace: "Erstatt valg", insert: "Sett inn under", - discard: "Forkast" - } + discard: "Forkast", + }, }, evidence: { title: "Bevisoppgaver", description: "Administrer og spor bevisoppgaver for dine samsvarsbehov.", dashboard: "Dashbord", - list: "Alle Bevis" - } + list: "Alle Bevis", + }, } as const; diff --git a/apps/app/src/locales/pt.ts b/apps/app/src/locales/pt.ts index 33698d6068..2f6a6f2fe5 100644 --- a/apps/app/src/locales/pt.ts +++ b/apps/app/src/locales/pt.ts @@ -4,36 +4,36 @@ export default { fr: "Francês", no: "Norueguês", pt: "Português", - en: "Inglês" + en: "Inglês", }, language: { title: "Idiomas", description: "Altere o idioma usado na interface do usuário.", - placeholder: "Selecione o idioma" + placeholder: "Selecione o idioma", }, common: { actions: { save: "Salvar", edit: "Editar", - "delete": "Excluir", + delete: "Excluir", cancel: "Cancelar", clear: "Limpar", create: "Criar", send: "Enviar", - "return": "Retornar", + return: "Retornar", success: "Sucesso", error: "Erro", next: "Próximo", complete: "Completo", - addNew: "Adicionar Novo" + addNew: "Adicionar Novo", }, assignee: { label: "Responsável", - placeholder: "Selecione o responsável" + placeholder: "Selecione o responsável", }, date: { pick: "Escolher uma data", - due_date: "Data de Vencimento" + due_date: "Data de Vencimento", }, status: { open: "Aberto", @@ -51,7 +51,7 @@ export default { assessed: "Avaliado", active: "Ativo", inactive: "Inativo", - title: "Status" + title: "Status", }, filters: { clear: "Limpar filtros", @@ -60,8 +60,8 @@ export default { department: "Departamento", owner: { label: "Responsável", - placeholder: "Filtrar por responsável" - } + placeholder: "Filtrar por responsável", + }, }, table: { title: "Título", @@ -69,7 +69,7 @@ export default { assigned_to: "Atribuído A", due_date: "Data de Vencimento", last_updated: "Última Atualização", - no_results: "Nenhum resultado encontrado" + no_results: "Nenhum resultado encontrado", }, empty_states: { no_results: { @@ -79,12 +79,12 @@ export default { description: "Tente outra pesquisa ou ajuste os filtros", description_filters: "Tente outra pesquisa ou ajuste os filtros", description_no_tasks: "Crie uma tarefa para começar", - description_no_risks: "Crie um risco para começar" + description_no_risks: "Crie um risco para começar", }, no_items: { title: "Nenhum item encontrado", - description: "Tente ajustar sua pesquisa ou filtros" - } + description: "Tente ajustar sua pesquisa ou filtros", + }, }, pagination: { of: "de", @@ -94,38 +94,42 @@ export default { go_to_first_page: "Ir para a primeira página", go_to_previous_page: "Ir para a página anterior", go_to_next_page: "Ir para a próxima página", - go_to_last_page: "Ir para a última página" + go_to_last_page: "Ir para a última página", }, comments: { title: "Comentários", description: "Adicione um comentário usando o formulário abaixo.", add: "Novo Comentário", - "new": "Novo Comentário", + new: "Novo Comentário", save: "Salvar Comentário", success: "Comentário adicionado com sucesso", error: "Falha ao adicionar comentário", placeholder: "Escreva seu comentário aqui...", empty: { title: "Nenhum comentário ainda", - description: "Seja o primeiro a adicionar um comentário" - } + description: "Seja o primeiro a adicionar um comentário", + }, }, attachments: { title: "Anexos", description: "Adicione um arquivo clicando em 'Adicionar Anexo'.", upload: "Enviar anexo", - upload_description: "Carregue um anexo ou adicione um link para um recurso externo.", + upload_description: + "Carregue um anexo ou adicione um link para um recurso externo.", drop: "Solte os arquivos aqui", - drop_description: "Solte arquivos aqui ou clique para escolher arquivos do seu dispositivo.", + drop_description: + "Solte arquivos aqui ou clique para escolher arquivos do seu dispositivo.", drop_files_description: "Os arquivos podem ter até ", empty: { title: "Nenhum anexo", - description: "Adicione um arquivo clicando em 'Adicionar Anexo'." + description: "Adicione um arquivo clicando em 'Adicionar Anexo'.", }, toasts: { error: "Algo deu errado, por favor tente novamente.", - error_uploading_files: "Não é possível carregar mais de 1 arquivo por vez", - error_uploading_files_multiple: "Não é possível carregar mais de 10 arquivos", + error_uploading_files: + "Não é possível carregar mais de 1 arquivo por vez", + error_uploading_files_multiple: + "Não é possível carregar mais de 10 arquivos", error_no_files_selected: "Nenhum arquivo selecionado", error_file_rejected: "Arquivo {file} foi rejeitado", error_failed_to_upload_files: "Falha ao carregar arquivos", @@ -136,18 +140,18 @@ export default { success_uploading_files_single: "Arquivo carregado com sucesso", success_uploading_files_target: "Arquivos carregados", uploading_files: "Carregando {target}...", - remove_file: "Remover arquivo" - } + remove_file: "Remover arquivo", + }, }, notifications: { inbox: "Caixa de entrada", archive: "Arquivo", archive_all: "Arquivar tudo", - no_notifications: "Sem novas notificações" + no_notifications: "Sem novas notificações", }, edit: "Editar", errors: { - unexpected_error: "Ocorreu um erro inesperado" + unexpected_error: "Ocorreu um erro inesperado", }, description: "Descrição", last_updated: "Última atualização", @@ -156,34 +160,35 @@ export default { weekly: "Semanal", monthly: "Mensal", quarterly: "Trimestral", - yearly: "Anual" - } + yearly: "Anual", + }, }, header: { discord: { - button: "Junte-se a nós no Discord" + button: "Junte-se a nós no Discord", }, feedback: { button: "Feedback", title: "Obrigado pelo seu feedback!", description: "Voltaremos a você assim que possível", - placeholder: "Ideias para melhorar esta página ou problemas que você está enfrentando.", + placeholder: + "Ideias para melhorar esta página ou problemas que você está enfrentando.", success: "Obrigado pelo seu feedback!", error: "Erro ao enviar feedback - tentar novamente?", - send: "Enviar Feedback" - } + send: "Enviar Feedback", + }, }, not_found: { title: "404 - Página não encontrada", description: "A página que você está procurando não existe.", - "return": "Retornar ao painel" + return: "Retornar ao painel", }, theme: { options: { light: "Claro", dark: "Escuro", - system: "Sistema" - } + system: "Sistema", + }, }, sidebar: { overview: "Visão Geral", @@ -193,11 +198,12 @@ export default { integrations: "Integrações", settings: "Configurações", evidence: "Tarefas de Evidência", - people: "Pessoas" + people: "Pessoas", }, auth: { title: "Automatize a conformidade com SOC 2, ISO 27001 e GDPR com IA.", - description: "Crie uma conta gratuita ou faça login com uma conta existente para continuar.", + description: + "Crie uma conta gratuita ou faça login com uma conta existente para continuar.", options: "Mais opções", google: "Continuar com o Google", email: { @@ -205,12 +211,14 @@ export default { placeholder: "Insira o endereço de e-mail", button: "Continuar com e-mail", magic_link_sent: "Link mágico enviado", - magic_link_description: "Verifique sua caixa de entrada para um link mágico.", + magic_link_description: + "Verifique sua caixa de entrada para um link mágico.", magic_link_try_again: "Tente novamente.", success: "E-mail enviado - verifique sua caixa de entrada!", - error: "Erro ao enviar e-mail - tentar novamente?" + error: "Erro ao enviar e-mail - tentar novamente?", }, - terms: "Ao clicar em continuar, você reconhece que leu e concorda com os Termos de Serviço e a Política de Privacidade." + terms: + "Ao clicar em continuar, você reconhece que leu e concorda com os Termos de Serviço e a Política de Privacidade.", }, onboarding: { title: "Criar uma organização", @@ -219,35 +227,35 @@ export default { fields: { name: { label: "Nome da Organização", - placeholder: "O nome da sua organização" + placeholder: "O nome da sua organização", }, website: { label: "Website", - placeholder: "O website da sua organização" + placeholder: "O website da sua organização", }, subdomain: { label: "Subdomínio", - placeholder: "exemplo" + placeholder: "exemplo", }, fullName: { label: "Seu Nome", - placeholder: "Seu nome completo" - } + placeholder: "Seu nome completo", + }, }, success: "Obrigado, tudo pronto!", error: "Algo deu errado, por favor tente novamente.", unavailable: "Indisponível", check_availability: "Verificando disponibilidade", - available: "Disponível" + available: "Disponível", }, overview: { title: "Visão Geral", framework_chart: { - title: "Progresso do Framework" + title: "Progresso do Framework", }, requirement_chart: { - title: "Status de Conformidade" - } + title: "Status de Conformidade", + }, }, policies: { dashboard: { @@ -258,32 +266,32 @@ export default { policies_by_framework: "Políticas por Framework", sub_pages: { overview: "Visão Geral", - edit_policy: "Editar Política" - } + edit_policy: "Editar Política", + }, }, table: { name: "Nome da Política", statuses: { draft: "Rascunho", published: "Publicado", - archived: "Arquivado" + archived: "Arquivado", }, filters: { owner: { label: "Responsável", - placeholder: "Filtrar por responsável" - } - } + placeholder: "Filtrar por responsável", + }, + }, }, filters: { search: "Pesquisar políticas...", - all: "Todas as Políticas" + all: "Todas as Políticas", }, status: { draft: "Rascunho", published: "Publicado", needs_review: "Necessita Revisão", - archived: "Arquivado" + archived: "Arquivado", }, policies: "políticas", title: "Políticas", @@ -304,20 +312,21 @@ export default { title: "Visão Geral da Política", form: { update_policy: "Atualizar Política", - update_policy_description: "Atualize o título ou a descrição da política.", + update_policy_description: + "Atualize o título ou a descrição da política.", update_policy_success: "Política atualizada com sucesso", update_policy_error: "Falha ao atualizar a política", update_policy_title: "Nome da Política", review_frequency: "Frequência de Revisão", review_frequency_placeholder: "Selecione uma frequência de revisão", review_date: "Data da Revisão", - review_date_placeholder: "Selecione uma data de revisão" - } - } + review_date_placeholder: "Selecione uma data de revisão", + }, + }, }, evidence_tasks: { evidence_tasks: "Tarefas de Evidência", - overview: "Visão Geral" + overview: "Visão Geral", }, risk: { risks: "riscos", @@ -331,8 +340,10 @@ export default { vendor_status: "Status do Fornecedor", vendor_category: "Categorias de Fornecedor", vendors_by_assignee: "Fornecedores por Responsável", - inherent_risk_description: "Nível de risco inicial antes da aplicação de quaisquer controles", - residual_risk_description: "Nível de risco restante após a aplicação de controles" + inherent_risk_description: + "Nível de risco inicial antes da aplicação de quaisquer controles", + residual_risk_description: + "Nível de risco restante após a aplicação de controles", }, register: { title: "Registro de Fornecedor", @@ -340,15 +351,16 @@ export default { name: "Nome", category: "Categoria", status: "Status", - owner: "Responsável" - } + owner: "Responsável", + }, }, assessment: { title: "Avaliação de Fornecedor", - update_success: "Avaliação de risco do fornecedor atualizada com sucesso", + update_success: + "Avaliação de risco do fornecedor atualizada com sucesso", update_error: "Falha ao atualizar a avaliação de risco do fornecedor", inherent_risk: "Risco Inerente", - residual_risk: "Risco Residual" + residual_risk: "Risco Residual", }, form: { vendor_details: "Detalhes do Fornecedor", @@ -367,38 +379,38 @@ export default { update_vendor: "Atualizar Fornecedor", update_vendor_success: "Fornecedor atualizado com sucesso", update_vendor_error: "Falha ao atualizar fornecedor", - add_comment: "Adicionar Comentário" + add_comment: "Adicionar Comentário", }, table: { name: "Nome", category: "Categoria", status: "Status", - owner: "Proprietário" + owner: "Proprietário", }, filters: { search_placeholder: "Pesquisar fornecedores...", status_placeholder: "Filtrar por status", category_placeholder: "Filtrar por categoria", - owner_placeholder: "Filtrar por proprietário" + owner_placeholder: "Filtrar por proprietário", }, empty_states: { no_vendors: { title: "Nenhum fornecedor ainda", - description: "Comece criando seu primeiro fornecedor" + description: "Comece criando seu primeiro fornecedor", }, no_results: { title: "Nenhum resultado encontrado", description: "Nenhum fornecedor corresponde à sua pesquisa", - description_with_filters: "Tente ajustar seus filtros" - } + description_with_filters: "Tente ajustar seus filtros", + }, }, actions: { - create: "Criar Fornecedor" + create: "Criar Fornecedor", }, status: { not_assessed: "Não Avaliado", in_progress: "Em Andamento", - assessed: "Avaliado" + assessed: "Avaliado", }, category: { cloud: "Nuvem", @@ -408,14 +420,14 @@ export default { marketing: "Marketing", sales: "Vendas", hr: "RH", - other: "Outro" + other: "Outro", }, risk_level: { low: "Baixo Risco", medium: "Risco Médio", high: "Alto Risco", - unknown: "Risco Desconhecido" - } + unknown: "Risco Desconhecido", + }, }, dashboard: { title: "Painel", @@ -423,36 +435,42 @@ export default { risk_status: "Status do Risco", risks_by_department: "Riscos por Departamento", risks_by_assignee: "Riscos por Responsável", - inherent_risk_description: "O risco inerente é calculado como probabilidade * impacto. Calculado antes de qualquer controle ser aplicado.", - residual_risk_description: "O risco residual é calculado como probabilidade * impacto. Este é o nível de risco após a aplicação de controles.", - risk_assessment_description: "Compare os níveis de risco inerente e residual" + inherent_risk_description: + "O risco inerente é calculado como probabilidade * impacto. Calculado antes de qualquer controle ser aplicado.", + residual_risk_description: + "O risco residual é calculado como probabilidade * impacto. Este é o nível de risco após a aplicação de controles.", + risk_assessment_description: + "Compare os níveis de risco inerente e residual", }, register: { title: "Registro de Risco", table: { - risk: "Risco" + risk: "Risco", }, empty: { no_risks: { title: "Crie um risco para começar", - description: "Acompanhe e classifique riscos, crie e atribua tarefas de mitigação para sua equipe e gerencie seu registro de risco tudo em uma interface simples." + description: + "Acompanhe e classifique riscos, crie e atribua tarefas de mitigação para sua equipe e gerencie seu registro de risco tudo em uma interface simples.", }, - create_risk: "Criar um risco" - } + create_risk: "Criar um risco", + }, }, metrics: { probability: "Probabilidade", impact: "Impacto", inherentRisk: "Risco Inerente", - residualRisk: "Risco Residual" + residualRisk: "Risco Residual", }, form: { update_inherent_risk: "Salvar Risco Inerente", - update_inherent_risk_description: "Atualize o risco inerente do risco. Este é o nível de risco antes de qualquer controle ser aplicado.", + update_inherent_risk_description: + "Atualize o risco inerente do risco. Este é o nível de risco antes de qualquer controle ser aplicado.", update_inherent_risk_success: "Risco inerente atualizado com sucesso", update_inherent_risk_error: "Falha ao atualizar risco inerente", update_residual_risk: "Salvar Risco Residual", - update_residual_risk_description: "Atualize o risco residual do risco. Este é o nível de risco após a aplicação de controles.", + update_residual_risk_description: + "Atualize o risco residual do risco. Este é o nível de risco após a aplicação de controles.", update_residual_risk_success: "Risco residual atualizado com sucesso", update_residual_risk_error: "Falha ao atualizar risco residual", update_risk: "Atualizar Risco", @@ -471,7 +489,7 @@ export default { risk_department: "Departamento", risk_department_placeholder: "Selecione um departamento", risk_status: "Status do Risco", - risk_status_placeholder: "Selecione um status de risco" + risk_status_placeholder: "Selecione um status de risco", }, tasks: { title: "Tarefas", @@ -488,33 +506,38 @@ export default { due_date: "Data de Vencimento", due_date_description: "Selecione a data de vencimento para a tarefa", success: "Tarefa criada com sucesso", - error: "Falha ao criar tarefa" + error: "Falha ao criar tarefa", }, sheet: { title: "Criar Tarefa", update: "Atualizar Tarefa", - update_description: "Atualize o título ou a descrição da tarefa." + update_description: "Atualize o título ou a descrição da tarefa.", }, empty: { - description_create: "Crie uma tarefa de mitigação para este risco, adicione um plano de tratamento e atribua a um membro da equipe." - } - } + description_create: + "Crie uma tarefa de mitigação para este risco, adicione um plano de tratamento e atribua a um membro da equipe.", + }, + }, }, settings: { general: { title: "Geral", org_name: "Nome da Organização", - org_name_description: "Este é o nome visível da sua organização. Você deve usar o nome legal da sua organização.", + org_name_description: + "Este é o nome visível da sua organização. Você deve usar o nome legal da sua organização.", org_name_tip: "Por favor, use no máximo 32 caracteres.", org_website: "Website da Organização", - org_website_description: "Este é o URL do website oficial da sua organização. Certifique-se de incluir o URL completo com https://.", + org_website_description: + "Este é o URL do website oficial da sua organização. Certifique-se de incluir o URL completo com https://.", org_website_tip: "Por favor, insira um URL válido incluindo https://", org_website_error: "Erro ao atualizar o website da organização", org_website_updated: "Website da organização atualizado", org_delete: "Excluir organização", - org_delete_description: "Remova permanentemente sua organização e todo o seu conteúdo da plataforma Comp AI. Esta ação não é reversível - continue com cautela.", + org_delete_description: + "Remova permanentemente sua organização e todo o seu conteúdo da plataforma Comp AI. Esta ação não é reversível - continue com cautela.", org_delete_alert_title: "Você tem certeza absoluta?", - org_delete_alert_description: "Esta ação não pode ser desfeita. Isso excluirá permanentemente sua organização e removerá seus dados de nossos servidores.", + org_delete_alert_description: + "Esta ação não pode ser desfeita. Isso excluirá permanentemente sua organização e removerá seus dados de nossos servidores.", org_delete_error: "Erro ao excluir organização", org_delete_success: "Organização excluída", org_name_updated: "Nome da organização atualizado", @@ -523,14 +546,14 @@ export default { delete_button: "Excluir", delete_confirm: "EXCLUIR", delete_confirm_tip: "Digite EXCLUIR para confirmar.", - cancel_button: "Cancelar" + cancel_button: "Cancelar", }, members: { - title: "Membros" + title: "Membros", }, billing: { - title: "Faturamento" - } + title: "Faturamento", + }, }, user_menu: { theme: "Tema", @@ -539,7 +562,7 @@ export default { account: "Conta", support: "Suporte", settings: "Configurações", - teams: "Equipes" + teams: "Equipes", }, frameworks: { title: "Estruturas", @@ -550,45 +573,48 @@ export default { status: "Status", control: "Controle", artifacts: "Artefatos", - actions: "Ações" + actions: "Ações", }, statuses: { not_started: "Não Iniciado", compliant: "Conforme", non_compliant: "Não Conforme", completed: "Concluído", - in_progress: "Em Andamento" - } + in_progress: "Em Andamento", + }, }, overview: { error: "Falha ao carregar frameworks", loading: "Carregando frameworks...", empty: { title: "Nenhum framework selecionado", - description: "Selecione frameworks para começar sua jornada de conformidade" + description: + "Selecione frameworks para começar sua jornada de conformidade", }, progress: { title: "Progresso do Framework", empty: { title: "Nenhum framework ainda", - description: "Comece adicionando um framework de conformidade para acompanhar seu progresso", - action: "Adicionar Framework" - } + description: + "Comece adicionando um framework de conformidade para acompanhar seu progresso", + action: "Adicionar Framework", + }, }, grid: { welcome: { title: "Bem-vindo ao Comp AI", - description: "Comece selecionando os frameworks de conformidade que você gostaria de implementar. Nós o ajudaremos a gerenciar e acompanhar sua jornada de conformidade em múltiplos padrões.", - action: "Começar" + description: + "Comece selecionando os frameworks de conformidade que você gostaria de implementar. Nós o ajudaremos a gerenciar e acompanhar sua jornada de conformidade em múltiplos padrões.", + action: "Começar", }, title: "Selecionar Frameworks", version: "Versão", actions: { clear: "Limpar", - confirm: "Confirmar Seleção" - } - } - } + confirm: "Confirmar Seleção", + }, + }, + }, }, vendor: { title: "Painel", @@ -599,8 +625,10 @@ export default { vendor_status: "Status do Fornecedor", vendor_category: "Categorias de Fornecedor", vendors_by_assignee: "Fornecedores por Responsável", - inherent_risk_description: "Nível de risco inicial antes que quaisquer controles sejam aplicados", - residual_risk_description: "Nível de risco restante após a aplicação de controles" + inherent_risk_description: + "Nível de risco inicial antes que quaisquer controles sejam aplicados", + residual_risk_description: + "Nível de risco restante após a aplicação de controles", }, register: { title: "Registro de Fornecedor", @@ -608,8 +636,8 @@ export default { name: "Nome", category: "Categoria", status: "Status", - owner: "Proprietário" - } + owner: "Proprietário", + }, }, category: { cloud: "Nuvem", @@ -619,7 +647,7 @@ export default { marketing: "Marketing", sales: "Vendas", hr: "RH", - other: "Outro" + other: "Outro", }, vendors: "fornecedores", form: { @@ -644,79 +672,79 @@ export default { contact_role: "Função do Contato", add_contact: "Adicionar Contato", new_contact: "Novo Contato", - min_one_contact_required: "Um fornecedor deve ter pelo menos um contato" + min_one_contact_required: "Um fornecedor deve ter pelo menos um contato", }, empty_states: { no_vendors: { title: "Nenhum fornecedor ainda", - description: "Comece criando seu primeiro fornecedor" + description: "Comece criando seu primeiro fornecedor", }, no_results: { title: "Nenhum resultado encontrado", description: "Nenhum fornecedor corresponde à sua pesquisa", - description_with_filters: "Tente ajustar seus filtros" - } - } + description_with_filters: "Tente ajustar seus filtros", + }, + }, }, people: { title: "Pessoas", details: { taskProgress: "Progresso da Tarefa", tasks: "Tarefas", - noTasks: "Nenhuma tarefa atribuída ainda" + noTasks: "Nenhuma tarefa atribuída ainda", }, description: "Gerencie os membros da sua equipe e seus papéis.", filters: { search: "Pesquisar pessoas...", - role: "Filtrar por papel" + role: "Filtrar por papel", }, actions: { invite: "Adicionar Funcionário", - clear: "Limpar filtros" + clear: "Limpar filtros", }, table: { name: "Nome", email: "Email", department: "Departamento", - externalId: "ID Externo" + externalId: "ID Externo", }, empty: { no_employees: { title: "Nenhum funcionário ainda", - description: "Comece convidando seu primeiro membro da equipe." + description: "Comece convidando seu primeiro membro da equipe.", }, no_results: { title: "Nenhum resultado encontrado", description: "Nenhum funcionário corresponde à sua pesquisa", - description_with_filters: "Tente ajustar seus filtros" - } + description_with_filters: "Tente ajustar seus filtros", + }, }, invite: { title: "Adicionar Funcionário", description: "Adicione um funcionário à sua organização.", email: { label: "Endereço de email", - placeholder: "Digite o endereço de email" + placeholder: "Digite o endereço de email", }, role: { label: "Função", - placeholder: "Selecione uma função" + placeholder: "Selecione uma função", }, name: { label: "Nome", - placeholder: "Digite o nome" + placeholder: "Digite o nome", }, department: { label: "Departamento", - placeholder: "Selecione um departamento" + placeholder: "Selecione um departamento", }, submit: "Adicionar Funcionário", success: "Funcionário adicionado com sucesso", - error: "Falha ao adicionar funcionário" - } + error: "Falha ao adicionar funcionário", + }, }, errors: { - unexpected: "Algo deu errado, por favor tente novamente" + unexpected: "Algo deu errado, por favor tente novamente", }, sub_pages: { risk: { @@ -725,29 +753,29 @@ export default { risk_overview: "Visão Geral dos Riscos", risk_comments: "Comentários sobre Riscos", tasks: { - task_overview: "Visão Geral da Tarefa" - } + task_overview: "Visão Geral da Tarefa", + }, }, policies: { all: "Todas as Políticas", editor: "Editor de Políticas", - policy_details: "Detalhes da política" + policy_details: "Detalhes da política", }, people: { all: "Pessoas", - employee_details: "Detalhes do Funcionário" + employee_details: "Detalhes do Funcionário", }, settings: { - members: "Membros da Equipe" + members: "Membros da Equipe", }, frameworks: { - overview: "Estruturas" + overview: "Estruturas", }, evidence: { title: "Evidência", list: "Lista de Evidências", - overview: "Visão Geral das Evidências" - } + overview: "Visão Geral das Evidências", + }, }, editor: { ai: { @@ -755,23 +783,25 @@ export default { thinking_spinner: "A IA está pensando", edit_or_generate: "Editar ou gerar...", tell_ai_what_to_do_next: "Diga à IA o que fazer a seguir", - request_limit_reached: "Você atingiu seu limite de solicitações para o dia." + request_limit_reached: + "Você atingiu seu limite de solicitações para o dia.", }, ai_selector: { improve: "Melhorar a escrita", fix: "Corrigir gramática", shorter: "Tornar mais curto", longer: "Tornar mais longo", - "continue": "Continuar escrevendo", + continue: "Continuar escrevendo", replace: "Substituir seleção", insert: "Inserir abaixo", - discard: "Descartar" - } + discard: "Descartar", + }, }, evidence: { title: "Tarefas de Evidência", - description: "Gerencie e acompanhe as tarefas de evidência para seus requisitos de conformidade.", + description: + "Gerencie e acompanhe as tarefas de evidência para seus requisitos de conformidade.", dashboard: "Painel", - list: "Todas as Evidências" - } + list: "Todas as Evidências", + }, } as const; diff --git a/apps/app/src/styles/globals.css b/apps/app/src/styles/globals.css index 722094644e..e8288f5f7f 100644 --- a/apps/app/src/styles/globals.css +++ b/apps/app/src/styles/globals.css @@ -247,4 +247,4 @@ input[type="time"]::-webkit-calendar-picker-indicator { #e0e0e0 0.5px, transparent 0 ); -} \ No newline at end of file +} diff --git a/biome.json b/biome.json index fa10a33ab7..902a681eb6 100644 --- a/biome.json +++ b/biome.json @@ -27,6 +27,29 @@ } }, "formatter": { - "indentStyle": "space" + "enabled": true, + "formatWithErrors": false, + "ignore": [], + "attributePosition": "auto", + "indentStyle": "tab", + "indentWidth": 2, + "lineWidth": 80, + "lineEnding": "lf" + }, + "javascript": { + "formatter": { + "arrowParentheses": "always", + "bracketSameLine": false, + "bracketSpacing": true, + "jsxQuoteStyle": "double", + "quoteProperties": "asNeeded", + "semicolons": "always", + "trailingCommas": "all" + } + }, + "json": { + "formatter": { + "trailingCommas": "none" + } } } \ No newline at end of file