import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:outbag_app/backend/request.dart'; import 'package:outbag_app/backend/room.dart'; import 'package:outbag_app/backend/user.dart'; import 'package:outbag_app/tools/fetch_wrapper.dart'; import 'package:outbag_app/tools/snackbar.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'dart:math'; class EditCategoryPage extends StatefulWidget { final String server; final String tag; final int? id; const EditCategoryPage(this.server, this.tag, {super.key, this.id}); @override State createState() => _EditCategoryPageState(); } class _EditCategoryPageState extends State { final TextEditingController _ctrName = TextEditingController(); ColorSwatch _ctrColor = Colors.purple; bool showSpinner = false; @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { if (widget.id == null) { // trying to create a new category return; } fetchCategory(); }); } void fetchCategory() { final user = context.read(); // TODO: load cached rooms doNetworkRequest(ScaffoldMessenger.of(context), req: () => postWithCreadentials( credentials: user, target: user.server, path: 'getCategory', body: { 'room': widget.tag, 'server': widget.server, 'listCatID': widget.id }), onOK: (json) { setState(() { _ctrName.text = json['data']['title']; _ctrColor = colorFromString(json['data']['color']); }); }); } @override Widget build(BuildContext context) { final textTheme = Theme.of(context) .textTheme .apply(displayColor: Theme.of(context).colorScheme.onSurface); double width = MediaQuery.of(context).size.width; double height = MediaQuery.of(context).size.height; double smallest = min(min(width, height), 400); return showSpinner ? Scaffold( body: Center( child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ const CircularProgressIndicator(), Text(AppLocalizations.of(context)!.loading, style: textTheme.titleLarge), ]))) : Scaffold( appBar: AppBar( title: Text((widget.id == null) ? AppLocalizations.of(context)!.newCategory : AppLocalizations.of(context)!.editCategory), ), body: SingleChildScrollView( child: Center( child: Padding( padding: const EdgeInsets.all(14), child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 400), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ IconButton( icon: Icon(Icons.square_rounded, size: 48.0, color: _ctrColor), tooltip: AppLocalizations.of(context)! .changeCategoryColor, onPressed: () { showDialog( context: context, builder: (ctx) => AlertDialog( title: Text( AppLocalizations.of(context)! .chooseCategoryColor), actions: const [], content: SizedBox( width: smallest * 0.3 * 3, height: smallest * 0.3 * 3, child: GridView.count( crossAxisCount: 3, children: RoomCategory .listColors() .map((color) { return GridTile( child: IconButton( icon: Icon( Icons .square_rounded, color: color, size: 48.0), // do not display tooltip for now // as it is hard to translate // and the tooltip prevented the click event, // when clicked on the tooltip bar // tooltip:icon.text, onPressed: () { setState(() { _ctrColor = color; }); Navigator.of( ctx) .pop(); })); }).toList())), )); }, ), Padding( padding: const EdgeInsets.all(8), child: TextField( controller: _ctrName, keyboardType: TextInputType.name, decoration: InputDecoration( prefixIcon: const Icon(Icons.badge), labelText: AppLocalizations.of(context)! .inputCategoryNameLabel, hintText: AppLocalizations.of(context)! .inputCategoryNameHint, helperText: AppLocalizations.of(context)! .inputCategoryNameHelp, border: const OutlineInputBorder(), ), ), ), ], ))))), floatingActionButton: FloatingActionButton.extended( onPressed: () async { final scaffMgr = ScaffoldMessenger.of(context); final router = GoRouter.of(context); final trans = AppLocalizations.of(context); // name may not be empty if (_ctrName.text.isEmpty) { showSimpleSnackbar(scaffMgr, text: trans!.errorNoRoomName, action: trans.ok); return; } setState(() { showSpinner = true; }); final user = context.read(); final color = colorIdFromColor(_ctrColor); if (widget.id == null) { await doNetworkRequest(scaffMgr, req: () => postWithCreadentials( target: user.server, credentials: user, path: 'addCategory', body: { 'room': widget.tag, 'server': widget.server, 'title': _ctrName.text, 'color': color }), onOK: (body) async { final id = body['data']['catID']; final cat = RoomCategory( server: widget.server, room: widget.tag, id: id, name: _ctrName.text, color: _ctrColor); // cache category await cat.toDisk(); // go back router.pop(); return; }, after: () { setState(() { showSpinner = false; }); }); } else { await doNetworkRequest(scaffMgr, req: () => postWithCreadentials( target: user.server, credentials: user, path: 'changeCategory', body: { 'room': widget.tag, 'server': widget.server, 'title': _ctrName.text, 'listCatID': widget.id, 'color': color }), onOK: (body) async { final cat = RoomCategory( server: widget.server, room: widget.tag, id: widget.id!, name: _ctrName.text, color: _ctrColor); // cache category await cat.toDisk(); // go back router.pop(); return; }, after: () { setState(() { showSpinner = false; }); }); } }, label: Text((widget.id == null) ? AppLocalizations.of(context)!.newCategoryShort : AppLocalizations.of(context)!.editCategoryShort), icon: Icon((widget.id == null) ? Icons.add : Icons.edit)), ); } }