source-code/
student-hub
Public
codeCodeinfoIssues 0call_splitPull Requestsplay_circleActions
student-hub/lib/screens/add_edit_schedule_screen.dart
text278 lines9.3 KB
import 'package:flutter/material.dart';
import '../models/class_schedule.dart';
import '../services/database_helper.dart';

class AddEditScheduleScreen extends StatefulWidget {
  final ClassSchedule? schedule;
  final String defaultSemester;

  const AddEditScheduleScreen({
    super.key,
    this.schedule,
    required this.defaultSemester,
  });

  @override
  State<AddEditScheduleScreen> createState() => _AddEditScheduleScreenState();
}

class _AddEditScheduleScreenState extends State<AddEditScheduleScreen> {
  // Pengendali (Controllers) untuk input teks
  final _courseController = TextEditingController();
  final _roomController = TextEditingController();
  
  // Variabel penampung state (status) formulir
  String _selectedDay = "Senin";
  late String _selectedSemester;
  TimeOfDay? _startTime;
  TimeOfDay? _endTime;
  bool _isMakeup = false;
  bool _isCancelled = false;

  final List<String> _days = ["Senin", "Selasa", "Rabu", "Kamis", "Jumat"];
  final List<String> _semesters = [
    "Semester 1",
    "Semester 2",
    "Semester 3",
    "Semester 4",
    "Semester 5",
    "Semester 6",
    "Semester 7",
    "Semester 8",
  ];

  @override
  void initState() {
    super.initState();
    _selectedSemester = widget.defaultSemester;

    // Jika mode edit (schedule tidak null), inisialisasi form dengan data yang sudah ada
    if (widget.schedule != null) {
      _courseController.text = widget.schedule!.course;
      _roomController.text = widget.schedule!.room;
      _selectedDay = widget.schedule!.day;
      _selectedSemester = widget.schedule!.semester;
      _isMakeup = widget.schedule!.isMakeup;
      _isCancelled = widget.schedule!.isCancelled;

      final startParts = widget.schedule!.startTime.split(":");
      _startTime = TimeOfDay(
        hour: int.parse(startParts[0]),
        minute: int.parse(startParts[1]),
      );

      final endParts = widget.schedule!.endTime.split(":");
      _endTime = TimeOfDay(
        hour: int.parse(endParts[0]),
        minute: int.parse(endParts[1]),
      );
    }
  }

  /// Menampilkan dialog pemilih waktu (Time Picker) untuk jam mulai atau selesai.
  Future<void> _pickTime(bool isStart) async {
    final TimeOfDay? pickedTime = await showTimePicker(
      context: context,
      initialTime: TimeOfDay.now(),
    );
    if (pickedTime != null) {
      setState(() {
        if (isStart) {
          _startTime = pickedTime;
        } else {
          _endTime = pickedTime;
        }
      });
    }
  }

  /// Memformat objek TimeOfDay menjadi string dengan format HH:MM.
  String _formatTimeOfDay(TimeOfDay? time) {
    if (time == null) return "Pilih Jam";
    return "${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}";
  }

