Skip to content

Mariano/stuff - #77

Merged
Marfuen merged 6 commits into
mainfrom
mariano/stuff
Feb 24, 2025
Merged

Marfuen merged 6 commits into
mainfrom
mariano/stuff

Conversation

@Marfuen

@Marfuen Marfuen commented Feb 24, 2025 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Enhanced evidence tasks with filtering by status and frequency, improved pagination, and sortable columns displaying frequency and next review dates.
    • Added a publish action in evidence details that provides real-time notifications.
    • Upgraded file and URL management interfaces with a dynamic file upload dropzone, clear tooltips, domain display, and easy copy functions.
    • Introduced a new Review Date Card component to display next review dates based on frequency.
    • Added frequency attributes to various policies and evidence entries for better tracking and management.
    • Streamlined dashboard layout with updated spacing for a more streamlined user experience.

@vercel

vercel Bot commented Feb 24, 2025 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
app ✅ Ready (Inspect) Visit Preview 💬 Add feedback Feb 24, 2025 9:01pm
2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
comp-portal ⬜️ Skipped (Inspect) Feb 24, 2025 9:01pm
web ⬜️ Skipped (Inspect) Feb 24, 2025 9:01pm

@coderabbitai

coderabbitai Bot commented Feb 24, 2025 •

Copy link
Copy Markdown

Walkthrough

The changes extend the data model and UI functionality across the application and database layers. New frequency fields are added to organization policies and evidence, while API endpoints are enhanced with refined filtering and pagination. UI components now support additional filters, sorting, and dynamic column resizing. New actions (e.g., for publishing evidence) and utility functions (for calculating review dates) have been introduced. On the database side, new ENUM types and migrations update table schemas. The seeding process and JSON configuration files are also updated to integrate the additional frequency attribute.

Changes

