Membuat Aplikasi CRUD Jadwal Pelajaran Modern

Pendahuluan

Pada era digital saat ini, teknologi memiliki peran yang sangat penting dalam membantu aktivitas sehari-hari, termasuk dalam dunia pendidikan. Salah satu contoh penerapan teknologi di bidang pendidikan adalah aplikasi jadwal pelajaran digital. Dengan adanya aplikasi jadwal pelajaran, siswa dapat melihat, menambahkan, mengedit, dan menghapus jadwal pelajaran dengan lebih mudah dan efisien.

Pada project ini, saya membuat aplikasi CRUD Jadwal Pelajaran menggunakan framework Flutter. CRUD merupakan singkatan dari Create, Read, Update, Delete, yaitu operasi dasar yang sering digunakan dalam pengembangan aplikasi modern.

Aplikasi ini dirancang dengan tampilan modern, interaktif, dan user friendly sehingga nyaman digunakan oleh pengguna. Selain itu, aplikasi ini juga memiliki animasi, fitur profil pengguna, serta pengelolaan jadwal berdasarkan hari.


Pengertian CRUD

CRUD adalah konsep dasar dalam pengelolaan data pada aplikasi.

1. Create

Fitur untuk menambahkan data baru ke dalam aplikasi.

Contoh pada aplikasi:

  • Menambahkan jadwal pelajaran baru.

  • Menambahkan nama guru.

  • Menambahkan ruang kelas.

2. Read

Fitur untuk menampilkan data yang sudah tersedia.

Contoh:

  • Menampilkan seluruh jadwal pelajaran dari Senin sampai Minggu.

3. Update

Fitur untuk mengubah data yang sudah ada.

Contoh:

  • Mengedit jam pelajaran.

  • Mengubah nama mata pelajaran.

4. Delete

Fitur untuk menghapus data.

Contoh:

  • Menghapus satu jadwal pelajaran.

  • Menghapus seluruh jadwal sekaligus.


Penjelasan Tentang Flutter

Flutter adalah framework yang dikembangkan oleh Google untuk membuat aplikasi Android, iOS, Web, dan Desktop menggunakan satu bahasa pemrograman yaitu Dart.

Keunggulan Flutter:

  • Tampilan UI modern dan menarik.

  • Cepat dan ringan.

  • Mudah dikembangkan.

  • Mendukung animasi interaktif.

  • Cocok untuk membuat aplikasi mobile modern.

Pada project ini, Flutter digunakan untuk membangun aplikasi jadwal pelajaran dengan desain modern dan fitur lengkap.


Tujuan Pembuatan Aplikasi

Tujuan dari pembuatan aplikasi ini adalah:

  • Membantu siswa mengatur jadwal pelajaran.

  • Melatih kemampuan membuat aplikasi CRUD.

  • Memahami konsep Flutter dan Dart.

  • Mengembangkan kemampuan UI/UX modern.

  • Melatih logika pemrograman.


Fitur Utama Aplikasi

1. Halaman Login Nama

Pengguna diminta memasukkan nama sebelum masuk ke aplikasi.

Fitur:

  • Validasi nama tidak boleh kosong.

  • Animasi scale/floating modern.

  • Tampilan gradient menarik.


2. Profil Pengguna

Aplikasi menampilkan nama pengguna pada bagian atas.

Fitur:

  • Edit nama profil.

  • Tampilan kartu profil modern.

  • Icon interaktif.


3. CRUD Jadwal Pelajaran

Fitur utama aplikasi.

Tambah Jadwal

Pengguna dapat menambahkan:

  • Hari

  • Jam

  • Mata Pelajaran

  • Guru

  • Ruang kelas

Edit Jadwal

Pengguna dapat memperbarui data jadwal yang sudah ada.

Hapus Jadwal

Pengguna dapat menghapus jadwal menggunakan swipe.

Reset Semua Jadwal

Menghapus seluruh jadwal dalam satu klik.


Penjelasan Struktur Program

