MIF_E31222888/lib/pages/pemula/materi/detail_materi.dart

335 lines
15 KiB
Dart

import 'package:bahasajepang/pages/pemula/materi/materi_service.dart';
import 'package:bahasajepang/pages/pemula/materi/isi_materi.dart';
import 'package:bahasajepang/theme.dart';
import 'package:flutter/material.dart';
class DetailMateriPage extends StatefulWidget {
final int materiId;
const DetailMateriPage({super.key, required this.materiId});
@override
State<DetailMateriPage> createState() => _DetailMateriPageState();
}
class _DetailMateriPageState extends State<DetailMateriPage>
with SingleTickerProviderStateMixin {
final MateriService _materiService = MateriService();
late Future<dynamic> _materiDetailFuture;
bool _isLoading = true;
dynamic _materiData;
bool _isExpanded = false;
@override
void initState() {
super.initState();
_materiDetailFuture = _loadMateriDetails();
}
Future<dynamic> _loadMateriDetails() async {
try {
final data = await _materiService.fetchMateriWithDetails(widget.materiId);
setState(() {
_materiData = data;
_isLoading = false;
});
return data;
} catch (e) {
setState(() {
_isLoading = false;
});
throw e;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: bgColor1,
appBar: PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: ClipRRect(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(15),
bottomRight: Radius.circular(15),
),
child: AppBar(
title: Text(
_isLoading ? 'Loading...' : _materiData['judul'],
style: TextStyle(
color: primaryTextColor, fontWeight: bold, fontSize: 18),
),
backgroundColor: bgColor3,
elevation: 0,
),
),
),
body: _isLoading
? Center(
child: CircularProgressIndicator(
color: bgColor2,
))
: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Container(
width: double.infinity,
margin: const EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: bgColor2,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.05),
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: Column(
children: [
// Header clickable
InkWell(
onTap: () {
setState(() {
_isExpanded = !_isExpanded;
});
},
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
_materiData['judul'],
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
Icon(
_isExpanded
? Icons.keyboard_arrow_up
: Icons.keyboard_arrow_down,
color: Colors.white,
size: 28,
),
],
),
),
),
// Animated dropdown content
AnimatedSize(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
child: Column(
children: _isExpanded &&
_materiData['detail_materis'] != null
? _materiData['detail_materis']
.asMap()
.entries
.map<Widget>((entry) {
final index = entry.key;
final detail = entry.value;
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => IsiMateriPage(
items:
_materiData['detail_materis'],
initialIndex: index,
),
),
);
},
child: Container(
margin: const EdgeInsets.symmetric(
horizontal: 16, vertical: 6),
padding: const EdgeInsets.symmetric(
horizontal: 14, vertical: 12),
decoration: BoxDecoration(
color: bgColor1,
borderRadius:
BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black
.withValues(alpha: 0.05),
blurRadius: 6,
offset: const Offset(0, 3),
),
],
),
child: Row(
children: [
Container(
width: 30,
height: 30,
alignment: Alignment.center,
decoration: BoxDecoration(
color: primaryColor.withValues(
alpha: 0.15),
shape: BoxShape.circle,
),
child: Text(
'${index + 1}',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.normal,
color: primaryColor,
),
),
),
const SizedBox(width: 12),
Expanded(
child: Text(
detail['judul'],
style: TextStyle(
fontSize: 16,
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
),
const Icon(
Icons.arrow_forward_ios_rounded,
size: 16,
color: Colors.white,
),
],
),
),
);
}).toList()
: [],
),
),
],
),
),
Container(
width: double.infinity,
padding: const EdgeInsets.all(20),
margin: const EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: bgColor2.withValues(alpha: 0.9),
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.1),
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.info_outline_rounded,
color: Colors.white.withValues(alpha: 0.9),
size: 24,
),
const SizedBox(width: 8),
Text(
'Tentang Materi Pemula',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
],
),
const SizedBox(height: 12),
Text(
'Materi Pemula adalah level paling dasar dalam kemampuan bahasa Jepang. '
'Materi yang cocok ketika belum pernah belajar bahasa Jepang sama sekali, pada materi ini mempelajari hiragana dan katanana. Hiragana adalah salah satu dari tiga sistem penulisan dalam bahasa Jepang. Ini adalah sistem suku kata fonetik (setiap karakter mewakili satu suku kata), dan merupakan sistem tulisan pertama yang dipelajari oleh anak-anak Jepang maupun pelajar asing. Sedangkan Katakana adalah sistem penulisan kedua dalam bahasa Jepang, juga fonetik seperti Hiragana, tapi digunakan untuk keperluan yang berbeda, yaitu digunakan pada kalimat atau kata asing seperti transmart/apartment.',
style: TextStyle(
fontSize: 14,
color: Colors.white.withValues(alpha: 0.9),
height: 1.5,
),
),
],
),
),
if (_materiData['detail_materis'] != null &&
_materiData['detail_materis'].isNotEmpty)
Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: bgColor2.withValues(alpha: 0.9),
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.1),
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Mulai Belajar',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
const SizedBox(height: 12),
SizedBox(
height: 48,
width: double.infinity,
child: ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => IsiMateriPage(
items: _materiData['detail_materis'],
initialIndex: 0,
),
),
);
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
foregroundColor: bgColor2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
elevation: 2,
),
child: const Text(
'Mulai dari Sub Materi Pertama',
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
),
),
],
),
),
],
),
),
);
}
}