feat(import): implement recipe import functionality with file and URL support
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -7,12 +7,46 @@ import '../../auth/data/auth_providers.dart';
|
||||
import '../data/inventory_providers.dart';
|
||||
import '../domain/inventory_item.dart';
|
||||
|
||||
/// Returns a sensible step size for quick swipe-adjustments given [unit].
|
||||
///
|
||||
/// Examples: "g" → 50, "kg" → 0.1, "ml" → 50, "l" / "dl" → 0.1,
|
||||
/// everything else (pieces, packages, etc.) → 1.
|
||||
double _stepForUnit(String unit) {
|
||||
switch (unit.trim().toLowerCase()) {
|
||||
case 'g':
|
||||
case 'gram':
|
||||
return 50;
|
||||
case 'kg':
|
||||
case 'kilo':
|
||||
case 'kilogram':
|
||||
return 0.1;
|
||||
case 'ml':
|
||||
return 50;
|
||||
case 'cl':
|
||||
return 1;
|
||||
case 'dl':
|
||||
return 0.5;
|
||||
case 'l':
|
||||
case 'liter':
|
||||
case 'litre':
|
||||
return 0.1;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// 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);
|
||||
|
||||
/// A [ListTile] wrapped in a swipe-to-adjust widget.
|
||||
///
|
||||
/// • Swipe **right** (+) → adds 1 unit to [item.quantity] via PATCH.
|
||||
/// • Swipe **left** (−) → consumes 1 unit via the consume endpoint,
|
||||
/// preserving consumption history.
|
||||
/// • Swipe **right** (+) → adds one unit-appropriate step via PATCH.
|
||||
/// • Swipe **left** (−) → consumes one unit-appropriate step via the
|
||||
/// consume endpoint, preserving consumption history.
|
||||
///
|
||||
/// The step size is determined by the item's unit (e.g. 50 g, 0.1 kg, 1 st).
|
||||
/// A small swipe-hint icon is shown at the start of the subtitle so users
|
||||
/// know the gesture is available without any extra instruction.
|
||||
class SwipeableInventoryTile extends ConsumerStatefulWidget {
|
||||
@@ -58,6 +92,7 @@ class _SwipeableInventoryTileState
|
||||
void _snapBack() => setState(() => _drag = 0);
|
||||
|
||||
Future<void> _adjust(int direction) async {
|
||||
final step = _stepForUnit(widget.item.unit);
|
||||
setState(() => _acting = true);
|
||||
try {
|
||||
final token = await ref.read(authStateProvider.future);
|
||||
@@ -67,16 +102,17 @@ class _SwipeableInventoryTileState
|
||||
// Increase: direct PATCH with new quantity.
|
||||
await repo.updateInventoryItem(
|
||||
widget.item.id,
|
||||
{'quantity': widget.item.quantity + 1},
|
||||
{'quantity': widget.item.quantity + step},
|
||||
token: token,
|
||||
);
|
||||
} else {
|
||||
// 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;
|
||||
await repo.consumeInventoryItem(
|
||||
widget.item.id,
|
||||
amountUsed: 1,
|
||||
amountUsed: consume,
|
||||
token: token,
|
||||
);
|
||||
}
|
||||
@@ -103,6 +139,10 @@ class _SwipeableInventoryTileState
|
||||
final rightProgress = (_drag / _threshold).clamp(0.0, 1.0);
|
||||
final leftProgress = (-_drag / _threshold).clamp(0.0, 1.0);
|
||||
|
||||
final step = _stepForUnit(widget.item.unit);
|
||||
final stepLabel = _fmtStep(step);
|
||||
final unit = widget.item.unit;
|
||||
|
||||
return GestureDetector(
|
||||
onHorizontalDragUpdate: _onUpdate,
|
||||
onHorizontalDragEnd: _onEnd,
|
||||
@@ -131,7 +171,7 @@ class _SwipeableInventoryTileState
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
'+1',
|
||||
'+$stepLabel $unit',
|
||||
style: theme.textTheme.labelSmall?.copyWith(
|
||||
color: colorScheme.onPrimaryContainer,
|
||||
fontWeight: FontWeight.bold,
|
||||
@@ -167,7 +207,7 @@ class _SwipeableInventoryTileState
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
'−1',
|
||||
'−$stepLabel $unit',
|
||||
style: theme.textTheme.labelSmall?.copyWith(
|
||||
color: colorScheme.onTertiaryContainer,
|
||||
fontWeight: FontWeight.bold,
|
||||
|
||||
Reference in New Issue
Block a user