feat: move inventory to own view model, add signing keys
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:kooltab2/models/product.dart';
|
||||
|
||||
|
||||
class ProductTile extends StatelessWidget {
|
||||
final Product product;
|
||||
final bool enabled;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const ProductTile({
|
||||
required this.product,
|
||||
required this.enabled,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
bool get _hasImage {
|
||||
final imagePath = product.imagePath;
|
||||
|
||||
if (imagePath == null || imagePath.isEmpty) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return File(imagePath).existsSync();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final scheme = theme.colorScheme;
|
||||
|
||||
final outOfStock = product.stockQuantity <= 0;
|
||||
final lowStock =
|
||||
product.stockQuantity > 0 &&
|
||||
product.stockQuantity <= product.lowStockThreshold; // adjust name
|
||||
|
||||
final borderColor = outOfStock
|
||||
? scheme.error.withValues(alpha: 0.7)
|
||||
: lowStock
|
||||
? Colors.amber.withValues(alpha: 0.9)
|
||||
: scheme.onSurface.withValues(alpha: 0.08);
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(
|
||||
color: borderColor,
|
||||
width: outOfStock || lowStock ? 2 : 1,
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
child: Material(
|
||||
color: theme.cardTheme.color ?? scheme.surface,
|
||||
child: InkWell(
|
||||
onTap: enabled && !outOfStock ? onTap : null,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Opacity(
|
||||
opacity: outOfStock ? 0.35 : (enabled ? 1 : 0.4),
|
||||
child: _hasImage
|
||||
? Image.file(
|
||||
File(product.imagePath!),
|
||||
fit: BoxFit.scaleDown,
|
||||
)
|
||||
: Center(
|
||||
child: Icon(
|
||||
Icons.image_not_supported_outlined,
|
||||
size: 34,
|
||||
color: scheme.onSurface.withValues(alpha: 0.3),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
if (_hasImage)
|
||||
Positioned.fill(
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Colors.transparent,
|
||||
Colors.black.withValues(alpha: 0.35),
|
||||
],
|
||||
stops: const [0.6, 1.0],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Stock badge
|
||||
Positioned(
|
||||
top: 10,
|
||||
right: 10,
|
||||
child: _StockBadge(
|
||||
product: product,
|
||||
),
|
||||
),
|
||||
|
||||
// Out of stock overlay
|
||||
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(
|
||||
'OUT OF STOCK',
|
||||
style: TextStyle(
|
||||
color: scheme.onError,
|
||||
fontWeight: FontWeight.w800,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _StockBadge extends StatelessWidget {
|
||||
final Product product;
|
||||
|
||||
const _StockBadge({
|
||||
required this.product,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
|
||||
if (product.stockQuantity <= 0) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final low =
|
||||
product.stockQuantity <= product.lowStockThreshold; // adjust name
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8,
|
||||
vertical: 4,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: low
|
||||
? Colors.amber.withValues(alpha: 0.9)
|
||||
: scheme.primary.withValues(alpha: 0.85),
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
),
|
||||
child: Text(
|
||||
'${product.stockQuantity}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w800,
|
||||
color: low ? Colors.black : scheme.onPrimary,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user