diff --git a/apps/lib/l10n/app_en.arb b/apps/lib/l10n/app_en.arb index bcc92a8..b479059 100644 --- a/apps/lib/l10n/app_en.arb +++ b/apps/lib/l10n/app_en.arb @@ -95,8 +95,8 @@ "settingsPrivacyAndNotificationSubtitle": "Manage placeholders for privacy and notification groups", "settingsLegalCenterTitle": "About & Agreements", "settingsLegalCenterSubtitle": "Read About Us, Privacy Policy, and Terms of Service", - "settingsCoinCenterTitle": "Coin Center", - "settingsCoinCenterSubtitle": "Balance: {balance} coins. View packages and recharge entry.", + "settingsCoinCenterTitle": "Credits Center", + "settingsCoinCenterSubtitle": "Balance: {balance} credits. View packages and recharge entry.", "@settingsCoinCenterSubtitle": { "placeholders": { "balance": { @@ -104,7 +104,7 @@ } } }, - "settingsCoinHeroSubtitle": "Coins will be used for casting and related services later.", + "settingsCoinHeroSubtitle": "Credits will be used for casting and related services later.", "settingsAiLanguage": "AI Response Language", "settingsAiLanguageHint": "This field will align with profiles.settings.preferences.ai_language once the real preference flow is connected.", "settingsTimezone": "Time Zone", @@ -140,8 +140,8 @@ "settingsLogoutConfirmHint": "Tap again to confirm logout", "settingsLogoutConfirmAction": "Tap again to logout", "settingsLanguageSection": "Interface Language", - "settingsCoinBalanceLabel": "Current Coins", - "settingsCoinBalanceValue": "{balance} coins", + "settingsCoinBalanceLabel": "Current Credits", + "settingsCoinBalanceValue": "{balance} credits", "@settingsCoinBalanceValue": { "placeholders": { "balance": { @@ -157,7 +157,7 @@ "settingsCoinPackPopularBadge": "Popular", "settingsPurchaseButton": "Pay Now", "settingsPurchasePending": "Payment is not connected yet", - "settingsCoinAmount": "{amount} coins", + "settingsCoinAmount": "{amount} credits", "@settingsCoinAmount": { "placeholders": { "amount": { @@ -184,6 +184,8 @@ "errorServiceUnavailable": "Service unavailable, please try again later", "errorServerGeneric": "Server error, please try again later", "errorRequestGeneric": "Request failed, please try again", + "errorRunLimitExceeded": "Run limit reached in this session. Please start a new divination.", + "errorDivinationPayloadRequired": "Missing divination payload. Please cast again.", "divinationScreenTitle": "Cast Hexagram", "divinationSelectMethod": "Select divination method", "divinationManualMethod": "Manual", @@ -192,7 +194,7 @@ "divinationQuestionInputPrompt": "Enter your question", "divinationQuestionInputHint": "Describe your question in detail for more accurate reading", "divinationStartButton": "Start Casting", - "divinationCoinBalance": "Simulated coin balance: {balance}", + "divinationCoinBalance": "Available coins: {balance}", "@divinationCoinBalance": { "placeholders": { "balance": { @@ -200,6 +202,7 @@ } } }, + "divinationRefreshBalance": "Refresh balance", "divinationRecommendManual": "Manual casting is recommended for more accurate readings! Prepare three identical coins and click here for the tutorial.", "divinationMethodTipTitle": "Divination Method", "divinationMethodTipAuto": "Auto: No coins needed, just follow the instructions.", @@ -289,7 +292,7 @@ }, "autoShakeComplete": "Tap the button below to analyze", "autoTryShakePhone": "You can also shake your phone", - "autoSimBalance": "Balance: {balance}", + "autoSimBalance": "Available coins: {balance}", "@autoSimBalance": { "placeholders": { "balance": { @@ -298,5 +301,10 @@ } }, "autoGuideTitle": "Auto Casting Tutorial", - "autoGuideInstruction": "Shake your phone or tap the button, cast 6 times to form a complete hexagram." + "autoGuideInstruction": "Shake your phone or tap the button, cast 6 times to form a complete hexagram.", + "dateTab": "Date", + "timeTab": "Time", + "confirm": "Confirm", + "cancel": "Cancel", + "autoSelectTime": "Select Time" } diff --git a/apps/lib/l10n/app_localizations.dart b/apps/lib/l10n/app_localizations.dart index 2b7eddf..98bca97 100644 --- a/apps/lib/l10n/app_localizations.dart +++ b/apps/lib/l10n/app_localizations.dart @@ -545,19 +545,19 @@ abstract class AppLocalizations { /// No description provided for @settingsCoinCenterTitle. /// /// In zh, this message translates to: - /// **'铜币中心'** + /// **'点数中心'** String get settingsCoinCenterTitle; /// No description provided for @settingsCoinCenterSubtitle. /// /// In zh, this message translates to: - /// **'当前余额 {balance} 枚铜币,查看套餐与充值入口'** + /// **'当前余额 {balance} 点数,查看套餐与充值入口'** String settingsCoinCenterSubtitle(int balance); /// No description provided for @settingsCoinHeroSubtitle. /// /// In zh, this message translates to: - /// **'铜币可用于后续起卦与相关服务消费'** + /// **'点数可用于后续起卦与相关服务消费'** String get settingsCoinHeroSubtitle; /// No description provided for @settingsAiLanguage. @@ -731,13 +731,13 @@ abstract class AppLocalizations { /// No description provided for @settingsCoinBalanceLabel. /// /// In zh, this message translates to: - /// **'当前铜币'** + /// **'当前点数'** String get settingsCoinBalanceLabel; /// No description provided for @settingsCoinBalanceValue. /// /// In zh, this message translates to: - /// **'{balance} 枚铜币'** + /// **'{balance} 点数'** String settingsCoinBalanceValue(int balance); /// No description provided for @settingsCoinCenterDescription. @@ -791,7 +791,7 @@ abstract class AppLocalizations { /// No description provided for @settingsCoinAmount. /// /// In zh, this message translates to: - /// **'{amount} 枚铜币'** + /// **'{amount} 点数'** String settingsCoinAmount(int amount); /// No description provided for @english. @@ -908,6 +908,18 @@ abstract class AppLocalizations { /// **'请求失败,请稍后重试'** String get errorRequestGeneric; + /// No description provided for @errorRunLimitExceeded. + /// + /// In zh, this message translates to: + /// **'本次会话追问次数已达上限,请新起一卦'** + String get errorRunLimitExceeded; + + /// No description provided for @errorDivinationPayloadRequired. + /// + /// In zh, this message translates to: + /// **'缺少六爻输入数据,请重新起卦'** + String get errorDivinationPayloadRequired; + /// No description provided for @divinationScreenTitle. /// /// In zh, this message translates to: @@ -959,9 +971,15 @@ abstract class AppLocalizations { /// No description provided for @divinationCoinBalance. /// /// In zh, this message translates to: - /// **'模拟铜钱余额:{balance} 枚'** + /// **'当前可用铜币:{balance} 枚'** String divinationCoinBalance(int balance); + /// No description provided for @divinationRefreshBalance. + /// + /// In zh, this message translates to: + /// **'刷新余额'** + String get divinationRefreshBalance; + /// No description provided for @divinationRecommendManual. /// /// In zh, this message translates to: @@ -1295,7 +1313,7 @@ abstract class AppLocalizations { /// No description provided for @autoSelectTime. /// /// In zh, this message translates to: - /// **'选择起卦时间'** + /// **'选择时间'** String get autoSelectTime; /// No description provided for @autoCoinDivination. @@ -1373,7 +1391,7 @@ abstract class AppLocalizations { /// No description provided for @autoSimBalance. /// /// In zh, this message translates to: - /// **'模拟余额:{balance} 枚'** + /// **'当前可用铜币:{balance} 枚'** String autoSimBalance(int balance); /// No description provided for @autoGuideTitle. @@ -1387,6 +1405,30 @@ abstract class AppLocalizations { /// In zh, this message translates to: /// **'摇晃手机或点击按钮,连续摇 6 次即可形成完整卦象。'** String get autoGuideInstruction; + + /// No description provided for @dateTab. + /// + /// In zh, this message translates to: + /// **'日期'** + String get dateTab; + + /// No description provided for @timeTab. + /// + /// In zh, this message translates to: + /// **'时间'** + String get timeTab; + + /// No description provided for @confirm. + /// + /// In zh, this message translates to: + /// **'确认'** + String get confirm; + + /// No description provided for @cancel. + /// + /// In zh, this message translates to: + /// **'取消'** + String get cancel; } class _AppLocalizationsDelegate diff --git a/apps/lib/l10n/app_localizations_en.dart b/apps/lib/l10n/app_localizations_en.dart index ecdee2f..43cc6ab 100644 --- a/apps/lib/l10n/app_localizations_en.dart +++ b/apps/lib/l10n/app_localizations_en.dart @@ -245,16 +245,16 @@ class AppLocalizationsEn extends AppLocalizations { 'Read About Us, Privacy Policy, and Terms of Service'; @override - String get settingsCoinCenterTitle => 'Coin Center'; + String get settingsCoinCenterTitle => 'Credits Center'; @override String settingsCoinCenterSubtitle(int balance) { - return 'Balance: $balance coins. View packages and recharge entry.'; + return 'Balance: $balance credits. View packages and recharge entry.'; } @override String get settingsCoinHeroSubtitle => - 'Coins will be used for casting and related services later.'; + 'Credits will be used for casting and related services later.'; @override String get settingsAiLanguage => 'AI Response Language'; @@ -350,11 +350,11 @@ class AppLocalizationsEn extends AppLocalizations { String get settingsLanguageSection => 'Interface Language'; @override - String get settingsCoinBalanceLabel => 'Current Coins'; + String get settingsCoinBalanceLabel => 'Current Credits'; @override String settingsCoinBalanceValue(int balance) { - return '$balance coins'; + return '$balance credits'; } @override @@ -384,7 +384,7 @@ class AppLocalizationsEn extends AppLocalizations { @override String settingsCoinAmount(int amount) { - return '$amount coins'; + return '$amount credits'; } @override @@ -449,6 +449,14 @@ class AppLocalizationsEn extends AppLocalizations { @override String get errorRequestGeneric => 'Request failed, please try again'; + @override + String get errorRunLimitExceeded => + 'Run limit reached in this session. Please start a new divination.'; + + @override + String get errorDivinationPayloadRequired => + 'Missing divination payload. Please cast again.'; + @override String get divinationScreenTitle => 'Cast Hexagram'; @@ -476,9 +484,12 @@ class AppLocalizationsEn extends AppLocalizations { @override String divinationCoinBalance(int balance) { - return 'Simulated coin balance: $balance'; + return 'Available coins: $balance'; } + @override + String get divinationRefreshBalance => 'Refresh balance'; + @override String get divinationRecommendManual => 'Manual casting is recommended for more accurate readings! Prepare three identical coins and click here for the tutorial.'; @@ -655,7 +666,7 @@ class AppLocalizationsEn extends AppLocalizations { String get autoScreenTitle => 'Auto Casting'; @override - String get autoSelectTime => 'Select time'; + String get autoSelectTime => 'Select Time'; @override String get autoCoinDivination => 'Coin Casting'; @@ -699,7 +710,7 @@ class AppLocalizationsEn extends AppLocalizations { @override String autoSimBalance(int balance) { - return 'Balance: $balance'; + return 'Available coins: $balance'; } @override @@ -708,4 +719,16 @@ class AppLocalizationsEn extends AppLocalizations { @override String get autoGuideInstruction => 'Shake your phone or tap the button, cast 6 times to form a complete hexagram.'; + + @override + String get dateTab => 'Date'; + + @override + String get timeTab => 'Time'; + + @override + String get confirm => 'Confirm'; + + @override + String get cancel => 'Cancel'; } diff --git a/apps/lib/l10n/app_localizations_zh.dart b/apps/lib/l10n/app_localizations_zh.dart index e568770..b2bd163 100644 --- a/apps/lib/l10n/app_localizations_zh.dart +++ b/apps/lib/l10n/app_localizations_zh.dart @@ -242,15 +242,15 @@ class AppLocalizationsZh extends AppLocalizations { String get settingsLegalCenterSubtitle => '查看关于我们、隐私政策与服务条款'; @override - String get settingsCoinCenterTitle => '铜币中心'; + String get settingsCoinCenterTitle => '点数中心'; @override String settingsCoinCenterSubtitle(int balance) { - return '当前余额 $balance 枚铜币,查看套餐与充值入口'; + return '当前余额 $balance 点数,查看套餐与充值入口'; } @override - String get settingsCoinHeroSubtitle => '铜币可用于后续起卦与相关服务消费'; + String get settingsCoinHeroSubtitle => '点数可用于后续起卦与相关服务消费'; @override String get settingsAiLanguage => 'AI 回复语言'; @@ -344,11 +344,11 @@ class AppLocalizationsZh extends AppLocalizations { String get settingsLanguageSection => '界面语言'; @override - String get settingsCoinBalanceLabel => '当前铜币'; + String get settingsCoinBalanceLabel => '当前点数'; @override String settingsCoinBalanceValue(int balance) { - return '$balance 枚铜币'; + return '$balance 点数'; } @override @@ -377,7 +377,7 @@ class AppLocalizationsZh extends AppLocalizations { @override String settingsCoinAmount(int amount) { - return '$amount 枚铜币'; + return '$amount 点数'; } @override @@ -440,6 +440,12 @@ class AppLocalizationsZh extends AppLocalizations { @override String get errorRequestGeneric => '请求失败,请稍后重试'; + @override + String get errorRunLimitExceeded => '本次会话追问次数已达上限,请新起一卦'; + + @override + String get errorDivinationPayloadRequired => '缺少六爻输入数据,请重新起卦'; + @override String get divinationScreenTitle => '起卦'; @@ -466,9 +472,12 @@ class AppLocalizationsZh extends AppLocalizations { @override String divinationCoinBalance(int balance) { - return '模拟铜钱余额:$balance 枚'; + return '当前可用铜币:$balance 枚'; } + @override + String get divinationRefreshBalance => '刷新余额'; + @override String get divinationRecommendManual => '推荐使用手动起卦,解卦更准确!准备三枚一样的铜钱或硬币,点击这里查看手动起卦教程。'; @@ -639,7 +648,7 @@ class AppLocalizationsZh extends AppLocalizations { String get autoScreenTitle => '自动起卦'; @override - String get autoSelectTime => '选择起卦时间'; + String get autoSelectTime => '选择时间'; @override String get autoCoinDivination => '铜钱摇卦'; @@ -683,7 +692,7 @@ class AppLocalizationsZh extends AppLocalizations { @override String autoSimBalance(int balance) { - return '模拟余额:$balance 枚'; + return '当前可用铜币:$balance 枚'; } @override @@ -691,4 +700,16 @@ class AppLocalizationsZh extends AppLocalizations { @override String get autoGuideInstruction => '摇晃手机或点击按钮,连续摇 6 次即可形成完整卦象。'; + + @override + String get dateTab => '日期'; + + @override + String get timeTab => '时间'; + + @override + String get confirm => '确认'; + + @override + String get cancel => '取消'; } diff --git a/apps/lib/l10n/app_zh.arb b/apps/lib/l10n/app_zh.arb index 78aa24e..c4f30da 100644 --- a/apps/lib/l10n/app_zh.arb +++ b/apps/lib/l10n/app_zh.arb @@ -95,8 +95,8 @@ "settingsPrivacyAndNotificationSubtitle": "分组管理 privacy 与 notification 占位设置", "settingsLegalCenterTitle": "关于与协议", "settingsLegalCenterSubtitle": "查看关于我们、隐私政策与服务条款", - "settingsCoinCenterTitle": "铜币中心", - "settingsCoinCenterSubtitle": "当前余额 {balance} 枚铜币,查看套餐与充值入口", + "settingsCoinCenterTitle": "点数中心", + "settingsCoinCenterSubtitle": "当前余额 {balance} 点数,查看套餐与充值入口", "@settingsCoinCenterSubtitle": { "placeholders": { "balance": { @@ -104,7 +104,7 @@ } } }, - "settingsCoinHeroSubtitle": "铜币可用于后续起卦与相关服务消费", + "settingsCoinHeroSubtitle": "点数可用于后续起卦与相关服务消费", "settingsAiLanguage": "AI 回复语言", "settingsAiLanguageHint": "该字段将对齐 profiles.settings.preferences.ai_language,后续接入真实偏好设置。", "settingsTimezone": "时区", @@ -140,8 +140,8 @@ "settingsLogoutConfirmHint": "再次点击确认退出登录", "settingsLogoutConfirmAction": "再次点击确认退出", "settingsLanguageSection": "界面语言", - "settingsCoinBalanceLabel": "当前铜币", - "settingsCoinBalanceValue": "{balance} 枚铜币", + "settingsCoinBalanceLabel": "当前点数", + "settingsCoinBalanceValue": "{balance} 点数", "@settingsCoinBalanceValue": { "placeholders": { "balance": { @@ -157,7 +157,7 @@ "settingsCoinPackPopularBadge": "推荐", "settingsPurchaseButton": "立即支付", "settingsPurchasePending": "支付能力暂未接入", - "settingsCoinAmount": "{amount} 枚铜币", + "settingsCoinAmount": "{amount} 点数", "@settingsCoinAmount": { "placeholders": { "amount": { @@ -184,6 +184,8 @@ "errorServiceUnavailable": "服务暂时不可用,请稍后重试", "errorServerGeneric": "服务异常,请稍后重试", "errorRequestGeneric": "请求失败,请稍后重试", + "errorRunLimitExceeded": "本次会话追问次数已达上限,请新起一卦", + "errorDivinationPayloadRequired": "缺少六爻输入数据,请重新起卦", "divinationScreenTitle": "起卦", "divinationSelectMethod": "选择起卦方式", "divinationManualMethod": "手动起卦", @@ -192,7 +194,7 @@ "divinationQuestionInputPrompt": "请输入您想占卜的问题", "divinationQuestionInputHint": "请描述您的问题,描述越详细解卦越准确", "divinationStartButton": "开始起卦", - "divinationCoinBalance": "模拟铜钱余额:{balance} 枚", + "divinationCoinBalance": "当前可用铜币:{balance} 枚", "@divinationCoinBalance": { "placeholders": { "balance": { @@ -200,6 +202,7 @@ } } }, + "divinationRefreshBalance": "刷新余额", "divinationRecommendManual": "推荐使用手动起卦,解卦更准确!准备三枚一样的铜钱或硬币,点击这里查看手动起卦教程。", "divinationMethodTipTitle": "起卦方式说明", "divinationMethodTipAuto": "自动起卦:不需要铜钱或硬币,按照引导完成摇卦。", @@ -289,7 +292,7 @@ }, "autoShakeComplete": "点击页面底部开始解卦", "autoTryShakePhone": "您也可以试试摇晃手机来起卦", - "autoSimBalance": "模拟余额:{balance} 枚", + "autoSimBalance": "当前可用铜币:{balance} 枚", "@autoSimBalance": { "placeholders": { "balance": { @@ -298,5 +301,10 @@ } }, "autoGuideTitle": "自动起卦教程", - "autoGuideInstruction": "摇晃手机或点击按钮,连续摇 6 次即可形成完整卦象。" + "autoGuideInstruction": "摇晃手机或点击按钮,连续摇 6 次即可形成完整卦象。", + "dateTab": "日期", + "timeTab": "时间", + "confirm": "确认", + "cancel": "取消", + "autoSelectTime": "选择时间" } diff --git a/apps/lib/shared/widgets/date_time_picker/date_time_picker_bottom_sheet.dart b/apps/lib/shared/widgets/date_time_picker/date_time_picker_bottom_sheet.dart new file mode 100644 index 0000000..862f0d2 --- /dev/null +++ b/apps/lib/shared/widgets/date_time_picker/date_time_picker_bottom_sheet.dart @@ -0,0 +1,109 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import '../../../l10n/app_localizations.dart'; + +class DateTimePickerBottomSheet extends StatefulWidget { + const DateTimePickerBottomSheet({ + super.key, + required this.initialDateTime, + this.minDateTime, + this.maxDateTime, + }); + + final DateTime initialDateTime; + final DateTime? minDateTime; + final DateTime? maxDateTime; + + @override + State createState() => + _DateTimePickerBottomSheetState(); +} + +class _DateTimePickerBottomSheetState extends State { + late DateTime _selectedDateTime; + int _selectedTab = 0; + + @override + void initState() { + super.initState(); + _selectedDateTime = widget.initialDateTime; + } + + @override + Widget build(BuildContext context) { + final l10n = AppLocalizations.of(context)!; + + return Container( + height: 400, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: const BorderRadius.vertical(top: Radius.circular(16)), + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(l10n.cancel), + ), + Text( + l10n.autoSelectTime, + style: Theme.of(context).textTheme.titleMedium, + ), + TextButton( + onPressed: () => Navigator.pop(context, _selectedDateTime), + child: Text(l10n.confirm), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: CupertinoSlidingSegmentedControl( + groupValue: _selectedTab, + children: {0: Text(l10n.dateTab), 1: Text(l10n.timeTab)}, + onValueChanged: (value) => + setState(() => _selectedTab = value ?? 0), + ), + ), + const SizedBox(height: 16), + Expanded( + child: CupertinoDatePicker( + mode: _selectedTab == 0 + ? CupertinoDatePickerMode.date + : CupertinoDatePickerMode.time, + initialDateTime: _selectedDateTime, + minimumDate: widget.minDateTime, + maximumDate: widget.maxDateTime, + onDateTimeChanged: (DateTime newDateTime) { + setState(() => _selectedDateTime = newDateTime); + }, + ), + ), + ], + ), + ); + } +} + +Future showDateTimePickerBottomSheet({ + required BuildContext context, + required DateTime initialDateTime, + DateTime? minDateTime, + DateTime? maxDateTime, +}) { + return showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => DateTimePickerBottomSheet( + initialDateTime: initialDateTime, + minDateTime: minDateTime, + maxDateTime: maxDateTime, + ), + ); +}