316 lines
12 KiB
Dart
316 lines
12 KiB
Dart
// 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<bool> 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<NewActivity> with RestorationMixin {
|
|
@override
|
|
String? get restorationId => widget.restorationId;
|
|
|
|
final RestorableDateTime _selectedDate = RestorableDateTime(DateTime.now());
|
|
|
|
late final RestorableRouteFuture<DateTime?> _restorableDatePickerRouteFuture =
|
|
RestorableRouteFuture<DateTime?>(
|
|
onComplete: _selectDate,
|
|
onPresent: (NavigatorState navigator, Object? arguments) {
|
|
return navigator.restorablePush(
|
|
_datePickerRoute,
|
|
arguments: _selectedDate.value.millisecondsSinceEpoch,
|
|
);
|
|
},
|
|
);
|
|
|
|
@pragma('vm:entry-point')
|
|
static Route<DateTime> _datePickerRoute(
|
|
BuildContext context,
|
|
Object? arguments,
|
|
) {
|
|
return DialogRoute<DateTime>(
|
|
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<FormState>();
|
|
|
|
@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;
|
|
}
|
|
}
|