<!DOCTYPE html>
<html lang="{{ app.request.locale }}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GENCAT | {% block title %}{{ 'header.title'|trans({}, 'base') }}{% endblock %}</title>
{% set route = app.request.attributes.get('_route') %}
{% set parts = route|split('_') %}
{% set paths = [] %}
{% for i in 1..parts|length %}
{% set paths = paths|merge([parts|slice(0, i)|join('_')]) %}
{% endfor %}
<!-- Hoja de estilos general para el layout -->
{% block stylesheets %}
<link rel="stylesheet" href="{{ asset("css/style.css") }}">
<link rel="stylesheet" href="{{ asset("css/layout.css") }}">
<link rel="stylesheet" href="{{ asset('css/modal.css') }}">
<link rel="stylesheet" href="{{ asset('css/modal-bootstrap-dialog.css') }}">
<link rel="stylesheet" href="{{ asset('css/chatbot.css') }}">
<link rel="stylesheet" href="{{ asset('css/tables.css') }}">
<link rel="stylesheet" href="{{ asset('css/sort.css') }}">
<!-- FontAwesome CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap3-dialog/1.34.7/css/bootstrap-dialog.min.css">
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css">
{# <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css" rel="stylesheet">#}
{# añadimos según el perfil de usuario su css correspondiente #}
{% if app.session.get('rol') %}
{% set perfil = app.session.get('rol') | lower %}
{% if css_exists('css/' ~ perfil ~ '/style.css') %}
<link rel="stylesheet" href="{{ asset('css/' ~ perfil ~ '/style.css') }}">
{% endif %}
{% if css_exists('css/' ~ perfil ~ '/layout.css') %}
<link rel="stylesheet" href="{{ asset('css/' ~ perfil ~ '/layout.css') }}">
{% endif %}
{% endif %}
{% for path in paths %}
{% if css_exists('css/' ~ path ~ '/style.css') %}
<link rel="stylesheet" href="{{ asset('css/' ~ path ~ '/style.css') }}">
{% endif %}
{% if css_exists('css/' ~ path ~ '/layout.css') %}
<link rel="stylesheet" href="{{ asset('css/' ~ path ~ '/layout.css') }}">
{% endif %}
{% endfor %}
{% endblock %}
<!-- JavaScript -->
{% block javascripts %}
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-validation@1.19.3/dist/jquery.validate.js"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-validation@1.19.3/dist/localization/messages_es.js"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/locale/es.min.js"
type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js"
type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/i18n/es.js"
type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jcarousel/0.3.9/jquery.jcarousel.min.js" integrity="sha512-5TU8T3STShZiLsdqDqiKnj0Z72ccPZpIDCuItxc2S7G3lyiwqiuLuDFVNsLQ7Hgu5f33DlZ2KAJspbn6NAXqnA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
{# Define missing asset variable that app.js expects #}
<script>
// Fix for missing asset variable that breaks existing JavaScriptf
// TODO lo comento porque está dando muchos problemas con app.js del código existente
{#if (typeof asset === 'undefined') {#}
{# window.asset = '{{ app.request.getBasePath() }}/';#}
{# console.log('🔧 Asset variable defined as:', window.asset);#}
{#}#}
// Fix for missing datetimepicker that breaks existing JavaScript
$(document).ready(function() {
// Add a dummy datetimepicker function if it doesn't exist
if (typeof $.fn.datetimepicker === 'undefined') {
$.fn.datetimepicker = function() {
console.log('🔧 Dummy datetimepicker called for:', this);
return this; // Return the jQuery object for chaining
};
}
});
</script>
<script src="{{ asset('js/app.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/functionality.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/taborder.js') }}" type="text/javascript"></script>
{% include 'JS/translations_js.html.twig' %}
{% include 'JS/env_js.html.twig' %}
{% include 'JS/routes_js.html.twig' %}
{# <script src="{{ asset("assets/bootstrap-dialog/js/bootstrap-dialog.min.js") }}"></script>#}
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap3-dialog/1.34.7/js/bootstrap-dialog.min.js"></script>
<script src="{{ asset("js/alert_utils.js") }}"></script>
{% include 'notification.js.twig' %}
<script type="text/javascript">
$(document).ready(function() {
$("select").select2();
// Handle alert close button
$(document).on('click', '.close-alert', function() {
$(this).closest('.alert').fadeOut(300, function() {
$(this).remove();
});
});
});
/**
* Clear all form filters and reload page
*/
function clearFilters() {
{% block clearFilters %}
$("section#filter input:not([type='hidden']), section#filter select").each(function(key, value) {
if($(value).attr("type") === "checkbox" || $(value).attr("type") === "radio")
{
$(value).prop("checked", false);
}
else
{
$(value).val(null).trigger("change");
}
});
$("section#filter form").submit();
{% endblock %}
}
</script>
{% endblock %}
<link rel="stylesheet" href="{{ asset('css/responsive.css') }}">
</head>
<body id="{{ route }}" class="{{ app.session.get('rol')|lower|default('default') }}" data-env="{{ app.environment }}">
{% block header_logo_hidden %}
<h1 class="h1-hidden">{{ 'header.logo'|trans({}, 'base') }}</h1>
{% endblock %}
<!-- Header -->
<header>
{% block header %}
<section id="header-top-bar">
<div class="header-top-container">
{% block header_top_bar %}
<div class="header-logo">
{% block header_logo %}
<div class="logo">
<a href="https://web.gencat.cat/ca/inici">
<img src="{{ asset("logo/gencat-w.svg") }}" alt="Logo">
</a>
</div>
{% endblock %}
</div>
{# {% block header_2_wrapper %}#}
{# <div class="header-2">#}
{# {% block header_title_secondary %}#}
{# {{ 'header.title.secondary'|trans({}, 'base') }}#}
{# {% endblock %}#}
{# </div>#}
{# {% endblock %}#}
{% block menu_wrapper %}
<ul class="menu">
{% block header_menu %}
<li><a href="{{ path('content_html', { 'slug': 'contact' }) }}">{{ 'header.menu.contact'|trans({}, 'base') }}</a></li>
<span class="separator">|</span>
<li>
{% block select_language %}
{# <a href="#">{{ 'header.menu.language'|trans({}, 'base') }}</a> #}
<select id="select-language" onchange="redirectToPage()">
{% set localesArray = locales|split(',') %}
{% for key, localeLiteral in localesLiteral|split(',') %}
<option value="{{ localesArray[key] | trim }}"
{% if (localesArray[key] | trim) == app.request.locale %}selected{% endif %}
data-url="{{ path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params') | merge({ '_locale': (localesArray[key] | trim) })) }}">{{ localeLiteral }}</option>
{% endfor %}
</select>
<script>
function redirectToPage() {
let select = document.getElementById("select-language");
let url = select.options[select.selectedIndex].getAttribute("data-url");
if (url) {
window.location.href = url;
}
}
</script>
{% endblock select_language %}
</li>
{% endblock %}
</ul>
{% endblock %}
{% block header_3_wrapper %}
{% block header_private_space %}
{% if app.user is empty %}
<div class="header-3">
<a href="{{ path('login_request_credentials') }}">{{ 'header.private_space'|trans({}, 'base') }}</a>
</div>
{% endif %}
{% endblock %}
{% endblock %}
{% endblock %}
</div>
</section>
{% block header_top_bar_2 %}
<section id="header-top-bar-2">
<div class="header-top-container">
{% block header_2_wrapper %}
<div class="header-2">
{% block header_title_secondary %}
<a href="{{ path('home') }}">{{ 'header.title.secondary'|trans({}, 'base') }}</a>
{% endblock %}
</div>
{% endblock %}
</div>
</section>
{% endblock %}
{% block header_links_wrapper %}
<section id="header-links">
<div class="header-top-container">
<div id="header-links-menu">
{% block header_links_menu %}
{% if app.user %}
<div id="menu-app">
{% set rol = app.session.get('rol') | default(constant('App\\Enum\\RolEnum::PARTICIPANTE')) %}
{{ menu('APP_' ~ rol, app.request.locale, '', 'nav-menu-app-'~ rol | lower , 'app_user_type_menu.html.twig') }}
</div>
{% else %}
<a href="{{ path('course_list') }}">{{ 'header.link.search_courses'|trans({}, 'home') }}</a>
<span class="separator">|</span>
<a href="{{ path('orientation_point_list') }}">{{ 'header.link.orientation_points'|trans({}, 'home') }}</a>
<span class="separator">|</span>
<a href="{{ path('login_request_credentials') }}">{{ 'header.link.your_space'|trans({}, 'home') }}</a>
{% endif %}
{% endblock %}
</div>
<div id="header-links-info">
{% block header_links_info %}
{% if app.user %}
{% set rol = app.session.get('rol') | default(constant('App\\Enum\\RolEnum::PARTICIPANTE')) %}
<div id="user-data">
{{ app.user.getPropietarioContenidoByRol(rol).nombreCompleto ?? app.user.nombreCompleto }}
<div id="menu-user">
{{ menu('USER_' ~ rol, app.request.locale, '', 'nav-menu-user-'~ rol | lower, 'user_type_menu.html.twig') }}
</div>
</div>
{% endif %}
{% endblock %}
</div>
</div>
</section>
{% endblock %}
{% block wrapper_header_miga_pan %}
<section id="miga-pan">
{% if app.session.get('rol')%}
{% set pathHome = path('home'~"_"~ app.session.get('rol')|lower) %}
{% else %}
{% set pathHome = path('home') %}
{% endif %}
{% block header_miga_pan %}
<a href="{{ pathHome }}">{{ 'header.breadcrumbs.home'|trans({}, 'base') }}</a>
{% endblock %}
</section>
{% endblock %}
{% block wrapper_header_title %}
<section id="title">
{% block header_title %}
{% endblock %}
</section>
{% endblock %}
{% endblock %}
</header>
<!-- Main Content -->
<main>
{% if 'HomeController' in app.request.get('_controller') and app.user and app.session.get('rol') != constant('App\\Enum\\RolEnum::CONSORCI')%}
{% set propietarioContenido = app.user.getPropietarioContenidoByRol(app.session.get('rol')) %}
{% set alertFillProfile = propietarioContenido ? propietarioContenido.alertFillProfile : null %}
{% if propietarioContenido and (alertFillProfile or alertFillProfile is null) %}
<div class="alert alert-danger">
<i class="fas fa-exclamation-circle alert-icon"></i>
{% set urlProfile = path((app.session.get('rol') ~ '_profile') | lower) %}
{{ 'alert.fill.profile' | trans({ '%url%': urlProfile }) | raw }}
<span class="close-alert"><i class="fas fa-times"></i></span>
</div>
{% endif %}
{% endif %}
{% for tipo, mensajes in app.flashes %}
{% set icon = 'fa-info-circle' %}
{% if tipo == 'success' %}
{% set icon = 'fa-check-circle' %}
{% elseif tipo == 'error' or tipo == 'danger' %}
{% set icon = 'fa-exclamation-circle' %}
{% elseif tipo == 'warning' %}
{% set icon = 'fa-exclamation-triangle' %}
{% endif %}
{% for mensaje in mensajes %}
<div class="alert alert-{{ tipo }}">
<i class="fas {{ icon }} alert-icon"></i>
{{ mensaje }}
<span class="close-alert"><i class="fas fa-times"></i></span>
</div>
{% endfor %}
{% endfor %}
{% block content %}
{% endblock %}
</main>
<!-- Prefooter -->
{% block prefooter_wrapper %}
{% endblock %}
<!-- Footer -->
<footer id="footer">
{% block footer %}
<div class="logo">
<a href="https://www.gencat.cat/" target="_blank"><img src="{{ asset("logo/logo_generalitat_color_b.png") }}"></a>
<a href="https://european-union.europa.eu/" target="_blank"><img src="{{ asset("logo/eu_cofi_feder_color_1.png") }}"></a>
</div>
<div class="footer-links">
<a href="{{ path('content_html', { 'slug': 'legal-notice' }) }}">{{ 'footer.legal_notice'|trans({}, 'base') }}</a>
<span class="separator">|</span>
<a href="{{ path('content_html', { 'slug': 'accessibility' }) }}">{{ 'footer.accessibility'|trans({}, 'base') }}</a>
<span class="separator">|</span>
<a href="{{ path('content_html', { 'slug': 'cookies-policy' }) }}">{{ 'footer.cookies_policy'|trans({}, 'base') }}</a>
<span class="separator">|</span>
<a href="{{ path('content_html', { 'slug': 'sitemap' }) }}">{{ 'footer.sitemap'|trans({}, 'base') }}</a>
</div>
{% endblock %}
{% block chatbot %}
{# Include the chatbot component #}
{% include 'functionality/chatbot/chatbot.html.twig' %}
{% endblock %}
</footer>
<!-- Loading -->
{% block loading %}
<div id="loading">
<img src="{{ asset('img/loadon.gif') }}" width="100px" alt="{{ 'loading.text'|trans({}, 'base') }}">
</div>
{% endblock %}
{% block modal %}
{% include 'modal/modal_change_rol.html.twig' %}
{% include 'modal/modal_admin_user.html.twig' %}
{% endblock %}
{# TinyMCE CDN para editor de texto enriquecido en foro (FORO-01) #}
<script src="https://cdn.tiny.cloud/1/nbx8er3s9hgvqhw2lx3l2bs2capgnkoixfadqf32ctt120vz/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>
{# Inicialización de TinyMCE para campos de foro #}
<script>
document.addEventListener('DOMContentLoaded', function() {
tinymce.init({
branding: false,
selector: 'textarea.wysiwyg', // Apunta a todos los textareas con nuestra clase
plugins: 'lists link autoresize',
toolbar: 'undo redo | bold italic | bullist numlist | link',
menubar: false,
language: 'es',
height: 500,
autoresize_bottom_margin: 20,
content_style: 'body { font-family: Arial, sans-serif; }',
setup: function (editor) {
// Compatibilidad con validación existente
editor.on('change', function () {
editor.save(); // Sincronizar contenido con textarea original
});
}
});
});
</script>
</body>
</html>