-
Notifications
You must be signed in to change notification settings - Fork 5
feat: add Interactive Dashboard with Sidebar, Header, Chart, and Data Table Components #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: add Interactive Dashboard with Sidebar, Header, Chart, and Data Table Components #3
Conversation
WalkthroughThis PR introduces an extensive UI component library built on Radix UI and Recharts, adds admin dashboard components featuring drag-and-drop tables and interactive charts, updates dependencies for drag-and-drop and theme support, and refactors the Dashboard to use a new SidebarProvider architecture. Changes
Estimated code review effortπ― 4 (Complex) | β±οΈ ~45 minutes
Poem
Pre-merge checks and finishing touchesβ Failed checks (1 warning)
β Passed checks (2 passed)
β¨ Finishing touches
π§ͺ Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 15
π§Ή Nitpick comments (28)
frontend/src/components/ui/skeleton.tsx (2)
1-3: Import React types explicitly instead of relying on globalReactnamespaceUsing
React.ComponentProps<"div">assumes theReactnamespace is globally available in types, which may not hold depending on your TS config. Safer to import the type explicitly:+import type { ComponentProps } from "react" import { cn } from "@/lib/utils" -function Skeleton({ className, ...props }: React.ComponentProps<"div">) { +function Skeleton({ className, ...props }: ComponentProps<"div">) {This avoids surprises if global React types are ever removed or reconfigured.
5-9: Consider basic accessibility semantics for skeletonsIf this skeleton is purely visual (no meaningful content), you might want to hide it from assistive tech to avoid noise in the accessibility tree:
- <div + <div data-slot="skeleton" className={cn("bg-accent animate-pulse rounded-md", className)} + aria-hidden="true" {...props} />Adjust if some usages need it to be announced, but defaulting to
aria-hiddenis usually safer for generic skeleton placeholders.frontend/src/components/ui/label.tsx (1)
8-22: Label wrapper looks solid; consider forwardRef for ref support and consistencyThe wrapper correctly passes props to
LabelPrimitive.Root, merges classes withcn, and adds adata-slotfor styling. Functionally this is fine.If your other Radix-based primitives use
React.forwardRef, you might want to align this one by forwarding the ref and exporting a typed props alias. That keeps ref behavior consistent with@radix-ui/react-labeland can help with accessibility tooling or focusing labels programmatically.Example refactor:
-import * as React from "react" +import * as React from "react" import * as LabelPrimitive from "@radix-ui/react-label" import { cn } from "@/lib/utils" -function Label({ - className, - ...props -}: React.ComponentProps<typeof LabelPrimitive.Root>) { - return ( - <LabelPrimitive.Root - data-slot="label" - className={cn( - "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", - className - )} - {...props} - /> - ) -} - -export { Label } +type LabelProps = React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> + +const Label = React.forwardRef< + React.ElementRef<typeof LabelPrimitive.Root>, + LabelProps +>(({ className, ...props }, ref) => ( + <LabelPrimitive.Root + ref={ref} + data-slot="label" + className={cn( + "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", + className + )} + {...props} + /> +)) + +Label.displayName = LabelPrimitive.Root.displayName + +export { Label }frontend/src/components/ui/checkbox.tsx (1)
7-27: Consider usingforwardRefforCheckboxto support refs and better interopRight now
Checkboxis a plain function component, so consumers cannot attach a ref (e.g., for focus management or form libraries that expect it). A small refactor toReact.forwardRefwould align with common Radix wrapper patterns and keep the typing tight.Example refactor:
-function Checkbox({ - className, - ...props -}: React.ComponentProps<typeof CheckboxPrimitive.Root>) { - return ( - <CheckboxPrimitive.Root - data-slot="checkbox" - className={cn( - "peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50", - className - )} - {...props} - > - <CheckboxPrimitive.Indicator - data-slot="checkbox-indicator" - className="flex items-center justify-center text-current transition-none" - > - <CheckIcon className="size-3.5" /> - </CheckboxPrimitive.Indicator> - </CheckboxPrimitive.Root> - ) -} +const Checkbox = React.forwardRef< + React.ElementRef<typeof CheckboxPrimitive.Root>, + React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> +>(({ className, ...props }, ref) => ( + <CheckboxPrimitive.Root + ref={ref} + data-slot="checkbox" + className={cn( + "peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50", + className + )} + {...props} + > + <CheckboxPrimitive.Indicator + data-slot="checkbox-indicator" + className="flex items-center justify-center text-current transition-none" + > + <CheckIcon className="size-3.5" /> + </CheckboxPrimitive.Indicator> + </CheckboxPrimitive.Root> +)) + +Checkbox.displayName = "Checkbox"frontend/src/components/ui/sonner.tsx (1)
4-21: MergeclassNameandstylewith caller props to avoid dropping defaultsWith
...propsspread afterclassNameandstyle(Line 18), any passedclassNameorstylewill fully override"toaster group"and the CSS variables for Sonner, which can accidentally strip your base styling.Consider destructuring and merging instead:
-const Toaster = ({ ...props }: ToasterProps) => { - const { theme = "system" } = useTheme() - - return ( - <Sonner - theme={theme as ToasterProps["theme"]} - className="toaster group" - style={ - { - "--normal-bg": "var(--popover)", - "--normal-text": "var(--popover-foreground)", - "--normal-border": "var(--border)", - } as React.CSSProperties - } - {...props} - /> - ) -} +const Toaster = ({ className, style, ...props }: ToasterProps) => { + const { theme = "system" } = useTheme() + + const cssVars = { + "--normal-bg": "var(--popover)", + "--normal-text": "var(--popover-foreground)", + "--normal-border": "var(--border)", + } as React.CSSProperties + + return ( + <Sonner + theme={theme as ToasterProps["theme"]} + className={cn("toaster group", className)} + style={{ ...cssVars, ...(style as React.CSSProperties) }} + {...props} + /> + ) +}(Youβd need to import
cnhere as well.)frontend/src/components/ui/card.tsx (1)
5-82: Optional: consider semantic elements forCardTitle/CardDescriptionCurrently
CardTitleandCardDescriptionare plain<div>s (Lines 31β49). Thatβs flexible, but you may want stronger semantics for assistive tech and document structure:
- Use a heading element for
CardTitle(e.g.,<h2>/<h3>), or- Support an
asChild/asprop so consumers can choose<h*>/<p>while reusing your styles.Not required for functionality, but worth considering if cards often represent primary sections.
frontend/src/components/ui/input.tsx (1)
5-19: Add ref forwarding for better composability.The Input component should forward refs to support form libraries (like React Hook Form) and parent component access to the underlying input element.
Apply this diff to add ref forwarding:
-function Input({ className, type, ...props }: React.ComponentProps<"input">) { - return ( +const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>( + ({ className, type, ...props }, ref) => { + return ( - <input - type={type} - data-slot="input" - className={cn( - "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", - "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", - "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", - className - )} - {...props} - /> - ) -} + <input + type={type} + data-slot="input" + className={cn( + "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", + "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", + "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + className + )} + ref={ref} + {...props} + /> + ) + } +) +Input.displayName = "Input"frontend/src/components/admin/site-header.tsx (1)
16-25: Extract hardcoded GitHub URL to a config constant.The GitHub URL is hardcoded in the component. Consider extracting it to a config file for easier maintenance and reusability across the application.
Create a config file (e.g.,
src/config/site.ts):export const siteConfig = { links: { github: "https://github.com/Foysal50x/zenith" } }Then update the component:
+import { siteConfig } from "@/config/site" + export function SiteHeader() { return ( <header className="flex h-[var(--header-height)] shrink-0 items-center gap-2 border-b transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-[var(--header-height)]"> <div className="flex w-full items-center gap-1 px-4 lg:gap-2 lg:px-6"> <SidebarTrigger className="-ml-1" /> <Separator orientation="vertical" className="mx-2 data-[orientation=vertical]:h-4" /> <h1 className="text-base font-medium">Documents</h1> <div className="ml-auto flex items-center gap-2"> <Button variant="ghost" asChild size="sm" className="hidden sm:flex"> <a - href="https://github.com/Foysal50x/zenith" + href={siteConfig.links.github} rel="noopener noreferrer" target="_blank" className="dark:text-foreground" > Project on GitHub </a> </Button> </div> </div> </header> ) }frontend/src/components/admin/nav-secondary.tsx (1)
29-29: Use a more reliable key for list items.Using
item.titleas the key may not be unique. Consider usingitem.urlor a combination of properties for better uniqueness.Apply this diff:
- <SidebarMenuItem key={item.title}> + <SidebarMenuItem key={item.url}>frontend/src/components/admin/section-cards.tsx (1)
13-102: Consider making the component data-driven.The component hardcodes all card data, making it inflexible and difficult to maintain. Consider accepting card data as props to improve reusability.
Example structure:
interface CardData { title: string value: string trend: number trendLabel: string description: string } export function SectionCards({ cards }: { cards: CardData[] }) { return ( <div className="*:data-[slot=card]:from-primary/5 *:data-[slot=card]:to-card dark:*:data-[slot=card]:bg-card grid grid-cols-1 gap-4 px-4 *:data-[slot=card]:bg-gradient-to-t *:data-[slot=card]:shadow-xs lg:px-6 @xl/main:grid-cols-2 @5xl/main:grid-cols-4"> {cards.map((card) => ( <Card key={card.title} className="@container/card"> {/* Render card using card data */} </Card> ))} </div> ) }frontend/src/components/ui/toggle.tsx (1)
31-45: Add ref forwarding for consistency.Like other UI primitives, the Toggle component should forward refs to support parent component access and form library integration.
Apply this diff:
-function Toggle({ - className, - variant, - size, - ...props -}: React.ComponentProps<typeof TogglePrimitive.Root> & - VariantProps<typeof toggleVariants>) { - return ( - <TogglePrimitive.Root - data-slot="toggle" - className={cn(toggleVariants({ variant, size, className }))} - {...props} - /> - ) -} +const Toggle = React.forwardRef< + React.ElementRef<typeof TogglePrimitive.Root>, + React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> & + VariantProps<typeof toggleVariants> +>(({ className, variant, size, ...props }, ref) => { + return ( + <TogglePrimitive.Root + ref={ref} + data-slot="toggle" + className={cn(toggleVariants({ variant, size, className }))} + {...props} + /> + ) +}) +Toggle.displayName = TogglePrimitive.Root.displayName -export { Toggle, toggleVariants } +export { Toggle, toggleVariants }frontend/src/components/admin/nav-user.tsx (2)
50-53: Consider deriving avatar fallback from user initials.The
AvatarFallbackis hardcoded as "CN" but should ideally display the user's initials for better personalization.Apply this diff to derive initials from the user's name:
+ const initials = user.name + .split(' ') + .map(n => n[0]) + .join('') + .toUpperCase() + .slice(0, 2) + <Avatar className="h-8 w-8 rounded-lg grayscale"> <AvatarImage src={user.avatar} alt={user.name} /> - <AvatarFallback className="rounded-lg">CN</AvatarFallback> + <AvatarFallback className="rounded-lg">{initials}</AvatarFallback> </Avatar>Apply the same pattern to the fallback at line 73.
Also applies to: 71-73
84-102: LGTM! Note: Menu items are placeholders.The dropdown menu structure is well-implemented with appropriate icons and layout. The menu items (Account, Billing, Notifications, Log out) currently have no click handlersβensure these are wired up with actual functionality before production use.
Would you like me to open an issue to track implementing the actual handlers for these menu actions?
frontend/src/components/AppSidebar.tsx (1)
167-167: Simplify the conditional expression.The ternary operator can be replaced with the nullish coalescing operator for cleaner code.
Apply this diff:
- <span className="text-base font-semibold">{user?.name ? user.name : ""}</span> + <span className="text-base font-semibold">{user?.name ?? ""}</span>frontend/src/components/admin/nav-main.tsx (1)
25-41: LGTM! Note: Action buttons need handlers.The "Quick Create" and "Inbox" buttons are properly styled and positioned. Ensure click handlers are implemented before production use.
Would you like me to open an issue to track implementing the actual handlers for these action buttons?
frontend/src/pages/Dashboard.tsx (1)
2-2: Remove unused import and variable.The
useAuthimport anduserdestructuring are not used in this component. The adminAppSidebarmanages its own user data internally.Apply this diff:
import React from 'react'; -import { useAuth } from '../contexts/AuthContext'; -import { User, Calendar, Mail } from 'lucide-react'; import { AppSidebar } from "@/components/admin/app-sidebar" // ... rest of imports export const Dashboard: React.FC = () => { - const { user } = useAuth(); - return (Also applies to: 17-17
frontend/src/components/admin/app-sidebar.tsx (1)
153-153: Avoid hardcoded z-index and background color.Line 153 has two styling concerns:
z-[999]is an extremely high z-index that could conflict with modals, tooltips, or other overlaysbg-whitehardcodes the background color, breaking dark mode supportApply this diff to use theme-aware styling:
- <Sidebar collapsible="offcanvas" {...props} className="z-[999] bg-white"> + <Sidebar collapsible="offcanvas" {...props} className={cn("z-50 bg-sidebar", props.className)}>The
z-50value is more reasonable andbg-sidebarwill respect the theme. If you need the z-index to be higher for specific overlay scenarios, consider using a semantic value likez-[100]and document why it's necessary.frontend/src/components/admin/nav-documents.tsx (1)
75-78: Consider adding confirmation for the Delete action.The Delete menu item correctly uses the
variant="destructive"styling, but when implementing the actual delete functionality, ensure you add a confirmation dialog to prevent accidental deletions.Would you like me to generate a confirmation dialog pattern for this delete action?
frontend/src/components/admin/chart-area-interactive.tsx (1)
153-165: Hardcoded reference date will become stale.The reference date
"2024-06-30"is hardcoded. For a demo with static data this is acceptable, but for production use consider making this dynamic or configurable to reflect real-time data ranges.frontend/src/components/ui/tooltip.tsx (1)
10-16:data-sloton Provider has no DOM effect.
TooltipPrimitive.Provideris a context-only component and doesn't render a DOM element, so thedata-slot="tooltip-provider"attribute won't appear in the rendered output. This is harmless but unnecessary.return ( <TooltipPrimitive.Provider - data-slot="tooltip-provider" delayDuration={delayDuration} {...props} /> )frontend/src/components/ui/chart.tsx (1)
70-101: Acknowledge security assumption fordangerouslySetInnerHTML.Static analysis flagged this as a potential XSS vector. The current implementation is safe because
configkeys and color values originate from developer-definedChartConfigobjects, not user input. However, consider adding a comment documenting this safety assumption to prevent future maintainers from inadvertently passing untrusted data.+// SAFETY: Config keys and colors are developer-defined, not user input. +// Do not pass user-controlled data to ChartConfig without sanitization. const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {frontend/src/components/admin/data-table.tsx (4)
286-310: Action menu items are non-functional placeholders.The Edit, Make a copy, Favorite, and Delete menu items have no
onClickhandlers. Consider adding TODO comments or implementing basic handlers.Would you like me to help implement these action handlers or create an issue to track this?
337-364: Consider syncing reorder changes to parent.The component copies
initialDatato local state. Drag-and-drop reordering updates local state only. If the parent needs to persist order changes, consider adding anonReordercallback prop.export function DataTable({ data: initialData, onReorder, }: { data: z.infer<typeof schema>[] onReorder?: (newData: z.infer<typeof schema>[]) => void })
391-400: Potential stale closure in drag handler.
handleDragEndcapturesdataIdsfrom render scope. If data changes during drag, the indices could be stale. Consider computing indices inside the callback.function handleDragEnd(event: DragEndEvent) { const { active, over } = event if (active && over && active.id !== over.id) { - setData((data) => { - const oldIndex = dataIds.indexOf(active.id) - const newIndex = dataIds.indexOf(over.id) + setData((currentData) => { + const currentIds = currentData.map(({ id }) => id) + const oldIndex = currentIds.indexOf(active.id as number) + const newIndex = currentIds.indexOf(over.id as number) - return arrayMove(data, oldIndex, newIndex) + return arrayMove(currentData, oldIndex, newIndex) }) } }
628-646: Chart data is static and not related to row items.
chartDataandchartConfigare hardcoded constants. Every row's drawer displays the same chart regardless of the actual row data. If this is intentional placeholder data, consider adding a comment.frontend/src/components/ui/dropdown-menu.tsx (1)
15-21: DropdownMenuPortal data-slot may not render.The
data-slotattribute onDropdownMenuPrimitive.Portalwon't render in the DOM since Portal is a logical component that doesn't create its own element.This is a minor inconsistency - the attribute has no effect but doesn't cause harm.
frontend/src/components/ui/sheet.tsx (1)
130-139: SheetPortal is not exported.
SheetPortalis defined but not included in the exports. Other similar components (Drawer) export their Portal. This may be intentional sinceSheetContentalready wraps withSheetPortal.Consider adding
SheetPortalto exports for consistency with other UI components, or remove the unused function if it's only meant for internal composition.frontend/src/components/ui/sidebar.tsx (1)
85-86: Consider addingSameSiteattribute to the cookie.While the cookie only stores non-sensitive UI state, modern browsers default to
SameSite=Laxwhen not specified. Being explicit improves consistency and clarity.- document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}` + document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}; SameSite=Lax`
π Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
β Files ignored due to path filters (1)
frontend/package-lock.jsonis excluded by!**/package-lock.json
π Files selected for processing (37)
frontend/package.json(1 hunks)frontend/src/app/dashboard/data.json(1 hunks)frontend/src/components/AppSidebar.tsx(1 hunks)frontend/src/components/ProtectedRoute.tsx(1 hunks)frontend/src/components/admin/app-sidebar.tsx(1 hunks)frontend/src/components/admin/chart-area-interactive.tsx(1 hunks)frontend/src/components/admin/data-table.tsx(1 hunks)frontend/src/components/admin/nav-documents.tsx(1 hunks)frontend/src/components/admin/nav-main.tsx(1 hunks)frontend/src/components/admin/nav-secondary.tsx(1 hunks)frontend/src/components/admin/nav-user.tsx(1 hunks)frontend/src/components/admin/section-cards.tsx(1 hunks)frontend/src/components/admin/site-header.tsx(1 hunks)frontend/src/components/ui/avatar.tsx(1 hunks)frontend/src/components/ui/badge.tsx(1 hunks)frontend/src/components/ui/breadcrumb.tsx(1 hunks)frontend/src/components/ui/button.tsx(1 hunks)frontend/src/components/ui/card.tsx(1 hunks)frontend/src/components/ui/chart.tsx(1 hunks)frontend/src/components/ui/checkbox.tsx(1 hunks)frontend/src/components/ui/drawer.tsx(1 hunks)frontend/src/components/ui/dropdown-menu.tsx(1 hunks)frontend/src/components/ui/input.tsx(1 hunks)frontend/src/components/ui/label.tsx(1 hunks)frontend/src/components/ui/select.tsx(1 hunks)frontend/src/components/ui/separator.tsx(1 hunks)frontend/src/components/ui/sheet.tsx(1 hunks)frontend/src/components/ui/sidebar.tsx(1 hunks)frontend/src/components/ui/skeleton.tsx(1 hunks)frontend/src/components/ui/sonner.tsx(1 hunks)frontend/src/components/ui/table.tsx(1 hunks)frontend/src/components/ui/tabs.tsx(1 hunks)frontend/src/components/ui/toggle-group.tsx(1 hunks)frontend/src/components/ui/toggle.tsx(1 hunks)frontend/src/components/ui/tooltip.tsx(1 hunks)frontend/src/hooks/use-mobile.ts(1 hunks)frontend/src/pages/Dashboard.tsx(1 hunks)
π§° Additional context used
𧬠Code graph analysis (27)
frontend/src/components/ui/badge.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/admin/section-cards.tsx (2)
frontend/src/components/ui/card.tsx (6)
Card(85-85)CardHeader(86-86)CardDescription(90-90)CardTitle(88-88)CardAction(89-89)CardFooter(87-87)frontend/src/components/ui/badge.tsx (1)
Badge(46-46)
frontend/src/components/ui/skeleton.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/admin/chart-area-interactive.tsx (5)
frontend/src/components/ui/chart.tsx (4)
ChartConfig(9-17)ChartContainer(345-345)ChartTooltip(346-346)ChartTooltipContent(347-347)frontend/src/hooks/use-mobile.ts (1)
useIsMobile(5-19)frontend/src/components/ui/card.tsx (6)
Card(85-85)CardHeader(86-86)CardTitle(88-88)CardDescription(90-90)CardAction(89-89)CardContent(91-91)frontend/src/components/ui/toggle-group.tsx (2)
ToggleGroup(71-71)ToggleGroupItem(71-71)frontend/src/components/ui/select.tsx (5)
Select(175-175)SelectTrigger(183-183)SelectValue(184-184)SelectContent(176-176)SelectItem(178-178)
frontend/src/components/admin/nav-secondary.tsx (1)
frontend/src/components/ui/sidebar.tsx (5)
SidebarGroup(705-705)SidebarGroupContent(707-707)SidebarMenu(712-712)SidebarMenuItem(716-716)SidebarMenuButton(715-715)
frontend/src/components/ui/chart.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/ui/breadcrumb.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/ui/tabs.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/ui/toggle-group.tsx (2)
frontend/src/components/ui/toggle.tsx (1)
toggleVariants(47-47)frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/ui/tooltip.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/ui/toggle.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/ui/checkbox.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/ui/separator.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/admin/app-sidebar.tsx (6)
frontend/src/components/AppSidebar.tsx (1)
AppSidebar(154-183)frontend/src/components/ui/sidebar.tsx (7)
Sidebar(702-702)SidebarHeader(709-709)SidebarMenu(712-712)SidebarMenuItem(716-716)SidebarMenuButton(715-715)SidebarContent(703-703)SidebarFooter(704-704)frontend/src/components/admin/nav-main.tsx (1)
NavMain(12-56)frontend/src/components/admin/nav-documents.tsx (1)
NavDocuments(28-92)frontend/src/components/admin/nav-secondary.tsx (1)
NavSecondary(14-42)frontend/src/components/admin/nav-user.tsx (1)
NavUser(30-108)
frontend/src/components/ui/button.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/admin/site-header.tsx (2)
frontend/src/components/ui/sidebar.tsx (1)
SidebarTrigger(724-724)frontend/src/components/ui/separator.tsx (1)
Separator(26-26)
frontend/src/components/ui/drawer.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/ui/table.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/ui/avatar.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/ui/dropdown-menu.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/ui/sheet.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/pages/Dashboard.tsx (8)
frontend/src/hooks/useAuth.ts (1)
useAuth(100-131)frontend/src/components/ui/sidebar.tsx (2)
SidebarProvider(721-721)SidebarInset(711-711)frontend/src/components/admin/app-sidebar.tsx (1)
AppSidebar(151-179)frontend/src/components/AppSidebar.tsx (1)
AppSidebar(154-183)frontend/src/components/admin/site-header.tsx (1)
SiteHeader(5-30)frontend/src/components/admin/section-cards.tsx (1)
SectionCards(13-102)frontend/src/components/admin/chart-area-interactive.tsx (1)
ChartAreaInteractive(143-292)frontend/src/components/admin/data-table.tsx (1)
DataTable(337-626)
frontend/src/components/ui/card.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/admin/nav-main.tsx (1)
frontend/src/components/ui/sidebar.tsx (5)
SidebarGroup(705-705)SidebarGroupContent(707-707)SidebarMenu(712-712)SidebarMenuItem(716-716)SidebarMenuButton(715-715)
frontend/src/components/ui/label.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/ui/select.tsx (1)
frontend/src/lib/utils.ts (1)
cn(4-6)
frontend/src/components/admin/nav-documents.tsx (2)
frontend/src/components/ui/sidebar.tsx (7)
useSidebar(725-725)SidebarGroup(705-705)SidebarGroupLabel(708-708)SidebarMenu(712-712)SidebarMenuItem(716-716)SidebarMenuButton(715-715)SidebarMenuAction(713-713)frontend/src/components/ui/dropdown-menu.tsx (5)
DropdownMenu(242-242)DropdownMenuTrigger(244-244)DropdownMenuContent(245-245)DropdownMenuItem(248-248)DropdownMenuSeparator(252-252)
πͺ ast-grep (0.40.0)
frontend/src/components/ui/chart.tsx
[warning] 80-80: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html
(react-unsafe-html-injection)
πͺ Biome (2.1.2)
frontend/src/components/ui/chart.tsx
[error] 81-81: Avoid passing content using the dangerouslySetInnerHTML prop.
Setting content using code can expose users to cross-site scripting (XSS) attacks
(lint/security/noDangerouslySetInnerHtml)
π Additional comments (30)
frontend/src/components/ui/separator.tsx (1)
6-24: Separator wrapper looks good and idiomaticThe orientation/decorative defaults and
cn-merged sizing classes are clean and match Radixβs expectations. Prop spread order also lets consumers override orientation/decorative when needed.frontend/src/components/ui/badge.tsx (1)
7-46: Badge variants andasChildcomposition look solidThe
cvasetup,asChild/Slotpattern, andcn-merged classes give a flexible, composable badge component with sensible defaults and clear variants.frontend/src/components/ui/tabs.tsx (1)
6-62: Tabs primitives wrapper set looks cleanThe Tabs, TabsList, TabsTrigger, and TabsContent wrappers correctly forward props, add data-slots, and apply sensible Tailwind classes for layout and focus/active states. This matches Radix usage patterns well.
frontend/package.json (1)
14-50:next-themesis compatible with Vite and requires no changes
next-themesis a React-focused theme provider that works seamlessly in Vite applications. Despite its name, it has no Next.js dependency or couplingβsimply wrap your app root withThemeProviderand useuseThemein components, following the same pattern documented for both Next.js and Vite projects. No friction points with Vite's module resolution or bundling; proceed as planned.frontend/src/components/ProtectedRoute.tsx (1)
1-1: LGTM: Import path refactored to use absolute alias.The change from relative to absolute import path improves maintainability and consistency with the rest of the codebase.
frontend/src/hooks/use-mobile.ts (1)
5-19: Potential SSR hydration mismatch.The initial state is
undefined, which returnsfalseon first render due to!!isMobile. If this project uses server-side rendering, the server will render the desktop version while the client may have a different state after hydration, causing a mismatch.If SSR/SSG is used in this project, consider initializing with a consistent value (e.g.,
trueorfalsebased on a default) or using a conditional rendering approach to delay rendering until after hydration completes.frontend/src/components/AppSidebar.tsx (1)
43-151: Note: All navigation URLs are placeholders.All navigation items currently point to
"#". Ensure these are replaced with actual routes before the dashboard goes live.Would you like me to help generate a routing structure or open an issue to track implementing the actual navigation routes?
frontend/src/components/ui/button.tsx (1)
1-59: LGTM! Solid Button implementation.The Button component is well-structured with proper variant/size management via CVA, Radix Slot integration for composition, and comprehensive styling including focus states and accessibility features. The long base className (line 8) appropriately centralizes complex styling rules.
frontend/src/pages/Dashboard.tsx (1)
20-43: LGTM! Well-structured dashboard layout.The new component-driven layout with
SidebarProvider,AppSidebar, and composed sections (SectionCards,ChartAreaInteractive,DataTable) provides a clean, maintainable structure. The CSS custom properties enable flexible theming.frontend/src/components/ui/toggle-group.tsx (1)
1-71: LGTM! Proper context-based variant management.The
ToggleGroupandToggleGroupItemcomponents correctly use React Context to share variant/size configuration, with appropriate fallbacks to props when context values aren't provided. The data attributes align with the variant resolution logic.frontend/src/components/admin/nav-documents.tsx (1)
28-92: LGTM! Well-implemented documents navigation.The
NavDocumentscomponent is properly structured with:
- Mobile-responsive dropdown positioning via
useSidebar- Collapsible behavior that hides when sidebar is in icon mode
- Clear action menus with appropriate icons
- Good accessibility with sr-only text for the menu trigger
frontend/src/components/ui/avatar.tsx (1)
1-53: LGTM!Clean implementation of Avatar primitives wrapping Radix UI. The components correctly forward props, use
React.ComponentPropsfor type safety, and follow the establisheddata-slotpattern for styling hooks consistent with other UI primitives in this PR.frontend/src/components/admin/chart-area-interactive.tsx (1)
167-291: LGTM!The responsive toggle/select switching, container queries, and chart rendering are well-implemented. Good use of gradient fills and proper Recharts configuration.
frontend/src/components/ui/table.tsx (1)
1-116: LGTM!Well-structured table primitives with consistent patterns:
data-slotattributes for styling hooks,cnutility for className composition, and proper prop forwarding. The wrapper div withoverflow-x-autoon the Table component is a good practice for responsive table handling.frontend/src/components/ui/tooltip.tsx (1)
35-57: LGTM!The TooltipContent correctly wraps content in a Portal, applies comprehensive animation classes, and includes the Arrow element. The styling is well-structured.
frontend/src/components/ui/chart.tsx (2)
25-68: LGTM!The
useCharthook properly throws when used outside the provider context.ChartContainercorrectly generates unique IDs and sanitizes them for CSS selector compatibility. The context pattern is well-implemented.
251-342: LGTM!
ChartLegendContentandgetPayloadConfigFromPayloadare well-implemented. The helper function handles various payload structures robustly with proper null checks.frontend/src/components/admin/data-table.tsx (4)
107-115: LGTM! Clean schema definition.The Zod schema is well-structured for row validation and type inference with
z.infer<typeof schema>.
117-135: LGTM! Accessible drag handle implementation.Good use of
sr-onlyfor screen reader accessibility. The component correctly extractsattributesandlistenersfromuseSortable.
312-335: LGTM! Clean drag-and-drop row implementation.Good use of
useSortablehook with proper transform and transition handling via CSS utilities.
531-607: LGTM! Well-implemented pagination controls.Clean implementation with proper disabled states, responsive design, and accessibility labels.
frontend/src/components/ui/drawer.tsx (1)
1-133: LGTM! Well-structured Drawer wrapper components.Clean implementation wrapping Vaul primitives with:
- Consistent
data-slotattributes for styling hooks- Direction-aware styling using
data-[vaul-drawer-direction=*]selectors- Proper className composition via
cnutilityfrontend/src/components/ui/dropdown-menu.tsx (1)
1-257: LGTM! Comprehensive dropdown menu wrapper.Well-implemented Radix wrapper with:
- Consistent
data-slotattributes- Animation classes for open/close states
- Variant support (
destructive) on menu items- Inset support for aligned menu items
frontend/src/components/ui/sheet.tsx (1)
1-139: LGTM! Clean Sheet component implementation.Well-structured with:
- Side-aware positioning and animations
- Built-in accessible close button
- Consistent
data-slotattributesfrontend/src/components/ui/select.tsx (1)
1-185: LGTM! Well-implemented Select wrapper components.Clean implementation with:
- Size variants for
SelectTrigger- Scroll buttons for overflow handling
- Proper item indicators with check icons
- Consistent
data-slotattributesfrontend/src/components/ui/sidebar.tsx (5)
609-612: Random width generation is client-safe due to "use client" directive.The
Math.random()inuseMemoworks correctly here because of the "use client" directive ensuring client-only rendering. The empty dependency array intentionally creates a stable random width per component instance.
1-27: Well-structured component library with good practices.The imports are organized logically, the "use client" directive is appropriate for a component with hooks and event handlers, and the constants are well-named. The design follows shadcn/ui conventions effectively.
47-54: Good context pattern with enforced provider usage.The
useSidebarhook correctly throws a descriptive error when used outsideSidebarProvider, preventing silent failures and guiding developers to proper usage.
96-110: Keyboard shortcut implementation is correct.The effect properly adds and cleans up the event listener, and the
toggleSidebardependency ensures the latest callback is used. The Ctrl/Cmd+B shortcut follows common UI conventions.
701-726: Comprehensive and well-organized exports.All 24 components and the
useSidebarhook are exported, providing a complete API surface for building complex sidebars. The naming is consistent and follows React conventions.
| [ | ||
| { | ||
| "id": 1, | ||
| "header": "Cover page", | ||
| "type": "Cover page", | ||
| "status": "In Process", | ||
| "target": "18", | ||
| "limit": "5", | ||
| "reviewer": "Eddie Lake" | ||
| }, | ||
| { | ||
| "id": 2, | ||
| "header": "Table of contents", | ||
| "type": "Table of contents", | ||
| "status": "Done", | ||
| "target": "29", | ||
| "limit": "24", | ||
| "reviewer": "Eddie Lake" | ||
| }, | ||
| { | ||
| "id": 3, | ||
| "header": "Executive summary", | ||
| "type": "Narrative", | ||
| "status": "Done", | ||
| "target": "10", | ||
| "limit": "13", | ||
| "reviewer": "Eddie Lake" | ||
| }, | ||
| { | ||
| "id": 4, | ||
| "header": "Technical approach", | ||
| "type": "Narrative", | ||
| "status": "Done", | ||
| "target": "27", | ||
| "limit": "23", | ||
| "reviewer": "Jamik Tashpulatov" | ||
| }, | ||
| { | ||
| "id": 5, | ||
| "header": "Design", | ||
| "type": "Narrative", | ||
| "status": "In Process", | ||
| "target": "2", | ||
| "limit": "16", | ||
| "reviewer": "Jamik Tashpulatov" | ||
| }, | ||
| { | ||
| "id": 6, | ||
| "header": "Capabilities", | ||
| "type": "Narrative", | ||
| "status": "In Process", | ||
| "target": "20", | ||
| "limit": "8", | ||
| "reviewer": "Jamik Tashpulatov" | ||
| }, | ||
| { | ||
| "id": 7, | ||
| "header": "Integration with existing systems", | ||
| "type": "Narrative", | ||
| "status": "In Process", | ||
| "target": "19", | ||
| "limit": "21", | ||
| "reviewer": "Jamik Tashpulatov" | ||
| }, | ||
| { | ||
| "id": 8, | ||
| "header": "Innovation and Advantages", | ||
| "type": "Narrative", | ||
| "status": "Done", | ||
| "target": "25", | ||
| "limit": "26", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 9, | ||
| "header": "Overview of EMR's Innovative Solutions", | ||
| "type": "Technical content", | ||
| "status": "Done", | ||
| "target": "7", | ||
| "limit": "23", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 10, | ||
| "header": "Advanced Algorithms and Machine Learning", | ||
| "type": "Narrative", | ||
| "status": "Done", | ||
| "target": "30", | ||
| "limit": "28", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 11, | ||
| "header": "Adaptive Communication Protocols", | ||
| "type": "Narrative", | ||
| "status": "Done", | ||
| "target": "9", | ||
| "limit": "31", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 12, | ||
| "header": "Advantages Over Current Technologies", | ||
| "type": "Narrative", | ||
| "status": "Done", | ||
| "target": "12", | ||
| "limit": "0", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 13, | ||
| "header": "Past Performance", | ||
| "type": "Narrative", | ||
| "status": "Done", | ||
| "target": "22", | ||
| "limit": "33", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 14, | ||
| "header": "Customer Feedback and Satisfaction Levels", | ||
| "type": "Narrative", | ||
| "status": "Done", | ||
| "target": "15", | ||
| "limit": "34", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 15, | ||
| "header": "Implementation Challenges and Solutions", | ||
| "type": "Narrative", | ||
| "status": "Done", | ||
| "target": "3", | ||
| "limit": "35", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 16, | ||
| "header": "Security Measures and Data Protection Policies", | ||
| "type": "Narrative", | ||
| "status": "In Process", | ||
| "target": "6", | ||
| "limit": "36", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 17, | ||
| "header": "Scalability and Future Proofing", | ||
| "type": "Narrative", | ||
| "status": "Done", | ||
| "target": "4", | ||
| "limit": "37", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 18, | ||
| "header": "Cost-Benefit Analysis", | ||
| "type": "Plain language", | ||
| "status": "Done", | ||
| "target": "14", | ||
| "limit": "38", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 19, | ||
| "header": "User Training and Onboarding Experience", | ||
| "type": "Narrative", | ||
| "status": "Done", | ||
| "target": "17", | ||
| "limit": "39", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 20, | ||
| "header": "Future Development Roadmap", | ||
| "type": "Narrative", | ||
| "status": "Done", | ||
| "target": "11", | ||
| "limit": "40", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 21, | ||
| "header": "System Architecture Overview", | ||
| "type": "Technical content", | ||
| "status": "In Process", | ||
| "target": "24", | ||
| "limit": "18", | ||
| "reviewer": "Maya Johnson" | ||
| }, | ||
| { | ||
| "id": 22, | ||
| "header": "Risk Management Plan", | ||
| "type": "Narrative", | ||
| "status": "Done", | ||
| "target": "15", | ||
| "limit": "22", | ||
| "reviewer": "Carlos Rodriguez" | ||
| }, | ||
| { | ||
| "id": 23, | ||
| "header": "Compliance Documentation", | ||
| "type": "Legal", | ||
| "status": "In Process", | ||
| "target": "31", | ||
| "limit": "27", | ||
| "reviewer": "Sarah Chen" | ||
| }, | ||
| { | ||
| "id": 24, | ||
| "header": "API Documentation", | ||
| "type": "Technical content", | ||
| "status": "Done", | ||
| "target": "8", | ||
| "limit": "12", | ||
| "reviewer": "Raj Patel" | ||
| }, | ||
| { | ||
| "id": 25, | ||
| "header": "User Interface Mockups", | ||
| "type": "Visual", | ||
| "status": "In Process", | ||
| "target": "19", | ||
| "limit": "25", | ||
| "reviewer": "Leila Ahmadi" | ||
| }, | ||
| { | ||
| "id": 26, | ||
| "header": "Database Schema", | ||
| "type": "Technical content", | ||
| "status": "Done", | ||
| "target": "22", | ||
| "limit": "20", | ||
| "reviewer": "Thomas Wilson" | ||
| }, | ||
| { | ||
| "id": 27, | ||
| "header": "Testing Methodology", | ||
| "type": "Technical content", | ||
| "status": "In Process", | ||
| "target": "17", | ||
| "limit": "14", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 28, | ||
| "header": "Deployment Strategy", | ||
| "type": "Narrative", | ||
| "status": "Done", | ||
| "target": "26", | ||
| "limit": "30", | ||
| "reviewer": "Eddie Lake" | ||
| }, | ||
| { | ||
| "id": 29, | ||
| "header": "Budget Breakdown", | ||
| "type": "Financial", | ||
| "status": "In Process", | ||
| "target": "13", | ||
| "limit": "16", | ||
| "reviewer": "Jamik Tashpulatov" | ||
| }, | ||
| { | ||
| "id": 30, | ||
| "header": "Market Analysis", | ||
| "type": "Research", | ||
| "status": "Done", | ||
| "target": "29", | ||
| "limit": "32", | ||
| "reviewer": "Sophia Martinez" | ||
| }, | ||
| { | ||
| "id": 31, | ||
| "header": "Competitor Comparison", | ||
| "type": "Research", | ||
| "status": "In Process", | ||
| "target": "21", | ||
| "limit": "19", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 32, | ||
| "header": "Maintenance Plan", | ||
| "type": "Technical content", | ||
| "status": "Done", | ||
| "target": "16", | ||
| "limit": "23", | ||
| "reviewer": "Alex Thompson" | ||
| }, | ||
| { | ||
| "id": 33, | ||
| "header": "User Personas", | ||
| "type": "Research", | ||
| "status": "In Process", | ||
| "target": "27", | ||
| "limit": "24", | ||
| "reviewer": "Nina Patel" | ||
| }, | ||
| { | ||
| "id": 34, | ||
| "header": "Accessibility Compliance", | ||
| "type": "Legal", | ||
| "status": "Done", | ||
| "target": "18", | ||
| "limit": "21", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 35, | ||
| "header": "Performance Metrics", | ||
| "type": "Technical content", | ||
| "status": "In Process", | ||
| "target": "23", | ||
| "limit": "26", | ||
| "reviewer": "David Kim" | ||
| }, | ||
| { | ||
| "id": 36, | ||
| "header": "Disaster Recovery Plan", | ||
| "type": "Technical content", | ||
| "status": "Done", | ||
| "target": "14", | ||
| "limit": "17", | ||
| "reviewer": "Jamik Tashpulatov" | ||
| }, | ||
| { | ||
| "id": 37, | ||
| "header": "Third-party Integrations", | ||
| "type": "Technical content", | ||
| "status": "In Process", | ||
| "target": "25", | ||
| "limit": "28", | ||
| "reviewer": "Eddie Lake" | ||
| }, | ||
| { | ||
| "id": 38, | ||
| "header": "User Feedback Summary", | ||
| "type": "Research", | ||
| "status": "Done", | ||
| "target": "20", | ||
| "limit": "15", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 39, | ||
| "header": "Localization Strategy", | ||
| "type": "Narrative", | ||
| "status": "In Process", | ||
| "target": "12", | ||
| "limit": "19", | ||
| "reviewer": "Maria Garcia" | ||
| }, | ||
| { | ||
| "id": 40, | ||
| "header": "Mobile Compatibility", | ||
| "type": "Technical content", | ||
| "status": "Done", | ||
| "target": "28", | ||
| "limit": "31", | ||
| "reviewer": "James Wilson" | ||
| }, | ||
| { | ||
| "id": 41, | ||
| "header": "Data Migration Plan", | ||
| "type": "Technical content", | ||
| "status": "In Process", | ||
| "target": "19", | ||
| "limit": "22", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 42, | ||
| "header": "Quality Assurance Protocols", | ||
| "type": "Technical content", | ||
| "status": "Done", | ||
| "target": "30", | ||
| "limit": "33", | ||
| "reviewer": "Priya Singh" | ||
| }, | ||
| { | ||
| "id": 43, | ||
| "header": "Stakeholder Analysis", | ||
| "type": "Research", | ||
| "status": "In Process", | ||
| "target": "11", | ||
| "limit": "14", | ||
| "reviewer": "Eddie Lake" | ||
| }, | ||
| { | ||
| "id": 44, | ||
| "header": "Environmental Impact Assessment", | ||
| "type": "Research", | ||
| "status": "Done", | ||
| "target": "24", | ||
| "limit": "27", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 45, | ||
| "header": "Intellectual Property Rights", | ||
| "type": "Legal", | ||
| "status": "In Process", | ||
| "target": "17", | ||
| "limit": "20", | ||
| "reviewer": "Sarah Johnson" | ||
| }, | ||
| { | ||
| "id": 46, | ||
| "header": "Customer Support Framework", | ||
| "type": "Narrative", | ||
| "status": "Done", | ||
| "target": "22", | ||
| "limit": "25", | ||
| "reviewer": "Jamik Tashpulatov" | ||
| }, | ||
| { | ||
| "id": 47, | ||
| "header": "Version Control Strategy", | ||
| "type": "Technical content", | ||
| "status": "In Process", | ||
| "target": "15", | ||
| "limit": "18", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 48, | ||
| "header": "Continuous Integration Pipeline", | ||
| "type": "Technical content", | ||
| "status": "Done", | ||
| "target": "26", | ||
| "limit": "29", | ||
| "reviewer": "Michael Chen" | ||
| }, | ||
| { | ||
| "id": 49, | ||
| "header": "Regulatory Compliance", | ||
| "type": "Legal", | ||
| "status": "In Process", | ||
| "target": "13", | ||
| "limit": "16", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 50, | ||
| "header": "User Authentication System", | ||
| "type": "Technical content", | ||
| "status": "Done", | ||
| "target": "28", | ||
| "limit": "31", | ||
| "reviewer": "Eddie Lake" | ||
| }, | ||
| { | ||
| "id": 51, | ||
| "header": "Data Analytics Framework", | ||
| "type": "Technical content", | ||
| "status": "In Process", | ||
| "target": "21", | ||
| "limit": "24", | ||
| "reviewer": "Jamik Tashpulatov" | ||
| }, | ||
| { | ||
| "id": 52, | ||
| "header": "Cloud Infrastructure", | ||
| "type": "Technical content", | ||
| "status": "Done", | ||
| "target": "16", | ||
| "limit": "19", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 53, | ||
| "header": "Network Security Measures", | ||
| "type": "Technical content", | ||
| "status": "In Process", | ||
| "target": "29", | ||
| "limit": "32", | ||
| "reviewer": "Lisa Wong" | ||
| }, | ||
| { | ||
| "id": 54, | ||
| "header": "Project Timeline", | ||
| "type": "Planning", | ||
| "status": "Done", | ||
| "target": "14", | ||
| "limit": "17", | ||
| "reviewer": "Eddie Lake" | ||
| }, | ||
| { | ||
| "id": 55, | ||
| "header": "Resource Allocation", | ||
| "type": "Planning", | ||
| "status": "In Process", | ||
| "target": "27", | ||
| "limit": "30", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 56, | ||
| "header": "Team Structure and Roles", | ||
| "type": "Planning", | ||
| "status": "Done", | ||
| "target": "20", | ||
| "limit": "23", | ||
| "reviewer": "Jamik Tashpulatov" | ||
| }, | ||
| { | ||
| "id": 57, | ||
| "header": "Communication Protocols", | ||
| "type": "Planning", | ||
| "status": "In Process", | ||
| "target": "15", | ||
| "limit": "18", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 58, | ||
| "header": "Success Metrics", | ||
| "type": "Planning", | ||
| "status": "Done", | ||
| "target": "30", | ||
| "limit": "33", | ||
| "reviewer": "Eddie Lake" | ||
| }, | ||
| { | ||
| "id": 59, | ||
| "header": "Internationalization Support", | ||
| "type": "Technical content", | ||
| "status": "In Process", | ||
| "target": "23", | ||
| "limit": "26", | ||
| "reviewer": "Jamik Tashpulatov" | ||
| }, | ||
| { | ||
| "id": 60, | ||
| "header": "Backup and Recovery Procedures", | ||
| "type": "Technical content", | ||
| "status": "Done", | ||
| "target": "18", | ||
| "limit": "21", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 61, | ||
| "header": "Monitoring and Alerting System", | ||
| "type": "Technical content", | ||
| "status": "In Process", | ||
| "target": "25", | ||
| "limit": "28", | ||
| "reviewer": "Daniel Park" | ||
| }, | ||
| { | ||
| "id": 62, | ||
| "header": "Code Review Guidelines", | ||
| "type": "Technical content", | ||
| "status": "Done", | ||
| "target": "12", | ||
| "limit": "15", | ||
| "reviewer": "Eddie Lake" | ||
| }, | ||
| { | ||
| "id": 63, | ||
| "header": "Documentation Standards", | ||
| "type": "Technical content", | ||
| "status": "In Process", | ||
| "target": "27", | ||
| "limit": "30", | ||
| "reviewer": "Jamik Tashpulatov" | ||
| }, | ||
| { | ||
| "id": 64, | ||
| "header": "Release Management Process", | ||
| "type": "Planning", | ||
| "status": "Done", | ||
| "target": "22", | ||
| "limit": "25", | ||
| "reviewer": "Assign reviewer" | ||
| }, | ||
| { | ||
| "id": 65, | ||
| "header": "Feature Prioritization Matrix", | ||
| "type": "Planning", | ||
| "status": "In Process", | ||
| "target": "19", | ||
| "limit": "22", | ||
| "reviewer": "Emma Davis" | ||
| }, | ||
| { | ||
| "id": 66, | ||
| "header": "Technical Debt Assessment", | ||
| "type": "Technical content", | ||
| "status": "Done", | ||
| "target": "24", | ||
| "limit": "27", | ||
| "reviewer": "Eddie Lake" | ||
| }, | ||
| { | ||
| "id": 67, | ||
| "header": "Capacity Planning", | ||
| "type": "Planning", | ||
| "status": "In Process", | ||
| "target": "21", | ||
| "limit": "24", | ||
| "reviewer": "Jamik Tashpulatov" | ||
| }, | ||
| { | ||
| "id": 68, | ||
| "header": "Service Level Agreements", | ||
| "type": "Legal", | ||
| "status": "Done", | ||
| "target": "26", | ||
| "limit": "29", | ||
| "reviewer": "Assign reviewer" | ||
| } | ||
| ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Convert numeric fields from strings to numbers.
The target and limit fields are stored as strings but represent numeric values. This will cause type issues when performing calculations, sorting, or filtering operations.
The fields should be numbers:
{
"id": 1,
"header": "Cover page",
"type": "Cover page",
"status": "In Process",
- "target": "18",
- "limit": "5",
+ "target": 18,
+ "limit": 5,
"reviewer": "Eddie Lake"
},Apply this change to all 68 entries in the file.
π 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.
| [ | |
| { | |
| "id": 1, | |
| "header": "Cover page", | |
| "type": "Cover page", | |
| "status": "In Process", | |
| "target": "18", | |
| "limit": "5", | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 2, | |
| "header": "Table of contents", | |
| "type": "Table of contents", | |
| "status": "Done", | |
| "target": "29", | |
| "limit": "24", | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 3, | |
| "header": "Executive summary", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": "10", | |
| "limit": "13", | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 4, | |
| "header": "Technical approach", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": "27", | |
| "limit": "23", | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 5, | |
| "header": "Design", | |
| "type": "Narrative", | |
| "status": "In Process", | |
| "target": "2", | |
| "limit": "16", | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 6, | |
| "header": "Capabilities", | |
| "type": "Narrative", | |
| "status": "In Process", | |
| "target": "20", | |
| "limit": "8", | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 7, | |
| "header": "Integration with existing systems", | |
| "type": "Narrative", | |
| "status": "In Process", | |
| "target": "19", | |
| "limit": "21", | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 8, | |
| "header": "Innovation and Advantages", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": "25", | |
| "limit": "26", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 9, | |
| "header": "Overview of EMR's Innovative Solutions", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": "7", | |
| "limit": "23", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 10, | |
| "header": "Advanced Algorithms and Machine Learning", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": "30", | |
| "limit": "28", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 11, | |
| "header": "Adaptive Communication Protocols", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": "9", | |
| "limit": "31", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 12, | |
| "header": "Advantages Over Current Technologies", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": "12", | |
| "limit": "0", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 13, | |
| "header": "Past Performance", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": "22", | |
| "limit": "33", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 14, | |
| "header": "Customer Feedback and Satisfaction Levels", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": "15", | |
| "limit": "34", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 15, | |
| "header": "Implementation Challenges and Solutions", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": "3", | |
| "limit": "35", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 16, | |
| "header": "Security Measures and Data Protection Policies", | |
| "type": "Narrative", | |
| "status": "In Process", | |
| "target": "6", | |
| "limit": "36", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 17, | |
| "header": "Scalability and Future Proofing", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": "4", | |
| "limit": "37", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 18, | |
| "header": "Cost-Benefit Analysis", | |
| "type": "Plain language", | |
| "status": "Done", | |
| "target": "14", | |
| "limit": "38", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 19, | |
| "header": "User Training and Onboarding Experience", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": "17", | |
| "limit": "39", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 20, | |
| "header": "Future Development Roadmap", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": "11", | |
| "limit": "40", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 21, | |
| "header": "System Architecture Overview", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": "24", | |
| "limit": "18", | |
| "reviewer": "Maya Johnson" | |
| }, | |
| { | |
| "id": 22, | |
| "header": "Risk Management Plan", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": "15", | |
| "limit": "22", | |
| "reviewer": "Carlos Rodriguez" | |
| }, | |
| { | |
| "id": 23, | |
| "header": "Compliance Documentation", | |
| "type": "Legal", | |
| "status": "In Process", | |
| "target": "31", | |
| "limit": "27", | |
| "reviewer": "Sarah Chen" | |
| }, | |
| { | |
| "id": 24, | |
| "header": "API Documentation", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": "8", | |
| "limit": "12", | |
| "reviewer": "Raj Patel" | |
| }, | |
| { | |
| "id": 25, | |
| "header": "User Interface Mockups", | |
| "type": "Visual", | |
| "status": "In Process", | |
| "target": "19", | |
| "limit": "25", | |
| "reviewer": "Leila Ahmadi" | |
| }, | |
| { | |
| "id": 26, | |
| "header": "Database Schema", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": "22", | |
| "limit": "20", | |
| "reviewer": "Thomas Wilson" | |
| }, | |
| { | |
| "id": 27, | |
| "header": "Testing Methodology", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": "17", | |
| "limit": "14", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 28, | |
| "header": "Deployment Strategy", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": "26", | |
| "limit": "30", | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 29, | |
| "header": "Budget Breakdown", | |
| "type": "Financial", | |
| "status": "In Process", | |
| "target": "13", | |
| "limit": "16", | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 30, | |
| "header": "Market Analysis", | |
| "type": "Research", | |
| "status": "Done", | |
| "target": "29", | |
| "limit": "32", | |
| "reviewer": "Sophia Martinez" | |
| }, | |
| { | |
| "id": 31, | |
| "header": "Competitor Comparison", | |
| "type": "Research", | |
| "status": "In Process", | |
| "target": "21", | |
| "limit": "19", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 32, | |
| "header": "Maintenance Plan", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": "16", | |
| "limit": "23", | |
| "reviewer": "Alex Thompson" | |
| }, | |
| { | |
| "id": 33, | |
| "header": "User Personas", | |
| "type": "Research", | |
| "status": "In Process", | |
| "target": "27", | |
| "limit": "24", | |
| "reviewer": "Nina Patel" | |
| }, | |
| { | |
| "id": 34, | |
| "header": "Accessibility Compliance", | |
| "type": "Legal", | |
| "status": "Done", | |
| "target": "18", | |
| "limit": "21", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 35, | |
| "header": "Performance Metrics", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": "23", | |
| "limit": "26", | |
| "reviewer": "David Kim" | |
| }, | |
| { | |
| "id": 36, | |
| "header": "Disaster Recovery Plan", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": "14", | |
| "limit": "17", | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 37, | |
| "header": "Third-party Integrations", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": "25", | |
| "limit": "28", | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 38, | |
| "header": "User Feedback Summary", | |
| "type": "Research", | |
| "status": "Done", | |
| "target": "20", | |
| "limit": "15", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 39, | |
| "header": "Localization Strategy", | |
| "type": "Narrative", | |
| "status": "In Process", | |
| "target": "12", | |
| "limit": "19", | |
| "reviewer": "Maria Garcia" | |
| }, | |
| { | |
| "id": 40, | |
| "header": "Mobile Compatibility", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": "28", | |
| "limit": "31", | |
| "reviewer": "James Wilson" | |
| }, | |
| { | |
| "id": 41, | |
| "header": "Data Migration Plan", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": "19", | |
| "limit": "22", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 42, | |
| "header": "Quality Assurance Protocols", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": "30", | |
| "limit": "33", | |
| "reviewer": "Priya Singh" | |
| }, | |
| { | |
| "id": 43, | |
| "header": "Stakeholder Analysis", | |
| "type": "Research", | |
| "status": "In Process", | |
| "target": "11", | |
| "limit": "14", | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 44, | |
| "header": "Environmental Impact Assessment", | |
| "type": "Research", | |
| "status": "Done", | |
| "target": "24", | |
| "limit": "27", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 45, | |
| "header": "Intellectual Property Rights", | |
| "type": "Legal", | |
| "status": "In Process", | |
| "target": "17", | |
| "limit": "20", | |
| "reviewer": "Sarah Johnson" | |
| }, | |
| { | |
| "id": 46, | |
| "header": "Customer Support Framework", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": "22", | |
| "limit": "25", | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 47, | |
| "header": "Version Control Strategy", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": "15", | |
| "limit": "18", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 48, | |
| "header": "Continuous Integration Pipeline", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": "26", | |
| "limit": "29", | |
| "reviewer": "Michael Chen" | |
| }, | |
| { | |
| "id": 49, | |
| "header": "Regulatory Compliance", | |
| "type": "Legal", | |
| "status": "In Process", | |
| "target": "13", | |
| "limit": "16", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 50, | |
| "header": "User Authentication System", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": "28", | |
| "limit": "31", | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 51, | |
| "header": "Data Analytics Framework", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": "21", | |
| "limit": "24", | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 52, | |
| "header": "Cloud Infrastructure", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": "16", | |
| "limit": "19", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 53, | |
| "header": "Network Security Measures", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": "29", | |
| "limit": "32", | |
| "reviewer": "Lisa Wong" | |
| }, | |
| { | |
| "id": 54, | |
| "header": "Project Timeline", | |
| "type": "Planning", | |
| "status": "Done", | |
| "target": "14", | |
| "limit": "17", | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 55, | |
| "header": "Resource Allocation", | |
| "type": "Planning", | |
| "status": "In Process", | |
| "target": "27", | |
| "limit": "30", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 56, | |
| "header": "Team Structure and Roles", | |
| "type": "Planning", | |
| "status": "Done", | |
| "target": "20", | |
| "limit": "23", | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 57, | |
| "header": "Communication Protocols", | |
| "type": "Planning", | |
| "status": "In Process", | |
| "target": "15", | |
| "limit": "18", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 58, | |
| "header": "Success Metrics", | |
| "type": "Planning", | |
| "status": "Done", | |
| "target": "30", | |
| "limit": "33", | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 59, | |
| "header": "Internationalization Support", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": "23", | |
| "limit": "26", | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 60, | |
| "header": "Backup and Recovery Procedures", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": "18", | |
| "limit": "21", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 61, | |
| "header": "Monitoring and Alerting System", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": "25", | |
| "limit": "28", | |
| "reviewer": "Daniel Park" | |
| }, | |
| { | |
| "id": 62, | |
| "header": "Code Review Guidelines", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": "12", | |
| "limit": "15", | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 63, | |
| "header": "Documentation Standards", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": "27", | |
| "limit": "30", | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 64, | |
| "header": "Release Management Process", | |
| "type": "Planning", | |
| "status": "Done", | |
| "target": "22", | |
| "limit": "25", | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 65, | |
| "header": "Feature Prioritization Matrix", | |
| "type": "Planning", | |
| "status": "In Process", | |
| "target": "19", | |
| "limit": "22", | |
| "reviewer": "Emma Davis" | |
| }, | |
| { | |
| "id": 66, | |
| "header": "Technical Debt Assessment", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": "24", | |
| "limit": "27", | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 67, | |
| "header": "Capacity Planning", | |
| "type": "Planning", | |
| "status": "In Process", | |
| "target": "21", | |
| "limit": "24", | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 68, | |
| "header": "Service Level Agreements", | |
| "type": "Legal", | |
| "status": "Done", | |
| "target": "26", | |
| "limit": "29", | |
| "reviewer": "Assign reviewer" | |
| } | |
| ] | |
| [ | |
| { | |
| "id": 1, | |
| "header": "Cover page", | |
| "type": "Cover page", | |
| "status": "In Process", | |
| "target": 18, | |
| "limit": 5, | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 2, | |
| "header": "Table of contents", | |
| "type": "Table of contents", | |
| "status": "Done", | |
| "target": 29, | |
| "limit": 24, | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 3, | |
| "header": "Executive summary", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": 10, | |
| "limit": 13, | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 4, | |
| "header": "Technical approach", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": 27, | |
| "limit": 23, | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 5, | |
| "header": "Design", | |
| "type": "Narrative", | |
| "status": "In Process", | |
| "target": 2, | |
| "limit": 16, | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 6, | |
| "header": "Capabilities", | |
| "type": "Narrative", | |
| "status": "In Process", | |
| "target": 20, | |
| "limit": 8, | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 7, | |
| "header": "Integration with existing systems", | |
| "type": "Narrative", | |
| "status": "In Process", | |
| "target": 19, | |
| "limit": 21, | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 8, | |
| "header": "Innovation and Advantages", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": 25, | |
| "limit": 26, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 9, | |
| "header": "Overview of EMR's Innovative Solutions", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": 7, | |
| "limit": 23, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 10, | |
| "header": "Advanced Algorithms and Machine Learning", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": 30, | |
| "limit": 28, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 11, | |
| "header": "Adaptive Communication Protocols", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": 9, | |
| "limit": 31, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 12, | |
| "header": "Advantages Over Current Technologies", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": 12, | |
| "limit": 0, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 13, | |
| "header": "Past Performance", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": 22, | |
| "limit": 33, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 14, | |
| "header": "Customer Feedback and Satisfaction Levels", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": 15, | |
| "limit": 34, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 15, | |
| "header": "Implementation Challenges and Solutions", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": 3, | |
| "limit": 35, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 16, | |
| "header": "Security Measures and Data Protection Policies", | |
| "type": "Narrative", | |
| "status": "In Process", | |
| "target": 6, | |
| "limit": 36, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 17, | |
| "header": "Scalability and Future Proofing", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": 4, | |
| "limit": 37, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 18, | |
| "header": "Cost-Benefit Analysis", | |
| "type": "Plain language", | |
| "status": "Done", | |
| "target": 14, | |
| "limit": 38, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 19, | |
| "header": "User Training and Onboarding Experience", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": 17, | |
| "limit": 39, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 20, | |
| "header": "Future Development Roadmap", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": 11, | |
| "limit": 40, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 21, | |
| "header": "System Architecture Overview", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": 24, | |
| "limit": 18, | |
| "reviewer": "Maya Johnson" | |
| }, | |
| { | |
| "id": 22, | |
| "header": "Risk Management Plan", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": 15, | |
| "limit": 22, | |
| "reviewer": "Carlos Rodriguez" | |
| }, | |
| { | |
| "id": 23, | |
| "header": "Compliance Documentation", | |
| "type": "Legal", | |
| "status": "In Process", | |
| "target": 31, | |
| "limit": 27, | |
| "reviewer": "Sarah Chen" | |
| }, | |
| { | |
| "id": 24, | |
| "header": "API Documentation", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": 8, | |
| "limit": 12, | |
| "reviewer": "Raj Patel" | |
| }, | |
| { | |
| "id": 25, | |
| "header": "User Interface Mockups", | |
| "type": "Visual", | |
| "status": "In Process", | |
| "target": 19, | |
| "limit": 25, | |
| "reviewer": "Leila Ahmadi" | |
| }, | |
| { | |
| "id": 26, | |
| "header": "Database Schema", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": 22, | |
| "limit": 20, | |
| "reviewer": "Thomas Wilson" | |
| }, | |
| { | |
| "id": 27, | |
| "header": "Testing Methodology", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": 17, | |
| "limit": 14, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 28, | |
| "header": "Deployment Strategy", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": 26, | |
| "limit": 30, | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 29, | |
| "header": "Budget Breakdown", | |
| "type": "Financial", | |
| "status": "In Process", | |
| "target": 13, | |
| "limit": 16, | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 30, | |
| "header": "Market Analysis", | |
| "type": "Research", | |
| "status": "Done", | |
| "target": 29, | |
| "limit": 32, | |
| "reviewer": "Sophia Martinez" | |
| }, | |
| { | |
| "id": 31, | |
| "header": "Competitor Comparison", | |
| "type": "Research", | |
| "status": "In Process", | |
| "target": 21, | |
| "limit": 19, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 32, | |
| "header": "Maintenance Plan", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": 16, | |
| "limit": 23, | |
| "reviewer": "Alex Thompson" | |
| }, | |
| { | |
| "id": 33, | |
| "header": "User Personas", | |
| "type": "Research", | |
| "status": "In Process", | |
| "target": 27, | |
| "limit": 24, | |
| "reviewer": "Nina Patel" | |
| }, | |
| { | |
| "id": 34, | |
| "header": "Accessibility Compliance", | |
| "type": "Legal", | |
| "status": "Done", | |
| "target": 18, | |
| "limit": 21, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 35, | |
| "header": "Performance Metrics", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": 23, | |
| "limit": 26, | |
| "reviewer": "David Kim" | |
| }, | |
| { | |
| "id": 36, | |
| "header": "Disaster Recovery Plan", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": 14, | |
| "limit": 17, | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 37, | |
| "header": "Third-party Integrations", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": 25, | |
| "limit": 28, | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 38, | |
| "header": "User Feedback Summary", | |
| "type": "Research", | |
| "status": "Done", | |
| "target": 20, | |
| "limit": 15, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 39, | |
| "header": "Localization Strategy", | |
| "type": "Narrative", | |
| "status": "In Process", | |
| "target": 12, | |
| "limit": 19, | |
| "reviewer": "Maria Garcia" | |
| }, | |
| { | |
| "id": 40, | |
| "header": "Mobile Compatibility", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": 28, | |
| "limit": 31, | |
| "reviewer": "James Wilson" | |
| }, | |
| { | |
| "id": 41, | |
| "header": "Data Migration Plan", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": 19, | |
| "limit": 22, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 42, | |
| "header": "Quality Assurance Protocols", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": 30, | |
| "limit": 33, | |
| "reviewer": "Priya Singh" | |
| }, | |
| { | |
| "id": 43, | |
| "header": "Stakeholder Analysis", | |
| "type": "Research", | |
| "status": "In Process", | |
| "target": 11, | |
| "limit": 14, | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 44, | |
| "header": "Environmental Impact Assessment", | |
| "type": "Research", | |
| "status": "Done", | |
| "target": 24, | |
| "limit": 27, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 45, | |
| "header": "Intellectual Property Rights", | |
| "type": "Legal", | |
| "status": "In Process", | |
| "target": 17, | |
| "limit": 20, | |
| "reviewer": "Sarah Johnson" | |
| }, | |
| { | |
| "id": 46, | |
| "header": "Customer Support Framework", | |
| "type": "Narrative", | |
| "status": "Done", | |
| "target": 22, | |
| "limit": 25, | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 47, | |
| "header": "Version Control Strategy", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": 15, | |
| "limit": 18, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 48, | |
| "header": "Continuous Integration Pipeline", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": 26, | |
| "limit": 29, | |
| "reviewer": "Michael Chen" | |
| }, | |
| { | |
| "id": 49, | |
| "header": "Regulatory Compliance", | |
| "type": "Legal", | |
| "status": "In Process", | |
| "target": 13, | |
| "limit": 16, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 50, | |
| "header": "User Authentication System", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": 28, | |
| "limit": 31, | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 51, | |
| "header": "Data Analytics Framework", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": 21, | |
| "limit": 24, | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 52, | |
| "header": "Cloud Infrastructure", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": 16, | |
| "limit": 19, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 53, | |
| "header": "Network Security Measures", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": 29, | |
| "limit": 32, | |
| "reviewer": "Lisa Wong" | |
| }, | |
| { | |
| "id": 54, | |
| "header": "Project Timeline", | |
| "type": "Planning", | |
| "status": "Done", | |
| "target": 14, | |
| "limit": 17, | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 55, | |
| "header": "Resource Allocation", | |
| "type": "Planning", | |
| "status": "In Process", | |
| "target": 27, | |
| "limit": 30, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 56, | |
| "header": "Team Structure and Roles", | |
| "type": "Planning", | |
| "status": "Done", | |
| "target": 20, | |
| "limit": 23, | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 57, | |
| "header": "Communication Protocols", | |
| "type": "Planning", | |
| "status": "In Process", | |
| "target": 15, | |
| "limit": 18, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 58, | |
| "header": "Success Metrics", | |
| "type": "Planning", | |
| "status": "Done", | |
| "target": 30, | |
| "limit": 33, | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 59, | |
| "header": "Internationalization Support", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": 23, | |
| "limit": 26, | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 60, | |
| "header": "Backup and Recovery Procedures", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": 18, | |
| "limit": 21, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 61, | |
| "header": "Monitoring and Alerting System", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": 25, | |
| "limit": 28, | |
| "reviewer": "Daniel Park" | |
| }, | |
| { | |
| "id": 62, | |
| "header": "Code Review Guidelines", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": 12, | |
| "limit": 15, | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 63, | |
| "header": "Documentation Standards", | |
| "type": "Technical content", | |
| "status": "In Process", | |
| "target": 27, | |
| "limit": 30, | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 64, | |
| "header": "Release Management Process", | |
| "type": "Planning", | |
| "status": "Done", | |
| "target": 22, | |
| "limit": 25, | |
| "reviewer": "Assign reviewer" | |
| }, | |
| { | |
| "id": 65, | |
| "header": "Feature Prioritization Matrix", | |
| "type": "Planning", | |
| "status": "In Process", | |
| "target": 19, | |
| "limit": 22, | |
| "reviewer": "Emma Davis" | |
| }, | |
| { | |
| "id": 66, | |
| "header": "Technical Debt Assessment", | |
| "type": "Technical content", | |
| "status": "Done", | |
| "target": 24, | |
| "limit": 27, | |
| "reviewer": "Eddie Lake" | |
| }, | |
| { | |
| "id": 67, | |
| "header": "Capacity Planning", | |
| "type": "Planning", | |
| "status": "In Process", | |
| "target": 21, | |
| "limit": 24, | |
| "reviewer": "Jamik Tashpulatov" | |
| }, | |
| { | |
| "id": 68, | |
| "header": "Service Level Agreements", | |
| "type": "Legal", | |
| "status": "Done", | |
| "target": 26, | |
| "limit": 29, | |
| "reviewer": "Assign reviewer" | |
| } | |
| ] |
π€ Prompt for AI Agents
In frontend/src/app/dashboard/data.json around lines 1 to 614, the "target" and
"limit" properties are stored as strings but should be numeric; update every of
the 68 objects so target and limit are numbers (remove surrounding quotes and
ensure values are numeric literals) across the file; you can do this by running
a small script or using a bulk edit to parse the JSON, convert
Number(obj.target) and Number(obj.limit) for each entry (or remove quotes
manually) and then save the file with the updated numeric values.
| navClouds: [ | ||
| { | ||
| title: "Capture", | ||
| icon: IconCamera, | ||
| isActive: true, | ||
| url: "#", | ||
| items: [ | ||
| { | ||
| title: "Active Proposals", | ||
| url: "#", | ||
| }, | ||
| { | ||
| title: "Archived", | ||
| url: "#", | ||
| }, | ||
| ], | ||
| }, | ||
| { | ||
| title: "Proposal", | ||
| icon: IconFileDescription, | ||
| url: "#", | ||
| items: [ | ||
| { | ||
| title: "Active Proposals", | ||
| url: "#", | ||
| }, | ||
| { | ||
| title: "Archived", | ||
| url: "#", | ||
| }, | ||
| ], | ||
| }, | ||
| { | ||
| title: "Prompts", | ||
| icon: IconFileAi, | ||
| url: "#", | ||
| items: [ | ||
| { | ||
| title: "Active Proposals", | ||
| url: "#", | ||
| }, | ||
| { | ||
| title: "Archived", | ||
| url: "#", | ||
| }, | ||
| ], | ||
| }, | ||
| ], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
π οΈ Refactor suggestion | π Major
Remove unused navClouds data.
The navClouds array is defined but never used in the component render. This is dead code that should be removed to improve maintainability.
Apply this diff:
},
],
- navClouds: [
- {
- title: "Capture",
- icon: IconCamera,
- isActive: true,
- url: "#",
- items: [
- {
- title: "Active Proposals",
- url: "#",
- },
- {
- title: "Archived",
- url: "#",
- },
- ],
- },
- {
- title: "Proposal",
- icon: IconFileDescription,
- url: "#",
- items: [
- {
- title: "Active Proposals",
- url: "#",
- },
- {
- title: "Archived",
- url: "#",
- },
- ],
- },
- {
- title: "Prompts",
- icon: IconFileAi,
- url: "#",
- items: [
- {
- title: "Active Proposals",
- url: "#",
- },
- {
- title: "Archived",
- url: "#",
- },
- ],
- },
- ],
navSecondary: [Alternatively, if this data is intended for future use, add a comment explaining its purpose.
Committable suggestion skipped: line range outside the PR's diff.
π€ Prompt for AI Agents
In frontend/src/components/admin/app-sidebar.tsx around lines 67 to 114, the
navClouds array is declared but never referenced in the component; remove the
entire navClouds definition to eliminate dead code, or if it's intended for
future use, keep it but add a clear comment above explaining its purpose and
intended usage (and ideally mark with TODO or FIXME) so reviewers know itβs
intentionally unused.
| desktop: { | ||
| label: "Desktop", | ||
| color: "var(--primary)", | ||
| }, | ||
| mobile: { | ||
| label: "Mobile", | ||
| color: "var(--primary)", | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Desktop and mobile series use identical colors.
Both desktop and mobile are configured with color: "var(--primary)", making them visually indistinguishable in the stacked area chart. Consider using distinct colors for each series.
desktop: {
label: "Desktop",
color: "var(--primary)",
},
mobile: {
label: "Mobile",
- color: "var(--primary)",
+ color: "var(--secondary)",
},π 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.
| desktop: { | |
| label: "Desktop", | |
| color: "var(--primary)", | |
| }, | |
| mobile: { | |
| label: "Mobile", | |
| color: "var(--primary)", | |
| }, | |
| desktop: { | |
| label: "Desktop", | |
| color: "var(--primary)", | |
| }, | |
| mobile: { | |
| label: "Mobile", | |
| color: "var(--secondary)", | |
| }, |
π€ Prompt for AI Agents
In frontend/src/components/admin/chart-area-interactive.tsx around lines 133 to
140, the desktop and mobile series both use color: "var(--primary)" making them
indistinguishable; update the mobile (or desktop) series to use a different CSS
variable or color (for example var(--accent) or a distinct hex) so each series
has a unique, accessible color, and ensure the chosen colors maintain sufficient
contrast and visual separation in the stacked area chart.
| { | ||
| accessorKey: "target", | ||
| header: () => <div className="w-full text-right">Target</div>, | ||
| cell: ({ row }) => ( | ||
| <form | ||
| onSubmit={(e) => { | ||
| e.preventDefault() | ||
| toast.promise(new Promise((resolve) => setTimeout(resolve, 1000)), { | ||
| loading: `Saving ${row.original.header}`, | ||
| success: "Done", | ||
| error: "Error", | ||
| }) | ||
| }} | ||
| > | ||
| <Label htmlFor={`${row.original.id}-target`} className="sr-only"> | ||
| Target | ||
| </Label> | ||
| <Input | ||
| className="hover:bg-input/30 focus-visible:bg-background dark:hover:bg-input/30 dark:focus-visible:bg-input/30 h-8 w-16 border-transparent bg-transparent text-right shadow-none focus-visible:border dark:bg-transparent" | ||
| defaultValue={row.original.target} | ||
| id={`${row.original.id}-target`} | ||
| /> | ||
| </form> | ||
| ), | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inline editing does not persist changes.
The form shows a success toast but doesn't actually update the data. The Input uses defaultValue without any mechanism to capture or persist the changed value. After "saving", row.original.target remains unchanged.
Consider implementing actual persistence:
cell: ({ row }) => (
- <form
- onSubmit={(e) => {
- e.preventDefault()
- toast.promise(new Promise((resolve) => setTimeout(resolve, 1000)), {
- loading: `Saving ${row.original.header}`,
- success: "Done",
- error: "Error",
- })
- }}
- >
+ <form
+ onSubmit={(e) => {
+ e.preventDefault()
+ const formData = new FormData(e.currentTarget)
+ const newTarget = formData.get("target") as string
+ // Call a save handler passed via props or context
+ onSave?.(row.original.id, { target: newTarget })
+ }}
+ >
<Label htmlFor={`${row.original.id}-target`} className="sr-only">
Target
</Label>
<Input
className="hover:bg-input/30 focus-visible:bg-background dark:hover:bg-input/30 dark:focus-visible:bg-input/30 h-8 w-16 border-transparent bg-transparent text-right shadow-none focus-visible:border dark:bg-transparent"
defaultValue={row.original.target}
id={`${row.original.id}-target`}
+ name="target"
/>
</form>
),Committable suggestion skipped: line range outside the PR's diff.
π€ Prompt for AI Agents
In frontend/src/components/admin/data-table.tsx around lines 202 to 226, the
inline edit form uses Input with defaultValue so edits are never captured or
persisted; change the Input to controlled (track value in component state or a
per-row state map) or use a ref to read the current value on submit, then call
the persistence layer (API or parent state updater) to save the new target,
update the table data (e.g., update row.original or invoke the table data
setter) and show toast based on the save result so the displayed value reflects
the persisted change.
| return ( | ||
| <> | ||
| <Label htmlFor={`${row.original.id}-reviewer`} className="sr-only"> | ||
| Reviewer | ||
| </Label> | ||
| <Select> | ||
| <SelectTrigger | ||
| className="w-38 **:data-[slot=select-value]:block **:data-[slot=select-value]:truncate" | ||
| size="sm" | ||
| id={`${row.original.id}-reviewer`} | ||
| > | ||
| <SelectValue placeholder="Assign reviewer" /> | ||
| </SelectTrigger> | ||
| <SelectContent align="end"> | ||
| <SelectItem value="Eddie Lake">Eddie Lake</SelectItem> | ||
| <SelectItem value="Jamik Tashpulatov"> | ||
| Jamik Tashpulatov | ||
| </SelectItem> | ||
| </SelectContent> | ||
| </Select> | ||
| </> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewer selection does not update state.
The Select component lacks an onValueChange handler, so selecting a reviewer has no effect. The selection is not persisted to the row data.
Add a handler to update the data:
- <Select>
+ <Select onValueChange={(value) => {
+ // Update row data or call parent callback
+ }}>Committable suggestion skipped: line range outside the PR's diff.
π€ Prompt for AI Agents
In frontend/src/components/admin/data-table.tsx around lines 262-282, the Select
has no onValueChange so chosen reviewer isn't saved; add an onValueChange
handler that updates the row's reviewer and make the Select controlled.
Implement something like: add onValueChange={(val) =>
handleAssignReviewer(row.index, val)} on the Select, pass the current reviewer
value into the Select (or SelectTrigger/SelectValue) so it displays the selected
name, and implement handleAssignReviewer to call the component's row-update API
(e.g., a provided updateRow/updateData prop or the table state setter) to
persist reviewer into row.original.reviewer (or row data) immutably.
| const data = { | ||
| user: { | ||
| name: "shadcn", | ||
| email: "m@example.com", | ||
| avatar: "/avatars/shadcn.jpg", | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix user data inconsistency between header and footer.
The header displays the authenticated user's name from useAuth() (line 167), but the footer renders NavUser with static placeholder data (data.user with name "shadcn" at line 179). This creates a confusing UX where different parts of the sidebar show different users.
Apply this diff to use the authenticated user consistently:
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
const { user } = useAuth();
return (
<Sidebar collapsible="offcanvas" {...props}>
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton
asChild
className="data-[slot=sidebar-menu-button]:!p-1.5"
>
<a href="#">
<IconInnerShadowTop className="!size-5" />
<span className="text-base font-semibold">{user?.name ?? ""}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
<SidebarContent>
<NavMain items={data.navMain} />
<NavDocuments items={data.documents} />
<NavSecondary items={data.navSecondary} className="mt-auto" />
</SidebarContent>
<SidebarFooter>
- <NavUser user={data.user} />
+ <NavUser user={user ? { name: user.name, email: user.email, avatar: user.avatar || "/avatars/default.jpg" } : data.user} />
</SidebarFooter>
</Sidebar>
)
}Alternatively, if data.user is meant as a fallback for unauthenticated states, ensure the header also uses this fallback pattern.
Also applies to: 155-155, 179-179
π€ Prompt for AI Agents
In frontend/src/components/AppSidebar.tsx around lines 37-42, 155, 167 and 179,
the footer NavUser is rendered with static placeholder data.user ("shadcn")
while the header uses the authenticated user from useAuth(), causing
inconsistent UX; update the footer to use the authenticated user object returned
by useAuth() (the same value used at line 167), and if data.user is intended as
a fallback for unauthenticated states, implement the same fallback pattern in
both header and footer (e.g., useAuthUser ?? data.user) so both header and
footer show the same user or the same fallback consistently.
| function BreadcrumbEllipsis({ | ||
| className, | ||
| ...props | ||
| }: React.ComponentProps<"span">) { | ||
| return ( | ||
| <span | ||
| data-slot="breadcrumb-ellipsis" | ||
| role="presentation" | ||
| aria-hidden="true" | ||
| className={cn("flex size-9 items-center justify-center", className)} | ||
| {...props} | ||
| > | ||
| <MoreHorizontal className="size-4" /> | ||
| <span className="sr-only">More</span> | ||
| </span> | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix BreadcrumbEllipsis accessibility: aria-hidden hides the sr-only label
In BreadcrumbEllipsis (Lines 88β97), the outer <span> has role="presentation" and aria-hidden="true" while containing an sr-only <span>More</span>. Because aria-hidden on the parent hides the entire subtree, assistive tech will never read the βMoreβ label.
Consider making the wrapper accessible and hiding only the icon:
-function BreadcrumbEllipsis({
- className,
- ...props
-}: React.ComponentProps<"span">) {
- return (
- <span
- data-slot="breadcrumb-ellipsis"
- role="presentation"
- aria-hidden="true"
- className={cn("flex size-9 items-center justify-center", className)}
- {...props}
- >
- <MoreHorizontal className="size-4" />
- <span className="sr-only">More</span>
- </span>
- )
-}
+function BreadcrumbEllipsis({
+ className,
+ ...props
+}: React.ComponentProps<"span">) {
+ return (
+ <span
+ data-slot="breadcrumb-ellipsis"
+ className={cn("flex size-9 items-center justify-center", className)}
+ {...props}
+ >
+ <MoreHorizontal className="size-4" aria-hidden="true" />
+ <span className="sr-only">More</span>
+ </span>
+ )
+}This keeps the icon decorative while exposing the βMoreβ text to screen readers.
π 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.
| function BreadcrumbEllipsis({ | |
| className, | |
| ...props | |
| }: React.ComponentProps<"span">) { | |
| return ( | |
| <span | |
| data-slot="breadcrumb-ellipsis" | |
| role="presentation" | |
| aria-hidden="true" | |
| className={cn("flex size-9 items-center justify-center", className)} | |
| {...props} | |
| > | |
| <MoreHorizontal className="size-4" /> | |
| <span className="sr-only">More</span> | |
| </span> | |
| ) | |
| function BreadcrumbEllipsis({ | |
| className, | |
| ...props | |
| }: React.ComponentProps<"span">) { | |
| return ( | |
| <span | |
| data-slot="breadcrumb-ellipsis" | |
| className={cn("flex size-9 items-center justify-center", className)} | |
| {...props} | |
| > | |
| <MoreHorizontal className="size-4" aria-hidden="true" /> | |
| <span className="sr-only">More</span> | |
| </span> | |
| ) | |
| } |
π€ Prompt for AI Agents
frontend/src/components/ui/breadcrumb.tsx lines 83-98: the wrapper span
currently has role="presentation" and aria-hidden="true" which hides the sr-only
"More" label; remove role and aria-hidden from the outer span so the assistive
label is exposed, and instead mark the decorative icon as hidden to AT (add
aria-hidden="true" to the MoreHorizontal SVG/component or wrap the icon in a
span with aria-hidden="true"); keep the sr-only "More" span unchanged so screen
readers read the label.
| {item.value && ( | ||
| <span className="text-foreground font-mono font-medium tabular-nums"> | ||
| {item.value.toLocaleString()} | ||
| </span> | ||
| )} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Truthy check will hide zero values.
{item.value && ...} will not render when item.value is 0, which is a valid numeric value in charts. Use an explicit check instead.
- {item.value && (
+ {item.value !== undefined && item.value !== null && (
<span className="text-foreground font-mono font-medium tabular-nums">
{item.value.toLocaleString()}
</span>
)}π 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.
| {item.value && ( | |
| <span className="text-foreground font-mono font-medium tabular-nums"> | |
| {item.value.toLocaleString()} | |
| </span> | |
| )} | |
| {item.value !== undefined && item.value !== null && ( | |
| <span className="text-foreground font-mono font-medium tabular-nums"> | |
| {item.value.toLocaleString()} | |
| </span> | |
| )} |
π€ Prompt for AI Agents
In frontend/src/components/ui/chart.tsx around lines 233-237, the conditional
`{item.value && ...}` hides legitimate zero values; change the guard to an
explicit null/undefined check (e.g., `item.value != null` or `item.value !==
undefined && item.value !== null`) so 0 renders, keeping the same inner span and
formatting logic.
| if (isMobile) { | ||
| return ( | ||
| <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}> | ||
| <SheetContent | ||
| data-sidebar="sidebar" | ||
| data-slot="sidebar" | ||
| data-mobile="true" | ||
| className="bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden" | ||
| style={ | ||
| { | ||
| "--sidebar-width": SIDEBAR_WIDTH_MOBILE, | ||
| } as React.CSSProperties | ||
| } | ||
| side={side} | ||
| > | ||
| <SheetHeader className="sr-only"> | ||
| <SheetTitle>Sidebar</SheetTitle> | ||
| <SheetDescription>Displays the mobile sidebar.</SheetDescription> | ||
| </SheetHeader> | ||
| <div className="flex h-full w-full flex-col">{children}</div> | ||
| </SheetContent> | ||
| </Sheet> | ||
| ) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Props type mismatch when spreading onto Sheet.
The props are typed as React.ComponentProps<"div">, but they're spread onto Sheet (line 185). This could pass incompatible props and cause React warnings. Consider filtering props or adjusting the type.
if (isMobile) {
return (
- <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>
+ <Sheet open={openMobile} onOpenChange={setOpenMobile}>
<SheetContent
data-sidebar="sidebar"
data-slot="sidebar"Alternatively, if specific Sheet props are needed, create a separate prop for them or extract div-specific props.
π 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.
| if (isMobile) { | |
| return ( | |
| <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}> | |
| <SheetContent | |
| data-sidebar="sidebar" | |
| data-slot="sidebar" | |
| data-mobile="true" | |
| className="bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden" | |
| style={ | |
| { | |
| "--sidebar-width": SIDEBAR_WIDTH_MOBILE, | |
| } as React.CSSProperties | |
| } | |
| side={side} | |
| > | |
| <SheetHeader className="sr-only"> | |
| <SheetTitle>Sidebar</SheetTitle> | |
| <SheetDescription>Displays the mobile sidebar.</SheetDescription> | |
| </SheetHeader> | |
| <div className="flex h-full w-full flex-col">{children}</div> | |
| </SheetContent> | |
| </Sheet> | |
| ) | |
| } | |
| if (isMobile) { | |
| return ( | |
| <Sheet open={openMobile} onOpenChange={setOpenMobile}> | |
| <SheetContent | |
| data-sidebar="sidebar" | |
| data-slot="sidebar" | |
| data-mobile="true" | |
| className="bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden" | |
| style={ | |
| { | |
| "--sidebar-width": SIDEBAR_WIDTH_MOBILE, | |
| } as React.CSSProperties | |
| } | |
| side={side} | |
| > | |
| <SheetHeader className="sr-only"> | |
| <SheetTitle>Sidebar</SheetTitle> | |
| <SheetDescription>Displays the mobile sidebar.</SheetDescription> | |
| </SheetHeader> | |
| <div className="flex h-full w-full flex-col">{children}</div> | |
| </SheetContent> | |
| </Sheet> | |
| ) | |
| } |
| const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) | ||
| const onChange = () => { | ||
| setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) | ||
| } | ||
| mql.addEventListener("change", onChange) | ||
| setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use MediaQueryList.matches for consistency.
The onChange handler uses window.innerWidth < MOBILE_BREAKPOINT while the MediaQueryList is created with max-width: ${MOBILE_BREAKPOINT - 1}px. This inconsistency can cause edge-case bugs at exactly 768px.
Apply this diff to use the MediaQueryList's matches property:
React.useEffect(() => {
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
const onChange = () => {
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
+ setIsMobile(mql.matches)
}
mql.addEventListener("change", onChange)
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
+ setIsMobile(mql.matches)
return () => mql.removeEventListener("change", onChange)
}, [])π 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.
| const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) | |
| const onChange = () => { | |
| setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) | |
| } | |
| mql.addEventListener("change", onChange) | |
| setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) | |
| const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) | |
| const onChange = () => { | |
| setIsMobile(mql.matches) | |
| } | |
| mql.addEventListener("change", onChange) | |
| setIsMobile(mql.matches) |
π€ Prompt for AI Agents
In frontend/src/hooks/use-mobile.ts around lines 9 to 14, the handler and
initial state use window.innerWidth while the MediaQueryList was created with
`(max-width: ${MOBILE_BREAKPOINT - 1}px)`, causing inconsistent edge-case
behavior; update the onChange handler to setIsMobile(mql.matches) and change the
initial setIsMobile call to use mql.matches so both use the MediaQueryList's
matches value consistently (and keep the existing mql.addEventListener call
as-is).
π PR Description:
This PR introduces a fully functional dashboard to the project, enhancing the UI with a structured layout and reusable components. The implementation includes:
β Page/Dashboard.tsx: Main dashboard entry point.
β data.json: Sample static data for charts and tables.
β Components added under components/:
app-sidebar.tsx: Responsive sidebar navigation
chart-area-interactive.tsx: Interactive area chart for visual data
data-table.tsx: Tabular display of sample data
nav-documents.tsx, nav-main.tsx, nav-secondary.tsx, nav-user.tsx: Modular navigation elements
section-cards.tsx: Dashboard metric cards
site-header.tsx: Top header bar for branding/user controls
This update lays the foundation for a scalable admin interface and improves project structure and modularity.
Summary by CodeRabbit
Release Notes
New Features
Refactor
βοΈ Tip: You can customize this high-level summary in your review settings.