Aplikasi CRUD Jadwal perlajaran

Membuat Aplikasi Jadwal Pelajaran Modern dengan Flutter

Halo sobat developer! Hari ini kita akan membahas bagaimana cara membangun aplikasi Jadwal Pelajaran yang interaktif menggunakan Flutter. Aplikasi ini bukan sekadar daftar statis, tapi sudah dilengkapi dengan fungsi CRUD (Create, Read, Update, Delete) serta fitur pencarian dan filter hari.

Fitur Utama Aplikasi:

  • Manajemen Data: Tambah, edit, dan hapus jadwal dengan mudah.
  • 🔍 Fitur Pencarian: Cari mata pelajaran tertentu secara real-time.
  • 📅 Filter Hari: Kelompokkan jadwal berdasarkan hari menggunakan FilterChip.
  • 📊 Statistik Ringkas: Pantau jumlah total jadwal dan tugas yang sudah selesai.
  • 🎨 UI Modern: Menggunakan tema warna Indigo yang profesional dan bersih.

Source Code Lengkap

Silakan salin kode di bawah ini ke dalam file main.dart di proyek Flutter Anda:

import 'package:flutter/material.dart';

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),
      home: JadwalPage(),
    );
  }
}

class Jadwal {
  String nama;
  String hari;
  String waktu;
  bool isCompleted;

  Jadwal({
    required this.nama,
    required this.hari,
    required this.waktu,
    this.isCompleted = false,
  });
}

class JadwalPage extends StatefulWidget {
  @override
  _JadwalPageState createState() => _JadwalPageState();
}

class _JadwalPageState extends State<JadwalPage> {
  List<Jadwal> jadwalList = [];
  String searchQuery = '';
  String filterHari = 'Semua';

  final List<String> daftarHari = [
    'Semua', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu',
  ];

  void tambahData(Jadwal jadwal) {
    setState(() {
      jadwalList.add(jadwal);
    });
  }

  void editData(int index, Jadwal jadwalBaru) {
    setState(() {
      jadwalList[index] = jadwalBaru;
    });
  }

  void hapusData(int index) {
    setState(() {
      jadwalList.removeAt(index);
    });
  }

  void toggleComplete(int index) {
    setState(() {
      jadwalList[index].isCompleted = !jadwalList[index].isCompleted;
    });
  }

