diff --git a/cosiap_api/administracion/admin.py b/cosiap_api/administracion/admin.py index c96937d883a4d45d6214f59ef71d154dbf500f1b..595fb2ac7f1e6408e589942eba879b70838dcc9f 100644 --- a/cosiap_api/administracion/admin.py +++ b/cosiap_api/administracion/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from .models import Convocatoria, ConfiguracionColores +from .models import Convocatoria, Colores admin.site.register(Convocatoria) -admin.site.register(ConfiguracionColores) \ No newline at end of file +admin.site.register(Colores) \ No newline at end of file diff --git a/cosiap_api/administracion/migrations/0001_crear_modelo_convocatoria.py b/cosiap_api/administracion/migrations/0001_crear_modelo_convocatoria.py deleted file mode 100644 index 51422bc49f9374c966ba4702301ecd406bc98223..0000000000000000000000000000000000000000 --- a/cosiap_api/administracion/migrations/0001_crear_modelo_convocatoria.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 5.0.8 on 2024-09-07 18:33 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ] - - operations = [ - migrations.CreateModel( - name='Convocatoria', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('nombre', models.CharField(max_length=100)), - ('abierta', models.BooleanField(default=False)), - ], - ), - ] diff --git a/cosiap_api/administracion/migrations/0001_initial.py b/cosiap_api/administracion/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..3a6d744a18131e5f6780d7d70164ff5166f9d0a6 --- /dev/null +++ b/cosiap_api/administracion/migrations/0001_initial.py @@ -0,0 +1,52 @@ +# Generated by Django 5.0.9 on 2024-10-31 19:18 + +from django.db import migrations, models + +def create_default_colors(apps, schema_editor): + Colores = apps.get_model('administracion', 'Colores') # Cambia 'tu_app' por el nombre de tu aplicación + Colores.objects.create( + logo=None, # Puedes establecer un logo por defecto si es necesario + color_principal='rgb(120, 16, 5)', + principal='#E2746E', + principal_mf='#781005', + principal_f='#BB4433', + principal_c='#F5ADAB', + principal_mc='#FCE2E4', + es_default=True, + ) + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Colores', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('logo', models.ImageField(blank=True, null=True, upload_to='logos/')), + ('color_principal', models.CharField(default='rgb(120, 16, 5)', max_length=255)), + ('principal', models.CharField(default='#E2746E', max_length=255)), + ('principal_mf', models.CharField(default='#781005', max_length=255)), + ('principal_f', models.CharField(default='#BB4433', max_length=255)), + ('principal_c', models.CharField(default='#F5ADAB', max_length=255)), + ('principal_mc', models.CharField(default='#FCE2E4', max_length=255)), + ('es_default', models.BooleanField(default=False)), + ], + options={ + 'verbose_name': 'Configuración de Estilo', + 'verbose_name_plural': 'Configuraciones de Estilo', + }, + ), + migrations.CreateModel( + name='Convocatoria', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('abierta', models.BooleanField(default=False)), + ], + ), + migrations.RunPython(create_default_colors), + ] diff --git a/cosiap_api/administracion/migrations/0002_eliminar_columna_nombre.py b/cosiap_api/administracion/migrations/0002_eliminar_columna_nombre.py deleted file mode 100644 index 174ddb9b2472ee04477dc7ecfae312357acdc8fd..0000000000000000000000000000000000000000 --- a/cosiap_api/administracion/migrations/0002_eliminar_columna_nombre.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 5.0.8 on 2024-09-07 19:01 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('administracion', '0001_crear_modelo_convocatoria'), - ] - - operations = [ - migrations.RemoveField( - model_name='convocatoria', - name='nombre', - ), - ] diff --git a/cosiap_api/administracion/migrations/0002_remove_colores_color_principal.py b/cosiap_api/administracion/migrations/0002_remove_colores_color_principal.py new file mode 100644 index 0000000000000000000000000000000000000000..6f39f82906a09298ac54c2c24389040bd693182a --- /dev/null +++ b/cosiap_api/administracion/migrations/0002_remove_colores_color_principal.py @@ -0,0 +1,17 @@ +# Generated by Django 5.0.9 on 2024-10-31 21:11 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('administracion', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='colores', + name='color_principal', + ), + ] diff --git a/cosiap_api/administracion/migrations/0003_modelo_configuracion_colores.py b/cosiap_api/administracion/migrations/0003_modelo_configuracion_colores.py deleted file mode 100644 index 78a71b249884a5379aef6efad664fa04eace3c79..0000000000000000000000000000000000000000 --- a/cosiap_api/administracion/migrations/0003_modelo_configuracion_colores.py +++ /dev/null @@ -1,120 +0,0 @@ -# Generated by Django 5.0.8 on 2024-09-13 17:37 - -from django.db import migrations, models - - -def create_default_configuration(apps, schema_editor): - ConfiguracionEstilo = apps.get_model('administracion', 'ConfiguracionColores') - ConfiguracionEstilo.objects.create( - logo=None, # Ajusta esto si quieres un logo por defecto - principal_mc='rgb(252, 226, 228)', - principal_c='rgb(245, 173, 171)', - principal='rgb(226, 116, 110)', - principal_f='rgb(187, 68, 51)', - principal_mf='rgb(120, 16, 5)', - secundario_mc='#e0e0e0', - secundario_c='#c0c0c0', - secundario='#a0a0a0', - secundario_f='#808080', - secundario_mf='#606060', - exito_f='#8abc94', - exito='#b9e2c1', - exito_c='#d5f5e2', - exito_btn='#527f18', - error_f='#c7564a', - error='#e4756f', - error_c='#e1b2af', - precaucion_f='#d4bf47', - precaucion='#e4d26f', - precaucion_c='#f1e7a8', - cancelar_f='#b8a9a8', - cancelar='#dccbca', - cancelar_c='#e9dedd', - informacion_f='#5b9bd5', - informacion='#85c1e9', - informacion_c='#cfe2f3', - neutral_f='#6c757d', - neutral='#adb5bd', - neutral_c='#dee2e6', - gris_principal='#b9b4b4', - gris_0='#f8f8f8', - gris_1='#efefef', - gris_2='#e0e0e0', - gris_3='#c0c0c0', - gris_4='#a0a0a0', - gris_5='#808080', - gris_6='#606060', - gris_7='#404040', - gris_8='#202020', - blanco='#ffffff', - negro='#000000', - pagina_fondo='#eee5e5', - texto_general='#676767', - es_default=True - ) - - -class Migration(migrations.Migration): - - dependencies = [ - ('administracion', '0002_eliminar_columna_nombre'), - ] - - operations = [ - migrations.CreateModel( - name='ConfiguracionColores', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('logo', models.ImageField(blank=True, null=True, upload_to='logos/')), - ('principal_mc', models.CharField(default='rgb(252, 226, 228)', max_length=20)), - ('principal_c', models.CharField(default='rgb(245, 173, 171)', max_length=20)), - ('principal', models.CharField(default='rgb(226, 116, 110)', max_length=20)), - ('principal_f', models.CharField(default='rgb(187, 68, 51)', max_length=20)), - ('principal_mf', models.CharField(default='rgb(120, 16, 5)', max_length=20)), - ('secundario_mc', models.CharField(default='#e0e0e0', max_length=7)), - ('secundario_c', models.CharField(default='#c0c0c0', max_length=7)), - ('secundario', models.CharField(default='#a0a0a0', max_length=7)), - ('secundario_f', models.CharField(default='#808080', max_length=7)), - ('secundario_mf', models.CharField(default='#606060', max_length=7)), - ('exito_f', models.CharField(default='#8abc94', max_length=7)), - ('exito', models.CharField(default='#b9e2c1', max_length=7)), - ('exito_c', models.CharField(default='#d5f5e2', max_length=7)), - ('exito_btn', models.CharField(default='#527f18', max_length=7)), - ('error_f', models.CharField(default='#c7564a', max_length=7)), - ('error', models.CharField(default='#e4756f', max_length=7)), - ('error_c', models.CharField(default='#e1b2af', max_length=7)), - ('precaucion_f', models.CharField(default='#d4bf47', max_length=7)), - ('precaucion', models.CharField(default='#e4d26f', max_length=7)), - ('precaucion_c', models.CharField(default='#f1e7a8', max_length=7)), - ('cancelar_f', models.CharField(default='#b8a9a8', max_length=7)), - ('cancelar', models.CharField(default='#dccbca', max_length=7)), - ('cancelar_c', models.CharField(default='#e9dedd', max_length=7)), - ('informacion_f', models.CharField(default='#5b9bd5', max_length=7)), - ('informacion', models.CharField(default='#85c1e9', max_length=7)), - ('informacion_c', models.CharField(default='#cfe2f3', max_length=7)), - ('neutral_f', models.CharField(default='#6c757d', max_length=7)), - ('neutral', models.CharField(default='#adb5bd', max_length=7)), - ('neutral_c', models.CharField(default='#dee2e6', max_length=7)), - ('gris_principal', models.CharField(default='#b9b4b4', max_length=7)), - ('gris_0', models.CharField(default='#f8f8f8', max_length=7)), - ('gris_1', models.CharField(default='#efefef', max_length=7)), - ('gris_2', models.CharField(default='#e0e0e0', max_length=7)), - ('gris_3', models.CharField(default='#c0c0c0', max_length=7)), - ('gris_4', models.CharField(default='#a0a0a0', max_length=7)), - ('gris_5', models.CharField(default='#808080', max_length=7)), - ('gris_6', models.CharField(default='#606060', max_length=7)), - ('gris_7', models.CharField(default='#404040', max_length=7)), - ('gris_8', models.CharField(default='#202020', max_length=7)), - ('blanco', models.CharField(default='#ffffff', max_length=7)), - ('negro', models.CharField(default='#000000', max_length=7)), - ('pagina_fondo', models.CharField(default='#eee5e5', max_length=7)), - ('texto_general', models.CharField(default='#676767', max_length=7)), - ('es_default', models.BooleanField(default=False)), - ], - options={ - 'verbose_name': 'Configuración de Estilo', - 'verbose_name_plural': 'Configuraciones de Estilo', - }, - ), - migrations.RunPython(create_default_configuration), - ] diff --git a/cosiap_api/administracion/models.py b/cosiap_api/administracion/models.py index 1bd5cc63f5cd372bc1c6632afba7df56e9c936c4..82dbdbd2a197190987518cf0da66caee82edf67e 100644 --- a/cosiap_api/administracion/models.py +++ b/cosiap_api/administracion/models.py @@ -8,75 +8,20 @@ class Convocatoria(models.Model): abierta = models.BooleanField(default=False) -class ConfiguracionColores(models.Model): +class Colores(models.Model): logo = models.ImageField(upload_to='logos/', blank=True, null=True) - - # Colores principales - principal_mc = models.CharField(max_length=20, default='rgb(252, 226, 228)') - principal_c = models.CharField(max_length=20, default='rgb(245, 173, 171)') - principal = models.CharField(max_length=20, default='rgb(226, 116, 110)') - principal_f = models.CharField(max_length=20, default='rgb(187, 68, 51)') - principal_mf = models.CharField(max_length=20, default='rgb(120, 16, 5)') - - # Colores secundarios - secundario_mc = models.CharField(max_length=7, default='#e0e0e0') - secundario_c = models.CharField(max_length=7, default='#c0c0c0') - secundario = models.CharField(max_length=7, default='#a0a0a0') - secundario_f = models.CharField(max_length=7, default='#808080') - secundario_mf = models.CharField(max_length=7, default='#606060') - - # Colores de éxito, error, precaución, información, etc. - exito_f = models.CharField(max_length=7, default='#8abc94') - exito = models.CharField(max_length=7, default='#b9e2c1') - exito_c = models.CharField(max_length=7, default='#d5f5e2') - exito_btn = models.CharField(max_length=7, default='#527f18') - - error_f = models.CharField(max_length=7, default='#c7564a') - error = models.CharField(max_length=7, default='#e4756f') - error_c = models.CharField(max_length=7, default='#e1b2af') - - precaucion_f = models.CharField(max_length=7, default='#d4bf47') - precaucion = models.CharField(max_length=7, default='#e4d26f') - precaucion_c = models.CharField(max_length=7, default='#f1e7a8') - - cancelar_f = models.CharField(max_length=7, default='#b8a9a8') - cancelar = models.CharField(max_length=7, default='#dccbca') - cancelar_c = models.CharField(max_length=7, default='#e9dedd') - - informacion_f = models.CharField(max_length=7, default='#5b9bd5') - informacion = models.CharField(max_length=7, default='#85c1e9') - informacion_c = models.CharField(max_length=7, default='#cfe2f3') - - # Colores neutros y grises - neutral_f = models.CharField(max_length=7, default='#6c757d') - neutral = models.CharField(max_length=7, default='#adb5bd') - neutral_c = models.CharField(max_length=7, default='#dee2e6') - - gris_principal = models.CharField(max_length=7, default='#b9b4b4') - gris_0 = models.CharField(max_length=7, default='#f8f8f8') - gris_1 = models.CharField(max_length=7, default='#efefef') - gris_2 = models.CharField(max_length=7, default='#e0e0e0') - gris_3 = models.CharField(max_length=7, default='#c0c0c0') - gris_4 = models.CharField(max_length=7, default='#a0a0a0') - gris_5 = models.CharField(max_length=7, default='#808080') - gris_6 = models.CharField(max_length=7, default='#606060') - gris_7 = models.CharField(max_length=7, default='#404040') - gris_8 = models.CharField(max_length=7, default='#202020') - - blanco = models.CharField(max_length=7, default='#ffffff') - negro = models.CharField(max_length=7, default='#000000') - - # Colores generales - pagina_fondo = models.CharField(max_length=7, default='#eee5e5') - texto_general = models.CharField(max_length=7, default='#676767') - + principal= models.CharField(max_length=255, default='#E2746E') + principal_mf = models.CharField(max_length=255, default='#781005') + principal_f = models.CharField(max_length=255, default='#BB4433') + principal_c = models.CharField(max_length=255, default='#F5ADAB') + principal_mc = models.CharField(max_length=255, default='#FCE2E4') es_default = models.BooleanField(default=False) def clean(self): """ Asegurar que solo haya una configuración por defecto. """ - if self.es_default and ConfiguracionEstilo.objects.filter(es_default=True).exclude(id=self.id).exists(): + if self.es_default and Colores.objects.filter(es_default=True).exclude(id=self.id).exists(): raise ValidationError('Solo puede haber una configuración predeterminada.') def __str__(self): diff --git a/cosiap_api/administracion/serializers.py b/cosiap_api/administracion/serializers.py index 84d83f26ed3cdfdbb16a97104dba91b6c7573e43..4a42f301ed6f9b40e5fd4a05d1d7b416191231a4 100644 --- a/cosiap_api/administracion/serializers.py +++ b/cosiap_api/administracion/serializers.py @@ -1,7 +1,7 @@ from rest_framework import serializers -from .models import ConfiguracionColores +from .models import Colores class ConfiguracionEstiloSerializer(serializers.ModelSerializer): class Meta: - model = ConfiguracionColores + model = Colores fields = '__all__' diff --git a/cosiap_api/administracion/views.py b/cosiap_api/administracion/views.py index 2513f625bc3e2008c16f4f867f6086faa95f0fa1..07ec7baa63b6336e103921081e9d7aa75886f1cc 100644 --- a/cosiap_api/administracion/views.py +++ b/cosiap_api/administracion/views.py @@ -1,9 +1,9 @@ from django.shortcuts import render, get_object_or_404 from common.views import BasePermissionAPIView -from rest_framework.permissions import IsAuthenticated +from rest_framework.permissions import IsAuthenticated, AllowAny from users.permisos import es_admin from rest_framework import status -from .models import Convocatoria, ConfiguracionColores +from .models import Convocatoria, Colores from rest_framework.response import Response from notificaciones.mensajes import Mensaje from .serializers import ConfiguracionEstiloSerializer @@ -65,18 +65,18 @@ class ConfiguracionEstiloAPIView(BasePermissionAPIView): Clase para manjear la recuperación y edición de la configuración default ''' - permission_classes_list = [IsAuthenticated, es_admin] + permission_classes_list = [AllowAny] permission_classes_update = [IsAuthenticated, es_admin] def get(self, request): """Recupera la configuración por defecto (es_default=True).""" - configuracion = get_object_or_404(ConfiguracionColores, es_default=True) + configuracion = get_object_or_404(Colores, es_default=True) serializer = ConfiguracionEstiloSerializer(configuracion) return Response(serializer.data, status=status.HTTP_200_OK) def put(self, request): """Edita la configuración por defecto (es_default=True).""" - configuracion = get_object_or_404(ConfiguracionColores, es_default=True) + configuracion = get_object_or_404(Colores, es_default=True) serializer = ConfiguracionEstiloSerializer(configuracion, data=request.data) if serializer.is_valid(): serializer.save() diff --git a/cosiap_frontend/src/App.css b/cosiap_frontend/src/App.css index b38c3e9d95644db0b73724fff6c3941552f80bbc..ddf68e2b49d9465026bc1c920f72bf253a26bee5 100644 --- a/cosiap_frontend/src/App.css +++ b/cosiap_frontend/src/App.css @@ -1,7 +1,15 @@ + body { background: var(--pagina-fondo); } +.site-title{ + color: var(--principal-mf); + font-size: 30px; + font-weight: bold; + margin-bottom: 16px; +} + /* Estilo para los estados */ .estado-label { padding: 5px 10px; @@ -38,7 +46,7 @@ body { } .button-editar{ - background-color: brown; + background-color: var(--principal-mf); color: white; padding: 5px 10px; border-radius: 5px; @@ -195,17 +203,17 @@ input[type="checkbox"] { .subtitle-text { font-size: 20px; - color: #c65f5f; + color: var(--principal); } .subtitle-text-1 { font-size: 18px; - color: #752323; + color: var(--principal-mf); } .subtitle-text-2 { font-size: 16px; - color: #9e5f5f; + color: var(--principal-f); } /* Ajustar márgenes y tamaño del texto en etiquetas */ @@ -250,7 +258,7 @@ input[type="checkbox"] { } .card { - border: 2px solid #b4756e; + border: 2px solid var(--principal); border-radius: 12px; margin: 20px 0; padding: 15px; @@ -263,27 +271,27 @@ input[type="checkbox"] { .card-header-section { font-weight: bold; font-size: 18px; - color: brown; /* Color verde oscuro para el título */ + color: var(--principal-mf); /* Color verde oscuro para el título */ margin-bottom: 10px; - border-bottom: 1px solid #6b1a08; /* Línea inferior */ + border-bottom: 1px solid var(--principal-mf); /* Línea inferior */ padding-bottom: 5px; } .card-header-element { font-weight: bold; font-size: 16px; - color: brown; /* Color verde oscuro para el título */ + color: var(--principal-mf); /* Color verde oscuro para el título */ margin-bottom: 10px; - border-bottom: 1px solid #6b1a08; /* Línea inferior */ + border-bottom: 1px solid var(--principal-mf); /* Línea inferior */ padding-bottom: 5px; } .card-header-option { font-weight: bold; font-size: 14px; - color: brown; /* Color verde oscuro para el título */ + color: var(--principal-mf); /* Color verde oscuro para el título */ margin-bottom: 10px; - border-bottom: 1px solid #6b1a08; /* Línea inferior */ + border-bottom: 1px solid var(--principal-mf); /* Línea inferior */ padding-bottom: 5px; } @@ -557,7 +565,7 @@ font-size: 16px; margin: 20px auto; /* Centrar las cards */ padding: 25px; border-radius: 15px; - border: 2px solid #b4756e; + border: 2px solid var(--principal); box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out; } @@ -566,7 +574,7 @@ font-size: 16px; font-size: 2rem; font-weight: 600; margin-bottom: 15px; - color: brown; + color: var(--principal-mf); text-align: center; position: relative; padding-bottom: 10px; @@ -575,10 +583,11 @@ font-size: 16px; .subtitle{ font-size: 20px; margin-bottom: 8px; - color: brown; + color: var(--principal-mf); text-align: center; position: relative; padding-bottom: 10px; + flex-direction: column; } /* Línea decorativa debajo del h3 */ @@ -587,7 +596,7 @@ font-size: 16px; position: absolute; width: 50%; height: 3px; - background-color: brown; + background-color: var(--principal-mf); bottom: 0; left: 25%; border-radius: 2px; @@ -656,7 +665,7 @@ font-size: 16px; .monto-card { background-color: var(--blanco); width: 90%; - border: 2px solid #b4756e; + border: 2px solid var(--principal); margin: 30px 0; padding: 30px; border-radius: 20px; @@ -667,7 +676,7 @@ font-size: 16px; font-size: 1.8rem; font-weight: bold; margin-bottom: 10px; - color: brown; + color: var(--principal-mf); text-align: center; } @@ -871,7 +880,7 @@ font-size: 16px; } thead tr { - background-color: #f28b8b; /* Rojo claro */ + background-color: var(--principal-c); /* Rojo claro */ color: white; font-weight: bold; } @@ -1096,7 +1105,7 @@ th, td { } .button-users { - background-color: brown; + background-color: var(--principal-mf); color: white; border: none; padding: 12px 18px; @@ -1166,7 +1175,7 @@ th, td { justify-content: center; align-items: center; padding: 20px; - background-color: #f9e8d7; + background-color: var(--principal-mc); border-radius: 16px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); } @@ -1176,7 +1185,7 @@ th, td { justify-content: center; align-items: center; padding: 20px; - background-color: #e4896f; + background-color: var(--principal-mc); border-radius: 16px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); } @@ -1189,7 +1198,7 @@ th, td { } .title { - color: #8d2f2f; + color: var(--principal-mf); font-size: 24px; font-weight: bold; margin-bottom: 16px; @@ -1208,7 +1217,7 @@ th, td { } .start-button { - background-color: #8d2f2f; + background-color: var(--principal-mf); color: white; border: none; padding: 10px 20px; diff --git a/cosiap_frontend/src/App.jsx b/cosiap_frontend/src/App.jsx index 1bcca9cd90d3a9e7527140eede49408db3a064c5..7d6143c0f3f3305a7352958995549fcfb9657d13 100644 --- a/cosiap_frontend/src/App.jsx +++ b/cosiap_frontend/src/App.jsx @@ -20,7 +20,7 @@ import NoAutorizado from "@/components/users/NoAutorizado"; import PageNotFound from "@/components/users/PageNotFound"; import Inicio from "@/components/Inicio"; -import { useState } from "react"; +import { useState, useEffect } from "react"; // Importaciones de layoutsBase import LayoutBaseAuthenticator from "@/components/common/layouts/LayoutBaseAuthenticator"; import LayoutBaseNavigation from "@/components/common/layouts/LayoutBaseNavigation"; @@ -39,10 +39,26 @@ import ListaAdmins from "./components/admin/TablaAdministradores"; import CrearAdmin from "./components/admin/CrearAdministrador"; import ListaFormatos from "./components/plantillas/ListaFormatos"; import CrearFormato from "./components/plantillas/CrearPlantilla"; +import useColor from "./components/useColor"; +import EditarColorLogo from "./components/design/colorLogo"; function App() { const [viewPageLoader, setViewPageLoader] = useState(false); + const colors = useColor(); + + useEffect(() => { + if (colors) { + document.documentElement.style.setProperty('--color-principal', colors.color_principal); + document.documentElement.style.setProperty('--principal-mf', colors.principal_mf); + document.documentElement.style.setProperty('--principal-f', colors.principal_f); + document.documentElement.style.setProperty('--principal', colors.principal); + document.documentElement.style.setProperty('--principal-c', colors.principal_c); + document.documentElement.style.setProperty('--principal-mc', colors.principal_mc); + } + }, [colors]); + + return ( @@ -132,6 +148,7 @@ function RoutesApp({ setViewPageLoader }) { } /> } /> } /> + } /> diff --git a/cosiap_frontend/src/api.js b/cosiap_frontend/src/api.js index c357def142b66581a230d1ce6cc7f837e0f6a46a..45cbcca9153f32b595dfe60849593910b9cf01a1 100644 --- a/cosiap_frontend/src/api.js +++ b/cosiap_frontend/src/api.js @@ -195,6 +195,10 @@ const api = { convocatoria: { get: () => ax.get('api/administracion/convocatoria/'), put: (data) => ax.put('api/administracion/convocatoria/', data) + }, + estilos: { + get: ()=> ax.get('api/administracion/estilos/'), + update: (data)=> ax.put('api/administracion/estilos/', data) } }; diff --git a/cosiap_frontend/src/components/Inicio.jsx b/cosiap_frontend/src/components/Inicio.jsx index 64541c48eb29971998fe8db77b4bc351fd1675bb..7866cd94816617ac3229e0a201903d01a7443c63 100644 --- a/cosiap_frontend/src/components/Inicio.jsx +++ b/cosiap_frontend/src/components/Inicio.jsx @@ -2,6 +2,7 @@ import { useAutenticacion } from "@/components/common/utility/Autenticador"; import MainContainer from "@/components/common/utility/MainContainer"; import '@/App.css' import { useNavigate } from 'react-router-dom'; +import { apiUrl } from "@/api"; export default function Inicio() { const { isAdmin } = useAutenticacion(); @@ -29,8 +30,8 @@ export default function Inicio() {
Home Solicitante
@@ -52,7 +53,7 @@ export default function Inicio() {
Home Solicitante
diff --git a/cosiap_frontend/src/components/common/layouts/LayoutsNavigation/Navbar/NavbarBrand.jsx b/cosiap_frontend/src/components/common/layouts/LayoutsNavigation/Navbar/NavbarBrand.jsx index 72c3dffb1baa3d3546dd7fd079d6dd82e8f16b68..0b391ad7b7d119c9c4da9fb728abd1e7c2fce8de 100644 --- a/cosiap_frontend/src/components/common/layouts/LayoutsNavigation/Navbar/NavbarBrand.jsx +++ b/cosiap_frontend/src/components/common/layouts/LayoutsNavigation/Navbar/NavbarBrand.jsx @@ -1,8 +1,11 @@ import { useNavigate } from "react-router-dom"; +import useColor from "@/components/useColor"; +import { apiUrl } from "@/api"; export default function NavbarBrand() { const navigate = useNavigate(); + const colors = useColor(); return ( <> @@ -10,7 +13,7 @@ export default function NavbarBrand() {
navigate('/inicio')}> - +
cosiap
diff --git a/cosiap_frontend/src/components/common/layouts/LayoutsNavigation/Settings.jsx b/cosiap_frontend/src/components/common/layouts/LayoutsNavigation/Settings.jsx index 0b589ad48644221bc3c9877e4e09c732709bf4bc..71d7bb33bb4fa92533cb6fd75304d3c772a3473d 100644 --- a/cosiap_frontend/src/components/common/layouts/LayoutsNavigation/Settings.jsx +++ b/cosiap_frontend/src/components/common/layouts/LayoutsNavigation/Settings.jsx @@ -2,11 +2,13 @@ import '@/App.css' import api from '@/api'; import { useEffect, useState } from "react"; import { useAutenticacion } from "@/components/common/utility/Autenticador"; +import { useNavigate } from '@/components/modalidades/Modalidad'; export default function Settings( {settingsRef, selectedNav, setSelectedNav} ){ const [convocatoria, setConvocatoria] = useState(true); const { isAdmin } = useAutenticacion(); + const navigate = useNavigate(); useEffect(() => { const fetchConvocatoria = async () => { @@ -76,6 +78,18 @@ export default function Settings( {settingsRef, selectedNav, setSelectedNav} ){
)}
+ {isAdmin && ( +
+ navigate('/editar-estilo')} + > + Configuración Estilo + +
+ )} diff --git a/cosiap_frontend/src/components/common/layouts/LayoutsNavigation/Sidebar/Sidebar.jsx b/cosiap_frontend/src/components/common/layouts/LayoutsNavigation/Sidebar/Sidebar.jsx index f118ec2da2f328dc70ba167053eb2bd9c96aedf6..753e2c0855c10bd3a7255b71848dc2463e57f2d3 100644 --- a/cosiap_frontend/src/components/common/layouts/LayoutsNavigation/Sidebar/Sidebar.jsx +++ b/cosiap_frontend/src/components/common/layouts/LayoutsNavigation/Sidebar/Sidebar.jsx @@ -7,10 +7,13 @@ import SidebarBrand from "@/components/common/layouts/LayoutsNavigation/Sidebar/ import Notifications from "@/components/common/layouts/LayoutsNavigation/Sidebar/Notifications"; import MobileMenu from "@/components/common/layouts/LayoutsNavigation/Sidebar/MobileMenu"; import { useAutenticacion } from '@/components/common/utility/Autenticador'; +import { apiUrl } from "@/api"; +import useColor from "@/components/useColor"; export default function Sidebar( {linksItems, viewMenu, setViewMenu} ){ const {cerrarSesion} = useAutenticacion(); const navigate = useNavigate(); + const colors = useColor(); // Estado para controlar la visibilidad de las notificaciones const [viewNotifications, setViewNotifications] = useState(false); @@ -61,7 +64,7 @@ export default function Sidebar( {linksItems, viewMenu, setViewMenu} ){
navigate('/inicio')}> - +
cosiap
diff --git a/cosiap_frontend/src/components/common/layouts/LayoutsNavigation/Sidebar/SidebarBrand.jsx b/cosiap_frontend/src/components/common/layouts/LayoutsNavigation/Sidebar/SidebarBrand.jsx index 3dde7c5ae79762872e066e8fbd52a7b200377fcc..0b551ef8708b129bf96eb0b11757438044e57d9e 100644 --- a/cosiap_frontend/src/components/common/layouts/LayoutsNavigation/Sidebar/SidebarBrand.jsx +++ b/cosiap_frontend/src/components/common/layouts/LayoutsNavigation/Sidebar/SidebarBrand.jsx @@ -1,12 +1,15 @@ import { useNavigate } from "react-router-dom"; +import { apiUrl } from "@/api"; +import useColor from "@/components/useColor"; export default function SidebarBrand(){ const navigate = useNavigate(); + const colors = useColor(); return (
navigate('/inicio')} className="cursor-pointer">
- +
diff --git a/cosiap_frontend/src/components/common/utility/MainContainer.jsx b/cosiap_frontend/src/components/common/utility/MainContainer.jsx index 4774e03649a642d9089827224c6d4b5b9ec6e51a..baa7330eeec20d13cf474818e5a64c79645349a8 100644 --- a/cosiap_frontend/src/components/common/utility/MainContainer.jsx +++ b/cosiap_frontend/src/components/common/utility/MainContainer.jsx @@ -8,7 +8,7 @@ export default function MainContainer({ title, children }) {
-
+
{children}
diff --git a/cosiap_frontend/src/components/design/colorLogo.jsx b/cosiap_frontend/src/components/design/colorLogo.jsx new file mode 100644 index 0000000000000000000000000000000000000000..7e80ee0d77d3ba3fe7df5014dbdd374b52118bc2 --- /dev/null +++ b/cosiap_frontend/src/components/design/colorLogo.jsx @@ -0,0 +1,184 @@ +import { useState, useEffect } from "react"; +import api from '../../api'; +import '@/App.css'; +import MainContainer from "../common/utility/MainContainer"; + +const EditarColorLogo = () => { + const [principal, setPrincipal] = useState(''); + const [principal_mf, setPrincipal_mf] = useState(''); + const [principal_f, setPrincipal_f] = useState(''); + const [principal_c, setPrincipal_c] = useState(''); + const [principal_mc, setPrincipal_mc] = useState(''); + const [logo, setLogo] = useState(null); + const [alertMessage, setAlertMessage] = useState(''); + const [isSuccess, setIsSuccess] = useState(false); + const [isConfirmingRedo, setIsConfirmingRedo] = useState(false); + + + useEffect(() => { + const fetchColors = async () => { + try { + const response = await api.estilos.get(); + setPrincipal(response.data.principal); + setPrincipal_mf(response.data.principal_mf); + setPrincipal_f(response.data.principal_f); + setPrincipal_c(response.data.principal_c); + setPrincipal_mc(response.data.principal_mc); + + } catch (error) { + console.error('Error al obtener los colores:', error); + } + }; + + fetchColors(); + }, []); + + const handleCloseMenu = () => { + setIsConfirmingRedo(false); + }; + + const handleRedoConfirm = () => { + setIsConfirmingRedo(true); + }; + + const handleLogoChange = (event) => { + const file = event.target.files[0]; + if (file && file.type.startsWith("image/")) { + setLogo(file); + } else { + showAlert("Por favor, selecciona un archivo de imagen válido.", false); + } + }; + + const handleSubmit = async (event) => { + event.preventDefault(); + const formData = new FormData(); + formData.append('principal', principal); + formData.append('principal_mf', principal_mf); + formData.append('principal_f', principal_f); + formData.append('principal_c', principal_c); + formData.append('principal_mc', principal_mc); + formData.append('es_default', true) + if (logo) { + formData.append('logo', logo); + } + + try { + await api.estilos.update(formData); + showAlert("Configuración actualizada correctamente.", true); + window.location.reload(); + } catch (error) { + showAlert("Hubo un problema al actualizar la configuración.", false); + } + }; + + const handleReestablecer = async (e) => { + e.preventDefault(); + const formData = new FormData(); + formData.append('principal', '#E2746E'); + formData.append('principal_mf', '#781005'); + formData.append('principal_f', '#BB4433'); + formData.append('principal_c', '#F5ADAB'); + formData.append('principal_mc', '#FCE2E4'); + formData.append('es_default', true) + try { + await api.estilos.update(formData); + showAlert("Configuración restablecida correctamente.", true); + setIsConfirmingRedo(false) + window.location.reload(); + } catch (error) { + showAlert("Hubo un problema al restablecer la configuración.", false); + } + }; + + const showAlert = (message, isSuccess) => { + setAlertMessage(message); + setIsSuccess(isSuccess); + + setTimeout(() => { + setAlertMessage(''); + }, 3000); + }; + + return ( + + {alertMessage && ( +
+ {alertMessage} +
+ )} +
+
+
+ + + +
+
+ + + +
+
+
+ + +
+ {isConfirmingRedo && ( +
+

¿Estás seguro de restablecer los estilos por defecto?

+ + +
+ )} +
+
+ ); +}; + +export default EditarColorLogo; diff --git a/cosiap_frontend/src/components/modalidades/EditarModalidad.jsx b/cosiap_frontend/src/components/modalidades/EditarModalidad.jsx index f815eaf01d2e0cb897451111cbd76bb9d3e60cb0..7263db06dae21eef47a880781fadfebc15c47439 100644 --- a/cosiap_frontend/src/components/modalidades/EditarModalidad.jsx +++ b/cosiap_frontend/src/components/modalidades/EditarModalidad.jsx @@ -3,6 +3,7 @@ import api from '../../api'; import '@/App.css'; import MainContainer from "../common/utility/MainContainer"; import { useNavigate, useParams } from 'react-router-dom'; +import { apiUrl } from "../../api"; const EditModalidad = () => { const { id } = useParams(); @@ -563,7 +564,7 @@ const EditModalidad = () => {
Imagen previa diff --git a/cosiap_frontend/src/components/modalidades/Modalidad.jsx b/cosiap_frontend/src/components/modalidades/Modalidad.jsx index 033d5fb8639e3529fce851ce3dcb2839f4fd620f..d3e1c3fbffc4bb940fa91e1990a5ed3721ff6bb1 100644 --- a/cosiap_frontend/src/components/modalidades/Modalidad.jsx +++ b/cosiap_frontend/src/components/modalidades/Modalidad.jsx @@ -1,6 +1,7 @@ import InputMonto from "@/components/common/utility/InputMonto"; import { renderElemento } from "@/components/common/utility/RenderElemento"; import '@/App.css'; +import { apiUrl } from "@/api"; /* Validaciones para formularios */ import { @@ -290,7 +291,7 @@ const SolicitarModalidad = () => { {/* Imagen y descripción de la modalidad */}
- Modalidad + Modalidad

Modalidad:

diff --git a/cosiap_frontend/src/components/modalidades/ModalidadCard.jsx b/cosiap_frontend/src/components/modalidades/ModalidadCard.jsx index b9d4fd2b18a157ee621fd9e28351cb2949b20f53..78e85fa64cc9ce18685ec15c77c8b8b23ad900e9 100644 --- a/cosiap_frontend/src/components/modalidades/ModalidadCard.jsx +++ b/cosiap_frontend/src/components/modalidades/ModalidadCard.jsx @@ -1,3 +1,5 @@ +import { apiUrl } from "@/api"; + export function ModalidadCard({ title, description, monto, image, children }) { /* Formatear monto con separadores de miles */ const formatCurrency = (amount) => { @@ -19,15 +21,15 @@ export function ModalidadCard({ title, description, monto, image, children }) { > Modalidad - {`http://localhost:8000${image}`} + {`${apiUrl}${image}`}
-
-
-
+
+
+
diff --git a/cosiap_frontend/src/components/solicitudes/EditarSolicitud.jsx b/cosiap_frontend/src/components/solicitudes/EditarSolicitud.jsx index 15c61bc9c4bb4485ea09b234dd8858aac9d035c9..dc7130a34c5e9d0b3d30ebd857c1369d91188f9c 100644 --- a/cosiap_frontend/src/components/solicitudes/EditarSolicitud.jsx +++ b/cosiap_frontend/src/components/solicitudes/EditarSolicitud.jsx @@ -4,6 +4,8 @@ import MainContainer from "../common/utility/MainContainer"; import { useNavigate, useParams } from 'react-router-dom'; import { renderElemento } from "@/components/common/utility/RenderElementEdit"; import '@/App.css'; +import { apiUrl } from "../../api"; + /* Validaciones para formularios */ import { MontoValidation, @@ -301,7 +303,7 @@ const EditarSolicitud = () => { )} {/* Imagen y descripción de la modalidad */}
- Modalidad + Modalidad

Modalidad:

diff --git a/cosiap_frontend/src/components/solicitudes/VerSolicitud.jsx b/cosiap_frontend/src/components/solicitudes/VerSolicitud.jsx index 7e1fe6c903aa9a30899ead5517644d81f087a735..9cf085ce388afba176073e0afe7250e687ee5c7a 100644 --- a/cosiap_frontend/src/components/solicitudes/VerSolicitud.jsx +++ b/cosiap_frontend/src/components/solicitudes/VerSolicitud.jsx @@ -4,6 +4,7 @@ import MainContainer from "../common/utility/MainContainer"; import { useParams } from "react-router-dom"; import { renderElemento } from "@/components/common/utility/RenderElementView"; import "@/App.css"; +import { apiUrl } from "../../api"; const VisualizarSolicitud = () => { const { id } = useParams(); @@ -157,7 +158,7 @@ const VisualizarSolicitud = () => {
)}
- Modalidad + Modalidad

Modalidad:

@@ -194,7 +195,7 @@ const VisualizarSolicitud = () => { <> diff --git a/cosiap_frontend/src/components/useColor.jsx b/cosiap_frontend/src/components/useColor.jsx new file mode 100644 index 0000000000000000000000000000000000000000..b3a0f22dfc7e49907644f3278619d9041382b578 --- /dev/null +++ b/cosiap_frontend/src/components/useColor.jsx @@ -0,0 +1,39 @@ +// useColor.js +import { useState, useEffect } from 'react'; +import api from '@/api'; + +const useColor = () => { + const [colors, setColors] = useState({ + principal: '', + principal_mf: '', + principal_f: '', + principal_c: '', + principal_mc: '', + logo: '' + }); + + useEffect(() => { + const fetchColors = async () => { + try { + const response = await api.estilos.get(); + const fetchedColors = { + principal: response.data.principal, + principal_mf: response.data.principal_mf, + principal_f: response.data.principal_f, + principal_c: response.data.principal_c, + principal_mc: response.data.principal_mc, + logo: response.data.logo + }; + setColors(fetchedColors); + } catch (error) { + console.error('Error al obtener los colores:', error); + } + }; + + fetchColors(); + }, []); + + return colors; +}; + +export default useColor; diff --git a/cosiap_frontend/tailwind.config.js b/cosiap_frontend/tailwind.config.js index 004dad414946e8f1385a33b9b13d4178e032205a..7a7e7e95854f8cdbd6532e1a3a2506e075cafda6 100644 --- a/cosiap_frontend/tailwind.config.js +++ b/cosiap_frontend/tailwind.config.js @@ -5,6 +5,7 @@ import aspectRatio from '@tailwindcss/aspect-ratio'; import containerQueries from '@tailwindcss/container-queries'; export default { + content: [ "./src/**/*.{html,js,jsx}", ],