import 'package:flutter/material.dart'; import '../models/profile.dart'; import '../models/norms.dart'; import '../services/calculator.dart'; import '../widgets/competence_table.dart'; import '../widgets/competence_chart.dart'; enum NormType { hs, fs } class ProfileDetailScreen extends StatefulWidget { final Profile profile; const ProfileDetailScreen({super.key, required this.profile}); @override State createState() => _ProfileDetailScreenState(); } class _ProfileDetailScreenState extends State with SingleTickerProviderStateMixin { late TabController _tabController; NormType _normType = NormType.hs; List _seValues = []; List _feValues = []; @override void initState() { super.initState(); _tabController = TabController(length: 4, vsync: this); _calculateValues(); } void _calculateValues() { final seSums = Calculator.calculateSums(widget.profile.seItems); final feSums = Calculator.calculateSums(widget.profile.feItems); final normSE = _normType == NormType.hs ? Norms.normSE_HS : Norms.normSE_FS; final normFE = _normType == NormType.hs ? Norms.normFE_HS : Norms.normFE_FS; setState(() { _seValues = Calculator.calculateProfileValues(seSums, normSE); _feValues = Calculator.calculateProfileValues(feSums, normFE); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.profile.name), actions: [ PopupMenuButton( onSelected: (value) { setState(() { _normType = value; _calculateValues(); }); }, itemBuilder: (context) => [ const PopupMenuItem(value: NormType.hs, child: Text('HS - Hauptschule')), const PopupMenuItem(value: NormType.fs, child: Text('FS - Förderschule')), ], ), ], bottom: TabBar( controller: _tabController, tabs: const [ Tab(text: 'Selbsteinschätzung'), Tab(text: 'Fremdeinschätzung'), Tab(text: 'Statistik'), Tab(text: 'Alle Items'), ], ), ), body: TabBarView( controller: _tabController, children: [ // SE Tab SingleChildScrollView( child: Column( children: [ CompetenceTable(values: _seValues, title: 'Selbsteinschätzung'), CompetenceChart(values: _seValues, title: 'SE - Profilverlauf', color: Colors.blue), ], ), ), // FE Tab SingleChildScrollView( child: Column( children: [ CompetenceTable(values: _feValues, title: 'Fremdeinschätzung'), CompetenceChart(values: _feValues, title: 'FE - Profilverlauf', color: Colors.red), ], ), ), // Statistik Tab _buildStatistics(), // Items Tab _buildItemsTable(), ], ), ); } Widget _buildStatistics() { final correlation = Calculator.calculateCorrelation(_seValues, _feValues); final agreement = Calculator.calculateAgreement( widget.profile.seItems, widget.profile.feItems, ); return SingleChildScrollView( child: Column( children: [ _buildComparisonChart(), Card( margin: const EdgeInsets.all(16), child: Padding( padding: const EdgeInsets.all(16), child: Row( children: [ Expanded( child: Column( children: [ const Text('Korrelation (r)', style: TextStyle(color: Colors.grey)), Text( correlation.toStringAsFixed(2), style: const TextStyle(fontSize: 28, fontWeight: FontWeight.bold), ), Text(_getCorrelationDescription(correlation)), ], ), ), Expanded( child: Column( children: [ const Text('Übereinstimmung', style: TextStyle(color: Colors.grey)), Text( '${agreement.toStringAsFixed(1)}%', style: const TextStyle(fontSize: 28, fontWeight: FontWeight.bold), ), Text(_getAgreementDescription(agreement)), ], ), ), ], ), ), ), Card( margin: const EdgeInsets.all(16), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('Interpretation', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), const SizedBox(height: 8), Text( Calculator.getInterpretation(correlation, agreement, _seValues, _feValues), style: const TextStyle(height: 1.5), ), ], ), ), ), ], ), ); } Widget _buildComparisonChart() { return Card( margin: const EdgeInsets.all(16), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('Vergleich SE vs. FE', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), const SizedBox(height: 16), SizedBox( height: 280, child: LineChart( LineChartData( gridData: const FlGridData(show: true), titlesData: FlTitlesData( leftTitles: const AxisTitles(sideTitles: SideTitles(showTitles: true)), bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, getTitlesWidget: (value, meta) { final index = value.toInt(); if (index >= 0 && index < Norms.kompetenzen.length) { return SideTitleWidget( axisSide: meta.axisSide, child: Text(Norms.kompetenzen[index].substring(0, 8)), ); } return Container(); }, ), ), ), borderData: FlBorderData(show: true), lineBarsData: [ LineChartBarData( spots: List.generate(6, (i) => FlSpot(i.toDouble(), _seValues[i].toDouble())), isCurved: true, color: Colors.blue, barWidth: 2, dotData: const FlDotData(show: true), ), LineChartBarData( spots: List.generate(6, (i) => FlSpot(i.toDouble(), _feValues[i].toDouble())), isCurved: true, color: Colors.red, barWidth: 2, dotData: const FlDotData(show: true), ), ], minY: 0, maxY: 6, ), ), ), const SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container(color: Colors.blue, width: 16, height: 16), const SizedBox(width: 8), const Text('Selbsteinschätzung (SE)'), const SizedBox(width: 24), Container(color: Colors.red, width: 16, height: 16), const SizedBox(width: 8), const Text('Fremdeinschätzung (FE)'), ], ), ], ), ), ); } Widget _buildItemsTable() { return SingleChildScrollView( padding: const EdgeInsets.all(16), child: Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('Alle Items', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), const SizedBox(height: 16), SizedBox( height: 500, child: SingleChildScrollView( child: DataTable( columnSpacing: 12, columns: const [ DataColumn(label: Text('Item')), DataColumn(label: Text('SE')), DataColumn(label: Text('FE')), ], rows: List.generate(36, (index) { return DataRow(cells: [ DataCell(Text('${index + 1}. ${Norms.items[index]}')), DataCell(Text('${widget.profile.seItems[index]}')), DataCell(Text('${widget.profile.feItems[index]}')), ]); }), ), ), ), ], ), ), ), ); } String _getCorrelationDescription(double correlation) { if (correlation >= 0.8) return 'sehr gut'; if (correlation >= 0.6) return 'gut'; if (correlation >= 0.4) return 'mäßig'; if (correlation >= 0.2) return 'schwach'; return 'keine'; } String _getAgreementDescription(double agreement) { if (agreement >= 80) return 'hohe'; if (agreement >= 60) return 'mittlere'; if (agreement >= 40) return 'geringe'; return 'sehr geringe'; } }