improved activity catalog
This commit is contained in:
parent
54da8c0465
commit
1ac3910259
|
@ -1,25 +1,5 @@
|
|||
.theme-basket {
|
||||
&--item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-bottom: 10px;
|
||||
border-bottom: $cell-entry-border;
|
||||
|
||||
@media(max-width: $very-small-limit) {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
&--item-details {
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
&--item-activity {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.theme-basket,
|
||||
.theme-activities {
|
||||
&--item-name,
|
||||
&--item-unit,
|
||||
&--item-location,
|
||||
|
@ -43,6 +23,29 @@
|
|||
&--item-name::before { content: "\f007"; }
|
||||
&--item-location::before { content: "\f041"; }
|
||||
&--item-date::before { content: "\f133"; }
|
||||
}
|
||||
|
||||
.theme-basket {
|
||||
&--item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-bottom: 10px;
|
||||
border-bottom: $cell-entry-border;
|
||||
|
||||
@media(max-width: $very-small-limit) {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
&--item-details {
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
&--item-activity {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&--item-summary {
|
||||
display: flex;
|
||||
|
@ -84,3 +87,97 @@
|
|||
@extend .cancel-button;
|
||||
}
|
||||
}
|
||||
|
||||
.theme-activities {
|
||||
&--search {
|
||||
display: grid;
|
||||
grid-auto-rows: auto;
|
||||
align-items: center;
|
||||
grid-template-columns: auto auto;
|
||||
margin-bottom: 2rem;
|
||||
|
||||
@media($max-mobile-viewport) {
|
||||
grid-template-columns: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&--criteria-label {
|
||||
margin: 1rem 1rem 0.5rem 0;
|
||||
|
||||
@media($max-mobile-viewport) {
|
||||
margin-bottom: 0.2rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
&--items {
|
||||
display: grid;
|
||||
grid-auto-rows: auto;
|
||||
}
|
||||
|
||||
&--item {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: right;
|
||||
|
||||
margin-bottom: 1rem;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid $cell-entry-border-color;
|
||||
|
||||
@media($max-mobile-viewport) {
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
&:not(.filtered) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&--item-label {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-right: calc(#{$title-font-size} + 0.5rem);
|
||||
margin-bottom: 0.5rem;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: -1rem;
|
||||
right: 0;
|
||||
font-size: $title-font-size;
|
||||
margin: 0 0.5rem;
|
||||
font-family: FontAwesome;
|
||||
color: $title-color;
|
||||
content: $cell-close-foldable-icon;
|
||||
}
|
||||
}
|
||||
|
||||
&--item.collapsed &--item-label::after {
|
||||
content: $cell-open-foldable-icon;
|
||||
}
|
||||
|
||||
&--item-type {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
&--item-summary {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@media($min-desktop-viewport) {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
&--item.collapsed &--item-details {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&--pagination {
|
||||
@extend .cell-items-pagination;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
"cache_duration": 0,
|
||||
"force_async": true,
|
||||
"name": "DUI (Teamnet Axel) : Activités auxquelles l'enfant est inscrit·e",
|
||||
"url": "{{passerelle_url}}toulouse-axel/{{slug}}/clae_children_activities_info?NameID={{user_nameid}}&booking_date={% now \"Y-m-d\" %}",
|
||||
"url": "{{ passerelle_url }}toulouse-maelis/{{ slug }}/read-activity-list?ref_date={% now 'Y-m-d' %}"",
|
||||
"form": [
|
||||
{"label": "Identifiant du connecteur", "varname": "slug", "required": true}
|
||||
]
|
||||
|
|
|
@ -1,264 +1,135 @@
|
|||
<h2>Catalogue des activité {{ json.meta.reference_year }}-{{ json.meta.reference_year|add:1 }}</h2>
|
||||
|
||||
<div class="search">
|
||||
<ul class="themes">
|
||||
{% for theme_id in json.meta.all_criterias_order %}
|
||||
{% with theme=json.meta.all_criterias|get:theme_id %}
|
||||
{% if theme.data %}
|
||||
<li class="theme-value {{ theme_id }}">
|
||||
<button>{{ theme.text }}</button>
|
||||
<ul class="criterias">
|
||||
{% for key in theme.order %}
|
||||
<li class="criteria-values {{ theme_id }}-{{ key }}">
|
||||
<button>{{ theme.data|get:key }}</button>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
<h2 class="cell--title">Catalogue des activité {{ json.meta.reference_year }}-{{ json.meta.reference_year|add:1 }}</h2>
|
||||
<div class="cell--body" data-cell-id="{{ cell.id }}">
|
||||
<div class="theme-activities--search">
|
||||
{% for criteria_id in json.meta.all_criterias_order %}
|
||||
{% with criteria=json.meta.all_criterias|get:criteria_id %}
|
||||
{% if criteria.data %}
|
||||
<div class="theme-activites--criteria">
|
||||
<label class="theme-activities--criteria-label">
|
||||
{{ criteria.text }} :
|
||||
</label>
|
||||
<div class="theme-activities--criteria-choices">
|
||||
<select data-autocomplete="true" multiple="true" data-criteria="{{criteria_id}}">
|
||||
{% for value_id in criteria.order %}
|
||||
<option value={{value_id}}>
|
||||
{{ criteria.data|get:value_id }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="results">
|
||||
<ul>
|
||||
</div>
|
||||
<div class="theme-activities--items">
|
||||
{% for item in json.data %}
|
||||
<li class="
|
||||
{% for theme_key, criterias in item.criterias.items %}
|
||||
{% for key in criterias.order %}{{ theme_key }}-{{ key }} {% endfor %}
|
||||
{% endfor %}
|
||||
result-item">
|
||||
<h3>{{ item.text }}</h3>
|
||||
{{ item.place.text }} /
|
||||
du {{ item.unit.dateStart|date:"d/m/Y" }} au {{ item.unit.dateEnd|date:"d/m/Y" }} /
|
||||
{{ item.criterias.type.data|get:item.criterias.type.order.0 }} /
|
||||
{{ item.place.text }} ---
|
||||
<span class="result-toggling">🔍 Voir</span>
|
||||
<a href="{{ eservices_url }}{{ form_url }}tryauth?activity_id={{ activity.activity_id}}&unit_id={{ activity.uniœt_id }}&place_id={{ activity.place_id }}">📝 Inscription</a>
|
||||
<span class="result-detail">
|
||||
<p class'resutl-detail-title'>Description :</p>
|
||||
{% lorem %}
|
||||
<p class'resutl-detail-title'>Public :</p>
|
||||
{% for key in item.criterias.public.order %}
|
||||
{{ item.criterias.public.data|get:key }}
|
||||
{% if not forloop.last %}, {% endif %}
|
||||
{% endfor %}.
|
||||
</p>
|
||||
</li>
|
||||
<div class="theme-activities--item filtered collapsed"
|
||||
{% for criteria_id, criterias in item.criterias.items %}
|
||||
data-criteria-{{ criteria_id }}="{{ criterias.order|join:',' }}"
|
||||
{% endfor %}
|
||||
>
|
||||
<div class="theme-activities--item-label" role="button" aria-label="Voir les détails" title="Détails">{{ item.text }}</div>
|
||||
<div class="theme-activities--item-summary">
|
||||
<div class="theme-activities--item-type">{{ item.criterias.type.data|get:item.criterias.type.order.0 }}</div>
|
||||
<div class="theme-activities--item-location">{{ item.place.text }}</div>
|
||||
<div class="theme-activities--item-date">Du {{ item.unit.dateStart|date:"d/m/Y" }} au {{ item.unit.dateEnd|date:"d/m/Y" }}</div>
|
||||
</div>
|
||||
<div class="theme-activities--item-details">
|
||||
<p class"theme-activities--item-description">{% lorem %}</p>
|
||||
<p class"theme-activities--item-audience">
|
||||
Public :
|
||||
{% for key in item.criterias.public.order %}
|
||||
{{ item.criterias.public.data|get:key }}
|
||||
{% if not forloop.last %}, {% endif %}
|
||||
{% endfor %}.
|
||||
</p>
|
||||
</div>
|
||||
<a class="pk-button"
|
||||
href="{{ eservices_url }}{{ form_url }}tryauth?activity_id={{ activity.activity_id}}&unit_id={{ activity.uniœt_id }}&place_id={{ activity.place_id }}">
|
||||
Inscription
|
||||
</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<div class="theme-activities--pagination">
|
||||
<button class="theme-activities--pagination-prev">←</a>
|
||||
<button class="theme-activities--pagination-next">→</a>
|
||||
</div>
|
||||
<div class="theme-activities--no-result" hidden>
|
||||
<p class="infonotice">Aucun Résultat</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.gru-content div.cell h2 + div {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.themes > li {
|
||||
display: flex;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.themes button {
|
||||
padding: 10px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.themes li > button {
|
||||
border: 1px solid #FFA58A;
|
||||
background-color: white;
|
||||
color: #FFA58A;
|
||||
}
|
||||
|
||||
.themes li.unused > button {
|
||||
background-color: #FFA58A;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.criterias {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.criterias li button {
|
||||
border: 1px solid #D8522A;
|
||||
background-color: white;
|
||||
color: #D8522A;
|
||||
margin-right: 5px;;
|
||||
}
|
||||
|
||||
.criterias li.selected button {
|
||||
background-color: #D8522A;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.results li {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.results li.shown {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.results h3 {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.results a {
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.result-detail {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.result-detail.shown {
|
||||
border-top: 1px solid black;
|
||||
border-bottom: 1px solid black;
|
||||
padding: 1em 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.resutl-detail-title {
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="{{portal_url}}/static/xstatic/select2.min.css">
|
||||
<script src="{{portal_url}}/static/xstatic/select2.min.js"></script>
|
||||
|
||||
<script>
|
||||
// criterias stored by themes
|
||||
const criterias = {
|
||||
{% for theme_key, criterias in json.meta.all_criterias.items %}
|
||||
'{{ theme_key }}': [{% for key in criterias.order %}'{{ key }}', {% endfor %}],
|
||||
{% endfor %}
|
||||
$(() => {
|
||||
const $cell = $('[data-cell-id="{{ cell.id }}"')
|
||||
const $pagination = $cell.find('.theme-activities--pagination')
|
||||
const $paginationPrev = $cell.find('.theme-activities--pagination-prev')
|
||||
const $paginationNext = $cell.find('.theme-activities--pagination-next')
|
||||
const paginateBy = 4;
|
||||
|
||||
function updatePagination(step) {
|
||||
const items = $cell.find('.theme-activities--item.filtered')
|
||||
|
||||
const maxPageIndex = Math.ceil(items.length / paginateBy);
|
||||
let pageIndex = $pagination.data('page_index') || 0
|
||||
pageIndex = Math.max(0, Math.min(pageIndex + step, maxPageIndex - 1));
|
||||
|
||||
$pagination.prop('hidden', maxPageIndex <= 1);
|
||||
$paginationPrev.prop('disabled', pageIndex === 0);
|
||||
$paginationNext.prop('disabled', pageIndex === maxPageIndex - 1)
|
||||
|
||||
const startItem = paginateBy * pageIndex;
|
||||
|
||||
items.hide();
|
||||
items.slice(startItem, startItem + paginateBy).show();
|
||||
$pagination.data('page_index', pageIndex);
|
||||
};
|
||||
|
||||
// ex: "http://.../?q=types-LOI_VAC,ages-0,ages-1,ages-3,ages-4,ages-5,places-A10053179604"
|
||||
const param_q = "{{ q }}";
|
||||
$paginationPrev.click(() => updatePagination(-1))
|
||||
$paginationNext.click(() => updatePagination(1))
|
||||
updatePagination(0)
|
||||
|
||||
// check if cell should be display, based on a uniq theme
|
||||
function is_cell_matching_theme(cell, theme) {
|
||||
$cell.find('select[data-criteria]').each((_, elem) => $(elem).select2())
|
||||
$cell.find('select[data-criteria]').on('change', evt => {
|
||||
let selectedCriterias = []
|
||||
|
||||
// accept cell as no criterias is selected for this theme
|
||||
if ($('.themes .' + theme).hasClass('unused')) {
|
||||
return true
|
||||
}
|
||||
|
||||
// accept cell is at least one criteria for this theme match (or)
|
||||
var found = false
|
||||
for (var i = 0; i < criterias[theme].length; i++) {
|
||||
var criteria = theme + '-' + criterias[theme][i];
|
||||
var criteria_class = '.criterias .' + criteria;
|
||||
if (cell.hasClass(criteria) && $(criteria_class).hasClass('selected')) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
// check if cell should be displayed, matching all themes (and)
|
||||
function is_cell_matching(cell) {
|
||||
var found = true;
|
||||
for (const theme in criterias) {
|
||||
if (is_cell_matching_theme(cell, theme) === false) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
// show all matching results
|
||||
function show_results() {
|
||||
$('.result-item').each(function(idx, elem) {
|
||||
if (is_cell_matching($(this))) {
|
||||
$(this).addClass('shown');
|
||||
}
|
||||
else {
|
||||
$(this).removeClass('shown');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// check if no criteria is selected for a theme
|
||||
function is_theme_still_in_use(theme) {
|
||||
var found = false
|
||||
for (var i = 0; i < criterias[theme].length; i++) {
|
||||
val = criterias[theme][i]
|
||||
if ($('.criterias .' + theme + '-' + val).hasClass('selected')) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
// trigger on criteria
|
||||
function select_criteria(theme, value) {
|
||||
var criteria = theme + '-' + value
|
||||
var criteria_class = '.' + criteria
|
||||
if (! $('.criterias ' + criteria_class).hasClass('selected')) {
|
||||
$('.criterias ' + criteria_class).addClass('selected');
|
||||
$('.themes .' + theme).removeClass('unused');
|
||||
}
|
||||
else {
|
||||
$('.criterias ' + criteria_class).removeClass('selected');
|
||||
if (! is_theme_still_in_use(theme)) {
|
||||
$('.themes .' + theme).addClass('unused');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// trigger on theme (first element of a row of criteria)
|
||||
function unuse_theme(theme) {
|
||||
if (! $('.themes .' + theme).hasClass('unused')) {
|
||||
$('.themes .' + theme + ' .criteria-values').removeClass('selected');
|
||||
$('.themes .' + theme).addClass('unused');
|
||||
}
|
||||
}
|
||||
|
||||
$('document').ready(function(){
|
||||
for (const theme in criterias) { // const needed
|
||||
|
||||
// register triggers to unuse themes
|
||||
$('.themes .'+ theme + ' > button').on('click', function() {
|
||||
unuse_theme(theme);
|
||||
show_results();
|
||||
});
|
||||
|
||||
// register triggers to select criterias
|
||||
var length = criterias[theme].length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
const value = criterias[theme][i] // const needed
|
||||
$('.criterias .' + theme + '-' + value).on('click', function() {
|
||||
select_criteria(theme, value);
|
||||
show_results();
|
||||
});
|
||||
for(const select of $cell.find('select[data-criteria]')) {
|
||||
if(select.selectedOptions.length === 0) {
|
||||
continue
|
||||
}
|
||||
|
||||
// initialize with all themes unused
|
||||
unuse_theme(theme);
|
||||
selectedCriterias.push([
|
||||
select.dataset.criteria,
|
||||
new Set([...select.selectedOptions].map(option => option.value))
|
||||
])
|
||||
}
|
||||
|
||||
// modify selection from query-string
|
||||
var params = param_q.split(',');
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
if (params[i].length > 0) {
|
||||
args = params[i].split('-');
|
||||
console.log(args.length)
|
||||
if (args.length == 2 && args[0].length > 0 && args[1].length > 0) {
|
||||
select_criteria(args[0], args[1]);
|
||||
$cell.find(`.theme-activities--item`).each((_, element) => {
|
||||
element.classList.add('filtered')
|
||||
for ([criteriaId, filteredValues] of selectedCriterias) {
|
||||
const elementValues = element.getAttribute(`data-criteria-${criteriaId}`)
|
||||
|
||||
if (elementValues !== undefined &&
|
||||
!elementValues.split(',').some(value => filteredValues.has(value))) {
|
||||
element.classList.remove('filtered')
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
show_results();
|
||||
});
|
||||
const filteredResults = $cell.find(`.theme-activities--item.filtered`)
|
||||
$cell.find(".theme-activities--no-result").prop('hidden', filteredResults.length !== 0)
|
||||
|
||||
// toggle result detail
|
||||
$('.result-toggling').on('click', function() {
|
||||
$(this).siblings(".result-detail").toggleClass('shown')
|
||||
});
|
||||
updatePagination(0)
|
||||
})
|
||||
|
||||
$cell.find('.theme-activities--item-label').on('click', evt => {
|
||||
$(evt.target).closest('.theme-activities--item').toggleClass('collapsed')
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue