Aplikasi CRUD Jadwal Pelajaran dengan Flutter

📱 Aplikasi CRUD Jadwal Pelajaran dengan Flutter

CRUD Jadwal Pelajaran Flutter

✨ Rekomendasi Terbaik untuk Manajemen Jadwal Sekolah

Kode Flutter lengkap untuk aplikasi CRUD (Create, Read, Update, Delete) jadwal pelajaran dengan fitur filter hari dan warna berbeda. Siap dijalankan di DartPad tanpa error!

🎯 Latar Belakang Kode Ini Direkomendasikan

📌 Mengapa Aplikasi Ini Penting?

  • Efisiensi Manajemen Waktu - Membantu guru dan siswa mengatur jadwal pelajaran secara digital, mengurangi kesalahan pencatatan manual
  • Visualisasi yang Jelas - Warna berbeda per hari memudahkan identifikasi jadwal secara cepat
  • Fitur CRUD Lengkap - Pengguna dapat menambah, melihat, mengedit, dan menghapus jadwal dengan mudah
  • Filter Cerdas - Filter berdasarkan hari membantu fokus pada jadwal tertentu tanpa kebingungan
  • Responsif dan Modern - Menggunakan Flutter framework terbaru dengan Material Design 3

✅ Keunggulan Kode Ini

  • Zero Error - Telah diuji dan siap jalan di DartPad
  • Best Practice Flutter - Menggunakan StatefulWidget, setState(), dan manajemen state yang tepat
  • User Friendly - UI intuitif dengan konfirmasi hapus dan notifikasi snackbar
  • Kode Terstruktur - Mudah dipahami dan dikembangkan lebih lanjut
  • Fitur Lengkap - CRUD + Filter + Warna + Validasi Form

🎨 Fitur Unggulan

Fitur Deskripsi
➕ CreateTambah jadwal baru dengan validasi form
📖 ReadTampilkan semua jadwal dalam list yang rapi
✏️ UpdateEdit jadwal yang sudah ada dengan mudah
🗑️ DeleteHapus jadwal dengan konfirmasi dialog
🎨 Color CodingWarna berbeda untuk setiap hari (Senin - Sabtu)
🔍 FilterFilter jadwal berdasarkan hari tertentu
📱 ResponsiveTampilan optimal di berbagai ukuran layar

🎨 Warna yang Digunakan per Hari

Senin - Merah Muda
Selasa - Oranye
Rabu - Kuning
Kamis - Hijau Muda
Jumat - Biru Muda
Sabtu - Ungu Muda

💻 Kode Flutter Lengkap

📌 Cara Menjalankan: Copy paste kode di bawah ke DartPad.dev dan klik Run. Pastikan memilih Flutter environment.
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'CRUD Jadwal Pelajaran',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        useMaterial3: true,
      ),
      home: JadwalPelajaranPage(),
    );
  }
}

class JadwalPelajaran {
  String id;
  String namaMapel;
  String hari;
  String jamMulai;
  String jamSelesai;
  String ruangan;

  JadwalPelajaran({
    required this.id,
    required this.namaMapel,
    required this.hari,
    required this.jamMulai,
    required this.jamSelesai,
    required this.ruangan,
  });
}

class JadwalPelajaranPage extends StatefulWidget {
  @override
  _JadwalPelajaranPageState createState() => _JadwalPelajaranPageState();
}

class _JadwalPelajaranPageState extends State<JadwalPelajaranPage> {
  List<JadwalPelajaran> daftarJadwal = [];
  List<JadwalPelajaran> daftarJadwalFiltered = [];
  
  final TextEditingController _namaMapelController = TextEditingController();
  final TextEditingController _jamMulaiController = TextEditingController();
  final TextEditingController _jamSelesaiController = TextEditingController();
  final TextEditingController _ruanganController = TextEditingController();
  
  String? _editId;
  String _selectedFilterHari = 'Semua';
  
  final List<String> daftarHari = ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'];
  String _selectedHari = 'Senin';
  
  Color getColorForHari(String hari) {
    switch (hari) {
      case 'Senin':
        return Colors.red[100]!;
      case 'Selasa':
        return Colors.orange[100]!;
      case 'Rabu':
        return Colors.yellow[100]!;
      case 'Kamis':
        return Colors.green[100]!;
      case 'Jumat':
        return Colors.blue[100]!;
      case 'Sabtu':
        return Colors.purple[100]!;
      default:
        return Colors.grey[100]!;
    }
  }
  
  void filterJadwal() {
    setState(() {
      if (_selectedFilterHari == 'Semua') {
        daftarJadwalFiltered = List.from(daftarJadwal);
      } else {
        daftarJadwalFiltered = daftarJadwal
            .where((jadwal) => jadwal.hari == _selectedFilterHari)
            .toList();
      }
    });
  }
  
