Merge branch '320-display-persons-in-banner' into 'master'

Display first associated persons in the banner of an accompanying course

Closes #320

See merge request Chill-Projet/chill-bundles!769
This commit is contained in:
Julien Fastré 2025-01-23 20:19:31 +00:00
commit 35f25daf7c
5 changed files with 105 additions and 50 deletions

View File

@ -0,0 +1,6 @@
kind: Feature
body: Show the first 3 persons directly in the accompanying period's banner
time: 2025-01-23T21:13:22.926870961+01:00
custom:
Issue: "320"
SchemaChange: No schema change

View File

@ -80,6 +80,13 @@
</span> </span>
</teleport> </teleport>
<teleport to="#header-accompanying_course-name #persons-associated-shortlist">
<persons-associated
:accompanyingCourse="accompanyingCourse"
:shortlist="true"
></persons-associated>
</teleport>
<teleport to="#header-accompanying_course-details #banner-social-issues"> <teleport to="#header-accompanying_course-details #banner-social-issues">
<social-issue <social-issue
v-for="issue in accompanyingCourse.socialIssues" v-for="issue in accompanyingCourse.socialIssues"
@ -89,7 +96,10 @@
</teleport> </teleport>
<teleport to="#header-accompanying_course-details #banner-persons-associated"> <teleport to="#header-accompanying_course-details #banner-persons-associated">
<persons-associated :accompanying-course="accompanyingCourse" /> <persons-associated
:accompanying-course="accompanyingCourse"
:shortlist="false"
/>
</teleport> </teleport>
</template> </template>

View File

