import 'package:flutter/material.dart'; import '../../../common/extension/extension.dart'; import '../../../common/theme/theme.dart'; import '../../../sample/shop_sample_data.dart'; /// "320 terjual" / "1,2rb terjual". String formatSoldCount(int count) { if (count < 1000) return '$count terjual'; final thousands = (count / 100).floor() / 10; final text = thousands == thousands.roundToDouble() ? thousands.toInt().toString() : thousands.toString().replaceAll('.', ','); return '${text}rb terjual'; } /// Grid 2 kolom produk; tinggi kartu = lebar gambar + bagian teks. SliverGridDelegate shopProductGridDelegate(BuildContext context) { final itemWidth = (MediaQuery.sizeOf(context).width - 32 - 12) / 2; return SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, mainAxisSpacing: 12, crossAxisSpacing: 12, mainAxisExtent: itemWidth + shopCardInfoHeight(context), ); } /// Tinggi bagian teks kartu produk, ikut skala font sistem supaya tidak /// terpotong. double shopCardInfoHeight(BuildContext context) => MediaQuery.textScalerOf(context).scale(118); /// Gambar produk: emoji di atas latar warna produk. class ShopProductImage extends StatelessWidget { const ShopProductImage({ super.key, required this.product, this.emojiSize = 56, }); final ShopProduct product; final double emojiSize; @override Widget build(BuildContext context) { return ColoredBox( color: Color(product.tint), child: Center( child: Text(product.emoji, style: TextStyle(fontSize: emojiSize)), ), ); } } /// Label pojok kartu seperti "Terlaris" atau "Baru". class ShopTagBadge extends StatelessWidget { const ShopTagBadge({super.key, required this.tag}); final ShopTag tag; @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration( color: switch (tag) { ShopTag.bestSeller => AppColor.primary, ShopTag.newArrival => AppColor.info, }, borderRadius: BorderRadius.circular(6), ), child: Text( tag.label, style: AppStyle.xs.copyWith( color: AppColor.textWhite, fontWeight: FontWeight.w800, ), ), ); } } /// Harga akhir, dengan harga coret dan persen potongan bila diskon. class ShopPrice extends StatelessWidget { const ShopPrice({super.key, required this.product, this.large = false}); final ShopProduct product; final bool large; @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text( product.finalPrice.currencyFormatRp, style: (large ? AppStyle.h5 : AppStyle.md).copyWith( fontWeight: FontWeight.w800, ), ), if (product.isDiscounted) ...[ SizedBox(height: large ? 4 : 2), Row( mainAxisSize: MainAxisSize.min, children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 1), decoration: BoxDecoration( color: AppColor.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(4), ), child: Text( '${product.discountPercent}%', style: (large ? AppStyle.sm : AppStyle.xs).copyWith( color: AppColor.primary, fontWeight: FontWeight.w800, ), ), ), const SizedBox(width: 6), Flexible( child: Text( product.price.currencyFormatRp, maxLines: 1, overflow: TextOverflow.ellipsis, style: (large ? AppStyle.sm : AppStyle.xs).copyWith( color: AppColor.textSecondary, decoration: TextDecoration.lineThrough, ), ), ), ], ), ], ], ); } }