Files
tripz-llc/apps/rider_new/lib/features/rewards/view/rewards_page.dart
T
2026-08-05 14:12:41 +03:00

206 lines
6.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:share_plus/share_plus.dart';
import '../../../core/design/tokens.dart';
import '../../../core/design/tripz_colors.dart';
import '../../../core/design/typography.dart';
import '../../../core/di.dart';
import '../../../core/l10n/l10n.dart';
import '../../../core/store_links.dart';
import '../../../core/ui/tripz_button.dart';
import '../../../core/ui/tripz_card.dart';
import '../../../core/ui/tripz_scaffold.dart';
import '../cubit/rewards_cubit.dart';
/// «مكافآتي» — الدعوات والكوبونات في شاشة واحدة (نمط سيرو: Promos + Invite).
class RewardsPage extends StatefulWidget {
const RewardsPage({super.key});
@override
State<RewardsPage> createState() => _RewardsPageState();
}
class _RewardsPageState extends State<RewardsPage> {
late final RewardsCubit _cubit = sl<RewardsCubit>()..load();
@override
void dispose() {
_cubit.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
final l10n = context.l10n;
return BlocProvider.value(
value: _cubit,
child: BlocBuilder<RewardsCubit, RewardsState>(
builder: (context, state) {
final ref = state.referrals;
return TripzScaffold(
title: l10n.rewardsTitle,
status: state.status,
error: state.error,
onRetry: _cubit.load,
child: ListView(
children: [
if (ref != null) _InviteCard(code: ref.code, summary: ref),
const SizedBox(height: Space.lg),
Text(l10n.rewardsCoupons, style: context.texts.titleMedium),
const SizedBox(height: Space.xs),
if (state.coupons.isEmpty)
Text(
l10n.rewardsCouponsEmpty,
style: context.texts.bodySmall?.copyWith(
color: context.colors.onSurfaceVariant,
),
)
else
for (final coupon in state.coupons) ...[
TripzCard(
child: Row(
children: [
Icon(
Icons.local_offer_outlined,
color: context.tripzColors.success,
),
const SizedBox(width: Space.sm),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
coupon.code,
textDirection: TextDirection.ltr,
style: numericStyle(context.texts.titleSmall),
),
if (coupon.description.isNotEmpty)
Text(
coupon.description,
style: context.texts.bodySmall?.copyWith(
color: context.colors.onSurfaceVariant,
),
),
],
),
),
],
),
),
const SizedBox(height: Space.xs),
],
],
),
);
},
),
);
}
}
class _InviteCard extends StatelessWidget {
const _InviteCard({required this.code, required this.summary});
final String code;
final dynamic summary;
@override
Widget build(BuildContext context) {
final l10n = context.l10n;
return Container(
padding: Space.page,
decoration: BoxDecoration(
color: context.colors.primaryContainer,
borderRadius: Radii.card_,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
l10n.rewardsInviteTitle,
style: context.texts.titleMedium?.copyWith(
color: context.colors.onPrimaryContainer,
),
),
const SizedBox(height: Space.xxs),
Text(
l10n.rewardsInviteLead,
style: context.texts.bodySmall?.copyWith(
color: context.colors.onPrimaryContainer.withValues(alpha: 0.8),
),
),
const SizedBox(height: Space.md),
// الكود يُنسخ ويُشارك — الطريقان اللذان يستعملهما الناس فعلاً.
Row(
children: [
Expanded(
child: SelectableText(
code,
textDirection: TextDirection.ltr,
style: numericStyle(context.texts.headlineSmall).copyWith(
letterSpacing: 3,
color: context.colors.onPrimaryContainer,
),
),
),
IconButton(
icon: const Icon(Icons.copy_rounded),
color: context.colors.onPrimaryContainer,
onPressed: () => Clipboard.setData(ClipboardData(text: code)),
),
],
),
const SizedBox(height: Space.sm),
TripzButton.primary(
label: l10n.menuShare,
icon: Icons.share_outlined,
// الكود بلا رابط لا ينفع: المدعوّ لا يعرف من أين يُنزّل. ورابطُ
// **هذا** البناء لا رابطٌ ثابت — سائق يدعو سائقاً وراكب راكباً.
onPressed: () => SharePlus.instance.share(
ShareParams(text: l10n.shareMessage(code, StoreLinks.thisApp)),
),
),
const SizedBox(height: Space.md),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_Stat(label: l10n.rewardsInvited, value: summary.total),
_Stat(label: l10n.rewardsPending, value: summary.pending),
_Stat(label: l10n.rewardsPaid, value: summary.paid),
],
),
],
),
);
}
}
class _Stat extends StatelessWidget {
const _Stat({required this.label, required this.value});
final String label;
final int value;
@override
Widget build(BuildContext context) {
return Column(
children: [
Text(
'$value',
style: numericStyle(context.texts.titleLarge).copyWith(
color: context.colors.onPrimaryContainer,
),
),
Text(
label,
style: context.texts.labelSmall?.copyWith(
color: context.colors.onPrimaryContainer.withValues(alpha: 0.8),
),
),
],
);
}
}