Skip to content

update layout of evidence#90

Merged
carhartlewis merged 5 commits into
mainfrom
mariano/stuff
Mar 3, 2025
Merged

update layout of evidence#90
carhartlewis merged 5 commits into
mainfrom
mariano/stuff

Conversation

@Marfuen
Copy link
Copy Markdown
Contributor

@Marfuen Marfuen commented Mar 3, 2025

Summary by CodeRabbit

  • New Features

    • Introduced an Edit Evidence page with an interactive form for updating evidence information.
    • Rolled out a refreshed dashboard layout with new navigation for quickly accessing evidence overview and edit sections.
    • Enhanced charts with dynamic legends and localized labels for a more intuitive visual experience.
    • Added a new Evidence Details component to display detailed evidence information with improved user feedback.
  • Refactor

    • Streamlined the Evidence Details view to display clear, alert-based information and improved loading states.
  • Chores

    • Updated localization content to provide clearer, more consistent interface text across multiple languages.

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 3, 2025

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 Mar 3, 2025 8:06pm
2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
comp-portal ⬜️ Skipped (Inspect) Mar 3, 2025 8:06pm
web ⬜️ Skipped (Inspect) Mar 3, 2025 8:06pm

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 3, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This pull request introduces several component restructurings and new features across the evidence module. The EvidenceDetails component has been simplified to use an alert-based layout that omits publish functionality. New components such as EditEvidencePage, EditEvidenceForm, and layout wrappers for both evidence details and overview have been added. A series of visualization components now incorporate internationalization support and helper functions for dynamic color and label management. Additionally, the pull request includes updates to middleware behavior, localization keys, linting scripts, and various hooks with adjusted import paths.

Changes

