feat: get cards from backend
This commit is contained in:
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../../../core/config.dart';
|
||||
import '../../../../core/theme/app_theme.dart';
|
||||
import '../../../../core/widgets/game_ui.dart';
|
||||
import '../../../wallet/presentation/bloc/wallet_bloc.dart';
|
||||
@@ -320,6 +321,7 @@ class _CardsTab extends StatelessWidget {
|
||||
title: c.title,
|
||||
glowColor: const Color(0xFF0E3C73),
|
||||
icon: Icons.style,
|
||||
art: _CardSkinArt(skin: c.id, selected: data.selectedCard == c.id),
|
||||
subtitle: c.priceCoins > 0 ? '${c.priceCoins} سکه' : 'پیشفرض',
|
||||
action: _cardAction(context, c, data),
|
||||
),
|
||||
@@ -381,6 +383,7 @@ class _ItemCard extends StatelessWidget {
|
||||
final String subtitle;
|
||||
final String? ribbon;
|
||||
final Widget action;
|
||||
final Widget? art; // هنرِ سفارشی (مثل پیشنمایشِ اسکینِ کارت) بهجای آیکن
|
||||
const _ItemCard({
|
||||
required this.title,
|
||||
required this.icon,
|
||||
@@ -388,6 +391,7 @@ class _ItemCard extends StatelessWidget {
|
||||
required this.subtitle,
|
||||
required this.action,
|
||||
this.ribbon,
|
||||
this.art,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -418,7 +422,7 @@ class _ItemCard extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Expanded(child: _GlowArt(color: glowColor, icon: icon)),
|
||||
Expanded(child: art ?? _GlowArt(color: glowColor, icon: icon)),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
subtitle,
|
||||
@@ -481,6 +485,71 @@ class _GlowArt extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// پیشنمایشِ اسکینِ کارت در فروشگاه: دو کارت فنشده (پشت + تکخال پیک)
|
||||
/// که مستقیماً از backend بارگذاری میشوند تا کاربر هنرِ واقعی را ببیند.
|
||||
class _CardSkinArt extends StatelessWidget {
|
||||
final String skin;
|
||||
final bool selected;
|
||||
const _CardSkinArt({required this.skin, required this.selected});
|
||||
|
||||
String _url(String file) => '${AppConfig.baseUrl}/cards/$skin/$file';
|
||||
|
||||
Widget _card(String file, {double angle = 0, double dx = 0}) {
|
||||
return Transform.translate(
|
||||
offset: Offset(dx, 0),
|
||||
child: Transform.rotate(
|
||||
angle: angle,
|
||||
child: AspectRatio(
|
||||
aspectRatio: 0.7,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
child: Image.network(
|
||||
_url(file),
|
||||
fit: BoxFit.cover,
|
||||
errorBuilder: (_, __, ___) => Container(
|
||||
color: const Color(0xFF0E3C73),
|
||||
child: const Icon(Icons.style, color: AppColors.gold),
|
||||
),
|
||||
loadingBuilder: (ctx, child, progress) => progress == null
|
||||
? child
|
||||
: Container(color: const Color(0xFF0A2547)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
gradient: const RadialGradient(
|
||||
colors: [Color(0xFF12508F), Colors.black87],
|
||||
radius: 0.95,
|
||||
),
|
||||
border: Border.all(
|
||||
color: selected ? AppColors.gold : Colors.black26,
|
||||
width: selected ? 2 : 1,
|
||||
),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Center(
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
_card('back.jpg', angle: -0.22, dx: -16),
|
||||
_card('AS.png', angle: 0.22, dx: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _PriceButton extends StatelessWidget {
|
||||
final String label;
|
||||
final VoidCallback? onTap;
|
||||
|
||||
Reference in New Issue
Block a user