File(s) Summary of Changes
apps/app/src/actions/framework/select-frameworks-action.ts Added frequency property in data creation for organization policies and organization evidence.
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getOrganizationEvidenceTasks.ts Enhanced the function with new parameters (status, frequency, page, pageSize), pagination metadata, and added new interfaces for type safety.
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/EvidenceList.tsx Updated component to support filtering by status and frequency, added dropdowns and pagination controls, and improved search & error handling.
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/data-table/columns.tsx, data-table-header.tsx, data-table.tsx Modified table components by removing some columns, adding frequency and nextReviewDate columns, updating the status column properties, and introducing sorting state and dynamic header resizing.
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/publishEvidence.ts, EvidenceDetails.tsx Introduced a new publishEvidence action and updated the EvidenceDetails component to enable publishing with toast notifications and conditional rendering; integrated the new ReviewDateCard.
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FileCard.tsx, FileSection.tsx, UrlSection.tsx Enhanced FileCard UI, added state management for displaying the file upload dropzone, and improved UrlSection with domain extraction and copy-to-clipboard functionality.
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/ReviewDateCard.tsx Added a new component that calculates and displays the next review date based on the last published date and frequency.
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTasks.ts Extended hook to support new filtering parameters (status, frequency, pagination) and improved error handling with explicit checks.
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/layout.tsx Removed the SecondaryMenu component and updated the main content’s vertical spacing from mt-8 to py-8.
apps/app/src/lib/utils/calculate-next-review.ts Introduced a utility function to compute the next review date based on the last published date and frequency, returning review information with urgency.
packages/data/controls/soc2.json, packages/data/policies/*.json Updated multiple JSON documents by adding a frequency field (with values like "monthly", "quarterly", or "yearly") to policy and evidence entries.
packages/db/prisma/migrations/*.sql Added new ENUM type Frequency and modified tables (OrganizationEvidence, OrganizationPolicy, Evidence, Policy, ControlRequirement) by adding frequency and lastPublishedAt columns.
packages/db/prisma/schema.prisma Introduced the Frequency enum and updated several models (Policy, ControlRequirement, OrganizationPolicy, Evidence, OrganizationEvidence) to include an optional frequency field; adjusted formatting.
packages/db/prisma/seed.ts, packages/db/prisma/seedTypes.ts Updated seed scripts and type definitions to include the frequency property when upserting policies, control requirements, and evidence, along with adjusted cleanup logic.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant ED as EvidenceDetails Component
    participant PE as publishEvidence Action
    participant DB as Database
    participant RTC as ReviewDateCard Component

    U->>ED: Click "Publish Evidence" button
    ED->>PE: Call publishEvidence action
    PE->>DB: Validate user/org and update evidence (set published status, lastPublishedAt, frequency)
    DB-->>PE: Return update result
    PE-->>ED: Send success response
    ED->>RTC: Request updated review information
    RTC-->>ED: Render next review date info
Loading

Poem

I hopped through lines of code today,
Adding fields that guide our way.
Frequency now leads each policy and test,
As pagination and sorting work at their best.
With a joyful leap, I refine and play—
A rabbit’s code sings in a playful display!
🐰✨

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🔭 Outside diff range comments (1)
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/layout.tsx (1)

2-2: 🛠️ Refactor suggestion

Remove unused import.

The SecondaryMenu component is imported but not used in the code.

-import { SecondaryMenu } from "@bubba/ui/secondary-menu";
🧹 Nitpick comments (32)
packages/db/prisma/migrations/20250224174548_add_frequency_to_evidence/migration.sql (1)

1-2: New Column Addition in Evidence Table
A new column "frequency" of type "Frequency" is introduced in the "Evidence" table. Ensure that existing records are handled appropriately—if this column is meant to be mandatory, consider specifying a default value or a NOT NULL constraint to avoid potential runtime issues on existing data.

packages/data/policies/data_center.json (1)

8-8: Frequency Field Integration in Metadata
The addition of "frequency": "yearly" to the metadata is correctly implemented. One note: the metadata now uses "yearly", while the table cell under "Review Frequency" displays "Annual". Verify that this difference is intentional and that any downstream processing (e.g., mapping to a database ENUM) handles this consistently.

packages/data/policies/thirdparty.json (1)

8-8: Frequency Field Addition for Third-Party Policy
The "frequency": "yearly" property is successfully added to the metadata. As with other policies, please check that the usage aligns across the system, especially if there is any logic converting between the metadata value and the display (e.g., "Annual" vs. "yearly").

packages/data/policies/data_classification.json (1)

8-8: New Frequency Attribute Added
The "frequency": "yearly" property has been introduced in the metadata section to indicate that the policy should be reviewed on a yearly basis. This update aligns with the broader PR objectives. Please confirm that downstream consumers—such as the UI renderers or database migrations—are aware of this new property, and consider if the internal value "yearly" should be mapped to a display-friendly string (e.g., "Annual") consistently across the application.

packages/data/policies/access_control.json (1)

8-8: Frequency Property Consistency
The addition of "frequency": "yearly" in the metadata is consistent with similar updates across the policy documents. Verify that any code consuming this JSON (e.g., for UI display or integration with database enums) correctly maps this internal value to the intended user-facing label (as seen elsewhere with “Annual”).

packages/data/policies/code_of_conduct.json (1)

8-8: Metadata Enhancement with Frequency
The "frequency": "yearly" property is now added to the Code of Conduct Policy metadata, which enhances the document by explicitly defining its review cadence. Ensure that any consumers of this file (for audits or UI rendering) are updated to handle this new field, and that if a display string is required, it should remain consistent with other policies.

packages/data/policies/information_security.json (1)

8-8: Review Frequency Field Inclusion
The Information Security Policy now includes "frequency": "yearly" in its metadata, aligning it with the updated data model for review scheduling. It is advisable to review the mapping between these metadata values and the corresponding display values (e.g., “Annual”) in the UI components to ensure a consistent experience.

packages/data/policies/cyber_risk.json (1)

8-8: Cyber Risk Policy Frequency Update
The addition of "frequency": "yearly" to the Cyber Risk Assessment Policy metadata ensures that the document now clearly indicates a yearly review cycle. Please ensure that the backend and frontend integration (notably the ENUM type in the database and the UI components) correctly handle this new field and that any references to review frequency reflect the intended mapping (e.g., “yearly” stored vs. “Annual” displayed).

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/layout.tsx (1)

9-9: Address the TODO comment regarding i18n implementation.

The comment indicates that i18n implementation is pending and was causing build failures.

Would you like me to help implement the i18n functionality or create an issue to track this task?

apps/app/src/lib/utils/calculate-next-review.ts (2)

9-14: Add JSDoc documentation for better code clarity.

The function would benefit from comprehensive documentation explaining its purpose, parameters, and return value.

+/**
+ * Calculates the next review date based on the last published date and frequency.
+ * @param lastPublishedAt - The date when the item was last published
+ * @param frequency - The frequency of reviews (monthly, quarterly, or yearly)
+ * @param urgentThresholdDays - Number of days before review is considered urgent (default: 7)
+ * @returns ReviewInfo object containing next review date and urgency status, or null if inputs are invalid
+ */
 export function calculateNextReview(
   lastPublishedAt: Date | null,
   frequency: Frequency | null,
   urgentThresholdDays = 7
 ): ReviewInfo | null {

12-12: Add input validation for urgentThresholdDays.

The function should validate that urgentThresholdDays is a positive number.

   urgentThresholdDays = 7
 ): ReviewInfo | null {
+  if (urgentThresholdDays < 0) {
+    throw new Error('urgentThresholdDays must be a positive number');
+  }
   if (!frequency || !lastPublishedAt) return null;

Also applies to: 33-35

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/ReviewDateCard.tsx (1)

14-27: Consider adding a more descriptive message for ASAP case.

While the current implementation is functional, consider providing more context about why immediate review is needed.

-          <p className="text-red-500 font-bold">ASAP</p>
+          <p className="text-red-500 font-bold">
+            ASAP - No review schedule set
+          </p>
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FileSection.tsx (1)

96-113: Consider extracting the Add Files card to a separate component.

The Add Files card could be extracted to improve code organization and reusability.

+// AddFilesCard.tsx
+interface AddFilesCardProps {
+  onClick: () => void;
+}
+
+export function AddFilesCard({ onClick }: AddFilesCardProps) {
+  return (
+    <Card
+      className="group cursor-pointer transition-all hover:shadow-md border-dashed border-2 border-primary/30 hover:border-primary h-[220px] flex flex-col overflow-hidden"
+      onClick={onClick}
+    >
+      <CardContent className="flex flex-col items-center justify-center h-full p-4">
+        <div className="rounded-full bg-primary/10 p-3 mb-2">
+          <Plus className="h-6 w-6 text-primary" />
+        </div>
+        <p className="text-sm font-medium text-center">Add Files</p>
+        <p className="text-xs text-muted-foreground mt-1 text-center">
+          Upload additional evidence files
+        </p>
+      </CardContent>
+    </Card>
+  );
+}
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/publishEvidence.ts (1)

42-77: Consider adding transaction for atomic updates.

While the current implementation works, wrapping the database operations in a transaction would ensure atomicity.

     try {
+      return await db.$transaction(async (tx) => {
         // Check if evidence exists and belongs to organization
-        const evidence = await db.organizationEvidence.findFirst({
+        const evidence = await tx.organizationEvidence.findFirst({
           where: {
             id,
             organizationId: user.organizationId,
           },
         });

         if (!evidence) {
           return {
             success: false,
             error: "Evidence not found",
           };
         }

         // Update the evidence to mark it as published
-        await db.organizationEvidence.update({
+        await tx.organizationEvidence.update({
           where: { id },
           data: {
             published: true,
             lastPublishedAt: new Date(),
           },
         });

         return {
           success: true,
         };
+      });
     } catch (error) {
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/data-table/data-table.tsx (2)

27-38: Consider adding pagination for large datasets.

While sorting is implemented well, consider adding pagination to handle large datasets efficiently.

   const table = useReactTable({
     data,
     columns,
     getCoreRowModel: getCoreRowModel(),
     getSortedRowModel: getSortedRowModel(),
+    getPaginationRowModel: getPaginationRowModel(),
     enableColumnResizing: true,
     columnResizeMode: "onChange",
     state: {
       sorting,
+      pagination: {
+        pageIndex: 0,
+        pageSize: 10,
+      },
     },
     onSortingChange: setSorting,
+    onPaginationChange: setPagination,
   });

41-93: Consider adding keyboard navigation for better accessibility.

While the table implementation is solid, consider enhancing keyboard navigation for better accessibility.

   <TableRow
     key={row.id}
     data-state={row.getIsSelected() && "selected"}
     className="hover:bg-muted/50 cursor-pointer"
     onClick={() => router.push(`/evidence/${row.original.id}`)}
+    onKeyDown={(e) => {
+      if (e.key === 'Enter' || e.key === ' ') {
+        e.preventDefault();
+        router.push(`/evidence/${row.original.id}`);
+      }
+    }}
+    tabIndex={0}
+    role="link"
   >
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/EvidenceList.tsx (2)

73-73: Avoid leaving console logs in production code.

console.log({ evidenceTasks, error }) can clutter logs. Consider removing or replacing it with more structured logging if needed.


75-87: Reuse smaller helper for unique frequencies for larger datasets.

Building a Set and transforming it via useMemo works fine. However, for data with large cardinalities or frequent updates, consider building the unique frequencies in a memoized server-side or store function to keep the UI responsive.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/EvidenceDetails.tsx (1)

7-7: Remove unused import if not needed.

CardTitle is imported but not used. Removing unused imports declutters the code and aligns with best practices.

-import { Card, CardContent, CardHeader, CardTitle } from "@bubba/ui/card";
+import { Card, CardContent, CardHeader } from "@bubba/ui/card";
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FileCard.tsx (3)

54-55: Consider a more fluid height.
Hard-coding a fixed height of 220px could hamper responsiveness on smaller screens. Opting for a more adaptive or auto height can improve the layout’s flexibility.


58-79: Add accessible labeling for the preview button.
This button lacks a text descriptor, potentially making it inaccessible to screen readers. Consider adding an aria-label or visually hidden text to clarify its purpose.


179-179: Provide feedback on deletion errors.
If onDelete fails, the user won’t see a status update. Consider adding toast notifications or UI feedback to handle errors gracefully.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/data-table/data-table-header.tsx (1)

14-61: Enforce a minimum column width.
Using header.getSize() - 32 could lead to negative widths if the table shrinks too much. Safeguard against very narrow columns to avoid layout distortion.

Increase accessibility for sorting.
Consider applying aria-sort or an equivalent attribute to inform users of the current sort state. This ensures a better experience for screen reader users.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getOrganizationEvidenceTasks.ts (2)

27-30: Pagination defaults are sensible.
A starting page of 1 and a page size of 10 are standard. Consider bounding the page size with an upper limit to avoid excessive queries.


52-87: Potential performance consideration with OR searches.
Using multiple OR conditions can degrade performance if data grows large. Evaluate whether partial indexes or a more advanced search approach (e.g., full-text indexing) might be beneficial long-term.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/UrlSection.tsx (1)

50-53: Consider adding error handling for clipboard operations.

The copyToClipboard function should handle potential failures when writing to clipboard.

-const copyToClipboard = (text: string) => {
-  navigator.clipboard.writeText(text);
+const copyToClipboard = async (text: string) => {
+  try {
+    await navigator.clipboard.writeText(text);
+  } catch (error) {
+    console.error('Failed to copy text:', error);
+  }
+};
packages/db/prisma/seed.ts (1)

388-405: Improve variable naming consistency.

The variable name change from evidence to evidenceReq improves clarity, but consider using full words.

-for (const evidenceReq of evidenceRequirements) {
+for (const evidenceRequirement of evidenceRequirements) {
packages/db/prisma/schema.prisma (1)

1048-1052: Consider adding a default frequency value.

The frequency field in OrganizationEvidence could benefit from a default value to ensure consistent behavior.

-frequency Frequency?
+frequency Frequency? @default(yearly)
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTasks.ts (1)

8-15: Consider validating pagination parameters.
Although the interface is well-defined, watch out for invalid pagination values. You might want to validate or guard against negative or zero page/pageSize values.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/data-table/columns.tsx (3)

19-33: Check default and minimum column sizing conflict.
You set size: 100 and minSize: 200. The minSize will always override the smaller default size. Consider aligning them to avoid layout confusion.


64-78: Consider user-friendly rendering for frequency.
If frequency is an enum, consider mapping it to friendlier labels for readability.


79-108: Improve date localization.
Using toLocaleDateString() is acceptable, but you might want a more robust library or i18n approach (e.g., dayjs or date-fns) if you need consistent formatting across locales.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e75a392 and 6b2abd8.

⛔ Files ignored due to path filters (2)
  • bun.lockb is excluded by !**/bun.lockb
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (48)
  • apps/app/src/actions/framework/select-frameworks-action.ts (2 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getOrganizationEvidenceTasks.ts (3 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/EvidenceList.tsx (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/data-table/columns.tsx (3 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/data-table/data-table-header.tsx (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/data-table/data-table.tsx (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/publishEvidence.ts (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/EvidenceDetails.tsx (2 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FileCard.tsx (3 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FileSection.tsx (3 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/ReviewDateCard.tsx (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/UrlSection.tsx (3 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTasks.ts (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/layout.tsx (1 hunks)
  • apps/app/src/lib/utils/calculate-next-review.ts (1 hunks)
  • packages/data/controls/soc2.json (92 hunks)
  • packages/data/policies/access_control.json (1 hunks)
  • packages/data/policies/application_security.json (1 hunks)
  • packages/data/policies/availability.json (1 hunks)
  • packages/data/policies/business_continuity.json (1 hunks)
  • packages/data/policies/change_management.json (1 hunks)
  • packages/data/policies/classification.json (1 hunks)
  • packages/data/policies/code_of_conduct.json (1 hunks)
  • packages/data/policies/confidentiality.json (1 hunks)
  • packages/data/policies/corporate_governance.json (1 hunks)
  • packages/data/policies/cyber_risk.json (1 hunks)
  • packages/data/policies/data_center.json (1 hunks)
  • packages/data/policies/data_classification.json (1 hunks)
  • packages/data/policies/disaster_recovery.json (1 hunks)
  • packages/data/policies/human_resources.json (1 hunks)
  • packages/data/policies/incident_response.json (1 hunks)
  • packages/data/policies/information_security.json (1 hunks)
  • packages/data/policies/password_policy.json (1 hunks)
  • packages/data/policies/privacy.json (1 hunks)
  • packages/data/policies/risk_assessment.json (1 hunks)
  • packages/data/policies/risk_management.json (1 hunks)
  • packages/data/policies/software_development.json (1 hunks)
  • packages/data/policies/system_change.json (1 hunks)
  • packages/data/policies/thirdparty.json (1 hunks)
  • packages/data/policies/vendor_risk_management.json (1 hunks)
  • packages/data/policies/workstation.json (1 hunks)
  • packages/db/prisma/migrations/20250224173509_add_frequency_to_policy_and_evidence/migration.sql (1 hunks)
  • packages/db/prisma/migrations/20250224174548_add_frequency_to_evidence/migration.sql (1 hunks)
  • packages/db/prisma/migrations/20250224180117_add_frequency_to_policy/migration.sql (1 hunks)
  • packages/db/prisma/migrations/20250224183431_add_frequency_to_control_requirement/migration.sql (1 hunks)
  • packages/db/prisma/schema.prisma (6 hunks)
  • packages/db/prisma/seed.ts (8 hunks)
  • packages/db/prisma/seedTypes.ts (3 hunks)
✅ Files skipped from review due to trivial changes (3)
  • packages/db/prisma/migrations/20250224183431_add_frequency_to_control_requirement/migration.sql
  • packages/db/prisma/migrations/20250224180117_add_frequency_to_policy/migration.sql
  • packages/data/policies/password_policy.json
🔇 Additional comments (56)
packages/data/policies/classification.json (1)

8-8: Addition of "frequency" Metadata Property
The "frequency": "yearly" property has been added to the metadata section. This change aligns with similar updates in other policy files and matches the ENUM values defined in the migration scripts. Please verify that "yearly" is the correct review frequency for this policy.

packages/data/policies/human_resources.json (1)

8-8: Frequency Field Addition in Human Resources Policy
The new field "frequency": "yearly" in the Human Resources policy metadata ensures consistency with the updated review cycle across all policies. Confirm that this annual frequency meets internal review guidelines.

packages/data/policies/availability.json (1)

8-8: Metadata Frequency Update for Availability Policy
The insertion of "frequency": "yearly" in the Availability Policy metadata is consistent with the broader changes across policy documents. Please verify that the annual review cycle specified here complies with any regulatory requirements or internal standards for system availability reviews.

packages/data/policies/risk_assessment.json (1)

8-8: Insertion of "frequency" in Risk Assessment Policy Metadata
The new "frequency": "yearly" property signifies that risk assessments are to be conducted on an annual basis. Ensure that this frequency is consistent with your organization's risk management strategy and that any impacted processes or UI components reflect this update.

packages/data/policies/privacy.json (1)

8-8: New Frequency Property in Privacy Policy
The new "frequency": "yearly" field is properly integrated into the privacy policy’s metadata, matching the approach taken in the other policy documents. Ensure that this term is consistent with any backend constraints or ENUM values defined in the database migrations.

packages/data/policies/confidentiality.json (1)

8-8: Frequency Metadata in Confidentiality Policy
The "frequency": "yearly" property has been added as expected. Please confirm that this value is consistent with the definitions in the database schema (e.g., the Frequency ENUM) and that the user interface correctly interprets this metadata.

packages/data/policies/application_security.json (1)

8-8: Integration of Frequency Field in Application Security Policy
The update introducing "frequency": "yearly" into the metadata is well implemented. As a follow-up, verify that any code consuming this data (for filtering or display) uses the proper mapping between the internal value (e.g., "yearly") and the user-facing label (e.g., "Annual").

packages/data/policies/software_development.json (1)

8-8: Ensure Consistent Policy Metadata
The addition of "frequency": "yearly" in the metadata is clear and consistent with the new review cadence requirements. Verify that any downstream mapping (e.g., to UI labels or database ENUM values) properly interprets "yearly" (which may be displayed as "Annual" elsewhere).

packages/data/policies/business_continuity.json (1)

8-8: Validate Frequency Field Integration
The new "frequency": "yearly" property is correctly added to the business continuity policy metadata. Confirm that this value aligns with UI representations and database schema mappings (e.g., the corresponding ENUM) to maintain consistency across the platform.

packages/data/policies/system_change.json (1)

8-8: Consistent Frequency Specification for System Change Policy
The addition of "frequency": "yearly" meets the new policy review requirements. As with other policy files, please ensure that the UI and database layers consistently interpret this value (e.g., mapping "yearly" to a display label like "Annual").

packages/data/policies/workstation.json (1)

8-8: Appropriate Frequency Field Addition
The new "frequency": "yearly" field in the workstation policy metadata appropriately specifies the review cadence. Make sure that any components (such as table displays showing "Review Frequency") correctly reflect this metadata and that the value maps to the expected ENUM in the database.

packages/data/policies/incident_response.json (1)

8-8: Clear Addition of Frequency for Incident Response
The inclusion of "frequency": "yearly" in the incident response policy metadata is straightforward and aligns with the broader update. Confirm that this field is integrated into downstream processes—such as policy review scheduling, UI displays, and database schema updates—to ensure end-to-end consistency.

packages/data/policies/risk_management.json (1)

8-8: Addition of "frequency" Property
The new "frequency": "yearly" property is correctly added to the metadata section. This value aligns with the ENUM values defined in the database schema (“monthly”, “quarterly”, “yearly”), ensuring consistency across policy documents.

packages/data/policies/change_management.json (1)

8-8: Introducing the Frequency Attribute
The addition of "frequency": "yearly" enhances the metadata by explicitly defining the review interval. This change is consistent with similar updates across other policies and supports subsequent database integration.

packages/data/policies/vendor_risk_management.json (1)

8-8: Consistent Frequency Field Update
Including "frequency": "yearly" clearly communicates that the vendor risk management policy is to be reviewed annually. This update mirrors changes in other policy files and fits within the overall design for policy frequency management.

packages/data/policies/corporate_governance.json (1)

8-8: New Frequency Attribute Added
The new "frequency": "yearly" property effectively sets the review cadence for the corporate governance policy. Its usage is consistent with the broader changes across policy documents and the expected database ENUM values.

packages/data/policies/disaster_recovery.json (1)

8-8: Disaster Recovery Frequency Update
The addition of "frequency": "yearly" improves clarity regarding the review interval for the disaster recovery policy. This update aligns with similar modifications in other policy documents and adheres to the standardized frequency values.

apps/app/src/actions/framework/select-frameworks-action.ts (1)

152-152:

Details

❓ Verification inconclusive

Consider handling null frequency values.

The frequency values from policy.frequency and evidence.frequency might be null. Consider providing a default value or handling null cases explicitly.

Also applies to: 269-269


🏁 Script executed:

#!/bin/bash
# Check if there are any policies or evidence with null frequency values
ast-grep --pattern 'frequency: null'

Length of output: 38


Potential Null Handling for Frequency Values

In apps/app/src/actions/framework/select-frameworks-action.ts (line 152), the frequency property is set directly from policy.frequency without any explicit null check. Since both policy.frequency and its counterpart in createOrganizationEvidence might be null, please ensure that you explicitly handle these cases—either by providing a default value (e.g., using the nullish coalescing operator like policy.frequency ?? defaultFrequencyValue) or by adding proper null-check logic—to prevent unexpected runtime behavior.

Please verify that this change is compatible with the rest of the codebase and that similar precautions are applied wherever frequency values are used.

packages/db/prisma/seedTypes.ts (1)

1-1: LGTM! Interface updates are consistent with schema changes.

The addition of the frequency field to both Requirement and Policy interfaces aligns well with the database schema updates.

Also applies to: 21-21, 50-50

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/ReviewDateCard.tsx (2)

7-13: LGTM! Props interface is well-defined.

The component's props are properly typed with explicit null handling for both lastPublishedAt and frequency.


29-42: LGTM! Good use of conditional styling for urgency.

The implementation effectively uses conditional styling to highlight urgent reviews, and properly formats the date display.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FileSection.tsx (2)

83-94: LGTM! Clean implementation of conditional file upload.

The implementation elegantly handles the visibility of the upload dropzone based on both file count and user interaction.


115-141: LGTM! Well-structured grid layout with proper key usage.

The implementation uses a responsive grid layout and properly handles file previews and dialog states.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/publishEvidence.ts (1)

7-9: LGTM! Good use of Zod for input validation.

The schema definition is clear and type-safe.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/data-table/data-table.tsx (1)

20-25: LGTM! Good default sorting configuration.

The initial sorting state is well-defined with a sensible default.

packages/db/prisma/migrations/20250224173509_add_frequency_to_policy_and_evidence/migration.sql (2)

1-2: Define a default or handle NULL constraints for the enum.

Creating an enum "Frequency" is fine, but ensure you have a clear strategy for how existing records handle the new column, especially if it's not nullable. Consider adding a default value or making the column nullable to avoid migration failures.


9-10: Mirror constraints or defaults for "OrganizationPolicy".

Same concern applies to the new columns in "OrganizationPolicy". Verify whether existing records require an explicit default "frequency" and whether lastPublishedAt expects backfilling or a default.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/EvidenceList.tsx (2)

41-46: Good addition of new state and hook parameters.

Your approach for storing status, frequency, page, and pageSize in query states and passing them to useOrganizationEvidenceTasks is logically consistent. This ensures modular and reactive URL-driven filtering and pagination.

Also applies to: 53-62


89-95: Clarify whether “clearFilters” should also reset the search query.

While clearing status and frequency, you might also want to reset the search query for complete filter clearing. If this behavior is intentional, document it explicitly.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/EvidenceDetails.tsx (3)

22-30: Efficient publish action with clear feedback.

Using useAction for publishEvidence paired with success/error toast messages is a well-structured approach. It provides clear user feedback and a concise implementation. Good job!


70-85: Seamless publish button in the header.

Conditionally showing the publish button only when !evidence.published avoids redundant interactions. The disabled state during publishing is a neat UX detail. This helps maintain clarity and consistency.


88-93: Informative “ReviewDateCard” usage.

Displaying the last published date with frequency provides transparency to the user. Ensure ReviewDateCard correctly handles edge cases where lastPublishedAt might be null.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FileCard.tsx (4)

117-118: Footer layout changes look good.
The new classes cohesively align elements at the bottom without introducing overflow issues.


122-142: Verify fallback when previewState.url is null.
You cleanly prevent the link’s default action if previewState.url is absent, but users might be left uncertain. Consider showing a disabled state or a message explaining that a preview is unavailable.


145-145: Tooltip usage is consistent.
“Open file” is an appropriate label, aligning well with the existing UI patterns.


152-169: Deletion logic is well-implemented.
The outlined destructive variant with a confirmation dialog follows recommended UI patterns.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/data-table/data-table-header.tsx (3)

5-5: New import is straightforward.
Importing flexRender aligns with the TanStack Table approach. No issues found.


7-8: Icon imports and class merging utility.
Pulling in arrow icons and the cn helper is consistent with project conventions.


10-12: Interface definition clarifies prop usage.
Defining DataTableHeaderProps improves readability and maintainability by clearly stating expected properties.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Actions/getOrganizationEvidenceTasks.ts (6)

4-5: Imports look appropriate.
Bringing in db, Frequency, and additional types from @bubba/db meets the new functionality’s requirements.


8-21: Type definitions add clarity.
PaginationMetadata and EvidenceTasksData refine the response structure, enhancing type safety and developer insight.


42-42: Destructured inputs appear correct.
Status, frequency, page, and pageSize are properly extracted and used later in the query.


89-92: Accurate total count retrieval.
Querying count for pagination is a standard approach. This is correctly aligned with the provided whereClause.


94-99: Pagination calculation is correct.
skip and take logic is clean, avoiding off-by-one errors. Ensure the page does not exceed the total number of pages.


100-123: Concise data encapsulation with pagination metadata.
Including pagination details alongside evidenceTasks keeps the API uniform and clear. No issues noted with the final return structure.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/UrlSection.tsx (3)

41-48: LGTM! Well-implemented domain extraction function.

The getDomainName function correctly handles URL parsing and gracefully falls back to the original URL on error.


192-200: LGTM! Secure external link implementation.

The external link implementation correctly uses rel="noopener noreferrer" for security.


164-225:

Details

❓ Verification inconclusive

Verify accessibility of tooltip buttons.

The buttons with tooltips need proper ARIA labels for screen readers.


🌐 Web query:

What are the WCAG requirements for tooltip accessibility?

💡 Result:

To ensure tooltips meet WCAG accessibility standards, they must adhere to specific requirements under Success Criterion 1.4.13 (Content on Hover or Focus)[8][10]. These guidelines focus on making tooltips perceivable and operable for all users, including those using assistive technologies.


Key Requirements for Accessible Tooltips

1. Dismissible

  • Tooltips must be closable without moving the mouse or changing focus (e.g., via the Escape key)[3][6][8].
  • Avoid auto-dismissing content unless it becomes irrelevant (e.g., a timeout)[8].

2. Hoverable

  • Content must remain visible when users move their pointer over it[6][8].
  • Example: A tooltip should stay open if a user hovers over its text to read it[8].

3. Persistent

  • Tooltips must stay visible until dismissed or until the trigger is removed (e.g., moving focus away)[6][8].
  • Avoid designs where tooltips disappear abruptly[8].

Technical Implementation Guidelines

Semantic Structure

  • Use role="tooltip" for the tooltip container[3][7].
  • Link the tooltip to its trigger element with aria-describedby[3][6].

Keyboard Navigation

  • Ensure tooltips can be triggered via keyboard focus (e.g., using tabindex="0" on non-focusable elements)[3].
  • Support closing with the Escape key[3][6].

Visual Design

  • Contrast: Meet WCAG’s minimum contrast ratio of 4.5:1 between text and background[4].
  • Positioning: Avoid obscuring related content[2][6]. Use arrows to clarify associations if multiple elements are nearby[2].
  • Typography: Use clear fonts and adequate size for readability[1][4].

Content Guidelines

  • Keep text concise (avoid long paragraphs)[1][2].
  • Avoid critical information in tooltips; use visible labels instead[2][7].

Common Pitfalls to Avoid

  • Non-dismissible content: Failing to provide an Escape key option[8].
  • Lack of keyboard support: Tooltips only triggered by mouse hover[2][6].
  • Low contrast: Text that blends into the background[4].
  • Blocking content: Tooltips covering essential UI elements[2][6].

Tools & Testing

  • Validate compliance using tools like WAVE or axe-core[5].
  • Test with screen readers (e.g., NVDA, VoiceOver) and keyboard navigation[5][6].

By adhering to these guidelines, tooltips become inclusive for users with disabilities while aligning with legal standards like ADA and WCAG 2.1 AA[4][5].

Citations:


Accessibility Improvement Required: Ensure Tooltip Buttons Are Properly Labeled

Please verify that each tooltip automatically associates the trigger button with its tooltip content using the appropriate ARIA attributes (such as aria-describedby on the button and role="tooltip" on the tooltip content). If these aren’t handled internally by the tooltip components, add them to meet WCAG Success Criterion 1.4.13 guidelines. Also, ensure tooltips remain keyboard accessible (e.g., dismissible via the Escape key).

packages/db/prisma/seed.ts (1)

23-24: LGTM! Improved database cleanup sequence.

The cleanup sequence is well-organized, ensuring proper deletion order to avoid foreign key constraint issues.

Also applies to: 36-36

packages/db/prisma/schema.prisma (1)

41-45: LGTM! Well-defined frequency enum.

The Frequency enum values are appropriately defined for the use case.

packages/data/controls/soc2.json (1)

14-15: LGTM! Appropriate frequency assignments.

The frequency values are appropriately assigned based on the control type - yearly for policies and quarterly for critical evidence.

Also applies to: 27-28

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTasks.ts (3)

5-6: Typed imports look good.
These imports appear correct and align well with the rest of the file.


17-24: Hook result type is clear and consistent.
Defining and exporting the result interface keeps things readable and coherent, particularly for SWR usage.


46-66: SWR integration and destructuring look good.
After correcting the returned data in fetchEvidenceTasks, the use of SWR keys and the returned fields (like data, pagination, etc.) should work smoothly.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/data-table/columns.tsx (2)

12-12: Ensure test coverage for calculateNextReview.
The utility function import looks fine. Just verify that any date calculations and edge cases (e.g., frequency undefined) have corresponding tests.


38-41: Column sizing refinements for Status.
These settings (resizing, sorting, size, minSize) and className adjustments look consistent. No issues here.

Also applies to: 47-47

Comment on lines +16 to +31
const baseDate = new Date(lastPublishedAt);
const nextReviewDate = new Date(baseDate);

switch (frequency) {
case "monthly":
nextReviewDate.setMonth(nextReviewDate.getMonth() + 1);
break;
case "quarterly":
nextReviewDate.setMonth(nextReviewDate.getMonth() + 3);
break;
case "yearly":
nextReviewDate.setFullYear(nextReviewDate.getFullYear() + 1);
break;
default:
return null;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Handle timezone-related edge cases in date calculations.

The current date calculations might lead to inconsistencies across different timezones. Consider using UTC dates for consistency.

-  const baseDate = new Date(lastPublishedAt);
-  const nextReviewDate = new Date(baseDate);
+  const baseDate = new Date(lastPublishedAt.toISOString());
+  const nextReviewDate = new Date(baseDate.toISOString());

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +31 to +40
.action(async ({ parsedInput, ctx }): Promise<ActionResponse> => {
const { user } = ctx;
const { id } = parsedInput;

if (!user.organizationId) {
return {
success: false,
error: "Not authorized - no organization found",
};
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

❓ Verification inconclusive

Consider adding organization role check.

While the organization check is good, consider also verifying if the user has the appropriate role/permissions to publish evidence.


🏁 Script executed:

#!/bin/bash
# Check if role-based authorization is implemented elsewhere
rg -A 5 "organizationRole|userRole|canPublish|hasPermission"

Length of output: 62


Action Required: Add Role-Based Authorization Check

The current implementation verifies that the user is associated with an organization via user.organizationId, but it does not check if the user has the necessary role or permissions (e.g. a publish permission flag or an organizational role) to execute the publish action. Please consider adding a role/permission check—for example, ensuring that the user holds the appropriate role—before proceeding with the publish logic.

  • Location: apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions/publishEvidence.ts (lines 31–40)
  • Suggestion: After verifying that user.organizationId exists, add an additional condition to check for the required role/permission (such as user.role, organizationRole, or a specific hasPermission flag).

Comment on lines +5 to +6
ALTER TABLE "OrganizationEvidence" ADD COLUMN "frequency" "Frequency",
ADD COLUMN "lastPublishedAt" TIMESTAMP(3);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Check for potential data conflicts or backfill strategy.

When adding new columns to "OrganizationEvidence", consider a backfill if you intend for existing rows to carry a valid value for "frequency" by default. Similarly, decide whether lastPublishedAt should default to the current timestamp or remain nullable.

Comment on lines +26 to 44
async function fetchEvidenceTasks(props: UseOrganizationEvidenceTasksProps) {
const result = await getOrganizationEvidenceTasks(props);

if (!result) {
throw new Error("No result received");
}

if (!result || "error" in result) {
if (result.serverError) {
throw new Error(result.serverError);
}

if (result.validationErrors) {
throw new Error(
typeof result?.error === "string"
? result.error
: "Failed to fetch evidence tasks"
result.validationErrors._errors?.join(", ") ?? "Unknown error"
);
}

return result.data?.data;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Return the entire result object to preserve pagination.
Currently, fetchEvidenceTasks returns only result.data?.data but the hook later references pagination. This mismatch will cause pagination to be undefined.

Please adjust line 43 to ensure you return the entire data payload:

-  return result.data?.data;
+  return result.data;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async function fetchEvidenceTasks(props: UseOrganizationEvidenceTasksProps) {
const result = await getOrganizationEvidenceTasks(props);
if (!result) {
throw new Error("No result received");
}
if (!result || "error" in result) {
if (result.serverError) {
throw new Error(result.serverError);
}
if (result.validationErrors) {
throw new Error(
typeof result?.error === "string"
? result.error
: "Failed to fetch evidence tasks"
result.validationErrors._errors?.join(", ") ?? "Unknown error"
);
}
return result.data?.data;
}
async function fetchEvidenceTasks(props: UseOrganizationEvidenceTasksProps) {
const result = await getOrganizationEvidenceTasks(props);
if (!result) {
throw new Error("No result received");
}
if (result.serverError) {
throw new Error(result.serverError);
}
if (result.validationErrors) {
throw new Error(
result.validationErrors._errors?.join(", ") ?? "Unknown error"
);
}
return result.data;
}

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/data-table/columns.tsx (2)

73-78: Improve empty state handling for better UX.

While the code correctly handles null frequency values, it doesn't provide any visual indication to users about why the cell is empty.

Apply this diff to improve empty state handling:

     cell: ({ row }) => {
       const frequency = row.original.frequency;
-      if (!frequency) return null;
+      if (!frequency) {
+        return (
+          <TooltipProvider>
+            <Tooltip>
+              <TooltipTrigger asChild>
+                <div className="text-gray-400">-</div>
+              </TooltipTrigger>
+              <TooltipContent>No frequency set</TooltipContent>
+            </Tooltip>
+          </TooltipProvider>
+        );
+      }

       return <div className="truncate">{frequency}</div>;
     },

88-108: Use locale-aware date formatting.

The date format is hardcoded to "MM/dd/yyyy", which might not be appropriate for all locales. Since the application appears to support internationalization (based on the [locale] route segment), consider using locale-aware date formatting.

Apply this diff to improve date formatting:

-import { format } from "date-fns";
+import { format } from "date-fns-tz";
+import { useParams } from "next/navigation";

 export const columns: ColumnDef<EvidenceTaskRow>[] = [
   // ... other columns ...
   {
     id: "nextReviewDate",
     // ... other properties ...
     cell: ({ row }) => {
+      const { locale } = useParams();
       if (row.original.lastPublishedAt === null) {
         return <div className="truncate text-red-500 font-medium">ASAP</div>;
       }

       const reviewInfo = calculateNextReview(
         row.original.lastPublishedAt,
         row.original.frequency
       );

       if (!reviewInfo) return null;

       return (
         <div
           className={`truncate ${reviewInfo.isUrgent ? "text-red-500" : ""}`}
         >
           {reviewInfo.daysUntil} days (
-          {format(reviewInfo.nextReviewDate, "MM/dd/yyyy")})
+          {format(reviewInfo.nextReviewDate, "P", { locale })})
         </div>
       );
     },
   },
 ];
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6b2abd8 and 69071b0.

📒 Files selected for processing (3)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/data-table/columns.tsx (3 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/ReviewDateCard.tsx (1 hunks)
  • apps/app/src/lib/utils/calculate-next-review.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/app/src/lib/utils/calculate-next-review.ts
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/ReviewDateCard.tsx
🔇 Additional comments (1)
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/data-table/columns.tsx (1)

39-42: LGTM!

The column configuration is well-structured with consistent size properties and proper enablement of resizing and sorting features.

Comment on lines +20 to +23
enableResizing: true,
enableSorting: true,
size: 100,
minSize: 200,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix inconsistent size properties.

The column's size property (100) is smaller than its minSize property (200), which means the column will always be at least 200px wide, making the size setting ineffective.

Apply this diff to fix the size properties:

-    size: 100,
+    size: 200,
     minSize: 200,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
enableResizing: true,
enableSorting: true,
size: 100,
minSize: 200,
enableResizing: true,
enableSorting: true,
size: 200,
minSize: 200,

@vercel
vercel Bot temporarily deployed to Preview – web February 24, 2025 20:58 Inactive
@vercel
vercel Bot temporarily deployed to Preview – comp-portal February 24, 2025 20:58 Inactive

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
apps/app/src/app/[locale]/providers.tsx (1)

28-38: LGTM! Clean analytics initialization.

The declarative approach using conditional rendering is cleaner than the previous imperative initialization. However, consider improving type safety by removing non-null assertions.

Apply this diff to remove non-null assertions:

        {hasAnalyticsKeys ? (
          <AnalyticsProvider
-            apiKey={env.NEXT_PUBLIC_POSTHOG_KEY!}
-            apiHost={env.NEXT_PUBLIC_POSTHOG_HOST!}
+            apiKey={env.NEXT_PUBLIC_POSTHOG_KEY}
+            apiHost={env.NEXT_PUBLIC_POSTHOG_HOST}
            userId={session?.user?.id}
          >
            {children}
          </AnalyticsProvider>
        ) : (
          children
        )}
packages/analytics/src/index.ts (1)

5-25: Consider adding error handling and type safety.

The implementation looks good with proper server-side safety checks. Consider these improvements:

  1. Add error handling for PostHog method calls
  2. Add type safety for event names to prevent typos

Example implementation:

+// Define allowed event names
+type EventName = "$pageview" | "custom_event_1" | "custom_event_2";

 export const Analytics = {
-  track: (eventName: string, properties?: Properties) => {
+  track: (eventName: EventName, properties?: Properties) => {
     if (typeof window === "undefined") return;
-    posthog.capture(eventName, properties);
+    try {
+      posthog.capture(eventName, properties);
+    } catch (error) {
+      console.error('Failed to track event:', error);
+    }
   },
   // Apply similar changes to other methods...
 };
packages/analytics/src/components/provider.tsx (1)

23-31: Consider adding error handling and type safety.

The PostHog initialization is well-structured and follows best practices. However, consider these improvements:

  1. Add error handling for the initialization
  2. Add type safety for the loaded callback
 // Initialize PostHog only once on the client side
-posthog.init(apiKey, {
-  api_host: apiHost,
-  loaded: (ph) => {
-    if (userId) {
-      ph.identify(userId);
-    }
-  },
-});
+try {
+  posthog.init(apiKey, {
+    api_host: apiHost,
+    loaded: (ph: typeof posthog) => {
+      if (userId) {
+        ph.identify(userId);
+      }
+    },
+  });
+} catch (error) {
+  console.error('Failed to initialize PostHog:', error);
+}
packages/analytics/src/components/page-view.tsx (1)

12-25: Consider enhancing URL construction robustness.

While the current implementation works, we could make it more resilient and maintainable.

Consider this refactoring:

  useEffect(() => {
    if (pathname && posthog) {
      // Track page views
-     const url = searchParams.toString()
-       ? `${pathname}?${searchParams.toString()}`
-       : pathname;
+     const getPageUrl = () => {
+       const params = searchParams.toString();
+       return params && searchParams.size > 0
+         ? `${pathname}?${params}`
+         : pathname;
+     };

      // Track pageview with current URL
      posthog.capture("$pageview", {
-       $current_url: url,
+       $current_url: getPageUrl(),
      });
    }
  }, [pathname, searchParams, posthog]);

This refactoring:

  • Adds an explicit check for empty searchParams using .size
  • Improves readability by extracting URL construction logic
  • Makes the code more maintainable and testable
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 69071b0 and 8a3d066.

📒 Files selected for processing (4)
  • apps/app/src/app/[locale]/providers.tsx (1 hunks)
  • packages/analytics/src/components/page-view.tsx (1 hunks)
  • packages/analytics/src/components/provider.tsx (1 hunks)
  • packages/analytics/src/index.ts (1 hunks)
🔇 Additional comments (9)
apps/app/src/app/[locale]/providers.tsx (1)

5-5: LGTM! Clean import changes.

The removal of the Analytics import while retaining AnalyticsProvider aligns well with the shift to a more declarative analytics initialization approach.

packages/analytics/src/index.ts (2)

1-4: Great architectural simplification!

The removal of the initialization complexity and direct usage of PostHog methods makes the implementation more maintainable while ensuring server-side safety.


27-29: LGTM!

The export statements are well-organized and clearly documented.

packages/analytics/src/components/provider.tsx (2)

21-21: LGTM! Good documentation.

The comment clearly explains why useEffect is used for PostHog initialization, which is important for understanding hydration-related concerns in React Server Components.


33-36: LGTM! Proper cleanup implementation.

The cleanup logic is correct and the removal of optional chaining is appropriate since PostHog is guaranteed to be initialized at this point.

packages/analytics/src/components/page-view.tsx (4)

1-6: LGTM! Clean import setup.

The imports are well-organized and include all necessary dependencies for PostHog page view tracking.


7-11: LGTM! Well-structured component setup.

The component is properly exported and uses the necessary hooks for page tracking functionality.


27-28: LGTM! Appropriate return value.

Correctly returns null as this is a tracking-only component with no UI elements.


1-28:

Details

✅ Verification successful

Verify integration with dependent components.

The AI summary indicates this component is used by evidence-related components. Let's verify the integration is not broken.


🏁 Script executed:

#!/bin/bash
# Search for usages of both old and new component names
echo "Searching for old PageViewTracker usage..."
rg "PageViewTracker"

echo -e "\nSearching for new PostHogPageView usage..."
rg "PostHogPageView"

Length of output: 755


Integration Verified: No further changes required

The search confirmed that there are no remaining references to the deprecated PageViewTracker, and all usages have been correctly updated to PostHogPageView. The new component is referenced in the following locations:

  • apps/web/src/app/components/posthog-pageview.tsx (both in the named and default export as SuspendedPostHogPageView)
  • packages/analytics/src/components/page-view.tsx
  • packages/analytics/src/components/provider.tsx

This indicates proper integration with dependent components, so you can proceed with confidence.

This branch was successfully deployed

1 active and 2 inactive deployments
Preview – app — 8a3d0666 Deployed Feb 24, 2025 by vercel[bot]
Preview – web — 8a3d0666 Deployed Feb 24, 2025 by vercel[bot]
Preview – comp-portal — 8a3d0666 Deployed Feb 24, 2025 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant