Skip to content

Commit

Permalink
feat: TeamMatchBouts of membership
Browse files Browse the repository at this point in the history
  • Loading branch information
Gustl22 committed Oct 6, 2024
1 parent 7c53d37 commit 34228e5
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 25 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:wrestling_scoreboard_client/localization/bout_utils.dart';
import 'package:wrestling_scoreboard_client/localization/date_time.dart';
import 'package:wrestling_scoreboard_client/localization/wrestling_style.dart';
import 'package:wrestling_scoreboard_client/provider/network_provider.dart';
import 'package:wrestling_scoreboard_client/view/screens/edit/membership_edit.dart';
import 'package:wrestling_scoreboard_client/view/screens/overview/person_overview.dart';
import 'package:wrestling_scoreboard_client/view/screens/overview/team_match/team_match_bout_overview.dart';
import 'package:wrestling_scoreboard_client/view/screens/overview/team_match/team_match_overview.dart';
import 'package:wrestling_scoreboard_client/view/widgets/consumer.dart';
import 'package:wrestling_scoreboard_client/view/widgets/font.dart';
import 'package:wrestling_scoreboard_client/view/widgets/grouped_list.dart';
import 'package:wrestling_scoreboard_common/common.dart';

Expand All @@ -23,31 +30,80 @@ class MembershipOverview extends AbstractPersonOverview {
id: id,
initialData: membership,
builder: (context, membership) {
return buildOverview(
context,
ref,
dataId: membership.person.id!,
initialData: membership.person,
classLocale: localizations.membership,
editPage: MembershipEdit(
membership: membership,
initialClub: membership.club,
),
onDelete: () async => (await ref.read(dataManagerNotifierProvider)).deleteSingle<Membership>(membership),
tiles: [
ContentItem(
title: membership.no ?? '-',
subtitle: localizations.membershipNumber,
icon: Icons.tag,
return buildOverview(context, ref,
dataId: membership.person.id!,
initialData: membership.person,
classLocale: localizations.membership,
editPage: MembershipEdit(
membership: membership,
initialClub: membership.club,
),
ContentItem(
title: membership.club.name,
subtitle: localizations.club,
icon: Icons.foundation,
)
],
);
onDelete: () async => (await ref.read(dataManagerNotifierProvider)).deleteSingle<Membership>(membership),
tiles: [
ContentItem(
title: membership.no ?? '-',
subtitle: localizations.membershipNumber,
icon: Icons.tag,
),
ContentItem(
title: membership.club.name,
subtitle: localizations.club,
icon: Icons.foundation,
)
],
buildRelations: (Person person) => {
Tab(child: HeadingText('${localizations.bouts} (${localizations.league})')):
ManyConsumer<TeamMatchBout, Membership>(
filterObject: membership,
builder: (BuildContext context, List<TeamMatchBout> teamMatchBouts) {
return GroupedList(
header: const HeadingItem(
// Adding a bout should not be an option here
),
items: teamMatchBouts.map(
(e) => SingleConsumer<TeamMatchBout>(
id: e.id,
initialData: e,
builder: (context, teamMatchBout) {
final bout = teamMatchBout.bout;
final weightClass = bout.weightClass;
final weightClassStr = weightClass == null
? ''
: '${weightClass.name}, ${weightClass.style.abbreviation(context)} | ';
return ListTile(
title: Text.rich(
TextSpan(
text: '${teamMatchBout.teamMatch.date.toDateString(context)}, $weightClassStr',
children: [
TextSpan(
text: bout.r?.fullName(context) ?? localizations.participantVacant,
style: bout.r?.participation.membership == membership
? const TextStyle(color: Colors.red, fontWeight: FontWeight.bold)
: null),
const TextSpan(text: ' - '),
TextSpan(
text: bout.b?.fullName(context) ?? localizations.participantVacant,
style: bout.b?.participation.membership == membership
? const TextStyle(color: Colors.blue, fontWeight: FontWeight.bold)
: null),
],
),
),
leading: const Icon(Icons.sports_kabaddi),
onTap: () => handleSelectedTeamMatchBout(teamMatchBout, context),
);
}),
),
);
},
),
// TODO: Add competition bouts
});
},
);
}

