// ignore_for_file: prefer_const_constructors, prefer_const_literals_to_create_immutables, file_names, use_build_context_synchronously, library_private_types_in_public_api import 'package:flutter/material.dart'; import 'package:smilet/LoginPage.dart'; import 'package:smilet/MainMenu/Meny.dart'; import 'dart:async'; import 'package:http/http.dart' as http; import 'package:smilet/User.dart'; Future addActivity( String title, String place, String dateTime, User user) async { var response = await http.get(Uri.parse( "http://group-15-3.pvt.dsv.su.se/activity/add?title=$title&place=$place&dateTime=$dateTime&creatorUser=${user.getUsername()}&schoolCode=${user.getSchoolCode()}")); if (response.statusCode == 200) { // If the server did return a 200 OK response, // then parse the JSON. return true; } else { // If the server did not return a 200 OK response, // then throw an exception. return false; } } class NewActivity extends StatefulWidget { final String? restorationId; final User user; const NewActivity({super.key, required this.user, this.restorationId}); @override _NewActivityState createState() => _NewActivityState(); } class _NewActivityState extends State with RestorationMixin { @override String? get restorationId => widget.restorationId; final RestorableDateTime _selectedDate = RestorableDateTime(DateTime.now()); late final RestorableRouteFuture _restorableDatePickerRouteFuture = RestorableRouteFuture( onComplete: _selectDate, onPresent: (NavigatorState navigator, Object? arguments) { return navigator.restorablePush( _datePickerRoute, arguments: _selectedDate.value.millisecondsSinceEpoch, ); }, ); @pragma('vm:entry-point') static Route _datePickerRoute( BuildContext context, Object? arguments, ) { return DialogRoute( context: context, builder: (BuildContext context) { return DatePickerDialog( restorationId: 'date_picker_dialog', initialEntryMode: DatePickerEntryMode.calendarOnly, initialDate: DateTime.fromMillisecondsSinceEpoch(arguments! as int), firstDate: DateTime.now(), lastDate: DateTime(2025), ); }, ); } @override void restoreState(RestorationBucket? oldBucket, bool initialRestore) { registerForRestoration(_selectedDate, 'selected_date'); registerForRestoration( _restorableDatePickerRouteFuture, 'date_picker_route_future'); } void _selectDate(DateTime? newSelectedDate) { if (newSelectedDate != null) { setState(() { _selectedDate.value = newSelectedDate; dateController.text = _selectedDate.value.toString().substring(0, 10); }); } } TextEditingController titleController = TextEditingController(); TextEditingController placeController = TextEditingController(); TextEditingController timeController = TextEditingController(); TextEditingController dateController = TextEditingController(); final _formKey = GlobalKey(); @override Widget build(BuildContext context) { final textHeadStyle = TextStyle(fontSize: 40.0, fontWeight: FontWeight.bold); return Scaffold( appBar: AppBar( centerTitle: true, title: Image.asset( 'assets/images/ml_logo.png', height: 40, ), ), // Form för att kunna använda TextFormField body: Form( key: _formKey, child: SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox(height: 50), Padding( padding: const EdgeInsets.only(bottom: 20.0), child: Text('Ny aktivitet', textAlign: TextAlign.center, style: textHeadStyle), ), SizedBox(height: 20), Container( alignment: Alignment.center, child: SizedBox( width: 300, height: 80, child: TextFormField( maxLength: 16, controller: titleController, keyboardType: TextInputType.text, decoration: const InputDecoration( border: OutlineInputBorder(), labelText: 'Namn på aktivitet', hintText: 'Ange namn på aktivitet', ), onSaved: (String? value) {}, // Kolla så namnet inte är tomt validator: (String? value) { return (value != null && value != "") ? null : 'Skriv in ett namn på aktiviteten'; }, ), ), ), SizedBox(height: 20), Container( alignment: Alignment.center, child: SizedBox( width: 300, height: 80, child: TextFormField( maxLength: 16, controller: placeController, keyboardType: TextInputType.text, decoration: const InputDecoration( border: OutlineInputBorder(), labelText: 'Plats', hintText: 'Ange plats', ), onSaved: (String? value) {}, // Kolla så platsen inte är tom validator: (String? value) { return (value != null && value != "") ? null : 'Skriv in en plats'; }, ), ), ), SizedBox(height: 20), Container( alignment: Alignment.center, child: SizedBox( width: 300, height: 80, child: TextFormField( readOnly: true, maxLength: 5, controller: timeController, onTap: () async { FocusScope.of(context).requestFocus(FocusNode()); TimeOfDay? selectedTime24Hour = await showTimePicker( context: context, initialTime: TimeOfDay.now(), builder: (BuildContext context, Widget? child) { return MediaQuery( data: MediaQuery.of(context) .copyWith(alwaysUse24HourFormat: true), child: child!, ); }, ); if (selectedTime24Hour != null) { timeController.text = selectedTime24Hour.toString().substring(10, 15); } }, decoration: const InputDecoration( border: OutlineInputBorder(), labelText: 'Tid', hintText: 'Ange tid', ), onSaved: (String? value) {}, // Kollar tidens giltighet validator: (String? value) { return (value != null && value != "" && validateTimeValue(value)) ? null : 'Välj en tid som inte har passerat'; }, ), ), ), SizedBox(height: 20), Container( alignment: Alignment.center, child: SizedBox( width: 300, height: 80, child: TextFormField( readOnly: true, controller: dateController, onTap: () { FocusScope.of(context).requestFocus(FocusNode()); _restorableDatePickerRouteFuture.present(); }, decoration: const InputDecoration( border: OutlineInputBorder(), labelText: 'Datum', hintText: 'Ange datum', ), onSaved: (String? value) {}, validator: (String? value) { return (value != null && value != "") ? null : 'Välj ett datum'; }, ), ), ), SizedBox(height: 20.0), SizedBox( height: 50, width: 200, child: ElevatedButton( style: TextButton.styleFrom( backgroundColor: Color.fromARGB(255, 10, 179, 74), ), onPressed: () async { String dateTime = "${dateController.text} ${timeController.text}:00"; if (_formKey.currentState!.validate()) { if (await addActivity(titleController.text, placeController.text, dateTime, user)) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( duration: Duration(seconds: 1), behavior: SnackBarBehavior.floating, backgroundColor: Color.fromARGB(255, 12, 148, 64), content: Text( "Aktivitet skapad!", style: TextStyle(color: Colors.white), )), ); Navigator.push( context, MaterialPageRoute( builder: (context) => Meny( user: user, schoolDetails: schoolDetails, ))); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar( duration: Duration(seconds: 7), behavior: SnackBarBehavior.floating, backgroundColor: Color.fromARGB(255, 224, 24, 24), content: Text( "Kunda ej lägga till aktivitiet! $dateTime", style: TextStyle(color: Colors.white), )), ); } } }, child: const Text('Skapa', style: TextStyle(color: Colors.white, fontSize: 16))), ) ], ), ))); } bool validateTimeValue(String value) { TimeOfDay selectedTime = TimeOfDay( hour: int.parse(value.split(":")[0]), minute: int.parse(value.split(":")[1])); double timetoDouble(TimeOfDay selectedTime) => selectedTime.hour + selectedTime.minute / 60.0; double timeNowDouble(TimeOfDay timeNow) => TimeOfDay.now().hour + TimeOfDay.now().minute / 60.0; if (_selectedDate.value.day == DateTime.now().day && timetoDouble(selectedTime) < timeNowDouble(TimeOfDay.now())) { return false; } return true; } }