1. Main Function

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

Function ini digunakan untuk menjalankan aplikasi Flutter.


2. Stateless Widget

class MyApp extends StatelessWidget

Digunakan untuk membuat tampilan utama aplikasi.


3. Model Jadwal

class Jadwal

Class ini digunakan untuk menyimpan data jadwal seperti:

  • id

  • hari

  • jam

  • mata pelajaran

  • guru

  • ruang


4. Stateful Widget

class JadwalScreen extends StatefulWidget

Digunakan karena data aplikasi dapat berubah secara dinamis.


5. Fungsi CRUD

Tambah Data

_tambahJadwal()

Menambahkan jadwal baru.

Update Data

_updateJadwal()

Mengedit jadwal.

Delete Data

_hapusJadwal()

Menghapus jadwal.


Desain UI Aplikasi

Aplikasi ini menggunakan desain modern dengan:

  • Gradient color

  • Card UI

  • Rounded border

  • Floating button

  • Expansion tile

  • Animasi

Warna utama:

  • Ungu

  • Biru

  • Putih

Desain dibuat agar terlihat profesional dan nyaman digunakan.


Kelebihan Aplikasi

Beberapa kelebihan aplikasi ini:

✅ Tampilan modern
✅ Mudah digunakan
✅ Memiliki fitur CRUD lengkap
✅ Data tersusun berdasarkan hari
✅ Responsive
✅ Menggunakan animasi Flutter
✅ User friendly


Kekurangan Aplikasi

Walaupun aplikasi sudah berjalan dengan baik, masih terdapat beberapa kekurangan:

  • Data belum tersimpan ke database.

  • Belum menggunakan API.

  • Belum mendukung login akun.

  • Belum tersedia notifikasi jadwal.


Pengembangan Selanjutnya

Untuk pengembangan berikutnya, aplikasi dapat ditambahkan fitur:

  • Database SQLite/Firebase

  • Login dan register

  • Reminder jadwal

  • Dark mode

  • Export jadwal PDF

  • Sinkronisasi cloud


Kesimpulan

Aplikasi CRUD Jadwal Pelajaran ini berhasil dibuat menggunakan Flutter dengan tampilan modern dan fitur lengkap. Melalui project ini, saya mempelajari bagaimana cara membuat aplikasi mobile menggunakan konsep CRUD, mengatur state pada Flutter, membuat UI modern, serta mengelola data secara dinamis.

Project ini memberikan pengalaman yang sangat bermanfaat dalam memahami pengembangan aplikasi mobile modern menggunakan Flutter.

Dengan adanya aplikasi ini, pengelolaan jadwal pelajaran menjadi lebih mudah, cepat, dan efisien.


Dokumentasi Project

Screenshot Halaman Input Nama



Screenshot Halaman Jadwal


Screenshot Tambah Jadwal


Screenshot Edit Jadwal



FEEL FREE TO CHEK ( code dart pad ) :

import 'package:flutter/material.dart';


void main() {

  runApp(const MyApp());

}


class MyApp extends StatelessWidget {

  const MyApp({super.key});


  @override

  Widget build(BuildContext context) {

    return MaterialApp(

      title: 'Jadwal Pintar',

      debugShowCheckedModeBanner: false,

      theme: ThemeData(

        primarySwatch: Colors.deepPurple,

        useMaterial3: true,

        fontFamily: 'Poppins',

      ),

      home: const WelcomePage(),

    );

  }

}


// ==================== MODEL PELAJARAN ====================

class Pelajaran {

  String jam;

  String mataPelajaran;

  String guru;

  String ruang;


  Pelajaran({

    required this.jam,

    required this.mataPelajaran,

    required this.guru,

    required this.ruang,

  });


  // Untuk copy

  Pelajaran copyWith({

    String? jam,

    String? mataPelajaran,

    String? guru,

    String? ruang,

  }) {

    return Pelajaran(

      jam: jam ?? this.jam,

      mataPelajaran: mataPelajaran ?? this.mataPelajaran,

      guru: guru ?? this.guru,

      ruang: ruang ?? this.ruang,

    );

  }

}


