fix: apply review feedback — type safety, overdue logic, dead code

- _EmptyState: accept PetType enum directly; use .emoji getter
  (drops string conversion round-trip and duplicate emoji mapping)
- TaskCard: compute _isOverdue from task.deadline when task is provided
  (previously isOverdue never fired when using the task: param)
- userNameProvider: derive from userProvider.name instead of hardcoded 'Zuf'
  (name was split across two independent providers)
- _petMessage: add explicit 'neutral' branch, remove unreachable 'sleepy' branch
  (PetMood enum has no .sleepy; neutral was silently falling to _)
- EnergyBar/EnergyBadge: assert both params not null simultaneously
  (EnergyBar() / EnergyBadge() previously compiled silently with default low)
- todayTasksProvider: fix comment — no date filtering in MVP

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
TrochtaOndrej
2026-03-18 11:18:26 +01:00
parent 371e8260ac
commit adc2f72a6d
6 changed files with 22 additions and 16 deletions
@@ -47,7 +47,8 @@ class TasksNotifier extends Notifier<List<TaskEntity>> {
final tasksProvider =
NotifierProvider<TasksNotifier, List<TaskEntity>>(TasksNotifier.new);
/// Alias — today's tasks (same provider, filtered by status in screens).
/// Alias for [tasksProvider]. Returns all tasks — no date filtering in MVP.
/// Screens are responsible for splitting into pending/completed.
final todayTasksProvider = tasksProvider;
/// Pending tasks only, ordered by sort order.
@@ -1,4 +1,6 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
/// Provider for current user name.
final userNameProvider = Provider<String>((ref) => 'Zuf');
import 'pet_providers.dart';
/// Derived provider for the current user's display name.
final userNameProvider = Provider<String>((ref) => ref.watch(userProvider).name);
+6 -10
View File
@@ -6,6 +6,7 @@ import 'package:google_fonts/google_fonts.dart';
import '../../../core/router/routes.dart';
import '../../../core/theme/kittie_colors.dart';
import '../../../domain/entities/pet_type.dart';
import '../../../shared/utils/czech_date.dart';
import '../../../shared/widgets/energy_bar.dart';
import '../../../shared/widgets/pet_bubble.dart';
@@ -34,7 +35,7 @@ class TasksScreen extends ConsumerWidget {
return Scaffold(
body: SafeArea(
child: tasks.isEmpty
? _EmptyState(petType: userState.petType.name)
? _EmptyState(petType: userState.petType)
: SingleChildScrollView(
padding: const EdgeInsets.fromLTRB(20, 16, 20, 100),
child: Column(
@@ -157,26 +158,21 @@ class TasksScreen extends ConsumerWidget {
static String _petMessage(String mood, String petName) {
return switch (mood) {
'happy' => '$petName je stastna! Jde ti to skvele \u{1F44F}',
'neutral' => '$petName te ceka! Co dnes zvladneme? \u{2728}',
'sad' => '$petName te podporuje. Zkus jeden ukol \u{1F495}',
'sleepy' => '$petName odpociva... Klid je taky dulezity \u{1F4A4}',
_ => '$petName te ceka! Co dnes zvladneme? \u{2728}',
_ => '$petName je tady pro tebe \u{1F60A}',
};
}
}
class _EmptyState extends StatelessWidget {
final String petType;
final PetType petType;
const _EmptyState({required this.petType});
@override
Widget build(BuildContext context) {
final emoji = switch (petType) {
'dog' => '\u{1F436}',
'cat' => '\u{1F431}',
'capybara' => '\u{1F9AB}',
_ => '\u{1F431}',
};
final emoji = petType.emoji;
return Center(
child: Column(
+3 -1
View File
@@ -27,7 +27,9 @@ enum EnergyLevel {
/// - medium: orange bg, orange text, sun icon — "Stredni"
/// - high: red bg, red text, fire icon — "Narocne"
class EnergyBadge extends StatelessWidget {
const EnergyBadge({super.key, this.level, this.energyLevel});
const EnergyBadge({super.key, this.level, this.energyLevel})
: assert(level != null || energyLevel != null,
'Provide either level or energyLevel');
final EnergyLevel? level;
+2 -1
View File
@@ -15,7 +15,8 @@ class EnergyBar extends StatelessWidget {
this.fraction,
this.energyLevel,
this.label = 'ENERGIE',
});
}) : assert(fraction != null || energyLevel != null,
'Provide either fraction or energyLevel');
/// Fill amount from 0.0 (empty) to 1.0 (full).
final double? fraction;
+5 -1
View File
@@ -47,6 +47,10 @@ class TaskCard extends StatelessWidget {
int get _energyLevel => task?.energyLevel ?? energyLevel ?? 2;
bool get _isDone => task?.isCompleted ?? isDone;
bool get _isSelfCare => task?.isSelfCare ?? isSelfCare;
bool get _isOverdue {
if (task?.deadline != null) return task!.deadline!.isBefore(DateTime.now());
return isOverdue;
}
VoidCallback? get _toggleCallback => onComplete ?? onToggle;
@override
@@ -57,7 +61,7 @@ class TaskCard extends StatelessWidget {
constraints: const BoxConstraints(minHeight: AppConstants.minTouchTarget),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
decoration: BoxDecoration(
color: isOverdue
color: _isOverdue
? KittieColors.redLight
: KittieColors.creamDark,
borderRadius: BorderRadius.circular(AppConstants.cardBorderRadius),