feat(divination): use DateTimePickerBottomSheet in manual_divination_screen

This commit is contained in:
qzl
2026-04-03 18:18:55 +08:00
parent dbc3e90a46
commit a73ba67ef1
@@ -2,20 +2,30 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:intl/intl.dart';
import '../../../../core/network/api_problem.dart';
import '../../../../core/network/api_problem_mapper.dart';
import '../../../../l10n/app_localizations.dart';
import '../../../../shared/theme/design_tokens.dart';
import '../../../../shared/widgets/divination/divination_shared_widgets.dart';
import '../../../../shared/widgets/divination/divination_terms.dart';
import '../../../../shared/widgets/divination/yao_legend.dart';
import '../../../../shared/widgets/divination/yao_line_row.dart';
import '../../../../shared/widgets/toast/toast.dart';
import '../../../../shared/widgets/toast/toast_type.dart';
import '../../../../shared/widgets/date_time_picker/date_time_picker_bottom_sheet.dart';
import '../../data/models/divination_params.dart';
import '../../data/services/divination_result_builder.dart';
import '../../data/services/divination_run_service.dart';
import 'divination_result_screen.dart';
class ManualDivinationScreen extends StatefulWidget {
const ManualDivinationScreen({super.key, required this.params});
const ManualDivinationScreen({
super.key,
required this.params,
required this.runService,
});
final DivinationParams params;
final DivinationRunService runService;
@override
State<ManualDivinationScreen> createState() => _ManualDivinationScreenState();
@@ -23,10 +33,10 @@ class ManualDivinationScreen extends StatefulWidget {
class _ManualDivinationScreenState extends State<ManualDivinationScreen>
with TickerProviderStateMixin {
final DivinationResultBuilder _resultBuilder = DivinationResultBuilder();
late DateTime _selectedTime;
final List<YaoType?> _selectedYaos = List<YaoType?>.filled(6, null);
late final AnimationController _blinkController;
bool _submitting = false;
@override
void initState() {
@@ -81,7 +91,7 @@ class _ManualDivinationScreenState extends State<ManualDivinationScreen>
width: double.infinity,
height: 50,
child: FilledButton(
onPressed: _allSelected ? _showMockPayload : null,
onPressed: _allSelected && !_submitting ? _submitRun : null,
style: FilledButton.styleFrom(
backgroundColor: _allSelected
? base.withValues(
@@ -89,7 +99,13 @@ class _ManualDivinationScreenState extends State<ManualDivinationScreen>
)
: base,
),
child: Text(l10n.manualStartResolve),
child: _submitting
? const SizedBox(
width: 18,
height: 18,
child: CircularProgressIndicator(strokeWidth: 2),
)
: Text(l10n.manualStartResolve),
),
);
},
@@ -125,30 +141,15 @@ class _ManualDivinationScreenState extends State<ManualDivinationScreen>
}
Future<void> _pickTime() async {
final date = await showDatePicker(
final result = await showDateTimePickerBottomSheet(
context: context,
initialDate: _selectedTime,
firstDate: DateTime(2000),
lastDate: DateTime(2100),
initialDateTime: _selectedTime,
minDateTime: DateTime(2000),
maxDateTime: DateTime(2100),
);
if (date == null || !mounted) {
return;
}
final time = await showTimePicker(
context: context,
initialTime: TimeOfDay.fromDateTime(_selectedTime),
);
if (time == null || !mounted) {
return;
}
if (result == null || !mounted) return;
setState(() {
_selectedTime = DateTime(
date.year,
date.month,
date.day,
time.hour,
time.minute,
);
_selectedTime = result;
});
}
@@ -178,16 +179,44 @@ class _ManualDivinationScreenState extends State<ManualDivinationScreen>
);
}
Future<void> _showMockPayload() async {
final result = _resultBuilder.build(
Future<void> _submitRun() async {
final l10n = AppLocalizations.of(context)!;
setState(() {
_submitting = true;
});
try {
final aggregate = await widget.runService.run(
params: widget.params.copyWith(divinationTime: _selectedTime),
yaoStates: _selectedYaos.cast<YaoType>(),
);
if (!mounted) {
return;
}
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (_) => DivinationResultScreen(data: result),
builder: (_) => DivinationResultScreen(
data: aggregate.toViewData(
widget.params.copyWith(divinationTime: _selectedTime),
),
),
),
);
} catch (error) {
if (!mounted) {
return;
}
final message = error is ApiProblem
? mapApiProblemToMessage(error, l10n)
: l10n.errorRequestGeneric;
Toast.show(context, message, type: ToastType.error);
} finally {
if (!mounted) {
return;
}
setState(() {
_submitting = false;
});
}
}
}
@@ -225,7 +254,9 @@ class _TimeCard extends StatelessWidget {
children: [
Expanded(
child: Text(
DateFormat('yyyy年MM月dd日 HH:mm').format(selectedTime),
DateFormat.yMd(
Localizations.localeOf(context).toString(),
).add_Hm().format(selectedTime),
style: Theme.of(context).textTheme.titleMedium,
),
),