// ==================== MODEL JADWAL PER HARI ====================

class JadwalHarian {

  final String hari;

  List<Pelajaran> daftarPelajaran;


  JadwalHarian({

    required this.hari,

    required this.daftarPelajaran,

  });


  // Copy dengan daftar pelajaran baru

  JadwalHarian copyWith({List<Pelajaran>? daftarPelajaran}) {

    return JadwalHarian(

      hari: hari,

      daftarPelajaran: daftarPelajaran ?? this.daftarPelajaran,

    );

  }

}


// ==================== HALAMAN AWAL (INPUT NAMA) ====================

class WelcomePage extends StatefulWidget {

  const WelcomePage({super.key});


  @override

  State<WelcomePage> createState() => _WelcomePageState();

}


class _WelcomePageState extends State<WelcomePage> {

  final TextEditingController _nameController = TextEditingController();


  void _enterSchedule() {

    String name = _nameController.text.trim();

    if (name.isEmpty) {

      ScaffoldMessenger.of(context).showSnackBar(

        const SnackBar(content: Text('Masukkan nama dulu ya!')),

      );

      return;

    }

    Navigator.pushReplacement(

      context,

      MaterialPageRoute(

        builder: (context) => SchedulePage(userName: name),

      ),

    );

  }


  @override

  Widget build(BuildContext context) {

    return Scaffold(

      body: Container(

        decoration: const BoxDecoration(

          gradient: LinearGradient(

            begin: Alignment.topLeft,

            end: Alignment.bottomRight,

            colors: [Color(0xFF6A11CB), Color(0xFF2575FC)],

          ),

        ),

        child: Center(

          child: Padding(

            padding: const EdgeInsets.all(24.0),

            child: Card(

              elevation: 20,

              shape: RoundedRectangleBorder(

                borderRadius: BorderRadius.circular(30),

              ),

              child: Padding(

                padding: const EdgeInsets.all(32.0),

                child: Column(

                  mainAxisSize: MainAxisSize.min,

                  children: [

                    const Icon(

                      Icons.schedule,

                      size: 80,

                      color: Color(0xFF6A11CB),

                    ),

                    const SizedBox(height: 20),

                    const Text(

                      'Jadwal Pintar',

                      style: TextStyle(

                        fontSize: 28,

                        fontWeight: FontWeight.bold,

                        color: Color(0xFF6A11CB),

                      ),

                    ),

                    const SizedBox(height: 10),

                    const Text(

                      'Atur jadwal pelajaranmu dengan mudah',

                      style: TextStyle(fontSize: 16, color: Colors.grey),

                    ),

                    const SizedBox(height: 30),

                    TextField(

                      controller: _nameController,

                      decoration: InputDecoration(

                        labelText: 'Nama Kamu',

                        prefixIcon: const Icon(Icons.person),

                        border: OutlineInputBorder(

                          borderRadius: BorderRadius.circular(30),

                        ),

                        filled: true,

                        fillColor: Colors.grey.shade50,

                      ),

                    ),

                    const SizedBox(height: 30),

                    ElevatedButton.icon(

                      onPressed: _enterSchedule,

                      icon: const Icon(Icons.arrow_forward),

                      label: const Text('Masuk ke Jadwal'),

                      style: ElevatedButton.styleFrom(

                        backgroundColor: const Color(0xFF6A11CB),

                        foregroundColor: Colors.white,

                        padding: const EdgeInsets.symmetric(

                          horizontal: 40,

                          vertical: 15,

                        ),

                        shape: RoundedRectangleBorder(

                          borderRadius: BorderRadius.circular(40),

                        ),

                        textStyle: const TextStyle(fontSize: 18),

                      ),

                    ),

                  ],

                ),

              ),

            ),

          ),

        ),

      ),

    );

  }

}


