Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/beca alimentacion #46

Draft
wants to merge 10 commits into
base: feat/user-role-controller
Choose a base branch
from
8 changes: 6 additions & 2 deletions lib/config/routes/router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import 'package:flutter/material.dart';
import 'package:get/route_manager.dart';
import 'package:mi_utem/config/routes/routes.dart';
import 'package:mi_utem/controllers/asignaturas_controller.dart';
import 'package:mi_utem/controllers/qr_passes_controller.dart';
import 'package:mi_utem/controllers/user_controller.dart';
import 'package:mi_utem/screens/asignatura/asignatura_detalle_screen.dart';
import 'package:mi_utem/screens/asignatura/asignaturas_lista_screen.dart';
import 'package:mi_utem/screens/calculadora_notas_screen.dart';
import 'package:mi_utem/screens/credencial_screen.dart';
import 'package:mi_utem/screens/horario/horario_screen.dart';
import 'package:mi_utem/screens/login_screen/login_screen.dart';
import 'package:mi_utem/screens/lunch_benefit/lunch_benefit_screen.dart';
import 'package:mi_utem/screens/main/main_screen.dart';
import 'package:mi_utem/screens/permiso_covid_screen.dart';
import 'package:mi_utem/screens/splash_screen.dart';
Expand All @@ -24,7 +24,6 @@ final _loginPage = GetPage(

final _homePage = GetPage(
name: Routes.home,
bindings: [QrPassesBinding()],
page: () => MainScreen(),
middlewares: [OnlyAuthMiddleware()],
);
Expand Down Expand Up @@ -76,6 +75,11 @@ final pages = <GetPage>[
page: () => PermisoCovidScreen(),
middlewares: [OnlyAuthMiddleware()],
),
GetPage(
name: Routes.lunchBenefit,
page: () => LunchBenefitScreen(),
middlewares: [OnlyAuthMiddleware()],
),
];

