From 8fc101cc478fe5ec82c546a81d6f9b4eca67f937 Mon Sep 17 00:00:00 2001 From: Anoop Kumar Date: Fri, 19 Apr 2024 17:51:47 +0530 Subject: [PATCH] make announcements , sort announcements , faculty views --- android/app/src/main/AndroidManifest.xml | 1 + db/cse_faculty.csv | 12 - db/ece_faculty.csv | 12 - db/mech_faculty.csv | 12 - db/sm_faculty.csv | 12 - lib/api.dart | 9 +- lib/main.dart | 16 +- .../Alumni_details/alumni_details.dart | 45 +- .../Announcements/browse_announcement.dart | 472 +++++++++++------- .../Announcements/make_announcement.dart | 141 ++++-- .../Faculty_details/faculty_details.dart | 308 ++++++------ .../Student_details/batch_details.dart | 170 ++++--- .../Student_details/student_details.dart | 125 +++-- .../Department/department_homepage.dart | 210 ++++---- lib/services/department_service.dart | 258 +++++++++- pubspec.yaml | 2 +- 16 files changed, 1106 insertions(+), 699 deletions(-) delete mode 100644 db/cse_faculty.csv delete mode 100644 db/ece_faculty.csv delete mode 100644 db/mech_faculty.csv delete mode 100644 db/sm_faculty.csv diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 494a18af..0d6b0c95 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -14,6 +14,7 @@ android:icon="@mipmap/ic_launcher" android:usesCleartextTraffic="true" android:enableOnBackInvokedCallback="true"> + selectedDepartmentData; return MediaQuery( data: windowData, child: MaterialApp( @@ -73,10 +79,10 @@ class MyApp extends StatelessWidget { title: 'Fusion', debugShowCheckedModeBanner: false, theme: ThemeData( - // primarySwatch: Colors.blueGrey, + // primarySwatch: Colors.blueGrey, // colorSchemeSeed: Color(0xFF2085D0), colorSchemeSeed: Color(0xFFF36C35), - fontFamily: 'Nunito', + fontFamily: 'Nunito', useMaterial3: true, ), initialRoute: '/landing', @@ -108,6 +114,10 @@ class MyApp extends StatelessWidget { '/programme_curriculum_home/courses_info': (context) => CoursesInfo(), '/department_home_page': (context) => DepartmentScreen( ModalRoute.of(context)!.settings.arguments.toString()), + '/student_details': (context) => StudentDetails(), + '/alumni_details': (context) => AlumniDetails(), + '/browse_announcement': (context) => BrowseAnnouncement(), + '/make_announcement': (context) => MakeAnnouncement(), '/establishment': (context) => Establishment(), '/gymkhana_homepage': (context) => GymkhanaHomepage(), '/gymkhana_homepage/apply': (context) => Apply(), diff --git a/lib/screens/Department/Alumni_details/alumni_details.dart b/lib/screens/Department/Alumni_details/alumni_details.dart index 95b9e8af..949e2816 100644 --- a/lib/screens/Department/Alumni_details/alumni_details.dart +++ b/lib/screens/Department/Alumni_details/alumni_details.dart @@ -1,13 +1,14 @@ import 'package:flutter/material.dart'; import 'package:fusion/Components/appBar.dart'; import 'package:fusion/Components/side_drawer.dart'; +import 'package:fusion/constants.dart'; -class AlumniDetailsScreen extends StatefulWidget { +class AlumniDetails extends StatefulWidget { @override _AlumniDetailsState createState() => _AlumniDetailsState(); } -class _AlumniDetailsState extends State +class _AlumniDetailsState extends State with SingleTickerProviderStateMixin { late TabController _tabController; List departmentOptions = [ @@ -54,14 +55,12 @@ class _AlumniDetailsState extends State _tabController = TabController(length: departmentOptions.length, vsync: this); _tabController.addListener(_handleTabSelection); - _tabController.index = 0; // Initialize the index - // fetchAlumnniDetails(); + _tabController.index = 0; } void _handleTabSelection() { setState(() { selectedDepartment = departmentOptions[_tabController.index]; - // fetchAlumniDetails(); }); } @@ -81,14 +80,14 @@ class _AlumniDetailsState extends State children: [ // SizedBox(height: 16), Container( - color: Colors.deepOrangeAccent, // Set background color here + color: kPrimaryColor, child: TabBar( controller: _tabController, isScrollable: true, indicatorColor: Colors.black, labelColor: Colors.black, unselectedLabelColor: - Colors.white, // Set unselected font color here + Colors.white, tabs: departmentOptions .map((department) => Tab( text: department, @@ -109,32 +108,48 @@ class _AlumniDetailsState extends State borderRadius: BorderRadius.circular(10.0), ), child: DataTable( - headingRowColor: MaterialStateColor.resolveWith( - (states) => Colors.black), columns: [ DataColumn( label: Text('ID', - style: TextStyle(color: Colors.white)), + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black)), ), DataColumn( label: Text('Alumni Name', - style: TextStyle(color: Colors.white)), + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black)), ), DataColumn( label: Text('Sex', - style: TextStyle(color: Colors.white)), + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black)), ), DataColumn( label: Text('Date of Birth', - style: TextStyle(color: Colors.white)), + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black)), ), DataColumn( label: Text('Address', - style: TextStyle(color: Colors.white)), + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black)), ), DataColumn( label: Text('Phone Number', - style: TextStyle(color: Colors.white)), + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black)), ), ], rows: alumniDetails diff --git a/lib/screens/Department/Announcements/browse_announcement.dart b/lib/screens/Department/Announcements/browse_announcement.dart index 6eab9a49..6c4e15b9 100644 --- a/lib/screens/Department/Announcements/browse_announcement.dart +++ b/lib/screens/Department/Announcements/browse_announcement.dart @@ -1,105 +1,124 @@ import 'dart:async'; -import 'dart:convert'; -import 'package:http/http.dart' as http; +import 'package:fusion/constants.dart'; +import 'package:intl/intl.dart'; import 'package:flutter/material.dart'; import 'package:fusion/Components/appBar.dart'; import 'package:fusion/Components/side_drawer.dart'; import 'package:fusion/models/profile.dart'; import 'package:fusion/services/service_locator.dart'; import 'package:fusion/services/storage_service.dart'; -import 'package:fusion/screens/Department/Announcements/make_announcement.dart'; import 'package:fusion/services/department_service.dart'; +import 'package:fusion/screens/Department/Announcements/make_announcement.dart'; +import 'package:webview_flutter/webview_flutter.dart'; -class BrowseAnnouncementScreen extends StatefulWidget { +class BrowseAnnouncement extends StatefulWidget { @override - _BrowseAnnouncementScreenState createState() => - _BrowseAnnouncementScreenState(); + _BrowseAnnouncementState createState() => _BrowseAnnouncementState(); +} + +enum AnnouncementSortingCriteria { date, announcementBy } + +class WebViewer extends StatefulWidget { + final String url; + const WebViewer({Key? key, required this.url}) : super(key: key); + @override + _WebViewerState createState() => _WebViewerState(); +} + +class _WebViewerState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Web Viewer'), + ), + body: WebView( + initialUrl: widget.url, + javascriptMode: JavascriptMode.unrestricted, + ), + ); + } } +// String _getUsername(String makerId) { +// var profile = data!.profile; +// if (profile != null && profile['id'] == makerId) { +// var user = data!.user; +// if (user != null) { +// return user['username'] ?? ''; +// } +// } +// return ''; +// } -class _BrowseAnnouncementScreenState extends State { +class _BrowseAnnouncementState extends State + with SingleTickerProviderStateMixin { ProfileData? data; - final DepartmentService _departmentService = DepartmentService(); + late TabController _tabController; + List departmentOptions = ['All', 'CSE', 'ECE', 'ME', 'SM']; final StreamController> _announcementsController = StreamController>(); - - Stream> get announcementsStream => - _announcementsController.stream; + AnnouncementSortingCriteria? _sortingCriteria; + bool _isAscending = true; @override void initState() { super.initState(); + _tabController = TabController( + length: departmentOptions.length, + vsync: this, + ); + _tabController.addListener(_handleTabSelection); + _tabController.index = 0; // Initialize the index var service = locator(); data = service.profileData; _loadAnnouncements(); } + void _handleTabSelection() { + setState(() { + _loadAnnouncements(); + }); + } + void _loadAnnouncements() async { - String? userRole = data?.profile?['user_type']; - print(userRole); - try { - if (userRole == 'student') { - try { - http.Response jsonResponse = - await _departmentService.getAnnouncements(); - List jsonData = json.decode(jsonResponse.body); - List announcements = jsonData.map((item) { - return Announcement.fromJson(item); - }).toList(); + int selectedIndex = _tabController.index; + String department = departmentOptions[selectedIndex]; + List announcements = + await DepartmentService().getDepartmentsAnnouncements(department); + _sortAnnouncements(announcements); + } - _announcementsController.add(announcements.toList()); - } catch (error) { - print('Error loading announcements: $error'); - } - } else if (userRole == 'faculty') { - try { - http.Response jsonResponse = - await _departmentService.getFacViewAnnouncements(); - Map jsonData = json.decode(jsonResponse.body); - List announcementsData = jsonData['announcements'] ?? []; - List announcements = []; - for (var list in announcementsData) { - if (list is List) { - for (var item in list) { - if (item is Map) { - announcements.add(Announcement.fromJson(item)); - } - } - } - } - print('Announcements: $announcements'); + void _sortAnnouncements(List announcements) { + if (_sortingCriteria == AnnouncementSortingCriteria.date) { + announcements.sort((a, b) => + DateTime.parse(a.ann_date).compareTo(DateTime.parse(b.ann_date))); + } else if (_sortingCriteria == AnnouncementSortingCriteria.announcementBy) { + announcements.sort((a, b) => a.maker_id.compareTo(b.maker_id)); + } + if (!_isAscending) { + announcements = announcements.reversed.toList(); + } + _announcementsController.add(announcements); + } - _announcementsController.add(announcements.toList()); - } catch (error) { - print('Error loading announcements: $error'); - } - } else if (userRole == 'admin') { - try { - http.Response jsonResponse = - await _departmentService.getAnnouncements(); - print('API Response Status Code: ${jsonResponse.statusCode}'); - print('API Response Body: ${jsonResponse.body}'); - List jsonData = json.decode(jsonResponse.body); - List announcements = jsonData.map((item) { - return Announcement.fromJson(item); - }).toList(); - print('Announcements: $announcements'); + void _toggleSortOrder() { + setState(() { + _isAscending = !_isAscending; + }); + _loadAnnouncements(); + } - _announcementsController.add(announcements.toList()); - } catch (error) { - print('Error loading announcements: $error'); - } - } else { - // Handle other cases or unknown roles - return; - } - } catch (error) { - print('Error loading announcements: $error'); - } + void _setSortingCriteria(AnnouncementSortingCriteria? criteria) { + setState(() { + _sortingCriteria = criteria; + }); + _loadAnnouncements(); } @override void dispose() { _announcementsController.close(); + _tabController.dispose(); super.dispose(); } @@ -112,122 +131,223 @@ class _BrowseAnnouncementScreenState extends State { body: Column( children: [ Container( - margin: EdgeInsets.all(5.0), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(1.0), + color: kPrimaryColor, + child: TabBar( + controller: _tabController, + isScrollable: true, + indicatorColor: Colors.black, + labelColor: Colors.black, + unselectedLabelColor: Colors.white, + tabs: departmentOptions + .map((department) => Tab( + text: department, + )) + .toList(), ), - child: Center( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (userRole == 'faculty' || userRole != 'student') - ElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => MakeAnnouncementScreen(), - ), - ); - }, - child: Icon(Icons.add, size: 20), // Set font size here - ), - SizedBox(width: 8), - ElevatedButton( - onPressed: () { - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => BrowseAnnouncementScreen(), - // ), - // ); - }, - child: Text( - 'Announcements', - style: TextStyle(fontSize: 18), // Set font size here - ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (userRole == 'faculty') + ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => MakeAnnouncement(), + ), + ); + }, + child: Icon(Icons.add, size: 20), + ), + SizedBox(width: 8), + ElevatedButton( + onPressed: () { + _loadAnnouncements(); + }, + child: Text( + 'Announcements', + style: TextStyle(fontSize: 18), // Set font size here + ), + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 30.0), + child: DropdownButton( + hint: Text('Sort by'), + value: _sortingCriteria, + onChanged: _setSortingCriteria, + items: [ + DropdownMenuItem( + child: Text('Sort by Date'), + value: AnnouncementSortingCriteria.date, + ), + DropdownMenuItem( + child: Text('Sort by Announcement By'), + value: AnnouncementSortingCriteria.announcementBy, + ), + ], ), - ], + ), ), - ), + IconButton( + icon: Icon( + _isAscending ? Icons.arrow_upward : Icons.arrow_downward), + onPressed: _toggleSortOrder, + ), + ], ), Expanded( - child: StreamBuilder>( - stream: announcementsStream, - builder: (context, snapshot) { - if (snapshot.hasData) { - return SingleChildScrollView( + child: Container( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(0), + child: SingleChildScrollView( scrollDirection: Axis.horizontal, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10.0), - ), - child: DataTable( - headingRowColor: MaterialStateColor.resolveWith( - (states) => Color.fromARGB(255, 84, 83, 83), - ), // Black background for column names - columns: [ - DataColumn( - label: Text( - 'Announcement Date', - style: TextStyle(color: Colors.white), - ), - ), - DataColumn( - label: Text( - 'Announcement By', - style: TextStyle(color: Colors.white), - ), - ), - DataColumn( - label: Text( - 'Programme', - style: TextStyle(color: Colors.white), - ), - ), - DataColumn( - label: Text( - 'Batch', - style: TextStyle(color: Colors.white), - ), - ), - DataColumn( - label: Text( - 'Message', - style: TextStyle(color: Colors.white), - ), - ), - DataColumn( - label: Text( - 'File', - style: TextStyle(color: Colors.white), - ), - ), - ], - rows: snapshot.data! - .map( - (announcement) => DataRow( - cells: [ - DataCell(Text(announcement.ann_date)), - DataCell(Text(announcement.maker_id)), - DataCell(Text(announcement.programme)), - DataCell(Text(announcement.batch)), - DataCell(Text(announcement.message)), - DataCell(Text( - announcement.upload_announcement ?? '')), + child: StreamBuilder>( + stream: _announcementsController.stream, + builder: (context, snapshot) { + if (snapshot.hasData) { + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10.0), + ), + child: DataTable( + columns: [ + DataColumn( + label: Text( + 'Announcement Date', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black), + ), + ), + DataColumn( + label: Text( + 'Announcement By', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black), + ), + ), + DataColumn( + label: Text( + 'Programme', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black), + ), + ), + DataColumn( + label: Text( + 'Batch', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black), + ), + ), + DataColumn( + label: Text( + 'Message', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black), + ), + ), + DataColumn( + label: Text( + 'File', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black), + ), + ), ], + rows: snapshot.data! + .map( + (announcement) => DataRow( + cells: [ + DataCell(Text( + DateFormat('MMM. dd, yyyy') + .format(DateTime.parse( + announcement.ann_date)))), + DataCell(Text(announcement.maker_id)), + // DataCell(Text(_getUsername(announcement + // .maker_id))), // Updated line + DataCell( + Text(announcement.programme)), + DataCell(Text(announcement.batch)), + DataCell(Container( + width: 250, + child: Text( + announcement.message, + softWrap: true, + ), + )), + DataCell( + announcement.upload_announcement != + null + ? TextButton( + onPressed: () { + String? fileUrl = + announcement + .upload_announcement; + if (fileUrl != null && + fileUrl.isNotEmpty) { + Navigator.push( + context, + MaterialPageRoute( + builder: + (context) => + WebViewer( + url: fileUrl, + ), + ), + ); + } + }, + child: Text( + 'Open File', + style: TextStyle( + color: Colors.blue, + decoration: + TextDecoration + .underline, + ), + ), + ) + : SizedBox(), + ), + ], + ), + ) + .toList(), ), - ) - .toList(), - ), + ), + ); + } else if (snapshot.hasError) { + return Text('Error: ${snapshot.error}'); + } else { + return Center(child: CircularProgressIndicator()); + } + }, ), - ); - } else if (snapshot.hasError) { - return Text('Error: ${snapshot.error}'); - } else { - return Center(child: CircularProgressIndicator()); - } - }, + ), + ), + ), ), ), ], diff --git a/lib/screens/Department/Announcements/make_announcement.dart b/lib/screens/Department/Announcements/make_announcement.dart index 88877e2d..abcd242d 100644 --- a/lib/screens/Department/Announcements/make_announcement.dart +++ b/lib/screens/Department/Announcements/make_announcement.dart @@ -1,40 +1,58 @@ +import 'dart:async'; +import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:fusion/Components/appBar.dart'; import 'package:fusion/Components/side_drawer.dart'; import 'package:file_picker/file_picker.dart'; import 'package:fusion/services/department_service.dart'; +import 'package:fusion/models/profile.dart'; +import 'package:fusion/services/profile_service.dart'; +import 'package:fusion/services/service_locator.dart'; +import 'package:fusion/services/storage_service.dart'; +import 'package:http/http.dart'; -class MakeAnnouncementScreen extends StatefulWidget { +class MakeAnnouncement extends StatefulWidget { @override - _MakeAnnouncementScreenState createState() => _MakeAnnouncementScreenState(); + _MakeAnnouncementState createState() => _MakeAnnouncementState(); } -class _MakeAnnouncementScreenState extends State { +class _MakeAnnouncementState extends State { + late ProfileData? data; + late ProfileService profileService; List> announcements = []; final _formKey = GlobalKey(); - List programmeTypes = [null, 'All', 'B.Tech', 'M.Tech', 'Ph.D']; + List programmeTypes = [null, 'B.Tech', 'M.Tech', 'Ph.D']; List departmentTypes = [null, 'All', 'CSE', 'ECE', 'ME', 'SM']; - List batches = [ - null, - 'All', - 'First Year', - 'Second Year', - 'Third Year', - 'Fourth Year' - ]; + List batches = [null, 'All', 'Year-1', 'Year-2', 'Year-3', 'Year-4']; + late String ann_date; String? selectedProgrammeType; String? selectedBatch; String? selectedDepartmentType; String? programmeWarning; String? departmentWarning; - String selectedFilePath = 'No file chosen'; + String? selectedFilePath = null; TextEditingController announcementDetailsController = TextEditingController(); @override void initState() { super.initState(); + var service = locator(); + profileService = ProfileService(); + data = service.profileData; announcementDetailsController = TextEditingController(); + getData(); + } + + getData() async { + try { + Response response = await profileService.getProfile(); + setState(() { + data = ProfileData.fromJson(jsonDecode(response.body)); + }); + } catch (e) { + print(e); + } } @override @@ -65,7 +83,7 @@ class _MakeAnnouncementScreenState extends State { Navigator.pop( context, MaterialPageRoute( - builder: (context) => MakeAnnouncementScreen(), + builder: (context) => MakeAnnouncement(), ), ); }, @@ -108,7 +126,7 @@ class _MakeAnnouncementScreenState extends State { }), if (programmeWarning != null) Padding( - padding: const EdgeInsets.only(left: 8.0), + padding: const EdgeInsets.only(left: 0.0), child: Text( programmeWarning!, style: TextStyle(color: Colors.red), @@ -135,7 +153,7 @@ class _MakeAnnouncementScreenState extends State { }), if (departmentWarning != null) Padding( - padding: const EdgeInsets.only(left: 8.0), + padding: const EdgeInsets.only(left: 0.0), child: Text( departmentWarning!, style: TextStyle(color: Colors.red), @@ -143,6 +161,7 @@ class _MakeAnnouncementScreenState extends State { ), SizedBox(height: 16), TextFormField( + controller: announcementDetailsController, decoration: InputDecoration( labelText: 'Announcement Details:*', ), @@ -175,7 +194,7 @@ class _MakeAnnouncementScreenState extends State { child: Text('Choose File'), ), SizedBox(width: 8), - Text(selectedFilePath), + Text(selectedFilePath ?? 'No file chosen'), ], ), ), @@ -184,9 +203,7 @@ class _MakeAnnouncementScreenState extends State { SizedBox(height: 16), ElevatedButton( onPressed: () { - if (_formKey.currentState!.validate()) { - submitForm(); - } + submitForm(); }, child: Text('Publish'), ), @@ -203,8 +220,10 @@ class _MakeAnnouncementScreenState extends State { Future _showFilePickerDialog(BuildContext context) async { try { - FilePickerResult? result = - await FilePicker.platform.pickFiles(allowMultiple: false); + FilePickerResult? result = await FilePicker.platform.pickFiles( + type: FileType.custom, + allowedExtensions: ['pdf', 'jpg', 'jpeg', 'png'], + ); if (result != null) { setState(() { @@ -219,30 +238,64 @@ class _MakeAnnouncementScreenState extends State { } Future submitForm() async { - if (selectedProgrammeType == null) { - setState(() { - programmeWarning = 'This field is required'; - }); - return; - } - if (selectedDepartmentType == null) { - setState(() { - departmentWarning = 'This field is required'; - }); - return; + setState(() { + programmeWarning = + selectedProgrammeType == null ? 'Please select programme' : null; + departmentWarning = + selectedDepartmentType == null ? 'Please select department' : null; + }); + if (_formKey.currentState!.validate()) { + Map announcementData = { + 'maker_id': data!.profile!['id'], + 'ann_date': DateTime.now().toIso8601String(), + 'programme': selectedProgrammeType, + 'batch': selectedBatch, + 'department': selectedDepartmentType, + 'message': announcementDetailsController.text, + 'upload_announcement': selectedFilePath, + }; + Future success = + DepartmentService().createAnnouncement(announcementData); + if (await success) { + _showSuccessSnackbar(); + } else { + _showFailureSnackbar(); + } } + } + + void _showSuccessSnackbar() { + setState(() { + _formKey.currentState!.reset(); + selectedBatch = null; + selectedProgrammeType = null; + selectedDepartmentType = null; + selectedFilePath = null; + announcementDetailsController.clear(); + }); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + 'Announcement Created Successfully', + style: TextStyle(color: Colors.white), + ), + duration: Duration(seconds: 5), + backgroundColor: Colors.green, + ), + ); + } - Map announcementData = { - 'maker_id': 'your_maker_id_value_here', - 'programme': selectedProgrammeType!, - 'batch': selectedBatch ?? '', - 'department': selectedDepartmentType!, - 'message': announcementDetailsController.text, - 'upload_announncement': selectedFilePath, - }; - await DepartmentService().createAnnouncement(announcementData).then((_) => - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text("Announcement created successfully !")))); + void _showFailureSnackbar() { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + 'Failed to create announcement. Please try again later.', + style: TextStyle(color: Colors.white), + ), + duration: Duration(seconds: 5), + backgroundColor: Colors.red, + ), + ); } Widget buildDropdown(String label, List items, String? selectedValue, diff --git a/lib/screens/Department/Faculty_details/faculty_details.dart b/lib/screens/Department/Faculty_details/faculty_details.dart index cdf84c0e..ec19c648 100644 --- a/lib/screens/Department/Faculty_details/faculty_details.dart +++ b/lib/screens/Department/Faculty_details/faculty_details.dart @@ -1,19 +1,22 @@ -// import 'dart:convert'; -// import 'package:http/http.dart' as http; -import 'package:csv/csv.dart'; -import 'dart:async' show Future; import 'package:flutter/material.dart'; import 'package:fusion/Components/appBar.dart'; import 'package:fusion/Components/side_drawer.dart'; -import 'package:flutter/services.dart' show rootBundle; +import 'package:fusion/constants.dart'; +import 'package:fusion/models/profile.dart'; +import 'package:fusion/services/department_service.dart'; +import 'package:fusion/services/service_locator.dart'; +import 'package:fusion/services/storage_service.dart'; class FacultyDetailsScreen extends StatefulWidget { + final String selectedDepartment; + FacultyDetailsScreen({required this.selectedDepartment}); @override _FacultyDetailsState createState() => _FacultyDetailsState(); } class _FacultyDetailsState extends State with SingleTickerProviderStateMixin { + ProfileData? data; late TabController _tabController; List departmentOptions = [ 'CSE Department', @@ -21,97 +24,37 @@ class _FacultyDetailsState extends State 'ME Department', 'SM Department' ]; - String selectedDepartment = 'CSE Department'; - Color outlineColor = Colors.grey; - - List> facultyDetails = []; - - //API section - // Future fetchFacultyDetails() async { - // final response = await http.get( - // Uri.parse('https://your-django-api-endpoint/faculty-details'), - // ); - - // if (response.statusCode == 200) { - // final List data = json.decode(response.body); - - // setState(() { - // facultyDetails.clear(); - // for (final Map faculty in data) { - // facultyDetails.add({ - // 'ID': faculty['id'].toString(), - // 'Faculty Name': faculty['name'], - // 'Sex': faculty['sex'], - // 'Date of Birth': faculty['date_of_birth'], - // 'Address': faculty['address'], - // 'Phone Number': faculty['phone_no'], - // }); - // } - // }); - // } else { - // throw Exception('Failed to load faculty details'); - // } - // } - Future fetchFacultyDetails() async { - // Load CSV data from asset file based on selected department - String departmentCSV; - switch (selectedDepartment) { - case 'CSE Department': - departmentCSV = "db/cse_faculty.csv"; - break; - case 'ECE Department': - departmentCSV = "db/ece_faculty.csv"; - break; - case 'ME Department': - departmentCSV = "db/mech_faculty.csv"; - break; - case 'SM Department': - departmentCSV = "db/sm_faculty.csv"; - break; - default: - departmentCSV = "db/cse_faculty.csv"; - } - - String csvData = await rootBundle.loadString(departmentCSV); - - // Parse CSV data - List> csvTable = CsvToListConverter().convert(csvData); - - // Convert CSV table to faculty details list - List> facultyList = []; - for (int i = 1; i < csvTable.length; i++) { - facultyList.add({ - 'ID': csvTable[i][0].toString(), - 'Faculty Name': csvTable[i][1].toString(), - 'Sex': csvTable[i][2].toString(), - 'Date of Birth': csvTable[i][3].toString(), - 'Address': csvTable[i][4].toString(), - 'Phone Number': csvTable[i][5].toString(), - 'Department': csvTable[i][6].toString(), // Add department information - }); - } - - // Set faculty details - setState(() { - facultyDetails = facultyList; - }); - } - + List facultyDetails = []; + late String updatedDepartment; + bool isLoading = false; @override void initState() { super.initState(); _tabController = TabController(length: departmentOptions.length, vsync: this); _tabController.addListener(_handleTabSelection); - _tabController.index = 0; // Initialize the index - fetchFacultyDetails(); + _tabController.index = 0; + var service = locator(); + data = service.profileData; + updatedDepartment = widget.selectedDepartment; + _handleTabSelection(); } void _handleTabSelection() { - setState(() { - selectedDepartment = departmentOptions[_tabController.index]; - fetchFacultyDetails(); - }); + final newDepartment = departmentOptions[_tabController.index].split(' ')[0]; + if (updatedDepartment != newDepartment) { + setState(() { + isLoading = true; + }); + updatedDepartment = newDepartment; + DepartmentService().getFacultyDetails(updatedDepartment).then((data) { + setState(() { + facultyDetails = + data?.map((json) => FacultyDetails.fromJson(json)).toList() ?? []; + isLoading = false; + }); + }); + } } @override @@ -125,89 +68,162 @@ class _FacultyDetailsState extends State return Scaffold( appBar: DefaultAppBar().buildAppBar(), drawer: SideDrawer(), - body: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // SizedBox(height: 16), - Container( - color: Colors.deepOrangeAccent, // Set background color here - child: TabBar( - controller: _tabController, - isScrollable: true, - indicatorColor: Colors.black, - labelColor: Colors.black, - unselectedLabelColor: - Colors.white, // Set unselected font color here - tabs: departmentOptions - .map((department) => Tab( - text: department, - )) - .toList(), + body: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + color: kPrimaryColor, + child: TabBar( + controller: _tabController, + isScrollable: true, + indicatorColor: Colors.black, + labelColor: Colors.black, + unselectedLabelColor: Colors.white, + tabs: departmentOptions + .map((department) => Tab( + text: department, + )) + .toList(), + ), ), - ), - Expanded( - child: Container( - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(0), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(10.0), - ), - child: DataTable( - headingRowColor: MaterialStateColor.resolveWith( - (states) => Colors.black), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: FutureBuilder>>( + future: + DepartmentService().getFacultyDetails(updatedDepartment), + builder: ((context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError) { + return Center(child: Text('Error: ${snapshot.error}')); + } else { + facultyDetails = snapshot.data + ?.map((json) => FacultyDetails.fromJson(json)) + .toList() ?? + []; + if (facultyDetails.isEmpty) { + return Padding( + padding: EdgeInsets.all(20), + child: Text( + 'No data available', + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + ); + } else { + return DataTable( columns: [ DataColumn( - label: Text('ID', - style: TextStyle(color: Colors.white)), + label: Text( + 'ID', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), ), DataColumn( - label: Text('Faculty Name', - style: TextStyle(color: Colors.white)), + label: Text( + 'Title', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), ), DataColumn( - label: Text('Sex', - style: TextStyle(color: Colors.white)), + label: Text( + 'Sex', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), ), DataColumn( - label: Text('Date of Birth', - style: TextStyle(color: Colors.white)), + label: Text( + 'Date of Birth', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), ), DataColumn( - label: Text('Address', - style: TextStyle(color: Colors.white)), + label: Text( + 'Address', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), ), DataColumn( - label: Text('Phone Number', - style: TextStyle(color: Colors.white)), + label: Text( + 'Phone Number', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + ), + DataColumn( + label: Text( + 'User', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + ), + DataColumn( + label: Text( + 'Department', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), ), ], rows: facultyDetails .map( - (batch) => DataRow( + (faculty) => DataRow( cells: [ - DataCell(Text(batch['ID']!)), - DataCell(Text(batch['Faculty Name']!)), - DataCell(Text(batch['Sex']!)), - DataCell(Text(batch['Date of Birth']!)), - DataCell(Text(batch['Address']!)), - DataCell(Text(batch['Phone Number']!)), + DataCell(Text(faculty.id)), + DataCell(Text(faculty.title)), + DataCell(Text(faculty.sex)), + DataCell(Text(faculty.dateOfBirth)), + DataCell(Text(faculty.address)), + DataCell( + Text(faculty.phoneNumber.toString())), + DataCell(Text(faculty.user.toString())), + DataCell(Text(faculty.department.toString())), ], ), ) .toList(), - ), - ), - ), - ), + ); + } + } + }), ), ), - ), - ], + ], + ), ), ); } diff --git a/lib/screens/Department/Student_details/batch_details.dart b/lib/screens/Department/Student_details/batch_details.dart index c7179268..9d16cdbc 100644 --- a/lib/screens/Department/Student_details/batch_details.dart +++ b/lib/screens/Department/Student_details/batch_details.dart @@ -1,42 +1,40 @@ import 'package:flutter/material.dart'; import 'package:fusion/Components/side_drawer.dart'; import 'package:fusion/models/profile.dart'; +import 'package:fusion/services/department_service.dart'; import 'package:fusion/services/service_locator.dart'; import 'package:fusion/services/storage_service.dart'; -class BatchDetailsScreen extends StatefulWidget { - // final Map? jsonResponse; +class BatchDetails extends StatefulWidget { final String selectedProgramme; - BatchDetailsScreen({required this.selectedProgramme}); + final Map selectedDepartmentData; + BatchDetails( + {required this.selectedProgramme, required this.selectedDepartmentData}); @override - _BatchDetailsScreenState createState() => _BatchDetailsScreenState(); + _BatchDetailsState createState() => _BatchDetailsState(); } -class _BatchDetailsScreenState extends State +class _BatchDetailsState extends State with SingleTickerProviderStateMixin { + late int bid; ProfileData? data; late TabController _tabController; - - List> batchDetails = []; - - // Future fetchBatchDetails() async { - // // Your existing fetchBatchDetails logic - // } + List> batchDetails = []; @override void initState() { super.initState(); var service = locator(); data = service.profileData; - + bid = + generateBid(widget.selectedProgramme, widget.selectedDepartmentData, 1); _tabController = TabController( length: _calculateTabCount(), vsync: this, ); _tabController.addListener(_handleTabSelection); - _tabController.index = 0; // Initialize the index - // fetchBatchDetails(); + _tabController.index = 0; } int _calculateTabCount() { @@ -53,7 +51,17 @@ class _BatchDetailsScreenState extends State } void _handleTabSelection() { - // You can perform actions when a tab is selected if needed + int year = _tabController.index + 1; + int newBid = generateBid( + widget.selectedProgramme, widget.selectedDepartmentData, year); + if (bid != newBid) { + bid = newBid; + DepartmentService().getStudents(bid).then((data) { + setState(() { + batchDetails = data ?? []; + }); + }); + } } @override @@ -104,60 +112,68 @@ class _BatchDetailsScreenState extends State padding: const EdgeInsets.all(0), child: SingleChildScrollView( scrollDirection: Axis.horizontal, - child: Container( - child: DataTable( - columns: [ - DataColumn( - label: Text('ID', - style: TextStyle( - fontWeight: FontWeight.w600, - color: Colors.black)), - ), - DataColumn( - label: Text('BATCH', - style: TextStyle( - fontWeight: FontWeight.w600, - color: Colors.black)), - ), - DataColumn( - label: Text('START DATE', - style: TextStyle( - fontWeight: FontWeight.w600, - color: Colors.black)), - ), - DataColumn( - label: Text('END DATE', - style: TextStyle( - fontWeight: FontWeight.w600, - color: Colors.black)), - ), - DataColumn( - label: Text('PROGRAMME', - style: TextStyle( - fontWeight: FontWeight.w600, - color: Colors.black)), - ), - ], - rows: batchDetails - .map( - (batch) => DataRow( - cells: [ - DataCell(Text(batch['ID'] ?? '')), - DataCell(Text(batch['Batch Name'] ?? '')), - DataCell(Text(batch['Start Date'] ?? '')), - DataCell(Text(batch['End Date'] ?? '')), - DataCell(Text(batch['Programme'] ?? '')), - ], - ), - ) - .toList(), - ), + child: FutureBuilder>>( + future: DepartmentService().getStudents(bid), + builder: ((context, snapshot) { + if (snapshot.connectionState == + ConnectionState.waiting) { + return Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError) { + return Center( + child: Text('Error: ${snapshot.error}')); + } else { + batchDetails = snapshot.data ?? []; + return batchDetails.isNotEmpty + ? DataTable( + columns: batchDetails.first.entries + .map( + (entry) => DataColumn( + label: Text( + entry.key.toUpperCase(), + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + ), + ) + .toList(), + rows: batchDetails + .map( + (batch) => DataRow( + cells: batch.entries + .map( + (entry) => DataCell( + Text( + entry.value?.toString() ?? + ''), + ), + ) + .toList(), + ), + ) + .toList(), + ) + : Padding( + padding: EdgeInsets.all(20), + child: Text( + 'No data available', + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + ); + } + }), ), ), ), ), ), - ), + ) ], ), ); @@ -165,10 +181,7 @@ class _BatchDetailsScreenState extends State List _buildTabs() { List tabs = []; - // String programme = widget.jsonResponse!['programme']; - // String department = widget.jsonResponse!['department']; String programme = widget.selectedProgramme; - if (programme == 'PhD') { tabs.add(Tab( child: Text( @@ -210,4 +223,27 @@ class _BatchDetailsScreenState extends State } return tabs; } + + int generateBid( + String programme, Map departmentData, int year) { + String departmentCode = + widget.selectedDepartmentData['departmentCode'] ?? ''; + String bid = departmentCode; + Map batchLengths = { + 'PhD': 6, + 'M.Tech': 4, + 'B.Tech': 1, + }; + if (programme == 'PhD') { + bid += '1'.padRight(batchLengths[programme]!, '1'); + } else if (programme == 'M.Tech') { + bid += '1'.padRight(batchLengths[programme]! + (year == 2 ? 1 : 0), '1'); + } else if (programme == 'B.Tech') { + if (year == 1) bid = bid; + if (year == 2) bid += '1'.padRight(batchLengths[programme]!, '1'); + if (year == 3) bid += '1'.padRight(batchLengths[programme]! + 1, '1'); + if (year == 4) bid += '1'.padRight(batchLengths[programme]! + 2, '1'); + } + return int.parse(bid); + } } diff --git a/lib/screens/Department/Student_details/student_details.dart b/lib/screens/Department/Student_details/student_details.dart index 44a3dfe3..5ef023df 100644 --- a/lib/screens/Department/Student_details/student_details.dart +++ b/lib/screens/Department/Student_details/student_details.dart @@ -1,20 +1,20 @@ import 'package:flutter/material.dart'; import 'package:fusion/Components/appBar.dart'; import 'package:fusion/Components/side_drawer.dart'; +import 'package:fusion/constants.dart'; import 'package:fusion/models/profile.dart'; import 'package:fusion/services/service_locator.dart'; import 'package:fusion/services/storage_service.dart'; import 'package:fusion/screens/Department/Student_details/batch_details.dart'; -class StudentDetailsScreen extends StatefulWidget { +class StudentDetails extends StatefulWidget { @override _StudentDetailsState createState() => _StudentDetailsState(); } -class _StudentDetailsState extends State { +class _StudentDetailsState extends State { ProfileData? data; late String programme; - late var fetchedDepartment; late String selectedDepartment; @override void initState() { @@ -31,29 +31,18 @@ class _StudentDetailsState extends State { } } - // Future?> fetchData(String programme) async { - // try { - // final response = await http.get( - // Uri.parse('https://your-api-endpoint/$programme/$selectedDepartment'), - // ); - - // if (response.statusCode == 200) { - // return json.decode(response.body); - // } else { - // throw Exception('Failed to load data'); - // } - // } catch (error) { - // print('Error fetching data: $error'); - // return null; - // } - // } - List departmentOptions = [ 'CSE Department', 'ECE Department', 'ME Department', 'SM Department' ]; + Map departmentCodes = { + 'CSE Department': '1', + 'ECE Department': '2', + 'ME Department': '3', + 'SM Department': '4', + }; @override Widget build(BuildContext context) { @@ -71,10 +60,7 @@ class _StudentDetailsState extends State { color: Color.fromARGB(255, 255, 237, 232), child: Padding( padding: EdgeInsets.only( - top: 10.0, - bottom: 12.0, - left: 24, - right: 24), // Add your desired padding value + top: 10.0, bottom: 12.0, left: 24, right: 24), child: Column( children: [ Container( @@ -105,7 +91,7 @@ class _StudentDetailsState extends State { text: data!.profile!['department']!['name'], style: TextStyle(fontSize: 15.0, color: Colors.black), children: [ - TextSpan(text: ' '), // Add space between the texts + TextSpan(text: ' '), TextSpan( text: data!.profile!['user_type'], style: @@ -125,13 +111,13 @@ class _StudentDetailsState extends State { margin: EdgeInsets.only(top: 15.0), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10.0), - color: Colors.deepOrangeAccent, + color: kPrimaryColor, boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 5, - offset: Offset(0, 2), // changes position of shadow + offset: Offset(0, 2), ), ], ), @@ -146,7 +132,7 @@ class _StudentDetailsState extends State { child: Text( 'Students', style: TextStyle( - fontSize: 24, // Increased font size + fontSize: 24, color: Colors.white, ), ), @@ -155,94 +141,99 @@ class _StudentDetailsState extends State { ), ), SizedBox(height: 32), - // Navigation buttons with decreased border radius, added space, and deepOrangeAccent outline ElevatedButton( style: ElevatedButton.styleFrom( shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(5.0), // Decreased border radius + borderRadius: BorderRadius.circular(5.0), ), - side: BorderSide( - color: Colors.deepOrangeAccent), // DeepOrangeAccent outline - foregroundColor: Colors.deepOrangeAccent, - backgroundColor: Colors.white, // Text color - minimumSize: Size(550, 50), // Increased button width + side: BorderSide(color: kPrimaryColor), + foregroundColor: kPrimaryColor, + backgroundColor: Colors.white, + minimumSize: Size(550, 50), ), onPressed: () async { - // Map? jsonResponse = await fetchData('PhD'); Navigator.push( context, MaterialPageRoute( - builder: (context) => - BatchDetailsScreen(selectedProgramme: 'PhD'), + builder: (context) => BatchDetails( + selectedProgramme: 'PhD', + selectedDepartmentData: { + 'department': selectedDepartment, + 'departmentCode': + departmentCodes[selectedDepartment] ?? '', + }, + ), ), ); }, child: Text( 'PhD Students', - style: TextStyle(fontSize: 18), // Increased font size + style: TextStyle(fontSize: 18), ), ), - SizedBox(height: 10), // Added space + SizedBox(height: 10), ElevatedButton( style: ElevatedButton.styleFrom( shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(5.0), // Decreased border radius + borderRadius: BorderRadius.circular(5.0), ), - side: BorderSide( - color: Colors.deepOrangeAccent), // DeepOrangeAccent outline - foregroundColor: Colors.deepOrangeAccent, - backgroundColor: Colors.white, // Text color - minimumSize: Size(550, 50), // Increased button width + side: BorderSide(color: kPrimaryColor), + foregroundColor: kPrimaryColor, + backgroundColor: Colors.white, + minimumSize: Size(550, 50), ), onPressed: () async { - // Map? jsonResponse = - // await fetchData('M.Tech'); Navigator.push( context, MaterialPageRoute( - builder: (context) => - BatchDetailsScreen(selectedProgramme: 'M.Tech'), + builder: (context) => BatchDetails( + selectedProgramme: 'M.Tech', + selectedDepartmentData: { + 'department': selectedDepartment, + 'departmentCode': + departmentCodes[selectedDepartment] ?? '', + }, + ), ), ); }, child: Text( 'M.Tech Students', - style: TextStyle(fontSize: 18), // Increased font size + style: TextStyle(fontSize: 18), ), ), - SizedBox(height: 10), // Added space + SizedBox(height: 10), ElevatedButton( style: ElevatedButton.styleFrom( shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(5.0), // Decreased border radius + borderRadius: BorderRadius.circular(5.0), ), - side: BorderSide( - color: Colors.deepOrangeAccent), // DeepOrangeAccent outline - foregroundColor: Colors.deepOrangeAccent, - backgroundColor: Colors.white, // Text color - minimumSize: Size(550, 50), // Increased button width + side: BorderSide(color: kPrimaryColor), + foregroundColor: kPrimaryColor, + backgroundColor: Colors.white, + minimumSize: Size(550, 50), ), onPressed: () async { - // Map? jsonResponse = - // await fetchData('B.Tech'); Navigator.push( context, MaterialPageRoute( - builder: (context) => - BatchDetailsScreen(selectedProgramme: 'B.Tech'), + builder: (context) => BatchDetails( + selectedProgramme: 'B.Tech', + selectedDepartmentData: { + 'department': selectedDepartment, + 'departmentCode': + departmentCodes[selectedDepartment] ?? '', + }, + ), ), ); }, child: Text( 'B.Tech Students', - style: TextStyle(fontSize: 18), // Increased font size + style: TextStyle(fontSize: 18), ), ), SizedBox(height: 32), - // Dropdown for department Row( mainAxisAlignment: MainAxisAlignment.start, children: [ diff --git a/lib/screens/Department/department_homepage.dart b/lib/screens/Department/department_homepage.dart index 4d95698d..2d7b9bf2 100644 --- a/lib/screens/Department/department_homepage.dart +++ b/lib/screens/Department/department_homepage.dart @@ -1,20 +1,20 @@ // ignore_for_file: must_be_immutable - import 'dart:async'; import 'dart:convert'; -import 'package:fusion/screens/Department/facilities.dart'; -import 'package:http/http.dart'; import 'package:flutter/material.dart'; +import 'package:fusion/constants.dart'; +import 'package:http/http.dart'; import 'package:fusion/Components/appBar.dart'; import 'package:fusion/Components/side_drawer.dart'; import 'package:fusion/models/profile.dart'; -import 'package:fusion/services/profile_service.dart'; -import 'package:fusion/services/service_locator.dart'; -import 'package:fusion/services/storage_service.dart'; import 'package:fusion/screens/Department/Alumni_details/alumni_details.dart'; -import 'package:fusion/screens/Department/Student_details/student_details.dart'; import 'package:fusion/screens/Department/Faculty_details/faculty_details.dart'; import 'package:fusion/screens/Department/Announcements/browse_announcement.dart'; +import 'package:fusion/screens/Department/Student_details/student_details.dart'; +import 'package:fusion/screens/Department/facilities.dart'; +import 'package:fusion/services/profile_service.dart'; +import 'package:fusion/services/service_locator.dart'; +import 'package:fusion/services/storage_service.dart'; class DepartmentScreen extends StatefulWidget { String? token; @@ -51,12 +51,12 @@ class _DepartmentScreenState extends State { } getData() async { - //print('token-'+widget.token!); try { Response response = await profileService.getProfile(); setState(() { data = ProfileData.fromJson(jsonDecode(response.body)); - print(data!.user!['username']); + // print(data!.user!); + // print(data!.profile!); _loading = false; }); } catch (e) { @@ -79,8 +79,7 @@ class _DepartmentScreenState extends State { @override Widget build(BuildContext context) { - // Define the RGBA color - Color customColor = Colors.deepOrangeAccent; + Color customColor = kPrimaryColor; Color outlineColor = Colors.grey; return Scaffold( @@ -164,125 +163,128 @@ class _DepartmentScreenState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - ElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => FacilitiesPage(), - ), - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 16, horizontal: 20), + SizedBox( + width: 250, + height: 60, + child: ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + FacilitiesPage(), + ), + ); + }, child: Text('Facilities', style: TextStyle(fontSize: 20)), - ), - style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, - backgroundColor: customColor, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(22), + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: customColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(22), + ), ), ), ), SizedBox(height: 14), - ElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - StudentDetailsScreen(), - ), - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 16, horizontal: 20), + SizedBox( + width: 250, + height: 60, + child: ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + StudentDetails(), + ), + ); + }, child: Text('Student details', style: TextStyle(fontSize: 20)), - ), - style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, - backgroundColor: customColor, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(22), + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: customColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(22), + ), ), ), ), SizedBox(height: 14), - ElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - FacultyDetailsScreen(), - ), - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 16, horizontal: 20), + SizedBox( + width: 250, + height: 60, + child: ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + FacultyDetailsScreen( + selectedDepartment: data! + .profile![ + 'department']!['name']), + ), + ); + }, child: Text('Faculty details', style: TextStyle(fontSize: 20)), - ), - style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, - backgroundColor: customColor, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(22), + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: customColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(22), + ), ), ), ), SizedBox(height: 14), - ElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - AlumniDetailsScreen(), - ), - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 16, horizontal: 20), + SizedBox( + width: 250, + height: 60, + child: ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => AlumniDetails(), + ), + ); + }, child: Text('Alumni details', style: TextStyle(fontSize: 20)), - ), - style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, - backgroundColor: customColor, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(22), + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: customColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(22), + ), ), ), ), SizedBox(height: 14), - ElevatedButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - BrowseAnnouncementScreen()), - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 16, horizontal: 20), + SizedBox( + width: 250, + height: 60, + child: ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + BrowseAnnouncement()), + ); + }, child: Text('Announcements', style: TextStyle(fontSize: 20)), - ), - style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, - backgroundColor: customColor, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(22), + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: customColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(22), + ), ), ), ), diff --git a/lib/services/department_service.dart b/lib/services/department_service.dart index 98331e0d..18bd7225 100644 --- a/lib/services/department_service.dart +++ b/lib/services/department_service.dart @@ -1,12 +1,110 @@ -// import 'dart:convert'; import 'dart:convert'; - import 'package:fusion/api.dart'; import 'package:fusion/constants.dart'; import 'package:http/http.dart' as http; +import 'package:http_parser/http_parser.dart'; import 'package:fusion/services/service_locator.dart'; import 'package:fusion/services/storage_service.dart'; +class Student { + final String id; + final String programme; + final int batch; + final double cpi; + final String category; + final String fatherName; + final String motherName; + final int hallNo; + final int? roomNo; + final String specialization; + final int currSemesterNo; + final int batchId; + + Student({ + required this.id, + required this.programme, + required this.batch, + required this.cpi, + required this.category, + required this.fatherName, + required this.motherName, + required this.hallNo, + required this.roomNo, + required this.specialization, + required this.currSemesterNo, + required this.batchId, + }); + + factory Student.fromJson(Map json) { + return Student( + id: json['id'] ?? '', + programme: json['programme'] ?? '', + batch: json['batch'] ?? 0, + cpi: json['cpi'] != null ? json['cpi'].toDouble() : 0.0, + category: json['category'] ?? '', + fatherName: json['father_name'] ?? '', + motherName: json['mother_name'] ?? '', + hallNo: json['hall_no'] ?? 0, + roomNo: json['room_no'], + specialization: json['specialization'] ?? '', + currSemesterNo: json['curr_semester_no'] ?? 0, + batchId: json['batch_id'] ?? 0, + ); + } +} + +class FacultyDetails { + final String id; + final String title; + final String sex; + final String dateOfBirth; + final String userStatus; + final String address; + final String userType; + final String profilePicture; + final String aboutMe; + final String dateModified; + final int phoneNumber; + final int user; + final int department; + + FacultyDetails({ + required this.id, + required this.title, + required this.sex, + required this.dateOfBirth, + required this.userStatus, + required this.address, + required this.phoneNumber, + required this.userType, + required this.profilePicture, + required this.aboutMe, + required this.dateModified, + required this.user, + required this.department, + }); + + factory FacultyDetails.fromJson(Map json) { + return FacultyDetails( + id: json['id'] ?? '', + title: json['title'] ?? '', + sex: json['sex'] ?? '', + dateOfBirth: json['date_of_birth'] ?? '', + userStatus: json['user_status'] ?? '', + address: json['address'] ?? '', + phoneNumber: json['phone_no'] ?? '', + userType: json['user_type'] ?? '', + profilePicture: json['profile_picture'] ?? '', + aboutMe: json['about_me'] ?? '', + dateModified: json['date_modified'] ?? '', + user: json['user'] ?? 0, + department: json['department'] ?? 0, + ); + } + + get entries => null; +} + class Announcement { final String ann_date; final String maker_id; @@ -40,7 +138,34 @@ class Announcement { } class DepartmentService { - Future getAnnouncements() async { + // Future> fetchDepartmentInfo(String departmentId) async { + // try { + // var storage_service = locator(); + // if (storage_service.userInDB?.token == null) + // throw Exception('Token Error'); + + // Map headers = { + // 'Authorization': 'Token ' + (storage_service.userInDB?.token ?? "") + // }; + + // http.Response response = await http.get( + // Uri.http(getLink(), kDepartmentInfo), + // headers: headers, + // ); + // if (response.statusCode == 200) { + // Map departmentInfo = jsonDecode(response.body); + // return departmentInfo; + // } else { + // throw Exception('Failed to fetch department information.'); + // } + // } catch (e) { + // print('Error in fetchDepartmentInfo: $e'); + // rethrow; + // } + // } + + Future>> getFacultyDetails( + String department) async { try { var storage_service = locator(); if (storage_service.userInDB?.token == null) @@ -49,24 +174,31 @@ class DepartmentService { Map headers = { 'Authorization': 'Token ' + (storage_service.userInDB?.token ?? "") }; - print(headers); + http.Response response = await http.get( - Uri.http(getLink(), kDepartmentAnnouncements), + Uri.http(getLink(), kDepMain), headers: headers, ); - if (response.statusCode == 200) { - return response; + Map jsonData = json.decode(response.body); + List> facultyList = []; + List>? departmentFacultyList = jsonData['fac_list'] + ?[department.toLowerCase() + '_f'] + ?.cast>(); + facultyList.addAll(departmentFacultyList ?? []); + // print(facultyList); + return facultyList; } else { - throw Exception('Failed to load announcements'); + throw Exception('Failed to load faculty details for $department'); } } catch (e) { - print('Error in getAnnouncements: $e'); + print('Error in getFacultyDetails: $e'); rethrow; } } - Future getFacViewAnnouncements() async { + Future> getDepartmentsAnnouncements( + String department) async { try { var storage_service = locator(); if (storage_service.userInDB?.token == null) @@ -77,14 +209,30 @@ class DepartmentService { }; http.Response response = await http.get( - Uri.http(getLink(), kFacView), + Uri.http(getLink(), kDepMain), headers: headers, ); if (response.statusCode == 200) { - return response; + Map jsonData = json.decode(response.body); + List departmentAnnouncements = []; + if (department.toLowerCase() == 'all') { + departmentAnnouncements.addAll(jsonData['announcements']['all']); + departmentAnnouncements.addAll(jsonData['announcements']['cse']); + departmentAnnouncements.addAll(jsonData['announcements']['ece']); + departmentAnnouncements.addAll(jsonData['announcements']['me']); + departmentAnnouncements.addAll(jsonData['announcements']['sm']); + } else { + departmentAnnouncements = + jsonData['announcements'][department.toLowerCase()]; + } + // print(departmentAnnouncements); + List announcements = departmentAnnouncements.map((item) { + return Announcement.fromJson(item); + }).toList(); + return announcements; } else { - throw Exception('Failed to load announcements'); + throw Exception('Failed to load announcements for $department'); } } catch (e) { print('Error in getAnnouncements: $e'); @@ -92,29 +240,93 @@ class DepartmentService { } } - Future createAnnouncement(Map announcementData) async { + + Future createAnnouncement(Map announcementData) async { try { - var storageService = locator(); - if (storageService.userInDB?.token == null) + var storage_service = locator(); + if (storage_service.userInDB?.token == null) { throw Exception('Token Error'); + } Map headers = { - 'Authorization': 'Token ' + (storageService.userInDB?.token ?? ""), - 'Content-Type': 'application/json', + 'Authorization': 'Token ' + (storage_service.userInDB?.token ?? ""), }; - http.Response response = await http.post( + if (announcementData['upload_announcement'] != null) { + var request = http.MultipartRequest( + 'POST', + Uri.http(getLink(), kDepartmentAnnouncements), + ); + + request.headers.addAll(headers); + announcementData.forEach((key, value) { + if (key != 'upload_announcement') { + request.fields[key] = value.toString(); + } + }); + var multipartFile = await http.MultipartFile.fromPath( + 'upload_announcement', + announcementData['upload_announcement'], + contentType: MediaType('file', 'pdf,jpeg,png,jpg'), + ); + + request.files.add(multipartFile); + print(request); + var response = await http.Response.fromStream(await request.send()); + if (response.statusCode == 201) { + return true; + } else { + return false; + } + } else { + headers['Content-Type'] = 'application/json'; + http.Response response = await http.post( Uri.http(getLink(), kDepartmentAnnouncements), headers: headers, - body: jsonEncode(announcementData)); + body: jsonEncode(announcementData), + ); + + if (response.statusCode == 201) { + return true; + } else { + return false; + } + } + } catch (e) { + print('Exception occurred while creating announcement: $e'); + return false; + } + } + Future>> getStudents(int bid) async { + try { + var storage_service = locator(); + if (storage_service.userInDB?.token == null) { + throw Exception('Token Error'); + } + + Map headers = { + 'Authorization': 'Token ' + (storage_service.userInDB?.token ?? "") + }; + + http.Response response = await http.get( + Uri.http(getLink(), '$kAllStudents$bid'), + headers: headers, + ); + print('$kAllStudents$bid'); if (response.statusCode == 200) { - print('Announcement created successfully'); + Map jsonResponse = json.decode(response.body); + List> studentList = + jsonResponse['student_list'].cast>(); + print(studentList); + return studentList; } else { - print('Failed to create announcement. Error: ${response.statusCode}'); + print('Failed to get students. Error: ${response.statusCode}'); + return []; } } catch (e) { - print('Exception occurred while creating announcement: $e'); + print('Exception occurred while getting students: $e'); + return []; } } } diff --git a/pubspec.yaml b/pubspec.yaml index 59c8dae7..f9d06ea4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -41,7 +41,7 @@ dependencies: flutter_html: ^2.2.1 file_selector: ^1.0.3 file_picker: ^3.0.4 - + webview_flutter: ^2.8.0 dev_dependencies: flutter_test: