Files
efrilmandClaude Opus 5.5 e273785268 EnakShop: katalog toko online
- Beranda toko: pencarian, banner promo, grid kategori, produk promo,
  dan rekomendasi
- Halaman kategori dengan urutan terlaris/terbaru/termurah/termahal
- Detail produk: harga diskon, varian, info, deskripsi, produk serupa
- Data contoh 14 produk dan 3 banner; keranjang menyusul
- DetailSection dan NumberedStep jadi komponen bersama
- Tinggi banner EnakPromo dan EnakShop ikut skala font sistem

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 02:47:47 +07:00

369 lines
9.2 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Models
//
// EnakShop adalah toko online. Tahap ini baru katalog; keranjang dan checkout
// menyusul setelah API toko tersedia.
enum ShopCategory {
frozen('Makanan Beku', '🥟'),
sauce('Sambal & Bumbu', '🌶️'),
coffee('Kopi & Minuman', '☕'),
noodle('Mie & Ramen', '🍜'),
snack('Camilan', '🍪'),
merch('Merchandise', '🛍️'),
hampers('Hampers', '🎁');
const ShopCategory(this.label, this.emoji);
final String label;
final String emoji;
}
/// Label pojok kartu produk.
enum ShopTag {
bestSeller('Terlaris'),
newArrival('Baru');
const ShopTag(this.label);
final String label;
}
class ShopProduct {
final String id;
final String name;
final ShopCategory category;
final int price;
/// Harga setelah diskon; `null` bila tidak sedang diskon.
final int? discountPrice;
final String emoji;
/// Warna latar gambar produk, ARGB.
final int tint;
/// Berat atau isi, mis. "500 g" atau "Isi 25 butir".
final String unit;
final String description;
/// Judul pilihan varian, mis. "Ukuran" atau "Level pedas".
final String variantLabel;
final List<String> variants;
final int soldCount;
final int stock;
final ShopTag? tag;
final DateTime addedAt;
const ShopProduct({
required this.id,
required this.name,
required this.category,
required this.price,
required this.emoji,
required this.tint,
required this.unit,
required this.description,
required this.soldCount,
required this.stock,
required this.addedAt,
this.discountPrice,
this.variantLabel = 'Varian',
this.variants = const [],
this.tag,
});
bool get isDiscounted => discountPrice != null;
int get finalPrice => discountPrice ?? price;
/// Persen potongan, dibulatkan.
int get discountPercent =>
isDiscounted ? ((price - discountPrice!) * 100 / price).round() : 0;
}
/// Banner promo di beranda toko; mengarah ke satu kategori.
class ShopPromo {
final String id;
final String title;
final String subtitle;
final ShopCategory category;
/// Warna gradasi banner, ARGB.
final List<int> gradient;
const ShopPromo({
required this.id,
required this.title,
required this.subtitle,
required this.category,
required this.gradient,
});
}
// Sample Data
DateTime _daysAgo(int days) => DateTime.now().subtract(Duration(days: days));
/// Getter, bukan `final`, supaya perubahan data langsung terbaca saat hot
/// reload (variabel global yang sudah terisi tidak diisi ulang).
List<ShopPromo> get shopPromoSamples => const [
ShopPromo(
id: 'sp1',
title: 'Diskon s.d. 20% Makanan Beku',
subtitle: 'Stok bakso & dimsum di rumah',
category: ShopCategory.frozen,
gradient: [0xFFD90000, 0xFF990000],
),
ShopPromo(
id: 'sp2',
title: 'Hampers Mulai Rp 299 Ribu',
subtitle: 'Kirim rasa Nusantara untuk orang tersayang',
category: ShopCategory.hampers,
gradient: [0xFF43A047, 0xFF1B5E20],
),
ShopPromo(
id: 'sp3',
title: 'Merchandise Diskon s.d. 15%',
subtitle: 'Tumbler, kaos, dan tote bag Enaklo',
category: ShopCategory.merch,
gradient: [0xFFF59E0B, 0xFFC2410C],
),
];
List<ShopProduct> get shopSamples => [
ShopProduct(
id: 's1',
name: 'Bakso Sapi Frozen Bakso 343',
category: ShopCategory.frozen,
price: 65000,
discountPrice: 52000,
emoji: '🍲',
tint: 0xFFF6D5D0,
unit: 'Isi 25 butir',
variantLabel: 'Ukuran',
variants: ['Isi 25 butir', 'Isi 50 butir'],
description:
'Bakso sapi resep Bakso 343, dibekukan segera setelah dibuat. Cukup '
'rebus 5 menit. Tahan 3 bulan di freezer.',
soldCount: 320,
stock: 48,
tag: ShopTag.bestSeller,
addedAt: _daysAgo(60),
),
ShopProduct(
id: 's2',
name: 'Dimsum Ayam Frozen',
category: ShopCategory.frozen,
price: 48000,
emoji: '🥟',
tint: 0xFFF3E6CF,
unit: 'Isi 20 pcs',
description:
'Dimsum ayam udang dengan kulit tipis. Kukus 10 menit dari beku, '
'sajikan dengan sambal.',
soldCount: 85,
stock: 30,
tag: ShopTag.newArrival,
addedAt: _daysAgo(5),
),
ShopProduct(
id: 's3',
name: 'Sambal Woku Pedas',
category: ShopCategory.sauce,
price: 35000,
discountPrice: 29000,
emoji: '🌶️',
tint: 0xFFFBDCC8,
unit: '200 g',
variantLabel: 'Level pedas',
variants: ['Level 2', 'Level 3', 'Level 5'],
description:
'Sambal khas Woku Pedas dengan cabai, kemangi, dan rempah Manado. '
'Tanpa pengawet, simpan di kulkas setelah dibuka.',
soldCount: 540,
stock: 120,
tag: ShopTag.bestSeller,
addedAt: _daysAgo(90),
),
ShopProduct(
id: 's4',
name: 'Bumbu Rica-Rica Instan',
category: ShopCategory.sauce,
price: 18000,
emoji: '🧂',
tint: 0xFFF7E2C8,
unit: '100 g',
description:
'Bumbu rica-rica siap pakai untuk 1 kg ayam atau ikan. Tinggal tumis '
'dan masak bersama bahan utama.',
soldCount: 140,
stock: 75,
addedAt: _daysAgo(40),
),
ShopProduct(
id: 's5',
name: 'Kopi Tumulu House Blend',
category: ShopCategory.coffee,
price: 85000,
emoji: '☕',
tint: 0xFFE8DCCF,
unit: '250 g',
variantLabel: 'Gilingan',
variants: ['Biji utuh', 'Bubuk halus', 'Bubuk kasar'],
description:
'Campuran arabika Gayo dan robusta Temanggung yang dipakai di Tumulu '
'Coffee. Cocok untuk kopi susu maupun kopi tubruk.',
soldCount: 410,
stock: 64,
tag: ShopTag.bestSeller,
addedAt: _daysAgo(120),
),
ShopProduct(
id: 's6',
name: 'Cold Brew Tumulu 1 Liter',
category: ShopCategory.coffee,
price: 75000,
discountPrice: 65000,
emoji: '🧋',
tint: 0xFFE2D6CC,
unit: '1 liter',
description:
'Kopi seduh dingin 18 jam, tinggal tuang ke es dan susu. Simpan di '
'kulkas, habiskan dalam 7 hari.',
soldCount: 95,
stock: 20,
addedAt: _daysAgo(20),
),
ShopProduct(
id: 's7',
name: 'Ramen Kit Shoyu Ramenmulu',
category: ShopCategory.noodle,
price: 79000,
discountPrice: 69000,
emoji: '🍜',
tint: 0xFFF5E1C8,
unit: '2 porsi',
description:
'Mie ramen segar, kuah shoyu pekat, chashu, dan telur ajitama untuk '
'2 porsi. Siap dalam 10 menit.',
soldCount: 150,
stock: 18,
tag: ShopTag.newArrival,
addedAt: _daysAgo(3),
),
ShopProduct(
id: 's8',
name: 'Mie Ramen Kering',
category: ShopCategory.noodle,
price: 32000,
emoji: '🍝',
tint: 0xFFF4EBD3,
unit: '500 g',
description:
'Mie ramen kering untuk 5 porsi, kenyal seperti mie segar. Rebus '
'3 menit.',
soldCount: 60,
stock: 90,
addedAt: _daysAgo(30),
),
ShopProduct(
id: 's9',
name: 'Keripik Kulit Ikan Pedas',
category: ShopCategory.snack,
price: 28000,
emoji: '🍘',
tint: 0xFFF6E7C1,
unit: '100 g',
description:
'Keripik kulit ikan renyah dengan bumbu woku pedas. Camilan pas '
'teman nonton.',
soldCount: 210,
stock: 55,
addedAt: _daysAgo(50),
),
ShopProduct(
id: 's10',
name: 'Nastar Keju Premium',
category: ShopCategory.snack,
price: 95000,
discountPrice: 85000,
emoji: '🍪',
tint: 0xFFF7E4B5,
unit: 'Toples 500 g',
description:
'Nastar selai nanas homemade dengan taburan keju edam. Tahan 1 bulan '
'dalam toples tertutup.',
soldCount: 130,
stock: 25,
addedAt: _daysAgo(15),
),
ShopProduct(
id: 's11',
name: 'Tumbler Enaklo 500 ml',
category: ShopCategory.merch,
price: 129000,
emoji: '🥤',
tint: 0xFFF3D3D3,
unit: '500 ml',
variantLabel: 'Warna',
variants: ['Merah', 'Hitam', 'Krem'],
description:
'Tumbler stainless dua lapis yang menjaga minuman tetap dingin sampai '
'12 jam. Tutup anti tumpah.',
soldCount: 75,
stock: 40,
tag: ShopTag.bestSeller,
addedAt: _daysAgo(70),
),
ShopProduct(
id: 's12',
name: 'Kaos "Enak Lho!"',
category: ShopCategory.merch,
price: 119000,
emoji: '👕',
tint: 0xFFE9E9E9,
unit: 'Katun combed 30s',
variantLabel: 'Ukuran',
variants: ['S', 'M', 'L', 'XL'],
description:
'Kaos katun yang adem dipakai seharian, dengan sablon "Enak Lho!" di '
'bagian depan.',
soldCount: 48,
stock: 32,
addedAt: _daysAgo(35),
),
ShopProduct(
id: 's13',
name: 'Tote Bag Kanvas Enaklo',
category: ShopCategory.merch,
price: 90000,
discountPrice: 76500,
emoji: '🛍️',
tint: 0xFFEDE3CF,
unit: '38 × 42 cm',
variantLabel: 'Warna',
variants: ['Natural', 'Hitam'],
description:
'Tote bag kanvas tebal dengan kantong dalam. Cukup untuk laptop 14 '
'inci.',
soldCount: 66,
stock: 3,
tag: ShopTag.newArrival,
addedAt: _daysAgo(8),
),
ShopProduct(
id: 's14',
name: 'Hampers Rasa Nusantara',
category: ShopCategory.hampers,
price: 350000,
discountPrice: 299000,
emoji: '🎁',
tint: 0xFFDCEBD6,
unit: 'Isi 5 produk',
description:
'Sambal Woku Pedas, Kopi Tumulu House Blend, Nastar Keju Premium, '
'Keripik Kulit Ikan Pedas, dan kartu ucapan dalam kotak kayu.',
soldCount: 34,
stock: 12,
tag: ShopTag.newArrival,
addedAt: _daysAgo(6),
),
];