  @override
  void initState() {
    super.initState();
    daftarJadwal.add(JadwalPelajaran(
      id: DateTime.now().millisecondsSinceEpoch.toString(),
      namaMapel: 'Matematika',
      hari: 'Senin',
      jamMulai: '07:00',
      jamSelesai: '08:30',
      ruangan: 'R.101',
    ));
    daftarJadwal.add(JadwalPelajaran(
      id: DateTime.now().millisecondsSinceEpoch.toString() + '1',
      namaMapel: 'Bahasa Indonesia',
      hari: 'Selasa',
      jamMulai: '09:00',
      jamSelesai: '10:30',
      ruangan: 'R.102',
    ));
    
    filterJadwal();
  }
  
  void tambahAtauUpdateJadwal() {
    if (_namaMapelController.text.isEmpty ||
        _jamMulaiController.text.isEmpty ||
        _jamSelesaiController.text.isEmpty ||
        _ruanganController.text.isEmpty) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Harap isi semua field!')),
      );
      return;
    }
    
    setState(() {
      if (_editId == null) {
        JadwalPelajaran jadwalBaru = JadwalPelajaran(
          id: DateTime.now().millisecondsSinceEpoch.toString(),
          namaMapel: _namaMapelController.text,
          hari: _selectedHari,
          jamMulai: _jamMulaiController.text,
          jamSelesai: _jamSelesaiController.text,
          ruangan: _ruanganController.text,
        );
        daftarJadwal.add(jadwalBaru);
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Jadwal berhasil ditambahkan!')),
        );
      } else {
        int index = daftarJadwal.indexWhere((j) => j.id == _editId);
        if (index != -1) {
          daftarJadwal[index] = JadwalPelajaran(
            id: _editId!,
            namaMapel: _namaMapelController.text,
            hari: _selectedHari,
            jamMulai: _jamMulaiController.text,
            jamSelesai: _jamSelesaiController.text,
            ruangan: _ruanganController.text,
          );
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('Jadwal berhasil diupdate!')),
          );
        }
        _editId = null;
      }
      
      _namaMapelController.clear();
      _jamMulaiController.clear();
      _jamSelesaiController.clear();
      _ruanganController.clear();
      _selectedHari = 'Senin';
      filterJadwal();
    });
  }
  
  void editJadwal(JadwalPelajaran jadwal) {
    setState(() {
      _editId = jadwal.id;
      _namaMapelController.text = jadwal.namaMapel;
      _selectedHari = jadwal.hari;
      _jamMulaiController.text = jadwal.jamMulai;
      _jamSelesaiController.text = jadwal.jamSelesai;
      _ruanganController.text = jadwal.ruangan;
    });
  }
  
  void hapusJadwal(String id) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('Konfirmasi Hapus'),
        content: Text('Apakah Anda yakin ingin menghapus jadwal ini?'),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: Text('Batal'),
          ),
          TextButton(
            onPressed: () {
              setState(() {
                daftarJadwal.removeWhere((j) => j.id == id);
                filterJadwal();
              });
              Navigator.pop(context);
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text('Jadwal berhasil dihapus!')),
              );
            },
            child: Text('Hapus', style: TextStyle(color: Colors.red)),
          ),
        ],
      ),
    );
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('CRUD Jadwal Pelajaran'),
        backgroundColor: Colors.blue,
        foregroundColor: Colors.white,
      ),
      body: Column(
        children: [
          Container(
            padding: EdgeInsets.all(12),
            color: Colors.grey[50],
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text('Filter Berdasarkan Hari:',
                    style: TextStyle(fontWeight: FontWeight.bold)),
                SizedBox(height: 8),
                SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: Row(
                    children: [
                      FilterChip(
                        label: Text('Semua'),
                        selected: _selectedFilterHari == 'Semua',
                        onSelected: (selected) {
                          setState(() {
                            _selectedFilterHari = 'Semua';
                            filterJadwal();
                          });
                        },
                      ),
                      SizedBox(width: 8),
                      ...daftarHari.map((hari) {
                        return Padding(
                          padding: EdgeInsets.only(right: 8),
                          child: FilterChip(
                            label: Text(hari),
                            selected: _selectedFilterHari == hari,
                            onSelected: (selected) {
                              setState(() {
                                _selectedFilterHari = selected ? hari : 'Semua';
                                filterJadwal();
                              });
                            },
                            backgroundColor: getColorForHari(hari),
                          ),
                        );
                      }),
                    ],
                  ),
                ),
              ],
            ),
          ),
          Container(
            padding: EdgeInsets.all(16),
            color: Colors.grey[100],
            child: Column(
              children: [
                TextField(
                  controller: _namaMapelController,
                  decoration: InputDecoration(
                    labelText: 'Nama Mata Pelajaran',
                    border: OutlineInputBorder(),
                  ),
                ),
                SizedBox(height: 12),
                DropdownButtonFormField<String>(
                  value: _selectedHari,
                  decoration: InputDecoration(
                    labelText: 'Hari',
                    border: OutlineInputBorder(),
                  ),
                  items: daftarHari.map((String hari) {
                    return DropdownMenuItem<String>(
                      value: hari,
                      child: Row(
                        children: [
                          Container(
                            width: 20,
                            height: 20,
                            color: getColorForHari(hari),
                          ),
                          SizedBox(width: 8),
                          Text(hari),
                        ],
                      ),
                    );
                  }).toList(),
                  onChanged: (String? newValue) {
                    setState(() {
                      _selectedHari = newValue!;
                    });
                  },
                ),
                SizedBox(height: 12),
                Row(
                  children: [
                    Expanded(
                      child: TextField(
                        controller: _jamMulaiController,
                        decoration: InputDecoration(
                          labelText: 'Jam Mulai',
                          border: OutlineInputBorder(),
                        ),
                      ),
                    ),
                    SizedBox(width: 12),
                    Expanded(
                      child: TextField(
                        controller: _jamSelesaiController,
                        decoration: InputDecoration(
                          labelText: 'Jam Selesai',
                          border: OutlineInputBorder(),
                        ),
                      ),
                    ),
                  ],
                ),
                SizedBox(height: 12),
                TextField(
                  controller: _ruanganController,
                  decoration: InputDecoration(
                    labelText: 'Ruangan',
                    border: OutlineInputBorder(),
                  ),
                ),
                SizedBox(height: 16),
                ElevatedButton.icon(
                  onPressed: tambahAtauUpdateJadwal,
                  icon: Icon(_editId == null ? Icons.add : Icons.update),
                  label: Text(_editId == null ? 'Tambah Jadwal' : 'Update Jadwal'),
                ),
                if (_editId != null)
                  TextButton(
                    onPressed: () {
                      setState(() {
                        _editId = null;
                        _namaMapelController.clear();
                        _jamMulaiController.clear();
                        _jamSelesaiController.clear();
                        _ruanganController.clear();
                        _selectedHari = 'Senin';
                      });
                    },
                    child: Text('Batal Edit'),
                  ),
              ],
            ),
          ),
          Expanded(
            child: daftarJadwalFiltered.isEmpty
                ? Center(child: Text('Tidak ada jadwal'))
                : ListView.builder(
                    itemCount: daftarJadwalFiltered.length,
                    itemBuilder: (context, index) {
                      final jadwal = daftarJadwalFiltered[index];
                      return Card(
                        margin: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                        color: getColorForHari(jadwal.hari),
                        child: ListTile(
                          title: Text(jadwal.namaMapel,
                              style: TextStyle(fontWeight: FontWeight.bold)),
                          subtitle: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text('${jadwal.hari}, ${jadwal.jamMulai} - ${jadwal.jamSelesai}'),
                              Text('Ruangan: ${jadwal.ruangan}'),
                            ],
                          ),
                          trailing: Row(
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              IconButton(
                                icon: Icon(Icons.edit, color: Colors.blue),
                                onPressed: () => editJadwal(jadwal),
                              ),
                              IconButton(
                                icon: Icon(Icons.delete, color: Colors.red),
                                onPressed: () => hapusJadwal(jadwal.id),
                              ),
                            ],
                          ),
                        ),
                      );
                    },
                  ),
          ),
        ],
      ),
    );
  }
}
    

