feat(web): improve web build configuration and accessibility
- Add source maps and web renderer build arguments with defaults - Configure Caddy with CSP headers, cache policies, and service worker handling - Defer loading of import screen for performance optimization - Add semantic labels to icons for accessibility - Update web index.html with Swedish language, meta tags, and description - Add robots.txt and lighthouse configuration - Add new planning documents and archive entries
This commit is contained in:
@@ -39,8 +39,9 @@ double _stepForUnit(String unit) {
|
||||
|
||||
/// Formats a step value for display: whole numbers without decimal,
|
||||
/// fractions with one decimal.
|
||||
String _fmtStep(double step) =>
|
||||
step == step.roundToDouble() ? step.toStringAsFixed(0) : step.toStringAsFixed(1);
|
||||
String _fmtStep(double step) => step == step.roundToDouble()
|
||||
? step.toStringAsFixed(0)
|
||||
: step.toStringAsFixed(1);
|
||||
|
||||
/// A [ListTile] wrapped in a swipe-to-adjust widget.
|
||||
///
|
||||
@@ -122,7 +123,8 @@ class _SwipeableInventoryTileState
|
||||
// Decrease: use consume endpoint so history is preserved.
|
||||
// Guard against going below zero.
|
||||
if (widget.item.quantity <= 0) return;
|
||||
final consume = step > widget.item.quantity ? widget.item.quantity : step;
|
||||
final consume =
|
||||
step > widget.item.quantity ? widget.item.quantity : step;
|
||||
await repo.consumeInventoryItem(
|
||||
widget.item.id,
|
||||
amountUsed: consume,
|
||||
@@ -402,32 +404,44 @@ class _TrailingActions extends ConsumerWidget {
|
||||
Tooltip(
|
||||
message: 'Konsumera',
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.remove_circle_outline),
|
||||
icon: const Icon(
|
||||
Icons.remove_circle_outline,
|
||||
semanticLabel: 'Konsumera',
|
||||
),
|
||||
onPressed: () => context.push('/inventory/${item.id}/consume'),
|
||||
),
|
||||
),
|
||||
Tooltip(
|
||||
message: 'Redigera',
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.edit_outlined),
|
||||
icon: const Icon(
|
||||
Icons.edit_outlined,
|
||||
semanticLabel: 'Redigera',
|
||||
),
|
||||
onPressed: () => context.push('/inventory/${item.id}/edit'),
|
||||
),
|
||||
),
|
||||
Tooltip(
|
||||
message: 'Flytta till baslager',
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.storefront_outlined),
|
||||
icon: const Icon(
|
||||
Icons.storefront_outlined,
|
||||
semanticLabel: 'Flytta till baslager',
|
||||
),
|
||||
onPressed: () async {
|
||||
try {
|
||||
final token = await ref.read(authStateProvider.future);
|
||||
await ref.read(inventoryRepositoryProvider).moveInventoryItemToPantry(
|
||||
await ref
|
||||
.read(inventoryRepositoryProvider)
|
||||
.moveInventoryItemToPantry(
|
||||
item.id,
|
||||
token: token,
|
||||
);
|
||||
ref.invalidate(inventoryProvider);
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
buildCopyableErrorSnackBar(context, mapErrorToUserMessage(e, context)),
|
||||
buildCopyableErrorSnackBar(
|
||||
context, mapErrorToUserMessage(e, context)),
|
||||
);
|
||||
}
|
||||
},
|
||||
@@ -449,7 +463,11 @@ class _DeleteButton extends ConsumerWidget {
|
||||
return Tooltip(
|
||||
message: 'Ta bort',
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.delete_outline, color: Colors.red),
|
||||
icon: const Icon(
|
||||
Icons.delete_outline,
|
||||
color: Colors.red,
|
||||
semanticLabel: 'Ta bort',
|
||||
),
|
||||
onPressed: () async {
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
@@ -477,7 +495,8 @@ class _DeleteButton extends ConsumerWidget {
|
||||
ref.invalidate(inventoryProvider);
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
buildCopyableErrorSnackBar(context, mapErrorToUserMessage(e, context)),
|
||||
buildCopyableErrorSnackBar(
|
||||
context, mapErrorToUserMessage(e, context)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -486,4 +505,3 @@ class _DeleteButton extends ConsumerWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user