File(s) Change Summary
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/components/EvidenceDetails.tsx Restructured component layout to use an Alert instead of cards; removed publish functionality; simplified loading state display; integrated ReviewSection.
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/edit/page.tsx
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/edit/components/EditEvidenceForm.tsx
Added new EditEvidencePage and EditEvidenceForm components to support evidence editing with state management and data fetching.
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/layout.tsx
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/layout.tsx
Introduced new asynchronous Layout components that utilize internationalization; render a SecondaryMenu with navigation items and conditionally show a back button.
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/*
(AssigneeBarChart.tsx, DepartmentBarChart.tsx, EvidenceOverview.tsx, FrameworkBarChart.tsx, HorizontalBarChart.tsx)
Enhanced dashboard components with internationalization support, helper functions for status labels/colors, use of Card components, and conditional rendering (e.g. optional legend in HorizontalBarChart).
apps/app/src/locales/en.ts Updated evidence-related localization keys, streamlining titles and expanding entries for dashboard, overview, edit, items, statuses, departments, and details.
apps/app/src/middleware.ts Reintroduced the I18nMiddleware call after session checks and URL redirection; added a custom header "x-pathname" in the response.
apps/app/.vscode/settings.json
apps/app/package.json
Added new VSCode configuration recommending Biome formatter; updated the lint script from using Next.js linting to Biome linting on the ./src directory.
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/*
(useFileDelete.ts, useFilePreview.ts, useFileUpload.ts, useOrganizationAdmins.ts, useOrganizationEvidence.ts, useUrlManagement.ts)
Adjusted import paths from uppercase "Actions" to lowercase "actions"; minor formatting updates without affecting functionality.
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/components/*
(AssigneeSection.tsx, DepartmentSection.tsx, FileCard.tsx, FrequencySection.tsx, ReviewSection.tsx, UrlSection.tsx)
Modified import paths and reorganized code formatting; ReviewSection received layout adjustments and introduced publishEvidence and toggleRelevance action updates.
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/components/EvidenceList.tsx Reordered import statements for clarity; functional logic remains unchanged.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant EP as EditEvidencePage
    participant EF as EditEvidenceForm
    participant H as useOrganizationEvidence
    participant S as Server/API

    U->>EP: Navigate to Edit Evidence Page
    EP->>EF: Render EditEvidenceForm
    EF->>H: Request evidence data (ID)
    H->>S: Fetch evidence details
    S-->>H: Return evidence data
    H-->>EF: Provide evidence data
    EF->>U: Render form with files and URL sections
Loading
sequenceDiagram
    participant R as Request
    participant M as Middleware
    participant I as I18nMiddleware

    R->>M: Incoming HTTP request
    M->>M: Perform session checks and URL redirection
    M->>I: Invoke I18nMiddleware(request)
    I-->>M: Processed request with i18n context
    M->>M: Set "x-pathname" header with request.nextUrl.pathname
    M-->>R: Respond with enhanced headers
Loading

Possibly related PRs

  • Mariano/stuff #74: Addresses restructuring of the EvidenceDetails component similar to the changes in this PR.
  • fix evidence statuses across app #80: Focuses on modifications regarding evidence status display and removal of publish functionality, paralleling aspects of this PR.
  • Charts #85: Contains updates to the EvidenceDetails file with changes to import paths and the introduction of a new handleMutate function, aligning closely with the current modifications.

Poem

Hi there, I'm a joyful code rabbit,
Hopping through changes with a nimble habit.
Alerts replaced my bulky old card,
New pages and hooks working just as hard.
I twirl through layouts in a coder's delight,
Celebrating new paths with each leap so bright! 🐇✨


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 32bf193 and ec64611.

⛔ Files ignored due to path filters (1)
  • apps/app/languine.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTableContext.tsx (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTasks.ts (4 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/hooks/useEvidenceTasksStats.ts (3 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/list/page.tsx (1 hunks)
  • apps/app/src/locales/es.ts (14 hunks)
  • apps/app/src/locales/fr.ts (13 hunks)
  • apps/app/src/locales/no.ts (18 hunks)
  • apps/app/src/locales/pt.ts (23 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 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.
  • @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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

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

42-44: 🛠️ Refactor suggestion

Remove debug console logs before production

There are several debug console logs that should be removed before pushing to production.

Remove the debug console logs:

- // Debug: Log the incoming data
- useEffect(() => {
-   console.log("HorizontalBarChart - data:", data);
- }, [data]);

// Further down in the code:

- // Debug: Log the filtered data
- useEffect(() => {
-   console.log("HorizontalBarChart - filteredData:", filteredData);
- }, [filteredData]);

Also applies to: 69-72

🧹 Nitpick comments (11)
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/layout.tsx (2)

13-19: Consider enhancing the evidence ID regex pattern.

The current regex pattern /\/evidence\/[a-z0-9]+/ only matches lowercase letters and numbers. If your evidence IDs could contain other characters (like hyphens, underscores, or uppercase letters), this pattern might be too restrictive.

-  const isEvidenceDetails = /\/evidence\/[a-z0-9]+/.test(pathname);
+  const isEvidenceDetails = /\/evidence\/[\w-]+/.test(pathname);

15-19: Simplify path parsing logic for better readability.

The current code for extracting the evidence ID is somewhat complex. Consider using a more direct approach with a regex capture group or URL parsing for better readability and maintainability.

-  const pathParts = pathname.split("/");
-  const evidenceIndex = pathParts.findIndex((part) => part === "evidence");
-  const id =
-    evidenceIndex >= 0 && pathParts.length > evidenceIndex + 1
-      ? pathParts[evidenceIndex + 1]
-      : "";
+  // Extract ID directly using regex
+  const evidenceIdMatch = pathname.match(/\/evidence\/([^\/]+)/);
+  const id = evidenceIdMatch ? evidenceIdMatch[1] : "";
apps/app/src/middleware.ts (1)

40-40: Consider URL encoding the pathname value.

The current implementation sets the raw pathname to the header. To handle special characters properly, consider URL encoding the pathname value.

-  response.headers.set("x-pathname", request.nextUrl.pathname);
+  response.headers.set("x-pathname", encodeURIComponent(request.nextUrl.pathname));

Then decode it when used in components:

// In components that use this header
const pathname = decodeURIComponent(headersList.get("x-pathname") || "");
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/HorizontalBarChart.tsx (2)

111-115: Consider abstracting bar width calculation logic to improve readability

The bar width calculation could be made more readable and maintainable by extracting it to a dedicated function.

Consider refactoring to use a helper function:

+ const calculateBarWidthAndPosition = (value, index, data) => {
+   const barWidth = (value / totalWidth) * 100;
+   const currentPosition = data
+     .slice(0, index)
+     .reduce((sum, item) => sum + (item.value / totalWidth) * 100 + gap, 0);
+   return { barWidth, position: currentPosition };
+ };

  {filteredData.map((d, index) => {
-   const barWidth = (d.value / totalWidth) * 100;
-   const xPosition = cumulativeWidth;
-   cumulativeWidth += barWidth + gap;
+   const { barWidth, position } = calculateBarWidthAndPosition(d.value, index, filteredData);
+   
    return (
      <div
        key={d.key}
        className="relative"
        style={{
          width: `${barWidth}%`,
          height: `${barHeight}px`,
-         left: `${xPosition}%`,
+         left: `${position}%`,
          position: "absolute",
        }}
      >

144-158: Legend implementation looks good but consider accessibility improvements

The legend implementation is clean and correctly uses the showLegend prop to conditionally render. However, it could benefit from improved accessibility attributes.

Enhance the legend with ARIA attributes for better accessibility:

  {showLegend && (
-   <div className="flex flex-wrap gap-3 text-xs text-muted-foreground mt-2">
+   <div className="flex flex-wrap gap-3 text-xs text-muted-foreground mt-2" role="list" aria-label="Chart legend">
      {filteredData.map((item) => (
        <div
          key={`legend-${String(item.key)}`}
-         className="flex items-center gap-1"
+         className="flex items-center gap-1" 
+         role="listitem"
        >
-         <div className="size-2" style={{ backgroundColor: item.color }} />
+         <div 
+           className="size-2" 
+           style={{ backgroundColor: item.color }} 
+           aria-hidden="true" 
+         />
          <span>
            {item.label} ({valueFormatter(item.value)})
          </span>
        </div>
      ))}
    </div>
  )}
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/EvidenceOverview.tsx (1)

15-17: Consider enhancing loading state with skeleton loaders

The current loading state is very basic. Consider using skeleton loaders to provide a more appealing loading experience.

Enhance the loading state with skeleton loaders:

  if (isLoading) {
-   return <div>Loading...</div>;
+   return (
+     <div className="space-y-8">
+       <h2 className="text-2xl font-semibold">
+         <div className="h-8 w-48 bg-gray-200 rounded animate-pulse" />
+       </h2>
+       <div className="grid grid-cols-1 md:grid-cols-2 gap-8">
+         {[1, 2, 3].map((i) => (
+           <Card key={i} className={i === 3 ? "md:col-span-2" : ""}>
+             <CardHeader>
+               <div className="h-6 w-32 bg-gray-200 rounded animate-pulse" />
+             </CardHeader>
+             <CardContent>
+               <div className="h-28 w-full bg-gray-200 rounded animate-pulse" />
+             </CardContent>
+           </Card>
+         ))}
+       </div>
+     </div>
+   );
  }
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/ReviewSection.tsx (2)

154-163: Publish button implementation is good but consider feedback enhancement

The publish button is well-implemented with proper loading state handling. However, there's no visual feedback to indicate when an evidence item is already published.

Consider adding a visual indicator for published evidence:

+ {evidence.published && (
+   <div className="flex items-center gap-2 text-sm text-green-600 w-fit self-end">
+     <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-check-circle">
+       <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" />
+       <polyline points="22 4 12 14.01 9 11.01" />
+     </svg>
+     Published
+   </div>
+ )}
  {!evidence.published && (
    <Button
      size="sm"
      className="w-fit self-end"
      onClick={() => publishAction({ id })}
      disabled={isExecuting}
    >
      {isExecuting ? "Publishing..." : "Publish"}
    </Button>
  )}

64-166: Consider adding a confirmation dialog for publishing

Publishing evidence might be a significant action that should require confirmation, especially if it has implications for compliance or reviews.

Consider adding a confirmation dialog before publishing:

+ import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@bubba/ui/dialog";
+ import { useState } from "react";

// Within the component:
+ const [showPublishDialog, setShowPublishDialog] = useState(false);
+ 
+ const handlePublish = () => {
+   publishAction({ id });
+   setShowPublishDialog(false);
+ };

// Replace the current publish button with:
  {!evidence.published && (
-   <Button
-     size="sm"
-     className="w-fit self-end"
-     onClick={() => publishAction({ id })}
-     disabled={isExecuting}
-   >
-     {isExecuting ? "Publishing..." : "Publish"}
-   </Button>
+   <Dialog open={showPublishDialog} onOpenChange={setShowPublishDialog}>
+     <DialogTrigger asChild>
+       <Button size="sm" className="w-fit self-end">
+         Publish
+       </Button>
+     </DialogTrigger>
+     <DialogContent>
+       <DialogHeader>
+         <DialogTitle>Publish Evidence</DialogTitle>
+         <DialogDescription>
+           Publishing this evidence will make it visible to reviewers. Are you sure you want to proceed?
+         </DialogDescription>
+       </DialogHeader>
+       <DialogFooter>
+         <Button variant="outline" onClick={() => setShowPublishDialog(false)}>
+           Cancel
+         </Button>
+         <Button onClick={handlePublish} disabled={isExecuting}>
+           {isExecuting ? "Publishing..." : "Publish"}
+         </Button>
+       </DialogFooter>
+     </DialogContent>
+   </Dialog>
  )}
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/DepartmentBarChart.tsx (2)

209-239: Inconsistency between color systems

The getStatusColor function returns hardcoded hex values which don't match the CSS variables used in STATUS_COLORS. This creates a maintenance challenge as color updates would need to be made in multiple places.

Consider refactoring to use CSS variables consistently:

function getStatusColor(status: StatusType): string {
  switch (status) {
-    case "upToDate":
-      return "#10b981"; // Green
-    case "draft":
-      return "#f59e0b"; // Amber
-    case "needsReview":
-      return "#ef4444"; // Red
-    case "empty":
-      return "#6b7280"; // Gray
-    default:
-      return "#6b7280"; // Default gray
+    case "upToDate":
+      return "var(--primary)"; // Green
+    case "draft":
+      return "var(--chart-open)"; // Amber
+    case "needsReview":
+      return "hsl(var(--destructive))"; // Red
+    case "empty":
+      return "var(--chart-pending)"; // Gray
+    default:
+      return "var(--chart-pending)"; // Default gray
  }
}

Alternatively, consider creating a shared helper function across all charts to avoid duplication.


210-210: Type the translation function properly

The t parameter in getStatusLabel is typed as any, which loses type safety.

Consider importing the proper type from your i18n library:

- function getStatusLabel(status: StatusType, t: any): string {
+ import type { Translator } from "@/locales/client";
+ function getStatusLabel(status: StatusType, t: Translator): string {
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/AssigneeBarChart.tsx (1)

225-255: Performance consideration: Console logging in production

There are numerous console.log statements throughout the chart components which should be removed before production deployment.

Consider removing all console.log statements or wrapping them in a debug utility that only logs in development:

// Create a utility function in a shared file
export function debugLog(...args: any[]): void {
  if (process.env.NODE_ENV === 'development') {
    console.log(...args);
  }
}

// Then replace console.log calls:
- console.log(`Status counts for ${assigneeId}:`, statusCounts);
+ debugLog(`Status counts for ${assigneeId}:`, statusCounts);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ca6ec36 and 187563b.

⛔ 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 (14)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/EvidenceList.tsx (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/ReviewSection.tsx (6 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/edit/page.tsx (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/layout.tsx (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/list/layout.tsx (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/AssigneeBarChart.tsx (8 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/DepartmentBarChart.tsx (8 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/EvidenceOverview.tsx (2 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/FrameworkBarChart.tsx (7 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/HorizontalBarChart.tsx (5 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/layout.tsx (1 hunks)
  • apps/app/src/locales/en.ts (1 hunks)
  • apps/app/src/middleware.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/Components/EvidenceList.tsx
🔇 Additional comments (35)
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/list/layout.tsx (1)

17-17: Translation key updated for consistency.

The translation key has been updated from "evidence.dashboard" to "evidence.dashboard.layout", which aligns with the hierarchical structure of the localization keys seen in other files.

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

1-26: New layout component establishes consistent navigation structure.

The new Layout component properly implements the secondary menu navigation and maintains consistency with the other evidence-related pages. It correctly uses the translation keys and provides appropriate spacing for the content.

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

23-34: Good use of conditional back button for improved navigation.

The implementation of the secondary menu with a conditional back button is well done. This provides a clear navigation path for users to return to the evidence list, improving the overall user experience.

apps/app/src/middleware.ts (1)

39-41:

Details

❓ Verification inconclusive

Middleware order change and custom header addition.

Moving the I18nMiddleware to run after session checks and adding the custom x-pathname header is a good approach to provide path information to components. This enables the dynamic path extraction in the evidence detail layout.

Verify that all components that rely on internationalization continue to work correctly with this new ordering.


🏁 Script executed:

#!/bin/bash
# Check for components that might be affected by the middleware change

# Look for components using internationalization that might be impacted
echo "Checking components using internationalization:"
rg -l "useI18n|getI18n" --type=tsx apps/app/src/app

# Check if there are any other places using the x-pathname header
echo -e "\nChecking for components using x-pathname header:"
rg -l "x-pathname" --type=tsx apps/app/src/

Length of output: 371


Below is a revised review comment. I’ve also provided an updated shell script that removes the TSX file type specification so you can re-run the checks without the “unrecognized file type” error. Please run the script below and manually verify that components using internationalization (e.g. those relying on hooks like useI18n or getI18n) are still functioning correctly, and that any component reading the custom x-pathname header behaves as expected.


Middleware ordering and header addition: Manual Verification Needed

Moving the I18nMiddleware after session checks and adding the custom x-pathname header appears to be a solid approach for providing path information to components such as the evidence detail layout. However, please verify that:

  • All components that rely on internationalization (e.g. via useI18n or getI18n) continue to work correctly.
  • The new x-pathname header is correctly consumed wherever it is expected.

To assist with this, please run the following shell script (which omits the problematic TSX file type flag) to locate references to these:

After executing the script, manually investigate any relevant findings to ensure that no issues arise from the middleware order change.


🏁 Script executed:

#!/bin/bash
set -e

echo "Checking for components using internationalization (primitive search):"
rg -l "useI18n|getI18n" apps/app/src/app

echo -e "\nChecking for usage of x-pathname header (primitive search):"
rg -l "x-pathname" apps/app/src/

Length of output: 3958


Middleware Ordering and Header Addition Verification

The updated middleware ordering—executing I18nMiddleware after session checks—and the addition of the custom x-pathname header appear correct. The static code searches confirm that:

  • Numerous components (e.g., in apps/app/src/app/[locale]/(app)/(dashboard)/...) are using internationalization hooks (useI18n/getI18n).
  • The x-pathname header is referenced in both the middleware and in key locations such as the evidence layout (apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/layout.tsx).

Please perform a runtime/manual verification that these components continue to function correctly with the updated middleware order and header addition.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/edit/page.tsx (1)

42-64: The Card layout implementation looks good

The Card layout structure is well-organized with proper component hierarchy using CardHeader, CardTitle, and CardContent. The spacing between sections is consistent, and the component correctly passes the necessary props to child components.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/HorizontalBarChart.tsx (2)

20-20: Props interface update for showLegend looks good

Adding the optional showLegend prop with a default value of false is a clean way to implement conditional rendering of the legend.

Also applies to: 39-39


81-84: Bar width calculation logic change looks good

The new approach to calculating bar widths and managing gaps between segments provides better control over the visualization.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/EvidenceOverview.tsx (3)

8-9: Good internationalization implementation

The addition of the useI18n hook and the usage of translation keys instead of hardcoded strings is a good practice for supporting multiple languages.

Also applies to: 13-13


29-31: Heading element looks good with i18n

The main heading is now properly using the internationalization function for the title.


35-63: Card-based layout is well-structured

The refactoring to use Card components provides a more consistent and structured layout. The grid layout and spacing are well-considered, and the responsive design (md: breakpoints) is appropriate.

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

4-16: Import organization is improved

The reorganization of imports provides better readability and follows a consistent pattern of grouping related imports.


53-61: Publishing functionality looks well-implemented

The addition of the publish action with proper loading state, success, and error handling is well-implemented.


65-73: Card header structure is improved

The updated card header with a main title and subtitle provides better information hierarchy and context for the user.


93-153: Grid layout is more structured than the previous flexbox approach

Changing from flexbox to grid provides a cleaner, more predictable layout for the different sections.

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

3-3: LGTM: Good choice using the Alert component system

The migration from Card components to Alert provides a more appropriate visual structure for presenting evidence details.


19-22: Improved loading state with visual hierarchy

Using different skeleton heights creates a better visual hierarchy during loading, making the loading state feel more natural and intentional.


31-33: LGTM: Simplified data refresh logic

The handleMutate function is now more focused and only defined after the loading/data checks, which is cleaner.


37-68: Improved evidence presentation with semantic markup

The new Alert-based layout provides a more focused and contextually appropriate way to display evidence information. The combination of icon, title, and status indicators creates a clearer information hierarchy.

The status indicators with appropriate icons and colors also improve the user experience by making the current state more immediately recognizable.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/DepartmentBarChart.tsx (4)

8-8: LGTM: Added internationalization support

Good addition of the useI18n hook for proper internationalization.


14-20: LGTM: Improved color system with CSS variables

Using CSS variables for status colors improves theme consistency across components and supports better theming capabilities.


120-122: LGTM: Improved internationalization support for department names

Good implementation of both fallback to DEPARTMENT_NAMES and translations via t function.


169-185: Enhanced visualization with status legend

The addition of a legend improves clarity by providing context for the color coding in the chart.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/FrameworkBarChart.tsx (3)

7-7: LGTM: Added internationalization support

Good addition of the useI18n hook for proper internationalization.


13-19: LGTM: Improved color system with CSS variables

Using CSS variables for status colors improves theme consistency across components and supports better theming capabilities.


153-169: Enhanced visualization with status legend

The addition of a legend improves clarity by providing context for the color coding in the chart.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/AssigneeBarChart.tsx (3)

7-7: LGTM: Added internationalization support

Good addition of the useI18n hook for proper internationalization.


14-20: LGTM: Improved color system with CSS variables

Using CSS variables for status colors improves theme consistency across components and supports better theming capabilities.


185-201: Enhanced visualization with status legend

The addition of a legend improves clarity by providing context for the color coding in the chart.

apps/app/src/locales/en.ts (7)

791-791: Title simplification improves clarity and consistency.

The title has been simplified from "Evidence Tasks" to just "Evidence", which provides a cleaner and more consistent naming convention throughout the application.


793-795: Good addition of key navigation sections.

Adding dedicated localization keys for "Overview" and "Edit Evidence" provides better support for these important user journeys within the evidence module.


795-802: Well-structured dashboard localization hierarchy.

The dashboard section has been organized into a logical hierarchy with clear keys for layout, navigation, title, and different categorization methods. This structure will support a more comprehensive and intuitive dashboard interface.


803-803: Added generic items key for better pluralization support.

Adding the "items" key allows for proper pluralization in UI elements, which is a good internationalization practice to support different language rules.


804-809: Comprehensive status categorization enhances filtering capabilities.

The well-defined status values ("Up to Date", "Needs Review", "Draft", "Empty") provide a clear set of states for evidence items, which will improve filtering and status indicators in the UI.


810-818: Thorough department categorization supports organizational structure.

The departments section provides a comprehensive set of department categories that align with common organizational structures in compliance-focused companies. Including an "Uncategorized" option under the "none" key is good practice for handling items without a department assignment.


819-822: Clear separation of review and content sections improves UX organization.

The details section clearly separates "Review Information" from "Evidence Content", providing a logical structure for the evidence details view that helps users distinguish between metadata and actual content.

Comment on lines +16 to +22
if (isLoading) {
return <Skeleton className="h-20 w-full" />;
}

if (error) {
return <div>Error</div>;
}
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

Remove duplicate loading state handling

The component contains two separate loading state handlers that render different skeleton UIs. The first one (lines 16-18) is more concise, while the second one (lines 28-36) is more detailed but will never be reached since the first condition already returns.

Apply this change to fix the issue:

  if (isLoading) {
    return (
-      <Skeleton className="h-20 w-full" />
+      <div className="flex flex-col gap-4">
+        <Skeleton className="h-20 w-full" />
+        <Skeleton className="h-40 w-full" />
+        <Skeleton className="h-60 w-full" />
+      </div>
    );
  }

  if (error) {
    return <div>Error</div>;
  }

  const handleMutate = async () => {
    await mutate();
  };

- if (isLoading) {
-   return (
-     <div className="flex flex-col gap-4">
-       <Skeleton className="h-20 w-full" />
-       <Skeleton className="h-40 w-full" />
-       <Skeleton className="h-60 w-full" />
-     </div>
-   );
- }

Also applies to: 28-36

Comment on lines +20 to +22
if (error) {
return <div>Error</div>;
}
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

Enhance error handling with error details and retry option

The current error state only displays "Error" without any details or recovery options, which provides a poor user experience.

Improve the error handling with more context and a retry option:

  if (error) {
-   return <div>Error</div>;
+   return (
+     <div className="flex flex-col gap-4 items-center p-4">
+       <div className="text-red-500 font-medium">Failed to load evidence details</div>
+       <p className="text-sm text-muted-foreground">{error.message || "An unexpected error occurred"}</p>
+       <Button variant="outline" size="sm" onClick={() => mutate()}>
+         Retry
+       </Button>
+     </div>
+   );
  }
📝 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
if (error) {
return <div>Error</div>;
}
if (error) {
return (
<div className="flex flex-col gap-4 items-center p-4">
<div className="text-red-500 font-medium">Failed to load evidence details</div>
<p className="text-sm text-muted-foreground">{error.message || "An unexpected error occurred"}</p>
<Button variant="outline" size="sm" onClick={() => mutate()}>
Retry
</Button>
</div>
);
}

Comment on lines +192 to +222
// Helper function to get status label
function getStatusLabel(status: StatusType, t: any): string {
switch (status) {
case "upToDate":
return t("evidence.status.up_to_date");
case "needsReview":
return t("evidence.status.needs_review");
case "draft":
return t("evidence.status.draft");
case "empty":
return t("evidence.status.empty");
default:
return status;
}
}

// Helper function to get status color
function getStatusColor(status: StatusType): string {
switch (status) {
case "upToDate":
return "#10b981"; // Green
case "draft":
return "#f59e0b"; // Amber
case "needsReview":
return "#ef4444"; // Red
case "empty":
return "#6b7280"; // Gray
default:
return "#6b7280"; // Default gray
}
}
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

DRY violation: Duplicated helper functions across charts

The getStatusLabel and getStatusColor functions are duplicated across multiple chart components (DepartmentBarChart, FrameworkBarChart, AssigneeBarChart).

Extract these helper functions to a shared utility file to improve maintainability:

// Create a new file: apps/app/src/app/[locale]/(app)/(dashboard)/evidence/overview/components/chartUtils.ts

import type { Translator } from "@/locales/client";

export const STATUS_PRIORITY = ["upToDate", "draft", "needsReview", "empty"] as const;
export type StatusType = (typeof STATUS_PRIORITY)[number];

export const STATUS_COLORS = {
  upToDate: "bg-primary",
  draft: "bg-[var(--chart-open)]",
  needsReview: "bg-[hsl(var(--destructive))]",
  empty: "bg-[var(--chart-pending)]",
};

export function getStatusLabel(status: StatusType, t: Translator): string {
  switch (status) {
    case "upToDate":
      return t("evidence.status.up_to_date");
    case "needsReview":
      return t("evidence.status.needs_review");
    case "draft":
      return t("evidence.status.draft");
    case "empty":
      return t("evidence.status.empty");
    default:
      return status;
  }
}

export function getStatusColor(status: StatusType): string {
  switch (status) {
    case "upToDate":
      return "var(--primary)"; // Green 
    case "draft":
      return "var(--chart-open)"; // Amber
    case "needsReview":
      return "hsl(var(--destructive))"; // Red
    case "empty":
      return "var(--chart-pending)"; // Gray
    default:
      return "var(--chart-pending)"; // Default gray
  }
}

Then import these from each chart component to avoid code duplication.

- Rename Components directory to lowercase components
- Update import paths to reflect new directory structure
- Reorganize actions and hooks imports
- Migrate edit evidence page to use client component with server-side data fetching
- Apply consistent formatting and trailing comma rules
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (4)
apps/app/package.json (1)

9-9: Switch from Next.js linter to Biome linter

This change replaces Next.js's built-in linting tool with Biome linter, targeting only the src directory. Biome is a fast formatter and linter with stricter defaults.

Consider adding a .biome.json configuration file in the project root to maintain consistent linting rules across the codebase. Also, ensure team members are aware of this tooling change as it might affect their workflow.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/edit/components/EditEvidenceForm.tsx (1)

30-32: Add error handling to mutate function

The handleMutate function doesn't handle failures of the mutation operation.

Consider adding try/catch block to handle potential errors during mutation:

-	const handleMutate = async () => {
-		await mutate();
-	};
+	const handleMutate = async () => {
+		try {
+			await mutate();
+		} catch (error) {
+			toast.error("Failed to update evidence data");
+			console.error("Mutation failed:", error);
+		}
+	};

Don't forget to import the toast component at the top of the file:

import { toast } from "sonner";
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/ReviewSection.tsx (1)

93-153: Consider responsive layout for smaller screens

The grid layout with 2 columns works well on desktop but might not be optimal on smaller screens.

Consider using responsive grid columns to ensure a better experience on mobile devices:

-        <div className="grid grid-cols-2 gap-8">
+        <div className="grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-8">
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/EvidenceDetails.tsx (1)

27-29: Consider adding error handling to mutate function

Similar to the EditEvidenceForm component, the handleMutate function here could benefit from error handling.

-  const handleMutate = async () => {
-    await mutate();
-  };
+  const handleMutate = async () => {
+    try {
+      await mutate();
+    } catch (error) {
+      console.error("Failed to update evidence:", error);
+      // Consider adding a toast notification here
+    }
+  };
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 187563b and b6f884a.

📒 Files selected for processing (19)
  • apps/app/.vscode/settings.json (1 hunks)
  • apps/app/package.json (2 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/AssigneeSection.tsx (2 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/DepartmentSection.tsx (4 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 (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FrequencySection.tsx (3 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/ReviewSection.tsx (6 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/UrlSection.tsx (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/edit/components/EditEvidenceForm.tsx (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/edit/page.tsx (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFileDelete.ts (2 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFilePreview.ts (2 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFileUpload.ts (3 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useOrganizationAdmins.ts (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useOrganizationEvidence.ts (3 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useUrlManagement.ts (3 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/page.tsx (1 hunks)
  • apps/app/src/middleware.ts (1 hunks)
✅ Files skipped from review due to trivial changes (12)
  • apps/app/.vscode/settings.json
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FrequencySection.tsx
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useOrganizationEvidence.ts
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/DepartmentSection.tsx
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/UrlSection.tsx
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFileUpload.ts
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useOrganizationAdmins.ts
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/FileCard.tsx
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Components/AssigneeSection.tsx
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFilePreview.ts
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/page.tsx
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useUrlManagement.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/edit/page.tsx
  • apps/app/src/middleware.ts
🔇 Additional comments (9)
apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFileDelete.ts (2)

46-46: Trailing comma removed from dependency array.

The trailing comma in the useCallback dependency array has been removed. This is a minor style change that doesn't affect functionality.


15-47: Implementation looks correct and follows React best practices.

The useCallback implementation correctly memoizes the handleDelete function with the appropriate dependencies. The error handling is robust, with specific error messages and appropriate toast notifications for success and failure cases.

apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/edit/components/EditEvidenceForm.tsx (1)

38-61: LGTM! Card layout structure is well-implemented

The card layout with separate sections for files and URLs is well-structured and provides a good separation of concerns. The component correctly passes the necessary props to child components.

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

4-11: Improved import organization

The imports have been reorganized for better readability and grouping.


53-61: Well-implemented publish evidence functionality

The publish evidence action is properly implemented with loading state handling and appropriate success/error toast notifications.


65-91: Better evidence overview presentation

The card header now provides more context with an improved title and helpful subtitle that clearly communicates the purpose of this section.


154-163: Well-implemented conditional publish button

The publish button is correctly shown only when the evidence isn't published yet, and it includes proper loading state management.

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

13-21: Simplified loading state

The loading skeleton has been simplified to a more straightforward structure with appropriately sized placeholders.


32-64: Improved layout with Alert component

The switch from Card to Alert component provides a more appropriate semantic structure for displaying evidence information and its status.

Consider extracting the status indicator into a separate component for better reusability:

+ const PublishStatus = ({ published }: { published: boolean }) => {
+   return published ? (
+     <div className="flex items-center gap-2">
+       <CheckCircle2 size={16} className="text-green-500 shrink-0" />
+       <span className="text-sm text-green-600">Published</span>
+     </div>
+   ) : (
+     <div className="flex items-center gap-2">
+       <XCircle size={16} className="text-red-500 shrink-0" />
+       <span className="text-sm text-red-600">Draft</span>
+     </div>
+   );
+ };

Then use it within the AlertTitle:

<div className="flex items-center gap-2">
  <PublishStatus published={evidence.published} />
</div>

import { useCallback } from "react";
import { useToast } from "@bubba/ui/use-toast";
import { deleteEvidenceFile } from "../Actions/deleteEvidenceFile";
import { deleteEvidenceFile } from "../actions/deleteEvidenceFile";
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

🧩 Analysis chain

Directory path casing updated for consistency.

The import path has been updated from ../Actions/deleteEvidenceFile to ../actions/deleteEvidenceFile, changing from uppercase to lowercase. This aligns with common JavaScript/TypeScript conventions for directory naming.


🏁 Script executed:

#!/bin/bash
# Check if both the old (Actions) and new (actions) directories exist
# which could indicate that the directory wasn't actually renamed

echo "Checking directory structure..."
if [ -d "apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions" ] && [ -d "apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/actions" ]; then
  echo "WARNING: Both 'Actions' and 'actions' directories exist. This could cause issues."
elif [ -d "apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/Actions" ]; then
  echo "WARNING: Only the old 'Actions' directory exists. The import may fail."
elif [ -d "apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/actions" ]; then
  echo "SUCCESS: Only the new 'actions' directory exists. The import should work correctly."
else
  echo "WARNING: Neither directory exists. The import will fail."
fi

# Check if there are other imports from the old Actions directory that might need updating
echo "Checking for other imports using the old path..."
rg -l "from \".*Actions/" --type ts

Length of output: 1276


Action Required: Resolve Import Case Inconsistency

The import in apps/app/src/app/[locale]/(app)/(dashboard)/evidence/[id]/hooks/useFileDelete.ts was changed from

import { deleteEvidenceFile } from "../Actions/deleteEvidenceFile";

to

import { deleteEvidenceFile } from "../actions/deleteEvidenceFile";

However, the verification script indicates that only the old "Actions" directory exists on disk. This means the current change to lowercase will likely cause the import to fail on case-sensitive filesystems. Additionally, similar imports in other parts of the project still reference the uppercase directory.

Recommendations:

  • Revert or Correct: Revert the change in useFileDelete.ts to use the correct casing (i.e., "../Actions/deleteEvidenceFile") unless the intended change is to rename the directory.
  • Consistency Check: If a change to lowercase is desired project-wide, update the filesystem (rename the directory) and modify all affected import paths accordingly.

Comment on lines +26 to +28
if (error) {
return <div>Error</div>;
}
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

Improve error handling with more context

The current error state displays a generic message without providing any useful information to the user.

Enhance the error handling by providing more context about what went wrong and possibly offering recovery options:

-	if (error) {
-		return <div>Error</div>;
-	}
+	if (error) {
+		return (
+			<div className="p-4 text-red-600 border border-red-300 rounded-md bg-red-50">
+				<p className="font-medium">Failed to load evidence</p>
+				<p className="text-sm">{error.message || "Please try again or contact support if the issue persists."}</p>
+			</div>
+		);
+	}
📝 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
if (error) {
return <div>Error</div>;
}
if (error) {
return (
<div className="p-4 text-red-600 border border-red-300 rounded-md bg-red-50">
<p className="font-medium">Failed to load evidence</p>
<p className="text-sm">
{error.message || "Please try again or contact support if the issue persists."}
</p>
</div>
);
}

- Update evidence-related translations in es, fr, no, and pt locales
- Refactor evidence section with consistent keys and structure
- Add new translations for evidence dashboard, status, and departments
- Improve language consistency and formatting
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.

2 participants