Skip to content

feat(session): add Community Dispute Appeal Form UI (#338)#381

Merged
Luluameh merged 1 commit into
LightForgeHub:mainfrom
Biokes:feat/dispute-appeal-form-ui-338
Jun 30, 2026
Merged

feat(session): add Community Dispute Appeal Form UI (#338)#381
Luluameh merged 1 commit into
LightForgeHub:mainfrom
Biokes:feat/dispute-appeal-form-ui-338

Conversation

@Biokes

@Biokes Biokes commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

feat(session): Community Dispute Appeal Form UI

Summary

Implements the appeal submission screen for contested dispute decisions, as specified in issue #338.

New component - src/components/session/AppealForm.tsx

  • AppealForm - inline card variant, conditionally rendered only when a session has a resolved dispute
  • AppealFormModal - modal wrapper for triggering the form as an overlay

Types - utils/types/types.ts

  • Added Dispute, DisputeEvidence, DisputeVerdict, and AppealFormData interfaces

Integration - src/app/session/[id]/page.tsx

  • "Appeal Dispute Decision" button appears in the session sidebar only when sessionDispute?.status === "resolved"
  • AppealFormModal is mounted conditionally on the same guard

What the form includes

  • Verdict summary banner showing the original decision and verdict note
  • Community jury info callout
  • Grounds for appeal textarea (minimum 30 characters, with live character counter)
  • New evidence description textarea
  • Drag-and-drop + click-to-browse file upload (PDF, PNG, JPG, WEBP, TXT - up to 5 files, 10 MB each)
  • File chip list with individual removal
  • Three-step flow: form -> confirm -> success with appeal ID on completion
  • Full keyboard accessibility (focus trap in modal, ARIA labels, roles)

Acceptance Criteria

  • Visible only on disputed sessions where a decision has been made (dispute.status === "resolved")
  • Form inputs to submit new text descriptions and upload supporting documents

Tested

Manual review of component logic and TypeScript types. Pre-existing tsconfig-level type errors in the repo are unrelated to this change.

Closes #338

Summary by CodeRabbit

  • New Features

    • Added an appeal flow for resolved disputes directly in the session page.
    • Users can now open a dispute appeal modal, submit appeal grounds, and attach supporting evidence files.
    • Added multi-step appeal submission with confirmation and success states.
  • Bug Fixes

    • The appeal option now appears only when a dispute is resolved, reducing accidental access to the form.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds shared Dispute, DisputeVerdict, DisputeEvidence, and AppealFormData types, then implements a new AppealForm client component with a three-step flow (form → confirm → success), file attachment support, and an AppealFormModal wrapper. The session page is updated to render an appeal button and mount the modal when a resolved dispute exists.

Dispute Appeal UI

Layer / File(s) Summary
Dispute and appeal type definitions
utils/types/types.ts
Adds DisputeVerdict union, DisputeEvidence, Dispute (with status union and optional verdict fields), and AppealFormData (grounds, evidence description, file attachments).
AppealForm component
src/components/session/AppealForm.tsx
Defines attachment constraints and verdict display helpers, implements FileChip, multi-step form state/validation/drag-drop/submission logic, all step UIs (form, confirm, success), and the AppealFormModal wrapper.
Session page integration
src/app/session/[id]/page.tsx
Imports AppealFormModal and Dispute, adds MOCK_DISPUTE constant, showAppealModal state, conditionally renders the "Appeal Dispute Decision" button for resolved disputes, and mounts AppealFormModal.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 A gavel falls, the verdict's set,
But bunnies aren't done hopping yet!
New grounds, new files, a three-step way,
To appeal the ruling of the day.
With drag-and-drop and confirm too,
Justice hops along anew! ⚖️

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding the Community Dispute Appeal Form UI for session pages.
Linked Issues check ✅ Passed The PR satisfies #338 by showing the appeal UI only for resolved disputes and providing text and document upload inputs.
Out of Scope Changes check ✅ Passed The changes stay focused on the appeal form, its types, and session-page integration without obvious unrelated additions.
✨ 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: 4

🤖 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/app/session/`[id]/page.tsx:
- Around line 54-65: Update the session page logic so the dispute mock is only
attached to the matching active session instead of always using MOCK_DISPUTE. In
the session page component that defines MOCK_DISPUTE and computes
sessionDispute, gate the assignment by the current route/session id (and apply
the same fix to the duplicated logic in the other referenced block) so
non-matching sessions do not expose the appeal entry point. Use the existing
session id lookup in the page component to scope the dispute correctly.
- Around line 363-368: The appeal modal is being closed too early in the session
page flow, which prevents the new success step from rendering. Update the
`AppealFormModal` usage in `page.tsx` so `onAppealSubmitted` no longer calls
`setShowAppealModal(false)`; let `AppealForm.handleSubmit()` advance to the
success state first, and only close the modal from the user’s explicit close
action or after the success screen is dismissed.

In `@src/components/session/AppealForm.tsx`:
- Line 12: Remove the unused Trash2 import from AppealForm to satisfy linting
and avoid CI failures. Update the import list in the AppealForm component so
only actually referenced symbols remain; this is a simple cleanup with no
behavior change.
- Around line 326-333: The custom upload trigger in AppealForm should support
keyboard activation with both Enter and Space since it uses role="button".
Update the onKeyDown handler on the upload div so it also opens the file picker
when Space is pressed, while keeping the existing click behavior and
fileInputRef.current?.click() usage intact.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: f2851a70-a45e-4146-9dbd-a85f93e6d974

📥 Commits

Reviewing files that changed from the base of the PR and between 9781272 and 575ae09.

📒 Files selected for processing (3)
  • src/app/session/[id]/page.tsx
  • src/components/session/AppealForm.tsx
  • utils/types/types.ts

Comment thread src/app/session/[id]/page.tsx
Comment thread src/app/session/[id]/page.tsx
Info,
Paperclip,
SendHorizonal,
Trash2,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the unused Trash2 import.

ESLint already flags this, and it will keep the file noisy or CI red if lint is enforced.

🧰 Tools
🪛 ESLint

[error] 12-12: 'Trash2' is defined but never used.

(@typescript-eslint/no-unused-vars)

🤖 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/session/AppealForm.tsx` at line 12, Remove the unused Trash2
import from AppealForm to satisfy linting and avoid CI failures. Update the
import list in the AppealForm component so only actually referenced symbols
remain; this is a simple cleanup with no behavior change.

Source: Linters/SAST tools

Comment thread src/components/session/AppealForm.tsx
@Luluameh Luluameh merged commit 2c783c4 into LightForgeHub:main Jun 30, 2026
1 check passed
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.

Community Dispute Appeal Form UI

2 participants