  @override
  Widget build(BuildContext context) {
    final isEditing = widget.schedule != null;

    return Scaffold(
      appBar: AppBar(
        title: Text(isEditing ? "Edit Jadwal" : "Tambah Jadwal"),
        actions: [
          // Menampilkan tombol hapus hanya jika dalam mode edit
          if (isEditing)
            IconButton(
              icon: const Icon(Icons.delete, color: Colors.redAccent),
              onPressed: () async {
                await DatabaseHelper.instance.deleteSchedule(
                  widget.schedule!.id!,
                );
                if (context.mounted) Navigator.pop(context);
              },
            ),
        ],
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(20),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            TextField(
              controller: _courseController,
              decoration: const InputDecoration(labelText: "Nama Mata Kuliah"),
            ),
            const SizedBox(height: 15),
            TextField(
              controller: _roomController,
              decoration: const InputDecoration(labelText: "Ruangan"),
            ),
            const SizedBox(height: 20),

            Row(
              children: [
                Expanded(
                  child: DropdownButtonFormField<String>(
                    initialValue: _selectedSemester,
                    decoration: const InputDecoration(labelText: "Semester"),
                    items: _semesters
                        .map(
                          (sem) =>
                              DropdownMenuItem(value: sem, child: Text(sem)),
                        )
                        .toList(),
                    onChanged: (val) =>
                        setState(() => _selectedSemester = val!),
                  ),
                ),
                const SizedBox(width: 15),
                Expanded(
                  child: DropdownButtonFormField<String>(
                    initialValue: _selectedDay,
                    decoration: const InputDecoration(labelText: "Hari"),
                    items: _days
                        .map(
                          (day) =>
                              DropdownMenuItem(value: day, child: Text(day)),
                        )
                        .toList(),
                    onChanged: (val) => setState(() => _selectedDay = val!),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 20),

            Row(
              children: [
                Expanded(
                  child: ListTile(
                    contentPadding: EdgeInsets.zero,
                    title: const Text(
                      "Mulai",
                      style: TextStyle(fontSize: 12, color: Colors.grey),
                    ),
                    subtitle: Text(
                      _formatTimeOfDay(_startTime),
                      style: const TextStyle(fontWeight: FontWeight.bold),
                    ),
                    trailing: const Icon(Icons.access_time),
                    onTap: () => _pickTime(true),
                  ),
                ),
                const SizedBox(width: 10),
                Expanded(
                  child: ListTile(
                    contentPadding: EdgeInsets.zero,
                    title: const Text(
                      "Selesai",
                      style: TextStyle(fontSize: 12, color: Colors.grey),
                    ),
                    subtitle: Text(
                      _formatTimeOfDay(_endTime),
                      style: const TextStyle(fontWeight: FontWeight.bold),
                    ),
                    trailing: const Icon(Icons.access_time),
                    onTap: () => _pickTime(false),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 20),

            SwitchListTile(
              title: const Text("Ini Kelas Pengganti?"),
              value: _isMakeup,
              onChanged: (val) => setState(() => _isMakeup = val),
              contentPadding: EdgeInsets.zero,
              activeThumbColor: Colors.orange,
            ),

            if (isEditing)
              SwitchListTile(
                title: const Text(
                  "Dosen Kosong / Batal?",
                  style: TextStyle(
                    color: Colors.redAccent,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                value: _isCancelled,
                onChanged: (val) => setState(() => _isCancelled = val),
                contentPadding: EdgeInsets.zero,
                activeThumbColor: Colors.redAccent,
              ),

            const SizedBox(height: 40),

            ElevatedButton(
              style: ElevatedButton.styleFrom(
                minimumSize: const Size(double.infinity, 50),
                backgroundColor: const Color(0xFF4A00E0),
                foregroundColor: Colors.white,
              ),
              onPressed: () async {
                // Validasi kelengkapan form sebelum menyimpan
                if (_courseController.text.isEmpty ||
                    _startTime == null ||
                    _endTime == null) {
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(
                      content: Text("Isi formnya yang lengkap bro!"),
                    ),
                  );
                  return;
                }

                // Membangun objek jadwal berdasarkan data yang diinput
                final newSchedule = ClassSchedule(
                  id: isEditing ? widget.schedule!.id : null,
                  course: _courseController.text,
                  room: _roomController.text,
                  day: _selectedDay,
                  semester: _selectedSemester,
                  startTime: _formatTimeOfDay(_startTime),
                  endTime: _formatTimeOfDay(_endTime),
                  isMakeup: _isMakeup,
                  isCancelled: _isCancelled,
                );

                // Menyimpan atau memperbarui data ke dalam database
                if (isEditing) {
                  await DatabaseHelper.instance.updateSchedule(newSchedule);
                } else {
                  await DatabaseHelper.instance.insertSchedule(newSchedule);
                }

                if (context.mounted) Navigator.pop(context);
              },
              child: Text(
                isEditing ? "Simpan Perubahan" : "Simpan ke Database",
              ),
            ),
          ],
        ),
      ),
    );
  }
}

About

Student Hub UGM - Task & Schedule Tracker

FlutterDartSQLiteAIGeminiMobile App

Contributors

2