  void tampilDialog({Jadwal? jadwalLama, int? index}) {
    final isEditing = jadwalLama != null;
    TextEditingController namaController = TextEditingController(text: jadwalLama?.nama ?? "");
    String selectedHari = jadwalLama?.hari ?? 'Senin';
    String selectedWaktu = jadwalLama?.waktu ?? '08:00';

    showDialog(
      context: context,
      builder: (context) {
        return StatefulBuilder(
          builder: (context, setStateDialog) {
            return AlertDialog(
              title: Text(isEditing ? "Edit Jadwal" : "Tambah Jadwal Baru"),
              content: SingleChildScrollView(
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    TextField(
                      controller: namaController,
                      decoration: InputDecoration(
                        labelText: "Mata Pelajaran",
                        prefixIcon: Icon(Icons.book),
                        border: OutlineInputBorder(borderRadius: BorderRadius.circular(10)),
                      ),
                    ),
                    SizedBox(height: 16),
                    DropdownButtonFormField<String>(
                      value: selectedHari,
                      items: daftarHari.where((h) => h != 'Semua').map((hari) {
                        return DropdownMenuItem(value: hari, child: Text(hari));
                      }).toList(),
                      onChanged: (val) => setStateDialog(() => selectedHari = val!),
                      decoration: InputDecoration(
                        labelText: "Hari",
                        prefixIcon: Icon(Icons.calendar_today),
                        border: OutlineInputBorder(borderRadius: BorderRadius.circular(10)),
                      ),
                    ),
                    SizedBox(height: 16),
                    TextField(
                      controller: TextEditingController(text: selectedWaktu),
                      onChanged: (val) => selectedWaktu = val,
                      decoration: InputDecoration(
                        labelText: "Waktu",
                        prefixIcon: Icon(Icons.access_time),
                        border: OutlineInputBorder(borderRadius: BorderRadius.circular(10)),
                      ),
                    ),
                  ],
                ),
              ),
              actions: [
                TextButton(onPressed: () => Navigator.pop(context), child: Text("Batal")),
                ElevatedButton(
                  onPressed: () {
                    if (namaController.text.isNotEmpty) {
                      final baru = Jadwal(nama: namaController.text, hari: selectedHari, waktu: selectedWaktu);
                      isEditing ? editData(index!, baru) : tambahData(baru);
                      Navigator.pop(context);
                    }
                  },
                  child: Text("Simpan"),
                ),
              ],
            );
          },
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    final filtered = jadwalList.where((j) {
      final matchesSearch = j.nama.toLowerCase().contains(searchQuery.toLowerCase());
      final matchesHari = filterHari == 'Semua' || j.hari == filterHari;
      return matchesSearch && matchesHari;
    }).toList();

    return Scaffold(
      appBar: AppBar(
        title: Text("Jadwal Pelajaran"),
        backgroundColor: Colors.indigo,
        bottom: PreferredSize(
          preferredSize: Size.fromHeight(60),
          child: Container(
            height: 50,
            child: ListView.builder(
              scrollDirection: Axis.horizontal,
              itemCount: daftarHari.length,
              itemBuilder: (context, i) => Padding(
                padding: EdgeInsets.symmetric(horizontal: 4),
                child: FilterChip(
                  label: Text(daftarHari[i]),
                  selected: filterHari == daftarHari[i],
                  onSelected: (val) => setState(() => filterHari = daftarHari[i]),
                ),
              ),
            ),
          ),
        ),
      ),
      body: Column(
        children: [
          Padding(
            padding: EdgeInsets.all(16),
            child: TextField(
              onChanged: (val) => setState(() => searchQuery = val),
              decoration: InputDecoration(
                hintText: "Cari mata pelajaran...",
                prefixIcon: Icon(Icons.search),
                filled: true,
                fillColor: Colors.grey[100],
                border: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none),
              ),
            ),
          ),
          Expanded(
            child: ListView.builder(
              itemCount: filtered.length,
              itemBuilder: (context, i) {
                final item = filtered[i];
                return Card(
                  margin: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                  child: ListTile(
                    leading: CircleAvatar(
                      backgroundColor: item.isCompleted ? Colors.green : Colors.indigo,
                      child: Icon(item.isCompleted ? Icons.check : Icons.book, color: Colors.white),
                    ),
                    title: Text(item.nama, style: TextStyle(
                      decoration: item.isCompleted ? TextDecoration.lineThrough : null,
                      fontWeight: FontWeight.bold
                    )),
                    subtitle: Text("${item.hari} | ${item.waktu}"),
                    trailing: Row(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        IconButton(icon: Icon(Icons.check_circle, color: Colors.green), onPressed: () => toggleComplete(jadwalList.indexOf(item))),
                        IconButton(icon: Icon(Icons.delete, color: Colors.red), onPressed: () => hapusData(jadwalList.indexOf(item))),
                      ],
                    ),
                  ),
                );
              },
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => tampilDialog(),
        child: Icon(Icons.add),
        backgroundColor: Colors.indigo,
      ),
    );
  }
}
        

Kesimpulan

Dengan kode ini, Anda telah berhasil membuat aplikasi manajemen jadwal yang fungsional dan memiliki tampilan menarik. Flutter memudahkan kita mengelola state (data) sehingga fitur seperti filter dan pencarian bisa berjalan dengan sangat mulus.

Tips: Anda bisa mengembangkan aplikasi ini lebih lanjut dengan menambahkan fitur database lokal seperti Sqflite atau Shared Preferences agar data tidak hilang saat aplikasi ditutup.

Selamat mencoba dan Happy Coding! 🚀

Komentar

Postingan populer dari blog ini

Jenis-jenis sistem operasi mobile

flutter todo list app

Aplikasi Manajemen Barang Pinjaman dengan Flutter + Fitur Upload Gambar