class OnlyAuthMiddleware extends GetMiddleware {
Expand Down
1 change: 1 addition & 0 deletions lib/config/routes/routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class Routes {
static const calculadoraNotas = '/calculadora-notas';
static const imageView = '/image-view';
static const asignatura = '/asignatura';
static const lunchBenefit = '/lunch-benefit';

static const passBase = '/pass';
static const passParameter = 'passId';
Expand Down
9 changes: 7 additions & 2 deletions lib/controllers/carreras_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class CarrerasController extends GetxController with StateMixin<List<Carrera>> {
final carreras = await CarreraService.getCarreras(forceRefresh: true);

change(carreras, status: RxStatus.success());
updateUserCarrerasRoles();
_autoSelectCarreraActiva(carreras);
}

Expand All @@ -45,10 +46,14 @@ class CarrerasController extends GetxController with StateMixin<List<Carrera>> {

AnalyticsService.setCarreraToUser(activa);

changeSelectedCarrera(activa);
changeUserSelectedCarrera(activa);
}

void changeSelectedCarrera(Carrera carrera) {
void updateUserCarrerasRoles() {
UserController.to.updateCarrerasRoles(state);
}

void changeUserSelectedCarrera(Carrera carrera) {
UserController.to.selectCarrera(carrera);
}
}
134 changes: 134 additions & 0 deletions lib/controllers/lunch_coupons_controller.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import 'dart:developer';

import 'package:dio/dio.dart';
import 'package:get/get.dart';
import 'package:mi_utem/controllers/user_controller.dart';
import 'package:mi_utem/models/lunch_coupon.dart';
import 'package:mi_utem/models/usuario.dart';
import 'package:mi_utem/services/lunch_coupons_service.dart';

class LunchBenefit {
final List<LunchCoupon> coupons;
final bool hasBenefit;

LunchCoupon? get todayCoupon {
return coupons.firstWhereOrNull(
(element) => element.isForToday,
);
}

List<LunchCoupon> get otherAvailableOrderedCoupons {
final now = DateTime.now();
final otherCoupons =
coupons.where((element) => element.validFor.isAfter(now)).toList();

otherCoupons.sort((a, b) => a.validFor.compareTo(b.validFor));
return otherCoupons;
}

LunchBenefit({
this.coupons = const [],
required this.hasBenefit,
});
}

class LunchBenefitController extends GetxController
with StateMixin<LunchBenefit> {
static LunchBenefitController get to => Get.find();

@override
void onInit() {
ever<Usuario?>(
Get.find<UserController>().user,
(carrera) => getBenefit(),
);

getBenefit();
super.onInit();
}

void getBenefit() async {
log("LunchBenefitController getBenefit");

change(null, status: RxStatus.loading());

log("LunchBenefitController getBenefit 2");

try {
final coupons = await LunchCouponsService.getAll();
log("LunchBenefitController coupons ${coupons.length}");

final lunchBenefit = LunchBenefit(
coupons: coupons,
hasBenefit: true,
);

change(
lunchBenefit,
status: RxStatus.success(),
);
} on DioError catch (e) {
log("LunchBenefitController catch DioError ${e.toString()}");
final response = e.response;
if (response != null && response.statusCode == 404) {
final lunchBenefit = LunchBenefit(
coupons: [],
hasBenefit: false,
);

change(
lunchBenefit,
status: RxStatus.success(),
);
}
} catch (e) {
log("LunchBenefitController catch ${e.toString()}");
change(
null,
status: RxStatus.error(e.toString()),
);
} finally {
_setRoleToUser();
}
}

Future<void> generateTodayCoupon() async {
try {
final coupons = await LunchCouponsService.generate();

final lunchBenefit = LunchBenefit(
coupons: coupons,
hasBenefit: true,
);

change(
lunchBenefit,
status: RxStatus.success(),
);
} on DioError catch (e) {
final response = e.response;
if (response != null && response.statusCode == 404) {
final lunchBenefit = LunchBenefit(
coupons: [],
hasBenefit: false,
);

change(
lunchBenefit,
status: RxStatus.success(),
);
}
} catch (e) {
change(
null,
status: RxStatus.error(e.toString()),
);
} finally {
_setRoleToUser();
}
}

void _setRoleToUser() {
UserController.to.updateLunchBenefitRole(state);
}
}
7 changes: 0 additions & 7 deletions lib/controllers/qr_passes_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,3 @@ class QrPassesController extends GetxController {
}
}
}

class QrPassesBinding extends Bindings {
@override
void dependencies() {
Get.put(QrPassesController());
}
}
68 changes: 50 additions & 18 deletions lib/controllers/user_controller.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import 'dart:async';
import 'dart:convert';
import 'dart:developer';

