feat: add click through for Stories on Story list view#20
feat: add click through for Stories on Story list view#20ananthsridhar wants to merge 2 commits into
Conversation
Make stories clickable to view their details. Add story detail page that shows description, acceptance criteria, and tasks.
📝 WalkthroughSummary by CodeRabbit
WalkthroughAjout d’une page serveur pour afficher le détail d’une story à partir du dépôt et du cache projet, avec redirection vers la connexion ou 404 selon les données disponibles. La table des stories ajoute aussi une navigation au clic vers cette page. ChangesNavigation des stories
Sequence Diagram(s)sequenceDiagram
participant StoryPage
participant getAuthenticatedUserId
participant getAuthenticatedRepoConfig
participant getCachedBmadProject
participant StoryDetailView
StoryPage->>StoryPage: resolve params
StoryPage->>getAuthenticatedUserId: read authenticated user id
alt no authenticated user
StoryPage->>StoryPage: redirect("/login")
else authenticated user
StoryPage->>getAuthenticatedRepoConfig: load repo config
alt repo config missing
StoryPage->>StoryPage: notFound()
else repo config found
StoryPage->>getCachedBmadProject: load project from cache
alt project missing or story missing
StoryPage->>StoryPage: notFound()
else story found
StoryPage->>StoryDetailView: render story detail
end
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested labels
🚥 Pre-merge checks | ✅ 6 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (6 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/components/stories/stories-table.tsx`:
- Around line 139-141: The handleRowClick navigation in stories-table.tsx is
building the detail URL with a raw story.id, which can break for IDs containing
special characters. Update the router.push target to encode the story.id before
concatenating it with pathname, and keep the change localized to handleRowClick
so it stays consistent with the StoryDetail route handling and Next.js params
decoding.
- Line 153: The row click handler in stories-table lacks keyboard accessibility
support. Update the row rendering around handleRowClick/onRowClick to make
interactive rows focusable and operable from the keyboard by adding
tabIndex={0}, an onKeyDown handler that triggers the same row click on Enter and
Space, and an appropriate ARIA role consistent with the interaction pattern.
Mirror the keyboard behavior already used in data-grid-table.tsx so the detail
navigation works without a mouse.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 4e147c0c-30fa-4212-8440-a26baa6b5416
📒 Files selected for processing (2)
src/app/(dashboard)/repo/[owner]/[repo]/stories/[storyId]/page.tsxsrc/components/stories/stories-table.tsx
📜 Review details
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{css,tsx,ts,jsx,js}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Tailwind CSS v4 with
@theme inlineinsrc/app/globals.css(no tailwind.config file)
Files:
src/components/stories/stories-table.tsxsrc/app/(dashboard)/repo/[owner]/[repo]/stories/[storyId]/page.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{tsx,jsx}: Never use arbitrary bracket values in Tailwind when a canonical class exists (spacing: divide px by 4, ring width: usering-3notring-[3px], percentages: use fraction notation liketop-1/2, rem values: convert to spacing scale)
Arbitrary Tailwind values are only OK for: calc expressions, non-standard values, and CSS variable references
Files:
src/components/stories/stories-table.tsxsrc/app/(dashboard)/repo/[owner]/[repo]/stories/[storyId]/page.tsx
**/*.{css,tsx,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Repeated hex colors should be added as theme tokens in
globals.cssrather than as inline arbitrary Tailwind values
Files:
src/components/stories/stories-table.tsxsrc/app/(dashboard)/repo/[owner]/[repo]/stories/[storyId]/page.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/*.{ts,tsx}: Use TypeScript strictly — noanyunless absolutely necessary
Prefer explicit types over inference for function signatures in TypeScript
Use Server Components by default — add"use client"directive only when needed
Files:
src/components/stories/stories-table.tsxsrc/app/(dashboard)/repo/[owner]/[repo]/stories/[storyId]/page.tsx
**/*.{css,ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/*.{css,ts,tsx,js,jsx}: Never use arbitrary bracket values in Tailwind CSS when a canonical class exists (e.g., usew-40instead ofw-[160px],mt-3.75instead ofmt-[15px],ring-3instead ofring-[3px],top-1/2instead oftop-[50%])
Arbitrary values in Tailwind CSS are acceptable for:calc()expressions, CSS variable references, and non-standard values
Files:
src/components/stories/stories-table.tsxsrc/app/(dashboard)/repo/[owner]/[repo]/stories/[storyId]/page.tsx
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (SECURITY.md)
Implement AES-256-GCM encryption for OAuth tokens stored in the database using
BETTER_AUTH_SECRETas the key material
Files:
src/components/stories/stories-table.tsxsrc/app/(dashboard)/repo/[owner]/[repo]/stories/[storyId]/page.tsx
**/*.{tsx,ts,css}
📄 CodeRabbit inference engine (Custom checks)
Tailwind v4 conventions: Use canonical utility classes over arbitrary bracket values, represent repeated colors as globals.css theme tokens, and ensure accessible responsive controls
Files:
src/components/stories/stories-table.tsxsrc/app/(dashboard)/repo/[owner]/[repo]/stories/[storyId]/page.tsx
**
⚙️ CodeRabbit configuration file
**: # MyBMAD DashboardTailwind CSS
- Uses Tailwind CSS v4 with
@theme inlineinsrc/app/globals.css(no tailwind.config file)- Never use arbitrary bracket values when a canonical Tailwind class exists:
- Spacing/sizing: divide px by 4 (e.g.
160px→w-40,15px→mt-3.75,2px→h-0.5)- Ring width:
ring-3notring-[3px]- Percentages: fraction notation (
top-1/2nottop-[50%])- Rem: convert to spacing scale (
8rem= 128px / 4 =min-w-32)- Arbitrary values are OK only for: calc expressions, non-standard values, CSS variable references
- Repeated hex colors should be added as theme tokens in
globals.cssrather than as inline arbitrary values- shadcn UI components live in
src/components/ui/and are project-owned — they can and should follow these conventionsError Handling Pattern
All server actions return
ActionResult<T>:type ActionResult<T> = { success: true; data: T } | { success: false; error: string; code?: string }Always use
sanitizeError()from@/lib/errorsto sanitize error messages before returning them to clients. Never exposeerror.messagedirectly.import { sanitizeError } from "`@/lib/errors`"; // ... } catch (error) { return { success: false, error: sanitizeError(error, "DB_ERROR"), code: "DB_ERROR" }; }Server Actions Conventions
- Always validate input with Zod at the top of the action
- Use
requireAdmin()from@/lib/db/helpersfor admin-only actions- Call
revalidatePath()orrevalidateTag()after mutations- Return
ActionResult<T>shape consistently- Actions live in
src/actions/Database Migrations
- Development:
pnpm prisma migrate dev --name <description>- Production:
pnpm prisma migrate deploy(never usemigrate devin production)- After schema changes:
pnpm prisma generateto regenerate the clientTesting
- Framework: Vitest
- Run tests:
pnpm test- Watch mode:
pnpm test:watch
-...
Files:
src/components/stories/stories-table.tsxsrc/app/(dashboard)/repo/[owner]/[repo]/stories/[storyId]/page.tsx
src/components/**
⚙️ CodeRabbit configuration file
src/components/**: Review React UI code for accessibility, server/client component boundaries, hydration risks, keyboard navigation, loading/error/empty states, and responsive behavior.
Tailwind CSS v4 conventions for this repo:
- Do not use arbitrary bracket values when a canonical Tailwind class exists.
- Repeated colors should become theme tokens in src/app/globals.css.
- shadcn components in src/components/ui are project-owned and should follow the same rules.
Ignore style concerns for src/components/animate-ui and src/components/reui because they are excluded vendored components.
Files:
src/components/stories/stories-table.tsx
src/app/(dashboard)/**
⚙️ CodeRabbit configuration file
src/app/(dashboard)/**: Review authenticated dashboard pages for server-side data access, cache invalidation assumptions, route params, suspense/loading behavior, empty states, and user isolation across repos.
Files:
src/app/(dashboard)/repo/[owner]/[repo]/stories/[storyId]/page.tsx
🔇 Additional comments (1)
src/app/(dashboard)/repo/[owner]/[repo]/stories/[storyId]/page.tsx (1)
17-54: LGTM!
| const handleRowClick = (story: StoryDetail) => { | ||
| router.push(`${pathname}/${story.id}`); | ||
| }; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Encoder story.id dans la cible de navigation.
story.id est concaténé brut dans l'URL. S'il contient des caractères spéciaux (espace, /, #, etc.), l'URL générée sera incorrecte ou cassée. La page de détail compare s.id === storyId après décodage automatique des params par Next.js, donc encoder ici reste cohérent côté serveur.
🐛 Correctif proposé
const handleRowClick = (story: StoryDetail) => {
- router.push(`${pathname}/${story.id}`);
+ router.push(`${pathname}/${encodeURIComponent(story.id)}`);
};📝 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 handleRowClick = (story: StoryDetail) => { | |
| router.push(`${pathname}/${story.id}`); | |
| }; | |
| const handleRowClick = (story: StoryDetail) => { | |
| router.push(`${pathname}/${encodeURIComponent(story.id)}`); | |
| }; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/stories/stories-table.tsx` around lines 139 - 141, The
handleRowClick navigation in stories-table.tsx is building the detail URL with a
raw story.id, which can break for IDs containing special characters. Update the
router.push target to encode the story.id before concatenating it with pathname,
and keep the change localized to handleRowClick so it stays consistent with the
StoryDetail route handling and Next.js params decoding.
| headerBorder: true, | ||
| rowBorder: true, | ||
| }} | ||
| onRowClick={handleRowClick} |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Inspecter l'implémentation de DataGrid/DataGridTable pour le support de onRowClick au clavier
fd -i 'data-grid' --type f
ast-grep run --pattern 'onRowClick' --lang tsx $(fd -i 'data-grid' --type f) 2>/dev/null
rg -nP -C3 'onRowClick|onKeyDown|role=|tabIndex' $(fd -i 'data-grid' --type f) 2>/dev/nullRepository: DevHDI/my-bmad
Length of output: 4239
Ajouter la navigation clavier pour les lignes cliquables
Les lignes interactives utilisent actuellement onRowClick mais manquent de support clavier. Il faut éviter les problèmes d'accessibilité en ajoutant :
- `tabIndex={0}
- Un gestionnaire d'événements
onKeyDownpour la touche Entrée et l'Espace. - Le rôle ARIA adéquat.
Sans cela, la navigation vers le détail est impossible au clavier.
src/components/reui/data-grid/data-grid-table.tsx
onMouseDown={(e) => {
if (isClickOrClickChild) {
e.currentTarget.setAttribute("data-is-interacting", "true");
e.preventDefault();
}
}}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
props.onRowClick?.(row.original);
}
}}
tabIndex={0}
role="button"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/stories/stories-table.tsx` at line 153, The row click handler
in stories-table lacks keyboard accessibility support. Update the row rendering
around handleRowClick/onRowClick to make interactive rows focusable and operable
from the keyboard by adding tabIndex={0}, an onKeyDown handler that triggers the
same row click on Enter and Space, and an appropriate ARIA role consistent with
the interaction pattern. Mirror the keyboard behavior already used in
data-grid-table.tsx so the detail navigation works without a mouse.
Source: Path instructions
Summary
Add the ability to click on stories in the stories list to view their full details, including
description, acceptance criteria, and task list.
Type of Change
Changes Made
/repo/[owner]/[repo]/stories/[storyId]/page.tsxStoryDetailViewcomponent for consistent stylingTesting
Describe how you tested this change:
pnpm lintpassespnpm testpassespnpm buildsucceedsManual testing verified:
Screenshots (if UI change)
Before: Stories list with non-clickable rows
After: Clickable story rows that navigate to detail page showing: