From 48a5da06c90ff93f8f041f68c92de8609d96bdb3 Mon Sep 17 00:00:00 2001 From: rinkyn05 Date: Mon, 2 Dec 2024 09:12:50 -0400 Subject: [PATCH] push git --- android/app/build.gradle | 46 +- android/app/google-services.json | 9 + assets/lang/en.json | 4 +- assets/lang/es.json | 4 +- .../add_calentameinto_f_screen copy.dart | 198 --- .../ejercicios/add_ejercicio_screen copy.dart | 1448 ----------------- .../ejercicios/add_ejercicio_screen.dart | 195 ++- .../ejercicios/add_ejercicio_screen_ori.dart | 1448 ----------------- lib/filtros/filter_dialog.dart | 200 +++ .../widgets/BodyPartDropdownWidget.dart | 187 +++ ...CalentamientoEspecificoDropdownWidget.dart | 186 +++ .../widgets/DificultyDropdownWidget.dart | 128 ++ .../widgets/EquipmentDropdownWidget.dart | 179 ++ .../widgets/IntensityDropdownWidget.dart | 151 ++ .../widgets/MembershipDropdownWidget.dart | 121 ++ .../widgets/NivelDeImpactoDropdownWidget.dart | 138 ++ .../widgets/ObjetivosDropdownWidget.dart | 179 ++ .../widgets/PosturaDropdownWidget.dart | 141 ++ .../ejercicios/add_ejercicios_functions.dart | 2 + .../mansory_calentamiento_fisico.dart | 34 +- pubspec.yaml | 2 +- 21 files changed, 1860 insertions(+), 3140 deletions(-) delete mode 100644 lib/backend/calentamiento_fisico/add_calentameinto_f_screen copy.dart delete mode 100644 lib/backend/ejercicios/add_ejercicio_screen copy.dart delete mode 100644 lib/backend/ejercicios/add_ejercicio_screen_ori.dart create mode 100644 lib/filtros/filter_dialog.dart create mode 100644 lib/filtros/widgets/BodyPartDropdownWidget.dart create mode 100644 lib/filtros/widgets/CalentamientoEspecificoDropdownWidget.dart create mode 100644 lib/filtros/widgets/DificultyDropdownWidget.dart create mode 100644 lib/filtros/widgets/EquipmentDropdownWidget.dart create mode 100644 lib/filtros/widgets/IntensityDropdownWidget.dart create mode 100644 lib/filtros/widgets/MembershipDropdownWidget.dart create mode 100644 lib/filtros/widgets/NivelDeImpactoDropdownWidget.dart create mode 100644 lib/filtros/widgets/ObjetivosDropdownWidget.dart create mode 100644 lib/filtros/widgets/PosturaDropdownWidget.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index b4c884a..eec5162 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -14,12 +14,12 @@ if (localPropertiesFile.exists()) { def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { - flutterVersionCode = '1' + flutterVersionCode = '2' } def flutterVersionName = localProperties.getProperty('flutter.versionName') if (flutterVersionName == null) { - flutterVersionName = '1.0' + flutterVersionName = '1.0.1' } android { @@ -48,27 +48,39 @@ android { versionName flutterVersionName } - // Definir las propiedades del keystore - def keystoreProperties = new Properties() - def keystorePropertiesFile = rootProject.file("key.properties") - if (keystorePropertiesFile.exists()) { - keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) - } - - // Configurar la firma para el modo release + // No necesitas la configuración del keystore local si usas Play App Signing signingConfigs { - release { - keyAlias keystoreProperties['keyAlias'] - keyPassword keystoreProperties['keyPassword'] - storeFile file(keystoreProperties['storeFile']) - storePassword keystoreProperties['storePassword'] - } + // No se necesita esta sección si solo vas a usar Play App Signing } + buildTypes { release { - signingConfig signingConfigs.release + // Google Play maneja la firma automáticamente + signingConfig null // No es necesario usar una firma local, ya que se usa la de Google Play } } + + // Definir las propiedades del keystore + // def keystoreProperties = new Properties() + // def keystorePropertiesFile = rootProject.file("key.properties") + // if (keystorePropertiesFile.exists()) { + // keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) + // } + + // // Configurar la firma para el modo release + // signingConfigs { + // release { + // keyAlias keystoreProperties['keyAlias'] + // keyPassword keystoreProperties['keyPassword'] + // storeFile file(keystoreProperties['storeFile']) + // storePassword keystoreProperties['storePassword'] + // } + // } + // buildTypes { + // release { + // signingConfig signingConfigs.release + // } + // } } flutter { diff --git a/android/app/google-services.json b/android/app/google-services.json index 560664e..7e3e8a2 100644 --- a/android/app/google-services.json +++ b/android/app/google-services.json @@ -1,6 +1,7 @@ { "project_info": { "project_number": "334278581961", + "firebase_url": "https://gabriel-coach-c7e30-default-rtdb.firebaseio.com", "project_id": "gabriel-coach-c7e30", "storage_bucket": "gabriel-coach-c7e30.appspot.com" }, @@ -13,6 +14,14 @@ } }, "oauth_client": [ + { + "client_id": "334278581961-80cplf2n50kias5p0hvl5bbr5a5sgapq.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.gabrielcoach.app", + "certificate_hash": "a634c3473ad20b0a38a126152f918a9a9c9ef806" + } + }, { "client_id": "334278581961-hovn5qqv584210bfq7hcu0ce69h6r3p1.apps.googleusercontent.com", "client_type": 1, diff --git a/assets/lang/en.json b/assets/lang/en.json index e4daeae..fcc956f 100644 --- a/assets/lang/en.json +++ b/assets/lang/en.json @@ -827,5 +827,7 @@ "selectDescansoEntreSeriesTime": "Select rest time between sets", "metodoEntrenamiento": "Training Method", "cardioHiit": "Cardio/Hiit", - "selectCardioHiitTime": "Select Cardio/Hiit time" + "selectCardioHiitTime": "Select Cardio/Hiit time", + "filterTitle": "Search Filters", + "filter": "Filter" } \ No newline at end of file diff --git a/assets/lang/es.json b/assets/lang/es.json index 8267259..8541e9b 100644 --- a/assets/lang/es.json +++ b/assets/lang/es.json @@ -836,5 +836,7 @@ "selectDescansoEntreSeriesTime": "Seleccionar tiempo de descanso entre series", "metodoEntrenamiento": "Metodo de Entrenamiento", "cardioHiit": "Cardio/Hiit", - "selectCardioHiitTime": "Selecciona el tiempo para Cardio/Hiit" + "selectCardioHiitTime": "Selecciona el tiempo para Cardio/Hiit", + "filterTitle": "Filtros de Busqueda", + "filter": "Filtrar" } \ No newline at end of file diff --git a/lib/backend/calentamiento_fisico/add_calentameinto_f_screen copy.dart b/lib/backend/calentamiento_fisico/add_calentameinto_f_screen copy.dart deleted file mode 100644 index 825c7ad..0000000 --- a/lib/backend/calentamiento_fisico/add_calentameinto_f_screen copy.dart +++ /dev/null @@ -1,198 +0,0 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:flutter/material.dart'; -import '../../../config/lang/app_localization.dart'; -import '../../../config/utils/appcolors.dart'; -import '../../functions/ejercicios/sports_in_ejercicio_functions.dart'; -import '../models/sports_in_ejercicio_model.dart'; - -class AddCalentamientoFisicoScreen extends StatefulWidget { - const AddCalentamientoFisicoScreen({Key? key}) : super(key: key); - - @override - AddCalentamientoFisicoScreenState createState() => - AddCalentamientoFisicoScreenState(); -} - -class AddCalentamientoFisicoScreenState extends State { - final List _selectedSports = []; - Map> sportsNames = {}; - - @override - void initState() { - super.initState(); - _loadSportsNames(); - } - - void _loadSportsNames() async { - var snapshot = await FirebaseFirestore.instance.collection('sports').get(); - Map> tempMap = {}; - for (var doc in snapshot.docs) { - tempMap[doc.id] = { - 'Esp': doc['NombreEsp'] ?? 'Nombre no disponible', - 'Eng': doc['NombreEng'] ?? 'Nombre no disponible', - }; - } - setState(() { - sportsNames = tempMap; - }); - } - - void _addSports(String sportsId) { - if (!_selectedSports.any((selected) => selected.id == sportsId)) { - String sportsEsp = - sportsNames[sportsId]?['Esp'] ?? 'Nombre no disponible'; - String sportsEng = - sportsNames[sportsId]?['Eng'] ?? 'Nombre no disponible'; - setState(() { - _selectedSports.add(SelectedSports( - id: sportsId, - sportsEsp: sportsEsp, - sportsEng: sportsEng, - )); - }); - } - } - - void _removeSports(String sportsId) { - setState(() { - _selectedSports.removeWhere((sports) => sports.id == sportsId); - }); - } - - Widget _buildSelectedSports(String langKey) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('sport'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - Wrap( - spacing: 8.0, - children: _selectedSports.map((sports) { - String sportsName = - langKey == 'Esp' ? sports.sportsEsp : sports.sportsEng; - return Chip( - label: Text(sportsName), - onDeleted: () => _removeSports(sports.id), - ); - }).toList(), - ), - ], - ); - } - - @override - Widget build(BuildContext context) { - List tabs = [ - Tab(text: AppLocalizations.of(context)!.translate('español')), - Tab(text: AppLocalizations.of(context)!.translate('english')), - ]; - - final tabLabelStyle = - Theme.of(context).textTheme.labelLarge?.copyWith(fontSize: 26); - final tabUnselectedLabelColor = - Theme.of(context).brightness == Brightness.light - ? Colors.grey - : Colors.white70; - final tabSelectedLabelColor = - Theme.of(context).brightness == Brightness.light - ? Colors.black - : Colors.white; - - return DefaultTabController( - length: 2, - child: Scaffold( - appBar: AppBar( - leading: IconButton( - icon: const Icon(Icons.arrow_back), - onPressed: () => Navigator.of(context).pop(), - ), - title: Text(AppLocalizations.of(context)! - .translate('addCalentamientoFisico')), - bottom: TabBar( - tabs: tabs, - labelStyle: tabLabelStyle, - unselectedLabelColor: tabUnselectedLabelColor, - labelColor: tabSelectedLabelColor, - indicatorColor: AppColors.lightBlueAccentColor, - indicatorWeight: 3, - ), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(bottom: Radius.circular(20)), - ), - ), - body: TabBarView( - children: [ - _buildCalentamientoFisicotsForm('Esp'), - _buildCalentamientoFisicotsForm('Eng'), - ], - ), - ), - ); - } - - Widget _buildCalentamientoFisicotsForm(String langKey) { - return SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox(height: 10), - _buildSelectedSports(langKey), - FutureBuilder>>( - future: SportsInEjercicioFunctions().getSimplifiedSports(langKey), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return const CircularProgressIndicator(); - } - return Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - color: Colors.grey.shade400, - borderRadius: BorderRadius.circular(20), - border: Border.all( - color: AppColors.lightBlueAccentColor, - width: 2, - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - AppLocalizations.of(context)!.translate('selectSports'), - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 18, - color: Colors.black, - ), - ), - DropdownButtonHideUnderline( - child: DropdownButton( - isExpanded: true, - hint: Text(AppLocalizations.of(context)! - .translate('selectSports')), - onChanged: (String? newValue) { - _addSports(newValue!); - }, - items: snapshot.data, - value: snapshot.data!.isNotEmpty - ? snapshot.data?.first.value - : null, - ), - ), - ], - ), - ); - }, - ), - ], - ), - ), - ); - } -} diff --git a/lib/backend/ejercicios/add_ejercicio_screen copy.dart b/lib/backend/ejercicios/add_ejercicio_screen copy.dart deleted file mode 100644 index 183e776..0000000 --- a/lib/backend/ejercicios/add_ejercicio_screen copy.dart +++ /dev/null @@ -1,1448 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -import 'package:flutter/material.dart'; -import 'package:fluttertoast/fluttertoast.dart'; -import '../../../config/lang/app_localization.dart'; -import '../../../config/utils/appcolors.dart'; -import 'package:cloud_firestore/cloud_firestore.dart'; - -import '../../functions/ejercicios/add_ejercicios_functions copy.dart'; -import '../../functions/ejercicios/body_part_in_ejercicio_functions.dart'; -import '../../functions/ejercicios/cat_ejercicio_in_ejercicio_functions.dart'; -import '../../functions/ejercicios/equipment_in_ejercicio_functions.dart'; -import '../../functions/ejercicios/objetivo_in_ejercicio_functions.dart'; -import '../../functions/ejercicios/unequipment_in_ejercicio_functions.dart'; -import '../../functions/role_checker.dart'; -import '../../functions/upload_exercise_image.dart'; -import '../models/bodypart_in_ejercicio_model.dart'; -import '../models/equipment_in_ejercicio_model.dart'; -import '../models/objetivos_in_ejercicio_model.dart'; -import '../models/selected_cat_ejercicio_model.dart'; -import '../models/unequipment_in_ejercicio_model.dart'; - -class AddEjercicioScreen extends StatefulWidget { - const AddEjercicioScreen({Key? key}) : super(key: key); - - @override - AddEjercicioScreenState createState() => AddEjercicioScreenState(); -} - -class AddEjercicioScreenState extends State { - final TextEditingController _nameControllerEsp = TextEditingController(); - final TextEditingController _nameControllerEng = TextEditingController(); - final TextEditingController _descriptionControllerEsp = - TextEditingController(); - final TextEditingController _descriptionControllerEng = - TextEditingController(); - final TextEditingController _contenidoControllerEsp = TextEditingController(); - final TextEditingController _contenidoControllerEng = TextEditingController(); - final TextEditingController _caloriasController = TextEditingController(); - final TextEditingController _repeticionesController = TextEditingController(); - final TextEditingController _videoController = TextEditingController(); - - String _imageUrl = ''; - final List _selectedObjetivos = []; - Map> objetivosNames = {}; - - final List _selectedEquipment = []; - Map> equipmentNames = {}; - - final List _selectedUnequipment = []; - Map> unequipmentNames = {}; - - final List _selectedBodyPart = []; - Map> bodypartNames = {}; - - final List _selectedCatEjercicio = []; - Map> catEjercicioNames = {}; - - String _intensityEsp = 'Baja'; - String _intensityEng = 'Low'; - - String _stanceEsp = 'Parado'; - String _stanceEng = 'Standing'; - - String _membershipEsp = 'Gratis'; - String _membershipEng = 'Free'; - - int _selectedMinutes = 0; - int _selectedSeconds = 0; - - @override - void initState() { - super.initState(); - _loadBodyPartNames(); - _loadCatEjercicioNames(); - _loadObjetivosNames(); - _loadEquipmentNames(); - _loadUnequipmentNames(); - _checkAccess(); - } - - Future _checkAccess() async { - bool hasAccess = await checkUserRole(); - if (!hasAccess) { - WidgetsBinding.instance.addPostFrameCallback((_) { - if (mounted) { - _showAccessDeniedDialog(context); - } - }); - } - } - - void _showAccessDeniedDialog(BuildContext context) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text( - AppLocalizations.of(context)!.translate('accessDeniedTitle')), - content: Text( - AppLocalizations.of(context)!.translate('accessDeniedMessage')), - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(AppLocalizations.of(context)!.translate('okButton')), - ), - ], - ); - }, - ); - } - - void _loadObjetivosNames() async { - var snapshot = - await FirebaseFirestore.instance.collection('objetivos').get(); - Map> tempMap = {}; - for (var doc in snapshot.docs) { - tempMap[doc.id] = { - 'Esp': doc['NombreEsp'] ?? 'Nombre no disponible', - 'Eng': doc['NombreEng'] ?? 'Nombre no disponible', - }; - } - setState(() { - objetivosNames = tempMap; - }); - } - - void _loadEquipmentNames() async { - var snapshot = - await FirebaseFirestore.instance.collection('equipment').get(); - Map> tempMap = {}; - for (var doc in snapshot.docs) { - tempMap[doc.id] = { - 'Esp': doc['NombreEsp'] ?? 'Nombre no disponible', - 'Eng': doc['NombreEng'] ?? 'Nombre no disponible', - }; - } - setState(() { - equipmentNames = tempMap; - }); - } - - void _loadUnequipmentNames() async { - var snapshot = - await FirebaseFirestore.instance.collection('unequipment').get(); - Map> tempMap = {}; - for (var doc in snapshot.docs) { - tempMap[doc.id] = { - 'Esp': doc['NombreEsp'] ?? 'Nombre no disponible', - 'Eng': doc['NombreEng'] ?? 'Nombre no disponible', - }; - } - setState(() { - unequipmentNames = tempMap; - }); - } - - void _loadBodyPartNames() async { - var snapshot = await FirebaseFirestore.instance.collection('bodyp').get(); - Map> tempMap = {}; - for (var doc in snapshot.docs) { - tempMap[doc.id] = { - 'Esp': doc['NombreEsp'] ?? 'Nombre no disponible', - 'Eng': doc['NombreEng'] ?? 'Nombre no disponible', - }; - } - setState(() { - bodypartNames = tempMap; - }); - } - - void _loadCatEjercicioNames() async { - var snapshot = - await FirebaseFirestore.instance.collection('catEjercicio').get(); - Map> tempMap = {}; - for (var doc in snapshot.docs) { - int id = int.tryParse(doc.id) ?? 0; - tempMap[id] = { - 'Esp': doc['NombreEsp'] ?? 'Nombre no disponible', - 'Eng': doc['NombreEng'] ?? 'Nombre no disponible', - }; - } - setState(() { - catEjercicioNames = tempMap; - }); - } - - void _addObjetivos(String objetivosId) { - if (!_selectedObjetivos.any((selected) => selected.id == objetivosId)) { - String objetivosEsp = - objetivosNames[objetivosId]?['Esp'] ?? 'Nombre no disponible'; - String objetivosEng = - objetivosNames[objetivosId]?['Eng'] ?? 'Nombre no disponible'; - setState(() { - _selectedObjetivos.add(SelectedObjetivos( - id: objetivosId, - objetivosEsp: objetivosEsp, - objetivosEng: objetivosEng, - )); - }); - } - } - - void _addEquipment(String equipmentId) { - if (!_selectedEquipment.any((selected) => selected.id == equipmentId)) { - String equipmentEsp = - equipmentNames[equipmentId]?['Esp'] ?? 'Nombre no disponible'; - String equipmentEng = - equipmentNames[equipmentId]?['Eng'] ?? 'Nombre no disponible'; - setState(() { - _selectedEquipment.add(SelectedEquipment( - id: equipmentId, - equipmentEsp: equipmentEsp, - equipmentEng: equipmentEng, - )); - }); - } - } - - void _addUnequipment(String unequipmentId) { - if (!_selectedUnequipment.any((selected) => selected.id == unequipmentId)) { - String unequipmentEsp = - unequipmentNames[unequipmentId]?['Esp'] ?? 'Nombre no disponible'; - String unequipmentEng = - unequipmentNames[unequipmentId]?['Eng'] ?? 'Nombre no disponible'; - setState(() { - _selectedUnequipment.add(SelectedUnequipment( - id: unequipmentId, - unequipmentEsp: unequipmentEsp, - unequipmentEng: unequipmentEng, - )); - }); - } - } - - void _addBodyPart(String bodypartId) { - if (!_selectedBodyPart.any((selected) => selected.id == bodypartId)) { - String bodypartEsp = - bodypartNames[bodypartId]?['Esp'] ?? 'Nombre no disponible'; - String bodypartEng = - bodypartNames[bodypartId]?['Eng'] ?? 'Nombre no disponible'; - setState(() { - _selectedBodyPart.add(SelectedBodyPart( - id: bodypartId, - bodypartEsp: bodypartEsp, - bodypartEng: bodypartEng, - )); - }); - } - } - - void _addCatEjercicio(int catEjercicioId) { - if (!_selectedCatEjercicio - .any((selected) => selected.id == catEjercicioId)) { - String catEjercicioEsp = - catEjercicioNames[catEjercicioId]?['Esp'] ?? 'Nombre no disponible'; - String catEjercicioEng = - catEjercicioNames[catEjercicioId]?['Eng'] ?? 'Nombre no disponible'; - setState(() { - _selectedCatEjercicio.add(SelectedCatEjercicio( - id: catEjercicioId, - nombreEsp: catEjercicioEsp, - nombreEng: catEjercicioEng, - )); - }); - } - } - - void _removeObjetivos(String objetivosId) { - setState(() { - _selectedObjetivos - .removeWhere((objetivos) => objetivos.id == objetivosId); - }); - } - - void _removeEquipment(String equipmentId) { - setState(() { - _selectedEquipment - .removeWhere((equipment) => equipment.id == equipmentId); - }); - } - - void _removeUnequipment(String unequipmentId) { - setState(() { - _selectedUnequipment - .removeWhere((unequipment) => unequipment.id == unequipmentId); - }); - } - - void _removeBodyPart(String bodypartId) { - setState(() { - _selectedBodyPart.removeWhere((bodypart) => bodypart.id == bodypartId); - }); - } - - void _removeCatEjercicio(int catEjercicioId) { - setState(() { - _selectedCatEjercicio - .removeWhere((catEjercicio) => catEjercicio.id == catEjercicioId); - }); - } - - Widget _buildMembershipSection() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('exerciseMembership'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - _buildMembershipSelector(), - ], - ); - } - - Widget _buildMembershipSelector() { - Locale currentLocale = Localizations.localeOf(context); - bool isEsp = currentLocale.languageCode == "es"; - - List optionsEsp = ['Gratis', 'Premium']; - List optionsEng = ['Free', 'Premium']; - - Map membershipMapEspToEng = { - 'Gratis': 'Free', - 'Premium': 'Premium', - }; - - Map membershipMapEngToEsp = { - 'Free': 'Gratis', - 'Premium': 'Premium', - }; - - List options = isEsp ? optionsEsp : optionsEng; - String currentMembership = isEsp ? _membershipEsp : _membershipEng; - - return Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: options.map((option) { - bool selected = isEsp - ? option == currentMembership - : membershipMapEspToEng[_membershipEsp] == option; - - return ChoiceChip( - label: Text(option), - selected: selected, - onSelected: (bool isSelected) { - setState(() { - if (isEsp) { - _membershipEsp = option; - _membershipEng = membershipMapEspToEng[option]!; - } else { - _membershipEng = option; - _membershipEsp = membershipMapEngToEsp[option]!; - } - }); - }, - ); - }).toList(), - ); - } - - Widget _buildIntensitySection() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('exerciseIntensity'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - _buildIntensitySelector(), - ], - ); - } - - Widget _buildIntensitySelector() { - Locale currentLocale = Localizations.localeOf(context); - bool isEsp = currentLocale.languageCode == "es"; - - List optionsEsp = ['Baja', 'Media', 'Alta']; - List optionsEng = ['Low', 'Medium', 'High']; - - Map intensityMapEspToEng = { - 'Baja': 'Low', - 'Media': 'Medium', - 'Alta': 'High', - }; - - Map intensityMapEngToEsp = { - 'Low': 'Baja', - 'Medium': 'Media', - 'High': 'Alta', - }; - - List options = isEsp ? optionsEsp : optionsEng; - - return Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: options.map((option) { - bool selected; - if (isEsp) { - selected = _intensityEsp == option; - } else { - String? equivalentInEng = intensityMapEspToEng[_intensityEsp]; - selected = equivalentInEng == option; - } - return ChoiceChip( - label: Text(option), - selected: selected, - onSelected: (bool isSelected) { - setState(() { - if (isEsp) { - _intensityEsp = option; - _intensityEng = intensityMapEspToEng[option]!; - } else { - _intensityEng = option; - _intensityEsp = intensityMapEngToEsp[option]!; - } - }); - }, - ); - }).toList(), - ); - } - - Widget _buildTimeSelectionSection() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('selectTime'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - _buildTimeSelector(), - ], - ); - } - - Widget _buildTimeSelector() { - return Container( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: DropdownButton( - isExpanded: true, - value: _selectedMinutes, - items: List.generate(60, (index) => index) - .map>((int value) { - return DropdownMenuItem( - value: value, - child: Center(child: Text("$value min")), - ); - }).toList(), - onChanged: (newValue) { - setState(() { - _selectedMinutes = newValue!; - }); - }, - underline: Container( - height: 2, - color: Theme.of(context).primaryColor, - ), - ), - ), - const SizedBox(width: 10), - Expanded( - child: DropdownButton( - isExpanded: true, - value: _selectedSeconds, - items: List.generate(60, (index) => index) - .map>((int value) { - return DropdownMenuItem( - value: value, - child: Center( - child: Text("${value.toString().padLeft(2, '0')} seg")), - ); - }).toList(), - onChanged: (newValue) { - setState(() { - _selectedSeconds = newValue!; - }); - }, - underline: Container( - height: 2, - color: Theme.of(context).primaryColor, - ), - ), - ), - ], - ), - ); - } - - Widget _buildStanceSection() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('exerciseStance'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - _buildStanceSelector(), - ], - ); - } - - Widget _buildStanceSelector() { - Locale currentLocale = Localizations.localeOf(context); - bool isEsp = currentLocale.languageCode == "es"; - - List optionsEsp = [ - 'Parado', - 'Sentado', - 'Acostado', - 'Saltando', - 'Corriendo' - ]; - List optionsEng = [ - 'Standing', - 'Sitting', - 'Lying Down', - 'Jumping', - 'Running' - ]; - - Map stanceMapEspToEng = { - 'Parado': 'Standing', - 'Sentado': 'Sitting', - 'Acostado': 'Lying Down', - 'Saltando': 'Jumping', - 'Corriendo': 'Running', - }; - - Map stanceMapEngToEsp = { - 'Standing': 'Parado', - 'Sitting': 'Sentado', - 'Lying Down': 'Acostado', - 'Jumping': 'Saltando', - 'Running': 'Corriendo', - }; - - List options = isEsp ? optionsEsp : optionsEng; - - return Wrap( - spacing: 8.0, - runSpacing: 4.0, - alignment: WrapAlignment.spaceEvenly, - children: options.map((option) { - bool selected; - if (isEsp) { - selected = _stanceEsp == option; - } else { - String? equivalentInEng = stanceMapEspToEng[_stanceEsp]; - selected = equivalentInEng == option; - } - return ChoiceChip( - label: Text(option), - selected: selected, - onSelected: (bool isSelected) { - setState(() { - if (isEsp) { - _stanceEsp = option; - _stanceEng = stanceMapEspToEng[option]!; - } else { - _stanceEng = option; - _stanceEsp = stanceMapEngToEsp[option]!; - } - }); - }, - ); - }).toList(), - ); - } - - Widget _buildSelectedObjetivos(String langKey) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('ocjetives'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - Wrap( - spacing: 8.0, - children: _selectedObjetivos.map((objetivos) { - String objetivosName = langKey == 'Esp' - ? objetivos.objetivosEsp - : objetivos.objetivosEng; - return Chip( - label: Text(objetivosName), - onDeleted: () => _removeObjetivos(objetivos.id), - ); - }).toList(), - ), - ], - ); - } - - Widget _buildSelectedEquipment(String langKey) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('equipments'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - Wrap( - spacing: 8.0, - children: _selectedEquipment.map((equipment) { - String equipmentName = langKey == 'Esp' - ? equipment.equipmentEsp - : equipment.equipmentEng; - return Chip( - label: Text(equipmentName), - onDeleted: () => _removeEquipment(equipment.id), - ); - }).toList(), - ), - ], - ); - } - - Widget _buildSelectedUnequipment(String langKey) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('unequipments'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - Wrap( - spacing: 8.0, - children: _selectedUnequipment.map((unequipment) { - String unequipmentName = langKey == 'Esp' - ? unequipment.unequipmentEsp - : unequipment.unequipmentEng; - return Chip( - label: Text(unequipmentName), - onDeleted: () => _removeUnequipment(unequipment.id), - ); - }).toList(), - ), - ], - ); - } - - Widget _buildSelectedBodyPart(String langKey) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('bodyParts'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - Wrap( - spacing: 8.0, - children: _selectedBodyPart.map((bodypart) { - String bodypartName = - langKey == 'Esp' ? bodypart.bodypartEsp : bodypart.bodypartEng; - return Chip( - label: Text(bodypartName), - onDeleted: () => _removeBodyPart(bodypart.id), - ); - }).toList(), - ), - ], - ); - } - - Widget _buildSelectedCatEjercicio(String langKey) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('catEjercicios'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - Wrap( - spacing: 8.0, - children: _selectedCatEjercicio.map((catEjercicio) { - String catEjercicioName = langKey == 'Esp' - ? catEjercicio.nombreEsp - : catEjercicio.nombreEng; - return Chip( - label: Text(catEjercicioName), - onDeleted: () => _removeCatEjercicio(catEjercicio.id), - ); - }).toList(), - ), - ], - ); - } - - @override - Widget build(BuildContext context) { - List tabs = [ - Tab(text: AppLocalizations.of(context)!.translate('español')), - Tab(text: AppLocalizations.of(context)!.translate('english')), - ]; - - final tabLabelStyle = - Theme.of(context).textTheme.labelLarge?.copyWith(fontSize: 26); - final tabUnselectedLabelColor = - Theme.of(context).brightness == Brightness.light - ? Colors.grey - : Colors.white70; - final tabSelectedLabelColor = - Theme.of(context).brightness == Brightness.light - ? Colors.black - : Colors.white; - - return DefaultTabController( - length: 2, - child: Scaffold( - appBar: AppBar( - leading: IconButton( - icon: const Icon(Icons.arrow_back), - onPressed: () => Navigator.of(context).pop(), - ), - title: Text(AppLocalizations.of(context)!.translate('addEjercicio')), - bottom: TabBar( - tabs: tabs, - labelStyle: tabLabelStyle, - unselectedLabelColor: tabUnselectedLabelColor, - labelColor: tabSelectedLabelColor, - indicatorColor: AppColors.lightBlueAccentColor, - indicatorWeight: 3, - ), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(bottom: Radius.circular(20)), - ), - ), - body: TabBarView( - children: [ - _buildEjercicioForm( - _nameControllerEsp, - _descriptionControllerEsp, - _contenidoControllerEsp, - _caloriasController, - _repeticionesController, - _videoController, - _intensityEsp, - _stanceEsp, - _membershipEsp, - 'Esp'), - _buildEjercicioForm( - _nameControllerEng, - _descriptionControllerEng, - _contenidoControllerEng, - _caloriasController, - _repeticionesController, - _videoController, - _intensityEng, - _stanceEng, - _membershipEng, - 'Eng'), - ], - ), - ), - ); - } - - Widget _buildEjercicioForm( - TextEditingController nameController, - TextEditingController descriptionController, - TextEditingController contenidoController, - TextEditingController caloriasController, - TextEditingController videoController, - TextEditingController repeticionesController, - String intensity, - String stance, - String membership, - String langKey) { - OutlineInputBorder borderStyle = OutlineInputBorder( - borderRadius: BorderRadius.circular(20), - borderSide: BorderSide(color: Colors.grey.shade300), - ); - - Color textColor = Theme.of(context).brightness == Brightness.dark - ? AppColors.darkBlueColor - : Colors.black; - - return SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('ejercicioName'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - TextFormField( - controller: nameController, - style: TextStyle(color: textColor), - decoration: InputDecoration( - labelText: - '${AppLocalizations.of(context)!.translate('ejercicioName')} ($langKey)', - hintText: AppLocalizations.of(context)! - .translate('enterEjercicioName'), - border: borderStyle, - enabledBorder: borderStyle, - focusedBorder: borderStyle.copyWith( - borderSide: const BorderSide( - color: AppColors.lightBlueAccentColor, width: 2), - ), - filled: true, - fillColor: Colors.grey.shade100, - ), - ), - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('ejercicioDescription'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - TextFormField( - controller: descriptionController, - maxLines: 3, - style: TextStyle(color: textColor), - decoration: InputDecoration( - labelText: - '${AppLocalizations.of(context)!.translate('ejercicioDescription')} ($langKey)', - hintText: AppLocalizations.of(context)! - .translate('enterEjercicioDescription'), - border: borderStyle, - enabledBorder: borderStyle, - focusedBorder: borderStyle.copyWith( - borderSide: const BorderSide( - color: AppColors.lightBlueAccentColor, width: 2), - ), - filled: true, - fillColor: Colors.grey.shade100, - ), - ), - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('content'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - TextFormField( - controller: contenidoController, - maxLines: 3, - style: TextStyle(color: textColor), - decoration: InputDecoration( - labelText: - '${AppLocalizations.of(context)!.translate('content')} ($langKey)', - hintText: - AppLocalizations.of(context)!.translate('enterContent'), - border: borderStyle, - enabledBorder: borderStyle, - focusedBorder: borderStyle.copyWith( - borderSide: const BorderSide( - color: AppColors.lightBlueAccentColor, width: 2), - ), - filled: true, - fillColor: Colors.grey.shade100, - ), - ), - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('repeticionesName'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - TextFormField( - controller: videoController, - style: TextStyle(color: textColor), - decoration: InputDecoration( - labelText: - '${AppLocalizations.of(context)!.translate('repeticionesName')} ($langKey)', - hintText: AppLocalizations.of(context)! - .translate('enterRepeticionesName'), - border: borderStyle, - enabledBorder: borderStyle, - focusedBorder: borderStyle.copyWith( - borderSide: const BorderSide( - color: AppColors.lightBlueAccentColor, width: 2), - ), - filled: true, - fillColor: Colors.grey.shade100, - ), - keyboardType: TextInputType.number, - ), - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('caloriasName'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - TextFormField( - controller: caloriasController, - style: TextStyle(color: textColor), - decoration: InputDecoration( - labelText: - '${AppLocalizations.of(context)!.translate('caloriasName')} ($langKey)', - hintText: AppLocalizations.of(context)! - .translate('enterCaloriasName'), - border: borderStyle, - enabledBorder: borderStyle, - focusedBorder: borderStyle.copyWith( - borderSide: const BorderSide( - color: AppColors.lightBlueAccentColor, width: 2), - ), - filled: true, - fillColor: Colors.grey.shade100, - ), - keyboardType: TextInputType.number, - ), - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('videoLink'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - TextFormField( - controller: repeticionesController, - style: TextStyle(color: textColor), - decoration: InputDecoration( - labelText: - '${AppLocalizations.of(context)!.translate('videoLink')} ($langKey)', - hintText: - AppLocalizations.of(context)!.translate('enterVideoLink'), - border: borderStyle, - enabledBorder: borderStyle, - focusedBorder: borderStyle.copyWith( - borderSide: const BorderSide( - color: AppColors.lightBlueAccentColor, width: 2), - ), - filled: true, - fillColor: Colors.grey.shade100, - ), - ), - const SizedBox(height: 15), - _buildMembershipSection(), - const SizedBox(height: 15), - _buildIntensitySection(), - const SizedBox(height: 15), - _buildStanceSection(), - const SizedBox(height: 15), - _buildTimeSelectionSection(), - const SizedBox(height: 15), - _buildSelectedBodyPart(langKey), - FutureBuilder>>( - future: - BodyPartInEjercicioFunctions().getSimplifiedBodyPart(langKey), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return const CircularProgressIndicator(); - } - return Container( - padding: - const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - color: Colors.grey.shade400, - borderRadius: BorderRadius.circular(20), - border: Border.all( - color: AppColors.lightBlueAccentColor, - width: 2, - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - AppLocalizations.of(context)! - .translate('selectBodyPart'), - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 18, - color: Colors.black, - ), - ), - DropdownButtonHideUnderline( - child: DropdownButton( - isExpanded: true, - hint: Text(AppLocalizations.of(context)! - .translate('selectBodyPart')), - onChanged: (String? newValue) { - _addBodyPart(newValue!); - }, - items: snapshot.data, - value: snapshot.data!.isNotEmpty - ? snapshot.data?.first.value - : null, - ), - ), - ], - ), - ); - }, - ), - const SizedBox(height: 20), - _buildSelectedCatEjercicio(langKey), - FutureBuilder>>( - future: CatEjercicioInEjercicioFunctions() - .getSimplifiedCatEjercicio(langKey), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return const CircularProgressIndicator(); - } - return Container( - padding: - const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - color: Colors.grey.shade400, - borderRadius: BorderRadius.circular(20), - border: Border.all( - color: AppColors.lightBlueAccentColor, - width: 2, - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - AppLocalizations.of(context)! - .translate('selectCatEjercicio'), - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 18, - color: Colors.black, - ), - ), - DropdownButtonHideUnderline( - child: DropdownButton( - isExpanded: true, - hint: Text(AppLocalizations.of(context)! - .translate('selectCatEjercicio')), - onChanged: (int? newValue) { - _addCatEjercicio(newValue!); - }, - items: snapshot.data, - value: snapshot.data!.isNotEmpty - ? snapshot.data?.first.value - : null, - ), - ), - ], - ), - ); - }, - ), - const SizedBox(height: 20), - _buildSelectedObjetivos(langKey), - FutureBuilder>>( - future: ObjetivosInEjercicioFunctions() - .getSimplifiedObjetivos(langKey), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return const CircularProgressIndicator(); - } - return Container( - padding: - const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - color: Colors.grey.shade400, - borderRadius: BorderRadius.circular(20), - border: Border.all( - color: AppColors.lightBlueAccentColor, - width: 2, - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - AppLocalizations.of(context)! - .translate('selectObjetivo'), - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 18, - color: Colors.black, - ), - ), - DropdownButtonHideUnderline( - child: DropdownButton( - isExpanded: true, - hint: Text(AppLocalizations.of(context)! - .translate('selectObjetivos')), - onChanged: (String? newValue) { - _addObjetivos(newValue!); - }, - items: snapshot.data, - value: snapshot.data!.isNotEmpty - ? snapshot.data?.first.value - : null, - ), - ), - ], - ), - ); - }, - ), - const SizedBox(height: 20), - _buildSelectedEquipment(langKey), - FutureBuilder>>( - future: EquipmentInEjercicioFunctions() - .getSimplifiedEquipment(langKey), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return const CircularProgressIndicator(); - } - return Container( - padding: - const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - color: Colors.grey.shade400, - borderRadius: BorderRadius.circular(20), - border: Border.all( - color: AppColors.lightBlueAccentColor, - width: 2, - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - AppLocalizations.of(context)! - .translate('selectEquipment'), - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 18, - color: Colors.black, - ), - ), - DropdownButtonHideUnderline( - child: DropdownButton( - isExpanded: true, - hint: Text(AppLocalizations.of(context)! - .translate('selectEquipment')), - onChanged: (String? newValue) { - _addEquipment(newValue!); - }, - items: snapshot.data, - value: snapshot.data!.isNotEmpty - ? snapshot.data?.first.value - : null, - ), - ), - ], - ), - ); - }, - ), - const SizedBox(height: 20), - _buildSelectedUnequipment(langKey), - FutureBuilder>>( - future: UnequipmentInEjercicioFunctions() - .getSimplifiedUnequipment(langKey), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return const CircularProgressIndicator(); - } - return Container( - padding: - const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - color: Colors.grey.shade400, - borderRadius: BorderRadius.circular(20), - border: Border.all( - color: AppColors.lightBlueAccentColor, - width: 2, - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - AppLocalizations.of(context)! - .translate('selectUnequipment'), - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 18, - color: Colors.black, - ), - ), - DropdownButtonHideUnderline( - child: DropdownButton( - isExpanded: true, - hint: Text(AppLocalizations.of(context)! - .translate('selectUnequipment')), - onChanged: (String? newValue) { - _addUnequipment(newValue!); - }, - items: snapshot.data, - value: snapshot.data!.isNotEmpty - ? snapshot.data?.first.value - : null, - ), - ), - ], - ), - ); - }, - ), - const SizedBox(height: 20), - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('image'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - _buildImagePreview(), - const SizedBox(height: 20), - _buildImageUploadButton(), - const SizedBox(height: 20), - _buildPublishButton(), - ], - ), - ), - ); - } - - Widget _buildImagePreview() { - return InkWell( - onTap: () async { - await uploadExerciseImage(context, (String url) { - setState(() { - _imageUrl = url; - }); - }); - }, - child: _imageUrl.isNotEmpty - ? ClipRRect( - borderRadius: BorderRadius.circular(20), - child: Image.network(_imageUrl, height: 200, fit: BoxFit.cover), - ) - : Container( - height: 200, - decoration: BoxDecoration( - color: Colors.grey[300], - borderRadius: BorderRadius.circular(20), - border: Border.all(color: Colors.grey.shade400), - ), - child: Icon(Icons.photo, size: 50, color: Colors.grey.shade600), - ), - ); - } - - Widget _buildImageUploadButton() { - return _buildCustomButton( - context, - 'Subir Imagen', - () async { - await uploadExerciseImage(context, (String url) { - setState(() { - _imageUrl = url; - }); - }); - }, - ); - } - - Widget _buildPublishButton() { - return _buildCustomButton( - context, - 'Publicar', - () async { - String formattedTime = - '${_selectedMinutes.toString().padLeft(2, '0')}:${_selectedSeconds.toString().padLeft(2, '0')}'; - if (_nameControllerEsp.text.isNotEmpty && - _descriptionControllerEsp.text.isNotEmpty && - _contenidoControllerEsp.text.isNotEmpty && - _videoController.text.isNotEmpty && - _nameControllerEng.text.isNotEmpty && - _descriptionControllerEng.text.isNotEmpty && - _contenidoControllerEng.text.isNotEmpty && - _caloriasController.text.isNotEmpty && - _repeticionesController.text.isNotEmpty && - _imageUrl.isNotEmpty && - _selectedObjetivos.isNotEmpty && - _selectedEquipment.isNotEmpty && - _selectedUnequipment.isNotEmpty && - _selectedBodyPart.isNotEmpty && - _selectedCatEjercicio.isNotEmpty && - _membershipEsp.isNotEmpty && - _membershipEng.isNotEmpty && - _intensityEsp.isNotEmpty && - _intensityEng.isNotEmpty && - _stanceEsp.isNotEmpty && - _stanceEng.isNotEmpty) { - await AddEjercicioFunctions().addEjercicioWithAutoIncrementId( - nombreEsp: _nameControllerEsp.text, - nombreEng: _nameControllerEng.text, - descripcionEsp: _descriptionControllerEsp.text, - descripcionEng: _descriptionControllerEng.text, - contenidoEsp: _contenidoControllerEsp.text, - calorias: _caloriasController.text, - repeticiones: _repeticionesController.text, - contenidoEng: _contenidoControllerEng.text, - video: _videoController.text, - imageUrl: _imageUrl, - selectedObjetivos: _selectedObjetivos, - selectedEquipment: _selectedEquipment, - selectedUnequipment: _selectedUnequipment, - selectedBodyPart: _selectedBodyPart, - selectedCatEjercicio: _selectedCatEjercicio, - membershipEsp: _membershipEsp, - membershipEng: _membershipEng, - intensityEsp: _intensityEsp, - intensityEng: _intensityEng, - stanceEsp: _stanceEsp, - stanceEng: _stanceEng, - duracion: formattedTime, - ); - _showSuccessSnackbar(context); - _clearFields(); - _sendCountToTotalExercises(); - Navigator.pop(context, true); - } else { - _showErrorSnackbar(context); - } - }, - ); - } - - void _sendCountToTotalExercises() async { - try { - final totalExercisesRef = FirebaseFirestore.instance - .collection('totalexercises') - .doc('contador'); - await totalExercisesRef.set({ - 'total': FieldValue.increment(1), - }, SetOptions(merge: true)); - } catch (error) { - //print('Error al enviar el conteo a totalexercises: $error'); - } - } - - Widget _buildCustomButton( - BuildContext context, String translationKey, VoidCallback onPressed) { - final ThemeData theme = Theme.of(context); - final bool isDarkTheme = theme.brightness == Brightness.dark; - - final Color backgroundColor = isDarkTheme - ? AppColors.deepPurpleColor - : AppColors.lightBlueAccentColor; - const Color textColor = Colors.white; - - return ElevatedButton( - onPressed: onPressed, - style: ElevatedButton.styleFrom( - foregroundColor: textColor, - backgroundColor: backgroundColor, - padding: const EdgeInsets.symmetric(horizontal: 40.0, vertical: 20.0), - textStyle: theme.textTheme.titleLarge?.copyWith(color: textColor), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(30), - ), - side: BorderSide(color: backgroundColor), - elevation: 5, - ), - child: Text(AppLocalizations.of(context)!.translate(translationKey)), - ); - } - - void _showSuccessSnackbar(BuildContext context) { - Fluttertoast.showToast( - msg: AppLocalizations.of(context)!.translate('ejercicioAdded'), - toastLength: Toast.LENGTH_SHORT, - gravity: ToastGravity.BOTTOM, - backgroundColor: Colors.green, - textColor: Colors.white, - fontSize: 24.0, - ); - } - - void _showErrorSnackbar(BuildContext context) { - Fluttertoast.showToast( - msg: AppLocalizations.of(context)!.translate('publishErrorMessage'), - toastLength: Toast.LENGTH_SHORT, - gravity: ToastGravity.BOTTOM, - backgroundColor: Colors.red, - textColor: Colors.white, - fontSize: 24.0, - ); - } - - void _clearFields() { - _nameControllerEsp.clear(); - _nameControllerEng.clear(); - _descriptionControllerEsp.clear(); - _descriptionControllerEng.clear(); - _contenidoControllerEsp.clear(); - _contenidoControllerEng.clear(); - _videoController.clear(); - _caloriasController.clear(); - _repeticionesController.clear(); - _intensityEng = 'Low'; - _intensityEsp = 'Baja'; - _stanceEng = 'Parado'; - _stanceEng = 'Standing'; - _membershipEsp = 'Gratis'; - _membershipEng = 'Free'; - setState(() { - _imageUrl = ''; - _selectedObjetivos.clear(); - _selectedEquipment.clear(); - _selectedUnequipment.clear(); - _selectedBodyPart.clear(); - _selectedCatEjercicio.clear(); - }); - } -} diff --git a/lib/backend/ejercicios/add_ejercicio_screen.dart b/lib/backend/ejercicios/add_ejercicio_screen.dart index a504863..51e450b 100644 --- a/lib/backend/ejercicios/add_ejercicio_screen.dart +++ b/lib/backend/ejercicios/add_ejercicio_screen.dart @@ -86,6 +86,41 @@ class AddEjercicioScreenState extends State { List _selectedPhasesEsp = []; List _selectedPhasesEng = []; + Map> specificMuscleOptions = { + 'deltoide': ['Frontal', 'Medio', 'Posterior'], + 'pectoral': ['Mayor', 'Medio', 'Bajo'], + 'espalda': ['Dorsal', 'Trapecio', 'Lumbar'], + 'bicep': ['Cabeza Larga', 'Cabeza Corta'], // Nuevas opciones para biceps + 'tricep': [ + 'Cabeza Larga', + 'Cabeza Lateral', + 'Cabeza Medial' + ], // Nuevas opciones para triceps + 'antebrazo': ['Frontal', 'Posterior'], // Nuevas opciones para antebrazo + 'abdomen': [ + 'Porción Alta', + 'Porción Baja', + 'Oblicuos', + 'Serratos' + ], // Nuevas opciones para abdomen + 'gluteo': ['Mayor', 'Medio', 'Menor'], // Nuevas opciones para glúteo + 'pierna': ['Abductor', 'Adductor'], // Nuevas opciones para pierna + 'cuadriceps': [ + 'Vasto Interno', + 'Vasto Intermedio', + 'Vasto Externo', + 'Recto Femoral' + ], // Nuevas opciones para cuadriceps + 'pantorrillla': [ + 'Gastrocnemio', + 'Soleo', + 'Tibial Anterior' + ], // Nuevas opciones para pantorrilla + }; + + final TextEditingController _specificMuscleController = + TextEditingController(); + @override void initState() { super.initState(); @@ -948,6 +983,46 @@ class AddEjercicioScreenState extends State { ); } + Widget _buildSelectedSpecificMuscle(String langKey) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (_specificMuscleController + .text.isNotEmpty) // Solo se muestra si hay selección + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Text( + AppLocalizations.of(context)! + .translate('MuscEspecifico'), // Título para la tarjeta + style: Theme.of(context).textTheme.titleMedium, + ), + ), + if (_specificMuscleController.text.isNotEmpty) + Wrap( + spacing: 8.0, + children: [ + Chip( + label: Text(_specificMuscleController + .text), // Muestra el músculo específico seleccionado + onDeleted: () { + setState(() { + _specificMuscleController.text = + ''; // Borra la selección al presionar el botón de eliminar + }); + }, + ), + ], + ), + ], + ); + } + + void _updateSpecificMuscleOptions(String selectedMuscle) { + setState(() { + _specificMuscleController.clear(); + }); + } + @override Widget build(BuildContext context) { List tabs = [ @@ -1122,21 +1197,13 @@ class AddEjercicioScreenState extends State { if (!snapshot.hasData) { return const CircularProgressIndicator(); } - return Container( - padding: - const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - color: Colors.grey.shade400, - borderRadius: BorderRadius.circular(20), - border: Border.all( - color: AppColors.lightBlueAccentColor, - width: 2, - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // Primer Dropdown para "Músculo Objetivo" + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Text( AppLocalizations.of(context)! .translate('selectMusculoObjetivo'), style: const TextStyle( @@ -1145,22 +1212,96 @@ class AddEjercicioScreenState extends State { color: Colors.black, ), ), - DropdownButtonHideUnderline( + ), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 4), + decoration: BoxDecoration( + color: Colors.grey.shade400, + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppColors.lightBlueAccentColor, + width: 2, + ), + ), + child: DropdownButtonHideUnderline( child: DropdownButton( isExpanded: true, - hint: Text(AppLocalizations.of(context)! - .translate('selectMusculoObjetivo')), + hint: Text(AppLocalizations.of(context)!.translate( + 'selectMusculoObjetivo')), // Este es el hint que aparecerá onChanged: (String? newValue) { - _addBodyPart(newValue!); + if (newValue != null) { + _addBodyPart(newValue); + _updateSpecificMuscleOptions(newValue + .toLowerCase()); // Actualiza el segundo dropdown + } }, items: snapshot.data, - value: snapshot.data!.isNotEmpty - ? snapshot.data?.first.value - : null, + value: _selectedBodyPart.isEmpty + ? null // Si no hay selección, se muestra "Seleccionar músculo objetivo" + : _selectedBodyPart.last + .id, // Si ya se ha seleccionado, muestra el valor correcto ), ), - ], - ), + ), + // Mostrar la tarjeta con la selección del músculo objetivo + // _buildSelectedBodyPart( + // langKey), // Aquí insertamos la tarjeta para el músculo objetivo + + // Segundo Dropdown para "Músculo Objetivo Específico" + if (_selectedBodyPart.isNotEmpty) + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Músculo Específico', + style: Theme.of(context).textTheme.titleMedium, + ), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 4), + decoration: BoxDecoration( + color: Colors.grey.shade400, + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppColors.lightBlueAccentColor, + width: 2, + ), + ), + child: DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + hint: Text('Selecciona músculo específico'), + value: _specificMuscleController.text.isEmpty + ? null + : _specificMuscleController.text, + items: specificMuscleOptions[_selectedBodyPart + .last.bodypartEsp + .toLowerCase()] + ?.map((option) { + return DropdownMenuItem( + value: option, + child: Text(option), + ); + }).toList(), + onChanged: (newValue) { + setState(() { + _specificMuscleController.text = + newValue!; + }); + }, + ), + ), + ), + ], + ), + ), + // Mostrar la tarjeta con la selección del músculo específico + _buildSelectedSpecificMuscle( + langKey), // Aquí insertamos la tarjeta para el músculo específico + ], ); }, ), @@ -1222,7 +1363,6 @@ class AddEjercicioScreenState extends State { const SizedBox(height: 10), _buildStanceSection(), const SizedBox(height: 10), - _buildSelectedObjetivos(langKey), FutureBuilder>>( future: ObjetivosInEjercicioFunctions() @@ -1654,6 +1794,9 @@ class AddEjercicioScreenState extends State { _phaseEng.isNotEmpty && _stanceEsp.isNotEmpty && _stanceEng.isNotEmpty) { + String? specificMuscle = _specificMuscleController.text.isNotEmpty + ? _specificMuscleController.text + : null; await AddEjercicioFunctions().addEjercicioWithAutoIncrementId( nombreEsp: _nameControllerEsp.text, nombreEng: _nameControllerEng.text, @@ -1682,6 +1825,7 @@ class AddEjercicioScreenState extends State { phaseEng: _phaseEng, stanceEsp: _stanceEsp, stanceEng: _stanceEng, + specificMuscle: specificMuscle, ); _showSuccessSnackbar(context); _clearFields(); @@ -1783,6 +1927,7 @@ class AddEjercicioScreenState extends State { _imageUrl = ''; _image3dUrl = ''; _selectedObjetivos.clear(); + _specificMuscleController.clear(); _selectedEquipment.clear(); _selectedBodyPart.clear(); }); diff --git a/lib/backend/ejercicios/add_ejercicio_screen_ori.dart b/lib/backend/ejercicios/add_ejercicio_screen_ori.dart deleted file mode 100644 index 183e776..0000000 --- a/lib/backend/ejercicios/add_ejercicio_screen_ori.dart +++ /dev/null @@ -1,1448 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -import 'package:flutter/material.dart'; -import 'package:fluttertoast/fluttertoast.dart'; -import '../../../config/lang/app_localization.dart'; -import '../../../config/utils/appcolors.dart'; -import 'package:cloud_firestore/cloud_firestore.dart'; - -import '../../functions/ejercicios/add_ejercicios_functions copy.dart'; -import '../../functions/ejercicios/body_part_in_ejercicio_functions.dart'; -import '../../functions/ejercicios/cat_ejercicio_in_ejercicio_functions.dart'; -import '../../functions/ejercicios/equipment_in_ejercicio_functions.dart'; -import '../../functions/ejercicios/objetivo_in_ejercicio_functions.dart'; -import '../../functions/ejercicios/unequipment_in_ejercicio_functions.dart'; -import '../../functions/role_checker.dart'; -import '../../functions/upload_exercise_image.dart'; -import '../models/bodypart_in_ejercicio_model.dart'; -import '../models/equipment_in_ejercicio_model.dart'; -import '../models/objetivos_in_ejercicio_model.dart'; -import '../models/selected_cat_ejercicio_model.dart'; -import '../models/unequipment_in_ejercicio_model.dart'; - -class AddEjercicioScreen extends StatefulWidget { - const AddEjercicioScreen({Key? key}) : super(key: key); - - @override - AddEjercicioScreenState createState() => AddEjercicioScreenState(); -} - -class AddEjercicioScreenState extends State { - final TextEditingController _nameControllerEsp = TextEditingController(); - final TextEditingController _nameControllerEng = TextEditingController(); - final TextEditingController _descriptionControllerEsp = - TextEditingController(); - final TextEditingController _descriptionControllerEng = - TextEditingController(); - final TextEditingController _contenidoControllerEsp = TextEditingController(); - final TextEditingController _contenidoControllerEng = TextEditingController(); - final TextEditingController _caloriasController = TextEditingController(); - final TextEditingController _repeticionesController = TextEditingController(); - final TextEditingController _videoController = TextEditingController(); - - String _imageUrl = ''; - final List _selectedObjetivos = []; - Map> objetivosNames = {}; - - final List _selectedEquipment = []; - Map> equipmentNames = {}; - - final List _selectedUnequipment = []; - Map> unequipmentNames = {}; - - final List _selectedBodyPart = []; - Map> bodypartNames = {}; - - final List _selectedCatEjercicio = []; - Map> catEjercicioNames = {}; - - String _intensityEsp = 'Baja'; - String _intensityEng = 'Low'; - - String _stanceEsp = 'Parado'; - String _stanceEng = 'Standing'; - - String _membershipEsp = 'Gratis'; - String _membershipEng = 'Free'; - - int _selectedMinutes = 0; - int _selectedSeconds = 0; - - @override - void initState() { - super.initState(); - _loadBodyPartNames(); - _loadCatEjercicioNames(); - _loadObjetivosNames(); - _loadEquipmentNames(); - _loadUnequipmentNames(); - _checkAccess(); - } - - Future _checkAccess() async { - bool hasAccess = await checkUserRole(); - if (!hasAccess) { - WidgetsBinding.instance.addPostFrameCallback((_) { - if (mounted) { - _showAccessDeniedDialog(context); - } - }); - } - } - - void _showAccessDeniedDialog(BuildContext context) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text( - AppLocalizations.of(context)!.translate('accessDeniedTitle')), - content: Text( - AppLocalizations.of(context)!.translate('accessDeniedMessage')), - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(AppLocalizations.of(context)!.translate('okButton')), - ), - ], - ); - }, - ); - } - - void _loadObjetivosNames() async { - var snapshot = - await FirebaseFirestore.instance.collection('objetivos').get(); - Map> tempMap = {}; - for (var doc in snapshot.docs) { - tempMap[doc.id] = { - 'Esp': doc['NombreEsp'] ?? 'Nombre no disponible', - 'Eng': doc['NombreEng'] ?? 'Nombre no disponible', - }; - } - setState(() { - objetivosNames = tempMap; - }); - } - - void _loadEquipmentNames() async { - var snapshot = - await FirebaseFirestore.instance.collection('equipment').get(); - Map> tempMap = {}; - for (var doc in snapshot.docs) { - tempMap[doc.id] = { - 'Esp': doc['NombreEsp'] ?? 'Nombre no disponible', - 'Eng': doc['NombreEng'] ?? 'Nombre no disponible', - }; - } - setState(() { - equipmentNames = tempMap; - }); - } - - void _loadUnequipmentNames() async { - var snapshot = - await FirebaseFirestore.instance.collection('unequipment').get(); - Map> tempMap = {}; - for (var doc in snapshot.docs) { - tempMap[doc.id] = { - 'Esp': doc['NombreEsp'] ?? 'Nombre no disponible', - 'Eng': doc['NombreEng'] ?? 'Nombre no disponible', - }; - } - setState(() { - unequipmentNames = tempMap; - }); - } - - void _loadBodyPartNames() async { - var snapshot = await FirebaseFirestore.instance.collection('bodyp').get(); - Map> tempMap = {}; - for (var doc in snapshot.docs) { - tempMap[doc.id] = { - 'Esp': doc['NombreEsp'] ?? 'Nombre no disponible', - 'Eng': doc['NombreEng'] ?? 'Nombre no disponible', - }; - } - setState(() { - bodypartNames = tempMap; - }); - } - - void _loadCatEjercicioNames() async { - var snapshot = - await FirebaseFirestore.instance.collection('catEjercicio').get(); - Map> tempMap = {}; - for (var doc in snapshot.docs) { - int id = int.tryParse(doc.id) ?? 0; - tempMap[id] = { - 'Esp': doc['NombreEsp'] ?? 'Nombre no disponible', - 'Eng': doc['NombreEng'] ?? 'Nombre no disponible', - }; - } - setState(() { - catEjercicioNames = tempMap; - }); - } - - void _addObjetivos(String objetivosId) { - if (!_selectedObjetivos.any((selected) => selected.id == objetivosId)) { - String objetivosEsp = - objetivosNames[objetivosId]?['Esp'] ?? 'Nombre no disponible'; - String objetivosEng = - objetivosNames[objetivosId]?['Eng'] ?? 'Nombre no disponible'; - setState(() { - _selectedObjetivos.add(SelectedObjetivos( - id: objetivosId, - objetivosEsp: objetivosEsp, - objetivosEng: objetivosEng, - )); - }); - } - } - - void _addEquipment(String equipmentId) { - if (!_selectedEquipment.any((selected) => selected.id == equipmentId)) { - String equipmentEsp = - equipmentNames[equipmentId]?['Esp'] ?? 'Nombre no disponible'; - String equipmentEng = - equipmentNames[equipmentId]?['Eng'] ?? 'Nombre no disponible'; - setState(() { - _selectedEquipment.add(SelectedEquipment( - id: equipmentId, - equipmentEsp: equipmentEsp, - equipmentEng: equipmentEng, - )); - }); - } - } - - void _addUnequipment(String unequipmentId) { - if (!_selectedUnequipment.any((selected) => selected.id == unequipmentId)) { - String unequipmentEsp = - unequipmentNames[unequipmentId]?['Esp'] ?? 'Nombre no disponible'; - String unequipmentEng = - unequipmentNames[unequipmentId]?['Eng'] ?? 'Nombre no disponible'; - setState(() { - _selectedUnequipment.add(SelectedUnequipment( - id: unequipmentId, - unequipmentEsp: unequipmentEsp, - unequipmentEng: unequipmentEng, - )); - }); - } - } - - void _addBodyPart(String bodypartId) { - if (!_selectedBodyPart.any((selected) => selected.id == bodypartId)) { - String bodypartEsp = - bodypartNames[bodypartId]?['Esp'] ?? 'Nombre no disponible'; - String bodypartEng = - bodypartNames[bodypartId]?['Eng'] ?? 'Nombre no disponible'; - setState(() { - _selectedBodyPart.add(SelectedBodyPart( - id: bodypartId, - bodypartEsp: bodypartEsp, - bodypartEng: bodypartEng, - )); - }); - } - } - - void _addCatEjercicio(int catEjercicioId) { - if (!_selectedCatEjercicio - .any((selected) => selected.id == catEjercicioId)) { - String catEjercicioEsp = - catEjercicioNames[catEjercicioId]?['Esp'] ?? 'Nombre no disponible'; - String catEjercicioEng = - catEjercicioNames[catEjercicioId]?['Eng'] ?? 'Nombre no disponible'; - setState(() { - _selectedCatEjercicio.add(SelectedCatEjercicio( - id: catEjercicioId, - nombreEsp: catEjercicioEsp, - nombreEng: catEjercicioEng, - )); - }); - } - } - - void _removeObjetivos(String objetivosId) { - setState(() { - _selectedObjetivos - .removeWhere((objetivos) => objetivos.id == objetivosId); - }); - } - - void _removeEquipment(String equipmentId) { - setState(() { - _selectedEquipment - .removeWhere((equipment) => equipment.id == equipmentId); - }); - } - - void _removeUnequipment(String unequipmentId) { - setState(() { - _selectedUnequipment - .removeWhere((unequipment) => unequipment.id == unequipmentId); - }); - } - - void _removeBodyPart(String bodypartId) { - setState(() { - _selectedBodyPart.removeWhere((bodypart) => bodypart.id == bodypartId); - }); - } - - void _removeCatEjercicio(int catEjercicioId) { - setState(() { - _selectedCatEjercicio - .removeWhere((catEjercicio) => catEjercicio.id == catEjercicioId); - }); - } - - Widget _buildMembershipSection() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('exerciseMembership'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - _buildMembershipSelector(), - ], - ); - } - - Widget _buildMembershipSelector() { - Locale currentLocale = Localizations.localeOf(context); - bool isEsp = currentLocale.languageCode == "es"; - - List optionsEsp = ['Gratis', 'Premium']; - List optionsEng = ['Free', 'Premium']; - - Map membershipMapEspToEng = { - 'Gratis': 'Free', - 'Premium': 'Premium', - }; - - Map membershipMapEngToEsp = { - 'Free': 'Gratis', - 'Premium': 'Premium', - }; - - List options = isEsp ? optionsEsp : optionsEng; - String currentMembership = isEsp ? _membershipEsp : _membershipEng; - - return Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: options.map((option) { - bool selected = isEsp - ? option == currentMembership - : membershipMapEspToEng[_membershipEsp] == option; - - return ChoiceChip( - label: Text(option), - selected: selected, - onSelected: (bool isSelected) { - setState(() { - if (isEsp) { - _membershipEsp = option; - _membershipEng = membershipMapEspToEng[option]!; - } else { - _membershipEng = option; - _membershipEsp = membershipMapEngToEsp[option]!; - } - }); - }, - ); - }).toList(), - ); - } - - Widget _buildIntensitySection() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('exerciseIntensity'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - _buildIntensitySelector(), - ], - ); - } - - Widget _buildIntensitySelector() { - Locale currentLocale = Localizations.localeOf(context); - bool isEsp = currentLocale.languageCode == "es"; - - List optionsEsp = ['Baja', 'Media', 'Alta']; - List optionsEng = ['Low', 'Medium', 'High']; - - Map intensityMapEspToEng = { - 'Baja': 'Low', - 'Media': 'Medium', - 'Alta': 'High', - }; - - Map intensityMapEngToEsp = { - 'Low': 'Baja', - 'Medium': 'Media', - 'High': 'Alta', - }; - - List options = isEsp ? optionsEsp : optionsEng; - - return Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: options.map((option) { - bool selected; - if (isEsp) { - selected = _intensityEsp == option; - } else { - String? equivalentInEng = intensityMapEspToEng[_intensityEsp]; - selected = equivalentInEng == option; - } - return ChoiceChip( - label: Text(option), - selected: selected, - onSelected: (bool isSelected) { - setState(() { - if (isEsp) { - _intensityEsp = option; - _intensityEng = intensityMapEspToEng[option]!; - } else { - _intensityEng = option; - _intensityEsp = intensityMapEngToEsp[option]!; - } - }); - }, - ); - }).toList(), - ); - } - - Widget _buildTimeSelectionSection() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('selectTime'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - _buildTimeSelector(), - ], - ); - } - - Widget _buildTimeSelector() { - return Container( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: DropdownButton( - isExpanded: true, - value: _selectedMinutes, - items: List.generate(60, (index) => index) - .map>((int value) { - return DropdownMenuItem( - value: value, - child: Center(child: Text("$value min")), - ); - }).toList(), - onChanged: (newValue) { - setState(() { - _selectedMinutes = newValue!; - }); - }, - underline: Container( - height: 2, - color: Theme.of(context).primaryColor, - ), - ), - ), - const SizedBox(width: 10), - Expanded( - child: DropdownButton( - isExpanded: true, - value: _selectedSeconds, - items: List.generate(60, (index) => index) - .map>((int value) { - return DropdownMenuItem( - value: value, - child: Center( - child: Text("${value.toString().padLeft(2, '0')} seg")), - ); - }).toList(), - onChanged: (newValue) { - setState(() { - _selectedSeconds = newValue!; - }); - }, - underline: Container( - height: 2, - color: Theme.of(context).primaryColor, - ), - ), - ), - ], - ), - ); - } - - Widget _buildStanceSection() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('exerciseStance'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - _buildStanceSelector(), - ], - ); - } - - Widget _buildStanceSelector() { - Locale currentLocale = Localizations.localeOf(context); - bool isEsp = currentLocale.languageCode == "es"; - - List optionsEsp = [ - 'Parado', - 'Sentado', - 'Acostado', - 'Saltando', - 'Corriendo' - ]; - List optionsEng = [ - 'Standing', - 'Sitting', - 'Lying Down', - 'Jumping', - 'Running' - ]; - - Map stanceMapEspToEng = { - 'Parado': 'Standing', - 'Sentado': 'Sitting', - 'Acostado': 'Lying Down', - 'Saltando': 'Jumping', - 'Corriendo': 'Running', - }; - - Map stanceMapEngToEsp = { - 'Standing': 'Parado', - 'Sitting': 'Sentado', - 'Lying Down': 'Acostado', - 'Jumping': 'Saltando', - 'Running': 'Corriendo', - }; - - List options = isEsp ? optionsEsp : optionsEng; - - return Wrap( - spacing: 8.0, - runSpacing: 4.0, - alignment: WrapAlignment.spaceEvenly, - children: options.map((option) { - bool selected; - if (isEsp) { - selected = _stanceEsp == option; - } else { - String? equivalentInEng = stanceMapEspToEng[_stanceEsp]; - selected = equivalentInEng == option; - } - return ChoiceChip( - label: Text(option), - selected: selected, - onSelected: (bool isSelected) { - setState(() { - if (isEsp) { - _stanceEsp = option; - _stanceEng = stanceMapEspToEng[option]!; - } else { - _stanceEng = option; - _stanceEsp = stanceMapEngToEsp[option]!; - } - }); - }, - ); - }).toList(), - ); - } - - Widget _buildSelectedObjetivos(String langKey) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('ocjetives'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - Wrap( - spacing: 8.0, - children: _selectedObjetivos.map((objetivos) { - String objetivosName = langKey == 'Esp' - ? objetivos.objetivosEsp - : objetivos.objetivosEng; - return Chip( - label: Text(objetivosName), - onDeleted: () => _removeObjetivos(objetivos.id), - ); - }).toList(), - ), - ], - ); - } - - Widget _buildSelectedEquipment(String langKey) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('equipments'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - Wrap( - spacing: 8.0, - children: _selectedEquipment.map((equipment) { - String equipmentName = langKey == 'Esp' - ? equipment.equipmentEsp - : equipment.equipmentEng; - return Chip( - label: Text(equipmentName), - onDeleted: () => _removeEquipment(equipment.id), - ); - }).toList(), - ), - ], - ); - } - - Widget _buildSelectedUnequipment(String langKey) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('unequipments'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - Wrap( - spacing: 8.0, - children: _selectedUnequipment.map((unequipment) { - String unequipmentName = langKey == 'Esp' - ? unequipment.unequipmentEsp - : unequipment.unequipmentEng; - return Chip( - label: Text(unequipmentName), - onDeleted: () => _removeUnequipment(unequipment.id), - ); - }).toList(), - ), - ], - ); - } - - Widget _buildSelectedBodyPart(String langKey) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('bodyParts'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - Wrap( - spacing: 8.0, - children: _selectedBodyPart.map((bodypart) { - String bodypartName = - langKey == 'Esp' ? bodypart.bodypartEsp : bodypart.bodypartEng; - return Chip( - label: Text(bodypartName), - onDeleted: () => _removeBodyPart(bodypart.id), - ); - }).toList(), - ), - ], - ); - } - - Widget _buildSelectedCatEjercicio(String langKey) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('catEjercicios'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - Wrap( - spacing: 8.0, - children: _selectedCatEjercicio.map((catEjercicio) { - String catEjercicioName = langKey == 'Esp' - ? catEjercicio.nombreEsp - : catEjercicio.nombreEng; - return Chip( - label: Text(catEjercicioName), - onDeleted: () => _removeCatEjercicio(catEjercicio.id), - ); - }).toList(), - ), - ], - ); - } - - @override - Widget build(BuildContext context) { - List tabs = [ - Tab(text: AppLocalizations.of(context)!.translate('español')), - Tab(text: AppLocalizations.of(context)!.translate('english')), - ]; - - final tabLabelStyle = - Theme.of(context).textTheme.labelLarge?.copyWith(fontSize: 26); - final tabUnselectedLabelColor = - Theme.of(context).brightness == Brightness.light - ? Colors.grey - : Colors.white70; - final tabSelectedLabelColor = - Theme.of(context).brightness == Brightness.light - ? Colors.black - : Colors.white; - - return DefaultTabController( - length: 2, - child: Scaffold( - appBar: AppBar( - leading: IconButton( - icon: const Icon(Icons.arrow_back), - onPressed: () => Navigator.of(context).pop(), - ), - title: Text(AppLocalizations.of(context)!.translate('addEjercicio')), - bottom: TabBar( - tabs: tabs, - labelStyle: tabLabelStyle, - unselectedLabelColor: tabUnselectedLabelColor, - labelColor: tabSelectedLabelColor, - indicatorColor: AppColors.lightBlueAccentColor, - indicatorWeight: 3, - ), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(bottom: Radius.circular(20)), - ), - ), - body: TabBarView( - children: [ - _buildEjercicioForm( - _nameControllerEsp, - _descriptionControllerEsp, - _contenidoControllerEsp, - _caloriasController, - _repeticionesController, - _videoController, - _intensityEsp, - _stanceEsp, - _membershipEsp, - 'Esp'), - _buildEjercicioForm( - _nameControllerEng, - _descriptionControllerEng, - _contenidoControllerEng, - _caloriasController, - _repeticionesController, - _videoController, - _intensityEng, - _stanceEng, - _membershipEng, - 'Eng'), - ], - ), - ), - ); - } - - Widget _buildEjercicioForm( - TextEditingController nameController, - TextEditingController descriptionController, - TextEditingController contenidoController, - TextEditingController caloriasController, - TextEditingController videoController, - TextEditingController repeticionesController, - String intensity, - String stance, - String membership, - String langKey) { - OutlineInputBorder borderStyle = OutlineInputBorder( - borderRadius: BorderRadius.circular(20), - borderSide: BorderSide(color: Colors.grey.shade300), - ); - - Color textColor = Theme.of(context).brightness == Brightness.dark - ? AppColors.darkBlueColor - : Colors.black; - - return SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('ejercicioName'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - TextFormField( - controller: nameController, - style: TextStyle(color: textColor), - decoration: InputDecoration( - labelText: - '${AppLocalizations.of(context)!.translate('ejercicioName')} ($langKey)', - hintText: AppLocalizations.of(context)! - .translate('enterEjercicioName'), - border: borderStyle, - enabledBorder: borderStyle, - focusedBorder: borderStyle.copyWith( - borderSide: const BorderSide( - color: AppColors.lightBlueAccentColor, width: 2), - ), - filled: true, - fillColor: Colors.grey.shade100, - ), - ), - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('ejercicioDescription'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - TextFormField( - controller: descriptionController, - maxLines: 3, - style: TextStyle(color: textColor), - decoration: InputDecoration( - labelText: - '${AppLocalizations.of(context)!.translate('ejercicioDescription')} ($langKey)', - hintText: AppLocalizations.of(context)! - .translate('enterEjercicioDescription'), - border: borderStyle, - enabledBorder: borderStyle, - focusedBorder: borderStyle.copyWith( - borderSide: const BorderSide( - color: AppColors.lightBlueAccentColor, width: 2), - ), - filled: true, - fillColor: Colors.grey.shade100, - ), - ), - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('content'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - TextFormField( - controller: contenidoController, - maxLines: 3, - style: TextStyle(color: textColor), - decoration: InputDecoration( - labelText: - '${AppLocalizations.of(context)!.translate('content')} ($langKey)', - hintText: - AppLocalizations.of(context)!.translate('enterContent'), - border: borderStyle, - enabledBorder: borderStyle, - focusedBorder: borderStyle.copyWith( - borderSide: const BorderSide( - color: AppColors.lightBlueAccentColor, width: 2), - ), - filled: true, - fillColor: Colors.grey.shade100, - ), - ), - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('repeticionesName'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - TextFormField( - controller: videoController, - style: TextStyle(color: textColor), - decoration: InputDecoration( - labelText: - '${AppLocalizations.of(context)!.translate('repeticionesName')} ($langKey)', - hintText: AppLocalizations.of(context)! - .translate('enterRepeticionesName'), - border: borderStyle, - enabledBorder: borderStyle, - focusedBorder: borderStyle.copyWith( - borderSide: const BorderSide( - color: AppColors.lightBlueAccentColor, width: 2), - ), - filled: true, - fillColor: Colors.grey.shade100, - ), - keyboardType: TextInputType.number, - ), - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('caloriasName'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - TextFormField( - controller: caloriasController, - style: TextStyle(color: textColor), - decoration: InputDecoration( - labelText: - '${AppLocalizations.of(context)!.translate('caloriasName')} ($langKey)', - hintText: AppLocalizations.of(context)! - .translate('enterCaloriasName'), - border: borderStyle, - enabledBorder: borderStyle, - focusedBorder: borderStyle.copyWith( - borderSide: const BorderSide( - color: AppColors.lightBlueAccentColor, width: 2), - ), - filled: true, - fillColor: Colors.grey.shade100, - ), - keyboardType: TextInputType.number, - ), - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('videoLink'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - TextFormField( - controller: repeticionesController, - style: TextStyle(color: textColor), - decoration: InputDecoration( - labelText: - '${AppLocalizations.of(context)!.translate('videoLink')} ($langKey)', - hintText: - AppLocalizations.of(context)!.translate('enterVideoLink'), - border: borderStyle, - enabledBorder: borderStyle, - focusedBorder: borderStyle.copyWith( - borderSide: const BorderSide( - color: AppColors.lightBlueAccentColor, width: 2), - ), - filled: true, - fillColor: Colors.grey.shade100, - ), - ), - const SizedBox(height: 15), - _buildMembershipSection(), - const SizedBox(height: 15), - _buildIntensitySection(), - const SizedBox(height: 15), - _buildStanceSection(), - const SizedBox(height: 15), - _buildTimeSelectionSection(), - const SizedBox(height: 15), - _buildSelectedBodyPart(langKey), - FutureBuilder>>( - future: - BodyPartInEjercicioFunctions().getSimplifiedBodyPart(langKey), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return const CircularProgressIndicator(); - } - return Container( - padding: - const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - color: Colors.grey.shade400, - borderRadius: BorderRadius.circular(20), - border: Border.all( - color: AppColors.lightBlueAccentColor, - width: 2, - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - AppLocalizations.of(context)! - .translate('selectBodyPart'), - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 18, - color: Colors.black, - ), - ), - DropdownButtonHideUnderline( - child: DropdownButton( - isExpanded: true, - hint: Text(AppLocalizations.of(context)! - .translate('selectBodyPart')), - onChanged: (String? newValue) { - _addBodyPart(newValue!); - }, - items: snapshot.data, - value: snapshot.data!.isNotEmpty - ? snapshot.data?.first.value - : null, - ), - ), - ], - ), - ); - }, - ), - const SizedBox(height: 20), - _buildSelectedCatEjercicio(langKey), - FutureBuilder>>( - future: CatEjercicioInEjercicioFunctions() - .getSimplifiedCatEjercicio(langKey), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return const CircularProgressIndicator(); - } - return Container( - padding: - const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - color: Colors.grey.shade400, - borderRadius: BorderRadius.circular(20), - border: Border.all( - color: AppColors.lightBlueAccentColor, - width: 2, - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - AppLocalizations.of(context)! - .translate('selectCatEjercicio'), - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 18, - color: Colors.black, - ), - ), - DropdownButtonHideUnderline( - child: DropdownButton( - isExpanded: true, - hint: Text(AppLocalizations.of(context)! - .translate('selectCatEjercicio')), - onChanged: (int? newValue) { - _addCatEjercicio(newValue!); - }, - items: snapshot.data, - value: snapshot.data!.isNotEmpty - ? snapshot.data?.first.value - : null, - ), - ), - ], - ), - ); - }, - ), - const SizedBox(height: 20), - _buildSelectedObjetivos(langKey), - FutureBuilder>>( - future: ObjetivosInEjercicioFunctions() - .getSimplifiedObjetivos(langKey), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return const CircularProgressIndicator(); - } - return Container( - padding: - const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - color: Colors.grey.shade400, - borderRadius: BorderRadius.circular(20), - border: Border.all( - color: AppColors.lightBlueAccentColor, - width: 2, - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - AppLocalizations.of(context)! - .translate('selectObjetivo'), - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 18, - color: Colors.black, - ), - ), - DropdownButtonHideUnderline( - child: DropdownButton( - isExpanded: true, - hint: Text(AppLocalizations.of(context)! - .translate('selectObjetivos')), - onChanged: (String? newValue) { - _addObjetivos(newValue!); - }, - items: snapshot.data, - value: snapshot.data!.isNotEmpty - ? snapshot.data?.first.value - : null, - ), - ), - ], - ), - ); - }, - ), - const SizedBox(height: 20), - _buildSelectedEquipment(langKey), - FutureBuilder>>( - future: EquipmentInEjercicioFunctions() - .getSimplifiedEquipment(langKey), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return const CircularProgressIndicator(); - } - return Container( - padding: - const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - color: Colors.grey.shade400, - borderRadius: BorderRadius.circular(20), - border: Border.all( - color: AppColors.lightBlueAccentColor, - width: 2, - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - AppLocalizations.of(context)! - .translate('selectEquipment'), - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 18, - color: Colors.black, - ), - ), - DropdownButtonHideUnderline( - child: DropdownButton( - isExpanded: true, - hint: Text(AppLocalizations.of(context)! - .translate('selectEquipment')), - onChanged: (String? newValue) { - _addEquipment(newValue!); - }, - items: snapshot.data, - value: snapshot.data!.isNotEmpty - ? snapshot.data?.first.value - : null, - ), - ), - ], - ), - ); - }, - ), - const SizedBox(height: 20), - _buildSelectedUnequipment(langKey), - FutureBuilder>>( - future: UnequipmentInEjercicioFunctions() - .getSimplifiedUnequipment(langKey), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return const CircularProgressIndicator(); - } - return Container( - padding: - const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - color: Colors.grey.shade400, - borderRadius: BorderRadius.circular(20), - border: Border.all( - color: AppColors.lightBlueAccentColor, - width: 2, - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - AppLocalizations.of(context)! - .translate('selectUnequipment'), - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 18, - color: Colors.black, - ), - ), - DropdownButtonHideUnderline( - child: DropdownButton( - isExpanded: true, - hint: Text(AppLocalizations.of(context)! - .translate('selectUnequipment')), - onChanged: (String? newValue) { - _addUnequipment(newValue!); - }, - items: snapshot.data, - value: snapshot.data!.isNotEmpty - ? snapshot.data?.first.value - : null, - ), - ), - ], - ), - ); - }, - ), - const SizedBox(height: 20), - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text( - AppLocalizations.of(context)!.translate('image'), - style: Theme.of(context).textTheme.titleMedium, - ), - ), - _buildImagePreview(), - const SizedBox(height: 20), - _buildImageUploadButton(), - const SizedBox(height: 20), - _buildPublishButton(), - ], - ), - ), - ); - } - - Widget _buildImagePreview() { - return InkWell( - onTap: () async { - await uploadExerciseImage(context, (String url) { - setState(() { - _imageUrl = url; - }); - }); - }, - child: _imageUrl.isNotEmpty - ? ClipRRect( - borderRadius: BorderRadius.circular(20), - child: Image.network(_imageUrl, height: 200, fit: BoxFit.cover), - ) - : Container( - height: 200, - decoration: BoxDecoration( - color: Colors.grey[300], - borderRadius: BorderRadius.circular(20), - border: Border.all(color: Colors.grey.shade400), - ), - child: Icon(Icons.photo, size: 50, color: Colors.grey.shade600), - ), - ); - } - - Widget _buildImageUploadButton() { - return _buildCustomButton( - context, - 'Subir Imagen', - () async { - await uploadExerciseImage(context, (String url) { - setState(() { - _imageUrl = url; - }); - }); - }, - ); - } - - Widget _buildPublishButton() { - return _buildCustomButton( - context, - 'Publicar', - () async { - String formattedTime = - '${_selectedMinutes.toString().padLeft(2, '0')}:${_selectedSeconds.toString().padLeft(2, '0')}'; - if (_nameControllerEsp.text.isNotEmpty && - _descriptionControllerEsp.text.isNotEmpty && - _contenidoControllerEsp.text.isNotEmpty && - _videoController.text.isNotEmpty && - _nameControllerEng.text.isNotEmpty && - _descriptionControllerEng.text.isNotEmpty && - _contenidoControllerEng.text.isNotEmpty && - _caloriasController.text.isNotEmpty && - _repeticionesController.text.isNotEmpty && - _imageUrl.isNotEmpty && - _selectedObjetivos.isNotEmpty && - _selectedEquipment.isNotEmpty && - _selectedUnequipment.isNotEmpty && - _selectedBodyPart.isNotEmpty && - _selectedCatEjercicio.isNotEmpty && - _membershipEsp.isNotEmpty && - _membershipEng.isNotEmpty && - _intensityEsp.isNotEmpty && - _intensityEng.isNotEmpty && - _stanceEsp.isNotEmpty && - _stanceEng.isNotEmpty) { - await AddEjercicioFunctions().addEjercicioWithAutoIncrementId( - nombreEsp: _nameControllerEsp.text, - nombreEng: _nameControllerEng.text, - descripcionEsp: _descriptionControllerEsp.text, - descripcionEng: _descriptionControllerEng.text, - contenidoEsp: _contenidoControllerEsp.text, - calorias: _caloriasController.text, - repeticiones: _repeticionesController.text, - contenidoEng: _contenidoControllerEng.text, - video: _videoController.text, - imageUrl: _imageUrl, - selectedObjetivos: _selectedObjetivos, - selectedEquipment: _selectedEquipment, - selectedUnequipment: _selectedUnequipment, - selectedBodyPart: _selectedBodyPart, - selectedCatEjercicio: _selectedCatEjercicio, - membershipEsp: _membershipEsp, - membershipEng: _membershipEng, - intensityEsp: _intensityEsp, - intensityEng: _intensityEng, - stanceEsp: _stanceEsp, - stanceEng: _stanceEng, - duracion: formattedTime, - ); - _showSuccessSnackbar(context); - _clearFields(); - _sendCountToTotalExercises(); - Navigator.pop(context, true); - } else { - _showErrorSnackbar(context); - } - }, - ); - } - - void _sendCountToTotalExercises() async { - try { - final totalExercisesRef = FirebaseFirestore.instance - .collection('totalexercises') - .doc('contador'); - await totalExercisesRef.set({ - 'total': FieldValue.increment(1), - }, SetOptions(merge: true)); - } catch (error) { - //print('Error al enviar el conteo a totalexercises: $error'); - } - } - - Widget _buildCustomButton( - BuildContext context, String translationKey, VoidCallback onPressed) { - final ThemeData theme = Theme.of(context); - final bool isDarkTheme = theme.brightness == Brightness.dark; - - final Color backgroundColor = isDarkTheme - ? AppColors.deepPurpleColor - : AppColors.lightBlueAccentColor; - const Color textColor = Colors.white; - - return ElevatedButton( - onPressed: onPressed, - style: ElevatedButton.styleFrom( - foregroundColor: textColor, - backgroundColor: backgroundColor, - padding: const EdgeInsets.symmetric(horizontal: 40.0, vertical: 20.0), - textStyle: theme.textTheme.titleLarge?.copyWith(color: textColor), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(30), - ), - side: BorderSide(color: backgroundColor), - elevation: 5, - ), - child: Text(AppLocalizations.of(context)!.translate(translationKey)), - ); - } - - void _showSuccessSnackbar(BuildContext context) { - Fluttertoast.showToast( - msg: AppLocalizations.of(context)!.translate('ejercicioAdded'), - toastLength: Toast.LENGTH_SHORT, - gravity: ToastGravity.BOTTOM, - backgroundColor: Colors.green, - textColor: Colors.white, - fontSize: 24.0, - ); - } - - void _showErrorSnackbar(BuildContext context) { - Fluttertoast.showToast( - msg: AppLocalizations.of(context)!.translate('publishErrorMessage'), - toastLength: Toast.LENGTH_SHORT, - gravity: ToastGravity.BOTTOM, - backgroundColor: Colors.red, - textColor: Colors.white, - fontSize: 24.0, - ); - } - - void _clearFields() { - _nameControllerEsp.clear(); - _nameControllerEng.clear(); - _descriptionControllerEsp.clear(); - _descriptionControllerEng.clear(); - _contenidoControllerEsp.clear(); - _contenidoControllerEng.clear(); - _videoController.clear(); - _caloriasController.clear(); - _repeticionesController.clear(); - _intensityEng = 'Low'; - _intensityEsp = 'Baja'; - _stanceEng = 'Parado'; - _stanceEng = 'Standing'; - _membershipEsp = 'Gratis'; - _membershipEng = 'Free'; - setState(() { - _imageUrl = ''; - _selectedObjetivos.clear(); - _selectedEquipment.clear(); - _selectedUnequipment.clear(); - _selectedBodyPart.clear(); - _selectedCatEjercicio.clear(); - }); - } -} diff --git a/lib/filtros/filter_dialog.dart b/lib/filtros/filter_dialog.dart new file mode 100644 index 0000000..b5a60b4 --- /dev/null +++ b/lib/filtros/filter_dialog.dart @@ -0,0 +1,200 @@ +// lib/widgets/filter_dialog.dart + +import 'package:flutter/material.dart'; +import '../config/lang/app_localization.dart'; +import 'widgets/BodyPartDropdownWidget.dart'; +import 'widgets/CalentamientoEspecificoDropdownWidget.dart'; +import 'widgets/DificultyDropdownWidget.dart'; +import 'widgets/EquipmentDropdownWidget.dart'; +import 'widgets/IntensityDropdownWidget.dart'; +import 'widgets/MembershipDropdownWidget.dart'; +import 'widgets/NivelDeImpactoDropdownWidget.dart'; +import 'widgets/ObjetivosDropdownWidget.dart'; +import 'widgets/PosturaDropdownWidget.dart'; + +class FilterDialog extends StatelessWidget { + const FilterDialog({ + Key? key, + required this.onFilterApplied, + }) : super(key: key); + + final Function( + String? selectedBodyPart, + String? selectedCalentamiento, + String? selectedEquipment, + String? selectedImpactLevel, + String? selectedPosture, + String? selectedDificulty, + String? selectedObjective, + String? selectedIntensity, + String? selectedMembership, + ) onFilterApplied; + + @override + Widget build(BuildContext context) { + String? selectedBodyPart; + String? selectedCalentamiento; + String? selectedEquipment; + String? selectedImpactLevel; + String? selectedPosture; + String? selectedDificulty; + String? selectedObjective; + String? selectedIntensity; + String? selectedMembership; + + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + child: Container( + height: MediaQuery.of(context).size.height * 0.8, + child: Column( + children: [ + Align( + alignment: Alignment.topRight, + child: IconButton( + icon: Icon(Icons.close, color: Colors.red), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ), + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + AppLocalizations.of(context)!.translate('filterTitle'), + style: Theme.of(context).textTheme.titleLarge, + ), + const SizedBox(height: 20), + + // Dropdown de BodyPart + BodyPartDropdownWidget( + langKey: 'Esp', + onChanged: (List value) { + selectedBodyPart = value.isNotEmpty + ? value.last.bodypartEsp + : null; + }, + ), + + const SizedBox(height: 20), + + // Otros Dropdowns + CalentamientoEspecificoDropdownWidget( + langKey: 'Esp', + onChanged: + (List value) { + selectedCalentamiento = value.isNotEmpty + ? value.last.CalentamientoEspecificoEsp + : null; + }, + ), + + const SizedBox(height: 20), + + EquipmentDropdownWidget( + langKey: 'Esp', + onChanged: (value) { + selectedEquipment = value; + }, + ), + const SizedBox(height: 20), + + NivelDeImpactoDropdownWidget( + langKey: 'Esp', + onChanged: (List value) { + selectedImpactLevel = value.isNotEmpty + ? value.last + : null; + }, + ), + + const SizedBox(height: 20), + + PosturaDropdownWidget( + langKey: 'Esp', + onChanged: (value) { + selectedPosture = value; + }, + ), + const SizedBox(height: 20), + + DificultyDropdownWidget( + langKey: 'Esp', + onChanged: (value) { + selectedDificulty = value; + }, + ), + const SizedBox(height: 20), + + ObjetivosDropdownWidget( + langKey: 'Esp', + onChanged: (value) { + selectedObjective = value; + }, + ), + const SizedBox(height: 20), + + IntensityDropdownWidget( + langKey: 'Esp', + onChanged: (value) { + selectedIntensity = value; + }, + ), + const SizedBox(height: 20), + + MembershipDropdownWidget( + langKey: 'Esp', + onChanged: (value) { + selectedMembership = value; + }, + ), + ], + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ElevatedButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text( + AppLocalizations.of(context)!.translate('cancel')), + ), + ElevatedButton( + onPressed: () { + onFilterApplied( + selectedBodyPart, + selectedCalentamiento, + selectedEquipment, + selectedImpactLevel, + selectedPosture, + selectedDificulty, + selectedObjective, + selectedIntensity, + selectedMembership, + ); + Navigator.of(context).pop(); + }, + child: Text( + AppLocalizations.of(context)!.translate('filter')), + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/filtros/widgets/BodyPartDropdownWidget.dart b/lib/filtros/widgets/BodyPartDropdownWidget.dart new file mode 100644 index 0000000..a4bfaa2 --- /dev/null +++ b/lib/filtros/widgets/BodyPartDropdownWidget.dart @@ -0,0 +1,187 @@ +import 'package:flutter/material.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import '../../../config/lang/app_localization.dart'; +import '../../../config/utils/appcolors.dart'; + +// Definición de la clase para las partes del cuerpo seleccionadas +class SelectedBodyPart { + final String id; + final String bodypartEsp; + final String bodypartEng; + + SelectedBodyPart({ + required this.id, + required this.bodypartEsp, + required this.bodypartEng, + }); +} + +class BodyPartDropdownWidget extends StatefulWidget { + final String langKey; + final Function(List) onChanged; + + const BodyPartDropdownWidget({ + Key? key, + required this.langKey, + required this.onChanged, // Añadido aquí + }) : super(key: key); + + @override + _BodyPartDropdownWidgetState createState() => _BodyPartDropdownWidgetState(); +} + +class _BodyPartDropdownWidgetState extends State { + final List _selectedBodyPart = []; + Map> bodypartNames = {}; + + // Cargar los nombres de las partes del cuerpo desde Firestore + @override + void initState() { + super.initState(); + _loadBodyPartNames(); + } + + void _loadBodyPartNames() async { + var snapshot = await FirebaseFirestore.instance.collection('bodyp').get(); + Map> tempMap = {}; + for (var doc in snapshot.docs) { + tempMap[doc.id] = { + 'Esp': doc['NombreEsp'] ?? 'Nombre no disponible', + 'Eng': doc['NombreEng'] ?? 'Nombre no disponible', + }; + } + setState(() { + bodypartNames = tempMap; + }); + } + + // void _addBodyPart(String bodypartId) { + // if (!_selectedBodyPart.any((selected) => selected.id == bodypartId)) { + // String bodypartEsp = + // bodypartNames[bodypartId]?['Esp'] ?? 'Nombre no disponible'; + // String bodypartEng = + // bodypartNames[bodypartId]?['Eng'] ?? 'Nombre no disponible'; + // setState(() { + // _selectedBodyPart.add(SelectedBodyPart( + // id: bodypartId, + // bodypartEsp: bodypartEsp, + // bodypartEng: bodypartEng, + // )); + // }); + // } + // } + + void _removeBodyPart(String bodypartId) { + setState(() { + _selectedBodyPart.removeWhere((bodypart) => bodypart.id == bodypartId); + }); + } + + // Widget que muestra las partes del cuerpo seleccionadas + Widget _buildSelectedBodyPart(String langKey) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Text( + AppLocalizations.of(context)!.translate('zonaObjetivo'), + style: Theme.of(context).textTheme.titleMedium, + ), + ), + Wrap( + spacing: 8.0, + children: _selectedBodyPart.map((bodypart) { + String bodypartName = + langKey == 'Esp' ? bodypart.bodypartEsp : bodypart.bodypartEng; + return Chip( + label: Text(bodypartName), + onDeleted: () => _removeBodyPart(bodypart.id), + ); + }).toList(), + ), + ], + ); + } + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Mostrar las partes del cuerpo seleccionadas + _buildSelectedBodyPart(widget.langKey), + // Dropdown de partes del cuerpo + FutureBuilder>>( + future: _getSimplifiedBodyPart(widget.langKey), + builder: (context, snapshot) { + if (!snapshot.hasData) { + return const CircularProgressIndicator(); + } + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + decoration: BoxDecoration( + color: Colors.grey.shade400, + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppColors.lightBlueAccentColor, + width: 2, + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + hint: Text(AppLocalizations.of(context)! + .translate('selectMusculoObjetivo')), + // BodyPartDropdownWidget + onChanged: (String? value) { + if (value != null) { + print( + 'Selected BodyPart ID: $value'); // Esto debería mostrar el id de la parte del cuerpo seleccionada. + setState(() { + _selectedBodyPart.add(SelectedBodyPart( + id: value, + bodypartEsp: bodypartNames[value]?['Esp'] ?? + 'Nombre no disponible', + bodypartEng: bodypartNames[value]?['Eng'] ?? + 'Nombre no disponible', + )); + }); + widget.onChanged( + _selectedBodyPart); // Esto pasa la lista de partes seleccionadas + } + }, + + items: snapshot.data, + value: snapshot.data!.isNotEmpty + ? snapshot.data?.first.value + : null, + ), + ), + ], + ), + ); + }, + ), + ], + ); + } + + // Método para obtener las partes del cuerpo simplificadas desde Firestore + Future>> _getSimplifiedBodyPart( + String langKey) async { + var snapshot = await FirebaseFirestore.instance.collection('bodyp').get(); + return snapshot.docs.map((doc) { + String bodypartName = + langKey == 'Esp' ? doc['NombreEsp'] : doc['NombreEng']; + return DropdownMenuItem( + value: doc.id, + child: Text(bodypartName), + ); + }).toList(); + } +} diff --git a/lib/filtros/widgets/CalentamientoEspecificoDropdownWidget.dart b/lib/filtros/widgets/CalentamientoEspecificoDropdownWidget.dart new file mode 100644 index 0000000..5409908 --- /dev/null +++ b/lib/filtros/widgets/CalentamientoEspecificoDropdownWidget.dart @@ -0,0 +1,186 @@ +import 'package:flutter/material.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import '../../../config/lang/app_localization.dart'; +import '../../../config/utils/appcolors.dart'; + +// Definición de la clase para los calentamientos específicos seleccionados +class SelectedCalentamientoEspecifico { + final String id; + final String CalentamientoEspecificoEsp; + final String CalentamientoEspecificoEng; + + SelectedCalentamientoEspecifico({ + required this.id, + required this.CalentamientoEspecificoEsp, + required this.CalentamientoEspecificoEng, + }); +} + +class CalentamientoEspecificoDropdownWidget extends StatefulWidget { + final String langKey; + final Function(List) onChanged; + + const CalentamientoEspecificoDropdownWidget({ + Key? key, + required this.langKey, + required this.onChanged, // Añadido aquí + }) : super(key: key); + + @override + _CalentamientoEspecificoDropdownWidgetState createState() => + _CalentamientoEspecificoDropdownWidgetState(); +} + +class _CalentamientoEspecificoDropdownWidgetState + extends State { + final List _selectedCalentamientoEspecifico = + []; + Map> CalentamientoEspecificoNames = {}; + + // Cargar los nombres de los calentamientos específicos desde Firestore + @override + void initState() { + super.initState(); + _loadCalentamientoEspecificoNames(); + } + + void _loadCalentamientoEspecificoNames() async { + var snapshot = + await FirebaseFirestore.instance.collection('calentamientoE').get(); + Map> tempMap = {}; + for (var doc in snapshot.docs) { + tempMap[doc.id] = { + 'Esp': doc['NombreEsp'] ?? 'Nombre no disponible', + 'Eng': doc['NombreEng'] ?? 'Nombre no disponible', + }; + } + setState(() { + CalentamientoEspecificoNames = tempMap; + }); + } + + void _addCalentamientoEspecifico(String calentamientoEspecificoId) { + if (!_selectedCalentamientoEspecifico + .any((selected) => selected.id == calentamientoEspecificoId)) { + String calentamientoEspecificoEsp = + CalentamientoEspecificoNames[calentamientoEspecificoId]?['Esp'] ?? + 'Nombre no disponible'; + String calentamientoEspecificoEng = + CalentamientoEspecificoNames[calentamientoEspecificoId]?['Eng'] ?? + 'Nombre no disponible'; + setState(() { + _selectedCalentamientoEspecifico.add(SelectedCalentamientoEspecifico( + id: calentamientoEspecificoId, + CalentamientoEspecificoEsp: calentamientoEspecificoEsp, + CalentamientoEspecificoEng: calentamientoEspecificoEng, + )); + widget.onChanged(_selectedCalentamientoEspecifico); + }); + } + } + + void _removeCalentamientoEspecifico(String CalentamientoEspecificoId) { + setState(() { + _selectedCalentamientoEspecifico.removeWhere((CalentamientoEspecifico) => + CalentamientoEspecifico.id == CalentamientoEspecificoId); + widget.onChanged(_selectedCalentamientoEspecifico); + }); + } + + Widget _buildSelectedCalentamientoEspecifico(String langKey) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Text( + AppLocalizations.of(context)!.translate('calentamientoEspecifico'), + style: Theme.of(context).textTheme.titleMedium, + ), + ), + Wrap( + spacing: 8.0, + children: + _selectedCalentamientoEspecifico.map((calentamientoEspecifico) { + String calentamientoEspecificoName = langKey == 'Esp' + ? (calentamientoEspecifico.CalentamientoEspecificoEsp) + : (calentamientoEspecifico.CalentamientoEspecificoEng); + return Chip( + label: Text(calentamientoEspecificoName), + onDeleted: () => + _removeCalentamientoEspecifico(calentamientoEspecifico.id), + ); + }).toList(), + ), + ], + ); + } + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Mostrar los calentamientos específicos seleccionados + _buildSelectedCalentamientoEspecifico(widget.langKey), + // Dropdown de calentamientos específicos + FutureBuilder>>( + future: _getSimplifiedCalentamientoEspecifico(widget.langKey), + builder: (context, snapshot) { + if (!snapshot.hasData) { + return const CircularProgressIndicator(); + } + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + decoration: BoxDecoration( + color: Colors.grey.shade400, + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppColors.lightBlueAccentColor, + width: 2, + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + hint: Text(AppLocalizations.of(context)! + .translate('selectCalentamientoEspecifico')), + onChanged: (String? newValue) { + if (newValue != null) { + _addCalentamientoEspecifico(newValue); + } + }, + items: snapshot.data, + value: snapshot.data!.isNotEmpty + ? snapshot.data?.first.value + : null, + ), + ), + ], + ), + ); + }, + ), + ], + ); + } + + // Método para obtener los calentamientos específicos simplificados desde Firestore + Future>> _getSimplifiedCalentamientoEspecifico( + String langKey) async { + var snapshot = + await FirebaseFirestore.instance.collection('calentamientoE').get(); + return snapshot.docs.map((doc) { + String calentamientoEspecificoName = + langKey == 'Esp' ? doc['NombreEsp'] : doc['NombreEng']; + return DropdownMenuItem( + value: doc.id, + child: Text(calentamientoEspecificoName), + ); + }).toList(); + } +} diff --git a/lib/filtros/widgets/DificultyDropdownWidget.dart b/lib/filtros/widgets/DificultyDropdownWidget.dart new file mode 100644 index 0000000..029347f --- /dev/null +++ b/lib/filtros/widgets/DificultyDropdownWidget.dart @@ -0,0 +1,128 @@ +import 'package:flutter/material.dart'; +import '../../config/lang/app_localization.dart'; +import '../../config/utils/appcolors.dart'; // Ajusta la importación según tu estructura + +class DificultyDropdownWidget extends StatefulWidget { + final String langKey; + final Function(String) onChanged; + + const DificultyDropdownWidget({ + Key? key, + required this.langKey, + required this.onChanged, // Añadido aquí + }) : super(key: key); + + @override + _DificultyDropdownWidgetState createState() => + _DificultyDropdownWidgetState(); +} + +class _DificultyDropdownWidgetState extends State { + String? _difficultyEsp; + String? _difficultyEng; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), + child: Text( + AppLocalizations.of(context)!.translate('difficulty'), + style: Theme.of(context).textTheme.titleMedium, + ), + ), + _buildDifficultySelector(), + if (_difficultyEsp != null || _difficultyEng != null) + _buildSelectedDifficulty(), // Solo muestra la tarjeta cuando se selecciona algo + ], + ); + } + + Widget _buildDifficultySelector() { + Locale currentLocale = Localizations.localeOf(context); + bool isEsp = currentLocale.languageCode == "es"; + + List optionsEsp = ['Fácil', 'Medio', 'Avanzado', 'Difícil']; + List optionsEng = ['Easy', 'Medium', 'Advanced', 'Difficult']; + + Map difficultyMapEspToEng = { + 'Fácil': 'Easy', + 'Medio': 'Medium', + 'Avanzado': 'Advanced', + 'Difícil': 'Difficult', + }; + + Map difficultyMapEngToEsp = { + 'Easy': 'Fácil', + 'Medium': 'Medio', + 'Advanced': 'Avanzado', + 'Difficult': 'Difícil', + }; + + List options = isEsp ? optionsEsp : optionsEng; + String? currentDifficulty = isEsp ? _difficultyEsp : _difficultyEng; + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 2), + decoration: BoxDecoration( + color: Colors.grey.shade400, + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppColors.lightBlueAccentColor, + width: 2, + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + hint: Text( + AppLocalizations.of(context)!.translate('selectDifficulty')), + onChanged: (String? newValue) { + setState(() { + if (isEsp) { + _difficultyEsp = newValue!; + _difficultyEng = difficultyMapEspToEng[newValue]!; + } else { + _difficultyEng = newValue!; + _difficultyEsp = difficultyMapEngToEsp[newValue]!; + } + }); + }, + value: currentDifficulty, + items: options.map>((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + ), + ), + ], + ), + ); + } + + Widget _buildSelectedDifficulty() { + Locale currentLocale = Localizations.localeOf(context); + bool isEsp = currentLocale.languageCode == "es"; + String difficultyName = isEsp ? _difficultyEsp! : _difficultyEng!; + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), + child: Chip( + label: Text(difficultyName), + onDeleted: () { + setState(() { + _difficultyEsp = null; // Reset to null on delete + _difficultyEng = null; // Reset to null on delete + }); + }, + ), + ); + } +} diff --git a/lib/filtros/widgets/EquipmentDropdownWidget.dart b/lib/filtros/widgets/EquipmentDropdownWidget.dart new file mode 100644 index 0000000..55a564a --- /dev/null +++ b/lib/filtros/widgets/EquipmentDropdownWidget.dart @@ -0,0 +1,179 @@ +import 'package:flutter/material.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import '../../../config/lang/app_localization.dart'; +import '../../../config/utils/appcolors.dart'; + +// Definición de la clase para los equipos seleccionados +class SelectedEquipment { + final String id; + final String equipmentEsp; + final String equipmentEng; + + SelectedEquipment({ + required this.id, + required this.equipmentEsp, + required this.equipmentEng, + }); +} + +class EquipmentDropdownWidget extends StatefulWidget { + final String langKey; +final Function(String) onChanged; + +const EquipmentDropdownWidget({ + Key? key, + required this.langKey, + required this.onChanged, // Añadido aquí +}) : super(key: key); + + + @override + _EquipmentDropdownWidgetState createState() => + _EquipmentDropdownWidgetState(); +} + +class _EquipmentDropdownWidgetState extends State { + final List _selectedEquipment = []; + Map> equipmentNames = {}; + + // Cargar los nombres de los equipos desde Firestore + @override + void initState() { + super.initState(); + _loadEquipmentNames(); + } + + void _loadEquipmentNames() async { + var snapshot = + await FirebaseFirestore.instance.collection('equipment').get(); + Map> tempMap = {}; + for (var doc in snapshot.docs) { + tempMap[doc.id] = { + 'Esp': doc['NombreEsp'] ?? 'Nombre no disponible', + 'Eng': doc['NombreEng'] ?? 'Nombre no disponible', + }; + } + setState(() { + equipmentNames = tempMap; + }); + } + + void _addEquipment(String equipmentId) { + if (!_selectedEquipment.any((selected) => selected.id == equipmentId)) { + String equipmentEsp = + equipmentNames[equipmentId]?['Esp'] ?? 'Nombre no disponible'; + String equipmentEng = + equipmentNames[equipmentId]?['Eng'] ?? 'Nombre no disponible'; + setState(() { + _selectedEquipment.add(SelectedEquipment( + id: equipmentId, + equipmentEsp: equipmentEsp, + equipmentEng: equipmentEng, + )); + }); + } + } + + void _removeEquipment(String equipmentId) { + setState(() { + _selectedEquipment + .removeWhere((equipment) => equipment.id == equipmentId); + }); + } + + // Widget que muestra los equipos seleccionados + Widget _buildSelectedEquipment(String langKey) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Text( + AppLocalizations.of(context)!.translate('equipmentNew'), + style: Theme.of(context).textTheme.titleMedium, + ), + ), + Wrap( + spacing: 8.0, + children: _selectedEquipment.map((equipment) { + String equipmentName = langKey == 'Esp' + ? equipment.equipmentEsp + : equipment.equipmentEng; + return Chip( + label: Text(equipmentName), + onDeleted: () => _removeEquipment(equipment.id), + ); + }).toList(), + ), + ], + ); + } + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Mostrar los equipos seleccionados + _buildSelectedEquipment(widget.langKey), + // Dropdown de equipos + FutureBuilder>>( + future: _getSimplifiedEquipment(widget.langKey), + builder: (context, snapshot) { + if (!snapshot.hasData) { + return const CircularProgressIndicator(); + } + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + decoration: BoxDecoration( + color: Colors.grey.shade400, + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppColors.lightBlueAccentColor, + width: 2, + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + hint: Text(AppLocalizations.of(context)! + .translate('selectEquipmentNew')), + onChanged: (String? newValue) { + if (newValue != null) { + _addEquipment(newValue); // Agregar equipo + } + }, + items: snapshot.data, + value: snapshot.data!.isNotEmpty + ? snapshot.data?.first.value + : null, + ), + ), + ], + ), + ); + }, + ), + ], + ); + } + + // Método para obtener los equipos simplificados desde Firestore + Future>> _getSimplifiedEquipment( + String langKey) async { + var snapshot = + await FirebaseFirestore.instance.collection('equipment').get(); + return snapshot.docs.map((doc) { + String equipmentName = + langKey == 'Esp' ? doc['NombreEsp'] : doc['NombreEng']; + return DropdownMenuItem( + value: doc.id, + child: Text(equipmentName), + ); + }).toList(); + } +} diff --git a/lib/filtros/widgets/IntensityDropdownWidget.dart b/lib/filtros/widgets/IntensityDropdownWidget.dart new file mode 100644 index 0000000..e80c1d7 --- /dev/null +++ b/lib/filtros/widgets/IntensityDropdownWidget.dart @@ -0,0 +1,151 @@ +import 'package:flutter/material.dart'; +import '../../config/lang/app_localization.dart'; +import '../../config/utils/appcolors.dart'; // Ajusta la importación según tu estructura + +class IntensityDropdownWidget extends StatefulWidget { + final String langKey; +final Function(String) onChanged; + +const IntensityDropdownWidget({ + Key? key, + required this.langKey, + required this.onChanged, // Añadido aquí +}) : super(key: key); + + + @override + _IntensityDropdownWidgetState createState() => + _IntensityDropdownWidgetState(); +} + +class _IntensityDropdownWidgetState extends State { + String? _intensityEsp; + String? _intensityEng; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), + child: Text( + AppLocalizations.of(context)!.translate('intensity'), + style: Theme.of(context).textTheme.titleMedium, + ), + ), + _buildIntensitySelector(), + if (_intensityEsp != null || _intensityEng != null) + _buildSelectedIntensity(), + ], + ); + } + + Widget _buildIntensitySelector() { + Locale currentLocale = Localizations.localeOf(context); + bool isEsp = currentLocale.languageCode == "es"; + + List optionsEsp = [ + 'Ascendente', + 'Descendente', + 'Baja', + 'Muy Baja', + 'Moderada', + 'Alta', + 'Muy Alta' + ]; + List optionsEng = [ + 'Ascending', + 'Descending', + 'Low', + 'Very Low', + 'Moderate', + 'High', + 'Very High' + ]; + + Map intensityMapEspToEng = { + 'Ascendente': 'Ascending', + 'Descendente': 'Descending', + 'Baja': 'Low', + 'Muy Baja': 'Very Low', + 'Moderada': 'Moderate', + 'Alta': 'High', + 'Muy Alta': 'Very High', + }; + + Map intensityMapEngToEsp = { + 'Ascending': 'Ascendente', + 'Descending': 'Descendente', + 'Low': 'Baja', + 'Very Low': 'Muy Baja', + 'Moderate': 'Moderada', + 'High': 'Alta', + 'Very High': 'Muy Alta', + }; + + List options = isEsp ? optionsEsp : optionsEng; + String? currentIntensity = isEsp ? _intensityEsp : _intensityEng; + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 2), + decoration: BoxDecoration( + color: Colors.grey.shade400, + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppColors.lightBlueAccentColor, + width: 2, + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + hint: Text( + AppLocalizations.of(context)!.translate('selectIntensity')), + onChanged: (String? newValue) { + setState(() { + if (isEsp) { + _intensityEsp = newValue!; + _intensityEng = intensityMapEspToEng[newValue]!; + } else { + _intensityEng = newValue!; + _intensityEsp = intensityMapEngToEsp[newValue]!; + } + }); + }, + value: currentIntensity, + items: options.map>((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + ), + ), + ], + ), + ); + } + + Widget _buildSelectedIntensity() { + Locale currentLocale = Localizations.localeOf(context); + bool isEsp = currentLocale.languageCode == "es"; + String intensityName = isEsp ? _intensityEsp! : _intensityEng!; + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), + child: Chip( + label: Text(intensityName), + onDeleted: () { + setState(() { + _intensityEsp = null; + _intensityEng = null; + }); + }, + ), + ); + } +} diff --git a/lib/filtros/widgets/MembershipDropdownWidget.dart b/lib/filtros/widgets/MembershipDropdownWidget.dart new file mode 100644 index 0000000..8ab6b1a --- /dev/null +++ b/lib/filtros/widgets/MembershipDropdownWidget.dart @@ -0,0 +1,121 @@ +import 'package:flutter/material.dart'; +import '../../config/lang/app_localization.dart'; +import '../../config/utils/appcolors.dart'; // Ajusta la importación según tu estructura + +class MembershipDropdownWidget extends StatefulWidget { + final String langKey; +final Function(String) onChanged; + +const MembershipDropdownWidget({ + Key? key, + required this.langKey, + required this.onChanged, // Añadido aquí +}) : super(key: key); + + + @override + _MembershipDropdownWidgetState createState() => + _MembershipDropdownWidgetState(); +} + +class _MembershipDropdownWidgetState extends State { + String? _membershipEsp; + String? _membershipEng; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), + child: Text( + AppLocalizations.of(context)!.translate('exerciseMembership'), + style: Theme.of(context).textTheme.titleMedium, + ), + ), + _buildMembershipSelector(), + if (_membershipEsp != null || _membershipEng != null) + _buildSelectedMembership(), + ], + ); + } + + Widget _buildMembershipSelector() { + Locale currentLocale = Localizations.localeOf(context); + bool isEsp = currentLocale.languageCode == "es"; + + List optionsEsp = ['Gratis', 'Premium']; + List optionsEng = ['Free', 'Premium']; + + Map membershipMapEspToEng = { + 'Gratis': 'Free', + 'Premium': 'Premium', + }; + + Map membershipMapEngToEsp = { + 'Free': 'Gratis', + 'Premium': 'Premium', + }; + + List options = isEsp ? optionsEsp : optionsEng; + String? selectedValue = isEsp ? _membershipEsp : _membershipEng; + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 2), + decoration: BoxDecoration( + color: Colors.grey.shade400, + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppColors.lightBlueAccentColor, + width: 2, + ), + ), + child: DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + hint: Text( + AppLocalizations.of(context)!.translate('selectMembership'), + ), + onChanged: (String? newValue) { + setState(() { + if (isEsp) { + _membershipEsp = newValue!; + _membershipEng = membershipMapEspToEng[newValue]!; + } else { + _membershipEng = newValue!; + _membershipEsp = membershipMapEngToEsp[newValue]!; + } + }); + }, + items: options.map>((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + value: selectedValue, + ), + ), + ); + } + + Widget _buildSelectedMembership() { + Locale currentLocale = Localizations.localeOf(context); + bool isEsp = currentLocale.languageCode == "es"; + String membershipName = isEsp ? _membershipEsp! : _membershipEng!; + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), + child: Chip( + label: Text(membershipName), + onDeleted: () { + setState(() { + _membershipEsp = null; + _membershipEng = null; + }); + }, + ), + ); + } +} diff --git a/lib/filtros/widgets/NivelDeImpactoDropdownWidget.dart b/lib/filtros/widgets/NivelDeImpactoDropdownWidget.dart new file mode 100644 index 0000000..ab4cc04 --- /dev/null +++ b/lib/filtros/widgets/NivelDeImpactoDropdownWidget.dart @@ -0,0 +1,138 @@ +import 'package:flutter/material.dart'; + +import '../../config/lang/app_localization.dart'; +import '../../config/utils/appcolors.dart'; // Ajusta la importación según tu estructura + +class NivelDeImpactoDropdownWidget extends StatefulWidget { + final String langKey; + final Function(List) onChanged; + + const NivelDeImpactoDropdownWidget({ + Key? key, + required this.langKey, + required this.onChanged, // Añadido aquí + }) : super(key: key); + + @override + _NivelDeImpactoDropdownWidgetState createState() => + _NivelDeImpactoDropdownWidgetState(); +} + +class _NivelDeImpactoDropdownWidgetState + extends State { + List _selectedImpactLevels = []; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), + child: Text( + AppLocalizations.of(context)!.translate('exerciseNivelDeImpacto'), + style: Theme.of(context).textTheme.titleMedium, + ), + ), + _buildNivelDeImpactoSelector(), + _buildSelectedNivelDeImpacto(), + ], + ); + } + + Widget _buildNivelDeImpactoSelector() { + Locale currentLocale = Localizations.localeOf(context); + bool isEsp = currentLocale.languageCode == "es"; + + List optionsEsp = ['Bajo', 'Regular', 'Medio', 'Bueno', 'Alto']; + List optionsEng = ['Low', 'Regular', 'Medium', 'Good', 'High']; + + // Mapas de traducción para gestionar entre español e inglés + + Map nivelDeImpactoMapEngToEsp = { + 'Low': 'Bajo', + 'Regular': 'Regular', + 'Medium': 'Medio', + 'Good': 'Bueno', + 'High': 'Alto', + }; + + List options = isEsp ? optionsEsp : optionsEng; + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 2), + decoration: BoxDecoration( + color: Colors.grey.shade400, + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppColors.lightBlueAccentColor, + width: 2, + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + hint: Text(AppLocalizations.of(context)! + .translate('selectNivelDeImpacto')), + onChanged: (String? newValue) { + setState(() { + if (newValue != null) { + // Si el idioma es español, agregamos el valor en español + // y el valor correspondiente en inglés + if (isEsp) { + if (!_selectedImpactLevels.contains(newValue)) { + _selectedImpactLevels.add(newValue); + widget.onChanged(_selectedImpactLevels); + } + } else { + if (!_selectedImpactLevels.contains(newValue)) { + // Convertir el valor en inglés a español + _selectedImpactLevels.add( + nivelDeImpactoMapEngToEsp[newValue]!); + widget.onChanged(_selectedImpactLevels); + } + } + } + }); + }, + value: null, // No hay un valor seleccionado por defecto + items: options.map>((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + ), + ), + ], + ), + ); + } + + Widget _buildSelectedNivelDeImpacto() { + if (_selectedImpactLevels.isEmpty) { + return const SizedBox.shrink(); // No mostrar nada si no hay selecciones + } + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), + child: Wrap( + spacing: 6.0, + children: _selectedImpactLevels.map((impacto) { + return Chip( + label: Text(impacto), + onDeleted: () { + setState(() { + _selectedImpactLevels.remove(impacto); + widget.onChanged(_selectedImpactLevels); // Notifica los cambios + }); + }, + ); + }).toList(), + ), + ); + } +} diff --git a/lib/filtros/widgets/ObjetivosDropdownWidget.dart b/lib/filtros/widgets/ObjetivosDropdownWidget.dart new file mode 100644 index 0000000..947b458 --- /dev/null +++ b/lib/filtros/widgets/ObjetivosDropdownWidget.dart @@ -0,0 +1,179 @@ +import 'package:flutter/material.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import '../../../config/lang/app_localization.dart'; +import '../../../config/utils/appcolors.dart'; + +// Definición de la clase para los objetivos seleccionados +class SelectedObjetivos { + final String id; + final String objetivosEsp; + final String objetivosEng; + + SelectedObjetivos({ + required this.id, + required this.objetivosEsp, + required this.objetivosEng, + }); +} + +class ObjetivosDropdownWidget extends StatefulWidget { + final String langKey; +final Function(String) onChanged; + +const ObjetivosDropdownWidget({ + Key? key, + required this.langKey, + required this.onChanged, // Añadido aquí +}) : super(key: key); + + + @override + _ObjetivosDropdownWidgetState createState() => + _ObjetivosDropdownWidgetState(); +} + +class _ObjetivosDropdownWidgetState extends State { + final List _selectedObjetivos = []; + Map> objetivosNames = {}; + + // Cargar los nombres de los objetivos desde Firestore + @override + void initState() { + super.initState(); + _loadObjetivosNames(); + } + + void _loadObjetivosNames() async { + var snapshot = + await FirebaseFirestore.instance.collection('objetivos').get(); + Map> tempMap = {}; + for (var doc in snapshot.docs) { + tempMap[doc.id] = { + 'Esp': doc['NombreEsp'] ?? 'Nombre no disponible', + 'Eng': doc['NombreEng'] ?? 'Nombre no disponible', + }; + } + setState(() { + objetivosNames = tempMap; + }); + } + + void _addObjetivos(String objetivosId) { + if (!_selectedObjetivos.any((selected) => selected.id == objetivosId)) { + String objetivosEsp = + objetivosNames[objetivosId]?['Esp'] ?? 'Nombre no disponible'; + String objetivosEng = + objetivosNames[objetivosId]?['Eng'] ?? 'Nombre no disponible'; + setState(() { + _selectedObjetivos.add(SelectedObjetivos( + id: objetivosId, + objetivosEsp: objetivosEsp, + objetivosEng: objetivosEng, + )); + }); + } + } + + void _removeObjetivos(String objetivosId) { + setState(() { + _selectedObjetivos + .removeWhere((objetivos) => objetivos.id == objetivosId); + }); + } + + // Widget que muestra los objetivos seleccionados + Widget _buildSelectedObjetivos(String langKey) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Text( + AppLocalizations.of(context)!.translate('applicableTo'), + style: Theme.of(context).textTheme.titleMedium, + ), + ), + Wrap( + spacing: 8.0, + children: _selectedObjetivos.map((objetivos) { + String objetivosName = langKey == 'Esp' + ? objetivos.objetivosEsp + : objetivos.objetivosEng; + return Chip( + label: Text(objetivosName), + onDeleted: () => _removeObjetivos(objetivos.id), + ); + }).toList(), + ), + ], + ); + } + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Mostrar los objetivos seleccionados + _buildSelectedObjetivos(widget.langKey), + // Dropdown de objetivos + FutureBuilder>>( + future: _getSimplifiedObjetivos(widget.langKey), + builder: (context, snapshot) { + if (!snapshot.hasData) { + return const CircularProgressIndicator(); + } + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + decoration: BoxDecoration( + color: Colors.grey.shade400, + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppColors.lightBlueAccentColor, + width: 2, + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + hint: Text(AppLocalizations.of(context)! + .translate('selectOApplicableTo')), + onChanged: (String? newValue) { + if (newValue != null) { + _addObjetivos(newValue); // Agregar objetivo + } + }, + items: snapshot.data, + value: snapshot.data!.isNotEmpty + ? snapshot.data?.first.value + : null, + ), + ), + ], + ), + ); + }, + ), + ], + ); + } + + // Método para obtener los objetivos simplificados desde Firestore + Future>> _getSimplifiedObjetivos( + String langKey) async { + var snapshot = + await FirebaseFirestore.instance.collection('objetivos').get(); + return snapshot.docs.map((doc) { + String objetivosName = + langKey == 'Esp' ? doc['NombreEsp'] : doc['NombreEng']; + return DropdownMenuItem( + value: doc.id, + child: Text(objetivosName), + ); + }).toList(); + } +} diff --git a/lib/filtros/widgets/PosturaDropdownWidget.dart b/lib/filtros/widgets/PosturaDropdownWidget.dart new file mode 100644 index 0000000..0c5cbd3 --- /dev/null +++ b/lib/filtros/widgets/PosturaDropdownWidget.dart @@ -0,0 +1,141 @@ +import 'package:flutter/material.dart'; + +import '../../config/lang/app_localization.dart'; +import '../../config/utils/appcolors.dart'; // Ajusta la importación según tu estructura + +class PosturaDropdownWidget extends StatefulWidget { + final String langKey; +final Function(String) onChanged; + +const PosturaDropdownWidget({ + Key? key, + required this.langKey, + required this.onChanged, // Añadido aquí +}) : super(key: key); + + + @override + _PosturaDropdownWidgetState createState() => _PosturaDropdownWidgetState(); +} + +class _PosturaDropdownWidgetState extends State { + String? _stanceEsp; + String? _stanceEng; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), + child: Text( + AppLocalizations.of(context)!.translate('exerciseStance'), + style: Theme.of(context).textTheme.titleMedium, + ), + ), + _buildStanceSelector(), + if (_stanceEsp != null || _stanceEng != null) _buildSelectedStance(), + ], + ); + } + + Widget _buildStanceSelector() { + Locale currentLocale = Localizations.localeOf(context); + bool isEsp = currentLocale.languageCode == "es"; + + List optionsEsp = [ + 'Parado', + 'Sentado', + 'Inclinado', + 'Declinado', + 'De Pie Horizontal', + 'Maquina Gimnasion' + ]; + List optionsEng = [ + 'Standing', + 'Sitting', + 'Inclined', + 'Declined', + 'Horizontal Standing', + 'Gym Machine' + ]; + + Map stanceMapEspToEng = { + 'Parado': 'Standing', + 'Sentado': 'Sitting', + 'Inclinado': 'Inclined', + 'Declinado': 'Declined', + 'De Pie Horizontal': 'Horizontal Standing', + 'Maquina Gimnasion': 'Gym Machine', + }; + + Map stanceMapEngToEsp = { + 'Standing': 'Parado', + 'Sitting': 'Sentado', + 'Inclined': 'Inclinado', + 'Declined': 'Declinado', + 'Horizontal Standing': 'De Pie Horizontal', + 'Gym Machine': 'Maquina Gimnasion', + }; + + List options = isEsp ? optionsEsp : optionsEng; + String? selectedValue = isEsp ? _stanceEsp : _stanceEng; + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 2), + decoration: BoxDecoration( + color: Colors.grey.shade400, + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppColors.lightBlueAccentColor, + width: 2, + ), + ), + child: DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + hint: Text( + AppLocalizations.of(context)!.translate('selectExerciseStance')), + onChanged: (String? newValue) { + setState(() { + if (isEsp) { + _stanceEsp = newValue!; + _stanceEng = stanceMapEspToEng[newValue]!; + } else { + _stanceEng = newValue!; + _stanceEsp = stanceMapEngToEsp[newValue]!; + } + }); + }, + items: options.map>((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + value: selectedValue, + ), + ), + ); + } + + Widget _buildSelectedStance() { + Locale currentLocale = Localizations.localeOf(context); + bool isEsp = currentLocale.languageCode == "es"; + String stanceName = isEsp ? _stanceEsp! : _stanceEng!; + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Chip( + label: Text(stanceName), + onDeleted: () { + setState(() { + _stanceEsp = null; + _stanceEng = null; + }); + }, + ), + ); + } +} diff --git a/lib/functions/ejercicios/add_ejercicios_functions.dart b/lib/functions/ejercicios/add_ejercicios_functions.dart index 8ba5503..2f5defb 100644 --- a/lib/functions/ejercicios/add_ejercicios_functions.dart +++ b/lib/functions/ejercicios/add_ejercicios_functions.dart @@ -36,6 +36,7 @@ class AddEjercicioFunctions { required String phaseEng, required String stanceEsp, required String stanceEng, + String? specificMuscle, }) async { User? user = FirebaseAuth.instance.currentUser; if (user == null) return; @@ -90,6 +91,7 @@ class AddEjercicioFunctions { 'NombreEng': e.bodypartEsp, }) .toList(), + 'specificMuscle': specificMuscle, 'URL de la Imagen': imageUrl, 'URL de la Imagen 3D': image3dUrl, 'MembershipEsp': membershipEsp, diff --git a/lib/widgets/grid_view/mansory_calentamiento_fisico.dart b/lib/widgets/grid_view/mansory_calentamiento_fisico.dart index e7545e6..368698c 100644 --- a/lib/widgets/grid_view/mansory_calentamiento_fisico.dart +++ b/lib/widgets/grid_view/mansory_calentamiento_fisico.dart @@ -6,6 +6,7 @@ import 'package:youtube_player_flutter/youtube_player_flutter.dart'; import '../../config/notifiers/selected_notifier.dart'; import '../../config/lang/app_localization.dart'; import '../../config/utils/appcolors.dart'; +import '../../filtros/filter_dialog.dart'; class MasonryCalentamientoFisico extends StatefulWidget { const MasonryCalentamientoFisico({Key? key}) : super(key: key); @@ -46,7 +47,38 @@ class _MasonryCalentamientoFisicoState }); } - void _showFilterDialog() {} + // En tu widget principal +void _showFilterDialog() { + showDialog( + context: context, + builder: (BuildContext context) { + return FilterDialog( + onFilterApplied: ( + String? selectedBodyPart, + String? selectedCalentamiento, + String? selectedEquipment, + String? selectedImpactLevel, + String? selectedPosture, + String? selectedDificulty, + String? selectedObjective, + String? selectedIntensity, + String? selectedMembership, + ) { + // Imprime las selecciones + print('BodyPart: $selectedBodyPart'); + print('Calentamiento: $selectedCalentamiento'); + print('Equipment: $selectedEquipment'); + print('Impact Level: $selectedImpactLevel'); + print('Posture: $selectedPosture'); + print('Dificulty: $selectedDificulty'); + print('Objective: $selectedObjective'); + print('Intensity: $selectedIntensity'); + print('Membership: $selectedMembership'); + }, + ); + }, + ); +} @override Widget build(BuildContext context) { diff --git a/pubspec.yaml b/pubspec.yaml index cc45e7d..ecb4b2b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,7 +8,7 @@ description: "A new Flutter project." publish_to: 'none' # Versión de la aplicación (versión principal y número de compilación) -version: 1.0.0+1 +version: 1.0.1+2 # Entorno de SDK que esta aplicación soporta (mínimo y máximo permitido) environment: