Insparkspokalen-ui/lib/leaderboard/leaderboardAdmin.dart

281 lines
8.0 KiB
Dart

import 'dart:async';
import 'package:insparkspokalen_ui/services/backend/LeaderBordSettingsService.dart';
import 'package:provider/provider.dart';
import 'package:flutter/material.dart';
import 'package:insparkspokalen_ui/models/teamModel.dart';
import 'package:insparkspokalen_ui/services/backend/teamService.dart';
import 'package:insparkspokalen_ui/services/googleAuthService.dart';
class LeaderboardAdmin extends StatefulWidget {
const LeaderboardAdmin({super.key});
@override
State<LeaderboardAdmin> createState() => _LeaderboardState();
}
class _LeaderboardState extends State<LeaderboardAdmin> {
late TeamService groupService;
List<TeamModel> groups = [];
bool isLoading = true;
bool showLeaderboard = true;
final SettingsService settingsService = SettingsService();
@override
void initState() {
super.initState();
groupService = Provider.of<TeamService>(context, listen: false);
groupService = Provider.of<TeamService>(context, listen: false);
super.initState();
_loadGroups();
settingsService.getLeaderboardVisibility().then((value) {
setState(() {
showLeaderboard = value;
});
});
// Uppdatera var 10:e sekund
Timer.periodic(Duration(seconds: 10), (_) {
_loadGroups();
});
}
Future<void> _loadGroups() async {
final result = await groupService.showTeams();
setState(() {
groups = result;
isLoading = false;
});
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Här kommer switchen
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'Visa leaderboard för deltagare',
style: TextStyle(color: Colors.white, fontSize: 16),
),
Switch(
value: showLeaderboard,
onChanged: (value) async {
setState(() {
showLeaderboard = value;
});
await settingsService.setLeaderboardVisibility(value);
},
activeColor: const Color(0xFFDAA520),
),
],
),
),
_GreyBackground(
child:
isLoading
? const Center(child: CircularProgressIndicator())
: _TopplistaBody(groups: groups),
),
],
),
);
}
}
class _GreyBackground extends StatelessWidget {
final Widget child;
const _GreyBackground({required this.child});
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(16.0),
padding: const EdgeInsets.all(16.0),
decoration: BoxDecoration(
color: const Color(0xFFDAA520),
borderRadius: BorderRadius.circular(40),
),
child: child,
);
}
}
class _TopplistaBody extends StatelessWidget {
final List<TeamModel> groups;
const _TopplistaBody({required this.groups});
@override
Widget build(BuildContext context) {
return Column(
children: [
...groups.asMap().entries.map(
(entry) =>
GruppKort.GroupCard(group: entry.value, place: entry.key + 1),
),
const SizedBox(height: 16),
],
);
}
}
class GruppKort extends StatefulWidget {
final TeamModel group;
final int place;
const GruppKort.GroupCard({
super.key,
required this.group,
required this.place,
});
@override
State<GruppKort> createState() => _GruppKortState();
}
class _GruppKortState extends State<GruppKort> {
late TextEditingController _controller;
@override
void initState() {
super.initState();
_controller = TextEditingController(text: '0');
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
final groupService = TeamService();
Future<void> _updateScore(int scoreChange) async {
final int? score = int.tryParse(_controller.text);
if (score == null) return;
final int updatedScore = scoreChange == 1 ? score : -score;
final success = await groupService.updateScore(
widget.group.teamId,
updatedScore,
);
if (success) {
setState(() {
_controller.text = '0';
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Poäng uppdaterad för ${widget.group.name}')),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Misslyckades att uppdatera poäng')),
);
}
}
@override
Widget build(BuildContext context) {
return Card(
elevation: 3,
margin: const EdgeInsets.symmetric(vertical: 8.0),
color: const Color(0xFF2E2E2E),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
children: [
ListTile(
contentPadding: EdgeInsets.zero,
title: Align(
alignment: Alignment.centerLeft,
child: Text(
widget.group.name,
style: const TextStyle(
fontSize: 18,
color: Color(0xFFD6D6D6),
),
),
),
trailing: Text(
'${widget.group.score} poäng',
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Color(0xFFD6D6D6),
),
),
),
const SizedBox(height: 8),
Row(
children: [
Expanded(
child: TextField(
controller: _controller,
keyboardType: TextInputType.number,
style: const TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: 'Ange poängändring',
labelStyle: const TextStyle(color: Colors.white),
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Color(0xFFFEDF00)),
borderRadius: BorderRadius.circular(8),
),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: Color(0xFFDAA520),
width: 2,
),
borderRadius: BorderRadius.circular(8),
),
),
),
),
const SizedBox(width: 8),
IconButton(
icon: const Icon(Icons.add, color: Color(0xFFfedf00)),
onPressed: () async {
if (!GoogleAuthService.isLoggedIn()) {
await GoogleAuthService.signInWithGoogle(context);
if (!GoogleAuthService.isLoggedIn())
return; // user cancelled or login failed
}
_updateScore(1);
},
),
const SizedBox(width: 8),
IconButton(
icon: const Icon(Icons.remove, color: Color(0xFFFEDF00)),
onPressed: () async {
if (!GoogleAuthService.isLoggedIn()) {
await GoogleAuthService.signInWithGoogle(context);
if (!GoogleAuthService.isLoggedIn())
return; // user cancelled or login failed
}
_updateScore(1);
},
),
],
),
],
),
),
);
}
}