From c6230abd5cf5ac8beb3a2e3565e015f075c74bde Mon Sep 17 00:00:00 2001 From: onie Date: Sun, 18 Oct 2026 00:28:18 +0700 Subject: [PATCH] v1.2.0: foto produk di kasir (grid + keranjang) + fix MIME jpg->jpeg --- lib/screens/kasir_screen.dart | 57 ++++++++++++++++++---------------- lib/screens/produk_screen.dart | 4 ++- pubspec.yaml | 2 +- 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/lib/screens/kasir_screen.dart b/lib/screens/kasir_screen.dart index b71624d..7e4fe74 100644 --- a/lib/screens/kasir_screen.dart +++ b/lib/screens/kasir_screen.dart @@ -8,6 +8,7 @@ import '../models/product.dart'; import '../models/sale.dart'; import '../state/app_state.dart'; import '../services/printer_service.dart'; +import 'produk_screen.dart' show productImageUrl; import '../utils/colors.dart'; import '../utils/format.dart'; import '../utils/rupiah_input.dart'; @@ -1138,19 +1139,7 @@ class _CartSheetContent extends StatelessWidget { padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), child: Row( children: [ - CircleAvatar( - radius: 18, - backgroundColor: kAccent.withValues(alpha: 0.15), - child: Text( - line.product.name.isNotEmpty - ? line.product.name[0].toUpperCase() - : '?', - style: TextStyle( - color: kAccent, - fontWeight: FontWeight.w700, - fontSize: 13), - ), - ), + _KasirAvatar(product: line.product, radius: 18), const SizedBox(width: 12), Expanded( child: Column( @@ -1490,19 +1479,7 @@ class _ProductCard extends StatelessWidget { children: [ Row( children: [ - CircleAvatar( - radius: 18, - backgroundColor: kAccent.withValues(alpha: 0.15), - child: Text( - product.name.isNotEmpty - ? product.name[0].toUpperCase() - : '?', - style: TextStyle( - color: kAccent, - fontWeight: FontWeight.w700, - ), - ), - ), + _KasirAvatar(product: product, radius: 18), const Spacer(), Container( padding: const EdgeInsets.symmetric( @@ -1579,6 +1556,34 @@ class _ProductCard extends StatelessWidget { } } +/// Avatar produk di kasir: foto jika ada, fallback huruf pertama nama. +class _KasirAvatar extends StatelessWidget { + final Product product; + final double radius; + const _KasirAvatar({required this.product, this.radius = 18}); + + @override + Widget build(BuildContext context) { + final url = productImageUrl(product.imagePath); + return CircleAvatar( + radius: radius, + backgroundColor: kAccent.withValues(alpha: 0.15), + backgroundImage: url != null ? NetworkImage(url) : null, + child: url == null + ? Text( + product.name.isNotEmpty + ? product.name[0].toUpperCase() + : '?', + style: TextStyle( + color: kAccent, + fontWeight: FontWeight.w700, + fontSize: radius * 0.75), + ) + : null, + ); + } +} + class _QtyButton extends StatelessWidget { final IconData icon; final VoidCallback onTap; diff --git a/lib/screens/produk_screen.dart b/lib/screens/produk_screen.dart index deb5093..c1fc0ce 100644 --- a/lib/screens/produk_screen.dart +++ b/lib/screens/produk_screen.dart @@ -40,12 +40,14 @@ Future pickAndUploadProductImage(BuildContext context, final raw = picked.name.substring(dot + 1).toLowerCase(); if (['jpg', 'jpeg', 'png', 'webp'].contains(raw)) ext = raw; } + // MIME resmi: jpg -> image/jpeg (bukan image/jpg, ditolak server 415) + final mime = ext == 'jpg' ? 'image/jpeg' : 'image/$ext'; final path = 'prod-${DateTime.now().millisecondsSinceEpoch}.$ext'; await Supabase.instance.client.storage .from(kProductImageBucket) .uploadBinary(path, bytes, - fileOptions: FileOptions(contentType: 'image/$ext', upsert: true)); + fileOptions: FileOptions(contentType: mime, upsert: true)); return path; } catch (e) { if (context.mounted) { diff --git a/pubspec.yaml b/pubspec.yaml index 6ac24cf..45c4d80 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.1.0+4 +version: 1.2.0+5 environment: sdk: ^3.9.2