mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-28 09:34:59 +00:00
Simplify and modernize entity components and translations for better performance and consistency
- Replace fragmented name rendering with unified `person.text` in Vue components. - Migrate `GenderIconRenderBox` to use Bootstrap icons and TypeScript. - Introduce `GenderTranslation` type and helper for gender rendering. - Refactor `PersonRenderBox` to streamline rendering logic and improve maintainability. Migrate to typescript - Update French translations for consistency with new gender rendering.
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
import {Gender, GenderTranslation} from "ChillMainAssets/types";
|
||||
|
||||
/**
|
||||
* Translates a given gender object into its corresponding gender translation string.
|
||||
*
|
||||
* @param {Gender|null} gender - The gender object to be translated, null values are also supported
|
||||
* @return {GenderTranslation} Returns the gender translation string corresponding to the provided gender,
|
||||
* or "unknown" if the gender is null.
|
||||
*/
|
||||
export function toGenderTranslation(gender: Gender|null): GenderTranslation
|
||||
{
|
||||
if (null === gender) {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
return gender.genderTranslation;
|
||||
}
|
@@ -33,11 +33,24 @@ export interface SetCivility {
|
||||
id: number;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gender translation.
|
||||
*
|
||||
* Match the GenderEnum in PHP code.
|
||||
*/
|
||||
export type GenderTranslation = "male" | "female" | "neutral" | "unknown";
|
||||
|
||||
/**
|
||||
* A gender
|
||||
*
|
||||
* See also
|
||||
*/
|
||||
export interface Gender {
|
||||
type: "chill_main_gender";
|
||||
id: number;
|
||||
label: string;
|
||||
genderTranslation: string;
|
||||
genderTranslation: GenderTranslation;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,28 +1,28 @@
|
||||
<template>
|
||||
<i :class="['fa', genderClass, 'px-1']" />
|
||||
<i :class="['bi', genderClass]"></i>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
const props = defineProps({
|
||||
gender: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
import type { Gender } from "ChillMainAssets/types";
|
||||
import {toGenderTranslation} from "ChillMainAssets/lib/api/genderHelper";
|
||||
|
||||
const genderClass = computed(() => {
|
||||
switch (props.gender.genderTranslation) {
|
||||
case "woman":
|
||||
return "fa-venus";
|
||||
case "man":
|
||||
return "fa-mars";
|
||||
case "both":
|
||||
return "fa-neuter";
|
||||
interface GenderIconRenderBoxProps {
|
||||
gender: Gender;
|
||||
}
|
||||
|
||||
const props = defineProps<GenderIconRenderBoxProps>();
|
||||
|
||||
const genderClass = computed<string>(() => {
|
||||
switch (toGenderTranslation(props.gender)) {
|
||||
case "female":
|
||||
return "bi-gender-female";
|
||||
case "male":
|
||||
return "bi-gender-male";
|
||||
case "neutral":
|
||||
case "unknown":
|
||||
return "fa-genderless";
|
||||
default:
|
||||
return "fa-genderless";
|
||||
return "bi-gender-neuter";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@@ -136,34 +136,6 @@ filter_order:
|
||||
Search: Chercher dans la liste
|
||||
By date: Filtrer par date
|
||||
search_box: Filtrer par contenu
|
||||
renderbox:
|
||||
person: "Usager"
|
||||
birthday:
|
||||
man: "Né le"
|
||||
woman: "Née le"
|
||||
neutral: "Né·e le"
|
||||
unknown: "Né·e le"
|
||||
deathdate: "Date de décès"
|
||||
household_without_address: "Le ménage de l'usager est sans adresse"
|
||||
no_data: "Aucune information renseignée"
|
||||
type:
|
||||
thirdparty: "Tiers"
|
||||
person: "Usager"
|
||||
holder: "Titulaire"
|
||||
years_old: >-
|
||||
{n, plural,
|
||||
=0 {0 an}
|
||||
one {1 an}
|
||||
other {# ans}
|
||||
}
|
||||
residential_address: "Adresse de résidence"
|
||||
located_at: "réside chez"
|
||||
household_number: "Ménage n°{number}"
|
||||
current_members: "Membres actuels"
|
||||
no_current_address: "Sans adresse actuellement"
|
||||
new_household: "Nouveau ménage"
|
||||
no_members_yet: "Aucun membre actuellement"
|
||||
|
||||
pick_entity:
|
||||
add: "Ajouter"
|
||||
modal_title: >-
|
||||
|
@@ -5,46 +5,16 @@
|
||||
<div class="item-col">
|
||||
<div class="entity-label">
|
||||
<div :class="'denomination h' + options.hLevel">
|
||||
<template v-if="options.addLink === true">
|
||||
<a v-if="options.addLink === true" :href="getUrl">
|
||||
<!-- use person-text here to avoid code duplication ? TODO -->
|
||||
<span class="firstname">{{ person.firstName }}</span>
|
||||
<span class="lastname">{{ person.lastName }}</span>
|
||||
<span v-if="person.suffixText" class="suffixtext"
|
||||
> {{ person.suffixText }}</span
|
||||
>
|
||||
<span
|
||||
v-if="person.altNames && options.addAltNames == true"
|
||||
class="altnames"
|
||||
>
|
||||
<span :class="'altname altname-' + altNameKey">{{
|
||||
altNameLabel
|
||||
}}</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<!-- use person-text here to avoid code duplication ? TODO -->
|
||||
<span class="firstname">{{ person.firstName + " " }}</span>
|
||||
<span class="lastname">{{ person.lastName }}</span>
|
||||
<span v-if="person.suffixText" class="suffixtext"
|
||||
> {{ person.suffixText }}</span
|
||||
>
|
||||
<span>{{ person.text }}</span>
|
||||
<span v-if="person.deathdate" class="deathdate"> (‡)</span>
|
||||
<span
|
||||
v-if="person.altNames && options.addAltNames == true"
|
||||
class="altnames"
|
||||
>
|
||||
<span :class="'altname altname-' + altNameKey">{{
|
||||
altNameLabel
|
||||
}}</span>
|
||||
</span>
|
||||
|
||||
<span
|
||||
v-if="options.addId == true"
|
||||
class="id-number"
|
||||
:title="'n° ' + person.id"
|
||||
>{{ person.id }}</span
|
||||
>
|
||||
|
||||
</a>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span>{{ person.text }}</span>
|
||||
<span v-if="person.deathdate" class="deathdate"> (‡)</span>
|
||||
</template>
|
||||
<badge-entity
|
||||
v-if="options.addEntity === true"
|
||||
:entity="person"
|
||||
@@ -52,61 +22,36 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<span
|
||||
v-if="options.addId == true"
|
||||
:title="person.personId"
|
||||
><i class="bi bi-info-circle"></i> {{ person.personId }}</span
|
||||
>
|
||||
</p>
|
||||
|
||||
<p v-if="options.addInfo === true" class="moreinfo">
|
||||
<gender-icon-render-box
|
||||
v-if="person.gender"
|
||||
:gender="person.gender"
|
||||
/>
|
||||
<time
|
||||
v-if="person.birthdate && !person.deathdate"
|
||||
:datetime="person.birthdate"
|
||||
:title="birthdate"
|
||||
/> <span
|
||||
v-if="person.birthdate"
|
||||
>
|
||||
{{
|
||||
trans(birthdateTranslation) +
|
||||
" " +
|
||||
new Intl.DateTimeFormat("fr-FR", {
|
||||
dateStyle: "long",
|
||||
}).format(birthdate)
|
||||
}}
|
||||
</time>
|
||||
|
||||
<time
|
||||
v-else-if="person.birthdate && person.deathdate"
|
||||
:datetime="person.deathdate"
|
||||
:title="person.deathdate"
|
||||
>
|
||||
{{
|
||||
new Intl.DateTimeFormat("fr-FR", {
|
||||
dateStyle: "long",
|
||||
}).format(birthdate)
|
||||
}}
|
||||
-
|
||||
{{
|
||||
new Intl.DateTimeFormat("fr-FR", {
|
||||
dateStyle: "long",
|
||||
}).format(deathdate)
|
||||
}}
|
||||
</time>
|
||||
|
||||
<time
|
||||
v-else-if="person.deathdate"
|
||||
:datetime="person.deathdate"
|
||||
:title="person.deathdate"
|
||||
>
|
||||
{{
|
||||
trans(RENDERBOX_DEATHDATE) +
|
||||
" " +
|
||||
new Intl.DateTimeFormat("fr-FR", {
|
||||
dateStyle: "long",
|
||||
}).format(deathdate)
|
||||
}}
|
||||
</time>
|
||||
|
||||
{{ trans(RENDERBOX_BIRTHDAY_STATEMENT, {gender: toGenderTranslation(person.gender), birthdate: ISOToDate(person.birthdate?.datetime)}) }}
|
||||
</span>
|
||||
<span v-if="options.addAge && person.birthdate" class="age">
|
||||
({{ trans(RENDERBOX_YEARS_OLD, {n: person.age}) }})
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<span
|
||||
v-if="person.deathdate"
|
||||
>
|
||||
{{ trans(RENDERBOX_DEATHDATE_STATEMENT, {gender: toGenderTranslation(person.gender), deathdate: ISOToDate(person.deathdate?.datetime)}) }}
|
||||
</span>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -130,11 +75,6 @@
|
||||
<a
|
||||
v-if="options.addHouseholdLink === true"
|
||||
:href="getCurrentHouseholdUrl"
|
||||
:title="
|
||||
trans(PERSONS_ASSOCIATED_SHOW_HOUSEHOLD_NUMBER, {
|
||||
id: person.current_household_id,
|
||||
})
|
||||
"
|
||||
>
|
||||
<span class="badge rounded-pill bg-chill-beige">
|
||||
<i
|
||||
@@ -180,6 +120,7 @@
|
||||
:person="addr.hostPerson"
|
||||
/>
|
||||
</span>
|
||||
|
||||
<address-render-box
|
||||
v-if="addr.hostPerson.address"
|
||||
:address="addr.hostPerson.address"
|
||||
@@ -299,7 +240,7 @@
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
import {computed} from "vue";
|
||||
import {ISOToDate} from "ChillMainAssets/chill/js/date";
|
||||
import AddressRenderBox from "ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue";
|
||||
@@ -311,108 +252,69 @@ import {
|
||||
trans,
|
||||
RENDERBOX_HOLDER,
|
||||
RENDERBOX_NO_DATA,
|
||||
RENDERBOX_DEATHDATE,
|
||||
RENDERBOX_DEATHDATE_STATEMENT,
|
||||
RENDERBOX_HOUSEHOLD_WITHOUT_ADDRESS,
|
||||
RENDERBOX_RESIDENTIAL_ADDRESS,
|
||||
RENDERBOX_LOCATED_AT,
|
||||
RENDERBOX_BIRTHDAY_MAN,
|
||||
RENDERBOX_BIRTHDAY_WOMAN,
|
||||
RENDERBOX_BIRTHDAY_UNKNOWN,
|
||||
RENDERBOX_BIRTHDAY_NEUTRAL,
|
||||
PERSONS_ASSOCIATED_SHOW_HOUSEHOLD_NUMBER,
|
||||
RENDERBOX_BIRTHDAY_STATEMENT,
|
||||
// PERSONS_ASSOCIATED_SHOW_HOUSEHOLD_NUMBER,
|
||||
RENDERBOX_YEARS_OLD,
|
||||
} from "translator";
|
||||
import {Person} from "ChillPersonAssets/types";
|
||||
import {toGenderTranslation} from "ChillMainAssets/lib/api/genderHelper";
|
||||
|
||||
const props = defineProps({
|
||||
person: {
|
||||
required: true,
|
||||
},
|
||||
options: {
|
||||
type: Object,
|
||||
required: false,
|
||||
},
|
||||
render: {
|
||||
type: String,
|
||||
},
|
||||
returnPath: {
|
||||
type: String,
|
||||
},
|
||||
showResidentialAddresses: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const birthdateTranslation = computed(() => {
|
||||
if (props.person.gender) {
|
||||
const { genderTranslation } = props.person.gender;
|
||||
switch (genderTranslation) {
|
||||
case "man":
|
||||
return RENDERBOX_BIRTHDAY_MAN;
|
||||
case "woman":
|
||||
return RENDERBOX_BIRTHDAY_WOMAN;
|
||||
case "neutral":
|
||||
return RENDERBOX_BIRTHDAY_NEUTRAL;
|
||||
case "unknown":
|
||||
return RENDERBOX_BIRTHDAY_UNKNOWN;
|
||||
default:
|
||||
return RENDERBOX_BIRTHDAY_UNKNOWN;
|
||||
interface RenderOptions {
|
||||
addInfo?: boolean;
|
||||
addEntity?: boolean;
|
||||
addAltNames?: boolean;
|
||||
addAge?: boolean;
|
||||
addId?: boolean;
|
||||
addLink?: boolean;
|
||||
hLevel?: number;
|
||||
entityDisplayLong?: boolean;
|
||||
addCenter?: boolean;
|
||||
addNoData?: boolean;
|
||||
isMultiline?: boolean;
|
||||
isHolder?: boolean;
|
||||
addHouseholdLink?: boolean;
|
||||
}
|
||||
} else {
|
||||
return RENDERBOX_BIRTHDAY_UNKNOWN;
|
||||
|
||||
interface Props {
|
||||
person: Person;
|
||||
options?: RenderOptions;
|
||||
render?: "bloc" | "badge";
|
||||
returnPath?: string;
|
||||
showResidentialAddresses?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
render: "bloc", options: {
|
||||
addInfo: true,
|
||||
addEntity: false,
|
||||
addAltNames: true,
|
||||
addAge: true,
|
||||
addId: true,
|
||||
addLink: false,
|
||||
hLevel: 3,
|
||||
entityDisplayingLong: true,
|
||||
addCenter: true,
|
||||
addNoData: true,
|
||||
isMultiline: true,
|
||||
isHolder: false,
|
||||
addHouseholdLink: true
|
||||
}
|
||||
});
|
||||
|
||||
const isMultiline = computed(() => {
|
||||
const isMultiline = computed<boolean>(() => {
|
||||
return props.options?.isMultiline || false;
|
||||
});
|
||||
|
||||
const birthdate = computed(() => {
|
||||
if (
|
||||
props.person.birthdate !== null &&
|
||||
props.person.birthdate !== undefined &&
|
||||
props.person.birthdate.datetime
|
||||
) {
|
||||
return ISOToDate(props.person.birthdate.datetime);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
});
|
||||
|
||||
const deathdate = computed(() => {
|
||||
if (
|
||||
props.person.deathdate !== null &&
|
||||
props.person.deathdate !== undefined &&
|
||||
props.person.deathdate.datetime
|
||||
) {
|
||||
return new Date(props.person.deathdate.datetime);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
});
|
||||
|
||||
const altNameLabel = computed(() => {
|
||||
let altNameLabel = "";
|
||||
(props.person.altNames || []).forEach(
|
||||
(altName) => (altNameLabel += altName.label),
|
||||
);
|
||||
return altNameLabel;
|
||||
});
|
||||
|
||||
const altNameKey = computed(() => {
|
||||
let altNameKey = "";
|
||||
(props.person.altNames || []).forEach(
|
||||
(altName) => (altNameKey += altName.key),
|
||||
);
|
||||
return altNameKey;
|
||||
});
|
||||
|
||||
const getUrl = computed(() => {
|
||||
const getUrl = computed<string>(() => {
|
||||
return `/fr/person/${props.person.id}/general`;
|
||||
});
|
||||
|
||||
const getCurrentHouseholdUrl = computed(() => {
|
||||
let returnPath = props.returnPath ? `?returnPath=${props.returnPath}` : ``;
|
||||
const getCurrentHouseholdUrl = computed<string>(() => {
|
||||
const returnPath = props.returnPath ? `?returnPath=${props.returnPath}` : ``;
|
||||
return `/fr/person/household/${props.person.current_household_id}/summary${returnPath}`;
|
||||
});
|
||||
</script>
|
||||
|
@@ -1,13 +1,7 @@
|
||||
<template>
|
||||
<span v-if="isCut">{{ cutText }}</span>
|
||||
<span v-else class="person-text">
|
||||
<span class="firstname">{{ person.firstName }}</span>
|
||||
<span class="lastname"> {{ person.lastName }}</span>
|
||||
<span v-if="person.altNames && person.altNames.length > 0" class="altnames">
|
||||
<span :class="'altname altname-' + altNameKey"
|
||||
> ({{ altNameLabel }})</span
|
||||
>
|
||||
</span>
|
||||
<span>{{ person.text }}</span>
|
||||
<span v-if="person.suffixText" class="suffixtext"
|
||||
> {{ person.suffixText }}</span
|
||||
>
|
||||
@@ -33,16 +27,6 @@ const props = defineProps<{
|
||||
|
||||
const { person, isCut = false, addAge = true } = toRefs(props);
|
||||
|
||||
const altNameLabel = computed(() => {
|
||||
if (!person.value.altNames) return "";
|
||||
return person.value.altNames.map((a: AltName) => a.labels).join("");
|
||||
});
|
||||
|
||||
const altNameKey = computed(() => {
|
||||
if (!person.value.altNames) return "";
|
||||
return person.value.altNames.map((a: AltName) => a.key).join("");
|
||||
});
|
||||
|
||||
const cutText = computed(() => {
|
||||
if (!person.value.text) return "";
|
||||
const more = person.value.text.length > 15 ? "…" : "";
|
||||
|
@@ -265,3 +265,38 @@ add_persons:
|
||||
title: "Centre"
|
||||
|
||||
error_only_one_person: "Une seule personne peut être sélectionnée !"
|
||||
|
||||
renderbox:
|
||||
person: "Usager"
|
||||
birthday_statement: >-
|
||||
{gender, select,
|
||||
man {Né le {birthdate, date}}
|
||||
woman {Née le {birthdate, date}}
|
||||
other {Né·e le {birthdate, date}}
|
||||
}
|
||||
deathdate_statement: >-
|
||||
{gender, select,
|
||||
man {Décédé le {deathdate, date}}
|
||||
woman {Décédée le {deathdate, date}}
|
||||
other {Décédé·e le {deathdate, date}}
|
||||
}
|
||||
household_without_address: "Le ménage de l'usager est sans adresse"
|
||||
no_data: "Aucune information renseignée"
|
||||
type:
|
||||
thirdparty: "Tiers"
|
||||
person: "Usager"
|
||||
holder: "Titulaire"
|
||||
years_old: >-
|
||||
{n, plural,
|
||||
=0 {0 an}
|
||||
one {1 an}
|
||||
other {# ans}
|
||||
}
|
||||
residential_address: "Adresse de résidence"
|
||||
located_at: "réside chez"
|
||||
household_number: "Ménage n°{number}"
|
||||
current_members: "Membres actuels"
|
||||
no_current_address: "Sans adresse actuellement"
|
||||
new_household: "Nouveau ménage"
|
||||
no_members_yet: "Aucun membre actuellement"
|
||||
|
||||
|
Reference in New Issue
Block a user