254 lines
8.7 KiB
Dart
254 lines
8.7 KiB
Dart
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<StatefulWidget> createState() => _EditCategoryPageState();
|
|
}
|
|
|
|
class _EditCategoryPageState extends State<EditCategoryPage> {
|
|
final TextEditingController _ctrName = TextEditingController();
|
|
ColorSwatch<int> _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<User>();
|
|
|
|
// 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<User>();
|
|
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(
|
|
id: id, name: _ctrName.text, color: _ctrColor);
|
|
// TODO: cache category
|
|
|
|
// 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(
|
|
id: widget.id!,
|
|
name: _ctrName.text,
|
|
color: _ctrColor);
|
|
// TODO: cache category
|
|
|
|
// 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)),
|
|
);
|
|
}
|
|
}
|