204 lines
5.4 KiB
Dart
204 lines
5.4 KiB
Dart
import 'dart:async';
|
|
import 'package:flutter/material.dart';
|
|
import 'dart:math';
|
|
import 'package:flutter_fortune_wheel/flutter_fortune_wheel.dart';
|
|
import 'package:pvt15/pages/game_page.dart';
|
|
import 'dart:convert';
|
|
import 'package:http/http.dart' as http;
|
|
|
|
class WheelPage extends StatefulWidget {
|
|
const WheelPage({super.key});
|
|
|
|
@override
|
|
State<WheelPage> createState() => _WheelPageState();
|
|
}
|
|
|
|
class _WheelPageState extends State<WheelPage> {
|
|
final StreamController<int> controller = StreamController<int>();
|
|
Map<String, dynamic> challenges = {};
|
|
|
|
// A list of game titles that represent the segments of the wheel.
|
|
List<String> wheelItems = [];
|
|
|
|
// Closes the controller's stream when the widget is disposed.
|
|
// This ensures proper cleanup of resources and prevents memory leaks.
|
|
@override
|
|
void dispose() {
|
|
controller.close();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
initializeChallenge();
|
|
}
|
|
|
|
void initializeChallenge() async {
|
|
await fetchChallenges();
|
|
setState(() { // Load the challenge
|
|
_loadChallenges();
|
|
});
|
|
}
|
|
|
|
// Simulates a spin of the fortune wheel by generating a random index.
|
|
void _spin() {
|
|
final result = Random().nextInt(wheelItems.length);
|
|
controller.add(result);
|
|
}
|
|
|
|
// Returns a description for the given title.
|
|
String _getDescriptionFor(String title) {
|
|
switch (title) {
|
|
case 'Rita & gissa':
|
|
return 'Text';
|
|
case 'Charader':
|
|
return 'Text';
|
|
case 'Dansbattle':
|
|
return 'Text';
|
|
case 'Gissa låten':
|
|
return 'Text';
|
|
case 'Sanningar':
|
|
return 'Text';
|
|
case 'Selfiejakt':
|
|
return 'Text';
|
|
default:
|
|
return 'Okänt spel';
|
|
}
|
|
}
|
|
|
|
// Builds the main UI for the wheel screen.
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: const Color.fromARGB(248, 180, 8, 129),
|
|
body: Center(
|
|
child: wheelItems.isEmpty ? const CircularProgressIndicator() // Waiting for wheel to build
|
|
:GestureDetector(
|
|
onTap: _spin,
|
|
child: _buildWheelContainer(),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// Builds the main container that holds the fortune wheel and its instructional text.
|
|
Widget _buildWheelContainer() {
|
|
return Container(
|
|
height: 500,
|
|
width: 370,
|
|
decoration: BoxDecoration(
|
|
color: const Color.fromARGB(255, 153, 101, 150),
|
|
borderRadius: BorderRadius.circular(40),
|
|
),
|
|
child: Stack(
|
|
alignment: Alignment.center,
|
|
children: [
|
|
_buildContainerText(),
|
|
_buildWheel(),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
// Builds the wheel and listens to spins and triggers an action when the animation ends.
|
|
Widget _buildWheel() {
|
|
return SizedBox(
|
|
width: 320,
|
|
height: 320,
|
|
child: FortuneWheel(
|
|
animateFirst: false,
|
|
selected: controller.stream,
|
|
onAnimationEnd: _handleWheelResult,
|
|
items: _buildWheelItems(),
|
|
indicators: <FortuneIndicator>[
|
|
_buildFortuneIndicator(),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
// Build fortune indicator
|
|
_buildFortuneIndicator() {
|
|
return FortuneIndicator(
|
|
alignment: Alignment.topCenter,
|
|
child: Container(
|
|
width: 12,
|
|
height: 12,
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// Builds a text widget that instructs the user to click on the wheel
|
|
Widget _buildContainerText() {
|
|
return Positioned(
|
|
top: 20,
|
|
child: Text(
|
|
'Klicka på hjulet!',
|
|
style: TextStyle(
|
|
fontSize: 24,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// Builds and returns the list of FortuneItem widgets that make up the wheel's segments
|
|
List<FortuneItem> _buildWheelItems() {
|
|
return wheelItems.map(
|
|
(item) => FortuneItem(
|
|
child: Text(
|
|
item,
|
|
style: const TextStyle(
|
|
fontSize: 18,
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
).toList();
|
|
}
|
|
|
|
|
|
// Handles the result of the wheel spin.
|
|
// It retrieves the selected item's title and description, then navigates to corresponding gamePage
|
|
void _handleWheelResult() {
|
|
String selectedTitle = "Charader";
|
|
final selectedDescription = _getDescriptionFor(selectedTitle);
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) => GamePage(
|
|
title: selectedTitle,
|
|
description: selectedDescription,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// Fetch the challenges through the api
|
|
Future<void> fetchChallenges() async {
|
|
final url = Uri.parse('https://group-1-15.pvt.dsv.su.se/api/challenges');
|
|
try {
|
|
final response = await http.get(url);
|
|
if (response.statusCode == 200) { // (HTTP 200 OK)
|
|
challenges = jsonDecode(utf8.decode(response.bodyBytes)); // convert the JSON string into a map
|
|
// var charaderChallenges = challenges["Charader"];
|
|
// debugPrint("Charader challenges: $charaderChallenges");
|
|
// debugPrint(challenges.toString());
|
|
}
|
|
} catch (e) {
|
|
debugPrint('Ett fel inträffade vid anrop till backend: $e');
|
|
throw Exception('Ett fel inträffade vid anrop till backend: $e');
|
|
}
|
|
}
|
|
|
|
void _loadChallenges() async {
|
|
wheelItems = challenges.keys.toList();
|
|
}
|
|
} |