new plus button
This commit is contained in:
@@ -13,6 +13,8 @@ import 'utils/dates.dart';
|
||||
import 'utils/money.dart';
|
||||
import 'widgets/confirm_dialog.dart';
|
||||
import 'widgets/item_edit_sheet.dart';
|
||||
import 'widgets/name_dialog.dart';
|
||||
import 'widgets/tag_editor.dart';
|
||||
|
||||
class ShopDetailScreen extends StatefulWidget {
|
||||
const ShopDetailScreen({
|
||||
@@ -31,11 +33,18 @@ class ShopDetailScreen extends StatefulWidget {
|
||||
class _ShopDetailScreenState extends State<ShopDetailScreen> {
|
||||
late Future<({Shop shop, List<ShopItem> items})> _future;
|
||||
bool _editing = false;
|
||||
List<String> _tagSuggestions = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_future = _load();
|
||||
widget.repository
|
||||
.getUsedShopTags()
|
||||
.then((tags) {
|
||||
if (mounted) setState(() => _tagSuggestions = tags);
|
||||
})
|
||||
.catchError((_) {});
|
||||
}
|
||||
|
||||
Future<({Shop shop, List<ShopItem> items})> _load() async {
|
||||
@@ -111,6 +120,28 @@ class _ShopDetailScreenState extends State<ShopDetailScreen> {
|
||||
if (mounted) _reload();
|
||||
}
|
||||
|
||||
Future<void> _editName(Shop shop) async {
|
||||
final name = await showNameDialog(
|
||||
context,
|
||||
title: 'Trip name',
|
||||
label: 'Name',
|
||||
initial: shop.name,
|
||||
allowEmpty: true,
|
||||
);
|
||||
if (name == null || !mounted) return;
|
||||
await widget.repository.updateShop(
|
||||
id: shop.id,
|
||||
name: name,
|
||||
clearName: name.isEmpty,
|
||||
);
|
||||
if (mounted) _reload();
|
||||
}
|
||||
|
||||
Future<void> _setTags(Shop shop, List<String> tags) async {
|
||||
await widget.repository.updateShop(id: shop.id, tags: tags);
|
||||
if (mounted) _reload();
|
||||
}
|
||||
|
||||
Widget? _itemSubtitle(ShopItem item) {
|
||||
final parts = [
|
||||
if (item.quantity != null)
|
||||
@@ -160,12 +191,40 @@ class _ShopDetailScreenState extends State<ShopDetailScreen> {
|
||||
return ListView(
|
||||
padding: const EdgeInsets.fromLTRB(16, 8, 16, 32),
|
||||
children: [
|
||||
Text(shop.supermarket, style: theme.textTheme.headlineMedium),
|
||||
if (_editing)
|
||||
ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text(
|
||||
shop.name?.isNotEmpty == true
|
||||
? shop.name!
|
||||
: 'Add a trip name',
|
||||
),
|
||||
subtitle: const Text('Optional name for this shop log'),
|
||||
trailing: const Icon(Icons.edit_outlined),
|
||||
onTap: () => _editName(shop),
|
||||
)
|
||||
else
|
||||
Text(shop.displayName, style: theme.textTheme.headlineMedium),
|
||||
if (_editing || (shop.name != null && shop.name!.isNotEmpty)) ...[
|
||||
const SizedBox(height: 4),
|
||||
Text(shop.supermarket, style: theme.textTheme.titleMedium),
|
||||
],
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
formatDate(shop.shoppedAt),
|
||||
style: theme.textTheme.bodyLarge,
|
||||
),
|
||||
if (_editing) ...[
|
||||
const SizedBox(height: 16),
|
||||
TagEditor(
|
||||
tags: shop.tags,
|
||||
suggestions: _tagSuggestions,
|
||||
onChanged: (tags) => _setTags(shop, tags),
|
||||
),
|
||||
] else if (shop.tags.isNotEmpty) ...[
|
||||
const SizedBox(height: 12),
|
||||
TagChips(tags: shop.tags),
|
||||
],
|
||||
if (hasReceipt) ...[
|
||||
const SizedBox(height: 16),
|
||||
GestureDetector(
|
||||
|
||||
Reference in New Issue
Block a user