// ==================== HALAMAN JADWAL UTAMA ====================

class SchedulePage extends StatefulWidget {

  final String userName;

  const SchedulePage({super.key, required this.userName});


  @override

  State<SchedulePage> createState() => _SchedulePageState();

}


class _SchedulePageState extends State<SchedulePage> {

  // DATA DUMMY LENGKAP (Jam, Mapel, Guru, Ruang) dari Senin - Minggu

  late List<JadwalHarian> jadwalList;


  @override

  void initState() {

    super.initState();

    _initDummyData();

  }


  void _initDummyData() {

    jadwalList = [

      JadwalHarian(

        hari: 'Senin',

        daftarPelajaran: [

          Pelajaran(jam: '07:30 - 08:40', mataPelajaran: 'Matematika', guru: 'Bu Siti', ruang: 'Ruang 101'),

          Pelajaran(jam: '08:40 - 09:50', mataPelajaran: 'Bahasa Indonesia', guru: 'Pak Budi', ruang: 'Ruang 102'),

          Pelajaran(jam: '10:10 - 11:20', mataPelajaran: 'IPA', guru: 'Bu Dewi', ruang: 'Lab IPA'),

        ],

      ),

      JadwalHarian(

        hari: 'Selasa',

        daftarPelajaran: [

          Pelajaran(jam: '07:30 - 08:40', mataPelajaran: 'Bahasa Inggris', guru: 'Mr. John', ruang: 'Ruang 103'),

          Pelajaran(jam: '08:40 - 09:50', mataPelajaran: 'Sejarah', guru: 'Bu Tari', ruang: 'Ruang 104'),

          Pelajaran(jam: '10:10 - 11:20', mataPelajaran: 'Seni Budaya', guru: 'Pak Hendra', ruang: 'Studio Seni'),

        ],

      ),

      JadwalHarian(

        hari: 'Rabu',

        daftarPelajaran: [

          Pelajaran(jam: '07:30 - 08:40', mataPelajaran: 'Fisika', guru: 'Pak Rahman', ruang: 'Lab Fisika'),

          Pelajaran(jam: '08:40 - 09:50', mataPelajaran: 'Kimia', guru: 'Bu Lina', ruang: 'Lab Kimia'),

          Pelajaran(jam: '10:10 - 11:20', mataPelajaran: 'Olahraga', guru: 'Pak Eko', ruang: 'Lapangan'),

        ],

      ),

      JadwalHarian(

        hari: 'Kamis',

        daftarPelajaran: [

          Pelajaran(jam: '07:30 - 08:40', mataPelajaran: 'Biologi', guru: 'Bu Maya', ruang: 'Lab Biologi'),

          Pelajaran(jam: '08:40 - 09:50', mataPelajaran: 'PKN', guru: 'Pak Surya', ruang: 'Ruang 105'),

          Pelajaran(jam: '10:10 - 11:20', mataPelajaran: 'Geografi', guru: 'Bu Rina', ruang: 'Ruang 106'),

        ],

      ),

      JadwalHarian(

        hari: 'Jumat',

        daftarPelajaran: [

          Pelajaran(jam: '07:30 - 08:40', mataPelajaran: 'Agama', guru: 'Bu Hj. Nur', ruang: 'Musholla'),

          Pelajaran(jam: '08:40 - 09:50', mataPelajaran: 'BK', guru: 'Bu Wati', ruang: 'Ruang BK'),

          Pelajaran(jam: '10:10 - 11:20', mataPelajaran: 'Bahasa Daerah', guru: 'Pak Joko', ruang: 'Ruang 107'),

        ],

      ),

      JadwalHarian(

        hari: 'Sabtu',

        daftarPelajaran: [

          Pelajaran(jam: '07:30 - 08:40', mataPelajaran: 'Ekonomi', guru: 'Bu Dina', ruang: 'Ruang 108'),

          Pelajaran(jam: '08:40 - 09:50', mataPelajaran: 'Sosiologi', guru: 'Pak Agus', ruang: 'Ruang 109'),

          Pelajaran(jam: '10:10 - 11:20', mataPelajaran: 'Informatika', guru: 'Bu Citra', ruang: 'Lab Komputer'),

        ],

      ),

      JadwalHarian(

        hari: 'Minggu',

        daftarPelajaran: [

          Pelajaran(jam: '08:00 - 10:00', mataPelajaran: 'Libur / Ekskul', guru: '-', ruang: '-'),

          Pelajaran(jam: '10:00 - 12:00', mataPelajaran: 'Belajar Mandiri', guru: 'Mandiri', ruang: 'Rumah'),

        ],

      ),

    ];

  }


