Skip to content

COMPONENT: ReportCard Component #53

Description

@nayan458

Task: ReportCard Component

Type: Component
Milestone: M0.5 — Shared Component Library
Estimate: M

Change Log

Updated: Now explicitly composes ListCard (not base Card directly). ListCard ticket must be completed before this one starts. Claimed state and deriveAvailableActions logic documented explicitly.

Component Type

  • Feature component (may use hooks)

Props Interface

interface ReportCardProps {
  report:          Report;
  isExpanded:      boolean;
  onToggleExpand:  () => void;
  onAction:        (reportId: string, action: ModerationAction) => void;
  isClaimed?:      boolean;
  claimedBy?:      string;
}

Internal Logic — deriveAvailableActions(report)

This function is the only place that decides which action buttons render. Maps directly to the Java backend state machine validateTransition().

Button Condition
Run AI screening status === 'PENDING' && aiConfidenceScore === 0
Remove content (status === 'PENDING' or 'ESCALATED') && targetType !== 'USER'
Ban author status === 'ESCALATED_TO_HUMAN'
Warn author status === 'PENDING' or 'ESCALATED_TO_HUMAN'
Dismiss status === 'PENDING' or 'ESCALATED_TO_HUMAN'
No buttons isClaimed === true — shows lock message instead

Variants / States

State Description
Collapsed Header row only — id, badges, title, AI score bar
Pending unscreened Expanded — "Run AI screening" button only
Pending screened Expanded — Remove + Warn + Dismiss
Escalated Expanded — all buttons including Ban author
Claimed Expanded — no buttons, shows "🔒 Being reviewed by {claimedBy}"
Resolved / Dismissed Expanded — read only, no action buttons

Acceptance Criteria

  • Composes ListCard — zero layout or expand logic duplicated here
  • deriveAvailableActions() is a pure function, unit tested independently
  • Correct buttons render for every status — verified via Storybook stories
  • onAction fires with correct (reportId, ModerationAction) — card does not execute the action itself
  • e.stopPropagation() on button clicks handled by ListCard footer — verify this works before closing
  • AI score bar uses ProgressBar shared component — not a raw div
  • Status badges use Badge shared component
  • Action buttons use Button shared component
  • Pipeline stepper uses StatusPipeline sub-component (private to this file unless reused)
  • Audit trail renders all entries with formatted timestamps
  • Zero hardcoded hex values
  • Storybook stories: one per state listed above + dark theme
  • Unit tested: deriveAvailableActions for all 6 statuses
  • No TypeScript errors

Notes

  • ListCard must be merged and signed off before this ticket starts
  • StatusPipeline and AuditTrail are sub-components private to this file — extract only if another feature needs them
  • deriveAvailableActions must be updated here if the backend state machine adds new valid transitions — single point of change

Activity

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

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requesttype: componentA reusable UI component (design system or feature-specific)

Type

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions