Mobile
Dashboard Improvements

Dashboard Improvements

Recent enhancements to the mobile app dashboard provide students with richer insights into their wellbeing trends over time.

Overview

The dashboard now features swipeable score cards showing current scores, 7-day trends, and 30-day trends, inspired by Apple Health's visualization approach.

Key Features

Swipeable Score Cards

Current Score Card

  • Displays latest Mind Measure score
  • Color-coded by wellbeing band (Green/Blue/Yellow/Red)
  • Shows mood score and check-in date
  • Baseline score displayed for comparison

7-Day View Card

  • Bar chart showing scores for last 7 days
  • Baseline reference line
  • Dynamic day labels (relative to current day)
  • Check-in counter showing participation
  • Encouragement message if few check-ins
  • Bars grow from baseline to show improvement/decline

30-Day View Card

  • Bar chart showing scores for last 30 days
  • Average score display
  • Check-in counter for the month
  • Day numbers (1-31) based on actual dates
  • Minimum 5 check-ins required for meaningful average

Visualization Design

Apple Health Inspiration

  • Prominent, solid bars
  • Clear baseline reference
  • Bars grow from bottom upwards
  • Strong contrast with white bars on colored backgrounds
  • Minimal, focused data display

Color-Coded Backgrounds

  • Green (80-100): Excellent wellbeing
  • Blue (60-79): Good wellbeing
  • Amber (40-59): Moderate concerns
  • Red (0-39): Concerning patterns

User Interface Components

SwipeableScoreCard Component

Main container handling swipe gestures and card transitions.

interface SwipeableScoreCardProps {
  latestScore: number | null;
  latestSession: SessionData | null;
  baselineScore: number | null;
  trendData: {
    last7CheckIns: Array<{score: number, date: string}>;
    last30Days: Array<{score: number, date: string}>;
  };
  userCreatedAt: string;
}

Features:

  • Framer Motion animations
  • Touch-friendly swipe gestures
  • Pagination dots for navigation
  • Conditional view display based on account age

CurrentScoreCard Component

Displays the user's most recent wellbeing score.

Key Elements:

  • Large score display (0-100)
  • Status badge (Excellent/Good/Moderate/Concerning)
  • Mood score indicator
  • Last check-in date
  • Baseline comparison indicator

SevenDayViewCard Component

Shows bar chart for the last 7 days of check-ins.

Key Elements:

  • "SEVEN DAY VIEW" title
  • Average score display top-left
  • Check-in counter
  • Baseline score label with horizontal line
  • 7 vertical bars (one per day)
  • Dynamic day labels (S M T W T F S)
  • Y-axis: 0, 50, 100
  • Encouragement message for low participation

Data Handling:

  • Only actual check-in scores shown
  • Days without check-ins show minimal 2px bar
  • Bar heights relative to score (0-100 scale)
  • Baseline line spans full width

ThirtyDayViewCard Component

Shows bar chart for the last 30 days of check-ins.

Key Elements:

  • "THIRTY DAY VIEW" title
  • Average score display
  • Check-in counter
  • Baseline score label with horizontal line
  • 30 vertical bars (one per day)
  • Day numbers (1-31) based on dates
  • Y-axis: 0, 50, 100

Minimum Check-in Logic:

  • If < 5 check-ins in 30 days: Show average with message
  • Message: "you have only checked in X times in the last 30 days, try checking in more often to measure and monitor your mood."

Technical Implementation

Data Preparation

7-Day Data:

const prepare7DayData = (sessions: SessionData[], baselineScore: number) => {
  const last7Days = getLast7Days();
  return last7Days.map(date => {
    const session = sessions.find(s => 
      isSameDay(new Date(s.created_at), date)
    );
    return {
      date,
      score: session?.final_score || null,
      hasCheckIn: !!session
    };
  });
};

30-Day Data:

const prepare30DayData = (sessions: SessionData[], baselineScore: number) => {
  const last30Days = getLast30Days();
  return last30Days.map(date => {
    const session = sessions.find(s => 
      isSameDay(new Date(s.created_at), date)
    );
    return {
      date,
      score: session?.final_score || null,
      hasCheckIn: !!session
    };
  });
};

Dynamic Day Labels

Day labels adjust based on the current day of the week:

const getDayLabels = () => {
  const today = new Date();
  const dayIndex = today.getDay(); // 0 = Sunday, 6 = Saturday
  const days = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
  
  // Rotate array so today is last
  return [
    ...days.slice(dayIndex + 1),
    ...days.slice(0, dayIndex + 1)
  ];
};

Color-Coded Backgrounds

Backgrounds change based on score ranges:

const getBackgroundGradient = (score: number) => {
  if (score >= 80) return 'linear-gradient(135deg, #10B981, #059669)'; // Green
  if (score >= 60) return 'linear-gradient(135deg, #3B82F6, #2563EB)'; // Blue
  if (score >= 40) return 'linear-gradient(135deg, #F59E0B, #D97706)'; // Amber
  return 'linear-gradient(135deg, #EF4444, #DC2626)'; // Red
};

Data Flow

Dashboard Data Hook

// useDashboardData.ts
const fetchDashboardData = async () => {
  // Fetch user profile with baseline
  const profile = await fetchProfile(userId);
  
  // Fetch all assessment sessions
  const sessions = await fetchSessions(userId);
  
  // Calculate trend data
  const trendData = calculateTrendData(sessions);
  
  return {
    profile: {
      ...profile,
      baselineScore: profile.baseline_score,
      createdAt: profile.created_at
    },
    latestScore: sessions[0]?.final_score || null,
    latestSession: sessions[0] || null,
    trendData
  };
};

Conditional View Display

Views only shown when account age permits:

const canShow7DayView = () => {
  const accountAge = Date.now() - new Date(userCreatedAt).getTime();
  return accountAge >= 7 * 24 * 60 * 60 * 1000; // 7 days in ms
};
 
const canShow30DayView = () => {
  const accountAge = Date.now() - new Date(userCreatedAt).getTime();
  return accountAge >= 30 * 24 * 60 * 60 * 1000; // 30 days in ms
};

User Experience

Swipe Gestures

  • Swipe left/right to navigate between cards
  • Smooth Framer Motion transitions
  • Pagination dots indicate current position
  • Dots are clickable for direct navigation

Visual Feedback

  • Active dot highlighted in purple
  • Inactive dots in white/transparent
  • Smooth animations between views
  • Loading states during data fetch

Encouragement Messages

7-Day View:

  • If < 3 check-ins: "you have checked in X times in the last seven days, try checking in more regularly for better monitoring"

30-Day View:

  • If < 5 check-ins: "you have only checked in X times in the last 30 days, try checking in more often to measure and monitor your mood."

Design Decisions

Why Apple Health Style?

  • Familiar pattern for users
  • Clear visual communication
  • Minimal, focused design
  • Proven effective for health data

Why Baseline Reference?

  • Shows progress over time
  • Contextualizes daily variations
  • Highlights improvements or concerns
  • Personalizes the experience

Why Dynamic Day Labels?

  • Always shows "today" as the last day
  • More intuitive than fixed calendar
  • Easier to understand recent patterns
  • Matches user's mental model

Why Minimum Check-in Thresholds?

  • Ensures data quality
  • Prevents misleading averages
  • Encourages regular participation
  • Provides actionable feedback

Related Documentation


Status: Complete and deployed
Last Updated: January 5, 2026
Components: SwipeableScoreCard, CurrentScoreCard, SevenDayViewCard, ThirtyDayViewCard