diff --git a/frontend/app_student/assets/fonts/arial.ttf b/frontend/app_student/assets/fonts/arial.ttf
new file mode 100644
index 0000000..ad7d8ea
Binary files /dev/null and b/frontend/app_student/assets/fonts/arial.ttf differ
diff --git a/frontend/app_student/assets/images/3il-icon-blue.png b/frontend/app_student/assets/images/3il-icon-blue.png
new file mode 100644
index 0000000..cb7e5b7
Binary files /dev/null and b/frontend/app_student/assets/images/3il-icon-blue.png differ
diff --git a/frontend/app_student/assets/images/3il-icon-white.png b/frontend/app_student/assets/images/3il-icon-white.png
new file mode 100644
index 0000000..0983585
Binary files /dev/null and b/frontend/app_student/assets/images/3il-icon-white.png differ
diff --git a/frontend/app_student/assets/images/3il-icon.png b/frontend/app_student/assets/images/3il-icon.png
new file mode 100644
index 0000000..5e45b2e
Binary files /dev/null and b/frontend/app_student/assets/images/3il-icon.png differ
diff --git a/frontend/app_student/assets/images/3il-logo-white.jpeg b/frontend/app_student/assets/images/3il-logo-white.jpeg
new file mode 100644
index 0000000..2a2c509
Binary files /dev/null and b/frontend/app_student/assets/images/3il-logo-white.jpeg differ
diff --git a/frontend/app_student/assets/images/eating.svg b/frontend/app_student/assets/images/eating.svg
new file mode 100644
index 0000000..096cb2c
--- /dev/null
+++ b/frontend/app_student/assets/images/eating.svg
@@ -0,0 +1,21 @@
+
+
\ No newline at end of file
diff --git a/frontend/app_student/assets/images/school.svg b/frontend/app_student/assets/images/school.svg
new file mode 100644
index 0000000..09f871f
--- /dev/null
+++ b/frontend/app_student/assets/images/school.svg
@@ -0,0 +1,49 @@
+
+
\ No newline at end of file
diff --git a/frontend/app_student/assets/images/teams.svg b/frontend/app_student/assets/images/teams.svg
new file mode 100644
index 0000000..b61b0cd
--- /dev/null
+++ b/frontend/app_student/assets/images/teams.svg
@@ -0,0 +1,18 @@
+
+
\ No newline at end of file
diff --git a/frontend/app_student/flutter_native_splash.yaml b/frontend/app_student/flutter_native_splash.yaml
new file mode 100644
index 0000000..98a9f47
--- /dev/null
+++ b/frontend/app_student/flutter_native_splash.yaml
@@ -0,0 +1,143 @@
+flutter_native_splash:
+ # This package generates native code to customize Flutter's default white native splash screen
+ # with background color and splash image.
+ # Customize the parameters below, and run the following command in the terminal:
+ # dart run flutter_native_splash:create
+ # To restore Flutter's default white splash screen, run the following command in the terminal:
+ # dart run flutter_native_splash:remove
+
+ # IMPORTANT NOTE: These parameter do not affect the configuration of Android 12 and later, which
+ # handle splash screens differently that prior versions of Android. Android 12 and later must be
+ # configured specifically in the android_12 section below.
+
+ # color or background_image is the only required parameter. Use color to set the background
+ # of your splash screen to a solid color. Use background_image to set the background of your
+ # splash screen to a png image. This is useful for gradients. The image will be stretch to the
+ # size of the app. Only one parameter can be used, color and background_image cannot both be set.
+ color: "#42a5f5"
+ #background_image: "assets/background.png"
+
+ # Optional parameters are listed below. To enable a parameter, uncomment the line by removing
+ # the leading # character.
+
+ # The image parameter allows you to specify an image used in the splash screen. It must be a
+ # png file and should be sized for 4x pixel density.
+ #image: assets/images/3il-logo-white.jpeg
+
+ # The branding property allows you to specify an image used as branding in the splash screen.
+ # It must be a png file. It is supported for Android, iOS and the Web. For Android 12,
+ # see the Android 12 section below.
+ branding: assets/images/3il-logo-white.jpeg
+ # To position the branding image at the bottom of the screen you can use bottom, bottomRight,
+ # and bottomLeft. The default values is bottom if not specified or specified something else.
+ #branding_mode: bottom
+
+ # The color_dark, background_image_dark, image_dark, branding_dark are parameters that set the background
+ # and image when the device is in dark mode. If they are not specified, the app will use the
+ # parameters from above. If the image_dark parameter is specified, color_dark or
+ # background_image_dark must be specified. color_dark and background_image_dark cannot both be
+ # set.
+ #color_dark: "#042a49"
+ #background_image_dark: "assets/dark-background.png"
+ #image_dark: assets/splash-invert.png
+ #branding_dark: assets/dart_dark.png
+
+ # From Android 12 onwards, the splash screen is handled differently than in previous versions.
+ # Please visit https://developer.android.com/guide/topics/ui/splash-screen
+ # Following are specific parameters for Android 12+.
+ android_12:
+ # The image parameter sets the splash screen icon image. If this parameter is not specified,
+ # the app's launcher icon will be used instead.
+ # Please note that the splash screen will be clipped to a circle on the center of the screen.
+ # App icon with an icon background: This should be 960×960 pixels, and fit within a circle
+ # 640 pixels in diameter.
+ # App icon without an icon background: This should be 1152×1152 pixels, and fit within a circle
+ # 768 pixels in diameter.
+ #image: assets/android12splash.png
+
+ # Splash screen background color.
+ #color: "#42a5f5"
+
+ # App icon background color.
+ #icon_background_color: "#111111"
+
+ # The branding property allows you to specify an image used as branding in the splash screen.
+ branding: assets/images/3il-logo-white.jpeg
+
+ # The image_dark, color_dark, icon_background_color_dark, and branding_dark set values that
+ # apply when the device is in dark mode. If they are not specified, the app will use the
+ # parameters from above.
+ #image_dark: assets/android12splash-invert.png
+ #color_dark: "#042a49"
+ #icon_background_color_dark: "#eeeeee"
+
+ # The android, ios and web parameters can be used to disable generating a splash screen on a given
+ # platform.
+ #android: false
+ #ios: false
+ #web: false
+
+ # Platform specific images can be specified with the following parameters, which will override
+ # the respective parameter. You may specify all, selected, or none of these parameters:
+ #color_android: "#42a5f5"
+ #color_dark_android: "#042a49"
+ #color_ios: "#42a5f5"
+ #color_dark_ios: "#042a49"
+ #color_web: "#42a5f5"
+ #color_dark_web: "#042a49"
+ #image_android: assets/splash-android.png
+ #image_dark_android: assets/splash-invert-android.png
+ #image_ios: assets/splash-ios.png
+ #image_dark_ios: assets/splash-invert-ios.png
+ #image_web: assets/splash-web.gif
+ #image_dark_web: assets/splash-invert-web.gif
+ #background_image_android: "assets/background-android.png"
+ #background_image_dark_android: "assets/dark-background-android.png"
+ #background_image_ios: "assets/background-ios.png"
+ #background_image_dark_ios: "assets/dark-background-ios.png"
+ #background_image_web: "assets/background-web.png"
+ #background_image_dark_web: "assets/dark-background-web.png"
+ #branding_android: assets/brand-android.png
+ #branding_dark_android: assets/dart_dark-android.png
+ #branding_ios: assets/brand-ios.png
+ #branding_dark_ios: assets/dart_dark-ios.png
+ #branding_web: assets/brand-web.gif
+ #branding_dark_web: assets/dart_dark-web.gif
+
+ # The position of the splash image can be set with android_gravity, ios_content_mode, and
+ # web_image_mode parameters. All default to center.
+ #
+ # android_gravity can be one of the following Android Gravity (see
+ # https://developer.android.com/reference/android/view/Gravity): bottom, center,
+ # center_horizontal, center_vertical, clip_horizontal, clip_vertical, end, fill, fill_horizontal,
+ # fill_vertical, left, right, start, or top.
+ #android_gravity: center
+ #
+ # ios_content_mode can be one of the following iOS UIView.ContentMode (see
+ # https://developer.apple.com/documentation/uikit/uiview/contentmode): scaleToFill,
+ # scaleAspectFit, scaleAspectFill, center, top, bottom, left, right, topLeft, topRight,
+ # bottomLeft, or bottomRight.
+ #ios_content_mode: center
+ #
+ # web_image_mode can be one of the following modes: center, contain, stretch, and cover.
+ #web_image_mode: center
+
+ # The screen orientation can be set in Android with the android_screen_orientation parameter.
+ # Valid parameters can be found here:
+ # https://developer.android.com/guide/topics/manifest/activity-element#screen
+ #android_screen_orientation: sensorLandscape
+
+ # To hide the notification bar, use the fullscreen parameter. Has no effect in web since web
+ # has no notification bar. Defaults to false.
+ # NOTE: Unlike Android, iOS will not automatically show the notification bar when the app loads.
+ # To show the notification bar, add the following code to your Flutter app:
+ # WidgetsFlutterBinding.ensureInitialized();
+ # SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.bottom, SystemUiOverlay.top], );
+ #fullscreen: true
+
+ # If you have changed the name(s) of your info.plist file(s), you can specify the filename(s)
+ # with the info_plist_files parameter. Remove only the # characters in the three lines below,
+ # do not remove any spaces:
+ #info_plist_files:
+ # - 'ios/Runner/Info-Debug.plist'
+ # - 'ios/Runner/Info-Release.plist'
\ No newline at end of file
diff --git a/frontend/app_student/l10n.yaml b/frontend/app_student/l10n.yaml
new file mode 100644
index 0000000..35d81e9
--- /dev/null
+++ b/frontend/app_student/l10n.yaml
@@ -0,0 +1,3 @@
+arb-dir: lib/l10n
+template-arb-file: app_fr.arb
+output-localization-file: app_localizations.dart
\ No newline at end of file
diff --git a/frontend/app_student/lib/api/users/repositories/user_repository.dart b/frontend/app_student/lib/api/users/repositories/user_repository.dart
new file mode 100644
index 0000000..6f3d76a
--- /dev/null
+++ b/frontend/app_student/lib/api/users/repositories/user_repository.dart
@@ -0,0 +1,57 @@
+import 'package:app_student/api/users/models/user_model.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+
+import '../entities/user_entity.dart';
+
+class UserRepository {
+ Future getUser() async {
+ final SharedPreferences prefs = await SharedPreferences.getInstance();
+
+ String? ine = prefs.getString('ine');
+ String? name = prefs.getString('name');
+ String? birthDate = prefs.getString('birthDate');
+ String? className = prefs.getString('className');
+ if (ine != null && name != null && birthDate != null) {
+ return UserModel(
+ entity: UserEntity(
+ ine: ine,
+ firstName: name,
+ birthDate: DateTime.parse(birthDate),
+ className: className,
+ ),
+ );
+ } else {
+ throw Exception('Utilisateur non trouvé');
+ }
+ }
+
+ Future saveUserDetails(
+ String ine, String name, String birthDate, String className) async {
+ SharedPreferences prefs = await SharedPreferences.getInstance();
+ UserModel(
+ entity: UserEntity(
+ ine: ine,
+ firstName: name,
+ birthDate: DateTime.parse(birthDate),
+ className: className,
+ ),
+ );
+ await prefs.setString('ine', ine);
+ await prefs.setString('name', name);
+ await prefs.setString('birthDate', birthDate);
+ await prefs.setString('className', className);
+ }
+
+ Future deleteUser() async {
+ SharedPreferences prefs = await SharedPreferences.getInstance();
+ await prefs.remove('ine');
+ await prefs.remove('name');
+ await prefs.remove('birthDate');
+ await prefs.remove('className');
+ }
+
+ Future saveUserClass(String className) async {
+ SharedPreferences prefs = await SharedPreferences.getInstance();
+ await prefs.setString('className', className);
+ }
+}
diff --git a/frontend/app_student/lib/class_groups/views/class_group_page.dart b/frontend/app_student/lib/class_groups/views/class_group_page.dart
new file mode 100644
index 0000000..9b4141d
--- /dev/null
+++ b/frontend/app_student/lib/class_groups/views/class_group_page.dart
@@ -0,0 +1,75 @@
+import 'package:app_student/api/class_groups/repositories/class_group_repository.dart';
+import 'package:app_student/class_groups/cubit/class_group_cubit.dart';
+import 'package:app_student/class_groups/views/widgets/card_list.dart';
+import 'package:app_student/class_groups/views/widgets/header/header_logo.dart';
+import 'package:app_student/class_groups/views/widgets/header/header_text.dart';
+import 'package:app_student/class_groups/views/widgets/header/header_title.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:go_router/go_router.dart';
+
+import '../../api/users/models/user_model.dart';
+import '../../api/users/repositories/user_repository.dart';
+
+class ClassGroupPage extends StatelessWidget {
+ const ClassGroupPage({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final classRepository =
+ RepositoryProvider.of(context);
+ final userRepository = RepositoryProvider.of(context);
+ final classCubit = ClassGroupCubit(
+ classRepository: classRepository, userRepository: userRepository);
+
+ return BlocProvider(
+ create: (context) => classCubit..fetchClasses(),
+ child: FutureBuilder(
+ future: context.read().getConnectedUser(),
+ builder: (context, snapshot) {
+ if (snapshot.connectionState == ConnectionState.waiting) {
+ return const Center(child: CircularProgressIndicator());
+ } else if (snapshot.hasError) {
+ return Center(
+ child: Text(AppLocalizations.of(context)!
+ .genericError(snapshot.error.toString())));
+ } else {
+ final user = snapshot.data;
+ return Scaffold(
+ body: BlocBuilder(
+ builder: (context, state) {
+ if (state is ClassGroupLoading) {
+ return const Center(child: CircularProgressIndicator());
+ } else if (state is ClassGroupSelected) {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ context.go('/schedule');
+ });
+ return const SizedBox.shrink();
+ } else if (state is ClassGroupLoaded) {
+ return Column(
+ children: [
+ const HeaderLogo(),
+ HeaderTitle(AppLocalizations.of(context)!
+ .classSelectionTitle(user!.name)),
+ HeaderText(AppLocalizations.of(context)!
+ .classSelectionSubtitle),
+ Expanded(
+ child: CardList(classesList: state.classes),
+ ),
+ ],
+ );
+ } else if (state is ClassGroupError) {
+ return Center(child: Text(state.message));
+ } else {
+ return const SizedBox.shrink();
+ }
+ },
+ ),
+ );
+ }
+ },
+ ),
+ );
+ }
+}
diff --git a/frontend/app_student/lib/class_groups/views/widgets/card_list.dart b/frontend/app_student/lib/class_groups/views/widgets/card_list.dart
new file mode 100644
index 0000000..c20ecb0
--- /dev/null
+++ b/frontend/app_student/lib/class_groups/views/widgets/card_list.dart
@@ -0,0 +1,31 @@
+import 'package:app_student/api/class_groups/models/class_group_model.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import '../../cubit/class_group_cubit.dart';
+
+class CardList extends StatelessWidget {
+ final List classesList;
+
+ const CardList({super.key, required this.classesList});
+
+ @override
+ Widget build(BuildContext context) {
+ return ListView.builder(
+ itemCount: classesList.length,
+ itemBuilder: (context, index) {
+ return Card(
+ margin: const EdgeInsets.only(left: 25.0, right: 25.0, top: 10.0),
+ child: ListTile(
+ title: Text(
+ classesList[index].name,
+ ),
+ onTap: () {
+ context.read().saveClass(classesList[index]);
+ },
+ ),
+ );
+ },
+ );
+ }
+}
diff --git a/frontend/app_student/lib/class_groups/views/widgets/header/header_logo.dart b/frontend/app_student/lib/class_groups/views/widgets/header/header_logo.dart
new file mode 100644
index 0000000..3aa3ab3
--- /dev/null
+++ b/frontend/app_student/lib/class_groups/views/widgets/header/header_logo.dart
@@ -0,0 +1,21 @@
+import 'package:flutter/material.dart';
+
+class HeaderLogo extends StatelessWidget {
+ const HeaderLogo({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return AppBar(
+ backgroundColor: const Color(0xFF005067),
+ toolbarHeight: 70.0,
+ title: Opacity(
+ opacity: 0.5,
+ child: Image.asset(
+ 'assets/images/3il-icon-white.png',
+ fit: BoxFit.contain,
+ ),
+ ),
+ centerTitle: true,
+ );
+ }
+}
diff --git a/frontend/app_student/lib/class_groups/views/widgets/header/header_text.dart b/frontend/app_student/lib/class_groups/views/widgets/header/header_text.dart
new file mode 100644
index 0000000..ff6d4b2
--- /dev/null
+++ b/frontend/app_student/lib/class_groups/views/widgets/header/header_text.dart
@@ -0,0 +1,25 @@
+import 'package:flutter/cupertino.dart';
+
+class HeaderText extends StatelessWidget {
+ final String content;
+
+ const HeaderText(this.content, {super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Padding(
+ padding: const EdgeInsets.only(top: 5.0, left: 25.0),
+ child: Align(
+ alignment: Alignment.centerLeft,
+ child: Text(
+ content,
+ style: const TextStyle(
+ fontSize: 18.0,
+ fontFamily: 'Arial',
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/frontend/app_student/lib/class_groups/views/widgets/header/header_title.dart b/frontend/app_student/lib/class_groups/views/widgets/header/header_title.dart
new file mode 100644
index 0000000..35f3e0a
--- /dev/null
+++ b/frontend/app_student/lib/class_groups/views/widgets/header/header_title.dart
@@ -0,0 +1,25 @@
+import 'package:flutter/cupertino.dart';
+
+class HeaderTitle extends StatelessWidget {
+ final String content;
+
+ const HeaderTitle(this.content, {super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Padding(
+ padding: const EdgeInsets.only(top: 20.0, left: 25.0, bottom: 2),
+ child: Align(
+ alignment: Alignment.centerLeft,
+ child: Text(
+ content,
+ style: const TextStyle(
+ fontSize: 34.0,
+ fontFamily: 'Arial',
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/frontend/app_student/lib/generated/assets.dart b/frontend/app_student/lib/generated/assets.dart
new file mode 100644
index 0000000..670f1c5
--- /dev/null
+++ b/frontend/app_student/lib/generated/assets.dart
@@ -0,0 +1,9 @@
+///This file is automatically generated. DO NOT EDIT, all your changes would be lost.
+class Assets {
+ Assets._();
+
+ static const String images3ilLogo = 'assets/images/3il-logo.jpg';
+ static const String imagesCalendar = 'assets/images/calendar.svg';
+ static const String imagesDisconnect = 'assets/images/disconnect.svg';
+ static const String imagesProfil = 'assets/images/profil.svg';
+}
diff --git a/frontend/app_student/lib/l10n/app_fr.arb b/frontend/app_student/lib/l10n/app_fr.arb
new file mode 100644
index 0000000..57e0c37
--- /dev/null
+++ b/frontend/app_student/lib/l10n/app_fr.arb
@@ -0,0 +1,72 @@
+{
+ "error404": "Page non trouvée {pageUri}",
+ "@error404": {
+ "description": "Message d'erreur pour une page non trouvée",
+ "placeholders": {
+ "pageUri": {
+ "type": "String",
+ "example": "/login"
+ }
+ }
+ },
+ "genericError": "Une erreur est survenue",
+ "@genericError": {
+ "description": "Message d'erreur générique",
+ "placeholders": {
+ "error": {
+ "type": "String",
+ "example": "Une erreur est survenue"
+ }
+ }
+ },
+ "loginButton": "Connexion",
+ "@loginButton": {
+ "description": "Texte du bouton de connexion"
+ },
+ "loginFirstNameLabel": "Prénom",
+ "@loginFirstName": {
+ "description": "Texte du label pour le prénom"
+ },
+ "loginFirstNameHint": "Entrez votre prénom",
+ "@loginFirstNameHint": {
+ "description": "Texte de l'attribut placeholder pour le prénom"
+ },
+ "loginIneLabel": "INE",
+ "@loginIneLabel": {
+ "description": "Texte du label pour le numéro INE"
+ },
+ "loginIneHint": "Entrez votre numéro INE",
+ "@loginIneHint": {
+ "description": "Texte de l'attribut placeholder pour le numéro INE"
+ },
+ "loginBirthDateLabel": "Date de naissance",
+ "@loginBirthDateLabel": {
+ "description": "Texte du label pour la date de naissance"
+ },
+ "loginWelcomeTitle": "Bonjour :)",
+ "@loginWelcomeTitle": {
+ "description": "Texte d'accueil de la page de connexion"
+ },
+ "loginWelcomeTitleError": "Oops, ca va aller",
+ "@loginWelcomeTitleError": {
+ "description": "Texte d'erreur d'accueil de la page de connexion"
+ },
+ "loginFieldError": "Veuillez remplir tous les champs",
+ "@loginFieldError": {
+ "description": "Message d'erreur pour les champs de connexion"
+ },
+ "classSelectionTitle": "Salut {firstName} !",
+ "@classSelectionTitle": {
+ "description": "Texte d'accueil de la page de sélection de classe",
+ "placeholders": {
+ "firstName": {
+ "type": "String",
+ "example": "John"
+ }
+ }
+ },
+ "classSelectionSubtitle": "Sélectionne ta classe",
+ "@classSelectionSubtitle": {
+ "description": "Texte de sous-titre de la page de sélection de classe"
+ }
+}
\ No newline at end of file
diff --git a/frontend/app_student/lib/routes.dart b/frontend/app_student/lib/routes.dart
new file mode 100644
index 0000000..f0417d9
--- /dev/null
+++ b/frontend/app_student/lib/routes.dart
@@ -0,0 +1,75 @@
+// lib/routes.dart
+import 'package:app_student/api/api_service.dart';
+import 'package:app_student/api/class_groups/repositories/class_group_repository.dart';
+import 'package:app_student/api/users/repositories/user_repository.dart';
+import 'package:app_student/api/week_schedule/repositories/week_schedule_repository.dart';
+import 'package:app_student/class_groups/cubit/class_group_cubit.dart';
+import 'package:app_student/config/config.dart';
+import 'package:app_student/week_schedule/cubit/week_schedule_cubit.dart';
+import 'package:app_student/week_schedule/views/week_schedule.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:go_router/go_router.dart';
+
+import 'class_groups/views/class_group_page.dart';
+import 'login/cubit/login_cubit.dart';
+import 'login/views/login_page.dart';
+
+class AppRoutes {
+ static const classListPage = '/classList';
+ static const loginPage = '/login';
+ static const schedulePage = '/schedule';
+
+ static final routes = [
+ GoRoute(
+ path: classListPage,
+ pageBuilder: (context, state) => MaterialPage(
+ key: state.pageKey,
+ child: MultiRepositoryProvider(
+ providers: [
+ RepositoryProvider(
+ create: (context) => ClassGroupRepository(
+ apiService: ApiService(
+ apiUrl: context.read().apiUrl))),
+ RepositoryProvider(create: (context) => UserRepository()),
+ ],
+ child: BlocProvider(
+ create: (context) => ClassGroupCubit(
+ classRepository: context.read(),
+ userRepository: context.read()),
+ child: const ClassGroupPage())))),
+ GoRoute(
+ path: loginPage,
+ pageBuilder: (context, state) => MaterialPage(
+ key: state.pageKey,
+ child: RepositoryProvider(
+ create: (context) => UserRepository(),
+ child: BlocProvider(
+ create: (context) => LoginCubit(context.read()),
+ child: const LoginPage(),
+ ),
+ ),
+ ),
+ ),
+ GoRoute(
+ path: schedulePage,
+ pageBuilder: (context, state) => MaterialPage(
+ key: state.pageKey,
+ child: MultiRepositoryProvider(
+ providers: [
+ RepositoryProvider(create: (context) {
+ return WeekScheduleRepository(
+ apiService:
+ ApiService(apiUrl: context.read().apiUrl));
+ }),
+ RepositoryProvider(create: (context) => UserRepository()),
+ ],
+ child: BlocProvider(
+ create: (context) => WeekScheduleCubit(
+ weekScheduleRepository:
+ context.read(),
+ userRepository: context.read(),
+ ),
+ child: const WeekSchedulePage())))),
+ ];
+}
diff --git a/frontend/app_student/lib/week_schedule/views/widgets/components/custom_appbar.dart b/frontend/app_student/lib/week_schedule/views/widgets/components/custom_appbar.dart
new file mode 100644
index 0000000..bb524d4
--- /dev/null
+++ b/frontend/app_student/lib/week_schedule/views/widgets/components/custom_appbar.dart
@@ -0,0 +1,23 @@
+import 'package:app_student/week_schedule/views/widgets/components/datepicker_button.dart';
+import 'package:flutter/material.dart';
+
+class AppBarWeekSchedule extends StatelessWidget
+ implements PreferredSizeWidget {
+ const AppBarWeekSchedule({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return AppBar(
+ backgroundColor: const Color(0xFF005067),
+ leading: Image.asset('assets/images/3il-logo.jpg'),
+ title: const Center(
+ child: Text('Classe Name', style: TextStyle(color: Colors.white))),
+ actions: const [
+ DatePickerButton(),
+ ],
+ );
+ }
+
+ @override
+ Size get preferredSize => const Size.fromHeight(70.0);
+}
diff --git a/frontend/app_student/lib/week_schedule/views/widgets/components/datepicker_button.dart b/frontend/app_student/lib/week_schedule/views/widgets/components/datepicker_button.dart
new file mode 100644
index 0000000..73e05d3
--- /dev/null
+++ b/frontend/app_student/lib/week_schedule/views/widgets/components/datepicker_button.dart
@@ -0,0 +1,23 @@
+import 'package:flutter/material.dart';
+
+class DatePickerButton extends StatelessWidget {
+ const DatePickerButton({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return IconButton(
+ icon: const Icon(Icons.calendar_month, color: Colors.white),
+ onPressed: () async {
+ final date = await showDatePicker(
+ context: context,
+ initialDate: DateTime.now(),
+ firstDate: DateTime(2000),
+ lastDate: DateTime(2100),
+ );
+ if (date != null) {
+ // Utilisez la date sélectionnée
+ }
+ },
+ );
+ }
+}
diff --git a/frontend/app_student/lib/week_schedule/views/widgets/events/event_card.dart b/frontend/app_student/lib/week_schedule/views/widgets/events/event_card.dart
new file mode 100644
index 0000000..c800d90
--- /dev/null
+++ b/frontend/app_student/lib/week_schedule/views/widgets/events/event_card.dart
@@ -0,0 +1,81 @@
+import 'package:app_student/api/events/models/event_model.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/svg.dart';
+
+class EventCard extends StatelessWidget {
+ const EventCard({
+ super.key,
+ required this.event,
+ });
+
+ final EventModel event;
+
+ @override
+ Widget build(BuildContext context) {
+ return Card(
+ color: const Color(0xFF007A8D).withOpacity(0.3),
+ child: Container(
+ decoration: const BoxDecoration(
+ border: Border(
+ left: BorderSide(
+ color: Color(0xFF005067),
+ width: 10.0,
+ ),
+ ),
+ ),
+ width: 300,
+ height: 90,
+ child: Padding(
+ padding:
+ const EdgeInsets.only(left: 20.0, right: 20, bottom: 3, top: 3),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: event.creneau == 3
+ ? MainAxisAlignment.center
+ : MainAxisAlignment.spaceEvenly,
+ children: event.creneau == 3
+ ? [
+ Center(
+ child: ColorFiltered(
+ colorFilter: const ColorFilter.mode(
+ Colors.white, BlendMode.srcIn),
+ child: SvgPicture.asset(
+ 'assets/images/eating.svg',
+ width: 40,
+ height: 40,
+ ),
+ ),
+ )
+ ]
+ : [
+ const Text('1h30',
+ style: TextStyle(color: Colors.white, fontSize: 12)),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(event.activite,
+ style: const TextStyle(
+ fontSize: 18, fontWeight: FontWeight.bold)),
+ ColorFiltered(
+ colorFilter: const ColorFilter.mode(
+ Colors.white, BlendMode.srcIn),
+ child: SvgPicture.asset(
+ event.visio
+ ? 'assets/images/teams.svg'
+ : 'assets/images/school.svg',
+ width: 40,
+ height: 40,
+ ),
+ ),
+ ],
+ ),
+ Text('Salle ${event.salle}',
+ style: const TextStyle(
+ fontSize: 15, fontWeight: FontWeight.bold)),
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/frontend/app_student/lib/week_schedule/views/widgets/events/event_details.dart b/frontend/app_student/lib/week_schedule/views/widgets/events/event_details.dart
new file mode 100644
index 0000000..d61ad2d
--- /dev/null
+++ b/frontend/app_student/lib/week_schedule/views/widgets/events/event_details.dart
@@ -0,0 +1,21 @@
+import 'package:app_student/api/events/models/event_model.dart';
+import 'package:app_student/week_schedule/views/widgets/events/event_card.dart';
+import 'package:app_student/week_schedule/views/widgets/events/event_hours.dart';
+import 'package:flutter/material.dart';
+
+class EventDetails extends StatelessWidget {
+ final EventModel event;
+
+ const EventDetails({super.key, required this.event});
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ EventHours(event: event),
+ EventCard(event: event),
+ ],
+ );
+ }
+}
diff --git a/frontend/app_student/lib/week_schedule/views/widgets/events/event_hours.dart b/frontend/app_student/lib/week_schedule/views/widgets/events/event_hours.dart
new file mode 100644
index 0000000..93c8228
--- /dev/null
+++ b/frontend/app_student/lib/week_schedule/views/widgets/events/event_hours.dart
@@ -0,0 +1,26 @@
+import 'package:app_student/api/events/models/event_model.dart';
+import 'package:flutter/material.dart';
+
+class EventHours extends StatelessWidget {
+ const EventHours({
+ super.key,
+ required this.event,
+ });
+
+ final EventModel event;
+
+ @override
+ Widget build(BuildContext context) {
+ return SizedBox(
+ width: 50,
+ child: Column(
+ children: [
+ Text(event.horaires.startAt,
+ style: const TextStyle(fontWeight: FontWeight.bold)),
+ Text(event.horaires.endAt,
+ style: const TextStyle(fontWeight: FontWeight.bold)),
+ ],
+ ),
+ );
+ }
+}
diff --git a/frontend/app_student/pubspec.lock b/frontend/app_student/pubspec.lock
index 4d39df3..21eeab5 100644
--- a/frontend/app_student/pubspec.lock
+++ b/frontend/app_student/pubspec.lock
@@ -102,6 +102,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "8.1.4"
+ flutter_dotenv:
+ dependency: "direct main"
+ description:
+ name: flutter_dotenv
+ sha256: "9357883bdd153ab78cbf9ffa07656e336b8bbb2b5a3ca596b0b27e119f7c7d77"
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.1.0"
flutter_lints:
dependency: "direct dev"
description:
@@ -110,6 +118,11 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.1"
+ flutter_localizations:
+ dependency: "direct main"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
flutter_svg:
dependency: "direct main"
description:
@@ -128,6 +141,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
+ go_router:
+ dependency: "direct main"
+ description:
+ name: go_router
+ sha256: "170c46e237d6eb0e6e9f0e8b3f56101e14fb64f787016e42edd74c39cf8b176a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "13.2.0"
http:
dependency: "direct main"
description:
@@ -144,6 +165,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.2"
+ intl:
+ dependency: "direct main"
+ description:
+ name: intl
+ sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.18.1"
leak_tracker:
dependency: transitive
description:
@@ -176,6 +205,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.0"
+ logging:
+ dependency: transitive
+ description:
+ name: logging
+ sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.0"
matcher:
dependency: transitive
description:
diff --git a/frontend/app_student/pubspec.yaml b/frontend/app_student/pubspec.yaml
index 68f785d..3f05856 100644
--- a/frontend/app_student/pubspec.yaml
+++ b/frontend/app_student/pubspec.yaml
@@ -42,6 +42,11 @@ dependencies:
flutter_bloc: ^8.1.4
meta: ^1.11.0
flutter_svg: ^2.0.10+1
+ go_router: ^13.2.0
+ flutter_localizations:
+ sdk: flutter
+ intl: any
+ flutter_dotenv: ^5.1.0
dev_dependencies:
flutter_test:
@@ -59,7 +64,7 @@ dev_dependencies:
# The following section is specific to Flutter packages.
flutter:
-
+ generate: true
# 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.
@@ -72,6 +77,7 @@ flutter:
assets:
- assets/images/
+ - .env
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware
@@ -95,5 +101,11 @@ flutter:
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
+
+ fonts:
+ - family: Arial
+ fonts:
+ - asset: assets/fonts/arial.ttf
+
# For details regarding fonts from package dependencies,
- # see https://flutter.dev/custom-fonts/#from-packages
+ # see https://flutter.dev/custom-fonts/#from-packages
\ No newline at end of file