EnakPoint & EnakCoin wallet, PIN, outlet, order, community, reward
- Wallet EnakPoint & EnakCoin: beranda, riwayat, saldo kedaluwarsa, kode bayar, tukar EnakCoin, transfer - PIN (buat, ganti, lupa), outlet, riwayat order, game spin - Halaman community, webview, coming soon, dan ikon menu beranda baru - Redesign Reward Saya: kartu tiket, filter chip, detail kode + QR - Hapus customer point loader, menu, dan checkout lama - Base URL ke enaklo-pos-api.altru.id Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
5954510b93
commit
f5e3075205
@@ -0,0 +1,226 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import '../../../../common/theme/theme.dart';
|
||||
import '../../../../sample/community_sample_data.dart';
|
||||
import '../community_ui.dart';
|
||||
|
||||
class CommunityEventCard extends StatelessWidget {
|
||||
const CommunityEventCard({
|
||||
super.key,
|
||||
required this.event,
|
||||
required this.isGoing,
|
||||
required this.onToggle,
|
||||
});
|
||||
|
||||
final CommunityEvent event;
|
||||
final bool isGoing;
|
||||
final VoidCallback onToggle;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final attendeeCount = event.attendeeCount + (isGoing ? 1 : 0);
|
||||
final remaining = event.quota - attendeeCount;
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.fromLTRB(16, 0, 16, 16),
|
||||
decoration: communityCardDecoration(radius: 24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(24),
|
||||
),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 2.2,
|
||||
child: Image.asset(event.image, fit: BoxFit.cover),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 12,
|
||||
top: 12,
|
||||
child: _DateBadge(date: event.startAt),
|
||||
),
|
||||
if (event.reward != null)
|
||||
Positioned(
|
||||
right: 12,
|
||||
top: 12,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
vertical: 6,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.white.withOpacity(0.92),
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
),
|
||||
child: Text(
|
||||
'🎁 ${event.reward}',
|
||||
style: AppStyle.xs.copyWith(fontWeight: FontWeight.w700),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 14, 16, 16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
event.title,
|
||||
style: AppStyle.lg.copyWith(fontWeight: FontWeight.w700),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
_InfoRow(
|
||||
icon: Icons.schedule_rounded,
|
||||
text:
|
||||
'${DateFormat('EEEE, d MMM', 'id_ID').format(event.startAt)}'
|
||||
' · ${DateFormat('HH:mm', 'id_ID').format(event.startAt)}',
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
_InfoRow(icon: Icons.place_outlined, text: event.location),
|
||||
const SizedBox(height: 14),
|
||||
Row(
|
||||
children: [
|
||||
CommunityAvatarStack(members: event.attendees),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'$attendeeCount akan hadir',
|
||||
style: AppStyle.xs.copyWith(
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
remaining > 0
|
||||
? 'Sisa $remaining kursi'
|
||||
: 'Kuota penuh',
|
||||
style: AppStyle.xs.copyWith(
|
||||
fontSize: 10,
|
||||
color: remaining <= 5
|
||||
? AppColor.primary
|
||||
: CommunityColor.muted,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
_GoingButton(isGoing: isGoing, onTap: onToggle),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DateBadge extends StatelessWidget {
|
||||
const _DateBadge({required this.date});
|
||||
|
||||
final DateTime date;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: 48,
|
||||
padding: const EdgeInsets.symmetric(vertical: 6),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.white.withOpacity(0.95),
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
DateFormat('d', 'id_ID').format(date),
|
||||
style: AppStyle.xl.copyWith(
|
||||
height: 1.1,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
DateFormat('MMM', 'id_ID').format(date).toUpperCase(),
|
||||
style: AppStyle.xs.copyWith(
|
||||
fontSize: 10,
|
||||
color: AppColor.primary,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _InfoRow extends StatelessWidget {
|
||||
const _InfoRow({required this.icon, required this.text});
|
||||
|
||||
final IconData icon;
|
||||
final String text;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
Icon(icon, size: 15, color: CommunityColor.muted),
|
||||
const SizedBox(width: 6),
|
||||
Expanded(
|
||||
child: Text(
|
||||
text,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: AppStyle.sm.copyWith(
|
||||
color: CommunityColor.muted,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _GoingButton extends StatelessWidget {
|
||||
const _GoingButton({required this.isGoing, required this.onTap});
|
||||
|
||||
final bool isGoing;
|
||||
final VoidCallback onTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
decoration: BoxDecoration(
|
||||
color: isGoing ? CommunityColor.blush : AppColor.primary,
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
),
|
||||
child: Material(
|
||||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
onTap: onTap,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Text(
|
||||
isGoing ? 'Terdaftar ✓' : 'Ikut',
|
||||
style: AppStyle.sm.copyWith(
|
||||
color: isGoing ? AppColor.primary : AppColor.white,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user