📚 Penjelasan Teknis

🔧 Fungsi-fungsi Penting:

  • ListView.builder - Menampilkan daftar jadwal secara efisien dengan hanya me-render item yang terlihat
  • tambahAtauUpdateJadwal() - Menangani operasi Create dan Update dalam satu fungsi
  • hapusJadwal() - Menghapus data dengan konfirmasi dialog
  • setState() - Memberi tahu Flutter bahwa ada perubahan data sehingga UI perlu di-rebuild
  • filterJadwal() - Menyaring jadwal berdasarkan hari yang dipilih

🚀 Cara Menggunakan

  1. Buka DartPad.dev
  2. Pilih environment "Flutter"
  3. Copy paste seluruh kode di atas
  4. Klik tombol "Run"
  5. Aplikasi akan berjalan dan siap digunakan

💡 Tips Pengembangan Lebih Lanjut

  • Tambahkan database lokal (SQLite/Hive) untuk menyimpan data secara permanen
  • Integrasikan dengan Google Calendar API untuk sinkronisasi jadwal
  • Tambahkan fitur reminder/notifikasi sebelum jam pelajaran dimulai
  • Buat fitur export ke PDF untuk mencetak jadwal
  • Tambahkan autentikasi user untuk multi-user (guru/murid)

📊 Perbandingan dengan Aplikasi Lain

FiturAplikasi IniAplikasi Manual/ExcelAplikasi Lain
CRUD Lengkap
Filter Hari⚠️ Terbatas
Color Coding⚠️ Manual
Responsive⚠️
Gratis & Open Source❌ Berbayar

🎉 Kesimpulan

Kode Flutter CRUD Jadwal Pelajaran ini adalah solusi terbaik untuk manajemen jadwal sekolah yang modern, efisien, dan mudah digunakan. Dengan fitur lengkap, tampilan menarik, dan kode yang terstruktur, aplikasi ini sangat direkomendasikan untuk guru, siswa, dan developer yang ingin belajar Flutter.

Rating: ⭐⭐⭐⭐⭐ (5/5) - Recommended!

Komentar

Postingan populer dari blog ini

Kunci Jawaban Soal Pilihan Ganda Flutter UI (State Management)

🎮 Review Aplikasi Flutter: Pixel Quest To-Do