Tab Community, tombol Bayar di navbar, logo placeholder, fix crash PIN

- Bottom navbar: Home, Pesanan, Bayar (tombol tengah ke kode bayar),
  Community, Profil; menu EnakCommunity di beranda pindah ke tab
- Image placeholder: logo Enaklo diperbesar, ilustrasi gelas dihapus
- Fix assertion Navigator saat PIN gagal karena error non-PIN: flushbar
  kini tampil lewat onFailure setelah sheet PIN tertutup (bayar, tukar,
  transfer)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
efrilm
2026-10-01 02:05:49 +07:00
co-authored by Claude Opus 5.5
parent f5e3075205
commit bc751246d8
11 changed files with 151 additions and 144 deletions
@@ -22,7 +22,7 @@ class ImagePlaceholder extends StatelessWidget {
final containerWidth = width ?? constraints.maxWidth;
final containerHeight = height ?? constraints.maxHeight;
// Calculate the minimum dimension to determine if we should show simple or detailed version
// Logo mengikuti sisi terpendek placeholder
final minDimension = math.min(
containerWidth == double.infinity ? containerHeight : containerWidth,
containerHeight == double.infinity ? containerWidth : containerHeight,
@@ -42,129 +42,44 @@ class ImagePlaceholder extends StatelessWidget {
)
: null,
),
child: Center(
child: minDimension < 150
? _buildSimpleVersion(minDimension)
: _buildDetailedVersion(minDimension),
),
child: Center(child: _buildLogo(context, minDimension)),
);
},
);
}
// Simple version for small sizes (< 100px)
Widget _buildSimpleVersion(double size) {
final iconSize = (size * 0.4).clamp(16.0, 32.0);
final fontSize = (size * 0.12).clamp(8.0, 12.0);
return Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: iconSize * 1.5,
height: iconSize * 1.5,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(iconSize * 0.75),
),
child: Center(
child: Assets.images.logo.image(
width: iconSize,
height: iconSize,
fit: BoxFit.contain,
),
),
),
if (size > 50) ...[
SizedBox(height: size * 0.05),
Text(
'Enaklo',
style: TextStyle(
color: AppColor.primary,
fontSize: fontSize,
fontWeight: FontWeight.bold,
),
),
],
],
);
}
// Detailed version for larger sizes (>= 100px)
Widget _buildDetailedVersion(double minDimension) {
final scaleFactor = minDimension / 200; // Base scale factor
// Proportional sizes
final illustrationSize = (120 * scaleFactor).clamp(80.0, 120.0);
final illustrationHeight = (160 * scaleFactor).clamp(100.0, 160.0);
final handWidth = (60 * scaleFactor).clamp(30.0, 60.0);
final handHeight = (80 * scaleFactor).clamp(40.0, 80.0);
final cupWidth = (70 * scaleFactor).clamp(35.0, 70.0);
final cupHeight = (90 * scaleFactor).clamp(45.0, 90.0);
final logoSize = (40 * scaleFactor).clamp(20.0, 40.0);
final fontSize = (12 * scaleFactor).clamp(8.0, 12.0);
Widget _buildLogo(BuildContext context, double minDimension) {
final size = (minDimension * 0.6).clamp(28.0, 140.0);
// Aset logo 1024px; decode seukuran tampilan saja.
final cacheSize = (size * 1.2 * MediaQuery.devicePixelRatioOf(context))
.round();
return Container(
width: illustrationSize,
height: illustrationHeight,
width: size,
height: size,
padding: EdgeInsets.all(size * 0.04),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(illustrationSize / 2),
),
child: Stack(
children: [
// Hand
Positioned(
bottom: illustrationHeight * 0.125, // 20/160 ratio
left: illustrationSize * 0.25, // 30/120 ratio
child: Container(
width: handWidth,
height: handHeight,
decoration: BoxDecoration(
color: const Color(0xFFFFDBB3),
borderRadius: BorderRadius.circular(handWidth / 2),
),
),
),
// Coffee cup
Positioned(
top: illustrationHeight * 0.1875, // 30/160 ratio
left: illustrationSize * 0.208, // 25/120 ratio
child: Container(
width: cupWidth,
height: cupHeight,
decoration: BoxDecoration(
color: const Color(0xFFF4E4BC),
borderRadius: BorderRadius.circular(
math.max(8.0, 10 * scaleFactor),
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Logo
Assets.images.logo.image(
width: logoSize,
height: logoSize,
fit: BoxFit.contain,
),
SizedBox(height: math.max(4.0, 8 * scaleFactor)),
if (cupHeight > 50) // Only show text if cup is big enough
Text(
'Enaklo',
style: TextStyle(
color: AppColor.primary,
fontSize: fontSize,
fontWeight: FontWeight.bold,
),
),
],
),
),
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.08),
blurRadius: size * 0.1,
offset: Offset(0, size * 0.03),
),
],
),
child: ClipOval(
// Sudut aset logo berlatar gelap; diperbesar sedikit supaya yang
// terlihat hanya lingkaran merahnya.
child: Transform.scale(
scale: 1.2,
child: Assets.images.logo.image(
fit: BoxFit.cover,
cacheWidth: cacheSize,
),
),
),
);
}
}