feat: Add location display and category chips in pantry and inventory screens
Test Suite / test (24.15.0) (push) Has been cancelled

This commit is contained in:
Nils-Johan Gynther
2026-05-11 20:53:11 +02:00
parent 68476142c1
commit 2281df3716
3 changed files with 90 additions and 22 deletions
@@ -218,6 +218,13 @@ class _InventoryEditScreenState extends ConsumerState<InventoryEditScreen> {
} }
Future<void> _save() async { Future<void> _save() async {
if (_selectedProductId == null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(context.l10n.inventorySelectProduct)),
);
return;
}
if (!_formKey.currentState!.validate()) return; if (!_formKey.currentState!.validate()) return;
setState(() => _saving = true); setState(() => _saving = true);
try { try {
@@ -286,10 +286,12 @@ class _ForegroundTile extends ConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final theme = Theme.of(context); final theme = Theme.of(context);
final location = item.location?.trim();
final hasLocation = location != null && location.isNotEmpty;
final subtitleText = [ final subtitleText = [
'${_fmtQty(item.quantity)} ${item.unit}', '${_fmtQty(item.quantity)} ${item.unit}',
if (item.location != null && item.location!.isNotEmpty) item.location!, if (hasLocation) location,
if (item.bestBeforeDate != null) if (item.bestBeforeDate != null)
'Bäst före: ${_formatDate(item.bestBeforeDate!)}', 'Bäst före: ${_formatDate(item.bestBeforeDate!)}',
].join(' · '); ].join(' · ');
@@ -305,8 +307,12 @@ class _ForegroundTile extends ConsumerWidget {
) )
: null, : null,
title: Text(item.displayName), title: Text(item.displayName),
// Subtitle: small swipe-hint icon + text on the same row. // Subtitle: swipe hint + details on first line, category chip below.
subtitle: Row( subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [ children: [
if (!selectableMode) ...[ if (!selectableMode) ...[
Icon( Icon(
@@ -324,6 +330,30 @@ class _ForegroundTile extends ConsumerWidget {
), ),
], ],
), ),
const SizedBox(height: 6),
Row(
children: [
Flexible(
child: Chip(
label: Text(
'L1: ${item.l1Category}',
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
padding: EdgeInsets.zero,
visualDensity: VisualDensity.compact,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
side: BorderSide(color: theme.colorScheme.outlineVariant),
backgroundColor: theme.colorScheme.surface,
labelStyle: theme.textTheme.bodySmall?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
),
),
],
),
],
),
trailing: acting trailing: acting
? const SizedBox( ? const SizedBox(
width: 24, width: 24,
@@ -219,6 +219,9 @@ class _PantryScreenState extends ConsumerState<PantryScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context);
final colorScheme = theme.colorScheme;
final textTheme = theme.textTheme;
final pantryAsync = ref.watch(pantryProvider); final pantryAsync = ref.watch(pantryProvider);
if (pantryAsync.isLoading) { if (pantryAsync.isLoading) {
@@ -370,15 +373,43 @@ class _PantryScreenState extends ConsumerState<PantryScreen> {
if (index == 1) return headerSection; if (index == 1) return headerSection;
final item = filteredItems[index - 2]; final item = filteredItems[index - 2];
final l1Category = _resolveL1Category(item); final l1Category = _resolveL1Category(item);
final location = item.location?.trim();
final hasLocation = location != null && location.isNotEmpty;
return ListTile( return ListTile(
title: Text(item.displayName), title: Text(item.displayName),
subtitle: Text( subtitle: Column(
[ crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
if (hasLocation)
Text(
'Plats: $location',
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 6),
Row(
children: [
Flexible(
child: Chip(
label: Text(
'L1: $l1Category', 'L1: $l1Category',
if (item.location != null && item.location!.trim().isNotEmpty) maxLines: 1,
'Plats: ${item.location}', overflow: TextOverflow.ellipsis,
].join(''), ),
padding: EdgeInsets.zero,
visualDensity: VisualDensity.compact,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
side: BorderSide(color: colorScheme.outlineVariant),
backgroundColor: colorScheme.surface,
labelStyle: textTheme.bodySmall?.copyWith(
color: colorScheme.onSurfaceVariant,
),
),
),
],
),
],
), ),
trailing: Row( trailing: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,