AtmoSphere/lib/screens/feedback_screen.dart
2026-01-16 18:22:32 +08:00

329 lines
10 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import '../constants.dart';
class FeedbackScreen extends StatefulWidget {
const FeedbackScreen({super.key});
@override
State<FeedbackScreen> createState() => _FeedbackScreenState();
}
class _FeedbackScreenState extends State<FeedbackScreen> {
final TextEditingController _feedbackController = TextEditingController();
final _formKey = GlobalKey<FormState>();
bool _isSubmitting = false;
String? _selectedFeedbackType; // 选中的反馈类型
@override
void dispose() {
_feedbackController.dispose();
super.dispose();
}
Future<void> _submitFeedback() async {
if (!_formKey.currentState!.validate()) {
return;
}
setState(() {
_isSubmitting = true;
});
// 模拟提交反馈实际应用中这里应该调用API
await Future.delayed(const Duration(milliseconds: 500));
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Thank you for your feedback!'),
duration: Duration(seconds: 1),
),
);
// 0.8秒后返回上一页
await Future.delayed(const Duration(milliseconds: 800));
if (mounted) {
Navigator.pop(context);
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Feedback')),
body: Form(
key: _formKey,
child: ListView(
padding: const EdgeInsets.all(24.0),
children: [
const SizedBox(height: 20),
// Header
Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: kCardBackground,
borderRadius: kCardBorderRadius,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Icon(
Icons.feedback,
size: 48,
color: Colors.blueAccent,
),
const SizedBox(height: 16),
const Text(
'We\'d love to hear from you!',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
const SizedBox(height: 8),
Text(
'Your feedback helps us improve AtmoSphere. Please share your thoughts, suggestions, or report any issues.',
style: TextStyle(
fontSize: 14,
color: Colors.white.withOpacity(0.7),
height: 1.5,
),
),
],
),
),
const SizedBox(height: 32),
// Feedback Type Selection
Text(
'Feedback Type',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.white.withOpacity(0.9),
),
),
const SizedBox(height: 12),
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: kCardBackground,
borderRadius: kCardBorderRadius,
),
child: Column(
children: [
_FeedbackTypeOption(
icon: Icons.bug_report,
title: 'Bug Report',
subtitle: 'Report a problem or issue',
isSelected: _selectedFeedbackType == 'bug',
onTap: () {
setState(() {
_selectedFeedbackType = 'bug';
});
},
),
const Divider(color: Colors.white24),
_FeedbackTypeOption(
icon: Icons.lightbulb_outline,
title: 'Feature Request',
subtitle: 'Suggest a new feature',
isSelected: _selectedFeedbackType == 'feature',
onTap: () {
setState(() {
_selectedFeedbackType = 'feature';
});
},
),
const Divider(color: Colors.white24),
_FeedbackTypeOption(
icon: Icons.star_outline,
title: 'General Feedback',
subtitle: 'Share your thoughts',
isSelected: _selectedFeedbackType == 'general',
onTap: () {
setState(() {
_selectedFeedbackType = 'general';
});
},
),
],
),
),
const SizedBox(height: 32),
// Feedback Text Field
Text(
'Your Feedback',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.white.withOpacity(0.9),
),
),
const SizedBox(height: 12),
Container(
decoration: BoxDecoration(
color: kCardBackground,
borderRadius: kCardBorderRadius,
),
child: TextFormField(
controller: _feedbackController,
maxLines: 8,
style: const TextStyle(color: Colors.white),
decoration: InputDecoration(
hintText: 'Please describe your feedback in detail...',
hintStyle: TextStyle(color: Colors.white.withOpacity(0.5)),
border: OutlineInputBorder(
borderRadius: kCardBorderRadius,
borderSide: BorderSide.none,
),
filled: true,
fillColor: Colors.transparent,
contentPadding: const EdgeInsets.all(16),
),
validator: (value) {
if (value == null || value.trim().isEmpty) {
return 'Please enter your feedback';
}
if (value.trim().length < 10) {
return 'Feedback must be at least 10 characters';
}
return null;
},
),
),
const SizedBox(height: 32),
// Submit Button
SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
onPressed: _isSubmitting ? null : _submitFeedback,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueAccent,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
elevation: 0,
),
child: _isSubmitting
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
Colors.white,
),
),
)
: const Text(
'Submit Feedback',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
),
const SizedBox(height: 24),
// Note
Center(
child: Text(
'We typically respond within 24-48 hours',
style: TextStyle(
fontSize: 12,
color: Colors.white.withOpacity(0.5),
),
),
),
const SizedBox(height: 40),
],
),
),
);
}
}
class _FeedbackTypeOption extends StatelessWidget {
final IconData icon;
final String title;
final String subtitle;
final bool isSelected;
final VoidCallback onTap;
const _FeedbackTypeOption({
required this.icon,
required this.title,
required this.subtitle,
required this.isSelected,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(8),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8),
decoration: BoxDecoration(
color: isSelected
? Colors.blueAccent.withOpacity(0.2)
: Colors.transparent,
borderRadius: BorderRadius.circular(8),
border: isSelected
? Border.all(color: Colors.blueAccent, width: 1.5)
: null,
),
child: Row(
children: [
Icon(
icon,
color: isSelected ? Colors.blueAccent : Colors.white70,
size: 24,
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(
fontSize: 16,
fontWeight: isSelected
? FontWeight.bold
: FontWeight.w600,
color: Colors.white,
),
),
const SizedBox(height: 4),
Text(
subtitle,
style: TextStyle(
fontSize: 12,
color: Colors.white.withOpacity(0.6),
),
),
],
),
),
if (isSelected)
const Icon(Icons.check_circle, color: Colors.blueAccent, size: 24)
else
Icon(
Icons.radio_button_unchecked,
color: Colors.white.withOpacity(0.3),
size: 24,
),
],
),
),
);
}
}