import 'dart:async'; import 'package:drift/drift.dart' hide Column; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'package:sendtrain/daos/media_items_dao.dart'; import 'package:sendtrain/daos/object_media_items_dao.dart'; import 'package:sendtrain/daos/sessions_dao.dart'; import 'package:sendtrain/database/database.dart'; import 'package:sendtrain/widgets/builders/dialogs.dart'; import 'package:sendtrain/widgets/generic/elements/form_search_input.dart'; import 'package:sendtrain/widgets/generic/elements/form_text_input.dart'; import 'package:sendtrain/widgets/sessions/session_view.dart'; class SessionEditor extends StatefulWidget { const SessionEditor({super.key, this.data, this.session, this.callback}); final Session? session; final Map? data; final Function? callback; @override State createState() => _SessionEditorState(); } // used to pass the result of the found image back to current context... class SessionPayload { String? photoUri; String? address; } class _SessionEditorState extends State { final GlobalKey _formKey = GlobalKey(); late AppDatabase db; String editorType = 'Create'; final Map sessionCreateController = { 'name': TextEditingController(), 'content': TextEditingController(), 'status': TextEditingController(), 'date': TextEditingController(), 'address': TextEditingController(), 'media': TextEditingController(), }; final SessionPayload sessionPayload = SessionPayload(); @override void initState() { super.initState(); db = Provider.of(context, listen: false); // if we're editing a session, we'll want to populate it with the appropriate values if (widget.session != null) { editorType = 'Edit'; final Session session = widget.session!; sessionCreateController['name']?.text = session.title; sessionCreateController['content']?.text = session.content; sessionCreateController['status']?.text = session.status.name; sessionCreateController['date']?.text = DateFormat('yyyy-MM-dd').format(session.date!); if (session.address != null) { sessionCreateController['address']?.text = session.address!; } } } Future createSession(context) async { Map payload = { Symbol('title'): Value(sessionCreateController['name']!.text), Symbol('content'): Value(sessionCreateController['content']!.text), // we want to maintain existing status during update Symbol('status'): widget.session != null ? Value(widget.session!.status) : Value(SessionStatus.pending), Symbol('date'): Value( DateTime.parse(sessionCreateController['date']!.text)), }; // if a session exists we'll want to update it // so the payload needs the session id if (widget.session != null) { payload[Symbol('id')] = Value(widget.session!.id); } // optional params if (sessionCreateController['address']!.text.isNotEmpty) { payload[Symbol('address')] = Value(sessionCreateController['address']!.text); } return await SessionsDao(db) .createOrUpdate(Function.apply(SessionsCompanion.new, [], payload)); } Future createSessionMedia(context, sessionId) async { List deletedMedia = await MediaItemsDao(db).fromSession(sessionId) ..where((mediaItem) => mediaItem.type == MediaType.location); await MediaItemsDao(db).removeAll(deletedMedia.map((m) => m.id)); if (sessionPayload.photoUri != null) { MediaItemsCompanion mediaItem = MediaItemsCompanion( title: Value('Location Image'), description: Value(sessionPayload.address!), reference: Value(sessionPayload.photoUri!), type: Value(MediaType.location)); return await MediaItemsDao(db).createOrUpdate(mediaItem).then((id) async { ObjectMediaItemsCompanion omi = ObjectMediaItemsCompanion( objectId: Value(sessionId), objectType: Value(ObjectType.sessions), mediaId: Value(id), ); await ObjectMediaItemsDao(db).createOrUpdate(omi); }); } } @override Widget build(BuildContext context) { sessionCreateController['date']!.text = DateFormat('yyyy-MM-dd').format(DateTime.now()); return Padding( padding: EdgeInsets.fromLTRB(15, 0, 15, 15), child: Form( key: _formKey, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: EdgeInsets.only(top: 10, bottom: 10), child: Text('$editorType Session', textAlign: TextAlign.center, style: Theme.of(context).textTheme.titleLarge)), FormTextInput( controller: sessionCreateController['name']!, title: 'Title'), FormTextInput( controller: sessionCreateController['content']!, title: 'Description', icon: Icon(Icons.description_rounded), maxLines: 10), FormTextInput( controller: sessionCreateController['date']!, title: 'Date', icon: Icon(Icons.date_range_rounded), onTap: () { showDatePicker( context: context, initialDate: DateTime.now(), firstDate: DateTime.now(), lastDate: DateTime.now().add(Duration(days: 365))) .then((date) { if (date != null) { sessionCreateController['date']?.text = DateFormat('yyyy-MM-dd').format(date); } }); }), // Padding( // padding: EdgeInsets.only(top: 10, bottom: 10), // child: TextFormField( // readOnly: true, // decoration: InputDecoration( // prefixIcon: Icon(Icons.image_rounded), // filled: true, // border: OutlineInputBorder( // borderSide: BorderSide.none, // borderRadius: BorderRadius.circular(12), // ), // labelText: 'Select Media (optional)', // ), // controller: sessionCreateController['media'], // onTap: () async { // FilePickerResult? result = await FilePicker.platform // .pickFiles(allowMultiple: true); // if (result != null) { // List files = result.paths // .map((path) => File(path!)) // .toList(); // } // })), FormSearchInput( sessionController: sessionCreateController['address']!, optionalPayload: sessionPayload), Row(mainAxisAlignment: MainAxisAlignment.end, children: [ Padding( padding: EdgeInsets.only(top: 10), child: FilledButton( onPressed: () async => { if (_formKey.currentState!.validate()) { await createSession(_formKey.currentContext) .then((sessionId) async { int currentSessionId = sessionId; // dirft weirdly doesn't return the proper id if // an upsert ends up bein an update, so we'll // set the id to the provided session for an update if (widget.session != null) { currentSessionId = widget.session!.id; } // if we've found a photo add it to media! if (sessionPayload.photoUri != null) { await createSessionMedia( _formKey.currentContext, currentSessionId); } // if session is null it's new so we show the dialog // otherwise the dialog is already open, so no need if (widget.session == null) { SessionsDao(db) .find(currentSessionId) .then((session) => showGenericDialog( SessionView( session: session), _formKey.currentContext!)); } Navigator.pop( _formKey.currentContext!, 'Submit'); if (widget.callback != null) { await widget .callback!(widget.session!.id); } }) } }, child: Text('Submit'))) ]), ], ))); } }