commit 7a3db5d6711f9ee8781c1b8fbb25d96982d43278 Author: Agboola Onasanya Date: Mon Oct 28 18:52:54 2024 +0000 Migrate from BitBucket diff --git a/README.md b/README.md new file mode 100644 index 0000000..d2077c7 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# school_management_system + +School Management System + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..0d29021 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,28 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/assets/icons/School_Picture.png b/assets/icons/School_Picture.png new file mode 100644 index 0000000..7216b91 Binary files /dev/null and b/assets/icons/School_Picture.png differ diff --git a/assets/icons/login.svg b/assets/icons/login.svg new file mode 100644 index 0000000..7d06d1c --- /dev/null +++ b/assets/icons/login.svg @@ -0,0 +1,152 @@ + + + + Group 261 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/icons/school.svg b/assets/icons/school.svg new file mode 100644 index 0000000..feb9353 --- /dev/null +++ b/assets/icons/school.svg @@ -0,0 +1,2067 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/school_home.svg b/assets/icons/school_home.svg new file mode 100644 index 0000000..c612e8c --- /dev/null +++ b/assets/icons/school_home.svg @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/image1.jpg b/assets/images/image1.jpg new file mode 100644 index 0000000..bd1dd7c Binary files /dev/null and b/assets/images/image1.jpg differ diff --git a/assets/images/image2.jpg b/assets/images/image2.jpg new file mode 100644 index 0000000..8cfc6b9 Binary files /dev/null and b/assets/images/image2.jpg differ diff --git a/assets/images/image3.jpg b/assets/images/image3.jpg new file mode 100644 index 0000000..968673e Binary files /dev/null and b/assets/images/image3.jpg differ diff --git a/assets/images/image4.jpg b/assets/images/image4.jpg new file mode 100644 index 0000000..ebdea97 Binary files /dev/null and b/assets/images/image4.jpg differ diff --git a/assets/images/image5.jpg b/assets/images/image5.jpg new file mode 100644 index 0000000..e91fbcc Binary files /dev/null and b/assets/images/image5.jpg differ diff --git a/assets/images/image6.jpg b/assets/images/image6.jpg new file mode 100644 index 0000000..9ec6421 Binary files /dev/null and b/assets/images/image6.jpg differ diff --git a/assets/images/image7.jpg b/assets/images/image7.jpg new file mode 100644 index 0000000..45c80ce Binary files /dev/null and b/assets/images/image7.jpg differ diff --git a/assets/images/image8.jpg b/assets/images/image8.jpg new file mode 100644 index 0000000..b117222 Binary files /dev/null and b/assets/images/image8.jpg differ diff --git a/assets/images/passport.jpg b/assets/images/passport.jpg new file mode 100644 index 0000000..d1a288c Binary files /dev/null and b/assets/images/passport.jpg differ diff --git a/assets/images/unilogo.png b/assets/images/unilogo.png new file mode 100644 index 0000000..269666e Binary files /dev/null and b/assets/images/unilogo.png differ diff --git a/fonts/Poppins-Bold.ttf b/fonts/Poppins-Bold.ttf new file mode 100644 index 0000000..b94d47f Binary files /dev/null and b/fonts/Poppins-Bold.ttf differ diff --git a/fonts/Poppins-Medium.ttf b/fonts/Poppins-Medium.ttf new file mode 100644 index 0000000..e90e87e Binary files /dev/null and b/fonts/Poppins-Medium.ttf differ diff --git a/fonts/Poppins-Regular.ttf b/fonts/Poppins-Regular.ttf new file mode 100644 index 0000000..be06e7f Binary files /dev/null and b/fonts/Poppins-Regular.ttf differ diff --git a/fonts/Poppins-SemiBold.ttf b/fonts/Poppins-SemiBold.ttf new file mode 100644 index 0000000..dabf7c2 Binary files /dev/null and b/fonts/Poppins-SemiBold.ttf differ diff --git a/lib/api/auth_requests.dart b/lib/api/auth_requests.dart new file mode 100644 index 0000000..8e3c6b9 --- /dev/null +++ b/lib/api/auth_requests.dart @@ -0,0 +1,92 @@ +import 'dart:io'; +import 'dart:convert'; +import 'package:http/http.dart'; +import 'package:school_management_system/components/default_values.dart'; + +Authorise authoriseFromJson(String str) => Authorise.fromJson(json.decode(str)); +String authoriseToJson(Authorise data) => json.encode(data.toJson()); + +class Authorise { + DateTime? validUntil; + String? token; + String? status; + String? message; + + Authorise({ + this.validUntil, + this.token, + this.status, + this.message, + }); + + factory Authorise.fromJson(Map json) => Authorise( + validUntil: DateTime.parse(json["validUntil"]), + token: json["token"], + status: json["status"], + message: json["message"], + ); + + Map toJson() => { + "validUntil": validUntil!.toIso8601String(), + "token": token, + "status": status, + "message": message, + }; +} + +Future login(String username, String password) async { + try { + print("$baseUrl/auth/generateToken"); + final response = await client + .post( + Uri.parse("$baseUrl/auth/generateToken"), + headers: { + "Content-Type": "application/json", + }, + body: json.encode({ + 'username': username, + 'password': password, + }), + ) + .timeout( + const Duration(seconds: timeout), + onTimeout: () { + return Response('', 400); + }, + ); + + if (response.statusCode == 200) { + var status = authoriseFromJson(response.body) + .status!; //Authorise.fromJson(json.decode(response.body)).status!; + loginId = username; + if (status.isEmpty || status.contains('failed')) { + return authoriseFromJson(response.body).message!; + } else { + setSharedPref('authkey', authoriseFromJson(response.body).token!); + setSharedPref('tokenValidity', + authoriseFromJson(response.body).validUntil.toString()); + setSharedPref('isLogin', true); + + header = { + "Authorization": "Bearer ${authoriseFromJson(response.body).token!}", + "Content-Type": "application/json", + }; + + return "Successfully Logged In"; + } + } else if (response.statusCode == 400) { + return "Cannot Reach Server"; + } else if (response.statusCode == 404) { + print(response.body); + return "Not Found"; + } else { + return "failed"; + } + } on SocketException { + return "Can not reach server"; + } on HttpException { + return "Couldnt find the post"; + } on FormatException { + return "Bad response format"; + } +} diff --git a/lib/api/calender_requests.dart b/lib/api/calender_requests.dart new file mode 100644 index 0000000..66c7ea0 --- /dev/null +++ b/lib/api/calender_requests.dart @@ -0,0 +1,157 @@ +import 'dart:io'; +import 'package:school_management_system/components/default_values.dart'; + +// To parse this JSON data, do +// +// final calendar = calendarFromJson(jsonString); + +import 'dart:convert'; + +Calendar calendarFromJson(String str) => Calendar.fromJson(json.decode(str)); + +String calendarToJson(Calendar data) => json.encode(data.toJson()); + +class Calendar { + final String? calenderid; + final String? session; + final String? semester; + final List? calenderrdetails; + + Calendar({ + this.calenderid, + this.session, + this.semester, + this.calenderrdetails, + }); + + factory Calendar.fromJson(Map json) => Calendar( + calenderid: json["calenderid"], + session: json["session"], + semester: json["semester"], + calenderrdetails: json["calenderrdetails"] == null + ? [] + : List.from(json["calenderrdetails"]! + .map((x) => Calenderrdetail.fromJson(x))), + ); + + Map toJson() => { + "calenderid": calenderid, + "session": session, + "semester": semester, + "calenderrdetails": calenderrdetails == null + ? [] + : List.from(calenderrdetails!.map((x) => x.toJson())), + }; +} + +class Calenderrdetail { + final String? note; + final String? event; + final bool? allday; + final DateTime? startdate; + final DateTime? enddate; + final String? endtime; + final String? starttime; + final String? frequency; + final String? interval; + final String? dayofweek; + + Calenderrdetail({ + this.note, + this.event, + this.allday, + this.startdate, + this.enddate, + this.endtime, + this.starttime, + this.frequency, + this.interval, + this.dayofweek, + }); + + factory Calenderrdetail.fromJson(Map json) => + Calenderrdetail( + note: json["note"], + event: json["event"], + allday: json["allday"], + startdate: json["startdate"] == null + ? null + : DateTime.parse(json["startdate"]), + enddate: + json["enddate"] == null ? null : DateTime.parse(json["enddate"]), + endtime: json["endtime"], + starttime: json["starttime"], + frequency: json["frequency"], + interval: json["interval"], + dayofweek: json["dayofweek"], + ); + + Map toJson() => { + "note": note, + "event": event, + "allday": allday, + "startdate": + "${startdate!.year.toString().padLeft(4, '0')}-${startdate!.month.toString().padLeft(2, '0')}-${startdate!.day.toString().padLeft(2, '0')}", + "enddate": + "${enddate!.year.toString().padLeft(4, '0')}-${enddate!.month.toString().padLeft(2, '0')}-${enddate!.day.toString().padLeft(2, '0')}", + "endtime": endtime, + "starttime": starttime, + "frequency": frequency, + "interval": interval, + "dayofweek": dayofweek, + }; +} + +Future getStudentCalender( + String calenderid, String session, String semester) async { + try { + final response = await client + .get( + Uri.parse( + "$baseUrl/calender/getCalender/$calenderid?session=$session&semester=$semester"), + headers: header, + ) + .timeout( + const Duration(seconds: timeout), + ); + + if (response.statusCode == 200) { + return calendarFromJson(response.body); + } else { + return calendarFromJson(""); + } + } on SocketException { + return throw Exception(); + } on HttpException { + return throw Exception(); + } on FormatException { + return throw Exception(); + } +} + +Future getSchoolCalender( + String calenderid, String session, String semester) async { + try { + final response = await client + .get( + Uri.parse( + "$baseUrl/calender/getCalender/$calenderid?session=$session&semester=$semester"), + headers: header, + ) + .timeout( + const Duration(seconds: timeout), + ); + + if (response.statusCode == 200) { + return calendarFromJson(response.body); + } else { + return calendarFromJson(response.body); + } + } on SocketException { + return throw Exception(); + } on HttpException { + return throw Exception(); + } on FormatException { + return throw Exception(); + } +} diff --git a/lib/api/module_requests.dart b/lib/api/module_requests.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/api/results_requests.dart b/lib/api/results_requests.dart new file mode 100644 index 0000000..711beee --- /dev/null +++ b/lib/api/results_requests.dart @@ -0,0 +1,167 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:school_management_system/components/default_values.dart'; + +// To parse this JSON data, do +// +// final result = resultFromJson(jsonString); + +Result resultFromJson(String str) => Result.fromJson(json.decode(str)); + +String resultToJson(Result data) => json.encode(data.toJson()); + +class Result { + final String? studentid; + final String? session; + final String? comments; + final bool? resit; + final String? semester; + final List? scores; + + Result({ + this.studentid, + this.session, + this.comments, + this.resit, + this.semester, + this.scores, + }); + + factory Result.fromJson(Map json) => Result( + studentid: json["studentid"], + session: json["session"], + comments: json["comments"], + resit: json["resit"], + semester: json["semester"], + scores: json["scores"] == null + ? [] + : List.from(json["scores"]!.map((x) => Score.fromJson(x))), + ); + + Map toJson() => { + "studentid": studentid, + "session": session, + "comments": comments, + "resit": resit, + "semester": semester, + "scores": scores == null + ? [] + : List.from(scores!.map((x) => x.toJson())), + }; +} + +class Score { + final String? module; + final double? score; + + Score({ + this.module, + this.score, + }); + + factory Score.fromJson(Map json) => Score( + module: json["module"], + score: json["score"], + ); + + Map toJson() => { + "module": module, + "score": score, + }; +} + +Map> sessionFromJson(String str) => + Map.from(json.decode(str)).map((k, v) => + MapEntry>(k, List.from(v.map((x) => x)))); + +String sessionToJson(Map> data) => + json.encode(Map.from(data).map((k, v) => + MapEntry(k, List.from(v.map((x) => x))))); + +Future>> getStudentSemester(String session) async { + try { + final response = await client + .get( + Uri.parse("$baseUrl/results/getSemester/$loginId?session=$session"), + headers: header) + .timeout( + const Duration(seconds: timeout), + ); + + if (response.statusCode == 200) { + if (response.body.isNotEmpty) { + return sessionFromJson(response.body); + } else { + return sessionFromJson(""); + } + } else { + return sessionFromJson(""); + } + } on SocketException { + return throw Exception(); + } on HttpException { + return throw Exception(); + } on FormatException { + return throw Exception(); + } +} + +Future>> getStudentSession() async { + try { + final response = await client + .get( + Uri.parse("$baseUrl/results/getSession/$loginId"), + headers: header, + ) + .timeout( + const Duration(seconds: timeout), + ); + + if (response.statusCode == 200) { + if (response.body.isNotEmpty) { + return sessionFromJson(response.body); + } else { + return sessionFromJson(""); + } + } else { + return sessionFromJson(""); + } + } on SocketException { + return throw Exception(); + } on HttpException { + return throw Exception(); + } on FormatException { + return throw Exception(); + } +} + +Future getStudentResult(String session, String semester) async { + try { + final response = await client + .get( + Uri.parse( + "$baseUrl/results/list/$loginId?session=$session&semester=$semester"), + headers: header, + ) + .timeout( + const Duration(seconds: timeout), + ); + + if (response.statusCode == 200) { + if (response.body.isNotEmpty) { + return resultFromJson(response.body); + } else { + return resultFromJson(""); + } + } else { + return resultFromJson(""); + } + } on SocketException { + return throw Exception(); + } on HttpException { + return throw Exception(); + } on FormatException { + return throw Exception(); + } +} diff --git a/lib/api/session_requests.dart b/lib/api/session_requests.dart new file mode 100644 index 0000000..e5f92a5 --- /dev/null +++ b/lib/api/session_requests.dart @@ -0,0 +1,101 @@ +import 'dart:io'; +import 'package:school_management_system/components/default_values.dart'; + +// To parse this JSON data, do +// +// final session = sessionFromJson(jsonString); + +import 'dart:convert'; + +Session sessionFromJson(String str) => Session.fromJson(json.decode(str)); + +String sessionToJson(Session data) => json.encode(data.toJson()); + +class Session { + final String? session; + final String? semester; + final DateTime? startdate; + final DateTime? enddate; + final String? status; + + Session({ + this.session, + this.semester, + this.startdate, + this.enddate, + this.status, + }); + + factory Session.fromJson(Map json) => Session( + session: json["session"], + semester: json["semester"], + startdate: json["startdate"] == null + ? null + : DateTime.parse(json["startdate"]), + enddate: + json["enddate"] == null ? null : DateTime.parse(json["enddate"]), + status: json["status"], + ); + + Map toJson() => { + "session": session, + "semester": semester, + "startdate": + "${startdate!.year.toString().padLeft(4, '0')}-${startdate!.month.toString().padLeft(2, '0')}-${startdate!.day.toString().padLeft(2, '0')}", + "enddate": + "${enddate!.year.toString().padLeft(4, '0')}-${enddate!.month.toString().padLeft(2, '0')}-${enddate!.day.toString().padLeft(2, '0')}", + "status": status, + }; +} + +Future getCurrentSession() async { + try { + final response = await client + .get( + Uri.parse("$baseUrl/session/getCurrentSession"), + headers: header, + ) + .timeout( + const Duration(seconds: timeout), + ); + + if (response.statusCode == 200) { + session = sessionFromJson(response.body).session!; + semester = sessionFromJson(response.body).semester!; + //return sessionFromJson(response.body); + } else { + return sessionFromJson(""); + } + } on SocketException { + throw Exception(); + } on HttpException { + throw Exception(); + } on FormatException { + throw Exception(); + } +} + +// Future> getSession() async { +// try { +// final response = await client.get( +// Uri.parse("$baseUrl/session/getSessionsList"), +// headers: header, +// ); + +// if (response.statusCode == 200) { +// if (response.body.isNotEmpty) { +// return sessionFromJson(response.body); +// } else { +// return sessionFromJson(""); +// } +// } else { +// return sessionFromJson(""); +// } +// } on SocketException { +// return throw Exception(); +// } on HttpException { +// return throw Exception(); +// } on FormatException { +// return throw Exception(); +// } +// } diff --git a/lib/api/student_requests.dart b/lib/api/student_requests.dart new file mode 100644 index 0000000..2aaadf3 --- /dev/null +++ b/lib/api/student_requests.dart @@ -0,0 +1,311 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:school_management_system/components/default_values.dart'; + +// To parse this JSON data, do +// +// final student = studentFromJson(jsonString); + +Student studentFromJson(String str) => Student.fromJson(json.decode(str)); + +String studentToJson(Student data) => json.encode(data.toJson()); + +class Student { + final String? studentid; + final String? title; + final String? firstname; + final String? lastname; + final String? schoolemail; + final DateTime? dateofbirth; + final String? currentyear; + final String? currentsession; + final String? homeaddress; + final String? mobilenumber; + final String? emailaddress; + final List? nextofkindetails; + final List? guardiandetails; + final List? medicaldetails; + final List? coursedetails; + final String? gender; + final Map>? sessiondetails; + final Map>? moduledetails; + + Student({ + this.studentid, + this.title, + this.firstname, + this.lastname, + this.schoolemail, + this.dateofbirth, + this.currentyear, + this.currentsession, + this.homeaddress, + this.mobilenumber, + this.emailaddress, + this.nextofkindetails, + this.guardiandetails, + this.medicaldetails, + this.coursedetails, + this.gender, + this.sessiondetails, + this.moduledetails, + }); + + factory Student.fromJson(Map json) => Student( + studentid: json["studentid"], + title: json["title"], + firstname: json["firstname"], + lastname: json["lastname"], + schoolemail: json["schoolemail"], + dateofbirth: json["dateofbirth"] == null + ? null + : DateTime.parse(json["dateofbirth"]), + currentyear: json["currentyear"], + currentsession: json["currentsession"], + homeaddress: json["homeaddress"], + mobilenumber: json["mobilenumber"], + emailaddress: json["emailaddress"], + nextofkindetails: json["nextofkindetails"] == null + ? [] + : List.from(json["nextofkindetails"]! + .map((x) => Nextofkindetail.fromJson(x))), + guardiandetails: json["guardiandetails"] == null + ? [] + : List.from(json["guardiandetails"]! + .map((x) => Guardiandetail.fromJson(x))), + medicaldetails: json["medicaldetails"] == null + ? [] + : List.from( + json["medicaldetails"]!.map((x) => Medicaldetail.fromJson(x))), + coursedetails: json["coursedetails"] == null + ? [] + : List.from( + json["coursedetails"]!.map((x) => Coursedetail.fromJson(x))), + gender: json["gender"], + sessiondetails: Map.from(json["sessiondetails"]!).map((k, v) => + MapEntry>( + k, List.from(v.map((x) => x)))), + moduledetails: Map.from(json["moduledetails"]!).map((k, v) => MapEntry< + String, List>(k, + List.from(v.map((x) => ModuleDetail.fromJson(x))))), + ); + + Map toJson() => { + "studentid": studentid, + "title": title, + "firstname": firstname, + "lastname": lastname, + "schoolemail": schoolemail, + "dateofbirth": + "${dateofbirth!.year.toString().padLeft(4, '0')}-${dateofbirth!.month.toString().padLeft(2, '0')}-${dateofbirth!.day.toString().padLeft(2, '0')}", + "currentyear": currentyear, + "currentsession": currentsession, + "homeaddress": homeaddress, + "mobilenumber": mobilenumber, + "emailaddress": emailaddress, + "nextofkindetails": nextofkindetails == null + ? [] + : List.from(nextofkindetails!.map((x) => x.toJson())), + "guardiandetails": guardiandetails == null + ? [] + : List.from(guardiandetails!.map((x) => x.toJson())), + "medicaldetails": medicaldetails == null + ? [] + : List.from(medicaldetails!.map((x) => x.toJson())), + "coursedetails": coursedetails == null + ? [] + : List.from(coursedetails!.map((x) => x.toJson())), + "gender": gender, + "sessiondetails": Map.from(sessiondetails!).map((k, v) => + MapEntry(k, List.from(v.map((x) => x)))), + "moduledetails": Map.from(moduledetails!).map((k, v) => + MapEntry( + k, List.from(v.map((x) => x.toJson())))), + }; +} + +class Coursedetail { + final String? courseofstudy; + final String? coursetype; + final String? coursequalification; + final String? coursemode; + + Coursedetail({ + this.courseofstudy, + this.coursetype, + this.coursequalification, + this.coursemode, + }); + + factory Coursedetail.fromJson(Map json) => Coursedetail( + courseofstudy: json["courseofstudy"], + coursetype: json["coursetype"], + coursequalification: json["coursequalification"], + coursemode: json["coursemode"], + ); + + Map toJson() => { + "courseofstudy": courseofstudy, + "coursetype": coursetype, + "coursequalification": coursequalification, + "coursemode": coursemode, + }; +} + +class Guardiandetail { + final String? guardianname; + final String? guardiancontact; + final String? guardianaddress; + final String? guardianrelationship; + + Guardiandetail({ + this.guardianname, + this.guardiancontact, + this.guardianaddress, + this.guardianrelationship, + }); + + factory Guardiandetail.fromJson(Map json) => Guardiandetail( + guardianname: json["guardianname"], + guardiancontact: json["guardiancontact"], + guardianaddress: json["guardianaddress"], + guardianrelationship: json["guardianrelationship"], + ); + + Map toJson() => { + "guardianname": guardianname, + "guardiancontact": guardiancontact, + "guardianaddress": guardianaddress, + "guardianrelationship": guardianrelationship, + }; +} + +class Medicaldetail { + final String? weight; + final String? height; + final String? genotype; + final String? bloodgroup; + final String? medicalcondition; + final String? allergies; + final bool? dnr; + final String? emergencycontactname; + final String? emergencycontactnumber; + final String? emergencycontractrelationship; + + Medicaldetail({ + this.weight, + this.height, + this.genotype, + this.bloodgroup, + this.medicalcondition, + this.allergies, + this.dnr, + this.emergencycontactname, + this.emergencycontactnumber, + this.emergencycontractrelationship, + }); + + factory Medicaldetail.fromJson(Map json) => Medicaldetail( + weight: json["weight"], + height: json["height"], + genotype: json["genotype"], + bloodgroup: json["bloodgroup"], + medicalcondition: json["medicalcondition"], + allergies: json["allergies"], + dnr: json["dnr"], + emergencycontactname: json["emergencycontactname"], + emergencycontactnumber: json["emergencycontactnumber"], + emergencycontractrelationship: json["emergencycontractrelationship"], + ); + + Map toJson() => { + "weight": weight, + "height": height, + "genotype": genotype, + "bloodgroup": bloodgroup, + "medicalcondition": medicalcondition, + "allergies": allergies, + "dnr": dnr, + "emergencycontactname": emergencycontactname, + "emergencycontactnumber": emergencycontactnumber, + "emergencycontractrelationship": emergencycontractrelationship, + }; +} + +class ModuleDetail { + final String? modulecode; + final String? modulename; + + ModuleDetail({ + this.modulecode, + this.modulename, + }); + + factory ModuleDetail.fromJson(Map json) => ModuleDetail( + modulecode: json["modulecode"], + modulename: json["modulename"], + ); + + Map toJson() => { + "modulecode": modulecode, + "modulename": modulename, + }; +} + +class Nextofkindetail { + final String? nextofkinname; + final String? nextofkincontact; + final String? nextofkinaddress; + final String? nextofkinrelationship; + + Nextofkindetail({ + this.nextofkinname, + this.nextofkincontact, + this.nextofkinaddress, + this.nextofkinrelationship, + }); + + factory Nextofkindetail.fromJson(Map json) => + Nextofkindetail( + nextofkinname: json["nextofkinname"], + nextofkincontact: json["nextofkincontact"], + nextofkinaddress: json["nextofkinaddress"], + nextofkinrelationship: json["nextofkinrelationship"], + ); + + Map toJson() => { + "nextofkinname": nextofkinname, + "nextofkincontact": nextofkincontact, + "nextofkinaddress": nextofkinaddress, + "nextofkinrelationship": nextofkinrelationship, + }; +} + +Future getStudentDetail(String studentId) async { + try { + final response = await client + .get( + Uri.parse("$baseUrl/student/$studentId"), + headers: header, + ) + .timeout( + const Duration(seconds: timeout), + ); + + if (response.statusCode == 200) { + if (response.body.isNotEmpty) { + return studentFromJson(response.body); + } else { + return studentFromJson(""); + } + } else { + return studentFromJson(""); + } + } on SocketException { + return throw Exception(); + } on HttpException { + return throw Exception(); + } on FormatException { + return throw Exception(); + } +} diff --git a/lib/components/default_values.dart b/lib/components/default_values.dart new file mode 100644 index 0000000..291519a --- /dev/null +++ b/lib/components/default_values.dart @@ -0,0 +1,126 @@ +import 'dart:math'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; + + +// const String baseUrl = "http://localhost:8123/smsApi/v1"; +// const String baseUrl = "https://api.theonasanyas.com/smsApi/v1"; +const String baseUrl = "http://10.15.45.29:8123/smsApi/v1"; + +const primaryColor = Color.fromARGB(255, 152, 120, 57); +const primaryLightColor = Color.fromARGB(150, 238, 224, 173); +const double defaultPadding = 15.0; +const timeout = 3; +var client = http.Client(); + +late String session; +late String semester; +late String loginId; +late Map header; + +setSharedPref(String key, var value) async { + SharedPreferences sharedPreferences = await SharedPreferences.getInstance(); + + switch (value.runtimeType.toString()) { + case 'String': + sharedPreferences.setString(key, value); + break; + + case 'double': + sharedPreferences.setDouble(key, value); + break; + + case 'int': + sharedPreferences.setInt(key, value); + break; + + case 'bool': + sharedPreferences.setBool(key, value); + break; + } +} + +getSharedPref(var key, var type) async { + SharedPreferences sharedPreferences = await SharedPreferences.getInstance(); + + switch (type) { + case 'String': + return sharedPreferences.getString(key); + + case 'double': + return sharedPreferences.getDouble(key); + + case 'int': + return sharedPreferences.getInt(key); + + case 'bool': + return sharedPreferences.getBool(key); + } +} + +Future checkTokenValidity() async { + final value = await getSharedPref('tokenValidity', 'String'); + + print("tokenValidity --- $value"); + DateTime dateTime; + DateTime currentTime; + if (value == '') { + currentTime = DateTime.now(); + dateTime = DateTime.now(); + } else { + currentTime = DateTime.now(); + dateTime = DateTime.parse(value); + } + + if (dateTime.isAfter(currentTime)) { + return true; + } else { + return false; + } +} + +String getImage() { + // + // + + List image = [ + 'assets/images/image1.jpg', + 'assets/images/image2.jpg', + 'assets/images/image3.jpg', + 'assets/images/image4.jpg', + 'assets/images/image5.jpg', + 'assets/images/image6.jpg', + 'assets/images/image7.jpg', + 'assets/images/image8.jpg' + ]; + + var rnd = Random(); + final index = rnd.nextInt(image.length); + return image[index]; +} + +String studentGrade(double score) { + // + // + String grade = ""; + switch (score) { + case >= 70: + grade = "Distinction"; + break; + + case >= 60: + grade = "Merit"; + break; + + case >= 50: + grade = "Pass"; + break; + + default: + grade = "Fail"; + break; + } + + return grade; +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..835d479 --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:school_management_system/screens/welcome/welcome_screen.dart'; +import 'package:school_management_system/components/default_values.dart'; + +void main() => runApp(const MyApp()); + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + return MaterialApp( + debugShowCheckedModeBanner: false, + title: 'School Management System Demo', + theme: ThemeData( + primaryColor: primaryColor, + scaffoldBackgroundColor: Colors.white, + elevatedButtonTheme: ElevatedButtonThemeData( + style: ElevatedButton.styleFrom( + elevation: 0, + foregroundColor: Colors.white, + backgroundColor: primaryColor, + shape: const StadiumBorder(), + maximumSize: const Size(double.infinity, 56), + minimumSize: const Size(double.infinity, 56), + ), + ), + inputDecorationTheme: const InputDecorationTheme( + filled: true, + fillColor: primaryLightColor, + iconColor: primaryColor, + prefixIconColor: primaryColor, + contentPadding: EdgeInsets.symmetric( + horizontal: defaultPadding, vertical: defaultPadding), + border: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(30)), + borderSide: BorderSide.none, + ), + ), + fontFamily: 'Poppins', + ), + home: const WelcomeScreen(), + ); + } +} diff --git a/lib/screens/attendance/attendance_screen.dart b/lib/screens/attendance/attendance_screen.dart new file mode 100644 index 0000000..b916e5b --- /dev/null +++ b/lib/screens/attendance/attendance_screen.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:school_management_system/components/default_values.dart'; +import 'package:school_management_system/screens/welcome/welcome_screen.dart'; + +late Future _checkToken; + +class AttendanceScreen extends StatefulWidget { + const AttendanceScreen({super.key}); + + @override + State createState() => _AttendanceScreenState(); +} + +class _AttendanceScreenState extends State { + @override + void initState() { + _checkToken = checkTokenValidity(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + _checkToken.then( + (value) { + if (!value) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + return const WelcomeScreen(); + }, + ), + ); + + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Session Time Out / Sign Back In'), + ), + ); + } + }, + ); + + return const Center( + child: Text( + 'Attendance Page', + style: TextStyle(fontWeight: FontWeight.w800), + ), + ); + } +} diff --git a/lib/screens/calender/calender_screen.dart b/lib/screens/calender/calender_screen.dart new file mode 100644 index 0000000..1f58173 --- /dev/null +++ b/lib/screens/calender/calender_screen.dart @@ -0,0 +1,222 @@ +import 'package:flutter/material.dart'; +import 'package:school_management_system/api/calender_requests.dart'; +import 'package:school_management_system/components/default_values.dart'; +import 'package:school_management_system/screens/welcome/welcome_screen.dart'; +import 'package:syncfusion_flutter_calendar/calendar.dart'; + +late Future _studentData; +late Future _schoolData; +late Future _checkToken; + +class SchoolCalender extends StatefulWidget { + const SchoolCalender({super.key}); + + @override + State createState() => _SchoolCalenderState(); +} + +class _SchoolCalenderState extends State { + List calendar = []; + + @override + void initState() { + _checkToken = checkTokenValidity(); + super.initState(); + _studentData = getStudentCalender(loginId, session, semester); + _schoolData = getSchoolCalender('HOLIDAY', session, semester); + } + + @override + Widget build(BuildContext context) { + + _checkToken.then( + (value) {; + if (!value) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + return const WelcomeScreen(); + }, + ), + ); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Session Time Out / Sign Back In'), + ), + ); + } + }, + ); + + return FutureBuilder>( + future: Future.wait([_schoolData, _studentData]), + builder: (context, snapshot) { + List children; + if (snapshot.hasData) { + calendar = []; + var levelOne = 0; + while (levelOne < snapshot.data!.length) { + var levelTwo = 0; + while (levelTwo < + snapshot.data![levelOne].calenderrdetails!.length) { + calendar + .add(snapshot.data![levelOne].calenderrdetails![levelTwo]); + levelTwo++; + } + levelOne++; + } + children = [ + const SizedBox(height: 20), + Expanded( + child: SfCalendar( + view: CalendarView.month, + showDatePickerButton: true, + showTodayButton: true, + dataSource: MeetingDataSource(_getDataSource()), + monthViewSettings: const MonthViewSettings( + showAgenda: true, + appointmentDisplayMode: + MonthAppointmentDisplayMode.appointment), + ), + ), + ]; + } else if (snapshot.hasError) { + calendar = []; + children = [ + const Icon( + Icons.error_outline, + color: Colors.red, + size: 60, + ), + Padding( + padding: const EdgeInsets.only(top: 16), + child: Text('Error: ${snapshot.error}'), + ), + ]; + } else { + calendar = []; + children = const [ + SizedBox( + width: 60, + height: 60, + child: CircularProgressIndicator(), + ), + Padding( + padding: EdgeInsets.only(top: 16), + child: Text('Loading Data...'), + ), + ]; + } + + return Container( + padding: const EdgeInsets.all(20), + color: Colors.white, + child: Column( + children: children, + ), + ); + }); + } + + List _getDataSource() { + List meetings = []; + + var calendarCount = 0; + if (calendar.isNotEmpty) { + while (calendarCount < calendar.length) { + bool? allday = calendar[calendarCount].allday; + + DateTime? sdate = calendar[calendarCount].startdate; + String? stime = calendar[calendarCount].starttime; + + DateTime? starttime = DateTime( + sdate!.year, + sdate.month, + sdate.day, + int.parse(stime!.split(':')[0]), + int.parse(stime.split(':')[1]), + int.parse(stime.split(':')[2])); + + DateTime? edate = calendar[calendarCount].enddate; + String? etime = calendar[calendarCount].endtime; + + DateTime? endtime = DateTime( + edate!.year, + edate.month, + edate.day, + int.parse(etime!.split(':')[0]), + int.parse(etime.split(':')[1]), + int.parse(etime.split(':')[2])); + + // DateTime? enddate = calendar[initVal].enddate; + String? event = calendar[calendarCount].event; +// String? recurrenceRule = calendar[initVal].occurence; + + meetings.add(Meeting( + event!, starttime, endtime, primaryColor, allday!, "")); + calendarCount++; + } + } + + // // final DateTime today = DateTime.now(); + // final DateTime startTime = DateTime(2024, 03, 16, 9, 0, 0); + // // DateTime(today.year, today.month, today.day, 9, 0, 0); + // final DateTime endTime = startTime.add(const Duration(hours: 2)); + + // meetings.add(Meeting( + // 'Birthday', startTime, endTime, const Color(0xFF0F8644), false)); + return meetings; + } +} + +class MeetingDataSource extends CalendarDataSource { + MeetingDataSource(this.source); + + List source; + + @override + List get appointments => source; + + @override + DateTime getStartTime(int index) { + return source[index].from; + } + + @override + DateTime getEndTime(int index) { + return source[index].to; + } + + @override + String getSubject(int index) { + return source[index].eventName; + } + + @override + Color getColor(int index) { + return source[index].background; + } + + @override + bool isAllDay(int index) { + return source[index].isAllDay; + } + + @override + String getRecurrenceRule(int index) { + return appointments[index].recurrenceRule; + } +} + +class Meeting { + Meeting(this.eventName, this.from, this.to, this.background, this.isAllDay, + this.recurrenceRule); + + String eventName; + DateTime from; + DateTime to; + Color background; + bool isAllDay; + String recurrenceRule; +} diff --git a/lib/screens/finance/finance_screen.dart b/lib/screens/finance/finance_screen.dart new file mode 100644 index 0000000..69cea00 --- /dev/null +++ b/lib/screens/finance/finance_screen.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:school_management_system/components/default_values.dart'; +import 'package:school_management_system/screens/welcome/welcome_screen.dart'; + +late Future _checkToken; + +class FinanceScreen extends StatefulWidget { + const FinanceScreen({super.key}); + + @override + State createState() => _FinanceScreenState(); +} + +class _FinanceScreenState extends State { + + @override + void initState() { + _checkToken = checkTokenValidity(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + + _checkToken.then( + (value) { + if (!value) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + return const WelcomeScreen(); + }, + ), + ); + + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Session Time Out / Sign Back In'), + ), + ); + } + }, + ); + + return const Center( + child: Text( + 'Finance Page', + style: TextStyle(fontWeight: FontWeight.w800), + ), + ); + } +} diff --git a/lib/screens/home/home_screen.dart b/lib/screens/home/home_screen.dart new file mode 100644 index 0000000..9e30aec --- /dev/null +++ b/lib/screens/home/home_screen.dart @@ -0,0 +1,95 @@ +import 'package:flutter/material.dart'; +import 'package:school_management_system/components/default_values.dart'; +import 'package:school_management_system/screens/welcome/welcome_screen.dart'; +import 'package:webview_flutter/webview_flutter.dart'; + +late Future _checkToken; + +class HomeScreen extends StatefulWidget { + const HomeScreen({super.key}); + + @override + State createState() => _HomeScreenState(); +} + +class _HomeScreenState extends State { + late final WebViewController controller; + var loadingPercentage = 0; +// String? message; + + // setMessage(String javascriptMessage) { + // if (mounted) { + // setState(() { + // message = javascriptMessage; + // }); + // } + // } + + @override + void initState() { + _checkToken = checkTokenValidity(); + super.initState(); + controller = WebViewController() + ..loadRequest( + Uri.parse('https://www.tees.ac.uk/sections/stud/news.cfm'), + ) + // ..addJavaScriptChannel("myChannel", + // onMessageReceived: (JavaScriptMessage message) { + // // setMessage(message.message); + // }) + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..setNavigationDelegate(NavigationDelegate( + onPageStarted: (url) { + setState(() { + loadingPercentage = 0; + }); + }, + onProgress: (progress) { + setState(() { + loadingPercentage = progress; + }); + }, + onPageFinished: (url) { + setState(() { + loadingPercentage = 100; + }); + }, + )); + } + + @override + Widget build(BuildContext context) { + _checkToken.then( + (value) { + if (!value) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + return const WelcomeScreen(); + }, + ), + ); + + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Session Time Out / Sign Back In'), + ), + ); + } + }, + ); + + return Stack( + children: [ + WebViewWidget( + controller: controller, + ), + if (loadingPercentage < 100) + LinearProgressIndicator( + value: loadingPercentage / 100.0, + ), + ], + ); + } +} diff --git a/lib/screens/login/components/login_form.dart b/lib/screens/login/components/login_form.dart new file mode 100644 index 0000000..ac67ea1 --- /dev/null +++ b/lib/screens/login/components/login_form.dart @@ -0,0 +1,132 @@ +import 'package:flutter/material.dart'; +import 'package:school_management_system/api/auth_requests.dart'; +import 'package:school_management_system/components/default_values.dart'; +import 'package:school_management_system/screens/main/main_screen.dart'; + +class LoginForm extends StatefulWidget { + const LoginForm({ + super.key, + }); + + @override + State createState() => _LoginFormState(); +} + +class _LoginFormState extends State { + var usernameController = TextEditingController(); + var passwordController = TextEditingController(); + var checked = false; + var obscureText = true; + //var authService = AuthoriseService(); + + @override + Widget build(BuildContext context) { + return Column( + // mainAxisAlignment: MainAxisAlignment.start, + children: [ + TextField( + controller: usernameController, + keyboardType: TextInputType.emailAddress, + textInputAction: TextInputAction.next, + cursorColor: primaryColor, + onSubmitted: (username) { + setState(() { + usernameController.text = username; + }); + }, + decoration: const InputDecoration( + hintText: "Username", + prefixIcon: Padding( + padding: EdgeInsets.all(defaultPadding), + child: Icon(Icons.person), + ), + ), + ), + const SizedBox(height: 10), + TextField( + controller: passwordController, + keyboardType: TextInputType.visiblePassword, + textInputAction: TextInputAction.done, + obscureText: obscureText, + onSubmitted: (paswword) { + setState(() { + passwordController.text = paswword; + }); + }, + cursorColor: primaryColor, + decoration: InputDecoration( + hintText: "Password", + prefixIcon: const Padding( + padding: EdgeInsets.all(defaultPadding), + child: Icon(Icons.lock), + ), + suffixIcon: IconButton( + icon: Icon( + obscureText ? Icons.visibility : Icons.visibility_off), + onPressed: () { + setState( + () { + obscureText = !obscureText; + }, + ); + }, + )), + ), + const SizedBox(), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Checkbox( + value: checked, + onChanged: (value) { + setState(() { + checked = value!; + }); + }), + const Text('Save Password'), + ], + ), + const SizedBox(height: defaultPadding), + ElevatedButton( + onPressed: () { + login(usernameController.value.text, passwordController.value.text) + .then((status) { + if (status.startsWith('Successful')) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + return const MainScaffold(); + }, + ), + ); + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(status), + ), + ); + } else { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(status), + ), + ); + } + }); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "sign in".toUpperCase(), + ), + const SizedBox(width: 10), + const Icon(Icons.login) + ], + ), + ), + ], + ); + } +} diff --git a/lib/screens/login/components/login_screen_top_image.dart b/lib/screens/login/components/login_screen_top_image.dart new file mode 100644 index 0000000..96a55dc --- /dev/null +++ b/lib/screens/login/components/login_screen_top_image.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:school_management_system/components/default_values.dart'; + +class LoginScreenTopImage extends StatelessWidget { + const LoginScreenTopImage({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return Column( + // mainAxisAlignment: MainAxisAlignment.start, + children: [ + // const Text( + // "LOGIN", + // style: TextStyle(fontWeight: FontWeight.bold), + // ), + const SizedBox(height: defaultPadding * 2), + Row( + children: [ + const Spacer(), + Expanded( + flex: 8, + child: SvgPicture.asset( + 'assets/icons/school.svg', + width: 320, + height: 320, + ), + ), + const Spacer(), + ], + ), + const SizedBox(height: defaultPadding * 2), + ], + ); + } +} \ No newline at end of file diff --git a/lib/screens/login/login_screen.dart b/lib/screens/login/login_screen.dart new file mode 100644 index 0000000..aec58f2 --- /dev/null +++ b/lib/screens/login/login_screen.dart @@ -0,0 +1,69 @@ +import 'package:flutter/material.dart'; +import 'package:school_management_system/screens/login/components/login_form.dart'; +import 'package:school_management_system/screens/login/components/login_screen_top_image.dart'; +import 'package:school_management_system/screens/main/main_screen.dart'; + +class LoginScreen extends StatefulWidget { + const LoginScreen({super.key}); + + @override + State createState() => _LoginScreenState(); +} + +class _LoginScreenState extends State { + @override + Widget build(BuildContext context) { + return const Scaffold( + resizeToAvoidBottomInset: false, + body: Responsive( + desktop: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Expanded( + child: LoginScreenTopImage(), + ), + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + width: 350, + child: LoginForm(), + ), + ], + ), + ), + ], + ), + mobile: MobileLoginScreen(), + ), + ); + } +} + +class MobileLoginScreen extends StatelessWidget { + const MobileLoginScreen({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return ListView( + + // mainAxisAlignment: MainAxisAlignment.center, + children: const [ + LoginScreenTopImage(), + Row( + children: [ + Spacer(), + Expanded( + flex: 8, + child: LoginForm(), + ), + Spacer(), + ], + ), + ], + ); + } +} diff --git a/lib/screens/main/components/navigation_details.dart b/lib/screens/main/components/navigation_details.dart new file mode 100644 index 0000000..9060335 --- /dev/null +++ b/lib/screens/main/components/navigation_details.dart @@ -0,0 +1,68 @@ +import 'package:flutter/material.dart'; +import 'package:school_management_system/screens/attendance/attendance_screen.dart'; +import 'package:school_management_system/screens/calender/calender_screen.dart'; +import 'package:school_management_system/screens/finance/finance_screen.dart'; +import 'package:school_management_system/screens/home/home_screen.dart'; +import 'package:school_management_system/screens/modules/modules_screen.dart'; +import 'package:school_management_system/screens/profile/profile_screen.dart'; +import 'package:school_management_system/screens/results/results_screen.dart'; + +class NavigationItems { + String label; + Widget icon; + Widget widget; + + NavigationItems({ + required this.label, + required this.icon, + required this.widget, + }); +} + +List getNavigationItems() { + List navigationItems = []; + + navigationItems.add(NavigationItems( + label: 'Home', + icon: const Icon(Icons.home), + widget: const HomeScreen(), + )); + + navigationItems.add(NavigationItems( + label: 'Modules', + icon: const Icon(Icons.book), + widget: const ModulesScreen(), + )); + + navigationItems.add(NavigationItems( + label: 'Calendar', + icon: const Icon(Icons.calendar_month), + widget: const SchoolCalender(), + )); + + navigationItems.add(NavigationItems( + label: 'Results', + icon: const Icon(Icons.school), + widget: const ResultsScreen(), + )); + + navigationItems.add(NavigationItems( + label: 'Profile', + icon: const Icon(Icons.person), + widget: const ProfileScreen(), + )); + + navigationItems.add(NavigationItems( + label: 'Finance', + icon: const Icon(Icons.money), + widget: const FinanceScreen(), + )); + + navigationItems.add(NavigationItems( + label: 'Attendance', + icon: const Icon(Icons.calendar_today_rounded), + widget: const AttendanceScreen(), + )); + + return navigationItems; +} diff --git a/lib/screens/main/main_screen.dart b/lib/screens/main/main_screen.dart new file mode 100644 index 0000000..0a15b9a --- /dev/null +++ b/lib/screens/main/main_screen.dart @@ -0,0 +1,201 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:school_management_system/api/session_requests.dart'; +import 'package:school_management_system/components/default_values.dart'; +import 'package:school_management_system/screens/main/components/navigation_details.dart'; +import 'package:school_management_system/screens/welcome/welcome_screen.dart'; + +class MainScaffold extends StatefulWidget { + //final Widget child; + final String appTitle; + + const MainScaffold({ + super.key, + // required this.child, + this.appTitle = 'School Management Demo', + }); + + @override + State createState() => _MainScaffold(); +} + +class _MainScaffold extends State { + var selectedIndex = 0; + + @override + void initState() { + super.initState(); + } + + List navigationItems = getNavigationItems(); + + @override + Widget build(BuildContext context) { + Widget page = navigationItems[selectedIndex].widget; + + return FutureBuilder( + future: getCurrentSession(), + builder: (context, snapshot) { + return Scaffold( + resizeToAvoidBottomInset: true, + appBar: AppBar( + title: Row( + children: [ + if (navigationItems[selectedIndex].label == 'Home') + Row( + children: [ + const SizedBox(width: 35), + Text(navigationItems[selectedIndex].label) + ], + ) + else + Row( + children: [ + Image.asset( + 'assets/images/unilogo.png', + width: 25, + height: 25, + fit: BoxFit.contain, + ), + const SizedBox(width: 10), + Text(navigationItems[selectedIndex].label), + ], + ), + // Text( + + // navigationItems[selectedIndex].label, + + // ), + ], + ), + backgroundColor: primaryColor, + actions: [ + IconButton( + icon: const Icon( + Icons.logout, + ), + tooltip: 'Logout', + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + if (Platform.isAndroid) { + //SystemNavigator.pop(); + return const WelcomeScreen(); + } else if (Platform.isIOS) { + // exit(0); + return const WelcomeScreen(); + } else { + return const WelcomeScreen(); + } + }, + ), + ); + }, + ) + ], + ), + drawer: SafeArea( + child: Responsive( + mobile: Row( + children: [ + NavigationDrawer( + elevation: 50, + backgroundColor: primaryLightColor.withOpacity(1), + indicatorColor: primaryColor, + selectedIndex: selectedIndex, + onDestinationSelected: (value) { + setState(() { + Navigator.pop(context); + selectedIndex = value; + }); + }, + children: + navigationItems.map((NavigationItems navigationItem) { + return NavigationDrawerDestination( + icon: navigationItem.icon, + label: Text(navigationItem.label), + selectedIcon: navigationItem.icon, + backgroundColor: primaryColor, + ); + }).toList(), + ), + ], + ), + desktop: Row( + children: [ + NavigationRail( + extended: true, + labelType: NavigationRailLabelType.none, + destinations: + navigationItems.map((NavigationItems navigationItem) { + return NavigationRailDestination( + label: Text(navigationItem.label), + icon: navigationItem.icon, + selectedIcon: navigationItem.icon, + ); + }).toList(), + selectedIndex: selectedIndex, + onDestinationSelected: (value) { + setState(() { + selectedIndex = value; + }); + }, + ), + ], + ), + ), + ), + body: SizedBox( + width: double.infinity, + height: MediaQuery.of(context).size.height, + child: Stack( + alignment: Alignment.center, + children: [ + SafeArea( + child: page, + ), + ], + ), + ), + ); + }); + } +} + +class Responsive extends StatelessWidget { + final Widget mobile; + final Widget? tablet; + final Widget desktop; + + const Responsive({ + super.key, + required this.mobile, + this.tablet, + required this.desktop, + }); + + static bool isMobile(BuildContext context) => + MediaQuery.of(context).size.width < 576; + + static bool isTablet(BuildContext context) => + MediaQuery.of(context).size.width >= 576 && + MediaQuery.of(context).size.width <= 992; + + static bool isDesktop(BuildContext context) => + MediaQuery.of(context).size.width > 992; + + @override + Widget build(BuildContext context) { + final Size size = MediaQuery.of(context).size; + if (size.width > 992) { + return desktop; + } else if (size.width >= 600 && tablet != null) { + return tablet!; + } else { + return mobile; + } + } +} diff --git a/lib/screens/modules/modules_screen.dart b/lib/screens/modules/modules_screen.dart new file mode 100644 index 0000000..2f86cd6 --- /dev/null +++ b/lib/screens/modules/modules_screen.dart @@ -0,0 +1,225 @@ +import 'package:flutter/material.dart'; +import 'package:school_management_system/api/student_requests.dart'; +import 'package:school_management_system/components/default_values.dart'; +import 'package:school_management_system/screens/welcome/welcome_screen.dart'; + +late Future _returnData; +late Student apiData; +late Map>? sessiondetails; +late Map> moduleDetail; +late Future _checkToken; + +class ModulesScreen extends StatefulWidget { + const ModulesScreen({super.key}); + + @override + State createState() => _ModulesScreenState(); +} + +class _ModulesScreenState extends State { + String? _selectedKey; + String? _selectedItem; + List? indivModule; + + @override + void initState() { + _checkToken = checkTokenValidity(); + super.initState(); + _returnData = getStudentDetail(loginId); + } + + @override + Widget build(BuildContext context) { + _checkToken.then( + (value) { + if (!value) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + return const WelcomeScreen(); + }, + ), + ); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Session Time Out / Sign Back In'), + ), + ); + } + }, + ); + + return FutureBuilder( + future: _returnData, + builder: (context, snapshot) { + List children; + if (snapshot.hasData) { + apiData = snapshot.data!; + moduleDetail = apiData.moduledetails!; + sessiondetails = apiData.sessiondetails!; + children = [ + const SizedBox(height: 20), + dropDownMenu(), + const SizedBox(height: 50), + dataTableMenu(), + ]; + } else if (snapshot.hasError) { + children = [ + const Icon( + Icons.error_outline, + color: Colors.red, + size: 60, + ), + Padding( + padding: const EdgeInsets.only(top: 16), + child: Text('Error: ${snapshot.error}'), + ), + ]; + } else { + children = const [ + SizedBox( + width: 60, + height: 60, + child: CircularProgressIndicator(), + ), + Padding( + padding: EdgeInsets.only(top: 16), + child: Text('Loading Data...'), + ), + ]; + } + + return Container( + color: Colors.white, + child: Padding( + padding: const EdgeInsets.only(left: 20, right: 20), + child: ListView( + scrollDirection: Axis.vertical, + children: children, + ), + ), + ); + }, + ); + } + + Row dropDownMenu() { + return Row( + children: [ + DropdownButton( + value: _selectedKey, + icon: const Icon(Icons.arrow_drop_down), + iconSize: 30, + elevation: 16, + style: const TextStyle(fontSize: 20, color: Colors.black), + underline: Container( + height: 2, + color: Colors.grey, + ), + onChanged: (newValue) { + setState(() { + _selectedKey = newValue; + _selectedItem = null; + }); + }, + items: sessiondetails?.keys.map((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + ), + const SizedBox(width: 30), + _selectedKey != null + ? DropdownButton( + value: _selectedItem, + icon: const Icon(Icons.arrow_drop_down), + iconSize: 30, + elevation: 16, + style: const TextStyle(fontSize: 20, color: Colors.black), + underline: Container( + height: 2, + color: Colors.grey, + ), + onChanged: (newValue) { + setState(() { + _selectedItem = newValue; + }); + }, + items: sessiondetails![_selectedKey]!.map((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + onTap: () { + setState(() { + indivModule = moduleDetail["$_selectedKey~$value"]; + }); + }, + ); + }).toList(), + ) + : Container() + ], + ); + } + + SingleChildScrollView dataTableMenu() { + return SingleChildScrollView( + scrollDirection: Axis.vertical, + child: indivModule != null + ? Column( + children: indivModule!.map((value) { + return Card( + elevation: 20, + color: const Color.fromARGB(255, 224, 208, 159), + child: InkWell( + onTap: () { + + }, + splashColor: primaryLightColor, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image.asset( + getImage(), + width: 120, + height: 120, + fit: BoxFit.cover, + ), + const SizedBox(width: 10), + Padding( + padding: const EdgeInsets.only(left: 5, top: 5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + value.modulecode!, + style: const TextStyle( + fontWeight: FontWeight.w800, + ), + ), + Text(value.modulename!), + const Column( + children: [ + Text('CLOSE'), + ], + ), + ], + ), + ), + ], + ), + ), + ); + }).toList(), + ) + : const Center( + child: Text( + 'Nothing to Display', + style: TextStyle(fontWeight: FontWeight.w800), + ), + ), + ); + } +} diff --git a/lib/screens/profile/components/personal_details.dart b/lib/screens/profile/components/personal_details.dart new file mode 100644 index 0000000..c48f306 --- /dev/null +++ b/lib/screens/profile/components/personal_details.dart @@ -0,0 +1,109 @@ +import 'package:intl/intl.dart'; +import 'package:school_management_system/api/student_requests.dart'; + +late DateTime dateOfBirth; + +Map getPersonalDetails(Student studentDetail) { + Map personalDetails = {}; + + if (studentDetail.dateofbirth != null) { + dateOfBirth = studentDetail.dateofbirth!; + } else { + dateOfBirth = DateTime.now(); + } + + personalDetails.addEntries({'Title': studentDetail.title}.entries); + personalDetails.addEntries({ + 'Full Name': "${studentDetail.firstname} ${studentDetail.lastname}" + }.entries); + personalDetails.addEntries({'Gender': studentDetail.gender}.entries); + personalDetails.addEntries({ + 'Date of Birth': DateFormat('MMMM, dd yyyy').format(dateOfBirth) + }.entries); + personalDetails + .addEntries({'Current Year': studentDetail.currentyear}.entries); + personalDetails + .addEntries({'Current Session': studentDetail.currentsession}.entries); + personalDetails.addEntries({ + 'Course of Study': studentDetail.coursedetails![0].courseofstudy + }.entries); + personalDetails.addEntries( + {'Course Type': studentDetail.coursedetails![0].coursetype}.entries); + personalDetails.addEntries({ + 'Course Qualification': studentDetail.coursedetails![0].coursequalification + }.entries); + personalDetails.addEntries( + {'Course Mode': studentDetail.coursedetails![0].coursemode}.entries); + + return personalDetails; +} + +Map getContactDetails(Student studentDetail) { + Map contactDetails = {}; + + contactDetails + .addEntries({'Home Address': studentDetail.homeaddress}.entries); + contactDetails + .addEntries({'Mobile Number': studentDetail.mobilenumber}.entries); + contactDetails + .addEntries({'E-Mail Address': studentDetail.emailaddress}.entries); + contactDetails + .addEntries({'School Email': studentDetail.schoolemail}.entries); + contactDetails.addEntries({ + 'Next of Kin Name ': studentDetail.nextofkindetails![0].nextofkinname + }.entries); + contactDetails.addEntries({ + 'Next of Kin Contact ': studentDetail.nextofkindetails![0].nextofkincontact + }.entries); + contactDetails.addEntries({ + 'Next of Kin Address ': studentDetail.nextofkindetails![0].nextofkinaddress + }.entries); + contactDetails.addEntries({ + 'Next of Kin Relationship ': studentDetail.nextofkindetails![0].nextofkinrelationship + }.entries); + contactDetails.addEntries({ + 'Guardian Name ': studentDetail.guardiandetails![0].guardianname + }.entries); + contactDetails.addEntries({ + 'Guardian Contact ': studentDetail.guardiandetails![0].guardiancontact + }.entries); + contactDetails.addEntries({ + 'Guardian Address ': studentDetail.guardiandetails![0].guardianaddress + }.entries); + contactDetails.addEntries({ + 'Guardian Relationship ': studentDetail.guardiandetails![0].guardianrelationship + }.entries); + + return contactDetails; +} + +Map getMedicalDetails(Student studentDetail) { + Map medicalDetails = {}; + + medicalDetails + .addEntries({'Weight': studentDetail.medicaldetails![0].weight}.entries); + medicalDetails + .addEntries({'Height': studentDetail.medicaldetails![0].height}.entries); + medicalDetails.addEntries( + {'Genotype': studentDetail.medicaldetails![0].genotype}.entries); + medicalDetails.addEntries( + {'Blood Group': studentDetail.medicaldetails![0].bloodgroup}.entries); + medicalDetails.addEntries( + {'DNR': studentDetail.medicaldetails![0].dnr.toString()}.entries); + medicalDetails.addEntries( + {'Allergies': studentDetail.medicaldetails![0].allergies}.entries); + medicalDetails.addEntries({ + 'Medical Condition': studentDetail.medicaldetails![0].medicalcondition + }.entries); + medicalDetails.addEntries({ + 'Emergency Contact': studentDetail.medicaldetails![0].emergencycontactname + }.entries); + medicalDetails.addEntries({ + 'Emergency Number': studentDetail.medicaldetails![0].emergencycontactnumber + }.entries); + medicalDetails.addEntries({ + 'Emergency Relationship': studentDetail.medicaldetails![0].emergencycontractrelationship + }.entries); + + return medicalDetails; +} diff --git a/lib/screens/profile/profile_screen.dart b/lib/screens/profile/profile_screen.dart new file mode 100644 index 0000000..0b0f60c --- /dev/null +++ b/lib/screens/profile/profile_screen.dart @@ -0,0 +1,265 @@ +import 'package:flutter/material.dart'; +import 'package:school_management_system/api/student_requests.dart'; +import 'package:school_management_system/components/default_values.dart'; +import 'package:school_management_system/screens/profile/components/personal_details.dart'; +import 'package:school_management_system/screens/welcome/welcome_screen.dart'; + +//This Screen Would include the basic Student Detials +//Profile Picture, Full Name, Course of Study, Current Year, Age (DOB), Medical History (Height, Weight, et all) +//Next of Kin, Contact Details, Address +//Every other item as remembered would be added. + +late Future _returnData; +late Student apiData; +late Future _checkToken; + +class ProfileScreen extends StatefulWidget { + const ProfileScreen({super.key}); + + @override + State createState() => _ProfileScreenState(); +} + +class _ProfileScreenState extends State { + @override + void initState() { + _checkToken = checkTokenValidity(); + super.initState(); + _returnData = getStudentDetail(loginId); + } + + @override + Widget build(BuildContext context) { + _checkToken.then( + (value) { + if (!value) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + return const WelcomeScreen(); + }, + ), + ); + + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Session Time Out / Sign Back In'), + ), + ); + } + }, + ); + return FutureBuilder( + future: _returnData, + builder: (context, snapshot) { + List children; + if (snapshot.hasData) { + apiData = snapshot.data!; + children = [ + const SizedBox(height: 20), + profileImage(), + const SizedBox(height: 30), + personalDetails(), + const SizedBox(height: 30), + contactDetails(), + const SizedBox(height: 30), + medicalDetails(), + const SizedBox(height: 30), + ]; + } else if (snapshot.hasError) { + children = [ + const Icon( + Icons.error_outline, + color: Colors.red, + size: 60, + ), + Padding( + padding: const EdgeInsets.only(top: 16), + child: Text('Error: ${snapshot.error}'), + ), + ]; + } else { + children = const [ + SizedBox( + width: 60, + height: 60, + child: CircularProgressIndicator(), + ), + Padding( + padding: EdgeInsets.only(top: 16), + child: Text('Loading Data...'), + ), + ]; + } + + return Container( + color: Colors.white, + child: Padding( + padding: const EdgeInsets.only(left: 20, right: 20), + child: ListView( + scrollDirection: Axis.vertical, + children: children, + ), + ), + ); + }, + ); + } + + Column medicalDetails() { + var medicalDetails = getMedicalDetails(apiData); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Medical Details', + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 5), + Column( + children: [ + Table( + columnWidths: const { + 0: IntrinsicColumnWidth(), + 1: FlexColumnWidth(), + 2: FixedColumnWidth(64) + }, + children: [ + for (var key in medicalDetails.keys) + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(right: 5), + child: Text( + key, + style: const TextStyle( + fontSize: 14, fontWeight: FontWeight.w500), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 5), + child: Text(medicalDetails[key]), + ) + ]) + ], + ) + ], + ), + ], + ); + } + + Column contactDetails() { + var contactDetails = getContactDetails(apiData); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Contact Details', + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 5), + Column( + children: [ + Table( + columnWidths: const { + 0: IntrinsicColumnWidth(), + 1: FlexColumnWidth(), + 2: FixedColumnWidth(64) + }, + children: [ + for (var key in contactDetails.keys) + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(right: 5), + child: Text( + key, + style: const TextStyle( + fontSize: 14, fontWeight: FontWeight.w500), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 5), + child: Text( + contactDetails[key], + ), + ) + ]) + ], + ) + ], + ) + ], + ); + } + + Column personalDetails() { + var personalDetails = getPersonalDetails(apiData); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Personal Details', + style: TextStyle( + color: Colors.black, + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 5), + Column( + children: [ + Table( + // border: TableBorder.all(), + columnWidths: const { + 0: IntrinsicColumnWidth(), + 1: FlexColumnWidth(), + 2: FixedColumnWidth(64) + }, + children: [ + for (var key in personalDetails.keys) + TableRow(children: [ + Padding( + padding: const EdgeInsets.only(right: 5), + child: Text( + key, + style: const TextStyle( + fontSize: 14, fontWeight: FontWeight.w500), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 5), + child: Text(personalDetails[key]), + ) + ]) + ], + ) + ], + ), + ], + ); + } + + Column profileImage() { + return Column( + children: [ + Image.asset( + 'assets/images/passport.jpg', + width: 120, + height: 120, + ) + ], + ); + } +} diff --git a/lib/screens/results/results_screen.dart b/lib/screens/results/results_screen.dart new file mode 100644 index 0000000..57efb86 --- /dev/null +++ b/lib/screens/results/results_screen.dart @@ -0,0 +1,215 @@ +import 'package:flutter/material.dart'; +import 'package:school_management_system/api/results_requests.dart'; +import 'package:school_management_system/api/student_requests.dart'; +import 'package:school_management_system/components/default_values.dart'; +import 'package:school_management_system/screens/welcome/welcome_screen.dart'; + +late Future _checkToken; +late Future _returnData; +late Map>? sessiondetails; +late Student apiData; +Future? _returnresult; +late List studentScores; + +class ResultsScreen extends StatefulWidget { + const ResultsScreen({super.key}); + + @override + State createState() => _ResultsScreenState(); +} + +class _ResultsScreenState extends State { + String? _selectedKey; + String? _selectedItem; + Result? resultList; + + @override + void initState() { + _checkToken = checkTokenValidity(); + super.initState(); + _returnData = getStudentDetail(loginId); + resultList = null; + } + + @override + Widget build(BuildContext context) { + _checkToken.then( + (value) { + if (!value) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + return const WelcomeScreen(); + }, + ), + ); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Session Time Out / Sign Back In'), + ), + ); + } + }, + ); + + return FutureBuilder( + future: _returnData, + builder: (context, snapshot) { + List children; + if (snapshot.hasData) { + apiData = snapshot.data!; + sessiondetails = apiData.sessiondetails!; + children = [ + const SizedBox(height: 20), + dropDownMenu(), + const SizedBox(height: 50), + dataTableMenu() + ]; + } else if (snapshot.hasError) { + children = [ + const Icon( + Icons.error_outline, + color: Colors.red, + size: 60, + ), + Padding( + padding: const EdgeInsets.only(top: 16), + child: Text('Error: ${snapshot.error}'), + ), + ]; + } else { + children = const [ + SizedBox( + width: 60, + height: 60, + child: CircularProgressIndicator(), + ), + Padding( + padding: EdgeInsets.only(top: 16), + child: Text('Loading Data...'), + ), + ]; + } + + return Container( + color: Colors.white, + child: Padding( + padding: const EdgeInsets.only(left: 20, right: 20), + child: ListView( + scrollDirection: Axis.vertical, + children: children, + ), + ), + ); + }, + ); + } + + Row dropDownMenu() { + return Row( + children: [ + DropdownButton( + value: _selectedKey, + icon: const Icon(Icons.arrow_drop_down), + iconSize: 30, + elevation: 16, + style: const TextStyle(fontSize: 20, color: Colors.black), + underline: Container( + height: 2, + color: Colors.grey, + ), + onChanged: (newValue) { + setState(() { + _selectedKey = newValue; + _selectedItem = null; + }); + }, + items: sessiondetails?.keys.map((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + ), + const SizedBox(width: 30), + _selectedKey != null + ? DropdownButton( + value: _selectedItem, + icon: const Icon(Icons.arrow_drop_down), + iconSize: 30, + elevation: 16, + style: const TextStyle(fontSize: 20, color: Colors.black), + underline: Container( + height: 2, + color: Colors.grey, + ), + onChanged: (newValue) { + setState(() { + _selectedItem = newValue; + }); + }, + items: sessiondetails![_selectedKey]!.map((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + onTap: () { + setState(() { + _returnresult = getStudentResult(_selectedKey!, value); + // resultList = null; + }); + }, + ); + }).toList(), + ) + : Container() + ], + ); + } + + FutureBuilder dataTableMenu() { + resultList = null; + return FutureBuilder( + future: _returnresult, + builder: (context, snapshot) { + if (snapshot.hasData) { + resultList = snapshot.data!; + studentScores = resultList!.scores!; + } else if (snapshot.hasError) { + resultList = snapshot.data; + } else { + resultList = null; + } + return SingleChildScrollView( + scrollDirection: Axis.vertical, + child: resultList != null + ? Column( + children: [ + DataTable( + columns: const [ + //DataColumn(label: Text('Module Code')), + DataColumn(label: Text('Module Title')), + DataColumn(label: Text('Score'), numeric: true), + DataColumn(label: Text('Grade')), + ], + rows: resultList!.scores!.map((value) { + return DataRow(cells: [ + // DataCell(Text(value.module!)), + DataCell(Text(value.module!)), + DataCell(Text(value.score!.toString())), + DataCell(Text(studentGrade(value.score!))), + ]); + }).toList()), + ], + ) + : const Center( + child: Text( + 'Nothing to Display', + style: TextStyle(fontWeight: FontWeight.w800), + ), + ), + ); + }, + ); + } +} diff --git a/lib/screens/welcome/components/welcome_image.dart b/lib/screens/welcome/components/welcome_image.dart new file mode 100644 index 0000000..76dc634 --- /dev/null +++ b/lib/screens/welcome/components/welcome_image.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:school_management_system/components/default_values.dart'; + +class WelcomeImage extends StatelessWidget { + const WelcomeImage({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + // const Text( + // "WELCOME", + // style: TextStyle(fontWeight: FontWeight.bold), + // ), + const SizedBox(height: defaultPadding * 2), + Row( + children: [ + const Spacer(), + Expanded( + flex: 8, + child: SvgPicture.asset( + 'assets/icons/school.svg', + width: 320, + height: 320, + ), + ), + const Spacer(), + ], + ), + const SizedBox(height: defaultPadding * 2), + ], + ); + } +} \ No newline at end of file diff --git a/lib/screens/welcome/components/welcome_login.dart b/lib/screens/welcome/components/welcome_login.dart new file mode 100644 index 0000000..f7df83d --- /dev/null +++ b/lib/screens/welcome/components/welcome_login.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:school_management_system/screens/login/login_screen.dart'; + +class LoginButton extends StatelessWidget { + const LoginButton({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + return const LoginScreen(); + }, + ), + ); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "go to sign in".toUpperCase(), + ), + const SizedBox(width: 10), + const Icon(Icons.school) + ], + ), + ), + const SizedBox(height: 16), + ], + ); + } +} diff --git a/lib/screens/welcome/welcome_screen.dart b/lib/screens/welcome/welcome_screen.dart new file mode 100644 index 0000000..c575f11 --- /dev/null +++ b/lib/screens/welcome/welcome_screen.dart @@ -0,0 +1,84 @@ +import 'package:flutter/material.dart'; +import 'package:school_management_system/components/default_values.dart'; +import 'package:school_management_system/screens/main/main_screen.dart'; +import 'package:school_management_system/screens/welcome/components/welcome_image.dart'; +import 'package:school_management_system/screens/welcome/components/welcome_login.dart'; + +class WelcomeScreen extends StatefulWidget { + const WelcomeScreen({super.key}); + + @override + State createState() => _WelcomeScreenState(); +} + +class _WelcomeScreenState extends State { + @override + void initState() { + + super.initState(); + setSharedPref('authkey', ''); + setSharedPref('isLogin', false); + setSharedPref('tokenValidity', ''); + } + + @override + Widget build(BuildContext context) { + return const Scaffold( + body: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SingleChildScrollView( + child: Responsive( + desktop: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Expanded( + child: WelcomeImage(), + ), + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + width: 350, + child: LoginButton(), + ), + ], + ), + ), + ], + ), + mobile: MobileWelcomeScreen(), + ), + ), + ], + ), + ); + } +} + +class MobileWelcomeScreen extends StatelessWidget { + const MobileWelcomeScreen({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return const Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + WelcomeImage(), + Row( + children: [ + Spacer(), + Expanded( + flex: 3, + child: LoginButton(), + ), + Spacer(), + ], + ), + ], + ); + } +} diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..e963e4a --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,578 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + archive: + dependency: transitive + description: + name: archive + sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d + url: "https://pub.dev" + source: hosted + version: "3.6.1" + args: + dependency: transitive + description: + name: args + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + url: "https://pub.dev" + source: hosted + version: "2.5.0" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 + url: "https://pub.dev" + source: hosted + version: "0.4.1" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://pub.dev" + source: hosted + version: "1.0.8" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" + url: "https://pub.dev" + source: hosted + version: "0.13.1" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2" + url: "https://pub.dev" + source: hosted + version: "2.0.10+1" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + http: + dependency: "direct main" + description: + name: http + sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + image: + dependency: transitive + description: + name: image + sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8" + url: "https://pub.dev" + source: hosted + version: "4.2.0" + intl: + dependency: "direct main" + description: + name: intl + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + url: "https://pub.dev" + source: hosted + version: "0.19.0" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + url: "https://pub.dev" + source: hosted + version: "10.0.4" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + url: "https://pub.dev" + source: hosted + version: "3.0.3" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + lints: + dependency: transitive + description: + name: lints + sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 + url: "https://pub.dev" + source: hosted + version: "3.0.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" + source: hosted + version: "0.12.16+1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + url: "https://pub.dev" + source: hosted + version: "0.8.0" + meta: + dependency: transitive + description: + name: meta + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + url: "https://pub.dev" + source: hosted + version: "1.12.0" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + url: "https://pub.dev" + source: hosted + version: "2.2.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + url: "https://pub.dev" + source: hosted + version: "6.0.2" + platform: + dependency: transitive + description: + name: platform + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + url: "https://pub.dev" + source: hosted + version: "3.1.5" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 + url: "https://pub.dev" + source: hosted + version: "2.2.3" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "93d0ec9dd902d85f326068e6a899487d1f65ffcd5798721a95330b26c8131577" + url: "https://pub.dev" + source: hosted + version: "2.2.3" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a" + url: "https://pub.dev" + source: hosted + version: "2.3.0" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + syncfusion_flutter_calendar: + dependency: "direct main" + description: + name: syncfusion_flutter_calendar + sha256: "4151e01aa1d6f17b2bcb19d709b93f231d40c9ce78db52ea195b7b7233ce0149" + url: "https://pub.dev" + source: hosted + version: "24.2.4" + syncfusion_flutter_core: + dependency: transitive + description: + name: syncfusion_flutter_core + sha256: "7666506885ebc8f62bb928ad4588a73e20caaff2b2cf2b2b56f67d98f4113525" + url: "https://pub.dev" + source: hosted + version: "24.2.9" + syncfusion_flutter_datepicker: + dependency: transitive + description: + name: syncfusion_flutter_datepicker + sha256: c010440ccef2beecb988684af3557c57ade8ea300d1177536f01059e3a16ce5d + url: "https://pub.dev" + source: hosted + version: "24.2.9" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + url: "https://pub.dev" + source: hosted + version: "0.7.0" + timezone: + dependency: transitive + description: + name: timezone + sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0" + url: "https://pub.dev" + source: hosted + version: "0.9.2" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3" + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81" + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + url: "https://pub.dev" + source: hosted + version: "14.2.1" + web: + dependency: transitive + description: + name: web + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + url: "https://pub.dev" + source: hosted + version: "0.5.1" + webview_flutter: + dependency: "direct main" + description: + name: webview_flutter + sha256: "6869c8786d179f929144b4a1f86e09ac0eddfe475984951ea6c634774c16b522" + url: "https://pub.dev" + source: hosted + version: "4.8.0" + webview_flutter_android: + dependency: transitive + description: + name: webview_flutter_android + sha256: f42447ca49523f11d8f70abea55ea211b3cafe172dd7a0e7ac007bb35dd356dc + url: "https://pub.dev" + source: hosted + version: "3.16.4" + webview_flutter_platform_interface: + dependency: transitive + description: + name: webview_flutter_platform_interface + sha256: d937581d6e558908d7ae3dc1989c4f87b786891ab47bb9df7de548a151779d8d + url: "https://pub.dev" + source: hosted + version: "2.10.0" + webview_flutter_wkwebview: + dependency: transitive + description: + name: webview_flutter_wkwebview + sha256: "7affdf9d680c015b11587181171d3cad8093e449db1f7d9f0f08f4f33d24f9a0" + url: "https://pub.dev" + source: hosted + version: "3.13.1" + win32: + dependency: transitive + description: + name: win32 + sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4 + url: "https://pub.dev" + source: hosted + version: "5.5.1" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + url: "https://pub.dev" + source: hosted + version: "1.0.4" + xml: + dependency: transitive + description: + name: xml + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + url: "https://pub.dev" + source: hosted + version: "6.5.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.4.0 <4.0.0" + flutter: ">=3.22.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..6443754 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,125 @@ +name: school_management_system +description: "School Management System" +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: "none" # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 1.0.0+1 + +environment: + sdk: ">=3.2.5 <4.0.0" + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 + flutter_svg: ^2.0.9 + http: ^1.2.0 + syncfusion_flutter_calendar: "24.2.4" + intl: ^0.19.0 + webview_flutter: ^4.7.0 + shared_preferences: ^2.2.3 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_launcher_icons: ^0.13.1 + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^3.0.1 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + - assets/icons/ + - assets/images/ + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + fonts: + - family: Poppins + fonts: + - asset: fonts/Poppins-Bold.ttf + weight: 700 + - asset: fonts/Poppins-Medium.ttf + weight: 500 + - asset: fonts/Poppins-Regular.ttf + weight: 400 + - asset: fonts/Poppins-SemiBold.ttf + weight: 600 + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages + +flutter_launcher_icons: + android: "launcher_icon" + ios: true + image_path: "assets/icons/School_Picture.png" + min_sdk_android: 21 # android min sdk min:16, default 21 + web: + generate: true + image_path: "assets/icons/School_Picture.png" + background_color: "#hexcode" + theme_color: "#hexcode" + windows: + generate: true + image_path: "assets/icons/School_Picture.png" + icon_size: 48 # min:48, max:256, default: 48 + macos: + generate: true + image_path: "assets/icons/School_Picture.png" \ No newline at end of file