MEMBUAT JADWAL PELAJARAN
ini kode aplikasi yang saya buat:
// pubspec.yaml
/*
name: jadwal_pelajaran
description: Aplikasi Jadwal Pelajaran Bernuansa Pink
publish_to: 'none'
version: 1.0.0+1
environment:
sdk: '>=3.0.0 <4.0.0'
dependencies:
flutter:
sdk: flutter
intl: ^0.18.1
shared_preferences: ^2.2.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
flutter:
uses-material-design: true
*/
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Jadwal Pelajaran',
theme: ThemeData(
primarySwatch: Colors.pink,
fontFamily: 'Poppins',
appBarTheme: const AppBarTheme(
backgroundColor: Colors.pink,
foregroundColor: Colors.white,
elevation: 0,
),
floatingActionButtonTheme: const FloatingActionButtonThemeData(
backgroundColor: Colors.pink,
foregroundColor: Colors.white,
),
inputDecorationTheme: InputDecorationTheme(
filled: true,
fillColor: Colors.pink.shade50,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide(color: Colors.pink, width: 2),
),
),
),
home: const JadwalPage(),
debugShowCheckedModeBanner: false,
);
}
}
// Model Jadwal
class Jadwal {
String id;
String hari;
String jamMulai;
String jamSelesai;
String mataPelajaran;
String ruang;
Jadwal({
required this.id,
required this.hari,
required this.jamMulai,
required this.jamSelesai,
required this.mataPelajaran,
required this.ruang,
});
Map<String, dynamic> toJson() => {
'id': id,
'hari': hari,
'jamMulai': jamMulai,
'jamSelesai': jamSelesai,
'mataPelajaran': mataPelajaran,
'ruang': ruang,
};
factory Jadwal.fromJson(Map<String, dynamic> json) => Jadwal(
id: json['id'],
hari: json['hari'],
jamMulai: json['jamMulai'],
jamSelesai: json['jamSelesai'],
mataPelajaran: json['mataPelajaran'],
ruang: json['ruang'],
);
}
// Halaman Utama
class JadwalPage extends StatefulWidget {
const JadwalPage({super.key});
@override
State<JadwalPage> createState() => _JadwalPageState();
}
class _JadwalPageState extends State<JadwalPage> {
List<Jadwal> _jadwalList = [];
String _selectedHari = 'Senin';
final List<String> _daftarHari = [
'Senin',
'Selasa',
'Rabu',
'Kamis',
'Jumat',
'Sabtu'
];
@override
void initState() {
super.initState();
_loadJadwal();
}
Future<void> _loadJadwal() async {
final prefs = await SharedPreferences.getInstance();
final String? jadwalString = prefs.getString('jadwal_list');
if (jadwalString != null) {
List<dynamic> jsonList = json.decode(jadwalString);
setState(() {
_jadwalList = jsonList.map((json) => Jadwal.fromJson(json)).toList();
});
}
}
Future<void> _saveJadwal() async {
final prefs = await SharedPreferences.getInstance();
List<Map<String, dynamic>> jsonList =
_jadwalList.map((jadwal) => jadwal.toJson()).toList();
await prefs.setString('jadwal_list', json.encode(jsonList));
}
void _tambahJadwal(Jadwal jadwalBaru) {
setState(() {
_jadwalList.add(jadwalBaru);
});
_saveJadwal();
}
void _editJadwal(String id, Jadwal jadwalBaru) {
setState(() {
final index = _jadwalList.indexWhere((j) => j.id == id);
if (index != -1) {
_jadwalList[index] = jadwalBaru;
}
});
_saveJadwal();
}
void _hapusJadwal(String id) {
setState(() {
_jadwalList.removeWhere((j) => j.id == id);
});
_saveJadwal();
}
List<Jadwal> get _jadwalFiltered {
return _jadwalList.where((j) => j.hari == _selectedHari).toList();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.pink.shade50,
body: SafeArea(
child: Column(
children: [
// Header dengan gradasi pink
Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.pink.shade400, Colors.pink.shade700],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(30),
bottomRight: Radius.circular(30),
),
),
child: Column(
children: [
const Text(
'π Jadwal Pelajaran',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
const SizedBox(height: 20),
// Hari selector
Container(
height: 50,
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.3),
borderRadius: BorderRadius.circular(25),
),
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: _daftarHari.length,
itemBuilder: (context, index) {
final hari = _daftarHari[index];
return GestureDetector(
onTap: () {
setState(() {
_selectedHari = hari;
});
},
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 20, vertical: 10),
margin: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: _selectedHari == hari
? Colors.white
: Colors.transparent,
borderRadius: BorderRadius.circular(25),
),
child: Center(
child: Text(
hari,
style: TextStyle(
color: _selectedHari == hari
? Colors.pink.shade700
: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
);
},
),
),
],
),
),
const SizedBox(height: 20),
// Daftar Jadwal
Expanded(
child: _jadwalFiltered.isEmpty
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.schedule,
size: 80,
color: Colors.pink.shade200,
),
const SizedBox(height: 10),
Text(
'Belum ada jadwal untuk hari $_selectedHari',
style: TextStyle(
fontSize: 16,
color: Colors.pink.shade300,
),
),
const SizedBox(height: 10),
TextButton.icon(
onPressed: () => _showFormDialog(null),
icon: const Icon(Icons.add),
label: const Text('Tambah Jadwal'),
style: TextButton.styleFrom(
foregroundColor: Colors.pink.shade700,
),
),
],
),
)
: ListView.builder(
padding: const EdgeInsets.symmetric(horizontal: 16),
itemCount: _jadwalFiltered.length,
itemBuilder: (context, index) {
final jadwal = _jadwalFiltered[index];
return Container(
margin: const EdgeInsets.only(bottom: 12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: Colors.pink.shade100,
blurRadius: 10,
offset: const Offset(0, 5),
),
],
),
child: ListTile(
contentPadding: const EdgeInsets.all(15),
leading: Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.pink.shade100,
borderRadius: BorderRadius.circular(15),
),
child: Icon(
Icons.book,
color: Colors.pink.shade700,
size: 30,
),
),
title: Text(
jadwal.mataPelajaran,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 5),
Text(
'⏰ ${jadwal.jamMulai} - ${jadwal.jamSelesai}',
style: TextStyle(color: Colors.grey.shade600),
),
Text(
'π« ${jadwal.ruang}',
style: TextStyle(color: Colors.grey.shade600),
),
],
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Icon(Icons.edit,
color: Colors.pink.shade400),
onPressed: () => _showFormDialog(jadwal),
),
IconButton(
icon: Icon(Icons.delete,
color: Colors.pink.shade400),
onPressed: () => _confirmDelete(jadwal.id),
),
],
),
),
);
},
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => _showFormDialog(null),
child: const Icon(Icons.add),
),
);
}
void _showFormDialog(Jadwal? jadwal) {
final isEdit = jadwal != null;
final formKey = GlobalKey<FormState>();
final hariController = TextEditingController(text: jadwal?.hari ?? 'Senin');
final jamMulaiController = TextEditingController(text: jadwal?.jamMulai ?? '');
final jamSelesaiController = TextEditingController(text: jadwal?.jamSelesai ?? '');
final mataPelajaranController = TextEditingController(text: jadwal?.mataPelajaran ?? '');
final ruangController = TextEditingController(text: jadwal?.ruang ?? '');
String selectedHari = jadwal?.hari ?? 'Senin';
showDialog(
context: context,
builder: (context) {
return StatefulBuilder(
builder: (context, setStateDialog) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25),
),
child: Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: Colors.white,
),
child: Form(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
isEdit ? '✏️ Edit Jadwal' : '➕ Tambah Jadwal',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.pink.shade700,
),
),
const SizedBox(height: 20),
// Hari
DropdownButtonFormField<String>(
value: selectedHari,
decoration: InputDecoration(
labelText: 'Hari',
labelStyle: TextStyle(color: Colors.pink.shade700),
prefixIcon: Icon(Icons.calendar_today,
color: Colors.pink.shade700),
),
items: _daftarHari.map((hari) {
return DropdownMenuItem(
value: hari,
child: Text(hari),
);
}).toList(),
onChanged: (value) {
setStateDialog(() {
selectedHari = value!;
});
},
),
const SizedBox(height: 15),
// Jam Mulai
TextFormField(
controller: jamMulaiController,
decoration: InputDecoration(
labelText: 'Jam Mulai (contoh: 07:30)',
labelStyle: TextStyle(color: Colors.pink.shade700),
prefixIcon:
Icon(Icons.access_time, color: Colors.pink.shade700),
),
validator: (value) =>
value!.isEmpty ? 'Jam mulai harus diisi' : null,
),
const SizedBox(height: 15),
// Jam Selesai
TextFormField(
controller: jamSelesaiController,
decoration: InputDecoration(
labelText: 'Jam Selesai (contoh: 09:00)',
labelStyle: TextStyle(color: Colors.pink.shade700),
prefixIcon:
Icon(Icons.access_time, color: Colors.pink.shade700),
),
validator: (value) =>
value!.isEmpty ? 'Jam selesai harus diisi' : null,
),
const SizedBox(height: 15),
// Mata Pelajaran
TextFormField(
controller: mataPelajaranController,
decoration: InputDecoration(
labelText: 'Mata Pelajaran',
labelStyle: TextStyle(color: Colors.pink.shade700),
prefixIcon: Icon(Icons.book, color: Colors.pink.shade700),
),
validator: (value) =>
value!.isEmpty ? 'Mata pelajaran harus diisi' : null,
),
const SizedBox(height: 15),
// Ruang
TextFormField(
controller: ruangController,
decoration: InputDecoration(
labelText: 'Ruang',
labelStyle: TextStyle(color: Colors.pink.shade700),
prefixIcon: Icon(Icons.location_on,
color: Colors.pink.shade700),
),
validator: (value) =>
value!.isEmpty ? 'Ruang harus diisi' : null,
),
const SizedBox(height: 25),
Row(
children: [
Expanded(
child: TextButton(
onPressed: () => Navigator.pop(context),
style: TextButton.styleFrom(
foregroundColor: Colors.grey,
padding: const EdgeInsets.symmetric(vertical: 12),
),
child: const Text('Batal'),
),
),
const SizedBox(width: 10),
Expanded(
child: ElevatedButton(
onPressed: () {
if (formKey.currentState!.validate()) {
final newJadwal = Jadwal(
id: isEdit
? jadwal!.id
: DateTime.now().millisecondsSinceEpoch
.toString(),
hari: selectedHari,
jamMulai: jamMulaiController.text,
jamSelesai: jamSelesaiController.text,
mataPelajaran: mataPelajaranController.text,
ruang: ruangController.text,
);
if (isEdit) {
_editJadwal(jadwal.id, newJadwal);
} else {
_tambahJadwal(newJadwal);
}
Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
isEdit ? 'Jadwal berhasil diubah!' : 'Jadwal berhasil ditambahkan!'),
backgroundColor: Colors.pink,
),
);
}
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.pink,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 12),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: Text(isEdit ? 'Update' : 'Simpan'),
),
),
],
),
],
),
),
),
);
},
);
},
);
}
void _confirmDelete(String id) {
showDialog(
context: context,
builder: (context) => AlertDialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
title: const Text('Hapus Jadwal'),
content: const Text('Apakah Anda yakin ingin menghapus jadwal ini?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('Batal'),
),
ElevatedButton(
onPressed: () {
_hapusJadwal(id);
Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Jadwal berhasil dihapus!'),
backgroundColor: Colors.pink,
),
);
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
foregroundColor: Colors.white,
),
child: const Text('Hapus'),
),
],
),
);
}
}
“Membangun Aplikasi Jadwal Pelajaran dengan Flutter: CRUD, Penyimpanan Lokal, dan Sentuhan Nuansa Pink
# Pendahuluan: Awal Mula Ide
Halo, para pembaca setia blog saya! π
Beberapa waktu lalu, saya mendapatkan tugas untuk membuat sebuah aplikasi sederhana menggunakan Flutter. Tema yang saya pilih adalah **aplikasi jadwal pelajaran**. Mengapa jadwal pelajaran? Karena sebagai seorang pelajar/mahasiswa, saya sering kali kewalahan mengingat jadwal kuliah atau sekolah yang berubah-ubah. Ditambah lagi, catatan jadwal di kertas sering hilang atau rusak. Maka dari itu, saya berpikir, kenapa tidak membuat aplikasi sendiri yang bisa saya atur sesuai kebutuhan dan selera saya?
Awalnya saya hanya berpikir untuk membuat tampilan statis yang menampilkan jadwal saja. Namun, semakin dalam saya belajar Flutter, saya sadar bahwa aplikasi yang baik adalah aplikasi yang **dinamis** dan **interaktif**. Saya pun memutuskan untuk menambahkan fitur-fitur penting seperti **menambah jadwal baru**, **mengedit jadwal yang sudah ada**, serta **menghapus jadwal** yang tidak diperlukan. Tidak lupa, karena saya sangat menyukai warna pink, saya memberikan sentuhan desain bernuansa pink pada seluruh antarmuka aplikasi. Hasilnya? Sebuah aplikasi yang tidak hanya fungsional, tetapi juga estetik dan menyenangkan untuk digunakan sehari-hari.
---
# Fitur-Fitur Unggulan dalam Aplikasi
Aplikasi jadwal pelajaran yang saya buat ini memiliki beberapa fitur utama yang akan saya jelaskan satu per satu di bawah ini.
## 1. Pemilihan Hari (Senin – Sabtu)
Fitur pertama yang saya buat adalah kemampuan untuk memilih hari. Saya menyediakan **enam pilihan hari**, mulai dari Senin hingga Sabtu. Mengapa tidak termasuk Minggu? Karena di lingkungan saya, hari Minggu biasanya tidak ada kegiatan belajar mengajar, jadi saya putuskan untuk fokus pada hari-hari sekolah saja.
Pengguna dapat dengan mudah menekan nama hari yang diinginkan, dan secara otomatis daftar jadwal yang tampil akan berubah sesuai dengan hari yang dipilih. Untuk memberikan pengalaman yang lebih nyaman, saya membuat tombol hari ini berbentuk seperti **tab yang dapat digeser (scrollable)**. Jadi meskipun layar HP kecil, pengguna tetap bisa mengakses semua pilihan hari dengan mudah.
## 2. Menampilkan Jadwal dalam Bentuk Card
Setiap jadwal yang sudah tersimpan akan ditampilkan dalam bentuk **card** yang rapi dan informatif. Di dalam card tersebut, pengguna bisa melihat:
- Nama mata pelajaran (dengan ukuran huruf tebal)
- Jam mulai dan jam selesai (lengkap dengan ikon jam ⏰)
- Ruang atau lokasi pelajaran (lengkap dengan ikon lokasi π«)
Selain itu, di sisi kanan card terdapat dua tombol aksi, yaitu **ikon pensil untuk mengedit** dan **ikon tempat sampah untuk menghapus**. Desain card ini saya beri warna putih bersih dengan bayangan halus berwarna pink muda agar terlihat lembut dan tidak menyilaukan mata.
## 3. Menambah Jadwal Baru
Fitur tambah jadwal adalah jantung dari aplikasi ini. Saya menyediakan **tombol aksi melayang (Floating Action Button)** berwarna pink yang jika ditekan akan memunculkan sebuah formulir (dialog). Di dalam formulir tersebut, pengguna diminta untuk mengisi:
- Hari (dari dropdown pilihan Senin–Sabtu)
- Jam mulai
- Jam selesai
- Nama mata pelajaran
- Ruang
Saya juga menambahkan **validasi formulir** (form validation) sehingga pengguna tidak bisa menyimpan jadwal jika ada kolom yang kosong. Hal ini penting untuk menjaga agar data yang tersimpan selalu lengkap dan konsisten.
Setelah pengguna menekan tombol "Simpan", jadwal baru akan langsung muncul di daftar jadwal pada hari yang dipilih, tanpa perlu me-refresh aplikasi. Ini dimungkinkan karena saya menggunakan `setState()` untuk memperbarui antarmuka secara real-time.
## 4. Mengedit Jadwal yang Sudah Ada
Tidak jarang kita membuat kesalahan saat memasukkan jadwal, misalnya salah menulis jam atau ruang. Oleh karena itu, fitur **edit** menjadi sangat penting. Ketika pengguna menekan ikon pensil pada sebuah card, akan muncul formulir yang sudah **terisi otomatis** dengan data jadwal yang sedang dipilih.
Pengguna cukup mengubah informasi yang diperlukan, lalu menekan tombol "Update". Data lama akan digantikan dengan data baru, dan tampilan daftar jadwal akan langsung berubah. Pengalaman ini saya rancang agar semulus mungkin, sehingga pengguna tidak perlu menghapus dan menambah ulang dari awal.
## 5. Menghapus Jadwal dengan Konfirmasi
Fitur hapus juga saya lengkapi dengan **dialog konfirmasi**. Ketika pengguna menekan ikon tempat sampah, akan muncul popup yang bertanya, "Apakah Anda yakin ingin menghapus jadwal ini?". Hal ini untuk mencegah penghapusan yang tidak disengaja. Jika pengguna menekan "Hapus", maka jadwal tersebut akan hilang dari daftar. Jika pengguna membatalkan, maka tidak ada perubahan apa pun.
Saya merasa fitur konfirmasi ini sangat penting, karena dalam dunia nyata, kita tidak ingin kehilangan data jadwal hanya karena salah tekan tombol.
## 6. Penyimpanan Data Lokal (Tidak Hilang Meskipun Aplikasi Ditutup)
Salah satu tantangan terbesar dalam membuat aplikasi ini adalah bagaimana **menyimpan data** agar tidak hilang ketika aplikasi ditutup dan dibuka kembali. Saya memutuskan untuk menggunakan **SharedPreferences**, yaitu mekanisme penyimpanan data sederhana yang disediakan oleh Flutter.
Setiap kali pengguna menambah, mengedit, atau menghapus jadwal, seluruh daftar jadwal akan otomatis disimpan ke dalam memori internal ponsel dalam format JSON. Ketika aplikasi dijalankan ulang, data akan dimuat kembali sehingga pengguna tidak perlu memasukkan jadwal dari awal lagi. Ini adalah fitur yang menurut saya paling krusial, karena tanpa penyimpanan, aplikasi jadwal akan terasa kurang berguna.
---
# Desain Antarmuka: Bernuansa Pink yang Lembut dan Ceria
Saya ingin aplikasi ini tidak hanya berguna, tetapi juga **menyenangkan untuk dilihat**. Oleh karena itu, saya memilih **warna pink** sebagai tema utama. Berikut adalah detail desain yang saya terapkan:
- **Gradasi pink di bagian header**: Dari pink 400 ke pink 700, menciptakan efek gradasi yang lembut dan elegan.
- **Warna latar belakang utama**: Pink 50 (pink paling muda), sehingga tidak terlalu mencolok dan nyaman di mata.
- **Tombol utama (FAB dan tombol simpan)**: Warna pink solid dengan teks putih.
- **Ikon dan aksen**: Menggunakan pink 400 hingga pink 700 untuk memberikan aksen tanpa berlebihan.
- **Card jadwal**: Putih bersih dengan bayangan (shadow) berwarna pink 100, sehingga terlihat seperti melayang.
- **Font**: Menggunakan gaya yang bersih dan mudah dibaca.
Saya percaya bahwa desain yang menarik secara visual dapat meningkatkan mood pengguna ketika menggunakan aplikasi. Apalagi untuk hal yang berhubungan dengan kegiatan sekolah atau kuliah, tampilan yang ceria bisa mengurangi rasa stres.
---
# Tantangan dan Pembelajaran Selama Pengembangan
Tentu saja, membuat aplikasi ini tidak sepenuhnya mulus. Ada beberapa tantangan yang saya hadapi:
1. **Memahami SharedPreferences**: Awalnya saya bingung bagaimana cara menyimpan dan memuat daftar objek jadwal yang jumlahnya bisa berubah-ubah. Setelah belajar, saya menemukan cara untuk mengonversi daftar jadwal ke format JSON dan menyimpannya sebagai string.
2. **Mengelola State**: Saya harus memastikan bahwa setiap kali data berubah (tambah, edit, hapus), tampilan langsung diperbarui. Penggunaan `setState()` memang sederhana, tetapi perlu ditempatkan di tempat yang tepat.
3. **Validasi Formulir**: Membuat formulir yang dinamis di dalam dialog membutuhkan teknik `StatefulBuilder` agar dropdown hari bisa berubah tanpa menutup dialog. Ini adalah pelajaran berharga bagi saya.
4. **Desain Responsif**: Memastikan bahwa aplikasi tetap nyaman digunakan di berbagai ukuran layar, dari HP kecil hingga tablet.
Setiap tantangan yang berhasil saya atasi membuat saya semakin percaya diri dengan kemampuan Flutter. Saya jadi lebih memahami konsep **widget, state management sederhana, penyimpanan lokal, dan navigasi antar-hari**.
---
# Kode yang Saya Gunakan (Gambaran Umum)
Tanpa membahas terlalu teknis, berikut adalah gambaran struktur kode yang saya buat:
- **Model Jadwal**: Sebuah kelas Dart yang berisi properti seperti `id`, `hari`, `jamMulai`, `jamSelesai`, `mataPelajaran`, dan `ruang`. Dilengkapi dengan metode `toJson()` dan `fromJson()` untuk keperluan penyimpanan.
- **Halaman Utama (JadwalPage)**: Berisi `AppBar` dengan gradasi, daftar hari yang bisa dipilih, serta `ListView` untuk menampilkan card-card jadwal.
- **Fungsi CRUD**: `_tambahJadwal()`, `_editJadwal()`, `_hapusJadwal()` yang masing-masing memanggil `_saveJadwal()` untuk menyimpan perubahan ke SharedPreferences.
- **Form Dialog**: Sebuah dialog yang dapat digunakan untuk mode tambah maupun edit, dengan field-field yang sudah divalidasi.
- **Konfirmasi Hapus**: Menggunakan `AlertDialog` sederhana dengan dua tombol aksi.
Saya juga menggunakan package `intl` untuk kemungkinan pengembangan ke depan (misalnya memformat waktu), meskipun di versi saat ini belum sepenuhnya dimanfaatkan.
---
# Cara Menjalankan Aplikasi (Jika Pembaca Ingin Mencoba)
Bagi pembaca yang tertarik untuk mencoba atau mempelajari kode ini, berikut langkah-langkah singkatnya:
1. Pastikan Flutter SDK sudah terinstall di komputer.
2. Buat project baru: `flutter create jadwal_pelajaran`
3. Ganti isi `pubspec.yaml` dengan dependencies yang diperlukan (`shared_preferences` dan `intl`).
4. Ganti seluruh isi `lib/main.dart` dengan kode lengkap yang telah saya bagikan.
5. Jalankan `flutter pub get` untuk mengunduh package.
6. Jalankan aplikasi dengan `flutter run` di perangkat atau emulator.
Saya juga menyarankan untuk mengeksplorasi sendiri kode tersebut, mengubah warna sesuai selera, atau menambahkan fitur-fitur baru seperti notifikasi atau ekspor data.
---
# Penutup dan Harapan ke Depan
Membuat aplikasi jadwal pelajaran ini adalah pengalaman yang sangat menyenangkan dan mendidik. Saya tidak hanya belajar tentang teknis pemrograman Flutter, tetapi juga tentang bagaimana merancang aplikasi yang **berguna, mudah digunakan, dan enak dipandang**.
Ke depannya, saya berencana untuk menambahkan beberapa fitur baru, seperti:
- **Notifikasi pengingat** sebelum jam pelajaran dimulai.
- **Ekspor jadwal ke PDF** agar bisa dicetak.
- **Mode gelap (dark mode)** dengan tetap mempertahankan nuansa pink.
- **Pencarian jadwal** berdasarkan mata pelajaran atau ruang.
Saya berharap tulisan ini dapat menginspirasi teman-teman yang sedang belajar Flutter untuk terus berkarya. Jangan takut untuk memulai, jangan takut untuk bereksperimen dengan warna dan desain, dan yang terpenting, **nikmati setiap prosesnya**!
Terima kasih sudah membaca sampai akhir. Jika ada pertanyaan atau saran, silakan tulis di kolom komentar ya. Sampai jumpa di postingan berikutnya! ππ✨
---
#Flutter #BelajarFlutter #JadwalPelajaran #AplikasiSekolah #PinkAesthetic #CodingJourney #CRUD #SharedPreferences
Komentar
Posting Komentar