diff --git a/README.md b/README.md
index d2dc923..64ccc2a 100644
--- a/README.md
+++ b/README.md
@@ -1,25 +1,56 @@
Hello,
I'm Md Shirajul Islam
+ width="45" /> My Name is Septian
## About The Project
-LC LMS is a cutting-edge online learning management system built with Flutter, offering a seamless and engaging educational experience. This mobile app empowers users with a user-friendly interface, interactive content delivery, and robust features for efficient learning. Whether you're a student or an instructor, LC LMS provides a dynamic platform for accessing courses, submitting assignments, and fostering collaboration. Experience the future of online education with LC LMS – where innovation meets education, all in the palm of your hand.
+This is a fork of [interactive_cares_lms](https://github.com/programmingwormhole/interactive_cares_lms), a Flutter-based Learning Management System (LMS).
+I extended it by adding role-based authentication and dashboards for different user types:
-
-## Demo Access
-[![Download][Download]][Download-url]
-
-
-### Built With
-
-LC LMS, crafted with the power of Dart and Flutter, redefines online learning. This dynamic app seamlessly blends innovation and education, providing a sleek, responsive, and user-friendly experience. Whether you're a student or instructor, dive into a world of interactive courses, streamlined assignments, and collaborative tools. LC LMS is the epitome of modern education, built for the future with Dart and Flutter's cutting-edge technology.
+* **Admin** 👨💻 – Manage courses, users, and system settings.
+* **Lecturer** 👩🏫 – Create and manage lessons.
+* **Student** 🎓 – Enroll in courses and track progress.
-[![Flutter][Flutter]][Flutter-url]
-[![Dart][Dart]][Dart-url]
+---
+
+## 🚀 Features
+### 🔑 Authentication
+* Login & Register with API integration
+* Role-based redirection (Admin, Lecturer, Student)
+
+### 📚 Course Management
+* Featured courses, lessons, and modules
+* Track lesson completion progress
+
+### 📌 Bookmarking
+* Save & manage bookmarked lessons locally
+
+### 🎨 UI
+* Flutter + GetX state management
+* Material Design widgets
+
+---
+## Project Structure
+```bash
+lib/
+├── bindings/ # GetX dependency bindings
+├── controllers/ # App controllers (auth, course, lesson, bookmark)
+├── core/services/ # API services (auth, shared services)
+├── global_widgets/ # Reusable UI components
+├── helpers/ # Helpers (requests, forms, alerts)
+├── models/ # Data models (user, course, category)
+├── routes/ # Route names & destinations
+├── utils/ # Config, constants, colors, assets
+├── views/ # Screens (Authentication, Home, Learning, etc.)
+│ ├── Admin/ # NEW: Admin dashboard
+│ ├── Lecturer/ # NEW: Lecturer dashboard
+│ └── Student/ # NEW: Student dashboard
+└── main.dart # App entry point with role-based redirection
+```
+---
## Getting Started
@@ -37,55 +68,33 @@ Follow the below steps to run the application on your device.
1. Clone the repo
```sh
- git clone https://github.com/programmingwormhole/interactive_cares_lms.git
- ```
-2. Open Project In IDE
- ```sh
- Android Studio, VS Code, or any other Flutter Supported IDE
+ git clone https://github.com//interactive_cares_lms.git
+ cd interactive_cares_lms
+
```
-3. Get Dependencies
+2. Get Dependencies
```js
flutter pub get
```
-4. Run
+3. Run
```js
flutter run
```
-## Key Features
-- [x] Authentication using RestAPI.
-- [x] Keep logged-in user by storing bearer token.
-- [x] Home Screen UI
-- [x] Bookmark screen with functionality
-- [x] Play a lesson from the bookmark to a specific time in the video.
-- [x] Enrolled Course Screen UI with functionality.
-- [x] Real-time course complete progress.
-- [x] Course modules
-- [x] Course lesson
-- [x] Previous or Next lesson system from the lesson screen
-- [x] Mark as complete a lesson
-- [x] After completing all lessons in a course students will get an animated dialogue to claim a certificate.
+## Role Based Authentication
+- On login, users are redirected to different dashboards based on their role.
+- For now, roles are stored in a local mock JSON (assets/json/fake_auth.json) for testing.
+- Future updates will connect to a backend API with real role-based authentication.
-## Packages
-- [x] GetX (For State management)
-- [x] http (For API request)
-- [x] flutter_svg (To display SVG icon in the app)
-- [x] lottie (To display animation in the app)
-- [x] shared_preferences (To store data in local storage)
-- [x] google_fonts (To use custom fonts)
-- [x] carousel_slider (For creating an image slider)
-- [x] page_view_dot_indicator (To show a slider dot indicator)
-- [x] flutter_staggered_grid_view (To make a user-friendly grid view)
-- [x] video_player & chewie (To play video from network or assets)
-
-
-
-
-[Flutter]: https://camo.githubusercontent.com/b6d2d66adc138025ea9cdf8444cdc29a588c98d062c263f8651ba6b7ad46fef0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f466c75747465722d2532333032353639422e7376673f7374796c653d666f722d7468652d6261646765266c6f676f3d466c7574746572266c6f676f436f6c6f723d7768697465
-[Flutter-url]: https://flutter.dev
-[Dart]: https://camo.githubusercontent.com/a0a1ad90011aa02e7e6f32be4998b8843f0884eed20b575c8a2189859550824d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f646172742d2532333031373543322e7376673f7374796c653d666f722d7468652d6261646765266c6f676f3d64617274266c6f676f436f6c6f723d7768697465
-[Dart-url]: https://dart.dev
-[Download]: https://camo.envatousercontent.com/66cff805c4d35c74668291a51e21f978424565d9/68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f70726f6772616d6d696e67776f726d686f6c652f656e7661746f2f6d61696e2f64656d6f2e676966
-[Download-url]: https://raw.githubusercontent.com/programmingwormhole/interactive_cares_lms/main/lc_lms_demo.apk
+## Roadmap
+- [x]Connect role management to backend API
+- [x]Add course creation for lecturers
+- [x]Add course/user management for admins
+- [x]Enhance student dashboard with certificates & progress tracking
+
+---
+## Credit
+* Original Project [Interactive Cares LMS](https://github.com/programmingwormhole/interactive_cares_lms)
+* Extended by [Septian Jauhariansyah](https://github.com/alchemista27)
\ No newline at end of file
diff --git a/assets/mock/fake_auth.json b/assets/mock/fake_auth.json
new file mode 100644
index 0000000..95f0dbd
--- /dev/null
+++ b/assets/mock/fake_auth.json
@@ -0,0 +1,5 @@
+{
+ "username": "john_doe",
+ "role": "student",
+ "token": "abc123xyz"
+}
diff --git a/lib/controllers/auth_controller.dart b/lib/controllers/auth_controller.dart
new file mode 100644
index 0000000..b8f750d
--- /dev/null
+++ b/lib/controllers/auth_controller.dart
@@ -0,0 +1,40 @@
+import 'dart:convert';
+import 'package:get/get.dart';
+import 'package:interactive_cares_lms/models/user_model.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+
+class AuthController extends GetxController {
+ var currentUser = Rxn();
+
+ Future login(String username, String password) async {
+ // Fake API call (replace with real HTTP later)
+ final fakeApiResponse = '''
+ {
+ "username": "$username",
+ "role": "${username == 'admin' ? 'admin' : username == 'lecturer' ? 'lecturer' : 'student'}",
+ "token": "mockToken123"
+ }
+ ''';
+
+ final data = json.decode(fakeApiResponse);
+ currentUser.value = UserModel.fromJson(data);
+
+ // Save user data
+ SharedPreferences prefs = await SharedPreferences.getInstance();
+ prefs.setString('user', json.encode(data));
+ }
+
+ Future loadUser() async {
+ SharedPreferences prefs = await SharedPreferences.getInstance();
+ if (prefs.containsKey('user')) {
+ final data = json.decode(prefs.getString('user')!);
+ currentUser.value = UserModel.fromJson(data);
+ }
+ }
+
+ Future logout() async {
+ SharedPreferences prefs = await SharedPreferences.getInstance();
+ prefs.remove('user');
+ currentUser.value = null;
+ }
+}
diff --git a/lib/helpers/request_helpers.dart b/lib/helpers/request_helpers.dart
index 870a5e2..903c0bf 100644
--- a/lib/helpers/request_helpers.dart
+++ b/lib/helpers/request_helpers.dart
@@ -1,9 +1,9 @@
class RequestHelpers {
- static Map header () {
+ static Map header() {
Map header = {
- 'Accept' : 'application/json',
+ 'Accept': 'application/json',
};
return header;
}
-}
\ No newline at end of file
+}
diff --git a/lib/main.dart b/lib/main.dart
index fb78fb8..c8f48cc 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,13 +1,21 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
+import 'package:interactive_cares_lms/controllers/auth_controller.dart';
import 'package:interactive_cares_lms/bindings/all_bindings.dart';
import 'package:interactive_cares_lms/routes/route_destinations.dart';
import 'package:interactive_cares_lms/routes/route_names.dart';
import 'package:interactive_cares_lms/utils/colors.dart';
import 'package:interactive_cares_lms/utils/config.dart';
+import 'package:interactive_cares_lms/views/Admin/admin_dashboard.dart';
+import 'package:interactive_cares_lms/views/Lecturer/lecturer_dashboard.dart';
+import 'package:interactive_cares_lms/views/Student/student_dashboard.dart';
+import 'package:interactive_cares_lms/views/Authentication/LoginScreen/login_screen.dart';
-void main() {
+
+void main() async {
WidgetsFlutterBinding.ensureInitialized();
+ final authController = Get.put(AuthController());
+ await authController.loadUser(); // ✅ allowed now
AllBindings().dependencies();
runApp(const MyApp());
}
@@ -18,15 +26,18 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
- debugShowCheckedModeBanner: false,
- title: AppConfig.appName,
- theme: ThemeData(
- colorScheme: ColorScheme.fromSeed(seedColor: AppColors.primary),
- useMaterial3: true,
- scaffoldBackgroundColor: AppColors.background,
- ),
- getPages: Routes.destination,
- initialRoute: RouteNames.initial,
- );
- }
-}
+ initialBinding: AllBindings(),
+ home: Obx(() {
+ final user = Get.find().currentUser.value;
+ if (user == null) {
+ return LoginPage();
+ } else if (user.role == 'admin') {
+ return AdminDashboard();
+ } else if (user.role == 'lecturer') {
+ return LecturerDashboard();
+ } else {
+ return StudentDashboard();
+ }
+ }),
+);
+
diff --git a/lib/models/category_model.dart b/lib/models/category_model.dart
index a51ba9b..5cf263e 100644
--- a/lib/models/category_model.dart
+++ b/lib/models/category_model.dart
@@ -4,7 +4,7 @@ class CategoryModel {
String title;
String icon;
- CategoryModel ({required this.title, required this.icon});
+ CategoryModel({required this.title, required this.icon});
}
List getCategories = [
@@ -13,4 +13,4 @@ List getCategories = [
CategoryModel(title: 'Editing', icon: ImageManager.video),
CategoryModel(title: 'Development', icon: ImageManager.personalDevelopment),
CategoryModel(title: 'Math', icon: ImageManager.math),
-];
\ No newline at end of file
+];
diff --git a/lib/models/user_model.dart b/lib/models/user_model.dart
index 24e154d..a79f2ae 100644
--- a/lib/models/user_model.dart
+++ b/lib/models/user_model.dart
@@ -3,20 +3,32 @@ class UserModel {
String? fullName;
String? email;
String? password;
+ String? role; //
UserModel({
this.username,
this.email,
this.password,
this.fullName,
+ this.role,
});
Map toJson() {
return {
- 'full_name' : fullName,
+ 'full_name': fullName,
'username': username,
'email': email,
'password': password,
+ 'role': role,
};
}
+
+ factory UserModel.fromJson(Map json) {
+ return UserModel(
+ username: json['username'],
+ fullName: json['full_name'],
+ email: json['email'],
+ role: json['role'],
+ );
+ }
}
diff --git a/lib/routes/route_destinations.dart b/lib/routes/route_destinations.dart
index 03b54c1..b5e6cfd 100644
--- a/lib/routes/route_destinations.dart
+++ b/lib/routes/route_destinations.dart
@@ -19,6 +19,8 @@ class Routes {
GetPage(name: RouteNames.home, page: () => const BottomBarView()),
GetPage(name: RouteNames.courseLearn, page: () => const LearningScreen()),
GetPage(name: RouteNames.lesson, page: () => const LessonScreen()),
- GetPage(name: RouteNames.bookmarkPlayer, page: () => const BookmarkPlayerScreen()),
+ GetPage(
+ name: RouteNames.bookmarkPlayer,
+ page: () => const BookmarkPlayerScreen()),
];
-}
\ No newline at end of file
+}
diff --git a/lib/routes/route_names.dart b/lib/routes/route_names.dart
index 764028d..adfbed1 100644
--- a/lib/routes/route_names.dart
+++ b/lib/routes/route_names.dart
@@ -8,4 +8,4 @@ class RouteNames {
static const String courseLearn = '/courseLearn';
static const String lesson = '/lesson';
static const String bookmarkPlayer = '/bookmark-player';
-}
\ No newline at end of file
+}
diff --git a/lib/utils/app_urls.dart b/lib/utils/app_urls.dart
index bfe6b95..bbaf20d 100644
--- a/lib/utils/app_urls.dart
+++ b/lib/utils/app_urls.dart
@@ -5,4 +5,4 @@ class AppUrls {
static const String apiUrl = '${AppConfig.baseUrl}/api/$apiVersion';
static Uri login = Uri.parse('$apiUrl/login');
static Uri register = Uri.parse('$apiUrl/register');
-}
\ No newline at end of file
+}
diff --git a/lib/views/Admin/admin_dashboard.dart b/lib/views/Admin/admin_dashboard.dart
new file mode 100644
index 0000000..48fee57
--- /dev/null
+++ b/lib/views/Admin/admin_dashboard.dart
@@ -0,0 +1,13 @@
+import 'package:flutter/material.dart';
+
+class AdminDashboard extends StatelessWidget {
+ const AdminDashboard({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(title: const Text("Admin Dashboard")),
+ body: const Center(child: Text("Welcome Admin")),
+ );
+ }
+}
diff --git a/lib/views/HomeScreen/home_screen.dart b/lib/views/HomeScreen/home_screen.dart
index 6b9c4fd..7b21da1 100644
--- a/lib/views/HomeScreen/home_screen.dart
+++ b/lib/views/HomeScreen/home_screen.dart
@@ -32,8 +32,8 @@ class HomeScreen extends StatelessWidget {
children: [
HomeAppBar(),
Padding(
- padding: EdgeInsets.symmetric(
- horizontal: 10, vertical: 15),
+ padding:
+ EdgeInsets.symmetric(horizontal: 10, vertical: 15),
child: Column(
children: [
SliderSection(),
diff --git a/lib/views/Lecturer/lecturer_dashboard.dart b/lib/views/Lecturer/lecturer_dashboard.dart
new file mode 100644
index 0000000..eabff83
--- /dev/null
+++ b/lib/views/Lecturer/lecturer_dashboard.dart
@@ -0,0 +1,13 @@
+import 'package:flutter/material.dart';
+
+class LecturerDashboard extends StatelessWidget {
+ const LecturerDashboard({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(title: const Text("Lecturer Dashboard")),
+ body: const Center(child: Text("Welcome Lecturer")),
+ );
+ }
+}
diff --git a/lib/views/Student/student_dashboard.dart b/lib/views/Student/student_dashboard.dart
new file mode 100644
index 0000000..ac07463
--- /dev/null
+++ b/lib/views/Student/student_dashboard.dart
@@ -0,0 +1,13 @@
+import 'package:flutter/material.dart';
+
+class StudentDashboard extends StatelessWidget {
+ const StudentDashboard({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(title: const Text("Student Dashboard")),
+ body: const Center(child: Text("Welcome Student")),
+ );
+ }
+}
diff --git a/pubspec.lock b/pubspec.lock
index e3261f8..d47932b 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -45,10 +45,10 @@ packages:
dependency: transitive
description:
name: characters
- sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
+ sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
url: "https://pub.dev"
source: hosted
- version: "1.3.0"
+ version: "1.4.0"
chewie:
dependency: "direct main"
description:
@@ -61,18 +61,18 @@ packages:
dependency: transitive
description:
name: clock
- sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
+ sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
url: "https://pub.dev"
source: hosted
- version: "1.1.1"
+ version: "1.1.2"
collection:
dependency: transitive
description:
name: collection
- sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
+ sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.dev"
source: hosted
- version: "1.17.1"
+ version: "1.19.1"
convert:
dependency: transitive
description:
@@ -117,10 +117,10 @@ packages:
dependency: transitive
description:
name: fake_async
- sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
+ sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
url: "https://pub.dev"
source: hosted
- version: "1.3.1"
+ version: "1.3.3"
ffi:
dependency: transitive
description:
@@ -224,6 +224,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.6.7"
+ leak_tracker:
+ dependency: transitive
+ description:
+ name: leak_tracker
+ sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
+ url: "https://pub.dev"
+ source: hosted
+ version: "11.0.2"
+ leak_tracker_flutter_testing:
+ dependency: transitive
+ description:
+ name: leak_tracker_flutter_testing
+ sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.10"
+ leak_tracker_testing:
+ dependency: transitive
+ description:
+ name: leak_tracker_testing
+ sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.2"
lints:
dependency: transitive
description:
@@ -244,26 +268,26 @@ packages:
dependency: transitive
description:
name: matcher
- sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
+ sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
url: "https://pub.dev"
source: hosted
- version: "0.12.15"
+ version: "0.12.17"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
- sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
+ sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev"
source: hosted
- version: "0.2.0"
+ version: "0.11.1"
meta:
dependency: transitive
description:
name: meta
- sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
+ sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
url: "https://pub.dev"
source: hosted
- version: "1.9.1"
+ version: "1.16.0"
nested:
dependency: transitive
description:
@@ -300,10 +324,10 @@ packages:
dependency: transitive
description:
name: path
- sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
+ sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.dev"
source: hosted
- version: "1.8.3"
+ version: "1.9.1"
path_parsing:
dependency: transitive
description:
@@ -460,7 +484,7 @@ packages:
dependency: transitive
description: flutter
source: sdk
- version: "0.0.99"
+ version: "0.0.0"
source_span:
dependency: transitive
description:
@@ -473,18 +497,18 @@ packages:
dependency: transitive
description:
name: stack_trace
- sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
+ sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
url: "https://pub.dev"
source: hosted
- version: "1.11.0"
+ version: "1.12.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
- sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
+ sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
url: "https://pub.dev"
source: hosted
- version: "2.1.1"
+ version: "2.1.4"
string_scanner:
dependency: transitive
description:
@@ -505,10 +529,10 @@ packages:
dependency: transitive
description:
name: test_api
- sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
+ sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
url: "https://pub.dev"
source: hosted
- version: "0.5.1"
+ version: "0.7.6"
typed_data:
dependency: transitive
description:
@@ -545,10 +569,10 @@ packages:
dependency: transitive
description:
name: vector_math
- sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
+ sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.dev"
source: hosted
- version: "2.1.4"
+ version: "2.2.0"
video_player:
dependency: "direct main"
description:
@@ -589,6 +613,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.17"
+ vm_service:
+ dependency: transitive
+ description:
+ name: vm_service
+ sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60"
+ url: "https://pub.dev"
+ source: hosted
+ version: "15.0.2"
wakelock_plus:
dependency: transitive
description:
@@ -630,5 +662,5 @@ packages:
source: hosted
version: "6.3.0"
sdks:
- dart: ">=3.0.6 <4.0.0"
- flutter: ">=3.10.0"
+ dart: ">=3.8.0-0 <4.0.0"
+ flutter: ">=3.18.0-18.0.pre.54"
diff --git a/pubspec.yaml b/pubspec.yaml
index 60dd123..1ee25b1 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -35,6 +35,7 @@ flutter:
uses-material-design: true
assets:
+ - assets/mock/
- assets/
- assets/images/
- assets/svg/