From 377e4e099dc45c003d01378a0cdf7d84dd48c9bd Mon Sep 17 00:00:00 2001 From: Francisco Solis <30329003+Im-Fran@users.noreply.github.com> Date: Tue, 11 Aug 2026 11:28:17 -0400 Subject: [PATCH] =?UTF-8?q?feat:=20se=20agrega=20feature=20flags=20al=20ac?= =?UTF-8?q?ceso=20r=C3=A1pido=20(#142)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- .../firebase/remote_config_service.dart | 6 ++ .../asignaturas/widgets/acceso_rapido.dart | 3 + lib/screens/home/widgets/acceso_rapido.dart | 3 + lib/styles/cards/card_acceso_rapido.dart | 75 ++++++++++++------- pubspec.yaml | 2 +- 5 files changed, 63 insertions(+), 26 deletions(-) diff --git a/lib/core/services/firebase/remote_config_service.dart b/lib/core/services/firebase/remote_config_service.dart index e3234f4..c64da02 100644 --- a/lib/core/services/firebase/remote_config_service.dart +++ b/lib/core/services/firebase/remote_config_service.dart @@ -19,6 +19,12 @@ final remoteConfigDefaults = { "apuntes": false, "perfil": true, }, + "acceso_rapido": { + "horario": {"enabled": true}, + "calculadora": {"enabled": true}, + "novedades": {"enabled": true}, + "malla_historica": {"enabled": true}, + }, "profile": { "notificaciones": true, "bug_report": true, diff --git a/lib/screens/asignaturas/widgets/acceso_rapido.dart b/lib/screens/asignaturas/widgets/acceso_rapido.dart index ef71a08..f0ac20c 100644 --- a/lib/screens/asignaturas/widgets/acceso_rapido.dart +++ b/lib/screens/asignaturas/widgets/acceso_rapido.dart @@ -17,6 +17,7 @@ class AccesoRapido extends StatelessWidget { colorDark: AppTheme.darkBlueCard, label: "Horario", icon: AppIcons.timetable, + flagKey: "horario", onTap: () => visitarHorario(context), ), CardAccesoRapido( @@ -25,6 +26,7 @@ class AccesoRapido extends StatelessWidget { label: "Notas", icon: AppIcons.calculator, fill: 0, + flagKey: "calculadora", onTap: () => visitarCalculadoraNotas(context), ), if (showEstudianteActions) @@ -34,6 +36,7 @@ class AccesoRapido extends StatelessWidget { label: "Malla Histórica", icon: AppIcons.historicTimetable, fill: 0, + flagKey: "malla_historica", onTap: () => visitarMallaHistorica(context), ), ]; diff --git a/lib/screens/home/widgets/acceso_rapido.dart b/lib/screens/home/widgets/acceso_rapido.dart index c1f39a7..a4c567c 100644 --- a/lib/screens/home/widgets/acceso_rapido.dart +++ b/lib/screens/home/widgets/acceso_rapido.dart @@ -21,6 +21,7 @@ Widget build(BuildContext context) { colorDark: AppTheme.darkBlueCard, label: "Horario", icon: AppIcons.timetable, + flagKey: "horario", onTap: () => visitarHorario(context), ), CardAccesoRapido( @@ -29,6 +30,7 @@ Widget build(BuildContext context) { label: "Notas", icon: AppIcons.calculator, fill: 0, + flagKey: "calculadora", onTap: () => visitarNotas(context), ), CardAccesoRapido( @@ -37,6 +39,7 @@ Widget build(BuildContext context) { label: "Novedades", icon: AppIcons.updates, fill: 0, + flagKey: "novedades", onTap: () => visitarNovedades(context), ), ]; diff --git a/lib/styles/cards/card_acceso_rapido.dart b/lib/styles/cards/card_acceso_rapido.dart index ba96f99..f4f7f5f 100644 --- a/lib/styles/cards/card_acceso_rapido.dart +++ b/lib/styles/cards/card_acceso_rapido.dart @@ -1,6 +1,7 @@ import "package:adaptive_theme/adaptive_theme.dart"; import "package:flutter/material.dart"; import "package:miutem/core/utils/utilities.dart"; +import "package:miutem/widgets/feature_flag.dart"; class CardAccesoRapido extends StatelessWidget { final Color color, colorDark; @@ -9,35 +10,59 @@ class CardAccesoRapido extends StatelessWidget { final Function() onTap; final double fill; - const CardAccesoRapido({super.key, required this.color, required this.label, required this.icon, required this.onTap, required this.colorDark, this.fill = 1.0}); + /// Clave del feature flag dentro de `acceso_rapido` en Remote Config (ej: "horario"). + /// Si la característica está desactivada, la tarjeta se ve opaca y al tocarla + /// muestra el motivo definido en `acceso_rapido..reason`. + final String? flagKey; + + const CardAccesoRapido({super.key, required this.color, required this.label, required this.icon, required this.onTap, required this.colorDark, this.fill = 1.0, this.flagKey}); + + bool get _isEnabled => flagKey == null || FeatureFlag.evaluateSync("acceso_rapido.$flagKey.enabled"); + + void _mostrarMotivo(BuildContext context) => showDialog( + context: context, + builder: (ctx) => AlertDialog( + icon: const Icon(Icons.info_outline_rounded), + title: Text(FeatureFlag.getString("acceso_rapido.$flagKey.reason.title", defaultValue: "$label no está disponible")), + content: Text(FeatureFlag.getString("acceso_rapido.$flagKey.reason.message", defaultValue: "Desactivamos temporalmente esta característica. Inténtalo más tarde.")), + actions: [ + TextButton(onPressed: () => Navigator.of(ctx).pop(), child: const Text("Entendido")), + ], + ), + ); @override - Widget build(BuildContext context) => GestureDetector( - onTap: onTap, - child: ValueListenableBuilder( - valueListenable: AdaptiveTheme.of(context).modeChangeNotifier, - builder: (ctx, mode, child) => DecoratedBox( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(14), - color: themedColor(context, light: color, dark: colorDark), - ), - child: SizedBox( - height: 120, - child: Padding( - padding: const EdgeInsets.fromLTRB(12,20,12,20), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Icon(icon, fill: fill, size: 32, weight: 600, color: Theme.of(context).textTheme.bodyMedium?.color), - const Spacer(), - Text(label, style: Theme.of(context).textTheme.labelMedium), - ], + Widget build(BuildContext context) { + final enabled = _isEnabled; + return GestureDetector( + onTap: enabled ? onTap : () => _mostrarMotivo(context), + child: Opacity( + opacity: enabled ? 1 : 0.4, + child: ValueListenableBuilder( + valueListenable: AdaptiveTheme.of(context).modeChangeNotifier, + builder: (ctx, mode, child) => DecoratedBox( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(14), + color: themedColor(context, light: color, dark: colorDark), + ), + child: SizedBox( + height: 120, + child: Padding( + padding: const EdgeInsets.fromLTRB(12,20,12,20), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon(icon, fill: fill, size: 32, weight: 600, color: Theme.of(context).textTheme.bodyMedium?.color), + const Spacer(), + Text(label, style: Theme.of(context).textTheme.labelMedium), + ], + ), + ), ), ), ), ), - ), - ); - + ); + } } diff --git a/pubspec.yaml b/pubspec.yaml index 8ce1b7c..39c3f7c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: miutem description: "Plataforma académica para estudiantes de la Universidad Tecnológica Metropolitana (UTEM)" publish_to: none -version: 4.0.0+152 +version: 4.0.0+153 environment: sdk: ^3.11.1