fix(apps): إصلاحات من أول تجربة حقيقية على الجهاز
## تعذّر حساب الأجرة — الخطأ في التطبيق لا في جدول الكازان الخادم يبذر التعرفة بـ city: 'default' (tenants.service.ts:156) ويستعمل dto.city ?? 'default' عند إنشاء الرحلة، وكنت أرسل city: '' فيرجّع 404 «No active tariff for /economy». تحقّق حيّ: city='default' → total 1.55 JOD ✅ city='' → 404 ❌ city='amman' → 404 ❌ لا تغيير مطلوب على السيرفر. أُضيف AppConfig.defaultCity موثّقاً بالسبب. ## التسعير مرة واحدة لكل الأنواع كان نداء شبكة عند كل ضغطة نوع. صار _priceAll يسعّر كل الأنواع بالتوازي بعد اكتمال المسار — المسافة والمدة ثابتتان والفرق في التعرفة وحدها. الراكب يرى سعر الاقتصادي والمريح معاً تحت كل خيار ويقارن بنظرة، وتبديل النوع بلا نداء. ## الكاميرا لا تتبع الموقع سببان: الموقع يصل قبل إنشاء الخريطة فيضيع التحريك، ولا فحص للإذن/الخدمة قبل getCurrentPosition فيُبتلع الخطأ صامتاً. - _onCreated يلحق بما فات عند جهوز الخريطة - LocationService.ensureReady يفحص الخدمة والإذن أولاً - didChangeAppLifecycleState يعيد المحاولة عند العودة من إعدادات النظام - حالة noLocation تُعرض للمستخدم مع زر إعادة بدل خريطة صامتة ## الخريطة والتنقّل - إطار المسار من حدوده الفعلية مع حشوة سفلية بمقدار ما تغطّيه الورقة - علامتا البداية والنهاية دائرتان ملوّنتان تطابقان ألوان الخط الزمني - زر رجوع في ورقة التأكيد + زر إعادة حساب عند فشل التسعيرة: كان المستخدم يعلق في الشاشة بلا مخرج ## المحفظة — على أي أساس يُشحن POST /wallet/topup شحنٌ تجريبي بلا مزوّد دفع خلفه (الخادم نفسه يصفه كذلك). أُضيف PaymentChannel مشتقّاً من countryPack المستأجر لا من لغة الجهاز: jo → CliQ · sy → سيرياتيل/MTN/شام كاش · eg → PayMob. ويُعرض تنبيه صريح بأن الشحن بلا تحصيل فعلي — إخفاؤه يجعل المستخدم يظنّ أنه دفع. وسحب السائق صار يستعمل القناة المختارة بدل 'cliq' المكتوبة في الكود. flutter analyze نظيف في التطبيقين. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
29f375b122
commit
8976821a93
@@ -5,6 +5,10 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../../../core/design/tokens.dart';
|
||||
|
||||
import '../../../core/design/tripz_colors.dart';
|
||||
import '../../../core/payments/payment_channels.dart';
|
||||
import '../../../core/tenant/tenant_cubit.dart';
|
||||
import '../../../core/ui/channel_picker.dart';
|
||||
import '../../../core/ui/status_banner.dart';
|
||||
|
||||
import '../../../core/di.dart';
|
||||
|
||||
@@ -103,15 +107,44 @@ class _WalletPageState extends State<WalletPage> {
|
||||
void _openTopup(BuildContext context) {
|
||||
final l10n = context.l10n;
|
||||
final controller = TextEditingController();
|
||||
// القنوات من حزمة دولة المستأجر لا من لغة الجهاز (docs/38 §10).
|
||||
final channels = PaymentChannel.forCountry(
|
||||
context.read<TenantCubit>().state.countryPack,
|
||||
);
|
||||
var channel = channels.first;
|
||||
|
||||
TripzSheet.show(
|
||||
context,
|
||||
title: l10n.walletTopup,
|
||||
child: TripzTextField(
|
||||
controller: controller,
|
||||
label: l10n.walletTopupAmount,
|
||||
numeric: true,
|
||||
autofocus: true,
|
||||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||||
child: StatefulBuilder(
|
||||
builder: (context, setState) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
TripzTextField(
|
||||
controller: controller,
|
||||
label: l10n.walletTopupAmount,
|
||||
numeric: true,
|
||||
autofocus: true,
|
||||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||||
),
|
||||
const SizedBox(height: Space.md),
|
||||
Text(l10n.walletChannel, style: context.texts.titleSmall),
|
||||
const SizedBox(height: Space.xs),
|
||||
ChannelPicker(
|
||||
channels: channels,
|
||||
selected: channel,
|
||||
onSelect: (c) => setState(() => channel = c),
|
||||
),
|
||||
const SizedBox(height: Space.md),
|
||||
// صراحةٌ مقصودة: الخادم يصف هذه النقطة بـ«كاش-إن تجريبي». إخفاء
|
||||
// ذلك يجعل المستخدم يظنّ أنه دفع فعلاً.
|
||||
StatusBanner(
|
||||
message: l10n.walletTopupNote,
|
||||
tone: BannerTone.warning,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
bottomAction: TripzButton.primary(
|
||||
label: l10n.walletTopup,
|
||||
|
||||
Reference in New Issue
Block a user