Files
front-hokm/lib/feature/wallet/presentation/screen/lobby_screen.parts.dart
T
2026-07-10 00:56:58 +03:30

454 lines
15 KiB
Dart

// ویجت‌های خصوصیِ لابی (عنوان، دکمه‌ی بازی، کاشی‌ها، کارتِ روزانه، نوارِ بالا).
part of 'lobby_screen.dart';
/// عنوانِ لابی: تاجِ طلایی + نامِ بازی + زیرعنوان.
class _LobbyHeader extends StatelessWidget {
const _LobbyHeader();
@override
Widget build(BuildContext context) {
return Column(
children: const [
Icon(Icons.workspace_premium, color: AppColors.gold, size: 34),
SizedBox(height: 4),
GlowText('حاکم ایرانی', size: 36),
SizedBox(height: 2),
Text(
'بازیِ آنلاینِ حکم',
style: TextStyle(color: Colors.white54, fontSize: 13),
),
],
);
}
}
/// اکشنِ اصلی: بازیِ سریع (میزِ عمومی) — کارتِ بزرگِ برجسته.
class _PrimaryPlay extends StatelessWidget {
final VoidCallback onTap;
const _PrimaryPlay({required this.onTap});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 18),
decoration: BoxDecoration(
gradient: const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [AppColors.lapis, AppColors.lapisHi, AppColors.lapisLo],
),
borderRadius: BorderRadius.circular(20),
border: Border.all(color: AppColors.gold, width: 2),
boxShadow: [
BoxShadow(
color: AppColors.gold.withValues(alpha: 0.28),
blurRadius: 16,
),
const BoxShadow(
color: Colors.black54,
blurRadius: 10,
offset: Offset(0, 5),
),
],
),
child: Row(
children: [
Container(
width: 54,
height: 54,
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [AppColors.gold, AppColors.goldDark],
),
shape: BoxShape.circle,
),
child: const Icon(
Icons.play_arrow_rounded,
color: AppColors.lapisInk,
size: 36,
),
),
const SizedBox(width: 14),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
'بازی سریع',
style: TextStyle(
color: Colors.white,
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 2),
Text(
'ورود به میزِ عمومی',
style: TextStyle(color: Colors.white70, fontSize: 13),
),
],
),
const Spacer(),
const Icon(
Icons.arrow_forward_ios,
color: AppColors.gold,
size: 18,
),
],
),
),
);
}
}
/// کاشیِ اکشنِ ثانویه در گرید (آیکن + عنوان + زیرعنوان).
class _ActionTile extends StatelessWidget {
final IconData icon;
final String label;
final String sub;
final Color accent;
final VoidCallback onTap;
const _ActionTile({
required this.icon,
required this.label,
required this.sub,
required this.accent,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return Material(
color: Colors.transparent,
borderRadius: BorderRadius.circular(18),
child: InkWell(
borderRadius: BorderRadius.circular(18),
onTap: onTap,
child: Ink(
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
gradient: const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [AppColors.lapisHi, AppColors.lapisLo],
),
borderRadius: BorderRadius.circular(18),
border: Border.all(color: AppColors.goldDark, width: 1.2),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.all(9),
decoration: BoxDecoration(
color: accent.withValues(alpha: 0.18),
shape: BoxShape.circle,
border: Border.all(color: accent.withValues(alpha: 0.6)),
),
child: Icon(icon, color: accent, size: 22),
),
const Spacer(),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
label,
style: const TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 2),
Text(
sub,
style: const TextStyle(color: Colors.white54, fontSize: 11),
),
],
),
],
),
),
),
);
}
}
/// کارتِ هدیه‌ی روزانه با استریک (مثلِ دولینگو): شعله + تعدادِ روزهای پیاپی و
/// وضعیتِ قابلِ‌دریافت/دریافت‌شده.
class _DailyCard extends StatelessWidget {
final WalletEntity? wallet;
final VoidCallback onTap;
const _DailyCard({super.key, required this.wallet, required this.onTap});
@override
Widget build(BuildContext context) {
final w = wallet;
final streak = w?.dailyStreak ?? 0;
final ready = w?.dailyReady ?? true;
final next = w?.nextDaily ?? 200;
final colors =
ready
? const [AppColors.success, AppColors.successDark]
: const [AppColors.lapisHi, AppColors.lapisLo];
return Opacity(
opacity: ready ? 1 : 0.75,
child: Material(
color: Colors.transparent,
borderRadius: BorderRadius.circular(16),
child: InkWell(
borderRadius: BorderRadius.circular(16),
onTap: onTap, // همیشه دیالوگِ استریک را باز می‌کند
child: Ink(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 13),
decoration: BoxDecoration(
gradient: LinearGradient(colors: colors),
borderRadius: BorderRadius.circular(16),
border: Border.all(color: AppColors.gold, width: 1.4),
),
child: Row(
children: [
// شعله‌ی استریک با عددِ روز.
Stack(
alignment: Alignment.center,
children: [
Icon(
Icons.local_fire_department,
color:
streak > 0 ? const Color(0xFFFF7A1A) : Colors.white54,
size: 40,
),
if (streak > 0)
Padding(
padding: const EdgeInsets.only(top: 6),
child: Text(
'$streak',
style: const TextStyle(
color: Colors.white,
fontSize: 13,
fontWeight: FontWeight.bold,
),
),
),
],
),
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'هدیه‌ی روزانه',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Text(
streak > 0
? '$streak روز پیاپی 🔥'
: 'زنجیره‌ات رو شروع کن!',
style: const TextStyle(
color: Colors.white70,
fontSize: 12,
),
),
],
),
const Spacer(),
if (ready)
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(
Icons.monetization_on,
color: AppColors.gold,
size: 16,
),
const SizedBox(width: 3),
Text(
'+$next',
style: const TextStyle(
color: AppColors.gold,
fontWeight: FontWeight.bold,
),
),
],
),
const Text(
'دریافت',
style: TextStyle(color: Colors.white70, fontSize: 11),
),
],
)
else
const Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.check_circle, color: AppColors.gold, size: 18),
SizedBox(width: 4),
Text(
'امروز گرفتی',
style: TextStyle(color: Colors.white70, fontSize: 12),
),
],
),
],
),
),
),
),
);
}
}
class _TopBar extends StatelessWidget {
final WalletEntity? wallet;
final VoidCallback onCoinTap;
final Key? coinKey;
const _TopBar({required this.wallet, required this.onCoinTap, this.coinKey});
@override
Widget build(BuildContext context) {
final w = wallet;
return Container(
margin: const EdgeInsets.all(8),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
decoration: BoxDecoration(
gradient: const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [AppColors.bg, AppColors.bgDark],
),
borderRadius: BorderRadius.circular(16),
border: Border.all(color: AppColors.goldDark),
boxShadow: const [BoxShadow(color: Colors.black54, blurRadius: 8)],
),
child: Row(
children: [
GestureDetector(
onTap: () async {
await context.push('/profile');
if (context.mounted) {
context.read<WalletBloc>().add(LoadWalletEvent());
}
},
child: Container(
width: 48,
height: 48,
padding: const EdgeInsets.all(2),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: AppColors.panel,
border: Border.all(color: AppColors.gold, width: 2),
),
child:
(w == null || w.avatar.isEmpty)
? const Icon(Icons.person, color: AppColors.gold)
: PlayerAvatar(seed: w.avatar, imageUrl: w.avatarImg),
),
),
const SizedBox(width: 10),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
if (w != null && w.name.isNotEmpty) ...[
Text(
w.name,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
const SizedBox(width: 6),
],
if (w?.vip == true) const _VipTag(),
],
),
const SizedBox(height: 2),
Row(
children: [
const Icon(Icons.star, color: AppColors.gold, size: 16),
const SizedBox(width: 4),
Text(
'سطح ${w?.level ?? '-'}',
style: const TextStyle(
color: AppColors.gold,
fontWeight: FontWeight.bold,
),
),
],
),
const SizedBox(height: 4),
ClipRRect(
borderRadius: BorderRadius.circular(4),
child: SizedBox(
width: 96,
height: 7,
child: LinearProgressIndicator(
value:
(w == null || w.xpForNext == 0)
? 0
: w.xpIntoLevel / w.xpForNext,
backgroundColor: Colors.white10,
valueColor: const AlwaysStoppedAnimation(AppColors.gold),
),
),
),
],
),
const Spacer(),
GestureDetector(
onTap: onCoinTap,
child: StatChip(
icon: Icons.confirmation_number,
value: '${w?.tickets ?? 0}',
),
),
const SizedBox(width: 8),
GestureDetector(
key: coinKey,
onTap: onCoinTap,
child: StatChip(
icon: Icons.monetization_on,
value: '${w?.coins ?? 0}',
),
),
],
),
);
}
}
class _VipTag extends StatelessWidget {
const _VipTag();
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 1),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFFFFD54F), AppColors.goldDark],
),
borderRadius: BorderRadius.circular(6),
),
child: const Text(
'VIP',
style: TextStyle(
color: AppColors.bg,
fontWeight: FontWeight.bold,
fontSize: 10,
),
),
);
}
}