edit_challenge_screen.dart 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_riverpod/flutter_riverpod.dart';
  3. import 'package:japp_flutter/core/models/challenge_model.dart';
  4. import 'package:japp_flutter/features/challenge/view_models/challenge_edit_vm.dart';
  5. class ChallengeEditScreen extends ConsumerWidget {
  6. final ChallengeModel? initialChallenge;
  7. const ChallengeEditScreen({
  8. super.key,
  9. this.initialChallenge,
  10. });
  11. @override
  12. Widget build(BuildContext context, WidgetRef ref) {
  13. final challengeState = ref.watch(challengeEditProvider);
  14. final theme = Theme.of(context);
  15. return Scaffold(
  16. appBar: AppBar(
  17. title: Text(initialChallenge == null ? '创建挑战' : '编辑挑战'),
  18. actions: [
  19. IconButton(
  20. icon: const Icon(Icons.save),
  21. onPressed: () async {
  22. await ref.read(challengeEditProvider.notifier).saveChallenge();
  23. if (context.mounted) Navigator.pop(context);
  24. },
  25. ),
  26. ],
  27. ),
  28. body: challengeState.when(
  29. loading: () => const Center(child: CircularProgressIndicator()),
  30. error: (error, _) => Center(child: Text('错误: $error')),
  31. data: (challenge) {
  32. if (challenge == null) {
  33. return const Center(child: Text('未初始化数据'));
  34. }
  35. return SingleChildScrollView(
  36. padding: const EdgeInsets.all(16),
  37. child: Column(
  38. crossAxisAlignment: CrossAxisAlignment.start,
  39. children: [
  40. _buildTitleField(challenge, ref),
  41. const SizedBox(height: 24),
  42. _buildDifficultySelector(challenge, ref),
  43. const SizedBox(height: 24),
  44. _buildDescriptionField(challenge, ref),
  45. ],
  46. ),
  47. );
  48. },
  49. ),
  50. );
  51. }
  52. Widget _buildTitleField(ChallengeModel challenge, WidgetRef ref) {
  53. return TextFormField(
  54. initialValue: challenge.title,
  55. decoration: const InputDecoration(
  56. labelText: '挑战标题',
  57. border: OutlineInputBorder(),
  58. ),
  59. onChanged: (value) => ref.read(challengeEditProvider.notifier).updateTitle(value),
  60. );
  61. }
  62. Widget _buildDescriptionField(ChallengeModel challenge, WidgetRef ref) {
  63. return TextFormField(
  64. initialValue: challenge.description,
  65. decoration: const InputDecoration(
  66. labelText: '挑战描述',
  67. border: OutlineInputBorder(),
  68. alignLabelWithHint: true,
  69. ),
  70. maxLines: 5,
  71. onChanged: (value) => ref.read(challengeEditProvider.notifier).updateDescription(value),
  72. );
  73. }
  74. Widget _buildDifficultySelector(ChallengeModel challenge, WidgetRef ref) {
  75. const difficulties = ['简单', '中等', '困难'];
  76. return Column(
  77. crossAxisAlignment: CrossAxisAlignment.start,
  78. children: [
  79. const Text('难度级别', style: TextStyle(fontSize: 16)),
  80. const SizedBox(height: 8),
  81. Wrap(
  82. spacing: 8,
  83. children: difficulties.map((level) {
  84. return ChoiceChip(
  85. label: Text(level),
  86. selected: challenge.difficulty == level,
  87. onSelected: (selected) {
  88. if (selected) {
  89. ref.read(challengeEditProvider.notifier).updateDifficulty(level);
  90. }
  91. },
  92. );
  93. }).toList(),
  94. ),
  95. ],
  96. );
  97. }
  98. }