Skip to content

feat: add click through for Stories on Story list view#20

Open
ananthsridhar wants to merge 2 commits into
DevHDI:mainfrom
ananthsridhar:stories-clickable
Open

feat: add click through for Stories on Story list view#20
ananthsridhar wants to merge 2 commits into
DevHDI:mainfrom
ananthsridhar:stories-clickable

Conversation

@ananthsridhar

Copy link
Copy Markdown

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

  • New feature
  • Bug fix
  • Refactoring (no behavior change)
  • Documentation update
  • Dependency update

Changes Made

  • Added new story detail page at /repo/[owner]/[repo]/stories/[storyId]/page.tsx
  • Made stories table rows clickable with navigation to the detail view
  • Added back button to return to stories list from detail view
  • Reused existing StoryDetailView component for consistent styling

Testing

Describe how you tested this change:

  • pnpm lint passes
  • pnpm test passes
  • pnpm build succeeds
  • Tested manually in browser

Manual testing verified:

  • Stories in the table are clickable
  • Clicking a story navigates to its detail page
  • Story details display correctly (title, description, acceptance criteria, tasks)
  • Back button returns to the stories list

Screenshots (if UI change)

Before: Stories list with non-clickable rows
After: Clickable story rows that navigate to detail page showing:

  • Story title and epic
  • Description
  • Acceptance criteria (bulleted list)
  • Tasks with completion status and progress gauge

Make stories clickable to view their details. Add story detail page that shows description, acceptance criteria, and tasks.
@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Nouvelles fonctionnalités

    • Ajout d’une page de détail pour les stories dans le tableau de bord, avec accès direct au contenu d’une story et retour vers la liste.
    • Les lignes du tableau des stories sont désormais cliquables pour ouvrir rapidement le détail d’une story.
  • Corrections de bugs

    • Gestion améliorée des accès : redirection vers la connexion si nécessaire et affichage d’une page introuvable lorsque le dépôt ou la story n’existe pas.

Walkthrough

Ajout 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.

Changes

Navigation des stories

Layer / File(s) Summary
Page de détail serveur
src/app/(dashboard)/repo/[owner]/[repo]/stories/[storyId]/page.tsx
StoryPage résout l’utilisateur, la config du dépôt, le projet en cache et la story, puis rend le lien de retour, le titre et StoryDetailView.
Navigation au clic dans la table
src/components/stories/stories-table.tsx
StoriesTable ajoute useRouter/usePathname, construit la route de story au clic sur une ligne, et déclenche router.push via onRowClick.

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

frontend

🚥 Pre-merge checks | ✅ 6 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Tailwind V4 Conventions ⚠️ Warning Le contrôle retour est un <Link><Button/></Link> sans asChild, et les lignes cliquables restent au onClick seul, sans support clavier. Passer le bouton retour en Button asChild avec Link, et rendre les lignes cliquables focusables/activables au clavier (tabIndex, role, onKeyDown).
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed Le titre est clair, lié au changement principal et respecte le préfixe conventionnel demandé.
Description check ✅ Passed La description correspond bien aux ajouts de navigation et à la page de détail des stories.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Server Action Contract ✅ Passed Aucun server action n’a été modifié: les fichiers changés sont une page serveur et un composant client, sans use server, ActionResult, Zod ni mutation.
Auth And Data Isolation ✅ Passed PASS — la page détail exige une session, filtre le repo par userId, récupère le token GitHub par userId et n’affiche que des données du projet courant; aucun chemin local/token/session n’est exposé.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 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

📥 Commits

Reviewing files that changed from the base of the PR and between ab2ed8e and 3d7b6df.

📒 Files selected for processing (2)
  • src/app/(dashboard)/repo/[owner]/[repo]/stories/[storyId]/page.tsx
  • src/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 inline in src/app/globals.css (no tailwind.config file)

Files:

  • src/components/stories/stories-table.tsx
  • src/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: use ring-3 not ring-[3px], percentages: use fraction notation like top-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.tsx
  • src/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.css rather than as inline arbitrary Tailwind values

Files:

  • src/components/stories/stories-table.tsx
  • src/app/(dashboard)/repo/[owner]/[repo]/stories/[storyId]/page.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{ts,tsx}: Use TypeScript strictly — no any unless 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.tsx
  • src/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., use w-40 instead of w-[160px], mt-3.75 instead of mt-[15px], ring-3 instead of ring-[3px], top-1/2 instead of top-[50%])
Arbitrary values in Tailwind CSS are acceptable for: calc() expressions, CSS variable references, and non-standard values

Files:

  • src/components/stories/stories-table.tsx
  • src/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_SECRET as the key material

Files:

  • src/components/stories/stories-table.tsx
  • src/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.tsx
  • src/app/(dashboard)/repo/[owner]/[repo]/stories/[storyId]/page.tsx
**

⚙️ CodeRabbit configuration file

**: # MyBMAD Dashboard

Tailwind CSS

  • Uses Tailwind CSS v4 with @theme inline in src/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. 160pxw-40, 15pxmt-3.75, 2pxh-0.5)
    • Ring width: ring-3 not ring-[3px]
    • Percentages: fraction notation (top-1/2 not top-[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.css rather than as inline arbitrary values
  • shadcn UI components live in src/components/ui/ and are project-owned — they can and should follow these conventions

Error 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/errors to sanitize error messages before returning them to clients. Never expose error.message directly.

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/helpers for admin-only actions
  • Call revalidatePath() or revalidateTag() 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 use migrate dev in production)
  • After schema changes: pnpm prisma generate to regenerate the client

Testing

  • Framework: Vitest
  • Run tests: pnpm test
  • Watch mode: pnpm test:watch
    -...

Files:

  • src/components/stories/stories-table.tsx
  • src/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!

Comment on lines +139 to +141
const handleRowClick = (story: StoryDetail) => {
router.push(`${pathname}/${story.id}`);
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 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.

Suggested change
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}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 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/null

Repository: 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 onKeyDown pour 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant