BLoC/Cubit state management, ADHD-friendly theme (calming teal, no red), GetIt DI, GoRouter navigation. Screens: task dashboard, focus mode, task create/detail, streaks, time perception, settings, onboarding, auth. Custom widgets: TaskCard, RewardPopup, StreakRing, GentleNudgeCard. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
97 lines
3.4 KiB
Dart
97 lines
3.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import '../theme/app_colors.dart';
|
|
|
|
/// Re-engagement card shown when the user returns after an absence.
|
|
///
|
|
/// Design rules:
|
|
/// - Warm, welcoming message — "Welcome back! Your tasks missed you."
|
|
/// - Show previous streak info gently.
|
|
/// - "Let's start small" CTA.
|
|
/// - NO guilt, NO "you missed X days" in red.
|
|
class GentleNudgeCard extends StatelessWidget {
|
|
final int? previousStreak;
|
|
final VoidCallback? onStartSmall;
|
|
final VoidCallback? onDismiss;
|
|
|
|
const GentleNudgeCard({
|
|
super.key,
|
|
this.previousStreak,
|
|
this.onStartSmall,
|
|
this.onDismiss,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final theme = Theme.of(context);
|
|
|
|
return Card(
|
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
|
color: AppColors.primaryLight.withAlpha(40),
|
|
elevation: 0,
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(20),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// ── Header row ─────────────────────────────────────────
|
|
Row(
|
|
children: [
|
|
const Icon(Icons.waving_hand_rounded,
|
|
size: 28, color: AppColors.secondary),
|
|
const SizedBox(width: 10),
|
|
Expanded(
|
|
child: Text(
|
|
'Welcome back!',
|
|
style: theme.textTheme.titleLarge?.copyWith(
|
|
fontWeight: FontWeight.w700,
|
|
),
|
|
),
|
|
),
|
|
if (onDismiss != null)
|
|
IconButton(
|
|
icon: const Icon(Icons.close_rounded, size: 20),
|
|
onPressed: onDismiss,
|
|
style: IconButton.styleFrom(
|
|
minimumSize: const Size(36, 36),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 10),
|
|
|
|
// ── Body ───────────────────────────────────────────────
|
|
Text(
|
|
'Your tasks missed you. No pressure — let\'s ease back in.',
|
|
style: theme.textTheme.bodyLarge,
|
|
),
|
|
|
|
if (previousStreak != null && previousStreak! > 0) ...[
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
'You had a $previousStreak-day streak going. '
|
|
'That\'s still impressive — let\'s build on it.',
|
|
style: theme.textTheme.bodyMedium,
|
|
),
|
|
],
|
|
|
|
const SizedBox(height: 16),
|
|
|
|
// ── CTA ────────────────────────────────────────────────
|
|
FilledButton.icon(
|
|
onPressed: onStartSmall,
|
|
icon: const Icon(Icons.play_arrow_rounded),
|
|
label: const Text('Let\'s start small'),
|
|
style: FilledButton.styleFrom(
|
|
backgroundColor: AppColors.primary,
|
|
minimumSize: const Size(double.infinity, 52),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|