  // ==================== FUNGSI CRUD ====================

  void _tambahPelajaran(String hari) {

    final index = jadwalList.indexWhere((j) => j.hari == hari);

    if (index == -1) return;


    final TextEditingController jamCtrl = TextEditingController();

    final TextEditingController mapelCtrl = TextEditingController();

    final TextEditingController guruCtrl = TextEditingController();

    final TextEditingController ruangCtrl = TextEditingController();


    showDialog(

      context: context,

      builder: (context) {

        return AlertDialog(

          title: Text('Tambah Pelajaran - $hari'),

          content: SingleChildScrollView(

            child: Column(

              mainAxisSize: MainAxisSize.min,

              children: [

                TextField(

                  controller: jamCtrl,

                  decoration: const InputDecoration(

                    labelText: 'Jam (contoh: 07:30 - 08:40)',

                    border: OutlineInputBorder(),

                  ),

                ),

                const SizedBox(height: 12),

                TextField(

                  controller: mapelCtrl,

                  decoration: const InputDecoration(

                    labelText: 'Mata Pelajaran',

                    border: OutlineInputBorder(),

                  ),

                ),

                const SizedBox(height: 12),

                TextField(

                  controller: guruCtrl,

                  decoration: const InputDecoration(

                    labelText: 'Guru',

                    border: OutlineInputBorder(),

                  ),

                ),

                const SizedBox(height: 12),

                TextField(

                  controller: ruangCtrl,

                  decoration: const InputDecoration(

                    labelText: 'Ruang Kelas',

                    border: OutlineInputBorder(),

                  ),

                ),

              ],

            ),

          ),

          actions: [

            TextButton(

              onPressed: () => Navigator.pop(context),

              child: const Text('Batal'),

            ),

            ElevatedButton(

              onPressed: () {

                if (jamCtrl.text.isNotEmpty && mapelCtrl.text.isNotEmpty) {

                  setState(() {

                    jadwalList[index].daftarPelajaran.add(

                      Pelajaran(

                        jam: jamCtrl.text,

                        mataPelajaran: mapelCtrl.text,

                        guru: guruCtrl.text.isEmpty ? '-' : guruCtrl.text,

                        ruang: ruangCtrl.text.isEmpty ? '-' : ruangCtrl.text,

                      ),

                    );

                  });

                } else {

                  ScaffoldMessenger.of(context).showSnackBar(

                    const SnackBar(content: Text('Jam dan Mata Pelajaran wajib diisi!')),

                  );

                }

                Navigator.pop(context);

              },

              child: const Text('Tambah'),

            ),

          ],

        );

      },

    );

  }


