mirror of
https://github.com/wger-project/flutter.git
synced 2026-02-18 00:17:48 +01:00
Also show the PR trophies in the regular log page
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of wger Workout Manager <https://github.com/wger-project>.
|
||||
* Copyright (c) 2020 - 2025 wger Team
|
||||
* Copyright (c) 2020 - 2026 wger Team
|
||||
*
|
||||
* wger Workout Manager is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
@@ -21,64 +21,45 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:wger/models/trophies/trophy.dart';
|
||||
import 'package:wger/providers/trophies.dart';
|
||||
import 'package:wger/screens/trophy_screen.dart';
|
||||
import 'package:wger/widgets/core/progress_indicator.dart';
|
||||
|
||||
class DashboardTrophiesWidget extends ConsumerWidget {
|
||||
const DashboardTrophiesWidget();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final provider = ref.watch(trophyStateProvider.notifier);
|
||||
final languageCode = Localizations.localeOf(context).languageCode;
|
||||
final trophiesState = ref.read(trophyStateProvider);
|
||||
|
||||
return FutureBuilder(
|
||||
future: provider.fetchUserTrophies(language: languageCode),
|
||||
builder: (context, asyncSnapshot) {
|
||||
if (asyncSnapshot.connectionState != ConnectionState.done) {
|
||||
return const Card(child: BoxedProgressIndicator());
|
||||
}
|
||||
return Card(
|
||||
color: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (trophiesState.nonPrTrophies.isEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text('No trophies yet', style: Theme.of(context).textTheme.bodyMedium),
|
||||
)
|
||||
else
|
||||
SizedBox(
|
||||
height: 140,
|
||||
child: ListView.separated(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: trophiesState.nonPrTrophies.length,
|
||||
separatorBuilder: (context, index) => const SizedBox(width: 12),
|
||||
itemBuilder: (context, index) {
|
||||
final userTrophy = trophiesState.nonPrTrophies[index];
|
||||
|
||||
final userTrophies = asyncSnapshot.data ?? [];
|
||||
|
||||
return Card(
|
||||
color: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// ListTile(
|
||||
// title: Text(
|
||||
// 'Trophies',
|
||||
// style: Theme.of(context).textTheme.headlineSmall,
|
||||
// ),
|
||||
// ),
|
||||
if (userTrophies.isEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text('No trophies yet', style: Theme.of(context).textTheme.bodyMedium),
|
||||
)
|
||||
else
|
||||
SizedBox(
|
||||
height: 140,
|
||||
child: ListView.separated(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: userTrophies.length,
|
||||
separatorBuilder: (context, index) => const SizedBox(width: 12),
|
||||
itemBuilder: (context, index) {
|
||||
final userTrophy = userTrophies[index];
|
||||
|
||||
return SizedBox(
|
||||
width: 220,
|
||||
child: TrophyCard(trophy: userTrophy.trophy),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
return SizedBox(
|
||||
width: 220,
|
||||
child: TrophyCard(trophy: userTrophy.trophy),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of wger Workout Manager <https://github.com/wger-project>.
|
||||
* Copyright (c) 2020 - 2025 wger Team
|
||||
* Copyright (c) 2020 - 2026 wger Team
|
||||
*
|
||||
* wger Workout Manager is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of wger Workout Manager <https://github.com/wger-project>.
|
||||
* Copyright (c) 2020 - 2025 wger Team
|
||||
* Copyright (c) 2020 - 2026 wger Team
|
||||
*
|
||||
* wger Workout Manager is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
@@ -49,7 +49,6 @@ class WorkoutSummary extends ConsumerStatefulWidget {
|
||||
class _WorkoutSummaryState extends ConsumerState<WorkoutSummary> {
|
||||
late Future<void> _initData;
|
||||
late Routine _routine;
|
||||
late List<UserTrophy> _userPrTrophies;
|
||||
bool _didInit = false;
|
||||
|
||||
@override
|
||||
@@ -76,11 +75,13 @@ class _WorkoutSummaryState extends ConsumerState<WorkoutSummary> {
|
||||
);
|
||||
|
||||
final trophyNotifier = ref.read(trophyStateProvider.notifier);
|
||||
_userPrTrophies = await trophyNotifier.fetchUserPRTrophies(language: languageCode);
|
||||
await trophyNotifier.fetchUserTrophies(language: languageCode);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final trophyState = ref.watch(trophyStateProvider);
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
NavigationHeader(
|
||||
@@ -102,10 +103,8 @@ class _WorkoutSummaryState extends ConsumerState<WorkoutSummary> {
|
||||
final apiSession = _routine.sessions.firstWhereOrNull(
|
||||
(s) => s.session.date.isSameDayAs(clock.now()),
|
||||
);
|
||||
final userTrophies = _userPrTrophies
|
||||
.where(
|
||||
(t) => t.contextData!.sessionId == apiSession?.session.id,
|
||||
)
|
||||
final userTrophies = trophyState.prTrophies
|
||||
.where((t) => t.contextData?.sessionId == apiSession?.session.id)
|
||||
.toList();
|
||||
|
||||
return WorkoutSessionStats(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of wger Workout Manager <https://github.com/wger-project>.
|
||||
* Copyright (c) 2020, 2025 wger Team
|
||||
* Copyright (c) 2020 - 2026 wger Team
|
||||
*
|
||||
* wger Workout Manager is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
@@ -17,33 +17,59 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:wger/helpers/date.dart';
|
||||
import 'package:wger/helpers/errors.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/workouts/routine.dart';
|
||||
import 'package:wger/providers/trophies.dart';
|
||||
|
||||
import '../gym_mode/summary.dart';
|
||||
import 'exercise_log_chart.dart';
|
||||
import 'muscle_groups.dart';
|
||||
import 'session_info.dart';
|
||||
|
||||
class DayLogWidget extends StatelessWidget {
|
||||
class DayLogWidget extends ConsumerWidget {
|
||||
final DateTime _date;
|
||||
final Routine _routine;
|
||||
final _logger = Logger('DayLogWidget');
|
||||
|
||||
const DayLogWidget(this._date, this._routine);
|
||||
DayLogWidget(this._date, this._routine);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final i18n = AppLocalizations.of(context);
|
||||
final theme = Theme.of(context);
|
||||
|
||||
final trophyState = ref.read(trophyStateProvider);
|
||||
|
||||
final sessionApi = _routine.sessions.firstWhere(
|
||||
(sessionApi) => sessionApi.session.date.isSameDayAs(_date),
|
||||
);
|
||||
final exercises = sessionApi.exercises;
|
||||
|
||||
final prTrophies = trophyState.prTrophies
|
||||
.where((t) => t.contextData?.sessionId == sessionApi.session.id)
|
||||
.toList();
|
||||
|
||||
_logger.info(trophyState.prTrophies);
|
||||
_logger.info(prTrophies);
|
||||
|
||||
return Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Card(child: SessionInfo(sessionApi.session)),
|
||||
if (prTrophies.isNotEmpty)
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: InfoCard(
|
||||
title: i18n.personalRecords,
|
||||
value: prTrophies.length.toString(),
|
||||
color: theme.colorScheme.tertiaryContainer,
|
||||
),
|
||||
),
|
||||
MuscleGroupsCard(sessionApi.logs),
|
||||
|
||||
Column(
|
||||
spacing: 10,
|
||||
children: [
|
||||
@@ -66,7 +92,17 @@ class DayLogWidget extends StatelessWidget {
|
||||
(log) => Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(log.repTextNoNl(context)),
|
||||
Row(
|
||||
children: [
|
||||
if (prTrophies.any((t) => t.contextData?.logId == log.id))
|
||||
Icon(
|
||||
Icons.emoji_events,
|
||||
color: theme.colorScheme.primary,
|
||||
size: 20,
|
||||
),
|
||||
Text(log.repTextNoNl(context)),
|
||||
],
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.delete),
|
||||
key: ValueKey('delete-log-${log.id}'),
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/*
|
||||
* This file is part of wger Workout Manager <https://github.com/wger-project>.
|
||||
* Copyright (C) 2020, 2025 wger Team
|
||||
* Copyright (c) 2026 wger Team
|
||||
*
|
||||
* wger Workout Manager is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wger Workout Manager is distributed in the hope that it will be useful,
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
@@ -18,20 +18,26 @@
|
||||
|
||||
import 'package:clock/clock.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:table_calendar/table_calendar.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/workouts/routine.dart';
|
||||
import 'package:wger/providers/trophies.dart';
|
||||
import 'package:wger/theme/theme.dart';
|
||||
import 'package:wger/widgets/routines/logs/day_logs_container.dart';
|
||||
|
||||
class WorkoutLogs extends StatelessWidget {
|
||||
class WorkoutLogs extends ConsumerWidget {
|
||||
final Routine _routine;
|
||||
|
||||
const WorkoutLogs(this._routine);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final languageCode = Localizations.localeOf(context).languageCode;
|
||||
final trophyNotifier = ref.read(trophyStateProvider.notifier);
|
||||
trophyNotifier.fetchUserTrophies(language: languageCode);
|
||||
|
||||
return ListView(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 8),
|
||||
children: [
|
||||
|
||||
@@ -21,15 +21,13 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:wger/helpers/material.dart';
|
||||
import 'package:wger/models/trophies/user_trophy_progression.dart';
|
||||
import 'package:wger/providers/trophies.dart';
|
||||
import 'package:wger/widgets/core/progress_indicator.dart';
|
||||
|
||||
class TrophiesOverview extends ConsumerWidget {
|
||||
const TrophiesOverview({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final notifier = ref.watch(trophyStateProvider.notifier);
|
||||
final languageCode = Localizations.localeOf(context).languageCode;
|
||||
final trophyState = ref.watch(trophyStateProvider);
|
||||
|
||||
// Responsive grid: determine columns based on screen width
|
||||
final width = MediaQuery.widthOf(context);
|
||||
@@ -44,52 +42,32 @@ class TrophiesOverview extends ConsumerWidget {
|
||||
crossAxisCount = 5;
|
||||
}
|
||||
|
||||
return FutureBuilder<List<UserTrophyProgression>>(
|
||||
future: notifier.fetchTrophyProgression(language: languageCode),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState != ConnectionState.done) {
|
||||
return const Card(child: BoxedProgressIndicator());
|
||||
}
|
||||
|
||||
if (snapshot.hasError) {
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text('Error loading trophies', style: Theme.of(context).textTheme.bodyLarge),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final userTrophyProgression = snapshot.data ?? [];
|
||||
|
||||
// If empty, show placeholder
|
||||
if (userTrophyProgression.isEmpty) {
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
'No trophies yet',
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return RepaintBoundary(
|
||||
child: GridView.builder(
|
||||
padding: const EdgeInsets.all(12),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: crossAxisCount,
|
||||
),
|
||||
key: const ValueKey('trophy-grid'),
|
||||
itemCount: userTrophyProgression.length,
|
||||
itemBuilder: (context, index) {
|
||||
return _TrophyCardImage(userProgression: userTrophyProgression[index]);
|
||||
},
|
||||
// If empty, show placeholder
|
||||
if (trophyState.trophyProgression.isEmpty) {
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
'No trophies yet',
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return RepaintBoundary(
|
||||
child: GridView.builder(
|
||||
padding: const EdgeInsets.all(12),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: crossAxisCount,
|
||||
),
|
||||
key: const ValueKey('trophy-grid'),
|
||||
itemCount: trophyState.trophyProgression.length,
|
||||
itemBuilder: (context, index) {
|
||||
return _TrophyCardImage(userProgression: trophyState.trophyProgression[index]);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user