Skip to content

feat(badges): Add volunteer badge system with 9 achievement levels

Suma Pullaiahgari requested to merge ehrs-badges into develop

Overview

This MR adds a comprehensive volunteer badge system to recognize and reward volunteers for their attendance at medical camps. The system includes 9 progressive achievement levels with visual badges, progress tracking, and real-time updates.

What does this MR do and why?

Motivation: Volunteers needed a gamification system to encourage consistent attendance and recognize their contributions to medical camps. The badge system provides visual feedback and motivation through progressive achievements.

Approach:

  • Implemented a complete badge UI system with React components
  • Added 9 custom SVG badge designs for different achievement levels
  • Integrated badge display into user profiles with real-time updates
  • Created comprehensive test coverage (49 tests) for all badge components
  • Added badge evaluation API integration for coordinators/admins

Trade-offs:

  • Badge SVG assets increase bundle size slightly (~50KB total)
  • Real-time badge updates require query invalidation after attendance marking
  • Badge evaluation is manual for coordinators (could be automated in future)

Changes Made

New Components

  • src/components/badges/BadgeSection.tsx - Main collapsible badge container
  • src/components/badges/BadgeGrid.tsx - Grid layout with earned/locked badges
  • src/components/badges/BadgeCard.tsx - Individual badge display with progress
  • src/components/badges/BadgeIcon.tsx - SVG badge icon renderer

Badge Assets (9 SVG files)

  • src/assets/badges/badge-1-first-step.svg
  • src/assets/badges/badge-2-certified-volunteer.svg
  • src/assets/badges/badge-3-consistent-volunteer.svg
  • src/assets/badges/badge-4-on-a-roll.svg
  • src/assets/badges/badge-5-century-contributor.svg
  • src/assets/badges/badge-6-bronze-volunteer.svg
  • src/assets/badges/badge-7-silver-volunteer.svg
  • src/assets/badges/badge-8-gold-volunteer.svg
  • src/assets/badges/badge-9-elite-volunteer.svg

API Integration

  • Added 5 new badge API functions in src/lib/api.ts:
    • getMyBadges() - Fetch own badges
    • getMyBadgeProgress() - Fetch own progress
    • getUserBadges(userId) - Fetch user badges (coordinator/admin)
    • getUserBadgeProgress(userId) - Fetch user progress
    • evaluateUserBadges(userId) - Trigger badge evaluation

Type Definitions

  • Added badge types in src/types/api.ts:
    • Badge - Earned badge structure
    • BadgeResponse - API response for badges
    • BadgeProgressItem - Progress tracking
    • BadgeProgressResponse - API response for progress
    • BadgeEvaluationResponse - Evaluation result

Integration Points

  • src/pages/profile/ProfilePage.tsx - Added BadgeSection to profiles
  • src/pages/admin/StaffAttendancePage.tsx - Added badge query invalidation

Test Coverage

  • tests/unit/components/badges/BadgeSection.test.tsx (14 tests)
  • tests/unit/components/badges/BadgeGrid.test.tsx (19 tests)
  • tests/unit/components/badges/BadgeCard.test.tsx (10 tests)
  • tests/unit/components/badges/BadgeIcon.test.tsx (6 tests)
  • Total: 49 tests, 100% statement coverage

Technical Details

Badge Progression System

First Step (1 visit) → Certified Volunteer (3) → Consistent Volunteer (5)
→ On a Roll (3 consecutive) → Bronze (6) → Century Contributor (10)
→ Silver (12) → Gold (20) → Elite (36)

Architecture Decisions

  1. Component Structure: Separated concerns into 4 components for reusability and testability
  2. State Management: Uses React Query for caching and automatic invalidation
  3. Badge Icons: SVG assets loaded via Vite's ?url import for optimal bundling
  4. Progress Tracking: Real-time progress bars with percentage calculations
  5. Permissions: Role-based evaluate button visibility (coordinator/admin only)

Data Flow

  1. User attends camp → Attendance marked
  2. Query invalidation triggers badge refetch
  3. BadgeSection fetches badges + progress from API
  4. BadgeGrid maps data to thresholdOrder for consistent display
  5. BadgeCard renders individual badges with locked/unlocked states

Type of Change

  • New feature (non-breaking change that adds functionality)
  • 🎨 UI/UX improvement
  • 🧪 Test update

Related Issues / References

  • Implements volunteer gamification feature
  • Related to attendance tracking system

Screenshots or Screen Recordings

before image after image

Badge Display Features

  • Collapsible badge section on profile pages
  • Visual distinction between earned (colored) and locked (grayscale) badges
  • Progress bars showing completion percentage
  • "Show more/less" toggle for locked badges
  • Earned date display for unlocked badges
  • Manual evaluation button for coordinators/admins

