Bestie Choice Sheet on home Mulai Curhat CTA. When the user has at least one prior session (bestieHistoryHasItemsProvider hits the chat- sessions history endpoint), the CTA opens a HaloBottomSheet with two cards: 'bestie yang udah kenal' -> /chat/history, 'bestie baru' -> /payment/entry. Empty history -> direct to /payment/entry. Bestie history list visual upgrade: HaloOrb (mitraId seed) + name + last-session date + topic pills + sessions count + ONLINE pill. Backend getCustomerHistory now returns topics, mitra_is_online, sessions_count in a single payload (no per-row presence round-trip). BestieOfflinePopup with two variants (returning | new_) replacing the legacy BestieUnavailableDialog. tanya admin ghost CTA on both variants opens the new TanyaAdminSheet. Stage 5's targeted-wait declined stub + Stage 7's chat-screen 409 stub + searching-screen call site all migrated to the real component. TanyaAdminSheet: HaloBottomSheet with WA + Telegram buttons, deeplinks fetched via supportHandlesProvider (CC-config-driven). url_launcher added to client_app; ios LSApplicationQueriesSchemes covers https/http/whatsapp/tg. Stage 2's OTP-blocked popup hubungi admin SnackBar stub also migrated to TanyaAdminSheet. Dev-only POST /internal/_test/seed-history-session lets Maestro 08 flow seed a history row before exercising the choice sheet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
55 lines
1.8 KiB
Dart
55 lines
1.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import '../../../core/theme/halo_tokens.dart';
|
|
import '../../../core/theme/widgets/widgets.dart';
|
|
import '../../support/widgets/tanya_admin_sheet.dart';
|
|
|
|
/// Modal shown when OTP delivery / verification is exhausted (rate-limited
|
|
/// 429 from `OTP_RATE_LIMIT_PHONE`, `OTP_RATE_LIMIT_IP`, `OTP_COOLDOWN`, or
|
|
/// `OTP_ATTEMPTS_EXCEEDED`). Offers a "lanjut tanpa verif" exit into the
|
|
/// anonymous flow (preserving any ESP/USP state) and a "hubungi admin" CTA
|
|
/// that opens the Tanya Admin sheet.
|
|
class OtpBlockedPopup {
|
|
const OtpBlockedPopup._();
|
|
|
|
static Future<void> show(BuildContext context) {
|
|
return HaloPopup.show<void>(
|
|
context,
|
|
title: 'Verifikasi nomor lagi penuh',
|
|
body:
|
|
'Sistem lagi nahan permintaan OTP buat keamanan. Kamu bisa lanjut '
|
|
'tanpa verifikasi, atau hubungi admin biar dibantu manual.',
|
|
icon: Container(
|
|
width: 64,
|
|
height: 64,
|
|
decoration: const BoxDecoration(
|
|
color: HaloTokens.brandSofter,
|
|
shape: BoxShape.circle,
|
|
),
|
|
alignment: Alignment.center,
|
|
child: const Icon(
|
|
Icons.lock_clock_outlined,
|
|
color: HaloTokens.brandDark,
|
|
size: 28,
|
|
),
|
|
),
|
|
primary: HaloPopupAction(
|
|
label: 'lanjut tanpa verif',
|
|
onPressed: () {
|
|
// ESP/USP picks live in Riverpod providers (espSelectionProvider,
|
|
// espSkippedProvider) and survive this navigation — no need to pass
|
|
// them as `extra`.
|
|
context.go('/onboarding/anon/method');
|
|
},
|
|
),
|
|
secondary: HaloPopupAction(
|
|
label: 'hubungi admin',
|
|
onPressed: () {
|
|
// ignore: discarded_futures
|
|
TanyaAdminSheet.show(context);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
}
|