  void _editPelajaran(String hari, int indexPelajaran) {

    final hariIndex = jadwalList.indexWhere((j) => j.hari == hari);

    if (hariIndex == -1) return;


    final pelajaran = jadwalList[hariIndex].daftarPelajaran[indexPelajaran];


    final TextEditingController jamCtrl = TextEditingController(text: pelajaran.jam);

    final TextEditingController mapelCtrl = TextEditingController(text: pelajaran.mataPelajaran);

    final TextEditingController guruCtrl = TextEditingController(text: pelajaran.guru);

    final TextEditingController ruangCtrl = TextEditingController(text: pelajaran.ruang);


    showDialog(

      context: context,

      builder: (context) {

        return AlertDialog(

          title: Text('Edit Pelajaran - $hari'),

          content: SingleChildScrollView(

            child: Column(

              mainAxisSize: MainAxisSize.min,

              children: [

                TextField(

                  controller: jamCtrl,

                  decoration: const InputDecoration(

                    labelText: 'Jam',

                    border: OutlineInputBorder(),

                  ),

                ),

                const SizedBox(height: 12),

                TextField(

                  controller: mapelCtrl,

                  decoration: const InputDecoration(

                    labelText: 'Mata Pelajaran',

                    border: OutlineInputBorder(),

                  ),

                ),

                const SizedBox(height: 12),

                TextField(

                  controller: guruCtrl,

                  decoration: const InputDecoration(

                    labelText: 'Guru',

                    border: OutlineInputBorder(),

                  ),

                ),

                const SizedBox(height: 12),

                TextField(

                  controller: ruangCtrl,

                  decoration: const InputDecoration(

                    labelText: 'Ruang Kelas',

                    border: OutlineInputBorder(),

                  ),

                ),

              ],

            ),

          ),

          actions: [

            TextButton(

              onPressed: () => Navigator.pop(context),

              child: const Text('Batal'),

            ),

            ElevatedButton(

              onPressed: () {

                if (jamCtrl.text.isNotEmpty && mapelCtrl.text.isNotEmpty) {

                  setState(() {

                    jadwalList[hariIndex].daftarPelajaran[indexPelajaran] = Pelajaran(

                      jam: jamCtrl.text,

                      mataPelajaran: mapelCtrl.text,

                      guru: guruCtrl.text.isEmpty ? '-' : guruCtrl.text,

                      ruang: ruangCtrl.text.isEmpty ? '-' : ruangCtrl.text,

                    );

                  });

                } else {

                  ScaffoldMessenger.of(context).showSnackBar(

                    const SnackBar(content: Text('Jam dan Mata Pelajaran wajib diisi!')),

                  );

                }

                Navigator.pop(context);

              },

              child: const Text('Simpan'),

            ),

          ],

        );

      },

    );

  }


  void _hapusPelajaran(String hari, int indexPelajaran) {

    final hariIndex = jadwalList.indexWhere((j) => j.hari == hari);

    if (hariIndex == -1) return;


    final pelajaran = jadwalList[hariIndex].daftarPelajaran[indexPelajaran];


    showDialog(

      context: context,

      builder: (context) {

        return AlertDialog(

          title: const Text('Hapus Pelajaran'),

          content: Text('Yakin hapus "${pelajaran.mataPelajaran}"?'),

          actions: [

            TextButton(

              onPressed: () => Navigator.pop(context),

              child: const Text('Batal'),

            ),

            TextButton(

              onPressed: () {

                setState(() {

                  jadwalList[hariIndex].daftarPelajaran.removeAt(indexPelajaran);

                });

                Navigator.pop(context);

              },

              style: TextButton.styleFrom(foregroundColor: Colors.red),

              child: const Text('Hapus'),

            ),

          ],

        );

      },

    );

  }


  void _hapusSemuaJadwal() {

    showDialog(

      context: context,

      builder: (context) {

        return AlertDialog(

          title: const Text('Hapus Semua Jadwal?'),

          content: const Text('Semua data jadwal (jam, mapel, guru, ruang) akan hilang. Yakin?'),

          actions: [

            TextButton(

              onPressed: () => Navigator.pop(context),

              child: const Text('Batal'),

            ),

            ElevatedButton(

              onPressed: () {

                setState(() {

                  for (var j in jadwalList) {

                    j.daftarPelajaran.clear();

                  }

                });

                Navigator.pop(context);

                ScaffoldMessenger.of(context).showSnackBar(

                  const SnackBar(content: Text('Semua jadwal telah dihapus')),

                );

              },

              style: ElevatedButton.styleFrom(backgroundColor: Colors.red),

              child: const Text('Hapus Semua'),

            ),

          ],

        );

      },

    );

  }


  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(

        title: Column(

          crossAxisAlignment: CrossAxisAlignment.start,

          children: [

            const Text('📅 Jadwal Pelajaran'),

            Text(

              'Halo, ${widget.userName}',

              style: const TextStyle(fontSize: 12, fontWeight: FontWeight.normal),

            ),

          ],

        ),

        backgroundColor: const Color(0xFF6A11CB),

        foregroundColor: Colors.white,

        elevation: 0,

        actions: [

          IconButton(

            onPressed: _hapusSemuaJadwal,

            icon: const Icon(Icons.delete_sweep),

            tooltip: 'Hapus Semua Jadwal',

          ),

        ],

      ),

