second draft

This commit is contained in:
2025-10-29 20:57:37 +01:00
parent ed1ffc8be4
commit 3054027ebf
5 changed files with 1164 additions and 212 deletions

View File

@@ -20,6 +20,8 @@ class ListsPage extends StatefulWidget {
class _ListsPageState extends State<ListsPage> {
late Future<List<Liste>> _listsFuture;
StreamSubscription? _listsSubscription;
Map<String, String> _layoutNameById = {};
bool _layoutsLoading = false;
@override
void initState() {
@@ -39,6 +41,25 @@ class _ListsPageState extends State<ListsPage> {
void _loadLists() {
_listsFuture = apiService.getLists();
setState(() {});
_refreshLayoutCache();
}
Future<void> _refreshLayoutCache() async {
if (!mounted) return;
setState(() => _layoutsLoading = true);
try {
final layouts = await apiService.getStoreLayouts();
if (!mounted) return;
setState(() {
_layoutNameById = {
for (final layout in layouts) layout.id: layout.name,
};
_layoutsLoading = false;
});
} catch (_) {
if (!mounted) return;
setState(() => _layoutsLoading = false);
}
}
Future<void> _showListMenu(Liste list) async {
@@ -46,6 +67,13 @@ class _ListsPageState extends State<ListsPage> {
context: context,
builder: (c) => Wrap(
children: <Widget>[
if (list.owner == apiService.userId)
ListTile(
leading: const Icon(Icons.store_mall_directory_outlined),
title: const Text('Layout zuordnen'),
onTap: () => Navigator.pop(c, 'layout'),
),
if (list.owner == apiService.userId) const Divider(height: 0),
ListTile(
leading: const Icon(Icons.edit),
title: const Text('Umbenennen'),
@@ -62,11 +90,107 @@ class _ListsPageState extends State<ListsPage> {
if (result == 'edit') {
_editList(list);
} else if (result == 'layout') {
_assignLayout(list);
} else if (result == 'delete') {
_deleteList(list);
}
}
Future<void> _assignLayout(Liste list) async {
if (list.owner != apiService.userId) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Nur Besitzer können Layouts zuordnen.'),
),
);
}
return;
}
List<StoreLayout> layouts = [];
try {
layouts = await apiService.getStoreLayouts();
if (!mounted) return;
} catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Layouts konnten nicht geladen werden: $e')),
);
return;
}
const String noLayoutOption = '__no_layout__';
final String? currentId = list.layoutId;
final String? selection = await showModalBottomSheet<String>(
context: context,
builder: (context) {
return SafeArea(
child: ListView(
shrinkWrap: true,
children: [
ListTile(
leading: const Icon(Icons.close),
title: const Text('Kein Layout zuordnen'),
trailing: currentId == null
? const Icon(Icons.check, size: 20)
: null,
onTap: () => Navigator.pop(context, noLayoutOption),
),
if (layouts.isNotEmpty) const Divider(height: 0),
if (layouts.isEmpty)
const Padding(
padding: EdgeInsets.all(16),
child: Text('Keine Layouts verfügbar.'),
),
...layouts.map((layout) {
return ListTile(
leading: Icon(
layout.owner == apiService.userId
? Icons.store_mall_directory
: Icons.share,
),
title: Text(layout.name),
subtitle: layout.address != null && layout.address!.isNotEmpty
? Text(layout.address!)
: null,
trailing: currentId == layout.id
? const Icon(Icons.check, size: 20)
: null,
onTap: () => Navigator.pop(context, layout.id),
);
}),
],
),
);
},
);
if (!mounted) return;
if (selection == null) return;
final String? newLayoutId = selection == noLayoutOption ? null : selection;
if (newLayoutId == currentId) return;
try {
await apiService.updateList(
list.id,
layoutId: newLayoutId,
clearLayout: newLayoutId == null,
);
list.layoutId = newLayoutId;
_loadLists();
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Layout konnte nicht gespeichert werden: $e')),
);
}
}
}
Future<void> _editList(Liste list) async {
final TextEditingController titleCtl = TextEditingController(
text: list.title,
@@ -243,10 +367,39 @@ class _ListsPageState extends State<ListsPage> {
itemCount: lists.length,
itemBuilder: (c, i) {
final l = lists[i];
final String? layoutName = l.layoutId != null
? _layoutNameById[l.layoutId!]
: null;
final String? subtitle = layoutName != null
? 'Layout: $layoutName'
: l.layoutId != null
? (_layoutsLoading
? 'Layout wird geladen...'
: 'Layout-ID: ${l.layoutId}')
: null;
Widget? trailing;
if (l.owner == apiService.userId) {
trailing = IconButton(
tooltip: l.layoutId != null
? 'Layout wechseln'
: 'Layout zuordnen',
icon: Icon(
l.layoutId != null
? Icons.store_mall_directory
: Icons.store_mall_directory_outlined,
),
onPressed: () => _assignLayout(l),
);
} else if (l.layoutId != null) {
trailing = const Icon(Icons.store_mall_directory_outlined);
}
return ListTile(
title: Text(l.title),
subtitle: subtitle != null ? Text(subtitle) : null,
onTap: () => _openList(l),
onLongPress: () => _showListMenu(l),
trailing: trailing,
);
},
);