320 lines
13 KiB
Dart
320 lines
13 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:insparkspokalen_ui/models/missionModel.dart';
|
|
import 'package:insparkspokalen_ui/services/backend/missionService.dart';
|
|
import 'package:intl/intl.dart';
|
|
|
|
class MissionAdminPage extends StatefulWidget {
|
|
@override
|
|
State<MissionAdminPage> createState() => _MissionAdminPageState();
|
|
}
|
|
|
|
class _MissionAdminPageState extends State<MissionAdminPage> {
|
|
final MissionService _missionService = MissionService();
|
|
List<MissionModel> challenges = [];
|
|
bool isLoading = true;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadMissions();
|
|
}
|
|
|
|
Future<void> _loadMissions() async {
|
|
try {
|
|
final missions = await _missionService.fetchMissions();
|
|
setState(() {
|
|
challenges = missions;
|
|
isLoading = false;
|
|
});
|
|
} catch (e) {
|
|
print('Fel vid hämtning av uppdrag: $e');
|
|
setState(() {
|
|
isLoading = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
void _showAddChallengeDialog() {
|
|
final titleController = TextEditingController();
|
|
final descriptionController = TextEditingController();
|
|
final pointsController = TextEditingController();
|
|
DateTime? selectedDeadline;
|
|
|
|
showDialog(
|
|
context: context,
|
|
builder:
|
|
(context) => AlertDialog(
|
|
backgroundColor: Colors.white, // Ljus bakgrund på dialogrutan
|
|
title: Text(
|
|
"Lägg till uppdrag",
|
|
style: TextStyle(color: Colors.black), // Svart titeltext
|
|
),
|
|
content: SingleChildScrollView(
|
|
child: Column(
|
|
children: [
|
|
TextField(
|
|
controller: titleController,
|
|
style: TextStyle(
|
|
color: Colors.black,
|
|
), // Svart text i fältet
|
|
decoration: InputDecoration(
|
|
labelText: "Namn",
|
|
labelStyle: TextStyle(color: Colors.black), // Svart label
|
|
enabledBorder: UnderlineInputBorder(
|
|
borderSide: BorderSide(color: Colors.grey),
|
|
),
|
|
focusedBorder: UnderlineInputBorder(
|
|
borderSide: BorderSide(color: Colors.black),
|
|
),
|
|
),
|
|
),
|
|
TextField(
|
|
controller: descriptionController,
|
|
style: TextStyle(color: Colors.black),
|
|
decoration: InputDecoration(
|
|
labelText: "Beskrivning",
|
|
labelStyle: TextStyle(color: Colors.black),
|
|
enabledBorder: UnderlineInputBorder(
|
|
borderSide: BorderSide(color: Colors.grey),
|
|
),
|
|
focusedBorder: UnderlineInputBorder(
|
|
borderSide: BorderSide(color: Colors.black),
|
|
),
|
|
),
|
|
),
|
|
TextField(
|
|
controller: pointsController,
|
|
style: TextStyle(color: Colors.black),
|
|
decoration: InputDecoration(
|
|
labelText: "Poäng",
|
|
labelStyle: TextStyle(color: Colors.black),
|
|
enabledBorder: UnderlineInputBorder(
|
|
borderSide: BorderSide(color: Colors.grey),
|
|
),
|
|
focusedBorder: UnderlineInputBorder(
|
|
borderSide: BorderSide(color: Colors.black),
|
|
),
|
|
),
|
|
keyboardType: TextInputType.number,
|
|
),
|
|
SizedBox(height: 12),
|
|
ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Color(0xFFFEDF00),
|
|
),
|
|
child: Text(
|
|
selectedDeadline == null
|
|
? "Välj deadline"
|
|
: selectedDeadline.toString().split(' ')[0],
|
|
style: TextStyle(color: Colors.black),
|
|
),
|
|
onPressed: () async {
|
|
final picked = await showDatePicker(
|
|
context: context,
|
|
initialDate: DateTime.now(),
|
|
firstDate: DateTime.now(),
|
|
lastDate: DateTime.now().add(Duration(days: 365)),
|
|
);
|
|
if (picked != null) {
|
|
setState(() => selectedDeadline = picked);
|
|
}
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.pop(context),
|
|
child: Text("Avbryt", style: TextStyle(color: Colors.black)),
|
|
),
|
|
ElevatedButton(
|
|
style: ElevatedButton.styleFrom(backgroundColor: Colors.yellow),
|
|
child: Text("Skapa", style: TextStyle(color: Colors.black)),
|
|
onPressed: () async {
|
|
if (titleController.text.isNotEmpty &&
|
|
descriptionController.text.isNotEmpty &&
|
|
pointsController.text.isNotEmpty &&
|
|
selectedDeadline != null) {
|
|
final newMission = MissionModel(
|
|
name: titleController.text,
|
|
description: descriptionController.text,
|
|
points: int.parse(pointsController.text),
|
|
deadline: selectedDeadline!.toIso8601String(),
|
|
);
|
|
|
|
try {
|
|
await _missionService.addMission(newMission);
|
|
Navigator.pop(context);
|
|
await _loadMissions();
|
|
} catch (e) {
|
|
print('Fel vid skapande: $e');
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text('Kunde inte lägga till uppdrag'),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
},
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
void _confirmDelete(MissionModel mission) async {
|
|
final shouldDelete = await showDialog<bool>(
|
|
context: context,
|
|
builder:
|
|
(context) => AlertDialog(
|
|
title: Text("Ta bort uppdrag"),
|
|
content: Text(
|
|
"Är du säker på att du vill ta bort uppdraget '${mission.name}'?",
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.pop(context, false),
|
|
child: Text("Avbryt"),
|
|
),
|
|
ElevatedButton(
|
|
onPressed: () => Navigator.pop(context, true),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Color(0xFF000000),
|
|
),
|
|
child: Text("Ta bort"),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
|
|
if (shouldDelete == true) {
|
|
try {
|
|
await _missionService.deleteMission(mission.id!);
|
|
await _loadMissions();
|
|
} catch (e) {
|
|
print('Fel vid borttagning: $e');
|
|
ScaffoldMessenger.of(
|
|
context,
|
|
).showSnackBar(SnackBar(content: Text('Kunde inte ta bort uppdrag')));
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: Color(0xFF2E2E2E),
|
|
body:
|
|
isLoading
|
|
? Center(child: CircularProgressIndicator())
|
|
: SingleChildScrollView(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children:
|
|
challenges.map((challenge) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
|
child: Card(
|
|
elevation: 4,
|
|
//color: Color(0xFFFEDF00),
|
|
color: Colors.amber,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
vertical: 4.0,
|
|
),
|
|
child: ExpansionTile(
|
|
tilePadding: EdgeInsets.symmetric(
|
|
horizontal: 16.0,
|
|
),
|
|
title: Text(
|
|
challenge.name,
|
|
style: TextStyle(
|
|
color: Colors.black,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
subtitle: Column(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
children: [
|
|
SizedBox(height: 4),
|
|
Text(
|
|
"Deadline: ${DateFormat('d MMMM yyyy', 'sv_SE').format(DateTime.parse(challenge.deadline))}",
|
|
style: TextStyle(color: Colors.black87),
|
|
),
|
|
Text(
|
|
"Poäng: ${challenge.points}",
|
|
style: TextStyle(color: Colors.black87),
|
|
),
|
|
],
|
|
),
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: Column(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"Beskrivning:",
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
SizedBox(height: 4),
|
|
Text(
|
|
challenge.description ??
|
|
'Ingen beskrivning',
|
|
style: TextStyle(
|
|
color: Colors.black,
|
|
),
|
|
),
|
|
SizedBox(height: 12),
|
|
if (challenge.timePosted != null)
|
|
Padding(
|
|
padding: const EdgeInsets.only(
|
|
top: 8.0,
|
|
),
|
|
child: Text(
|
|
"Postad: ${challenge.timePosted!.toLocal().toString().split('.')[0]}",
|
|
style: TextStyle(
|
|
color: Colors.black54,
|
|
),
|
|
),
|
|
),
|
|
ElevatedButton.icon(
|
|
onPressed:
|
|
() => _confirmDelete(challenge),
|
|
icon: Icon(Icons.delete),
|
|
label: Text("Ta bort"),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.white,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}).toList(),
|
|
),
|
|
),
|
|
),
|
|
floatingActionButton: FloatingActionButton(
|
|
onPressed: _showAddChallengeDialog,
|
|
backgroundColor: Color(0xFFFFFFFF),
|
|
child: Icon(Icons.add, color: Colors.black),
|
|
),
|
|
);
|
|
}
|
|
}
|