From 069e2b058f9cdda0f7464d44625777fb8dea2ab1 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Wed, 14 Feb 2024 09:39:15 +0530 Subject: [PATCH 01/30] initial commit --- frontend/lib/generated/assets.dart | 6 +- frontend/lib/main.dart | 4 + frontend/lib/models/timtable.dart | 35 +++++++ frontend/lib/provider/home_provider.dart | 7 ++ frontend/lib/provider/timetable_provider.dart | 92 +++++++++++++++++++ .../repositories/timetable_repository.dart | 42 +++++++++ frontend/lib/routes/routes.dart | 24 +++-- frontend/lib/screens/loading_page.dart | 1 + .../lib/screens/user/timetable_editor.dart | 70 ++++++++++++++ frontend/lib/screens/user/timetables.dart | 84 +++++++++++++++++ frontend/pubspec.lock | 8 ++ frontend/pubspec.yaml | 1 + 12 files changed, 365 insertions(+), 9 deletions(-) create mode 100644 frontend/lib/models/timtable.dart create mode 100644 frontend/lib/provider/timetable_provider.dart create mode 100644 frontend/lib/repositories/timetable_repository.dart create mode 100644 frontend/lib/screens/user/timetable_editor.dart create mode 100644 frontend/lib/screens/user/timetables.dart diff --git a/frontend/lib/generated/assets.dart b/frontend/lib/generated/assets.dart index 9fc10b4..7a8752c 100644 --- a/frontend/lib/generated/assets.dart +++ b/frontend/lib/generated/assets.dart @@ -59,6 +59,7 @@ class Assets { static const String modelsRoom = 'lib/models/room.dart'; static const String modelsSkills = 'lib/models/skills.dart'; static const String modelsStudent = 'lib/models/student.dart'; + static const String modelsTimtable = 'lib/models/timtable.dart'; static const String modelsUser = 'lib/models/user.dart'; static const String providerAdminProvider = 'lib/provider/admin_provider.dart'; static const String providerAuthProvider = 'lib/provider/auth_provider.dart'; @@ -70,6 +71,7 @@ class Assets { static const String providerOtpProvider = 'lib/provider/otp_provider.dart'; static const String providerRoomProvider = 'lib/provider/room_provider.dart'; static const String providerStudentProvider = 'lib/provider/student_provider.dart'; + static const String providerTimetableProvider = 'lib/provider/timetable_provider.dart'; static const String repositoriesAchievementRepository = 'lib/repositories/achievement_repository.dart'; static const String repositoriesAdminRepository = 'lib/repositories/admin_repository.dart'; static const String repositoriesCourseRepository = 'lib/repositories/course_repository.dart'; @@ -78,12 +80,14 @@ class Assets { static const String repositoriesRoomRepository = 'lib/repositories/room_repository.dart'; static const String repositoriesSkillRepository = 'lib/repositories/skill_repository.dart'; static const String repositoriesStudentRepository = 'lib/repositories/student_repository.dart'; + static const String repositoriesTimetableRepository = 'lib/repositories/timetable_repository.dart'; static const String routesRoutes = 'lib/routes/routes.dart'; static const String screensLoadingPage = 'lib/screens/loading_page.dart'; static const String userFacultyProfile = 'lib/screens/user/faculty_profile.dart'; static const String userLostAndFound = 'lib/screens/user/lost_and_found.dart'; static const String userRoomVacancy = 'lib/screens/user/room_vacancy.dart'; static const String userStudentProfile = 'lib/screens/user/student_profile.dart'; + static const String userTimetableEditor = 'lib/screens/user/timetable_editor.dart'; + static const String userTimetables = 'lib/screens/user/timetables.dart'; static const String userUserHome = 'lib/screens/user/user_home.dart'; - } diff --git a/frontend/lib/main.dart b/frontend/lib/main.dart index 77efd40..dc04b62 100644 --- a/frontend/lib/main.dart +++ b/frontend/lib/main.dart @@ -1,11 +1,15 @@ +import 'package:auto_orientation/auto_orientation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:smart_insti_app/constants/constants.dart'; import 'package:smart_insti_app/routes/routes.dart'; +import 'package:smart_insti_app/screens/user/timetable_editor.dart'; Future main() async { + WidgetsFlutterBinding.ensureInitialized(); await dotenv.load(fileName: ".env"); + AutoOrientation.portraitUpMode(); runApp(const ProviderScope(child: SmartInstiApp())); } diff --git a/frontend/lib/models/timtable.dart b/frontend/lib/models/timtable.dart new file mode 100644 index 0000000..4079dd0 --- /dev/null +++ b/frontend/lib/models/timtable.dart @@ -0,0 +1,35 @@ +class Timetable { + final String id; + final String name; + final int rows; + final int columns; + final List> timetable; + + Timetable({ + required this.id, + required this.name, + required this.rows, + required this.columns, + required this.timetable, + }); + + factory Timetable.fromJson(Map json) { + return Timetable( + id: json['_id'], + name: json['name'], + rows: json['rows'], + columns: json['columns'], + timetable: List>.from(json['timetable'].map((x) => List.from(x.map((x) => x)))), + ); + } + + Map toJson() { + return { + 'id': id, + 'name': name, + 'rows': rows, + 'columns': columns, + 'timetable': List.from(timetable.map((x) => List.from(x.map((x) => x)))), + }; + } +} diff --git a/frontend/lib/provider/home_provider.dart b/frontend/lib/provider/home_provider.dart index 39b57b1..6c73c4b 100644 --- a/frontend/lib/provider/home_provider.dart +++ b/frontend/lib/provider/home_provider.dart @@ -78,6 +78,13 @@ class UserProvider extends StateNotifier { secondaryColor: Colors.orangeAccent.shade200, icon: Icons.search, ), + MenuTile( + title: "Timetables", + onTap: () => context.push('/user_home/timetables'), + primaryColor: Colors.blueAccent.shade100, + secondaryColor: Colors.blueAccent.shade200, + icon: Icons.edit, + ), ]; String query = state.searchController.text; state = state.copyWith( diff --git a/frontend/lib/provider/timetable_provider.dart b/frontend/lib/provider/timetable_provider.dart new file mode 100644 index 0000000..fad3a29 --- /dev/null +++ b/frontend/lib/provider/timetable_provider.dart @@ -0,0 +1,92 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:logger/logger.dart'; +import '../components/menu_tile.dart'; +import '../constants/constants.dart'; +import '../models/timtable.dart'; +import '../repositories/timetable_repository.dart'; + +final timetableProvider = StateNotifierProvider((ref) => TimetableProvider(ref)); + +class TimetableState { + final List timetableList; + final List timetableTiles; + final TextEditingController searchTimetableController; + final TextEditingController timetableNameController; + final TextEditingController columnsController; + final LoadingState loadingState; + + TimetableState( + {required this.timetableList, + required this.timetableTiles, + required this.searchTimetableController, + required this.timetableNameController, + required this.columnsController, + required this.loadingState}); + + TimetableState copyWith({ + List? timetableList, + List? timetableTiles, + TextEditingController? searchTimetableController, + TextEditingController? timetableNameController, + TextEditingController? columnsController, + LoadingState? loadingState, + }) { + return TimetableState( + timetableList: timetableList ?? this.timetableList, + timetableTiles: timetableTiles ?? this.timetableTiles, + searchTimetableController: searchTimetableController ?? this.searchTimetableController, + timetableNameController: timetableNameController ?? this.timetableNameController, + columnsController: columnsController ?? this.columnsController, + loadingState: loadingState ?? this.loadingState, + ); + } +} + +class TimetableProvider extends StateNotifier { + TimetableProvider(Ref ref) + : _api = ref.read(timetableRepositoryProvider), + super( + TimetableState( + timetableList: [], + timetableTiles: [], + searchTimetableController: TextEditingController(), + timetableNameController: TextEditingController(), + columnsController: TextEditingController(), + loadingState: LoadingState.progress, + ), + ) { + // loadTimetables(); + } + + final TimetableRepository _api; + final Logger _logger = Logger(); + + void loadTimetables() async { + try { + final List timetables = await _api.getTimetables(''); + state = state.copyWith( + timetableList: timetables, + loadingState: LoadingState.success, + ); + } catch (e) { + _logger.e(e); + state = state.copyWith(loadingState: LoadingState.error); + } + } + + void addTimetable() { + final Timetable timetable = + Timetable(id: '1', name: state.timetableNameController.text, rows: 5, columns: 5, timetable: []); + state = state.copyWith( + timetableList: [...state.timetableList, timetable], + timetableNameController: TextEditingController(), + ); + } + + void deleteTimetable(Timetable timetable) { + state = state.copyWith( + timetableList: state.timetableList.where((t) => t.id != timetable.id).toList(), + ); + } +} diff --git a/frontend/lib/repositories/timetable_repository.dart b/frontend/lib/repositories/timetable_repository.dart new file mode 100644 index 0000000..5959beb --- /dev/null +++ b/frontend/lib/repositories/timetable_repository.dart @@ -0,0 +1,42 @@ +import 'package:dio/dio.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:logger/logger.dart'; +import '../models/timtable.dart'; + +final timetableRepositoryProvider = Provider((ref) => TimetableRepository()); + +class TimetableRepository { + final _client = Dio( + BaseOptions( + baseUrl: dotenv.env['BACKEND_DOMAIN']!, + validateStatus: (status) { + return status! < 500; + }, + ), + ); + + final Logger _logger = Logger(); + + Future> getTimetables(String token) async { + _client.options.headers['authorization'] = token; + try { + final response = await _client.get('/timetable'); + return (response.data as List).map((e) => Timetable.fromJson(e)).toList(); + } catch (e) { + _logger.e(e); + return []; + } + } + + Future getTimetableById(String id, String token) async { + _client.options.headers['authorization'] = token; + try { + final response = await _client.get('/timetable/$id'); + return Timetable.fromJson(response.data); + } catch (e) { + _logger.e(e); + return null; + } + } +} diff --git a/frontend/lib/routes/routes.dart b/frontend/lib/routes/routes.dart index 6fb94c9..5daf305 100644 --- a/frontend/lib/routes/routes.dart +++ b/frontend/lib/routes/routes.dart @@ -8,6 +8,7 @@ import 'package:smart_insti_app/screens/admin/view_students.dart'; import 'package:smart_insti_app/screens/auth/login_general.dart'; import 'package:smart_insti_app/screens/loading_page.dart'; import 'package:smart_insti_app/screens/user/lost_and_found.dart'; +import 'package:smart_insti_app/screens/user/timetable_editor.dart'; import '../screens/admin/add_faculty.dart'; import '../screens/admin/add_menu.dart'; import '../screens/admin/admin_profile.dart'; @@ -16,6 +17,7 @@ import '../screens/admin/view_faculty.dart'; import '../screens/admin/view_menu.dart'; import '../screens/auth/admin_login.dart'; import '../screens/user/room_vacancy.dart'; +import '../screens/user/timetables.dart'; import '../screens/user/user_home.dart'; import '../screens/user/faculty_profile.dart'; import '../screens/user/student_profile.dart'; @@ -43,8 +45,7 @@ final GoRouter routes = GoRouter( routes: [ GoRoute( path: 'profile', - pageBuilder: (context, state) => - const MaterialPage(child: AdminProfile()), + pageBuilder: (context, state) => const MaterialPage(child: AdminProfile()), ), GoRoute( path: 'add_students', @@ -90,23 +91,30 @@ final GoRouter routes = GoRouter( routes: [ GoRoute( path: 'faculty_profile', - pageBuilder: (context, state) => - const MaterialPage(child: FacultyProfile()), + pageBuilder: (context, state) => const MaterialPage(child: FacultyProfile()), ), GoRoute( path: 'student_profile', - pageBuilder: (context, state) => - const MaterialPage(child: StudentProfile()), + pageBuilder: (context, state) => const MaterialPage(child: StudentProfile()), ), GoRoute( path: 'room_vacancy', - pageBuilder: (context, state) => - const MaterialPage(child: RoomVacancy()), + pageBuilder: (context, state) => const MaterialPage(child: RoomVacancy()), ), GoRoute( path: 'lost_and_found', pageBuilder: (context, state) => MaterialPage(child: LostAndFound()), ), + GoRoute( + path: 'timetables', + pageBuilder: (context, state) => const MaterialPage(child: Timetables()), + routes: [ + GoRoute( + path: 'editor', + pageBuilder: (context, state) => const MaterialPage(child: TimetableEditor()), + ), + ], + ), ], ), ], diff --git a/frontend/lib/screens/loading_page.dart b/frontend/lib/screens/loading_page.dart index 284e79b..e22d9a9 100644 --- a/frontend/lib/screens/loading_page.dart +++ b/frontend/lib/screens/loading_page.dart @@ -1,4 +1,5 @@ import 'package:animated_text_kit/animated_text_kit.dart'; +import 'package:auto_orientation/auto_orientation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; diff --git a/frontend/lib/screens/user/timetable_editor.dart b/frontend/lib/screens/user/timetable_editor.dart new file mode 100644 index 0000000..d90943f --- /dev/null +++ b/frontend/lib/screens/user/timetable_editor.dart @@ -0,0 +1,70 @@ +import 'package:auto_orientation/auto_orientation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:logger/logger.dart'; +import 'package:responsive_framework/responsive_framework.dart'; + +class TimetableEditor extends ConsumerWidget { + const TimetableEditor({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + double width = MediaQuery.of(context).size.width; + double height = MediaQuery.of(context).size.height; + + AutoOrientation.landscapeAutoMode(); + return PopScope( + onPopInvoked: (value) { + AutoOrientation.portraitUpMode(); + context.go('/user_home/timetables'); + }, + child: Scaffold( + floatingActionButton: SizedBox( + width: 35, + height: 35, + child: FittedBox( + child: FloatingActionButton( + onPressed: () { + // context.push('/user_home/room_vacancy'); + }, + child: const Icon(Icons.add), + ), + ), + ), + floatingActionButtonAnimator: FloatingActionButtonAnimator.scaling, + body: Container( + color: Colors.green, + child: InteractiveViewer( + boundaryMargin: const EdgeInsets.all(20), + constrained: true, + child: Container( + color: Colors.blue, + child: Row( + children: [ + Column( + children: [ + for (int i = 0; i < 10; i++) + Container( + width: 100, + height: 100, + color: Colors.red, + child: Center( + child: Text( + 'Column $i', + style: const TextStyle(fontSize: 20), + ), + ), + ), + ], + ) + ], + ), + ), + ), + ), + ), + ); + } +} diff --git a/frontend/lib/screens/user/timetables.dart b/frontend/lib/screens/user/timetables.dart new file mode 100644 index 0000000..73439a2 --- /dev/null +++ b/frontend/lib/screens/user/timetables.dart @@ -0,0 +1,84 @@ +import 'package:auto_orientation/auto_orientation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:go_router/go_router.dart'; +import 'package:responsive_framework/responsive_framework.dart'; +import 'package:smart_insti_app/components/borderless_button.dart'; +import 'package:smart_insti_app/components/material_textformfield.dart'; + +class Timetables extends StatelessWidget { + const Timetables({super.key}); + + @override + Widget build(BuildContext context) { + return ResponsiveScaledBox( + width: 411, + child: Scaffold( + appBar: AppBar( + title: const Text('Time Tables'), + ), + floatingActionButton: FloatingActionButton( + onPressed: () { + showDialog( + context: context, + builder: (_) => AlertDialog( + content: const SizedBox( + width: 300, + height: 250, + child: Column( + children: [ + Text( + 'Add Time Table', + style: TextStyle(fontSize: 28), + ), + SizedBox(height: 20), + MaterialTextFormField(hintText: "Timetable name"), + SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + SizedBox( + child: MaterialTextFormField(hintText: "7"), + width: 100, + ), + Text('X'), + SizedBox( + child: MaterialTextFormField(hintText: ""), + width: 100, + ), + ], + ), + SizedBox(height: 20), + ], + ), + ), + actions: [ + BorderlessButton( + onPressed: () => context.push('/user_home/timetables/editor'), + label: const Text('Add'), + backgroundColor: Colors.green.shade100, + splashColor: Colors.green.shade700, + ), + ], + ), + ); + }, + child: const Icon(Icons.add), + ), + body: ListView.builder( + itemCount: 20, + itemBuilder: (context, index) { + return OutlinedButton( + onPressed: () { + // context.push('/user_home/room_vacancy'); + }, + child: ListTile( + title: Text('Time Table $index'), + ), + ); + }, + ), + ), + ); + } +} diff --git a/frontend/pubspec.lock b/frontend/pubspec.lock index 6f01968..db92003 100644 --- a/frontend/pubspec.lock +++ b/frontend/pubspec.lock @@ -49,6 +49,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" + auto_orientation: + dependency: "direct main" + description: + name: auto_orientation + sha256: cd56bb59b36fa54cc28ee254bc600524f022a4862f31d5ab20abd7bb1c54e678 + url: "https://pub.dev" + source: hosted + version: "2.3.1" awesome_notifications: dependency: "direct main" description: diff --git a/frontend/pubspec.yaml b/frontend/pubspec.yaml index ad0c690..b65cc10 100644 --- a/frontend/pubspec.yaml +++ b/frontend/pubspec.yaml @@ -57,6 +57,7 @@ dependencies: image_cropper: ^5.0.1 url_launcher: ^6.2.4 flutter_dotenv: ^5.1.0 + auto_orientation: ^2.3.1 dev_dependencies: flutter_test: From d02e58911c32b0872f281b82a39f2fa1dc218573 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 14:28:40 +0530 Subject: [PATCH 02/30] Added auto size text and removed unused packages --- frontend/pubspec.lock | 40 ++++++++++++---------------------------- frontend/pubspec.yaml | 2 +- 2 files changed, 13 insertions(+), 29 deletions(-) diff --git a/frontend/pubspec.lock b/frontend/pubspec.lock index db92003..e811dcc 100644 --- a/frontend/pubspec.lock +++ b/frontend/pubspec.lock @@ -57,6 +57,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.1" + auto_size_text: + dependency: "direct main" + description: + name: auto_size_text + sha256: "3f5261cd3fb5f2a9ab4e2fc3fba84fd9fcaac8821f20a1d4e71f557521b22599" + url: "https://pub.dev" + source: hosted + version: "3.0.0" awesome_notifications: dependency: "direct main" description: @@ -177,14 +185,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.4" - delightful_toast: - dependency: "direct main" - description: - name: delightful_toast - sha256: "93d0b9e89a65947e42daa8aafe552596487dbedc15f68d0480654e789e94bc5b" - url: "https://pub.dev" - source: hosted - version: "1.1.0" dio: dependency: "direct main" description: @@ -262,14 +262,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_animate: - dependency: transitive - description: - name: flutter_animate - sha256: "7c8a6594a9252dad30cc2ef16e33270b6248c4dedc3b3d06c86c4f3f4dc05ae5" - url: "https://pub.dev" - source: hosted - version: "4.5.0" flutter_dotenv: dependency: "direct main" description: @@ -398,14 +390,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0" - flutter_shaders: - dependency: transitive - description: - name: flutter_shaders - sha256: "02750b545c01ff4d8e9bbe8f27a7731aa3778402506c67daa1de7f5fc3f4befe" - url: "https://pub.dev" - source: hosted - version: "0.1.2" flutter_svg: dependency: transitive description: @@ -937,10 +921,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "507dc655b1d9cb5ebc756032eb785f114e415f91557b73bf60b7e201dfedeb2f" + sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745 url: "https://pub.dev" source: hosted - version: "6.2.2" + version: "6.3.0" url_launcher_ios: dependency: transitive description: @@ -969,10 +953,10 @@ packages: dependency: transitive description: name: url_launcher_platform_interface - sha256: a932c3a8082e118f80a475ce692fde89dc20fddb24c57360b96bc56f7035de1f + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" url_launcher_web: dependency: transitive description: diff --git a/frontend/pubspec.yaml b/frontend/pubspec.yaml index b65cc10..784de5a 100644 --- a/frontend/pubspec.yaml +++ b/frontend/pubspec.yaml @@ -49,7 +49,6 @@ dependencies: grouped_list: ^5.1.2 slide_switcher: ^1.1.2 awesome_snackbar_content: ^0.1.1 - delightful_toast: ^1.1.0 animated_toggle_switch: ^0.8.0 dio: ^5.4.0 animated_text_kit: ^4.2.2 @@ -58,6 +57,7 @@ dependencies: url_launcher: ^6.2.4 flutter_dotenv: ^5.1.0 auto_orientation: ^2.3.1 + auto_size_text: ^3.0.0 dev_dependencies: flutter_test: From bd4ac744aa6b91d86e647f915041ae049b90f3f6 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 14:32:58 +0530 Subject: [PATCH 03/30] Added component time table button --- frontend/lib/components/timetable_button.dart | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 frontend/lib/components/timetable_button.dart diff --git a/frontend/lib/components/timetable_button.dart b/frontend/lib/components/timetable_button.dart new file mode 100644 index 0000000..93a935f --- /dev/null +++ b/frontend/lib/components/timetable_button.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; + +class TimetableButton extends StatelessWidget { + const TimetableButton({super.key, required this.child, required this.onPressed}); + + final Widget child; + final void Function() onPressed; + + @override + Widget build(BuildContext context) { + return SizedBox( + width: 130, + height: 60, + child: OutlinedButton( + onPressed: onPressed, + style: OutlinedButton.styleFrom( + primary: Colors.black, + backgroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + // padding: const EdgeInsets.all(0), + side: const BorderSide(color: Colors.black, width: 1), + ), + child: child, + ), + ); + } +} From 39596ac441193969bd3e58da237b807a306a253b Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 14:33:47 +0530 Subject: [PATCH 04/30] Updated generated assets --- frontend/lib/generated/assets.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/lib/generated/assets.dart b/frontend/lib/generated/assets.dart index 7a8752c..efa078b 100644 --- a/frontend/lib/generated/assets.dart +++ b/frontend/lib/generated/assets.dart @@ -32,6 +32,7 @@ class Assets { static const String componentsSnackbar = 'lib/components/snackbar.dart'; static const String componentsSuggestionTextField = 'lib/components/suggestion_text_field.dart'; static const String componentsTextDivider = 'lib/components/text_divider.dart'; + static const String componentsTimetableButton = 'lib/components/timetable_button.dart'; static const String componentsYearPicker = 'lib/components/year_picker.dart'; static const String constantsConstants = 'lib/constants/constants.dart'; static const String constantsDummyEntries = 'lib/constants/dummy_entries.dart'; @@ -90,4 +91,5 @@ class Assets { static const String userTimetableEditor = 'lib/screens/user/timetable_editor.dart'; static const String userTimetables = 'lib/screens/user/timetables.dart'; static const String userUserHome = 'lib/screens/user/user_home.dart'; + } From 8e6658ca7e5eee0332e845941b519b7c326cd2bb Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 14:34:38 +0530 Subject: [PATCH 05/30] Added prompt for adding timetable --- frontend/lib/screens/user/timetables.dart | 98 +++++++++++++++++++---- 1 file changed, 83 insertions(+), 15 deletions(-) diff --git a/frontend/lib/screens/user/timetables.dart b/frontend/lib/screens/user/timetables.dart index 73439a2..2db36dd 100644 --- a/frontend/lib/screens/user/timetables.dart +++ b/frontend/lib/screens/user/timetables.dart @@ -22,29 +22,97 @@ class Timetables extends StatelessWidget { showDialog( context: context, builder: (_) => AlertDialog( - content: const SizedBox( - width: 300, - height: 250, + content: SizedBox( + width: 400, + height: 305, + child: Form( + key: _formKey, child: Column( children: [ - Text( + const Text( 'Add Time Table', style: TextStyle(fontSize: 28), ), - SizedBox(height: 20), - MaterialTextFormField(hintText: "Timetable name"), - SizedBox(height: 20), + const SizedBox(height: 20), + MaterialTextFormField( + hintText: "Timetable name", + controller: ref.read(timetableProvider).timetableNameController, + validator: (value) => Validators.nameValidator(value), + ), + const SizedBox(height: 20), Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox( - child: MaterialTextFormField(hintText: "7"), - width: 100, - ), - Text('X'), - SizedBox( - child: MaterialTextFormField(hintText: ""), - width: 100, + width: 70, + child: MaterialTextFormField( + controller: ref.read(timetableProvider).rowsController, + textAlign: TextAlign.center, + enabled: false, + hintText: '', + ), + ), + const SizedBox(width: 15), + const Text('X', style: TextStyle(fontSize: 18)), + const SizedBox(width: 15), + Tooltip( + key: _toolTipKey, + verticalOffset: 40, + showDuration: const Duration(seconds: 1), + message: "Please enter number of columns", + triggerMode: TooltipTriggerMode.manual, + child: SizedBox( + width: 70, + child: MaterialTextFormField( + hintText: "", + textAlign: TextAlign.center, + controller: ref.read(timetableProvider).columnsController, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly, + LengthLimitingTextInputFormatter(1), + ], + ), + ), + ), + ], + ), + const SizedBox(height: 30), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text('Include Saturday?', style: TextStyle(fontSize: 15)), + const SizedBox(width: 20), + Consumer( + builder: (_, ref, __) => AnimatedToggleSwitch.dual( + height: 45, + spacing: 15, + onTap: (value) { + ref.read(timetableProvider.notifier).toggleIncludeSaturday(); + }, + current: ref.watch(timetableProvider).includeSaturday, + first: true, + second: false, + styleBuilder: (value) => value + ? ToggleStyle( + indicatorColor: Colors.teal, + backgroundColor: Colors.tealAccent.shade100, + borderColor: Colors.transparent, + ) + : ToggleStyle( + indicatorColor: Colors.redAccent, + backgroundColor: Colors.redAccent.shade100, + borderColor: Colors.transparent, + ), + iconBuilder: (value) => value + ? const Icon( + Icons.check, + color: Colors.white, + ) + : const Icon( + Icons.not_interested_rounded, + color: Colors.white, + ), + ), ), ], ), From 73d239335ce2fbc9d14cc5f5edff1d4bf4a03d91 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 14:38:01 +0530 Subject: [PATCH 06/30] List view for current timetables --- frontend/lib/screens/user/timetables.dart | 75 ++++++++++++++++++++--- 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/frontend/lib/screens/user/timetables.dart b/frontend/lib/screens/user/timetables.dart index 2db36dd..41c407a 100644 --- a/frontend/lib/screens/user/timetables.dart +++ b/frontend/lib/screens/user/timetables.dart @@ -116,34 +116,89 @@ class Timetables extends StatelessWidget { ), ], ), - SizedBox(height: 20), ], + ), ), ), actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + BorderlessButton( + onPressed: () { + ref.read(timetableProvider.notifier).clearControllers(); + context.pop(); + }, + label: const Text('Back'), + backgroundColor: Colors.red.shade100, + splashColor: Colors.red.shade700, + ), BorderlessButton( - onPressed: () => context.push('/user_home/timetables/editor'), + onPressed: () { + if (_formKey.currentState!.validate()) { + if (ref.read(timetableProvider).columnsController.text == '') { + _toolTipKey.currentState?.ensureTooltipVisible(); + } else { + context.pop(); + ref.read(timetableProvider.notifier).initTileControllersAndTime(); + context.push('/user_home/timetables/editor'); + } + } + }, label: const Text('Add'), backgroundColor: Colors.green.shade100, splashColor: Colors.green.shade700, ), ], + ) + ], + actionsAlignment: MainAxisAlignment.spaceBetween, ), ); }, child: const Icon(Icons.add), ), - body: ListView.builder( - itemCount: 20, + ), + ), + body: Consumer( + builder: (_, ref, __) { + if (ref.watch(timetableProvider).timetables.isEmpty) { + return const Center( + child: Text( + 'No timetables so far', + style: TextStyle(fontSize: 30, color: Colors.black38), + ), + ); + } else { + return ListView.builder( + itemCount: ref.watch(timetableProvider).timetables.length, itemBuilder: (context, index) { - return OutlinedButton( - onPressed: () { - // context.push('/user_home/room_vacancy'); + return Container( + margin: const EdgeInsets.all(10), + child: ListTile( + title: Text(ref.watch(timetableProvider).timetables[index].name), + tileColor: Colors.grey.shade300, + subtitle: Text('Rows: ${ref.watch(timetableProvider).timetables[index].rows} Columns: ${ref.watch(timetableProvider).timetables[index].columns}'), + onTap: () { + ref.read(timetableProvider.notifier).initTileControllersAndTime(timetable : ref.read(timetableProvider).timetables[index]); + context.push('/user_home/timetables/editor'); }, - child: ListTile( - title: Text('Time Table $index'), - ), + trailing: IconButton( + icon: const Icon(Icons.delete), + iconSize: 21, + onPressed: () async { + await ref.read(timetableProvider.notifier).deleteTimetable(ref.read(timetableProvider).timetables[index]); + }, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + + ), ); + }, + ); + } }, ), ), From bc338b2ff82692720c53ed4b3fed5462064495c1 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 14:38:36 +0530 Subject: [PATCH 07/30] Updated timetable's json factories --- frontend/lib/models/timtable.dart | 35 ++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/frontend/lib/models/timtable.dart b/frontend/lib/models/timtable.dart index 4079dd0..64e6e02 100644 --- a/frontend/lib/models/timtable.dart +++ b/frontend/lib/models/timtable.dart @@ -1,15 +1,21 @@ +import 'package:flutter/material.dart'; + class Timetable { - final String id; + final String? id; final String name; final int rows; final int columns; + final String creatorId; + final List<(TimeOfDay, TimeOfDay)> timeRanges; final List> timetable; Timetable({ - required this.id, + this.id, required this.name, required this.rows, required this.columns, + required this.creatorId, + required this.timeRanges, required this.timetable, }); @@ -19,16 +25,39 @@ class Timetable { name: json['name'], rows: json['rows'], columns: json['columns'], + creatorId: json['creatorId'], + timeRanges: List<(TimeOfDay, TimeOfDay)>.from( + json['timeRanges'].map( + (x) => ( + TimeOfDay(hour: x['start']['hour'], minute: x['start']['minute']), + TimeOfDay(hour: x['end']['hour'], minute: x['end']['minute']) + ), + ), + ), timetable: List>.from(json['timetable'].map((x) => List.from(x.map((x) => x)))), ); } Map toJson() { return { - 'id': id, 'name': name, 'rows': rows, 'columns': columns, + 'creatorId': creatorId, + 'timeRanges': List.from( + timeRanges.map( + (x) => { + 'start': { + 'hour': '${x.$1.hour}', + 'minute': '${x.$1.minute}', + }, + 'end': { + 'hour': '${x.$2.hour}', + 'minute': '${x.$2.minute}', + } + }, + ), + ), 'timetable': List.from(timetable.map((x) => List.from(x.map((x) => x)))), }; } From d9705ad001c8431604959dbf93ee8e6b73120ae8 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 14:39:04 +0530 Subject: [PATCH 08/30] Added token check logic and necessary imports --- frontend/lib/screens/user/timetables.dart | 96 ++++++++++++++--------- 1 file changed, 59 insertions(+), 37 deletions(-) diff --git a/frontend/lib/screens/user/timetables.dart b/frontend/lib/screens/user/timetables.dart index 41c407a..f3a291a 100644 --- a/frontend/lib/screens/user/timetables.dart +++ b/frontend/lib/screens/user/timetables.dart @@ -1,38 +1,60 @@ +import 'package:animated_toggle_switch/animated_toggle_switch.dart'; import 'package:auto_orientation/auto_orientation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; +import 'package:logger/logger.dart'; import 'package:responsive_framework/responsive_framework.dart'; import 'package:smart_insti_app/components/borderless_button.dart'; import 'package:smart_insti_app/components/material_textformfield.dart'; +import 'package:smart_insti_app/constants/constants.dart'; +import 'package:smart_insti_app/provider/timetable_provider.dart'; -class Timetables extends StatelessWidget { - const Timetables({super.key}); +import '../../provider/auth_provider.dart'; + +class Timetables extends ConsumerWidget { + Timetables({super.key}); + + final GlobalKey _formKey = GlobalKey(); + final GlobalKey _toolTipKey = GlobalKey(); @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (ref.read(authProvider.notifier).tokenCheckProgress != LoadingState.progress && context.mounted) { + ref.read(authProvider.notifier).verifyAuthTokenExistence(context, AuthConstants.generalAuthLabel.toLowerCase()); + } + }); + return ResponsiveScaledBox( width: 411, child: Scaffold( appBar: AppBar( title: const Text('Time Tables'), ), - floatingActionButton: FloatingActionButton( - onPressed: () { - showDialog( - context: context, - builder: (_) => AlertDialog( + floatingActionButton: Padding( + padding: const EdgeInsets.all(8.0), + child: SizedBox( + width: 70, + height: 70, + child: FloatingActionButton( + onPressed: () { + ref.read(timetableProvider.notifier).clearControllers(); + showDialog( + context: context, + builder: (_) => AlertDialog( content: SizedBox( width: 400, height: 305, child: Form( key: _formKey, - child: Column( - children: [ + child: Column( + children: [ const Text( - 'Add Time Table', - style: TextStyle(fontSize: 28), - ), + 'Add Time Table', + style: TextStyle(fontSize: 28), + ), const SizedBox(height: 20), MaterialTextFormField( hintText: "Timetable name", @@ -40,10 +62,10 @@ class Timetables extends StatelessWidget { validator: (value) => Validators.nameValidator(value), ), const SizedBox(height: 20), - Row( + Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox( + children: [ + SizedBox( width: 70, child: MaterialTextFormField( controller: ref.read(timetableProvider).rowsController, @@ -113,14 +135,14 @@ class Timetables extends StatelessWidget { color: Colors.white, ), ), - ), - ], - ), - ], + ), + ], + ), + ], ), - ), - ), - actions: [ + ), + ), + actions: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -133,7 +155,7 @@ class Timetables extends StatelessWidget { backgroundColor: Colors.red.shade100, splashColor: Colors.red.shade700, ), - BorderlessButton( + BorderlessButton( onPressed: () { if (_formKey.currentState!.validate()) { if (ref.read(timetableProvider).columnsController.text == '') { @@ -145,19 +167,19 @@ class Timetables extends StatelessWidget { } } }, - label: const Text('Add'), - backgroundColor: Colors.green.shade100, - splashColor: Colors.green.shade700, - ), - ], + label: const Text('Add'), + backgroundColor: Colors.green.shade100, + splashColor: Colors.green.shade700, + ), + ], ) ], actionsAlignment: MainAxisAlignment.spaceBetween, - ), - ); - }, - child: const Icon(Icons.add), - ), + ), + ); + }, + child: const Icon(Icons.add), + ), ), ), body: Consumer( @@ -172,7 +194,7 @@ class Timetables extends StatelessWidget { } else { return ListView.builder( itemCount: ref.watch(timetableProvider).timetables.length, - itemBuilder: (context, index) { + itemBuilder: (context, index) { return Container( margin: const EdgeInsets.all(10), child: ListTile( @@ -182,7 +204,7 @@ class Timetables extends StatelessWidget { onTap: () { ref.read(timetableProvider.notifier).initTileControllersAndTime(timetable : ref.read(timetableProvider).timetables[index]); context.push('/user_home/timetables/editor'); - }, + }, trailing: IconButton( icon: const Icon(Icons.delete), iconSize: 21, @@ -195,7 +217,7 @@ class Timetables extends StatelessWidget { ), ), - ); + ); }, ); } From 2b4a9c12f1b2dde7beb8dbbdb015c0973650e569 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 14:42:35 +0530 Subject: [PATCH 09/30] Added token to header with timetable api calls --- .../repositories/timetable_repository.dart | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/frontend/lib/repositories/timetable_repository.dart b/frontend/lib/repositories/timetable_repository.dart index 5959beb..65ef03e 100644 --- a/frontend/lib/repositories/timetable_repository.dart +++ b/frontend/lib/repositories/timetable_repository.dart @@ -1,6 +1,7 @@ import 'package:dio/dio.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:logger/logger.dart'; import '../models/timtable.dart'; @@ -17,23 +18,25 @@ class TimetableRepository { ); final Logger _logger = Logger(); + final _secureStorage = const FlutterSecureStorage(); - Future> getTimetables(String token) async { - _client.options.headers['authorization'] = token; + Future createTimetable(Timetable timetable) async { + _client.options.headers['authorization'] = await _secureStorage.read(key: 'token') ?? ''; try { - final response = await _client.get('/timetable'); - return (response.data as List).map((e) => Timetable.fromJson(e)).toList(); + final response = await _client.post('/timetable', data: timetable.toJson()); + _logger.i(response.data); + return true; } catch (e) { _logger.e(e); - return []; + return false; } } - Future getTimetableById(String id, String token) async { - _client.options.headers['authorization'] = token; + Future?> getTimetablesByCreatorId(String creatorId) async { + _client.options.headers['authorization'] = await _secureStorage.read(key: 'token') ?? ''; try { - final response = await _client.get('/timetable/$id'); - return Timetable.fromJson(response.data); + final response = await _client.get('/timetables/$creatorId'); + return (response.data as List).map((e) => Timetable.fromJson(e)).toList(); } catch (e) { _logger.e(e); return null; From 761d6d3fcaa1482d4e06df12145d773e9269c8be Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 14:42:58 +0530 Subject: [PATCH 10/30] Added delete timetable method to api --- frontend/lib/repositories/timetable_repository.dart | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/frontend/lib/repositories/timetable_repository.dart b/frontend/lib/repositories/timetable_repository.dart index 65ef03e..e5aaa60 100644 --- a/frontend/lib/repositories/timetable_repository.dart +++ b/frontend/lib/repositories/timetable_repository.dart @@ -42,4 +42,16 @@ class TimetableRepository { return null; } } + + Future deleteTimetableById(String id) async { + _client.options.headers['authorization'] = await _secureStorage.read(key: 'token') ?? ''; + try { + final response = await _client.delete('/timetables/$id'); + _logger.i(response.data); + return true; + } catch (e) { + _logger.e(e); + return false; + } + } } From 30f03e6919e1411860a5721218603a91b27cb4fb Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 14:48:58 +0530 Subject: [PATCH 11/30] Fixed orientation change upon opening timetable editor --- .../lib/screens/user/timetable_editor.dart | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/frontend/lib/screens/user/timetable_editor.dart b/frontend/lib/screens/user/timetable_editor.dart index d90943f..7f722ff 100644 --- a/frontend/lib/screens/user/timetable_editor.dart +++ b/frontend/lib/screens/user/timetable_editor.dart @@ -6,20 +6,24 @@ import 'package:go_router/go_router.dart'; import 'package:logger/logger.dart'; import 'package:responsive_framework/responsive_framework.dart'; -class TimetableEditor extends ConsumerWidget { +class TimetableEditor extends ConsumerStatefulWidget { const TimetableEditor({super.key}); @override - Widget build(BuildContext context, WidgetRef ref) { + ConsumerState createState() => _TimetableEditorState(); +} + +class _TimetableEditorState extends ConsumerState { + @override + Widget build(BuildContext context) { double width = MediaQuery.of(context).size.width; double height = MediaQuery.of(context).size.height; - - AutoOrientation.landscapeAutoMode(); - return PopScope( - onPopInvoked: (value) { - AutoOrientation.portraitUpMode(); - context.go('/user_home/timetables'); - }, + WidgetsBinding.instance.addPostFrameCallback((_) { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.landscapeRight, + DeviceOrientation.landscapeLeft, + ]); + }); child: Scaffold( floatingActionButton: SizedBox( width: 35, @@ -67,4 +71,13 @@ class TimetableEditor extends ConsumerWidget { ), ); } + + @override + void dispose() { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); + super.dispose(); + } } From a5c618fc233d0b7e6ac50cb3a064d6f48640ef28 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 14:50:41 +0530 Subject: [PATCH 12/30] Extracted build timetable method to the provider --- .../lib/screens/user/timetable_editor.dart | 69 ++++++++----------- 1 file changed, 29 insertions(+), 40 deletions(-) diff --git a/frontend/lib/screens/user/timetable_editor.dart b/frontend/lib/screens/user/timetable_editor.dart index 7f722ff..7b72caf 100644 --- a/frontend/lib/screens/user/timetable_editor.dart +++ b/frontend/lib/screens/user/timetable_editor.dart @@ -1,10 +1,9 @@ -import 'package:auto_orientation/auto_orientation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; -import 'package:logger/logger.dart'; import 'package:responsive_framework/responsive_framework.dart'; +import 'package:smart_insti_app/provider/timetable_provider.dart'; class TimetableEditor extends ConsumerStatefulWidget { const TimetableEditor({super.key}); @@ -24,51 +23,41 @@ class _TimetableEditorState extends ConsumerState { DeviceOrientation.landscapeLeft, ]); }); + return ResponsiveScaledBox( + width: 411, child: Scaffold( - floatingActionButton: SizedBox( - width: 35, - height: 35, - child: FittedBox( - child: FloatingActionButton( - onPressed: () { - // context.push('/user_home/room_vacancy'); - }, - child: const Icon(Icons.add), + resizeToAvoidBottomInset: false, + floatingActionButton: SizedBox( + width: 30, + height: 30, + child: FittedBox( + child: FloatingActionButton( + onPressed: () async { + await ref.read(timetableProvider.notifier).addTimetable(); + if (context.mounted) { + context.pop(); + } + }, + child: const Icon(Icons.add), + ), ), ), - ), - floatingActionButtonAnimator: FloatingActionButtonAnimator.scaling, - body: Container( - color: Colors.green, - child: InteractiveViewer( - boundaryMargin: const EdgeInsets.all(20), - constrained: true, - child: Container( - color: Colors.blue, - child: Row( - children: [ - Column( - children: [ - for (int i = 0; i < 10; i++) - Container( - width: 100, - height: 100, - color: Colors.red, - child: Center( - child: Text( - 'Column $i', - style: const TextStyle(fontSize: 20), - ), - ), - ), - ], - ) - ], + body: SizedBox( + height: height, + width: width, + child: InteractiveViewer( + boundaryMargin: const EdgeInsets.all(20), + constrained: true, + child: Container( + width: 90, + padding: const EdgeInsets.all(10), + child: Consumer( + builder: (_, ref, __) => ref.read(timetableProvider.notifier).buildTimetableTiles(context), + ), ), ), ), ), - ), ); } From def5228cd001a144c209c5c2f3dc548e7ec51779 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 14:53:08 +0530 Subject: [PATCH 13/30] Added text alignment and input formatters in material text form field --- frontend/lib/components/material_textformfield.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/frontend/lib/components/material_textformfield.dart b/frontend/lib/components/material_textformfield.dart index 63e1828..a47516a 100644 --- a/frontend/lib/components/material_textformfield.dart +++ b/frontend/lib/components/material_textformfield.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; class MaterialTextFormField extends StatelessWidget { const MaterialTextFormField( @@ -11,7 +12,9 @@ class MaterialTextFormField extends StatelessWidget { this.contentPadding, this.hintColor, this.enabled, - this.controllerLessValue}); + this.controllerLessValue, + this.textAlign, + this.inputFormatters}); final TextEditingController? controller; final String? Function(String?)? validator; @@ -22,6 +25,8 @@ class MaterialTextFormField extends StatelessWidget { final EdgeInsets? contentPadding; final bool? enabled; final String? controllerLessValue; + final TextAlign? textAlign; + final List? inputFormatters; @override Widget build(BuildContext context) { @@ -33,6 +38,8 @@ class MaterialTextFormField extends StatelessWidget { enabled: enabled ?? true, controller: controller ?? substituteController, maxLines: 1, + inputFormatters: inputFormatters, + textAlign: textAlign ?? TextAlign.start, onChanged: (value) => onChanged != null ? onChanged!(value) : null, validator: (value) => validator != null ? validator!(value) : null, onFieldSubmitted: (value) => onSubmitted != null ? onSubmitted!(value) : null, From aa154359c41ffad0b8ded5898fc393dad9439f19 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 14:53:33 +0530 Subject: [PATCH 14/30] removed unused imports --- frontend/lib/main.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/lib/main.dart b/frontend/lib/main.dart index dc04b62..265db95 100644 --- a/frontend/lib/main.dart +++ b/frontend/lib/main.dart @@ -4,7 +4,6 @@ import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:smart_insti_app/constants/constants.dart'; import 'package:smart_insti_app/routes/routes.dart'; -import 'package:smart_insti_app/screens/user/timetable_editor.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); From e8b74002aeb499c4b997547977192d83d583bff8 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 14:53:48 +0530 Subject: [PATCH 15/30] Updated routes.dart --- frontend/lib/routes/routes.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/lib/routes/routes.dart b/frontend/lib/routes/routes.dart index 5daf305..820fdd2 100644 --- a/frontend/lib/routes/routes.dart +++ b/frontend/lib/routes/routes.dart @@ -107,7 +107,7 @@ final GoRouter routes = GoRouter( ), GoRoute( path: 'timetables', - pageBuilder: (context, state) => const MaterialPage(child: Timetables()), + pageBuilder: (context, state) => MaterialPage(child: Timetables()), routes: [ GoRoute( path: 'editor', From 7a9c3d48ab12bf6013a27195ddf30c041ec4f0c5 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 14:55:33 +0530 Subject: [PATCH 16/30] Updated time table state and added imports --- frontend/lib/provider/timetable_provider.dart | 52 +++++++++++++++---- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/frontend/lib/provider/timetable_provider.dart b/frontend/lib/provider/timetable_provider.dart index fad3a29..916ff16 100644 --- a/frontend/lib/provider/timetable_provider.dart +++ b/frontend/lib/provider/timetable_provider.dart @@ -1,43 +1,68 @@ -import 'package:flutter/cupertino.dart'; +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:logger/logger.dart'; +import 'package:smart_insti_app/components/borderless_button.dart'; +import 'package:smart_insti_app/components/material_textformfield.dart'; +import 'package:smart_insti_app/provider/auth_provider.dart'; import '../components/menu_tile.dart'; +import '../components/timetable_button.dart'; import '../constants/constants.dart'; +import '../models/admin.dart'; +import '../models/faculty.dart'; +import '../models/student.dart'; import '../models/timtable.dart'; import '../repositories/timetable_repository.dart'; final timetableProvider = StateNotifierProvider((ref) => TimetableProvider(ref)); class TimetableState { - final List timetableList; - final List timetableTiles; + final List timetables; final TextEditingController searchTimetableController; final TextEditingController timetableNameController; + final TextEditingController rowsController; final TextEditingController columnsController; + final bool includeSaturday; + final List> tileControllers; + final List<(TimeOfDay, TimeOfDay)> timeRanges; + final bool tilesDisabled; final LoadingState loadingState; TimetableState( - {required this.timetableList, - required this.timetableTiles, + {required this.timetables, required this.searchTimetableController, required this.timetableNameController, + required this.rowsController, required this.columnsController, + required this.includeSaturday, + required this.tileControllers, + required this.timeRanges, + required this.tilesDisabled, required this.loadingState}); TimetableState copyWith({ - List? timetableList, + List? timetables, List? timetableTiles, TextEditingController? searchTimetableController, TextEditingController? timetableNameController, + TextEditingController? rowsController, TextEditingController? columnsController, + bool? includeSaturday, + List>? tileControllers, + List<(TimeOfDay, TimeOfDay)>? timeRanges, + bool? tilesDisabled, LoadingState? loadingState, }) { return TimetableState( - timetableList: timetableList ?? this.timetableList, - timetableTiles: timetableTiles ?? this.timetableTiles, + timetables: timetables ?? this.timetables, searchTimetableController: searchTimetableController ?? this.searchTimetableController, timetableNameController: timetableNameController ?? this.timetableNameController, + rowsController: rowsController ?? this.rowsController, columnsController: columnsController ?? this.columnsController, + includeSaturday: includeSaturday ?? this.includeSaturday, + tileControllers: tileControllers ?? this.tileControllers, + timeRanges: timeRanges ?? this.timeRanges, + tilesDisabled: tilesDisabled ?? this.tilesDisabled, loadingState: loadingState ?? this.loadingState, ); } @@ -45,15 +70,20 @@ class TimetableState { class TimetableProvider extends StateNotifier { TimetableProvider(Ref ref) - : _api = ref.read(timetableRepositoryProvider), + : _authState = ref.read(authProvider), + _api = ref.read(timetableRepositoryProvider), super( TimetableState( - timetableList: [], - timetableTiles: [], + timetables: [], searchTimetableController: TextEditingController(), timetableNameController: TextEditingController(), + rowsController: TextEditingController(text: '6'), columnsController: TextEditingController(), + includeSaturday: true, + tileControllers: [], + timeRanges: [], loadingState: LoadingState.progress, + tilesDisabled: false, ), ) { // loadTimetables(); From d4dfd5bd56a2d7c84a3b35a81352ce3b7d280862 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 14:56:08 +0530 Subject: [PATCH 17/30] Completed load timetables and run on provider constructor --- frontend/lib/provider/timetable_provider.dart | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/frontend/lib/provider/timetable_provider.dart b/frontend/lib/provider/timetable_provider.dart index 916ff16..b7ade35 100644 --- a/frontend/lib/provider/timetable_provider.dart +++ b/frontend/lib/provider/timetable_provider.dart @@ -86,17 +86,31 @@ class TimetableProvider extends StateNotifier { tilesDisabled: false, ), ) { - // loadTimetables(); + loadTimetables(); } final TimetableRepository _api; + final AuthState _authState; final Logger _logger = Logger(); void loadTimetables() async { + state = state.copyWith(loadingState: LoadingState.progress); try { - final List timetables = await _api.getTimetables(''); + String userId; + + if (_authState.currentUserRole == 'student') { + userId = (_authState.currentUser as Student).id; + } else if (_authState.currentUserRole == 'faculty') { + userId = (_authState.currentUser as Faculty).id; + } else if (_authState.currentUserRole == 'admin') { + userId = (_authState.currentUser as Admin).id; + } else { + return; + } + + final List timetables = await _api.getTimetablesByCreatorId(userId) ?? []; state = state.copyWith( - timetableList: timetables, + timetables: timetables, loadingState: LoadingState.success, ); } catch (e) { From 3a2e288d5ca977ae93f621e3648d0b80bde200dd Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 14:58:05 +0530 Subject: [PATCH 18/30] Init controllers for button method --- frontend/lib/provider/timetable_provider.dart | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/frontend/lib/provider/timetable_provider.dart b/frontend/lib/provider/timetable_provider.dart index b7ade35..4ab2462 100644 --- a/frontend/lib/provider/timetable_provider.dart +++ b/frontend/lib/provider/timetable_provider.dart @@ -119,9 +119,47 @@ class TimetableProvider extends StateNotifier { } } - void addTimetable() { - final Timetable timetable = - Timetable(id: '1', name: state.timetableNameController.text, rows: 5, columns: 5, timetable: []); + initTileControllersAndTime({Timetable? timetable}) { + if (timetable != null) { + state.rowsController.text = timetable.rows.toString(); + state.columnsController.text = timetable.columns.toString(); + state = state.copyWith( + //2d matrix of text controllers + tileControllers: List.generate( + timetable.columns, + (i) => List.generate( + timetable.rows, + (j) => TextEditingController(), + ), + ), + includeSaturday: timetable.rows == 6 ? true : false, + timeRanges: timetable.timeRanges, + tilesDisabled: true, + ); + + for (int i = 0; i < timetable.columns; i++) { + for (int j = 0; j < timetable.rows; j++) { + state.tileControllers[i][j].text = timetable.timetable[i][j]; + } + } + } else { + state = state.copyWith( + //2d matrix of text controllers + tileControllers: List.generate( + int.parse(state.columnsController.text), + (i) => List.generate( + int.parse(state.rowsController.text), + (j) => TextEditingController(), + ), + ), + timeRanges: List.generate( + int.parse(state.columnsController.text), + (index) => (const TimeOfDay(hour: 0, minute: 0), const TimeOfDay(hour: 0, minute: 0)), + ), + tilesDisabled: false, + ); + } + } state = state.copyWith( timetableList: [...state.timetableList, timetable], timetableNameController: TextEditingController(), From 6945b8f53cd6b16aa86296997803d8c5fc436075 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 15:00:25 +0530 Subject: [PATCH 19/30] Defined build timetable method --- frontend/lib/provider/timetable_provider.dart | 155 +++++++++++++++++- 1 file changed, 153 insertions(+), 2 deletions(-) diff --git a/frontend/lib/provider/timetable_provider.dart b/frontend/lib/provider/timetable_provider.dart index 4ab2462..4b88cac 100644 --- a/frontend/lib/provider/timetable_provider.dart +++ b/frontend/lib/provider/timetable_provider.dart @@ -160,10 +160,161 @@ class TimetableProvider extends StateNotifier { ); } } + + Widget buildTimetableTiles(BuildContext context) { + final timeTable = Consumer( + builder: (_, ref, __) => Row( + children: [ + Column( + children: [ + TimetableButton( + child: const Text(''), + onPressed: () {}, + ), + TimetableButton( + child: const Text('Monday'), + onPressed: () {}, + ), + TimetableButton( + child: const Text('Tuesday'), + onPressed: () {}, + ), + TimetableButton( + child: const Text('Wednesday'), + onPressed: () {}, + ), + TimetableButton( + child: const Text('Thursday'), + onPressed: () {}, + ), + TimetableButton( + child: const Text('Friday'), + onPressed: () {}, + ), + if (state.includeSaturday) + TimetableButton( + child: const Text('Saturday'), + onPressed: () {}, + ), + ], + ), + for (int i = 0; i < int.parse(state.columnsController.text); i++) + Column( + children: [ + TimetableButton( + onPressed: ref.read(timetableProvider).tilesDisabled + ? () {} + : () { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text('Edit Time Range'), + content: Container( + width: 300, + height: 100, + color: Colors.transparent, + child: Consumer( + builder: (_, ref, __) => Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + BorderlessButton( + backgroundColor: Colors.green.shade100, + onPressed: () async { + final TimeOfDay? time = await showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + initialEntryMode: TimePickerEntryMode.dial, + ); + if (time != null) { + state = state.copyWith( + timeRanges: [ + ...state.timeRanges.sublist(0, i), + (time, state.timeRanges[i].$2), + ...state.timeRanges.sublist(i + 1), + ], + ); + } + }, + splashColor: Colors.green.shade700, + label: Text( + '${ref.watch(timetableProvider).timeRanges[i].$1.hour}:${ref.watch(timetableProvider).timeRanges[i].$1.minute}'), + ), + BorderlessButton( + backgroundColor: Colors.red.shade100, + onPressed: () async { + final TimeOfDay? time = await showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + initialEntryMode: TimePickerEntryMode.dial, + ); + if (time != null) { state = state.copyWith( - timetableList: [...state.timetableList, timetable], - timetableNameController: TextEditingController(), + timeRanges: [ + ...state.timeRanges.sublist(0, i), + (state.timeRanges[i].$1, time), + ...state.timeRanges.sublist(i + 1), + ], + ); + } + }, + splashColor: Colors.red.shade700, + label: Text( + '${ref.watch(timetableProvider).timeRanges[i].$2.hour}:${ref.watch(timetableProvider).timeRanges[i].$2.minute}'), + ) + ], + ), + ), + ), + ), + ); + }, + child: AutoSizeText( + '${ref.watch(timetableProvider).timeRanges[i].$1.hour}:${ref.watch(timetableProvider).timeRanges[i].$1.minute} - ${ref.watch(timetableProvider).timeRanges[i].$2.hour}:${ref.watch(timetableProvider).timeRanges[i].$2.minute}', + maxLines: 1, + minFontSize: 12, + overflow: TextOverflow.ellipsis, + ), + ), + for (int j = 0; j < int.parse(state.rowsController.text); j++) + TimetableButton( + onPressed: ref.read(timetableProvider).tilesDisabled + ? () {} + : () { + showDialog( + context: context, + builder: (context) => AlertDialog( + scrollable: true, + title: const Text('Edit Subject'), + content: Container( + width: 300, + color: Colors.transparent, + child: IntrinsicHeight( + child: MaterialTextFormField( + controller: state.tileControllers[i][j], + hintText: 'Enter Subject', + ), + ), + ), + ), + ); + }, + child: AutoSizeText( + state.tileControllers[i][j].text, + overflow: TextOverflow.ellipsis, + maxLines: 3, + minFontSize: 12, + ), + ), + ], + ), + ], + ), ); + + return FittedBox( + child: timeTable, + ); + } } void deleteTimetable(Timetable timetable) { From da7241e13dd51d0627012341f7acc161545619c7 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 15:00:50 +0530 Subject: [PATCH 20/30] disable weekday button on view mode --- frontend/lib/provider/timetable_provider.dart | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/frontend/lib/provider/timetable_provider.dart b/frontend/lib/provider/timetable_provider.dart index 4b88cac..c96b603 100644 --- a/frontend/lib/provider/timetable_provider.dart +++ b/frontend/lib/provider/timetable_provider.dart @@ -168,33 +168,33 @@ class TimetableProvider extends StateNotifier { Column( children: [ TimetableButton( + onPressed: ref.read(timetableProvider).tilesDisabled ? () {} : () {}, child: const Text(''), - onPressed: () {}, ), TimetableButton( + onPressed: ref.read(timetableProvider).tilesDisabled ? () {} : () {}, child: const Text('Monday'), - onPressed: () {}, ), TimetableButton( + onPressed: ref.read(timetableProvider).tilesDisabled ? () {} : () {}, child: const Text('Tuesday'), - onPressed: () {}, ), TimetableButton( + onPressed: ref.read(timetableProvider).tilesDisabled ? () {} : () {}, child: const Text('Wednesday'), - onPressed: () {}, ), TimetableButton( + onPressed: ref.read(timetableProvider).tilesDisabled ? () {} : () {}, child: const Text('Thursday'), - onPressed: () {}, ), TimetableButton( + onPressed: ref.read(timetableProvider).tilesDisabled ? () {} : () {}, child: const Text('Friday'), - onPressed: () {}, ), if (state.includeSaturday) TimetableButton( + onPressed: ref.read(timetableProvider).tilesDisabled ? () {} : () {}, child: const Text('Saturday'), - onPressed: () {}, ), ], ), From 2143dee05002cacd287a3a78076633e2c049809a Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 15:01:14 +0530 Subject: [PATCH 21/30] Include saturday toggle method --- frontend/lib/provider/timetable_provider.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/lib/provider/timetable_provider.dart b/frontend/lib/provider/timetable_provider.dart index c96b603..333fd4a 100644 --- a/frontend/lib/provider/timetable_provider.dart +++ b/frontend/lib/provider/timetable_provider.dart @@ -315,6 +315,10 @@ class TimetableProvider extends StateNotifier { child: timeTable, ); } + + void toggleIncludeSaturday() { + state.rowsController.text = state.includeSaturday ? '5' : '6'; + state = state.copyWith(includeSaturday: !state.includeSaturday); } void deleteTimetable(Timetable timetable) { From 41bb98dcd91db82fcb41172f04b7a70d4a347198 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 15:01:43 +0530 Subject: [PATCH 22/30] Defined add timetable method --- frontend/lib/provider/timetable_provider.dart | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/frontend/lib/provider/timetable_provider.dart b/frontend/lib/provider/timetable_provider.dart index 333fd4a..895bef1 100644 --- a/frontend/lib/provider/timetable_provider.dart +++ b/frontend/lib/provider/timetable_provider.dart @@ -321,7 +321,36 @@ class TimetableProvider extends StateNotifier { state = state.copyWith(includeSaturday: !state.includeSaturday); } - void deleteTimetable(Timetable timetable) { + Future addTimetable() async { + String userId; + + if (_authState.currentUserRole == 'student') { + userId = (_authState.currentUser as Student).id; + } else if (_authState.currentUserRole == 'faculty') { + userId = (_authState.currentUser as Faculty).id; + } else { + userId = (_authState.currentUser as Admin).id; + } + + final Timetable timetable = Timetable( + creatorId: userId, + name: state.timetableNameController.text, + rows: int.parse(state.rowsController.text), + columns: int.parse(state.columnsController.text), + timeRanges: state.timeRanges, + timetable: List.generate( + int.parse(state.columnsController.text), + (i) => List.generate( + int.parse(state.rowsController.text), + (j) => state.tileControllers[i][j].text, + ), + ), + ); + if (await _api.createTimetable(timetable)) { + loadTimetables(); + } + } + state = state.copyWith( timetableList: state.timetableList.where((t) => t.id != timetable.id).toList(), ); From 141c80c5f88458c516b94af7fe29306a03003197 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 15:01:57 +0530 Subject: [PATCH 23/30] defined delete timetable method --- frontend/lib/provider/timetable_provider.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/frontend/lib/provider/timetable_provider.dart b/frontend/lib/provider/timetable_provider.dart index 895bef1..7a98eba 100644 --- a/frontend/lib/provider/timetable_provider.dart +++ b/frontend/lib/provider/timetable_provider.dart @@ -351,6 +351,12 @@ class TimetableProvider extends StateNotifier { } } + Future deleteTimetable(Timetable timetable) async { + if (await _api.deleteTimetableById(timetable.id!)) { + loadTimetables(); + } + } + state = state.copyWith( timetableList: state.timetableList.where((t) => t.id != timetable.id).toList(), ); From 6aa651c5d4d483aaed7b924d8bc4033da9291270 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 15:02:30 +0530 Subject: [PATCH 24/30] Updated clear controllers method --- frontend/lib/provider/timetable_provider.dart | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/frontend/lib/provider/timetable_provider.dart b/frontend/lib/provider/timetable_provider.dart index 7a98eba..1a86a72 100644 --- a/frontend/lib/provider/timetable_provider.dart +++ b/frontend/lib/provider/timetable_provider.dart @@ -248,7 +248,7 @@ class TimetableProvider extends StateNotifier { initialEntryMode: TimePickerEntryMode.dial, ); if (time != null) { - state = state.copyWith( + state = state.copyWith( timeRanges: [ ...state.timeRanges.sublist(0, i), (state.timeRanges[i].$1, time), @@ -357,8 +357,14 @@ class TimetableProvider extends StateNotifier { } } + void clearControllers() { state = state.copyWith( - timetableList: state.timetableList.where((t) => t.id != timetable.id).toList(), + timetableNameController: TextEditingController(), + rowsController: TextEditingController(text: '6'), + columnsController: TextEditingController(), + tileControllers: [], + timeRanges: [], + includeSaturday: true, ); } } From c26e7a4b3e398f492c70f53e2cde74f45d0fdc2d Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 15:02:44 +0530 Subject: [PATCH 25/30] Added timetable schema --- backend/models/timetable.js | 56 +++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 backend/models/timetable.js diff --git a/backend/models/timetable.js b/backend/models/timetable.js new file mode 100644 index 0000000..935cfe8 --- /dev/null +++ b/backend/models/timetable.js @@ -0,0 +1,56 @@ +import mongoose from "mongoose"; + +const timetableSchema = new mongoose.Schema({ + id: String, + name: { + type: String, + required: true, + }, + rows: { + type: Number, + required: true, + }, + columns: { + type: Number, + required: true, + }, + creatorId: { + type: String, + required: true, + }, + timeRanges: [ + { + start: { + hour: { + type: Number, + required: true, + }, + minute: { + type: Number, + required: true, + }, + }, + end: { + hour: { + type: Number, + required: true, + }, + minute: { + type: Number, + required: true, + }, + }, + }, + ], + timetable: [ + [ + { + type: String, + }, + ], + ], +}); + +const Timetable = mongoose.model("Timetable", timetableSchema); + +export default Timetable; From 5b15da618558ccf7215639c794e5999b1677110a Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 15:03:35 +0530 Subject: [PATCH 26/30] Post method for add timetable --- .../resources/timetable/timetableResource.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 backend/resources/timetable/timetableResource.js diff --git a/backend/resources/timetable/timetableResource.js b/backend/resources/timetable/timetableResource.js new file mode 100644 index 0000000..d684269 --- /dev/null +++ b/backend/resources/timetable/timetableResource.js @@ -0,0 +1,19 @@ +import express from "express"; +import * as messages from "../../constants/messages.js"; +import Timetable from "../../models/timetable.js"; +import tokenRequired from "../../middlewares/tokenRequired.js"; +const timetableRouter = express.Router(); + +// POST create a new timetable +timetableRouter.post("/", tokenRequired, async (req, res) => { + try { + const newTimetable = new Timetable(req.body); + const savedTimetable = await newTimetable.save(); + res.json(savedTimetable); + } catch (error) { + console.error(error); + res.status(500).json({ message: messages.internalServerError }); + } +}); + +export default timetableRouter; From fa8fcb67aab28e05bfa56783517b6602e4bd4b88 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 15:03:56 +0530 Subject: [PATCH 27/30] Add timetableListResource.js with GET and DELETE routes --- .../timetable/timetableListResource.js | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 backend/resources/timetable/timetableListResource.js diff --git a/backend/resources/timetable/timetableListResource.js b/backend/resources/timetable/timetableListResource.js new file mode 100644 index 0000000..8e91bcf --- /dev/null +++ b/backend/resources/timetable/timetableListResource.js @@ -0,0 +1,34 @@ +import express from "express"; +import * as messages from "../../constants/messages.js"; +import Timetable from "../../models/timetable.js"; +import tokenRequired from "../../middlewares/tokenRequired.js"; +const timetableListRouter = express.Router(); + +// GET list of timetables by id +timetableListRouter.get("/:id", tokenRequired, async (req, res) => { + try { + const creatorId = req.params.id; + const timetables = await Timetable.find({ creatorId }); + res.json(timetables); + } catch (error) { + console.error(error); + res.status(500).json({ message: messages.internalServerError }); + } +}); + +//DELETE method +timetableListRouter.delete("/:id", tokenRequired, async (req, res) => { + try { + const { id } = req.params; + const timetable = await Timetable.findByIdAndDelete(id); + if (!timetable) { + return res.status(404).json({ error: "Timetable not found" }); + } + res.json({ message: "Timetable deleted successfully" }); + } catch (error) { + console.error("Error deleting timetable:", error); + res.status(500).json({ error: "Internal server error" }); + } +}); + +export default timetableListRouter; From 8afd129629ef97a4d9ba81e7d73b04e167f30c5f Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 15:04:15 +0530 Subject: [PATCH 28/30] Add timetable resources --- backend/app.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/app.js b/backend/app.js index 4759035..f0951be 100644 --- a/backend/app.js +++ b/backend/app.js @@ -16,6 +16,8 @@ import roomResource from "./resources/rooms/roomResource.js"; import lostAndFoundListResource from "./resources/lostAndFound/lostAndFoundListResource.js"; import studentListResource from "./resources/student/studentListResource.js"; import facultyListResource from "./resources/faculty/facultyListResource.js"; +import timetableListResource from "./resources/timetable/timetableListResource.js"; +import timetableResource from "./resources/timetable/timetableResource.js"; const PORT = `${process.env.PORT || 3000}`; const app = express(); @@ -33,6 +35,9 @@ app.use("/student", studentResource); app.use("/students", studentListResource); app.use("/faculty", facultyResource); app.use("/faculties", facultyListResource); +app.use("/timetable", timetableResource); +app.use("/timetables", timetableListResource); + app.use("/admin-auth", adminAuthResource); app.use("/general-auth", generalAuthResource); app.use("/otp", otpResource); From 0b60eeeae89208cbe422f0a9e95eca3c0f1fcdf9 Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 15:29:53 +0530 Subject: [PATCH 29/30] Post merge cleanup --- .../lib/components/material_textformfield.dart | 2 +- frontend/lib/provider/home_provider.dart | 18 ++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/frontend/lib/components/material_textformfield.dart b/frontend/lib/components/material_textformfield.dart index 7ea6e7b..dec7de6 100644 --- a/frontend/lib/components/material_textformfield.dart +++ b/frontend/lib/components/material_textformfield.dart @@ -14,7 +14,7 @@ class MaterialTextFormField extends StatelessWidget { this.enabled, this.controllerLessValue, this.textAlign, - this.inputFormatters}); + this.inputFormatters, this.onTap}); final TextEditingController? controller; diff --git a/frontend/lib/provider/home_provider.dart b/frontend/lib/provider/home_provider.dart index 70d2027..cce4962 100644 --- a/frontend/lib/provider/home_provider.dart +++ b/frontend/lib/provider/home_provider.dart @@ -7,8 +7,7 @@ import '../components/menu_tile.dart'; import '../models/student.dart'; import '../models/faculty.dart'; -final homeProvider = - StateNotifierProvider((ref) => UserProvider(ref)); +final homeProvider = StateNotifierProvider((ref) => UserProvider(ref)); class HomeState { final bool toggleSearch; @@ -44,6 +43,7 @@ class UserProvider extends StateNotifier { menuTiles: [], ), ); + get searchController => state.searchController; get toggleSearch => state.toggleSearch; @@ -87,10 +87,7 @@ class UserProvider extends StateNotifier { ), MenuTile( title: 'Broadcast', - onTap: () { - // Navigate to the broadcast page - context.push('/user_home/broadcast'); - }, + onTap: () => context.push('/user_home/broadcast'), icon: Icons.announcement, primaryColor: Colors.greenAccent.shade100, secondaryColor: Colors.greenAccent.shade200, @@ -98,17 +95,14 @@ class UserProvider extends StateNotifier { MenuTile( title: "Chat\nRoom", onTap: () => context.push('/user_home/chat_room'), - primaryColor: Colors.blueAccent.shade100, - secondaryColor: Colors.blueAccent.shade200, + primaryColor: Colors.redAccent.shade100, + secondaryColor: Colors.redAccent.shade200, icon: Icons.search, ), ]; String query = state.searchController.text; state = state.copyWith( - menuTiles: menuTiles - .where((element) => - element.title.toLowerCase().contains(query.toLowerCase())) - .toList()); + menuTiles: menuTiles.where((element) => element.title.toLowerCase().contains(query.toLowerCase())).toList()); } void toggleSearchBar() { From 73d883f4db416701e58a4a26269723621e686f1f Mon Sep 17 00:00:00 2001 From: nailsonseat Date: Fri, 16 Feb 2024 15:37:51 +0530 Subject: [PATCH 30/30] Removed deprecated import --- frontend/lib/components/timetable_button.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontend/lib/components/timetable_button.dart b/frontend/lib/components/timetable_button.dart index 93a935f..bf4f2bb 100644 --- a/frontend/lib/components/timetable_button.dart +++ b/frontend/lib/components/timetable_button.dart @@ -14,12 +14,10 @@ class TimetableButton extends StatelessWidget { child: OutlinedButton( onPressed: onPressed, style: OutlinedButton.styleFrom( - primary: Colors.black, backgroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5), ), - // padding: const EdgeInsets.all(0), side: const BorderSide(color: Colors.black, width: 1), ), child: child,