How to Set Up and Validate Locally

  1. Pull this branch:

    git checkout feat/volunteer-badges
  2. Install dependencies (if needed):

    bun install
  3. Run development server:

    bun dev
  4. Test badge display:

    • Navigate to your profile: http://localhost:5173/profile
    • Click on "Volunteer Badges" section to expand
    • Verify earned badges show in color with dates
    • Verify locked badges show in grayscale with progress
  5. Test badge evaluation (coordinator/admin only):

    • Navigate to another user's profile
    • Click "Evaluate" button in badge section
    • Verify success toast appears
    • Verify badges refresh automatically
  6. Test attendance integration:

    • Mark attendance at a camp
    • Navigate to profile
    • Verify badge progress updates
    • Check if new badges are unlocked

Testing Done

  • Manual testing completed
  • Unit tests added/updated

Test Cases Covered:

Scenario Expected Result Status
Display earned badges Shows colored badges with dates
Display locked badges Shows grayscale badges with progress
Progress calculation Correct percentage and remaining visits
Expand/collapse section Toggles badge visibility
Evaluate badges (admin) Triggers evaluation and refreshes
Badge query invalidation Updates after attendance marking
Show more/less toggle Expands/collapses locked badges
Empty state Shows default locked badges
API error handling Shows error toast
Permission-based UI Evaluate button only for coordinators

Test Coverage:

  • BadgeSection: 100% statements, 100% branches, 100% functions
  • BadgeGrid: 100% statements, 92.59% branches, 100% functions
  • BadgeCard: 100% statements, 100% branches, 100% functions
  • BadgeIcon: 100% statements, 100% branches, 100% functions

Code Quality Checklist

Code Standards

  • Code follows project conventions (naming, structure, formatting)
  • No console.log() or debugger statements left in code
  • No unused imports, variables, or functions
  • No duplicate code and use of existing components for reusability
  • i18n check passed with no hardcoded strings in codebase for i18n support
  • TypeScript types are properly defined (no any unless justified)
  • ESLint and Prettier checks pass

React Best Practices

  • Components are properly split and single-responsibility
  • Hooks follow rules (no conditional hooks, proper dependencies)
  • State management is appropriate (local vs global state)
  • No unnecessary re-renders (memoization used where needed)
  • Event handlers are properly cleaned up

Component Patterns

  • shadcn/ui components used correctly (Card, Button)
  • Tailwind classes follow utility-first approach
  • Responsive design considered (mobile-first with sm: breakpoints)
  • Accessibility attributes included (aria-labels, roles)
  • Icons from lucide-react used consistently (Award, Lock, CheckCircle, etc.)

API & Data Fetching

  • TanStack Query used for server state
  • Loading and error states handled
  • API types defined in src/types/api.ts
  • Axios interceptors handle auth tokens correctly
  • Query invalidation on attendance marking

Error Handling

  • Errors are caught and handled gracefully
  • User-friendly error messages displayed
  • Errors are being toasted properly (sonner)
  • Network failures handled appropriately

Documentation

  • CHANGELOG.md updated
  • BADGE_FEATURE_VERIFICATION.md created with complete workflow analysis
  • Test documentation included

Known Limitations / Technical Debt

  1. Badge Evaluation: Currently manual for coordinators. Could be automated on attendance marking in future.
  2. Badge Assets: SVG files add ~50KB to bundle. Could optimize with sprite sheets if needed.
  3. Consecutive Tracking: "On a Roll" badge requires backend to track consecutive visits accurately.
  4. Real-time Updates: Relies on query invalidation. Could use WebSocket for instant updates.

Additional Notes

Design Decisions

  • 9 Badge Levels: Balanced progression from 1 to 36 visits
  • Collapsible UI: Saves space on profile pages
  • Grayscale Locked Badges: Clear visual distinction between earned/locked
  • Progress Bars: Motivate users to reach next milestone
  • Manual Evaluation: Gives coordinators control over badge awarding

Future Enhancements

  • Notification when new badge is earned
  • Badge sharing on social media
  • Leaderboard showing top volunteers
  • Animated badge unlock transitions
  • Badge details modal with achievement history

Dependencies

  • No new npm packages added
  • Uses existing lucide-react icons
  • Leverages shadcn/ui Card and Button components
  • Compatible with current TanStack Query setup

MR Acceptance Checklist

  • Code quality standards met
  • Tests provide adequate coverage (100% statements)
  • Documentation is complete
  • No breaking changes introduced
  • Performance impact is minimal
  • Security considerations addressed (role-based permissions)
  • Accessibility requirements met
Edited by Suma Pullaiahgari

Merge request reports

Loading