import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:mi_utem/controllers/carreras_controller.dart';
import 'package:mi_utem/controllers/lunch_coupons_controller.dart';
import 'package:mi_utem/models/carrera.dart';
import 'package:mi_utem/models/usuario.dart';
import 'package:mi_utem/services/analytics_service.dart';
Expand All @@ -23,23 +25,9 @@ class UserController extends GetxController {

final user = Rxn<Usuario>(null);
final selectedCarrera = Rxn<Carrera>();
final roles = RxList<Role>([]);

List<Role> get roles {
final roles = <Role>[];

if (user.value != null) {
final carreras = CarrerasController.to.state;
if (carreras != null && carreras.length > 0) {
roles.add(Role.hasCareers);
final hasActive = carreras.firstWhereOrNull((c) => c.isActive) != null;

if (hasActive) {
roles.add(Role.hasActiveCareer);
}
}
}
return roles;
}
FutureOr<String?>? _tokenRefresher;

@override
void onInit() {
Expand Down Expand Up @@ -98,14 +86,34 @@ class UserController extends GetxController {
}

Future<String> refreshToken() async {
log("refreshToken");

if (_tokenRefresher != null) {
log("refreshToken _tokenRefresher != null $_tokenRefresher");
final token = await (_tokenRefresher as FutureOr<String>);

log("refreshToken _tokenRefresher != null token $token");

return token;
}

log("refreshToken _tokenRefresher == null");

try {
final email = user.value?.correoUtem;
final password = await _secureStorage.read(key: _storagePasswordKey);

log("refreshToken _tokenRefresher == null email $email password $password");

if (email != null && password != null) {
final token = await AuthService.refreshToken(email, password);
_tokenRefresher = AuthService.refreshToken(email, password);
final token = await (_tokenRefresher as FutureOr<String>);
_storeToken(token);

_tokenRefresher = null;

log("refreshToken _tokenRefresher == null token $token");

return token;
}
throw Exception("No se pudo refrescar el token");
Expand Down Expand Up @@ -151,4 +159,28 @@ class UserController extends GetxController {
void selectCarrera(Carrera carrera) {
selectedCarrera.value = carrera;
}

void updateCarrerasRoles(List<Carrera>? carreras) {
final user = this.user.value;

final roles = <Role>[];

if (user != null) {
if (carreras != null && carreras.length > 0) {
roles.add(Role.hasCareers);
final hasActive = carreras.firstWhereOrNull((c) => c.isActive) != null;

if (hasActive) {
roles.add(Role.hasActiveCareer);
}
}
}
this.roles.value = roles;
}

void updateLunchBenefitRole(LunchBenefit? lunchBenefit) {
if (lunchBenefit?.hasBenefit == true) {
roles.add(Role.hasLunchBenefit);
}
}
}
39 changes: 39 additions & 0 deletions lib/helpers/image.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import 'package:barcode_image/barcode_image.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:image/image.dart' as dartImage;
import 'package:mi_utem/config/routes/routes.dart';
import 'package:mi_utem/widgets/image_view_screen.dart';

void openBarcodeView(
String code, {
required Size size,
EdgeInsets padding = const EdgeInsets.all(25),
String? heroTag,
Barcode? type,
}) {
final image = dartImage.Image(size.width.toInt(), size.height.toInt());

dartImage.fill(image, dartImage.getColor(255, 255, 255));
drawBarcode(
image,
type ?? Barcode.qrCode(),
code,
x: padding.left.toInt(),
y: padding.top.toInt(),
width: (size.width - padding.horizontal).toInt(),
height: (size.height - padding.vertical).toInt(),
);

Uint8List data = Uint8List.fromList(dartImage.encodePng(image));

Get.to(
() => ImageViewScreen(
imageProvider: MemoryImage(data),
heroTag: heroTag,
occlude: true,
),
routeName: Routes.imageView,
);
}
5 changes: 4 additions & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import 'package:get_storage/get_storage.dart';
import 'package:mi_utem/config/constants.dart';
import 'package:mi_utem/config/routes/router.dart';
import 'package:mi_utem/config/routes/routes.dart';
import 'package:mi_utem/controllers/asignatura_controller.dart';
import 'package:mi_utem/controllers/calculator_controller.dart';
import 'package:mi_utem/controllers/carreras_controller.dart';
import 'package:mi_utem/controllers/lunch_coupons_controller.dart';
import 'package:mi_utem/controllers/qr_passes_controller.dart';
import 'package:mi_utem/controllers/user_controller.dart';
import 'package:mi_utem/services/background_service.dart';
import 'package:mi_utem/services/notification_service.dart';
Expand Down Expand Up @@ -64,6 +65,8 @@ class MiUtem extends StatelessWidget {
initialBinding: BindingsBuilder(() {
Get.put(UserController(), permanent: true);
Get.put(CarrerasController(), permanent: true);
Get.put(LunchBenefitController(), permanent: true);
Get.put(QrPassesController(), permanent: true);
Get.put(CalculatorController(), permanent: true);
}),
theme: MainTheme.theme,
Expand Down
Loading