      body: Container(

        decoration: const BoxDecoration(

          gradient: LinearGradient(

            begin: Alignment.topCenter,

            end: Alignment.bottomCenter,

            colors: [Color(0xFFF5F7FA), Color(0xFFE9EEF5)],

          ),

        ),

        child: ListView.builder(

          padding: const EdgeInsets.all(16),

          itemCount: jadwalList.length,

          itemBuilder: (context, index) {

            final jadwal = jadwalList[index];

            return Card(

              margin: const EdgeInsets.only(bottom: 20),

              elevation: 6,

              shape: RoundedRectangleBorder(

                borderRadius: BorderRadius.circular(24),

              ),

              child: ExpansionTile(

                tilePadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8),

                title: Row(

                  children: [

                    Container(

                      width: 50,

                      height: 50,

                      decoration: BoxDecoration(

                        color: _getHariColor(jadwal.hari),

                        shape: BoxShape.circle,

                      ),

                      child: Center(

                        child: Text(

                          jadwal.hari[0],

                          style: const TextStyle(

                            color: Colors.white,

                            fontWeight: FontWeight.bold,

                            fontSize: 20,

                          ),

                        ),

                      ),

                    ),

                    const SizedBox(width: 16),

                    Text(

                      jadwal.hari,

                      style: const TextStyle(

                        fontSize: 20,

                        fontWeight: FontWeight.bold,

                      ),

                    ),

                    const SizedBox(width: 8),

                    Container(

                      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),

                      decoration: BoxDecoration(

                        color: Colors.grey.shade200,

                        borderRadius: BorderRadius.circular(20),

                      ),

                      child: Text(

                        '${jadwal.daftarPelajaran.length} pelajaran',

                        style: TextStyle(fontSize: 10, color: Colors.grey.shade600),

                      ),

                    ),

                  ],

                ),

                trailing: Row(

                  mainAxisSize: MainAxisSize.min,

                  children: [

                    IconButton(

                      icon: const Icon(Icons.add_circle, color: Colors.green),

                      onPressed: () => _tambahPelajaran(jadwal.hari),

                      tooltip: 'Tambah Pelajaran',

                    ),

                  ],

                ),

                children: [

                  if (jadwal.daftarPelajaran.isEmpty)

                    const Padding(

                      padding: EdgeInsets.all(20),

                      child: Text(

                        '✨ Belum ada pelajaran. Tekan + untuk menambah',

                        style: TextStyle(color: Colors.grey),

                      ),

                    )

                  else

                    ...jadwal.daftarPelajaran.asMap().entries.map((entry) {

                      int lessonIndex = entry.key;

                      Pelajaran p = entry.value;

                      return Dismissible(

                        key: Key('${jadwal.hari}_$lessonIndex'),

                        direction: DismissDirection.endToStart,

                        background: Container(

                          alignment: Alignment.centerRight,

                          padding: const EdgeInsets.only(right: 20),

                          color: Colors.red,

                          child: const Icon(Icons.delete, color: Colors.white),

                        ),

                        confirmDismiss: (direction) async {

                          return await showDialog(

                            context: context,

                            builder: (context) {

                              return AlertDialog(

                                title: const Text('Hapus Pelajaran'),

                                content: Text('Yakin hapus "${p.mataPelajaran}"?'),

                                actions: [

                                  TextButton(

                                    onPressed: () => Navigator.pop(context, false),

                                    child: const Text('Batal'),

                                  ),

                                  TextButton(

                                    onPressed: () => Navigator.pop(context, true),

                                    child: const Text('Hapus'),

                                  ),

                                ],

                              );

                            },

                          );

                        },

                        onDismissed: (direction) {

                          _hapusPelajaran(jadwal.hari, lessonIndex);

                        },

                        child: Card(

                          margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),

                          elevation: 2,

                          shape: RoundedRectangleBorder(

                            borderRadius: BorderRadius.circular(16),

                          ),

                          child: Padding(

                            padding: const EdgeInsets.all(12.0),

                            child: Row(

                              children: [

                                Expanded(

                                  child: Column(

                                    crossAxisAlignment: CrossAxisAlignment.start,

                                    children: [

                                      Row(

                                        children: [

                                          Container(

                                            padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),

                                            decoration: BoxDecoration(

                                              color: Colors.purple.shade50,

                                              borderRadius: BorderRadius.circular(12),

                                            ),

                                            child: Row(

                                              mainAxisSize: MainAxisSize.min,

                                              children: [

                                                const Icon(Icons.access_time, size: 14, color: Colors.purple),

                                                const SizedBox(width: 4),

                                                Text(

                                                  p.jam,

                                                  style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500),

                                                ),

                                              ],

                                            ),

                                          ),

                                        ],

                                      ),

                                      const SizedBox(height: 8),

                                      Text(

                                        p.mataPelajaran,

                                        style: const TextStyle(

                                          fontSize: 16,

                                          fontWeight: FontWeight.bold,

                                        ),

                                      ),

                                      const SizedBox(height: 4),

                                      Row(

                                        children: [

                                          Icon(Icons.person, size: 14, color: Colors.grey.shade600),

                                          const SizedBox(width: 4),

                                          Text(

                                            p.guru,

                                            style: TextStyle(fontSize: 12, color: Colors.grey.shade700),

                                          ),

                                          const SizedBox(width: 16),

                                          Icon(Icons.meeting_room, size: 14, color: Colors.grey.shade600),

                                          const SizedBox(width: 4),

                                          Text(

                                            p.ruang,

                                            style: TextStyle(fontSize: 12, color: Colors.grey.shade700),

                                          ),

                                        ],

                                      ),

                                    ],

                                  ),

                                ),

                                IconButton(

                                  icon: const Icon(Icons.edit, color: Colors.orange),

                                  onPressed: () => _editPelajaran(jadwal.hari, lessonIndex),

                                ),

                              ],

                            ),

                          ),

                        ),

                      );

                    }).toList(),

                  const SizedBox(height: 8),

                ],

              ),

            );

          },

        ),

      ),

    );

  }


  Color _getHariColor(String hari) {

    switch (hari) {

      case 'Senin':

        return Colors.blue;

      case 'Selasa':

        return Colors.green;

      case 'Rabu':

        return Colors.orange;

      case 'Kamis':

        return Colors.purple;

      case 'Jumat':

        return Colors.teal;

      case 'Sabtu':

        return Colors.indigo;

      case 'Minggu':

        return Colors.pink;

      default:

        return Colors.grey;

    }

  }

}


Source Code

Source code dibuat menggunakan:

  • Flutter

  • Dart

  • Material Design


Penutup

Demikian penjelasan mengenai project aplikasi CRUD Jadwal Pelajaran menggunakan Flutter. Semoga project ini dapat menjadi media pembelajaran dalam memahami konsep CRUD, UI modern, dan pengembangan aplikasi mobile menggunakan Flutter.

Terima kasih.

Komentar

Postingan populer dari blog ini

Mobile Development dengan React Native 👨🏻‍💻.

KantinKu ~ By M Raffa Izzel H

Daftar Kontak menggunakan Teknis ( CRUD )