source-code/
student-hub
Public
codeCodeinfoIssues 0call_splitPull Requestsplay_circleActions
student-hub/lib/screens/view_materials_screen.dart
text175 lines6.3 KB
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart' as fp;
import 'package:path_provider/path_provider.dart';
import '../services/database_helper.dart';
import '../widgets/material_card.dart';
import '../widgets/add_material_dialog.dart';
import 'pdf_viewer_screen.dart';

class ViewMaterialsScreen extends StatefulWidget {
  const ViewMaterialsScreen({super.key});

  @override
  State<ViewMaterialsScreen> createState() => _ViewMaterialsScreenState();
}

class _ViewMaterialsScreenState extends State<ViewMaterialsScreen> {
  late Future<List<Map<String, dynamic>>> _materialsFuture;
  String _selectedCategory = 'Semua';
  final List<String> _categories = ['Semua', 'Slide', 'Catatan', 'Latihan', 'Lainnya'];

  @override
  void initState() {
    super.initState();
    _refreshMaterials();
  }

  void _refreshMaterials() {
    setState(() {
      _materialsFuture = DatabaseHelper.instance.getAllMaterials();
    });
  }

  /// Mengeksekusi modul pengelola file sistem (File Picker) untuk memilih dokumen dari luar lingkup aplikasi.
  Future<void> _addMaterialFromDevice() async {
    // Menggunakan alias (namespace) 'fp.' agar tidak memunculkan konflik kelas dengan elemen antarmuka Flutter
    fp.FilePickerResult? result = await fp.FilePicker.pickFiles(
      type: fp.FileType.custom,
      allowedExtensions: ['pdf'],
    );

    if (result != null && result.files.single.path != null) {
      File originalFile = File(result.files.single.path!);
      String fileName = result.files.single.name;
      
      // Membuka jendela dialog interaktif untuk mendefinisikan label (judul dan matkul) dokumen
      _showMaterialDetailsDialog(originalFile, fileName);
    }
  }

  /// Menampilkan dialog popup formulir kelengkapan keterangan dari dokumen materi yang baru diunggah.
  void _showMaterialDetailsDialog(File originalFile, String fileName) {
    showDialog(
      context: context,
      builder: (context) {
        return AddMaterialDialog(
          fileName: fileName,
          onSave: (title, course, category) async {
            // 1. Menggandakan data file ke dalam penyimpanan terisolasi yang hanya dapat diakses oleh aplikasi
            Directory appDocDir = await getApplicationDocumentsDirectory();
            String newFilePath = '${appDocDir.path}/$fileName';
            await originalFile.copy(newFilePath);

            // 2. Meregistrasikan informasi struktural materi ke dalam database lokal
            await DatabaseHelper.instance.insertMaterial(
              title,
              course,
              category,
              newFilePath,
            );

            _refreshMaterials();
          },
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Materi Kuliah Terunduh"),
        backgroundColor: const Color(0xFF4A00E0),
        foregroundColor: Colors.white,
      ),
      body: Column(
        children: [
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            color: Colors.grey[100],
            child: Row(
              children: [
                const Text("Kategori: ", style: TextStyle(fontWeight: FontWeight.bold)),
                const SizedBox(width: 10),
                Expanded(
                  child: DropdownButton<String>(
                    isExpanded: true,
                    value: _selectedCategory,
                    items: _categories.map((String category) {
                      return DropdownMenuItem<String>(
                        value: category,
                        child: Text(category),
                      );
                    }).toList(),
                    onChanged: (String? newValue) {
                      if (newValue != null) {
                        setState(() {
                          _selectedCategory = newValue;
                        });
                      }
                    },
                  ),
                ),
              ],
            ),
          ),
          Expanded(
            child: FutureBuilder<List<Map<String, dynamic>>>(
              future: _materialsFuture,
              builder: (context, snapshot) {
                if (snapshot.connectionState == ConnectionState.waiting) {
                  return const Center(child: CircularProgressIndicator());
                }
                if (!snapshot.hasData || snapshot.data!.isEmpty) {
                  return const Center(child: Text("Belum ada materi offline yang disimpan."));
                }

                final allMaterials = snapshot.data!;
                final materials = _selectedCategory == 'Semua' 
                    ? allMaterials 
                    : allMaterials.where((m) => m['category'] == _selectedCategory).toList();

                if (materials.isEmpty) {
                  return Center(child: Text("Tidak ada materi untuk kategori $_selectedCategory."));
                }

                return ListView.builder(
                  itemCount: materials.length,
                  itemBuilder: (context, index) {
                    final material = materials[index];
                    return MaterialCard(
                      material: material,
                      onDelete: () async {
                        File(material['filePath']).deleteSync(); 
                        await DatabaseHelper.instance.deleteMaterial(material['id']);
                        _refreshMaterials();
                      },
                      onTap: () {
                        Navigator.push(
                          context,
                          MaterialPageRoute(
                            builder: (context) => PdfViewerScreen(localPath: material['filePath']),
                          ),
                        );
                      },
                    );
                  },
                );
              },
            ),
          ),
        ],
      ),
      // Tombol Tindakan Mengambang (Floating Action Button) untuk memulai rutinitas penambahan file secara manual
      floatingActionButton: FloatingActionButton.extended(
        onPressed: _addMaterialFromDevice,
        icon: const Icon(Icons.add),
        label: const Text("File PDF"),
        backgroundColor: const Color(0xFF4A00E0),
        foregroundColor: Colors.white,
      ),
    );
  }
}

About

Student Hub UGM - Task & Schedule Tracker

FlutterDartSQLiteAIGeminiMobile App

Contributors

2