HopSpotFrontend/lib/pages/game_ended.dart
2025-05-28 15:41:16 +02:00

315 lines
9.1 KiB
Dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:pvt15/api/backend_api.dart';
import 'package:pvt15/hop_colors.dart';
class GameEndedPage extends StatefulWidget {
final String sessionID;
const GameEndedPage({super.key, required this.sessionID});
@override
State<GameEndedPage> createState() => _GameEndedPageState();
}
class _GameEndedPageState extends State<GameEndedPage> {
List<Map<String, dynamic>> winners = [];
List<Map<String, dynamic>> participants = [];
bool isLoading = true;
String? errorMessage;
@override
void initState() {
super.initState();
handleFetchParticipants();
}
void handleFetchParticipants() async {
await fetchParticipants();
}
Future<void> fetchParticipants() async {
try {
final response = await authHttpRequest(
context: context,
url:
'https://group-1-15.pvt.dsv.su.se/api/participants/${widget.sessionID}',
method: 'GET',
);
if (response.statusCode == 200) {
final List<dynamic> data = jsonDecode(utf8.decode(response.bodyBytes));
setState(() {
participants =
data
.map<Map<String, dynamic>>(
(participant) => {
'name': participant['username'],
'points': participant['score'] ?? 0,
},
)
.toList()
..sort(
(a, b) => (b['points'] as int).compareTo(a['points'] as int),
);
print('Participants: $participants'); // för debug
if (participants.isNotEmpty) {
final maxScore = participants.first['points'] as int;
winners =
participants.where((p) => p['points'] == maxScore).toList();
}
isLoading = false;
});
} else {
setState(() {
isLoading = false;
errorMessage =
'Misslyckades att hämta poäng (Status: ${response.statusCode})';
});
}
} catch (e) {
setState(() {
isLoading = false;
errorMessage = 'Misslyckades att hämta poäng: $e';
});
}
}
@override
Widget build(BuildContext context) {
return PopScope(
canPop: false,
onPopInvokedWithResult: (bool didPop, dynamic result) {
if (!didPop) {
_goBackToGameCategoryPage();
}
},
child: Scaffold(
body: Container(
decoration: HopColors.hopBackgroundDecoration,
child: SafeArea(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildHeader(),
Expanded(
child:
isLoading
? const Center(child: CircularProgressIndicator())
: errorMessage != null
? Center(
child: Text(
errorMessage!,
style: const TextStyle(color: Colors.white),
),
)
: _buildContent(),
),
],
),
),
),
),
),
);
}
Widget _buildHeader() {
return const Padding(
padding: EdgeInsets.only(bottom: 24.0),
child: Align(
alignment: Alignment.center,
child: Text(
'Spelet är avslutat!',
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
),
);
}
Widget _buildContent() {
return Container(
decoration: BoxDecoration(
color: const Color(0xFFF3E5F5).withValues(alpha: 0.6),
borderRadius: BorderRadius.circular(24.0),
),
child: Column(
children: [
if (winners.isNotEmpty) _buildWinnerCard(),
const SizedBox(height: 16),
_buildColumnHeaders(),
Expanded(
child: ListView.builder(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
itemCount: participants.length,
itemBuilder:
(context, index) =>
_buildParticipantItem(participants[index], index),
),
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 16.0,
),
child: ElevatedButton(
onPressed: () {
_goBackToGameCategoryPage();
},
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFFB39DDB),
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 16.0),
minimumSize: const Size(200, 0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(32.0),
),
textStyle: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
child: const Text('Tillbaka'),
),
),
const SizedBox(height: 16),
],
),
);
}
void _goBackToGameCategoryPage() {
Navigator.popUntil(
context,
(route) => route.settings.name == '/gameCategory',
);
}
Widget _buildWinnerCard() {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0),
padding: const EdgeInsets.all(16.0),
decoration: BoxDecoration(
color: const Color(0xFFFCE4EC).withValues(alpha: 0.9),
borderRadius: BorderRadius.circular(24.0),
border: Border.all(color: HopColors.hopPurplePrimary, width: 2),
),
child: Column(
children: [
Text(
winners.length > 1 ? 'Delade vinnare!' : 'Vinnare!',
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 24,
),
),
const SizedBox(height: 8),
...winners.map(
(winner) => Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
winner['name'],
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 20,
),
),
Text(
'${winner['points']} poäng',
style: const TextStyle(
color: Colors.black,
fontSize: 16,
),
),
],
),
],
),
),
),
],
),
);
}
Widget _buildColumnHeaders() {
return const Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Namn',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 16,
),
),
Text(
'Poäng',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 16,
),
),
],
),
);
}
Widget _buildParticipantItem(Map<String, dynamic> participant, int index) {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0),
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 12.0),
decoration: BoxDecoration(
color: const Color(0xFFFCE4EC).withValues(alpha: 0.7),
borderRadius: BorderRadius.circular(24.0),
),
child: Row(
children: [
SizedBox(
width: 32,
child: Text(
'${index + 1}',
style: const TextStyle(color: Colors.black, fontSize: 18),
),
),
const SizedBox(width: 12),
Expanded(
child: Text(
participant['name'],
style: const TextStyle(color: Colors.black, fontSize: 16),
),
),
SizedBox(
width: 60,
child: Text(
participant['points'].toString(),
textAlign: TextAlign.right,
style: const TextStyle(color: Colors.black, fontSize: 16),
),
),
],
),
);
}
}