import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Jadwal Pelajaran',
theme: ThemeData(primarySwatch: Colors.indigo, useMaterial3: true),
darkTheme: ThemeData(brightness: Brightness.dark, useMaterial3: true),
themeMode: ThemeMode.system,
home: JadwalPage(),
);
}
}
// Model Data
class JadwalModel {
String id, mataPelajaran, hari, jam, ruang;
int warnaIndeks;
JadwalModel({required this.id, required this.mataPelajaran, required this.hari, required this.jam, required this.ruang, this.warnaIndeks = 0});
Map<String,dynamic> toJson() => {'id':id,'mataPelajaran':mataPelajaran,'hari':hari,'jam':jam,'ruang':ruang,'warnaIndeks':warnaIndeks};
factory JadwalModel.fromJson(Map<String,dynamic> json) => JadwalModel(id:json['id'],mataPelajaran:json['mataPelajaran'],hari:json['hari'],jam:json['jam'],ruang:json['ruang'],warnaIndeks:json['warnaIndeks']);
}
// Halaman Utama dengan CRUD + setState
class JadwalPage extends StatefulWidget {
@override
_JadwalPageState createState() => _JadwalPageState();
}
class _JadwalPageState extends State<JadwalPage> {
List<JadwalModel> jadwalList = [];
List<JadwalModel> filteredList = [];
String searchQuery = '';
String filterHari = 'Semua';
final List<String> daftarHari = ['Semua','Senin','Selasa','Rabu','Kamis','Jumat','Sabtu'];
@override
void initState() { super.initState(); _loadData(); }
// Simpan ke Local Storage
Future<void> _saveData() async {
final prefs = await SharedPreferences.getInstance();
List<String> jsonList = jadwalList.map((j) => jsonEncode(j.toJson())).toList();
await prefs.setStringList('jadwal_list', jsonList);
}
// Load dari Local Storage
Future<void> _loadData() async {
final prefs = await SharedPreferences.getInstance();
List<String>? jsonList = prefs.getStringList('jadwal_list');
if (jsonList != null) {
setState(() { jadwalList = jsonList.map((j) => JadwalModel.fromJson(jsonDecode(j))).toList(); _filterData(); });
} else {
// Data dummy awal
setState(() {
jadwalList = [JadwalModel(id: DateTime.now().toString(), mataPelajaran: 'Flutter UI', hari: 'Selasa', jam: '09:00-11:00', ruang: 'Lab 1')];
_saveData(); _filterData();
});
}
}
void _filterData() => setState(() {
filteredList = jadwalList.where((j) =>
(filterHari == 'Semua' || j.hari == filterHari) &&
j.mataPelajaran.toLowerCase().contains(searchQuery.toLowerCase())
).toList();
});
// CRUD OPERATIONS
void tambahData(JadwalModel j) { setState(() { jadwalList.add(j); _saveData(); _filterData(); }); }
void editData(int idx, JadwalModel j) { setState(() { jadwalList[idx] = j; _saveData(); _filterData(); }); }
void hapusData(int idx) { setState(() { jadwalList.removeAt(idx); _saveData(); _filterData(); }); }
// Dialog Input (Tambah/Edit)
void tampilDialog({JadwalModel? jadwalLama, int? index}) {
bool isEdit = jadwalLama != null;
TextEditingController mapelC = TextEditingController(text: jadwalLama?.mataPelajaran ?? '');
TextEditingController jamC = TextEditingController(text: jadwalLama?.jam ?? '');
TextEditingController ruangC = TextEditingController(text: jadwalLama?.ruang ?? '');
String selectedHari = jadwalLama?.hari ?? daftarHari[1];
showModalBottomSheet(context: context, isScrollControlled: true, builder: (_) {
return StatefulBuilder(builder: (ctx, setStateBottom) {
return Padding(padding: EdgeInsets.only(bottom: MediaQuery.of(ctx).viewInsets.bottom, left: 20, right: 20, top: 20),
child: Column(mainAxisSize: MainAxisSize.min, children: [
Text(isEdit ? 'Edit Jadwal' : 'Tambah Jadwal', style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold)),
TextField(controller: mapelC, decoration: InputDecoration(labelText: 'Mata Pelajaran', prefixIcon: Icon(Icons.book))),
DropdownButtonFormField(value: selectedHari, items: daftarHari.skip(1).map((h) => DropdownMenuItem(value: h, child: Text(h))).toList(),
onChanged: (v) => setStateBottom(() => selectedHari = v!)),
TextField(controller: jamC, decoration: InputDecoration(labelText: 'Jam', prefixIcon: Icon(Icons.access_time))),
TextField(controller: ruangC, decoration: InputDecoration(labelText: 'Ruang', prefixIcon: Icon(Icons.location_on))),
SizedBox(height: 20),
Row(children: [
Expanded(child: OutlinedButton(onPressed: () => Navigator.pop(ctx), child: Text('Batal'))),
SizedBox(width: 10),
Expanded(child: ElevatedButton(onPressed: () {
if (mapelC.text.isNotEmpty) {
if (isEdit) editData(index!, JadwalModel(id: jadwalLama!.id, mataPelajaran: mapelC.text, hari: selectedHari, jam: jamC.text, ruang: ruangC.text));
else tambahData(JadwalModel(id: DateTime.now().toString(), mataPelajaran: mapelC.text, hari: selectedHari, jam: jamC.text, ruang: ruangC.text));
Navigator.pop(ctx);
}
}, child: Text(isEdit ? 'Update' : 'Simpan')))
]),
SizedBox(height: 20)
]),
);
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Jadwal Pelajaran'), centerTitle: true, flexibleSpace: Container(decoration: BoxDecoration(gradient: LinearGradient(colors: [Colors.indigo, Colors.blue])))),
body: Column(children: [
Padding(padding: EdgeInsets.all(12), child: TextField(onChanged: (v) => setState(() { searchQuery = v; _filterData(); }), decoration: InputDecoration(hintText: 'Cari jadwal...', prefixIcon: Icon(Icons.search), border: OutlineInputBorder(borderRadius: BorderRadius.circular(30))))),
SizedBox(height: 40, child: ListView.builder(scrollDirection: Axis.horizontal, padding: EdgeInsets.symmetric(horizontal: 12), itemCount: daftarHari.length, itemBuilder: (_, i) => Padding(padding: EdgeInsets.only(right: 8), child: FilterChip(label: Text(daftarHari[i]), selected: filterHari == daftarHari[i], onSelected: (_) => setState(() { filterHari = daftarHari[i]; _filterData(); }))))),
Expanded(child: filteredList.isEmpty ? Center(child: Text('Belum ada jadwal')) : ListView.builder(itemCount: filteredList.length, itemBuilder: (_, i) {
var j = filteredList[i];
int originalIdx = jadwalList.indexOf(j);
return Card(margin: EdgeInsets.all(8), child: ListTile(
leading: CircleAvatar(child: Text(j.mataPelajaran[0])),
title: Text(j.mataPelajaran, style: TextStyle(fontWeight: FontWeight.bold)),
subtitle: Text('${j.hari} | ${j.jam} | ${j.ruang}'),
trailing: Row(mainAxisSize: MainAxisSize.min, children: [
IconButton(icon: Icon(Icons.edit, color: Colors.blue), onPressed: () => tampilDialog(jadwalLama: j, index: originalIdx)),
IconButton(icon: Icon(Icons.delete, color: Colors.red), onPressed: () => hapusData(originalIdx))
])
));
}))
]),
floatingActionButton: FloatingActionButton(onPressed: () => tampilDialog(), child: Icon(Icons.add)),
);
}
}
Komentar
Posting Komentar