feat: make server owner of tabs
This commit is contained in:
@@ -9,7 +9,6 @@ import '../../l10n/app_localizations.dart';
|
||||
import '../../l10n/app_localizations_helpers.dart';
|
||||
import '../../models/product.dart';
|
||||
import '../../models/remote_command.dart';
|
||||
import '../../services/product_service.dart';
|
||||
import '../../utils/app_updater.dart';
|
||||
import '../../viewmodels/admin_pin_view_model.dart';
|
||||
import '../../viewmodels/bar_screen_view_model.dart';
|
||||
@@ -85,15 +84,9 @@ class _BarScreenViewState extends State<BarScreenView> {
|
||||
await viewModel.addProductToSelectedTab(product);
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
e is InsufficientStockException
|
||||
? l10n.productOutOfStock
|
||||
: l10n.couldNotAddProductToTab,
|
||||
),
|
||||
),
|
||||
);
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text(l10n.couldNotAddProductToTab)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,10 +101,6 @@ class _BarScreenViewState extends State<BarScreenView> {
|
||||
final viewModel = context.watch<BarScreenViewModel>();
|
||||
final productsViewModel = context.watch<ProductListViewModel>();
|
||||
final settings = context.watch<SettingsViewModel>().settings;
|
||||
final stockByProductId = {
|
||||
for (final product in productsViewModel.products)
|
||||
if (!product.infiniteStock) product.id: product.stockQuantity,
|
||||
};
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
@@ -206,7 +195,6 @@ class _BarScreenViewState extends State<BarScreenView> {
|
||||
tabs: viewModel.tabs,
|
||||
selectedTab: viewModel.selectedTab,
|
||||
selectedTabId: viewModel.selectedTabId,
|
||||
stockByProductId: stockByProductId,
|
||||
showSearch: _showSearch,
|
||||
onTabSelected: viewModel.selectTab,
|
||||
onItemQuantityChanged: viewModel.changeItemQuantity,
|
||||
|
||||
@@ -3,19 +3,16 @@ import 'package:flutter/material.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../../models/bar_tab.dart';
|
||||
import '../../models/tab_item.dart';
|
||||
import '../../services/product_service.dart';
|
||||
import '../../utils/money.dart';
|
||||
|
||||
class SelectedTabDetails extends StatelessWidget {
|
||||
final BarTab tab;
|
||||
final Map<String, int> stockByProductId;
|
||||
final Future<void> Function(TabItem item, int delta) onItemQuantityChanged;
|
||||
final VoidCallback onCloseTabPressed;
|
||||
|
||||
const SelectedTabDetails({
|
||||
super.key,
|
||||
required this.tab,
|
||||
required this.stockByProductId,
|
||||
required this.onItemQuantityChanged,
|
||||
required this.onCloseTabPressed,
|
||||
});
|
||||
@@ -55,7 +52,6 @@ class SelectedTabDetails extends StatelessWidget {
|
||||
|
||||
return TabItemRow(
|
||||
item: item,
|
||||
stockByProductId: stockByProductId,
|
||||
onQuantityChanged: onItemQuantityChanged,
|
||||
);
|
||||
},
|
||||
@@ -108,13 +104,11 @@ class SelectedTabDetails extends StatelessWidget {
|
||||
|
||||
class TabItemRow extends StatelessWidget {
|
||||
final TabItem item;
|
||||
final Map<String, int> stockByProductId;
|
||||
final Future<void> Function(TabItem item, int delta) onQuantityChanged;
|
||||
|
||||
const TabItemRow({
|
||||
super.key,
|
||||
required this.item,
|
||||
required this.stockByProductId,
|
||||
required this.onQuantityChanged,
|
||||
});
|
||||
|
||||
@@ -125,23 +119,15 @@ class TabItemRow extends StatelessWidget {
|
||||
await onQuantityChanged(item, delta);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
e is InsufficientStockException
|
||||
? l10n.productOutOfStock
|
||||
: l10n.couldNotUpdateQuantity,
|
||||
),
|
||||
),
|
||||
);
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text(l10n.couldNotUpdateQuantity)));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
final availableStock = stockByProductId[item.productId];
|
||||
final canIncrease = availableStock == null || availableStock > 0;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
@@ -188,9 +174,7 @@ class TabItemRow extends StatelessWidget {
|
||||
),
|
||||
IconButton(
|
||||
visualDensity: VisualDensity.compact,
|
||||
onPressed: canIncrease
|
||||
? () => _changeQuantity(context, 1)
|
||||
: null,
|
||||
onPressed: () => _changeQuantity(context, 1),
|
||||
icon: const Icon(Icons.add_rounded, size: 18),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -39,7 +39,6 @@ class TabPanel extends StatefulWidget {
|
||||
final List<BarTab> tabs;
|
||||
final BarTab? selectedTab;
|
||||
final String? selectedTabId;
|
||||
final Map<String, int> stockByProductId;
|
||||
final bool showSearch;
|
||||
final ValueChanged<String> onTabSelected;
|
||||
final Future<void> Function(TabItem item, int delta) onItemQuantityChanged;
|
||||
@@ -52,7 +51,6 @@ class TabPanel extends StatefulWidget {
|
||||
required this.tabs,
|
||||
required this.selectedTab,
|
||||
required this.selectedTabId,
|
||||
required this.stockByProductId,
|
||||
required this.showSearch,
|
||||
required this.onTabSelected,
|
||||
required this.onItemQuantityChanged,
|
||||
@@ -409,8 +407,6 @@ class _TabPanelState extends State<TabPanel> {
|
||||
)
|
||||
: SelectedTabDetails(
|
||||
tab: widget.selectedTab!,
|
||||
stockByProductId:
|
||||
widget.stockByProductId,
|
||||
onItemQuantityChanged:
|
||||
widget.onItemQuantityChanged,
|
||||
onCloseTabPressed:
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../../models/product.dart';
|
||||
|
||||
class ProductTile extends StatelessWidget {
|
||||
@@ -24,8 +23,6 @@ class ProductTile extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final scheme = theme.colorScheme;
|
||||
final l10n = AppLocalizations.of(context);
|
||||
|
||||
final outOfStock = product.isOutOfStock;
|
||||
final lowStock = !outOfStock && product.isLowStock;
|
||||
|
||||
@@ -50,13 +47,14 @@ class ProductTile extends StatelessWidget {
|
||||
child: Material(
|
||||
color: theme.cardTheme.color ?? scheme.surface,
|
||||
child: InkWell(
|
||||
onTap: enabled && !outOfStock ? onTap : null,
|
||||
// Never blocked by stock: the count may simply be off
|
||||
onTap: enabled ? onTap : null,
|
||||
onLongPress: onLongPress,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Opacity(
|
||||
opacity: outOfStock ? 0.35 : (enabled ? 1 : 0.4),
|
||||
opacity: enabled ? 1 : 0.4,
|
||||
child: hasImage
|
||||
? Image.file(
|
||||
File(product.imagePath!),
|
||||
@@ -90,28 +88,6 @@ class ProductTile extends StatelessWidget {
|
||||
right: 10,
|
||||
child: _StockBadge(product: product),
|
||||
),
|
||||
|
||||
if (outOfStock)
|
||||
Center(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 6,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: scheme.error.withValues(alpha: 0.9),
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
),
|
||||
child: Text(
|
||||
l10n.outOfStock,
|
||||
style: TextStyle(
|
||||
color: scheme.onError,
|
||||
fontWeight: FontWeight.w800,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -140,16 +116,15 @@ class _StockBadge extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
|
||||
if (product.isOutOfStock) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final low = product.isLowStock;
|
||||
final out = product.isOutOfStock;
|
||||
final low = !out && product.isLowStock;
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: low
|
||||
color: out
|
||||
? scheme.error.withValues(alpha: 0.9)
|
||||
: low
|
||||
? Colors.amber.withValues(alpha: 0.9)
|
||||
: scheme.primary.withValues(alpha: 0.85),
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
@@ -159,7 +134,11 @@ class _StockBadge extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w800,
|
||||
color: low ? Colors.black : scheme.onPrimary,
|
||||
color: out
|
||||
? scheme.onError
|
||||
: low
|
||||
? Colors.black
|
||||
: scheme.onPrimary,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user