import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../core/theme/app_theme.dart'; import '../../core/constants/app_constants.dart'; class SUSQuestionnaireScreen extends ConsumerStatefulWidget { const SUSQuestionnaireScreen({super.key}); @override ConsumerState createState() => _SUSQuestionnaireScreenState(); } class _SUSQuestionnaireScreenState extends ConsumerState { final List _responses = List.filled(10, 0); bool _isCompleted = false; final List _questions = [ "Saya pikir saya akan sering menggunakan aplikasi ini", "Saya merasa aplikasi ini terlalu rumit untuk digunakan", "Saya pikir aplikasi ini mudah digunakan", "Saya pikir saya membutuhkan bantuan teknis untuk menggunakan aplikasi ini", "Saya merasa berbagai fitur dalam aplikasi ini terintegrasi dengan baik", "Saya pikir ada terlalu banyak ketidakkonsistenan dalam aplikasi ini", "Saya pikir kebanyakan orang akan belajar menggunakan aplikasi ini dengan cepat", "Saya merasa aplikasi ini sangat merepotkan untuk digunakan", "Saya merasa sangat percaya diri menggunakan aplikasi ini", "Saya perlu belajar banyak hal sebelum bisa menggunakan aplikasi ini dengan baik", ]; @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppTheme.warmWhite, appBar: AppBar( title: const Text('System Usability Scale (SUS)'), backgroundColor: Colors.transparent, elevation: 0, ), body: SingleChildScrollView( padding: const EdgeInsets.all(AppConstants.defaultPadding), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header _buildHeader(), const SizedBox(height: 24), // Questions ..._buildQuestions(), const SizedBox(height: 32), // Submit Button _buildSubmitButton(), if (_isCompleted) ...[const SizedBox(height: 24), _buildResults()], ], ), ), ); } Widget _buildHeader() { return Container( width: double.infinity, padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: AppTheme.info.withOpacity(0.1), borderRadius: BorderRadius.circular(AppConstants.borderRadius), border: Border.all(color: AppTheme.info.withOpacity(0.2)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(Icons.quiz_outlined, color: AppTheme.info, size: 24), const SizedBox(width: 8), Text( 'Evaluasi Kegunaan Sistem', style: Theme.of(context).textTheme.titleLarge?.copyWith( fontWeight: FontWeight.bold, color: AppTheme.info, ), ), ], ), const SizedBox(height: 12), Text( 'Mohon berikan penilaian Anda terhadap aplikasi AMORI Menu Recommender berdasarkan pengalaman penggunaan. Skala penilaian dari 1 (Sangat Tidak Setuju) hingga 5 (Sangat Setuju).', style: Theme.of( context, ).textTheme.bodyMedium?.copyWith(color: AppTheme.grey700), ), ], ), ); } List _buildQuestions() { return _questions.asMap().entries.map((entry) { final index = entry.key; final question = entry.value; return Container( margin: const EdgeInsets.only(bottom: 16), padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(AppConstants.borderRadius), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Pertanyaan ${index + 1}', style: Theme.of(context).textTheme.labelLarge?.copyWith( color: AppTheme.primaryBrown, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), Text( question, style: Theme.of( context, ).textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500), ), const SizedBox(height: 16), // Rating Scale Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Sangat\nTidak Setuju', style: Theme.of( context, ).textTheme.bodySmall?.copyWith(color: AppTheme.grey600), textAlign: TextAlign.center, ), Text( 'Sangat\nSetuju', style: Theme.of( context, ).textTheme.bodySmall?.copyWith(color: AppTheme.grey600), textAlign: TextAlign.center, ), ], ), const SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: List.generate(5, (rating) { final value = rating + 1; final isSelected = _responses[index] == value; return GestureDetector( onTap: () { setState(() { _responses[index] = value; }); }, child: Container( width: 40, height: 40, decoration: BoxDecoration( shape: BoxShape.circle, color: isSelected ? AppTheme.primaryBrown : Colors.transparent, border: Border.all( color: isSelected ? AppTheme.primaryBrown : AppTheme.grey300, width: 2, ), ), child: Center( child: Text( value.toString(), style: TextStyle( color: isSelected ? Colors.white : AppTheme.grey600, fontWeight: FontWeight.bold, ), ), ), ), ); }), ), ], ), ); }).toList(); } Widget _buildSubmitButton() { final allAnswered = !_responses.contains(0); return SizedBox( width: double.infinity, child: ElevatedButton( onPressed: allAnswered ? _calculateSUSScore : null, style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 16), backgroundColor: allAnswered ? AppTheme.primaryBrown : AppTheme.grey300, ), child: Text( _isCompleted ? 'Selesai' : 'Hitung Skor SUS', style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), ), ); } Widget _buildResults() { final score = _calculateSUSScore(); final interpretation = _interpretSUSScore(score); return Container( width: double.infinity, padding: const EdgeInsets.all(24), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ AppTheme.success.withOpacity(0.1), AppTheme.info.withOpacity(0.1), ], ), borderRadius: BorderRadius.circular(AppConstants.borderRadius), border: Border.all(color: AppTheme.success.withOpacity(0.3)), ), child: Column( children: [ Icon(Icons.analytics_outlined, size: 48, color: AppTheme.success), const SizedBox(height: 16), Text( 'Hasil SUS Score', style: Theme.of(context).textTheme.titleLarge?.copyWith( fontWeight: FontWeight.bold, color: AppTheme.success, ), ), const SizedBox(height: 8), Text( score.toStringAsFixed(1), style: Theme.of(context).textTheme.displayMedium?.copyWith( fontWeight: FontWeight.bold, color: AppTheme.primaryBrown, ), ), const SizedBox(height: 8), Text( 'dari 100', style: Theme.of( context, ).textTheme.titleMedium?.copyWith(color: AppTheme.grey600), ), const SizedBox(height: 16), Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white.withOpacity(0.7), borderRadius: BorderRadius.circular(12), ), child: Column( children: [ Text( 'Interpretasi:', style: Theme.of( context, ).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.bold), ), const SizedBox(height: 8), Text( interpretation['category']!, style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, color: interpretation['color'] as Color, ), ), const SizedBox(height: 4), Text( interpretation['description']!, style: Theme.of(context).textTheme.bodyMedium, textAlign: TextAlign.center, ), ], ), ), const SizedBox(height: 16), _buildScoreBreakdown(), ], ), ); } Widget _buildScoreBreakdown() { return ExpansionTile( title: const Text('Detail Perhitungan'), children: [ Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Rumus SUS Score:', style: TextStyle(fontWeight: FontWeight.bold), ), const SizedBox(height: 8), const Text('• Pertanyaan ganjil (1,3,5,7,9): (nilai - 1) × 2.5'), const Text('• Pertanyaan genap (2,4,6,8,10): (5 - nilai) × 2.5'), const Text('• Total: Jumlah semua skor'), const SizedBox(height: 12), const Text( 'Interpretasi Skor:', style: TextStyle(fontWeight: FontWeight.bold), ), const SizedBox(height: 8), _buildScoreRange('90-100', 'Excellent', AppTheme.success), _buildScoreRange('80-89', 'Good', Colors.lightGreen), _buildScoreRange('70-79', 'OK', AppTheme.warning), _buildScoreRange('60-69', 'Poor', Colors.orange), _buildScoreRange('0-59', 'Awful', AppTheme.error), ], ), ), ], ); } Widget _buildScoreRange(String range, String category, Color color) { return Padding( padding: const EdgeInsets.symmetric(vertical: 2), child: Row( children: [ Container( width: 12, height: 12, decoration: BoxDecoration(color: color, shape: BoxShape.circle), ), const SizedBox(width: 8), Text('$range: $category'), ], ), ); } double _calculateSUSScore() { double totalScore = 0; for (int i = 0; i < _responses.length; i++) { if (i % 2 == 0) { // Odd questions (1,3,5,7,9) - positive statements totalScore += (_responses[i] - 1) * 2.5; } else { // Even questions (2,4,6,8,10) - negative statements totalScore += (5 - _responses[i]) * 2.5; } } if (!_isCompleted) { setState(() => _isCompleted = true); } return totalScore; } Map _interpretSUSScore(double score) { if (score >= 90) { return { 'category': 'Excellent', 'description': 'Aplikasi memiliki kegunaan yang sangat baik', 'color': AppTheme.success, }; } else if (score >= 80) { return { 'category': 'Good', 'description': 'Aplikasi memiliki kegunaan yang baik', 'color': Colors.lightGreen, }; } else if (score >= 70) { return { 'category': 'OK', 'description': 'Aplikasi memiliki kegunaan yang cukup', 'color': AppTheme.warning, }; } else if (score >= 60) { return { 'category': 'Poor', 'description': 'Aplikasi memiliki kegunaan yang kurang', 'color': Colors.orange, }; } else { return { 'category': 'Awful', 'description': 'Aplikasi memiliki kegunaan yang sangat kurang', 'color': AppTheme.error, }; } } }