@ -1,26 +1,45 @@
<template> <template>
<span <span v-if="shortlist">
v-for="h in personsByHousehold()" <span v-for="person in firstPersons" class="me-1" :key="person.id">
:class="{
household: householdExists(h.id),
'no-household': !householdExists(h.id),
}"
:key="h.id"
>
<a v-if="householdExists(h.id)" :href="householdLink(h.id)">
<i
class="fa fa-home fa-fw text-light"
:title="$t('persons_associated.show_household_number', { id: h.id })"
/>
</a>
<span v-for="person in h.persons" class="me-1" :key="person.id">
<on-the-fly <on-the-fly
:type="person.type" :type="person.type"
:id="person.id" :id="person.id"
:button-text="person.textAge" :buttonText="person.textAge"
:display-badge="'true' === 'true'" :displayBadge="'true' === 'true'"
action="show" action="show"
/> ></on-the-fly>
</span>
<span v-if="hasMoreThanShortListPerson">
<a
class="showMore carousel-control"
role="button"
data-bs-target="#ACHeaderSlider"
data-bs-slide="next"
>{{ $t("more_x", { x: countMoreThanShortListPerson }) }}</a
>
</span>
</span>
<span v-else>
<span
v-for="([pk, persons], h) in personsByHousehold"
:class="{ household: pk > -1, 'no-household': pk === -1 }"
:key="h.id"
>
<a v-if="pk !== -1" :href="householdLink(h)">
<i
class="fa fa-home fa-fw text-light"
:title="$t('persons_associated.show_household_number', { id: h })"
></i>
</a>
<span v-for="person in persons" class="me-1" :key="person.id">
<on-the-fly
:type="person.type"
:id="person.id"
:buttonText="person.textAge"
:displayBadge="true"
action="show"
></on-the-fly>
</span>
</span> </span>
</span> </span>
</template> </template>
@ -33,7 +52,14 @@ export default {
components: { components: {
OnTheFly, OnTheFly,
}, },
props: ["accompanyingCourse"], props: ["accompanyingCourse", "shortlist"],
data() {
return {
showAllPersons: false,
maxTotalPersons: 2,
nbShortList: 3,
};
},
computed: { computed: {
participations() { participations() {
return this.accompanyingCourse.participations.filter( return this.accompanyingCourse.participations.filter(
@ -43,36 +69,37 @@ export default {
persons() { persons() {
return this.participations.map((p) => p.person); return this.participations.map((p) => p.person);
}, },
firstPersons() {
return this.participations.slice(0, 3).map((p) => p.person);
},
hasMoreThanShortListPerson() {
return this.participations.length > 3;
},
countMoreThanShortListPerson() {
return this.participations.length - 3;
},
resources() { resources() {
return this.accompanyingCourse.resources; return this.accompanyingCourse.resources;
}, },
requestor() { requestor() {
return this.accompanyingCourse.requestor; return this.accompanyingCourse.requestor;
}, },
},
methods: {
uniq(array) {
return [...new Set(array)];
},
personsByHousehold() { personsByHousehold() {
let households = []; const households = new Map();
this.persons.forEach((p) => { this.accompanyingCourse.participations
households.push(p.current_household_id); .filter((p) => p.endDate === null)
.map((p) => p.person)
.forEach((person) => {
if (!households.has(person.current_household_id || -1)) {
households.set(person.current_household_id || -1, []);
}
households.get(person.current_household_id || -1).push(person);
}); });
let personsByHousehold = []; return households;
this.uniq(households).forEach((h) => {
personsByHousehold.push({
id: h !== null ? h : 0,
persons: this.persons.filter((p) => p.current_household_id === h),
});
});
//console.log(personsByHousehold)
return personsByHousehold;
}, },
householdExists(id) {
return id !== 0;
}, },
methods: {
householdLink(id) { householdLink(id) {
return `/fr/person/household/${id}/summary`; return `/fr/person/household/${id}/summary`;
}, },
@ -81,6 +108,10 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.showMore {
cursor: pointer;
color: white;
}
span.household { span.household {
display: inline-block; display: inline-block;
border-top: 1px solid rgba(255, 255, 255, 0.3); border-top: 1px solid rgba(255, 255, 255, 0.3);

View File

@ -5,6 +5,7 @@ import { ontheflyMessages } from "ChillMainAssets/vuejs/OnTheFly/i18n";
const appMessages = { const appMessages = {
fr: { fr: {
more_x: "et {x} de plus",
course: { course: {
id: "id", id: "id",
title: { title: {

View File

@ -2,14 +2,23 @@
<div id="header-accompanying_course-name" class="header-name"> <div id="header-accompanying_course-name" class="header-name">
<div class="container-xxl"> <div class="container-xxl">
<div class="row"> <div class="row">
<div class="col-md-6 ps-md-5 ps-xxl-0"> <div class="col-md-6 ps-md-5 ps-xxl-0">
<div class="row">
<div class="col-12">
<h1> <h1>
<i class="fa fa-random fa-fw"></i> <i class="fa fa-random fa-fw"></i>
{{ 'Accompanying Course'|trans }} {{ 'Accompanying Course'|trans }}
<span class="id-number">{{ accompanyingCourse.id }}</span> <span class="id-number">{{ accompanyingCourse.id }}</span>
</h1> </h1>
</div> </div>
</div>
<div class="row">
<div class="col-12">
<div id="persons-associated-shortlist"></div>
</div>
</div>
</div>
{# vue teleport fragment here #} {# vue teleport fragment here #}
<div class="col-md-3 mt-3 mb-1 my-md-3" id="banner-flags"></div> <div class="col-md-3 mt-3 mb-1 my-md-3" id="banner-flags"></div>
@ -24,12 +33,10 @@
<div id="header-accompanying_course-details" class="header-details"> <div id="header-accompanying_course-details" class="header-details">
<div class="container-xxl"> <div class="container-xxl">
<div class="row"> <div class="row">
<div class="col-md-12 px-md-5 px-xxl-0"> <div class="col-md-12 px-md-5 px-xxl-0">
<div id="ACHeaderSlider" class="carousel carousel-dark slide" data-bs-ride="carousel"> <div id="ACHeaderSlider" class="carousel carousel-dark slide" data-bs-ride="carousel">
<div class="carousel-inner"> <div class="carousel-inner">
<div class="carousel-item active"> <div class="carousel-item active">
{# vue teleport fragment here #}
<div id="banner-social-issues" class="col-11"></div> <div id="banner-social-issues" class="col-11"></div>
</div> </div>
<div class="carousel-item"> <div class="carousel-item">