import 'package:bahasajepang/pages/n4/materi/detail_materi.dart'; import 'package:bahasajepang/pages/n5/materi/materi_service.dart'; import 'package:bahasajepang/pages/n4/materi/ujian.dart'; import 'package:bahasajepang/service/ujian_service.dart'; import 'package:bahasajepang/theme.dart'; import 'package:flutter/material.dart'; class MateriN4Page extends StatefulWidget { const MateriN4Page({super.key}); @override State createState() => _MateriN4PageState(); } class _MateriN4PageState extends State { final MateriService _materiService = MateriService(); late Future> _materiFuture; bool _isLoading = true; List _materiList = []; String _errorMessage = ''; @override void initState() { super.initState(); _loadInitialData(); } void _loadInitialData() { _materiFuture = _loadMateriData(); _materiFuture.catchError((error) {}); } Future> _loadMateriData() async { try { setState(() { _isLoading = true; _errorMessage = ''; }); final data = await _materiService.getMateriByLevel('N4'); setState(() { _materiList = data; _isLoading = false; }); return data; } catch (e) { final errorMessage = e.toString().replaceAll('Exception: ', ''); setState(() { _isLoading = false; _errorMessage = errorMessage; }); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(errorMessage), backgroundColor: Colors.red[400], behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), ), ); } throw e; } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: bgColor1.withValues(alpha:0.95), appBar: AppBar( title: const Text( 'Materi N4', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 20, ), ), backgroundColor: bgColor3, elevation: 4, shadowColor: bgColor2.withValues(alpha:0.5), shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical( bottom: Radius.circular(15), ), ), centerTitle: true, iconTheme: IconThemeData(color: Colors.white.withValues(alpha:0.9)), ), body: _buildBody(), ); } Widget _buildBody() { if (_isLoading) { return Center( child: CircularProgressIndicator( valueColor: AlwaysStoppedAnimation(bgColor2), strokeWidth: 3, ), ); } if (_errorMessage.isNotEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.error_outline, color: Colors.red[400], size: 50, ), const SizedBox(height: 16), Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: Text( _errorMessage, style: TextStyle( color: Colors.red[400], fontSize: 16, ), textAlign: TextAlign.center, ), ), const SizedBox(height: 24), ElevatedButton( onPressed: _loadMateriData, style: ElevatedButton.styleFrom( backgroundColor: bgColor2, padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), elevation: 2, ), child: const Text( 'Coba Lagi', style: TextStyle( color: Colors.white, fontWeight: FontWeight.w500, ), ), ), ], ), ); } if (_materiList.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.library_books_outlined, color: bgColor2.withValues(alpha:0.7), size: 60, ), const SizedBox(height: 16), Text( 'Tidak ada materi tersedia', style: TextStyle( fontSize: 16, color: Colors.grey[600], ), ), ], ), ); } return RefreshIndicator( color: bgColor2, backgroundColor: bgColor1, onRefresh: _loadMateriData, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ Expanded( child: ListView.separated( itemCount: _materiList.length, separatorBuilder: (context, index) => const SizedBox(height: 16), itemBuilder: (context, index) { final materi = _materiList[index]; return _buildMateriCard(materi); }, ), ), _buildLatihanSoalCard(), ], ), ), ); } Widget _buildMateriCard(Map materi) { return InkWell( borderRadius: BorderRadius.circular(12), onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => DetailMateriN4Page(materiId: materi['id']), ), ); }, child: Card( margin: const EdgeInsets.symmetric(horizontal: 4), elevation: 2, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), color: bgColor2.withValues(alpha:0.9), shadowColor: bgColor2.withValues(alpha:0.3), child: Padding( padding: const EdgeInsets.all(16), child: Row( children: [ Icon( Icons.article_outlined, color: Colors.white.withValues(alpha:0.9), size: 28, ), const SizedBox(width: 16), Expanded( child: Text( materi['judul'] ?? 'Judul tidak tersedia', style: TextStyle( color: Colors.white, fontWeight: FontWeight.w600, fontSize: 16, ), ), ), Icon( Icons.chevron_right, color: Colors.white.withValues(alpha:0.7), ), ], ), ), ), ); } Widget _buildLatihanSoalCard() { final UjianService ujianService = UjianService(); return FutureBuilder>( future: ujianService.getUjianByLevel(3), // Level pemula builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return Center( child: CircularProgressIndicator( valueColor: AlwaysStoppedAnimation(bgColor2), ), ); } if (snapshot.hasError) { return Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Icon( Icons.error_outline, color: Colors.red[400], size: 40, ), const SizedBox(height: 8), Text( 'Error: ${snapshot.error}', style: TextStyle(color: Colors.red[400]), textAlign: TextAlign.center, ), ], ), ); } final ujianList = snapshot.data ?? []; if (ujianList.isEmpty) { return Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Icon( Icons.quiz_outlined, color: bgColor2.withValues(alpha:0.7), size: 40, ), const SizedBox(height: 8), Text( 'Tidak ada ujian tersedia', style: TextStyle( color: Colors.grey[600], ), ), ], ), ); } return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.only(left: 8, top: 16, bottom: 8), child: Text( 'Latihan Soal', style: TextStyle( color: Colors.grey[700], fontWeight: FontWeight.bold, fontSize: 18, ), ), ), ...ujianList.map((ujian) { return InkWell( borderRadius: BorderRadius.circular(12), onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => UjianN4Page(ujianId: ujian['id']), ), ); }, child: Card( margin: const EdgeInsets.symmetric(vertical: 8), elevation: 2, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), color: bgColor2.withValues(alpha:0.9), child: Padding( padding: const EdgeInsets.all(16), child: Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: bgColor1.withValues(alpha:0.3), borderRadius: BorderRadius.circular(8), ), child: Icon( Icons.quiz_outlined, color: Colors.white, ), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( ujian['judul'] ?? 'Latihan Soal', style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 16, color: Colors.white, ), ), const SizedBox(height: 4), Text( ujian['deskripsi'] ?? 'Jumlah soal: ${ujian['jumlah_soal']}', style: TextStyle( color: Colors.white.withValues(alpha:0.8), fontSize: 14, ), ), ], ), ), Icon( Icons.chevron_right, color: Colors.white.withValues(alpha:0.7), ), ], ), ), ), ); }).toList(), ], ); }, ); } }