handleSelectedTeamMatchBout(TeamMatchBout bout, BuildContext context) {
context.push('/${TeamMatchOverview.route}/${bout.teamMatch.id}/${TeamMatchBoutOverview.route}/${bout.id}');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ class TeamMatchOverview extends ConsumerWidget {
builder: (context, teamMatchBout) => ContentItem(
title: teamMatchBout.bout.title(context),
icon: Icons.sports_kabaddi,
onTap: () => handleSelectedBout(match, teamMatchBout, context),
onTap: () => handleSelectedTeamMatchBout(match, teamMatchBout, context),
),
),
),
Expand All @@ -286,7 +286,7 @@ class TeamMatchOverview extends ConsumerWidget {
Future<List<BoutAction>> _getActions(WidgetRef ref, {required Bout bout}) =>
ref.read(manyDataStreamProvider<BoutAction, Bout>(ManyProviderData<BoutAction, Bout>(filterObject: bout)).future);

handleSelectedBout(TeamMatch match, TeamMatchBout bout, BuildContext context) {
handleSelectedTeamMatchBout(TeamMatch match, TeamMatchBout bout, BuildContext context) {
context.push('/${TeamMatchOverview.route}/${match.id}/${TeamMatchBoutOverview.route}/${bout.id}');
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import 'package:shelf/shelf.dart';
import 'package:wrestling_scoreboard_common/common.dart';
import 'package:wrestling_scoreboard_server/controllers/auth_controller.dart';
import 'package:wrestling_scoreboard_server/controllers/organizational_controller.dart';
import 'package:wrestling_scoreboard_server/controllers/participation_controller.dart';
import 'package:wrestling_scoreboard_server/controllers/team_match_bout_controller.dart';
import 'package:wrestling_scoreboard_server/request.dart';

class MembershipController extends OrganizationalController<Membership> {
static final MembershipController _singleton = MembershipController._internal();
Expand All @@ -10,6 +15,36 @@ class MembershipController extends OrganizationalController<Membership> {

MembershipController._internal() : super(tableName: 'membership');

static const _teamMatchBoutsQuery = '''
SELECT tmb.*
FROM bout as b
JOIN participant_state AS pst ON b.red_id = pst.id OR b.blue_id = pst.id
JOIN participation AS p ON pst.participation_id = p.id
JOIN team_match_bout AS tmb ON tmb.bout_id = b.id
JOIN team_match AS tm ON tmb.team_match_id = tm.id
WHERE p.membership_id = @id
ORDER BY tm.date DESC, tmb.pos;''';

Future<Response> requestTeamMatchBouts(Request request, User? user, String id) async {
final bool obfuscate = user?.obfuscate ?? true;

return TeamMatchBoutController().handleRequestManyFromQuery(
isRaw: request.isRaw,
sqlQuery: _teamMatchBoutsQuery,
substitutionValues: {'id': id},
obfuscate: obfuscate,
);
}

Future<Response> requestParticipations(Request request, User? user, String id) async {
return ParticipationController().handleRequestMany(
isRaw: request.isRaw,
conditions: ['membership_id = @id'],
substitutionValues: {'id': id},
obfuscate: user?.obfuscate ?? true,
);
}

@override
Map<String, dynamic> obfuscate(Map<String, dynamic> raw) {
raw['no'] = null;
Expand Down
2 changes: 2 additions & 0 deletions wrestling_scoreboard_server/lib/routes/api_route.dart
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ class ApiRoute {
router.restrictedPost('/membership', membershipController.postSingle);
router.restrictedGet('/memberships', membershipController.requestMany);
router.restrictedGetOne('/membership/<id|[0-9]+>', membershipController.requestSingle);
router.restrictedGetOne('/membership/<id|[0-9]+>/participations', membershipController.requestParticipations);
router.restrictedGetOne('/membership/<id|[0-9]+>/team_match_bouts', membershipController.requestTeamMatchBouts);

final participantStateController = ParticipantStateController();
router.restrictedPost('/participant_state', participantStateController.postSingle);
Expand Down

0 comments on commit 34228e5

Please sign in to comment.