mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-26 08:35:00 +00:00
Refactor person creation workflow: Introduce PersonEdit
component and integrate it across Create
, Person.vue
, and modals for improved modularity. Update type definitions and API methods for consistency.
This commit is contained in:
@@ -1,15 +1,35 @@
|
|||||||
import {GenericDoc} from "ChillDocStoreAssets/types/generic_doc";
|
import { GenericDoc } from "ChillDocStoreAssets/types/generic_doc";
|
||||||
import {StoredObject, StoredObjectStatus} from "ChillDocStoreAssets/types";
|
import { StoredObject, StoredObjectStatus } from "ChillDocStoreAssets/types";
|
||||||
import {CreatableEntityType} from "ChillPersonAssets/types";
|
import { CreatableEntityType } from "ChillPersonAssets/types";
|
||||||
|
|
||||||
export interface DateTime {
|
export interface DateTime {
|
||||||
datetime: string;
|
datetime: string;
|
||||||
datetime8601: string;
|
datetime8601: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A date representation to use when we create an instance
|
||||||
|
*/
|
||||||
|
export interface DateTimeCreate {
|
||||||
|
/**
|
||||||
|
* Must be a string in format Y-m-d\TH:i:sO
|
||||||
|
*/
|
||||||
|
datetime: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Civility {
|
export interface Civility {
|
||||||
|
type: "chill_main_civility";
|
||||||
id: number;
|
id: number;
|
||||||
// TODO
|
abbreviation: TranslatableString;
|
||||||
|
active: boolean;
|
||||||
|
name: TranslatableString;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Gender {
|
||||||
|
type: "chill_main_gender";
|
||||||
|
id: number;
|
||||||
|
label: string;
|
||||||
|
genderTranslation: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Household {
|
export interface Household {
|
||||||
@@ -306,7 +326,7 @@ export interface TabDefinition {
|
|||||||
* Configuration for the CreateModal and Create component
|
* Configuration for the CreateModal and Create component
|
||||||
*/
|
*/
|
||||||
export interface CreateComponentConfig {
|
export interface CreateComponentConfig {
|
||||||
action?: string;
|
action?: string;
|
||||||
allowedTypes: CreatableEntityType[];
|
allowedTypes: CreatableEntityType[];
|
||||||
query?: string;
|
query?: string;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<ul class="nav nav-tabs">
|
<ul class="nav nav-tabs">
|
||||||
<li v-if="allowedTypes.includes('person')" class="nav-item">
|
<li v-if="containsPerson" class="nav-item">
|
||||||
<a class="nav-link" :class="{ active: isActive('person') }">
|
<a class="nav-link" :class="{ active: isActive('person') }">
|
||||||
<label for="person">
|
<label for="person">
|
||||||
<input
|
<input
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="allowedTypes.includes('thirdparty')" class="nav-item">
|
<li v-if="containsThirdParty" class="nav-item">
|
||||||
<a class="nav-link" :class="{ active: isActive('thirdparty') }">
|
<a class="nav-link" :class="{ active: isActive('thirdparty') }">
|
||||||
<label for="thirdparty">
|
<label for="thirdparty">
|
||||||
<input
|
<input
|
||||||
@@ -31,9 +31,9 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="my-4">
|
<div class="my-4">
|
||||||
<on-the-fly-person
|
<PersonEdit
|
||||||
v-if="type === 'person'"
|
v-if="type === 'person'"
|
||||||
:action="action"
|
action="create"
|
||||||
:query="query"
|
:query="query"
|
||||||
ref="castPerson"
|
ref="castPerson"
|
||||||
/>
|
/>
|
||||||
@@ -47,17 +47,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed, onMounted, ref} from "vue";
|
import { computed, onMounted, ref } from "vue";
|
||||||
import OnTheFlyPerson from "ChillPersonAssets/vuejs/_components/OnTheFly/Person.vue";
|
import OnTheFlyPerson from "ChillPersonAssets/vuejs/_components/OnTheFly/Person.vue";
|
||||||
import OnTheFlyThirdparty from "ChillThirdPartyAssets/vuejs/_components/OnTheFly/ThirdParty.vue";
|
import OnTheFlyThirdparty from "ChillThirdPartyAssets/vuejs/_components/OnTheFly/ThirdParty.vue";
|
||||||
import {ONTHEFLY_CREATE_PERSON, ONTHEFLY_CREATE_THIRDPARTY, trans,} from "translator";
|
import {
|
||||||
import {CreatableEntityType} from "ChillPersonAssets/types";
|
ONTHEFLY_CREATE_PERSON,
|
||||||
import {CreateComponentConfig} from "ChillMainAssets/types";
|
ONTHEFLY_CREATE_THIRDPARTY,
|
||||||
|
trans,
|
||||||
|
} from "translator";
|
||||||
|
import { CreatableEntityType } from "ChillPersonAssets/types";
|
||||||
|
import { CreateComponentConfig } from "ChillMainAssets/types";
|
||||||
|
import PersonEdit from "ChillPersonAssets/vuejs/_components/OnTheFly/PersonEdit.vue";
|
||||||
|
|
||||||
const props = defineProps<CreateComponentConfig>();
|
const props = withDefaults(defineProps<CreateComponentConfig>(), {
|
||||||
const type = ref<CreatableEntityType| null>(null);
|
allowedTypes: ["person", "thirdparty"],
|
||||||
|
action: "create",
|
||||||
|
query: "",
|
||||||
|
});
|
||||||
|
const type = ref<CreatableEntityType | null>(null);
|
||||||
|
|
||||||
const radioType = computed<CreatableEntityType| null>({
|
const radioType = computed<CreatableEntityType | null>({
|
||||||
get: () => type.value,
|
get: () => type.value,
|
||||||
set: (val: CreatableEntityType | null) => {
|
set: (val: CreatableEntityType | null) => {
|
||||||
type.value = val;
|
type.value = val;
|
||||||
@@ -65,7 +74,10 @@ const radioType = computed<CreatableEntityType| null>({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
type AnyComponentInstance = InstanceType<typeof OnTheFlyPerson> | InstanceType<typeof OnTheFlyThirdparty> | null;
|
type AnyComponentInstance =
|
||||||
|
| InstanceType<typeof OnTheFlyPerson>
|
||||||
|
| InstanceType<typeof OnTheFlyThirdparty>
|
||||||
|
| null;
|
||||||
|
|
||||||
const castPerson = ref<AnyComponentInstance>(null);
|
const castPerson = ref<AnyComponentInstance>(null);
|
||||||
const castThirdparty = ref<AnyComponentInstance>(null);
|
const castThirdparty = ref<AnyComponentInstance>(null);
|
||||||
@@ -81,6 +93,14 @@ function isActive(tab: CreatableEntityType) {
|
|||||||
return type.value === tab;
|
return type.value === tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const containsThirdParty = computed<boolean>(() =>
|
||||||
|
props.allowedTypes.includes("thirdparty"),
|
||||||
|
);
|
||||||
|
const containsPerson = computed<boolean>(() => {
|
||||||
|
console.log(props.allowedTypes);
|
||||||
|
return props.allowedTypes.includes("person");
|
||||||
|
});
|
||||||
|
|
||||||
// Types for data structures coming from child components are not declared in TS yet.
|
// Types for data structures coming from child components are not declared in TS yet.
|
||||||
// We conservatively type them as any to preserve runtime behavior while enabling TS in this component.
|
// We conservatively type them as any to preserve runtime behavior while enabling TS in this component.
|
||||||
function castDataByType(): any {
|
function castDataByType(): any {
|
||||||
|
@@ -1,9 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
|
import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
|
||||||
import Create from "ChillMainAssets/vuejs/OnTheFly/components/Create.vue";
|
import Create from "ChillMainAssets/vuejs/OnTheFly/components/Create.vue";
|
||||||
import {CreateComponentConfig} from "ChillMainAssets/types";
|
import { CreateComponentConfig } from "ChillMainAssets/types";
|
||||||
|
|
||||||
|
const emit = defineEmits<(e: "close") => void>();
|
||||||
|
|
||||||
const props = defineProps<CreateComponentConfig>();
|
const props = defineProps<CreateComponentConfig>();
|
||||||
|
const modalDialogClass = { "modal-xl": true, "modal-scrollable": true };
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -18,15 +21,15 @@ const props = defineProps<CreateComponentConfig>();
|
|||||||
</template>
|
</template>
|
||||||
<template #body-head>
|
<template #body-head>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<Create :allowed-types="props.allowed-types" :action="props.action" :query="props.query"></Create>
|
<Create
|
||||||
|
:allowedTypes="props.allowedTypes"
|
||||||
|
:action="props.action"
|
||||||
|
:query="props.query"
|
||||||
|
></Create>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
</modal>
|
||||||
</modal>
|
</teleport>
|
||||||
</teleport>
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss"></style>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
@@ -76,7 +76,8 @@ import {
|
|||||||
Entities,
|
Entities,
|
||||||
EntitiesOrMe,
|
EntitiesOrMe,
|
||||||
EntityType,
|
EntityType,
|
||||||
SearchOptions, Suggestion,
|
SearchOptions,
|
||||||
|
Suggestion,
|
||||||
} from "ChillPersonAssets/types";
|
} from "ChillPersonAssets/types";
|
||||||
import {
|
import {
|
||||||
PICK_ENTITY_MODAL_TITLE,
|
PICK_ENTITY_MODAL_TITLE,
|
||||||
@@ -183,7 +184,7 @@ function addNewSuggested(entity: EntitiesOrMe) {
|
|||||||
emits("addNewEntity", { entity });
|
emits("addNewEntity", { entity });
|
||||||
}
|
}
|
||||||
|
|
||||||
function addNewEntity({ selected }: { selected: Suggestion[]}) {
|
function addNewEntity({ selected }: { selected: Suggestion[] }) {
|
||||||
Object.values(selected).forEach((item) => {
|
Object.values(selected).forEach((item) => {
|
||||||
emits("addNewEntity", { entity: item.result });
|
emits("addNewEntity", { entity: item.result });
|
||||||
});
|
});
|
||||||
|
@@ -52,23 +52,15 @@ import { trans, MODAL_ACTION_CLOSE } from "translator";
|
|||||||
import { defineProps } from "vue";
|
import { defineProps } from "vue";
|
||||||
|
|
||||||
export interface ModalProps {
|
export interface ModalProps {
|
||||||
modalDialogClass: string;
|
modalDialogClass?: string | Record<string, boolean>;
|
||||||
hideFooter: boolean;
|
hideFooter?: boolean;
|
||||||
|
show?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
defineProps({
|
const props = withDefaults(defineProps<ModalProps>(), {
|
||||||
modalDialogClass: {
|
modalDialogClass: "",
|
||||||
type: String,
|
hideFooter: false,
|
||||||
default: "",
|
show: true,
|
||||||
},
|
|
||||||
hideFooter: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
show: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const emits = defineEmits<{
|
const emits = defineEmits<{
|
||||||
|
@@ -10,6 +10,7 @@ import {
|
|||||||
Scope,
|
Scope,
|
||||||
Job,
|
Job,
|
||||||
PrivateCommentEmbeddable,
|
PrivateCommentEmbeddable,
|
||||||
|
TranslatableString,
|
||||||
} from "ChillMainAssets/types";
|
} from "ChillMainAssets/types";
|
||||||
import { StoredObject } from "ChillDocStoreAssets/types";
|
import { StoredObject } from "ChillDocStoreAssets/types";
|
||||||
import { Thirdparty } from "../../../ChillThirdPartyBundle/Resources/public/types";
|
import { Thirdparty } from "../../../ChillThirdPartyBundle/Resources/public/types";
|
||||||
@@ -17,7 +18,7 @@ import { Calendar } from "../../../ChillCalendarBundle/Resources/public/types";
|
|||||||
import Person from "./vuejs/_components/OnTheFly/Person.vue";
|
import Person from "./vuejs/_components/OnTheFly/Person.vue";
|
||||||
|
|
||||||
export interface AltName {
|
export interface AltName {
|
||||||
label: string;
|
label: TranslatableString;
|
||||||
key: string;
|
key: string;
|
||||||
}
|
}
|
||||||
export interface Person {
|
export interface Person {
|
||||||
@@ -331,15 +332,13 @@ export interface AccompanyingPeriodWorkEvaluationDocument {
|
|||||||
/**
|
/**
|
||||||
* Entity types that a user can create
|
* Entity types that a user can create
|
||||||
*/
|
*/
|
||||||
export type CreatableEntityType =
|
export type CreatableEntityType = "person" | "thirdparty";
|
||||||
| "person"
|
|
||||||
| "thirdparty";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entities that can be search and selected by a user
|
* Entities that can be search and selected by a user
|
||||||
*/
|
*/
|
||||||
export type EntityType = CreatableEntityType
|
export type EntityType =
|
||||||
|
| CreatableEntityType
|
||||||
| "user_group"
|
| "user_group"
|
||||||
| "user"
|
| "user"
|
||||||
| "household";
|
| "household";
|
||||||
|
@@ -1,88 +0,0 @@
|
|||||||
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
|
||||||
|
|
||||||
/*
|
|
||||||
* GET a person by id
|
|
||||||
*/
|
|
||||||
const getPerson = (id) => {
|
|
||||||
const url = `/api/1.0/person/person/${id}.json`;
|
|
||||||
return fetch(url).then((response) => {
|
|
||||||
if (response.ok) {
|
|
||||||
return response.json();
|
|
||||||
}
|
|
||||||
throw Error("Error with request resource response");
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const getPersonAltNames = () =>
|
|
||||||
fetch("/api/1.0/person/config/alt_names.json").then((response) => {
|
|
||||||
if (response.ok) {
|
|
||||||
return response.json();
|
|
||||||
}
|
|
||||||
throw Error("Error with request resource response");
|
|
||||||
});
|
|
||||||
|
|
||||||
const getCivilities = () =>
|
|
||||||
fetch("/api/1.0/main/civility.json").then((response) => {
|
|
||||||
if (response.ok) {
|
|
||||||
return response.json();
|
|
||||||
}
|
|
||||||
throw Error("Error with request resource response");
|
|
||||||
});
|
|
||||||
|
|
||||||
const getGenders = () => makeFetch("GET", "/api/1.0/main/gender.json");
|
|
||||||
// .then(response => {
|
|
||||||
// console.log(response)
|
|
||||||
// if (response.ok) { return response.json(); }
|
|
||||||
// throw Error('Error with request resource response');
|
|
||||||
// });
|
|
||||||
|
|
||||||
const getCentersForPersonCreation = () =>
|
|
||||||
makeFetch("GET", "/api/1.0/person/creation/authorized-centers", null);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* POST a new person
|
|
||||||
*/
|
|
||||||
const postPerson = (body) => {
|
|
||||||
const url = `/api/1.0/person/person.json`;
|
|
||||||
return fetch(url, {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json;charset=utf-8",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
}).then((response) => {
|
|
||||||
if (response.ok) {
|
|
||||||
return response.json();
|
|
||||||
}
|
|
||||||
throw Error("Error with request resource response");
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PATCH an existing person
|
|
||||||
*/
|
|
||||||
const patchPerson = (id, body) => {
|
|
||||||
const url = `/api/1.0/person/person/${id}.json`;
|
|
||||||
return fetch(url, {
|
|
||||||
method: "PATCH",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json;charset=utf-8",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
}).then((response) => {
|
|
||||||
if (response.ok) {
|
|
||||||
return response.json();
|
|
||||||
}
|
|
||||||
throw Error("Error with request resource response");
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export {
|
|
||||||
getCentersForPersonCreation,
|
|
||||||
getPerson,
|
|
||||||
getPersonAltNames,
|
|
||||||
getCivilities,
|
|
||||||
getGenders,
|
|
||||||
postPerson,
|
|
||||||
patchPerson,
|
|
||||||
};
|
|
@@ -0,0 +1,33 @@
|
|||||||
|
import { fetchResults, makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
||||||
|
import { Center, Civility, Gender } from "ChillMainAssets/types";
|
||||||
|
import { AltName, Person } from "ChillPersonAssets/types";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GET a person by id
|
||||||
|
*/
|
||||||
|
export const getPerson = async (id: number): Promise<Person> => {
|
||||||
|
const url = `/api/1.0/person/person/${id}.json`;
|
||||||
|
return fetch(url).then((response) => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
throw Error("Error with request resource response");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getPersonAltNames = async (): Promise<AltName[]> =>
|
||||||
|
fetch("/api/1.0/person/config/alt_names.json").then((response) => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
throw Error("Error with request resource response");
|
||||||
|
});
|
||||||
|
|
||||||
|
export const getCivilities = async (): Promise<Civility[]> =>
|
||||||
|
fetchResults("/api/1.0/main/civility.json");
|
||||||
|
|
||||||
|
export const getGenders = async (): Promise<Gender[]> =>
|
||||||
|
fetchResults("/api/1.0/main/gender.json");
|
||||||
|
|
||||||
|
export const getCentersForPersonCreation = async (): Promise<Center[]> =>
|
||||||
|
makeFetch("GET", "/api/1.0/person/creation/authorized-centers", null);
|
@@ -3,7 +3,7 @@
|
|||||||
class="btn"
|
class="btn"
|
||||||
:class="getClassButton"
|
:class="getClassButton"
|
||||||
:title="buttonTitle"
|
:title="buttonTitle"
|
||||||
@click="openModal"
|
@click="openModalChoose"
|
||||||
>
|
>
|
||||||
<span v-if="displayTextButton">{{ buttonTitle }}</span>
|
<span v-if="displayTextButton">{{ buttonTitle }}</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -16,22 +16,28 @@
|
|||||||
:selected="selected"
|
:selected="selected"
|
||||||
:modal-dialog-class="'modal-dialog-scrollable modal-xl'"
|
:modal-dialog-class="'modal-dialog-scrollable modal-xl'"
|
||||||
:allow-create="props.allowCreate"
|
:allow-create="props.allowCreate"
|
||||||
@close="closeModal"
|
@close="closeModalChoose"
|
||||||
@addNewPersons="payload => emit('addNewPersons', payload)"
|
@addNewPersons="(payload) => emit('addNewPersons', payload)"
|
||||||
@onAskForCreate="onAskForCreate"
|
@onAskForCreate="onAskForCreate"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<CreateModal
|
<CreateModal
|
||||||
v-if="creatableEntityTypes.length > 0 && showModalCreate"
|
v-if="creatableEntityTypes.length > 0 && showModalCreate"
|
||||||
:allowed-types="creatableEntityTypes"
|
:allowed-types="creatableEntityTypes"
|
||||||
></CreateModal>
|
@close="closeModalCreate"
|
||||||
|
></CreateModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from "vue";
|
||||||
import PersonChooseModal from './AddPersons/PersonChooseModal.vue';
|
import PersonChooseModal from "./AddPersons/PersonChooseModal.vue";
|
||||||
import type {Suggestion, SearchOptions, CreatableEntityType, EntityType} from 'ChillPersonAssets/types';
|
import type {
|
||||||
import {marked} from "marked";
|
Suggestion,
|
||||||
|
SearchOptions,
|
||||||
|
CreatableEntityType,
|
||||||
|
EntityType,
|
||||||
|
} from "ChillPersonAssets/types";
|
||||||
|
import { marked } from "marked";
|
||||||
import options = marked.options;
|
import options = marked.options;
|
||||||
import CreateModal from "ChillMainAssets/vuejs/OnTheFly/components/CreateModal.vue";
|
import CreateModal from "ChillMainAssets/vuejs/OnTheFly/components/CreateModal.vue";
|
||||||
|
|
||||||
@@ -42,7 +48,7 @@ interface AddPersonsConfig {
|
|||||||
modalTitle: string;
|
modalTitle: string;
|
||||||
options: SearchOptions;
|
options: SearchOptions;
|
||||||
allowCreate?: boolean;
|
allowCreate?: boolean;
|
||||||
types?: EntityType|undefined;
|
types?: EntityType | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<AddPersonsConfig>(), {
|
const props = withDefaults(defineProps<AddPersonsConfig>(), {
|
||||||
@@ -52,43 +58,54 @@ const props = withDefaults(defineProps<AddPersonsConfig>(), {
|
|||||||
types: () => undefined,
|
types: () => undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit =
|
||||||
(e: 'addNewPersons', payload: { selected: Suggestion[] }): void;
|
defineEmits<
|
||||||
}>();
|
(e: "addNewPersons", payload: { selected: Suggestion[] }) => void
|
||||||
|
>();
|
||||||
|
|
||||||
const showModalChoose = ref(false);
|
const showModalChoose = ref(false);
|
||||||
const showModalCreate = ref(false);
|
const showModalCreate = ref(false);
|
||||||
|
|
||||||
const getClassButton = computed(() => {
|
const getClassButton = computed(() => {
|
||||||
const size = props.options?.button?.size ?? '';
|
const size = props.options?.button?.size ?? "";
|
||||||
const type = props.options?.button?.type ?? 'btn-create';
|
const type = props.options?.button?.type ?? "btn-create";
|
||||||
return size ? `${size} ${type}` : type;
|
return size ? `${size} ${type}` : type;
|
||||||
});
|
});
|
||||||
|
|
||||||
const displayTextButton = computed(() =>
|
const displayTextButton = computed(() =>
|
||||||
props.options?.button?.display !== undefined ? props.options.button.display : true,
|
props.options?.button?.display !== undefined
|
||||||
|
? props.options.button.display
|
||||||
|
: true,
|
||||||
);
|
);
|
||||||
|
|
||||||
const creatableEntityTypes = computed<CreatableEntityType[]>(() => {
|
const creatableEntityTypes = computed<CreatableEntityType[]>(() => {
|
||||||
if (typeof props.options.type !== 'undefined') {
|
if (typeof props.options.type !== "undefined") {
|
||||||
return props.options.type.filter((e: EntityType) => e === 'thirdparty' || e === 'person');
|
return props.options.type.filter(
|
||||||
|
(e: EntityType) => e === "thirdparty" || e === "person",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return props.type.filter((e: EntityType) => e === 'thirdparty' || e === 'person');
|
return props.types.filter(
|
||||||
})
|
(e: EntityType) => e === "thirdparty" || e === "person",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
function onAskForCreate({query}: {query: string}) {
|
function onAskForCreate({ query }: { query: string }) {
|
||||||
console.log('onAskForCreate', query);
|
console.log("onAskForCreate", query);
|
||||||
showModalChoose.value = false;
|
showModalChoose.value = false;
|
||||||
showModalCreate.value = true;
|
showModalCreate.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function openModal() {
|
function openModalChoose() {
|
||||||
showModalChoose.value = true;
|
showModalChoose.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeModal() {
|
function closeModalChoose() {
|
||||||
showModalChoose.value = false;
|
showModalChoose.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function closeModalCreate() {
|
||||||
|
showModalCreate.value = false;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@@ -14,7 +14,9 @@
|
|||||||
<div class="search">
|
<div class="search">
|
||||||
<label class="col-form-label" style="float: right">
|
<label class="col-form-label" style="float: right">
|
||||||
{{
|
{{
|
||||||
trans(ADD_PERSONS_SUGGESTED_COUNTER, { count: suggestedCounter })
|
trans(ADD_PERSONS_SUGGESTED_COUNTER, {
|
||||||
|
count: suggestedCounter,
|
||||||
|
})
|
||||||
}}
|
}}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
@@ -26,7 +28,11 @@
|
|||||||
ref="searchRef"
|
ref="searchRef"
|
||||||
/>
|
/>
|
||||||
<i class="fa fa-search fa-lg" />
|
<i class="fa fa-search fa-lg" />
|
||||||
<i class="fa fa-times" v-if="queryLength >= 3" @click="resetSuggestion" />
|
<i
|
||||||
|
class="fa fa-times"
|
||||||
|
v-if="queryLength >= 3"
|
||||||
|
@click="resetSuggestion"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -42,7 +48,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
<span v-if="selectedCounter > 0">
|
<span v-if="selectedCounter > 0">
|
||||||
{{ trans(ADD_PERSONS_SELECTED_COUNTER, { count: selectedCounter }) }}
|
{{
|
||||||
|
trans(ADD_PERSONS_SELECTED_COUNTER, { count: selectedCounter })
|
||||||
|
}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -60,11 +68,11 @@
|
|||||||
@update-selected="updateSelected"
|
@update-selected="updateSelected"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div v-if="props.allowCreate && query.length > 0" class="create-button">
|
<div
|
||||||
<button
|
v-if="props.allowCreate && query.length > 0"
|
||||||
type="button"
|
class="create-button"
|
||||||
@click="emit('onAskForCreate', {query })"
|
>
|
||||||
>
|
<button type="button" @click="emit('onAskForCreate', { query })">
|
||||||
{{ trans(ONTHEFLY_CREATE_BUTTON, { q: query }) }}
|
{{ trans(ONTHEFLY_CREATE_BUTTON, { q: query }) }}
|
||||||
</button>
|
</button>
|
||||||
<!--
|
<!--
|
||||||
@@ -100,12 +108,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, reactive, computed, nextTick, watch, onMounted} from 'vue';
|
import { ref, reactive, computed, nextTick, watch, onMounted } from "vue";
|
||||||
import Modal from 'ChillMainAssets/vuejs/_components/Modal.vue';
|
import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
|
||||||
import PersonSuggestion from './PersonSuggestion.vue';
|
import PersonSuggestion from "./PersonSuggestion.vue";
|
||||||
import OnTheFly from 'ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue';
|
import OnTheFly from "ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue";
|
||||||
import { searchEntities } from 'ChillPersonAssets/vuejs/_api/AddPersons';
|
import { searchEntities } from "ChillPersonAssets/vuejs/_api/AddPersons";
|
||||||
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods';
|
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
trans,
|
trans,
|
||||||
@@ -116,14 +124,15 @@ import {
|
|||||||
ACTION_CHECK_ALL,
|
ACTION_CHECK_ALL,
|
||||||
ACTION_RESET,
|
ACTION_RESET,
|
||||||
ACTION_ADD,
|
ACTION_ADD,
|
||||||
} from 'translator';
|
} from "translator";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
Suggestion,
|
Suggestion,
|
||||||
Search,
|
Search,
|
||||||
AddPersonResult as OriginalResult,
|
AddPersonResult as OriginalResult,
|
||||||
SearchOptions, EntitiesOrMe,
|
SearchOptions,
|
||||||
} from 'ChillPersonAssets/types';
|
EntitiesOrMe,
|
||||||
|
} from "ChillPersonAssets/types";
|
||||||
|
|
||||||
type Result = OriginalResult & { addressId?: number };
|
type Result = OriginalResult & { addressId?: number };
|
||||||
|
|
||||||
@@ -139,16 +148,16 @@ interface Props {
|
|||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
suggested: () => [],
|
suggested: () => [],
|
||||||
selected: () => [],
|
selected: () => [],
|
||||||
modalDialogClass: 'modal-dialog-scrollable modal-xl',
|
modalDialogClass: "modal-dialog-scrollable modal-xl",
|
||||||
allowCreate: () => true,
|
allowCreate: () => true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'close'): void;
|
(e: "close"): void;
|
||||||
/** @deprecated use 'onPickEntities' */
|
/** @deprecated use 'onPickEntities' */
|
||||||
(e: 'addNewPersons', payload: { selected: Suggestion[] }): void;
|
(e: "addNewPersons", payload: { selected: Suggestion[] }): void;
|
||||||
(e: 'onPickEntities', payload: { selected: EntitiesOrMe[] }): void;
|
(e: "onPickEntities", payload: { selected: EntitiesOrMe[] }): void;
|
||||||
(e: 'onAskForCreate', payload: { query: string }): void;
|
(e: "onAskForCreate", payload: { query: string }): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const searchRef = ref<HTMLInputElement | null>(null);
|
const searchRef = ref<HTMLInputElement | null>(null);
|
||||||
@@ -160,8 +169,8 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const search = reactive({
|
const search = reactive({
|
||||||
query: '' as string,
|
query: "" as string,
|
||||||
previousQuery: '' as string,
|
previousQuery: "" as string,
|
||||||
currentSearchQueryController: null as AbortController | null,
|
currentSearchQueryController: null as AbortController | null,
|
||||||
suggested: (props.suggested ?? []) as Suggestion[],
|
suggested: (props.suggested ?? []) as Suggestion[],
|
||||||
selected: (props.selected ?? []) as Suggestion[],
|
selected: (props.selected ?? []) as Suggestion[],
|
||||||
@@ -173,7 +182,7 @@ watch(
|
|||||||
(newSelected) => {
|
(newSelected) => {
|
||||||
search.selected = newSelected ? [...newSelected] : [];
|
search.selected = newSelected ? [...newSelected] : [];
|
||||||
},
|
},
|
||||||
{ deep: true }
|
{ deep: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
@@ -181,7 +190,7 @@ watch(
|
|||||||
(newSuggested) => {
|
(newSuggested) => {
|
||||||
search.suggested = newSuggested ? [...newSuggested] : [];
|
search.suggested = newSuggested ? [...newSuggested] : [];
|
||||||
},
|
},
|
||||||
{ deep: true }
|
{ deep: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
const query = computed({
|
const query = computed({
|
||||||
@@ -193,7 +202,9 @@ const suggestedCounter = computed(() => search.suggested.length);
|
|||||||
const selectedComputed = computed<Suggestion[]>(() => search.selected);
|
const selectedComputed = computed<Suggestion[]>(() => search.selected);
|
||||||
const selectedCounter = computed(() => search.selected.length);
|
const selectedCounter = computed(() => search.selected.length);
|
||||||
|
|
||||||
const checkUniq = computed(() => (props.options.uniq === true ? 'radio' : 'checkbox'));
|
const checkUniq = computed(() =>
|
||||||
|
props.options.uniq === true ? "radio" : "checkbox",
|
||||||
|
);
|
||||||
|
|
||||||
const priorSuggestion = computed(() => search.priorSuggestion);
|
const priorSuggestion = computed(() => search.priorSuggestion);
|
||||||
const hasPriorSuggestion = computed(() => !!search.priorSuggestion.key);
|
const hasPriorSuggestion = computed(() => !!search.priorSuggestion.key);
|
||||||
@@ -230,7 +241,7 @@ function setQuery(q: string) {
|
|||||||
search.currentSearchQueryController = null;
|
search.currentSearchQueryController = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (q === '') {
|
if (q === "") {
|
||||||
loadSuggestions([]);
|
loadSuggestions([]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -250,7 +261,7 @@ function setQuery(q: string) {
|
|||||||
loadSuggestions(suggested.results);
|
loadSuggestions(suggested.results);
|
||||||
})
|
})
|
||||||
.catch((error: DOMException) => {
|
.catch((error: DOMException) => {
|
||||||
if (error instanceof DOMException && error.name === 'AbortError') {
|
if (error instanceof DOMException && error.name === "AbortError") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
@@ -270,7 +281,7 @@ function updateSelected(value: Suggestion[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function resetSuggestion() {
|
function resetSuggestion() {
|
||||||
search.query = '';
|
search.query = "";
|
||||||
search.suggested = [];
|
search.suggested = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,10 +317,12 @@ function newPriorSuggestion(entity: Result | null) {
|
|||||||
* Triggered when the user clicks on the "add" button.
|
* Triggered when the user clicks on the "add" button.
|
||||||
*/
|
*/
|
||||||
function pickEntities(): void {
|
function pickEntities(): void {
|
||||||
emit('addNewPersons', { selected: search.selected });
|
emit("addNewPersons", { selected: search.selected });
|
||||||
emit('onPickEntities', {selected: search.selected.map((s: Suggestion) => s.result )})
|
emit("onPickEntities", {
|
||||||
search.query = '';
|
selected: search.selected.map((s: Suggestion) => s.result),
|
||||||
emit('close');
|
});
|
||||||
|
search.query = "";
|
||||||
|
emit("close");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="action === 'show'">
|
<div v-if="action === 'show' && person !== null">
|
||||||
<div class="flex-table">
|
<div class="flex-table">
|
||||||
<person-render-box
|
<person-render-box
|
||||||
render="bloc"
|
render="bloc"
|
||||||
@@ -22,445 +22,48 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="action === 'edit' || action === 'create'">
|
<div v-else-if="action === 'edit' || action === 'create'">
|
||||||
<div class="form-floating mb-3">
|
<PersonEdit
|
||||||
<input
|
:id="props.id"
|
||||||
class="form-control form-control-lg"
|
:type="props.type"
|
||||||
id="lastname"
|
:action="props.action"
|
||||||
v-model="lastName"
|
:query="props.query"
|
||||||
:placeholder="trans(PERSON_MESSAGES_PERSON_LASTNAME)"
|
/>
|
||||||
@change="checkErrors"
|
|
||||||
/>
|
|
||||||
<label for="lastname">{{ trans(PERSON_MESSAGES_PERSON_LASTNAME) }}</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="queryItems">
|
|
||||||
<ul class="list-suggest add-items inline">
|
|
||||||
<li
|
|
||||||
v-for="(qi, i) in queryItems"
|
|
||||||
:key="i"
|
|
||||||
@click="addQueryItem('lastName', qi)"
|
|
||||||
>
|
|
||||||
<span class="person-text">{{ qi }}</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input
|
|
||||||
class="form-control form-control-lg"
|
|
||||||
id="firstname"
|
|
||||||
v-model="firstName"
|
|
||||||
:placeholder="trans(PERSON_MESSAGES_PERSON_FIRSTNAME)"
|
|
||||||
@change="checkErrors"
|
|
||||||
/>
|
|
||||||
<label for="firstname">{{
|
|
||||||
trans(PERSON_MESSAGES_PERSON_FIRSTNAME)
|
|
||||||
}}</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="queryItems">
|
|
||||||
<ul class="list-suggest add-items inline">
|
|
||||||
<li
|
|
||||||
v-for="(qi, i) in queryItems"
|
|
||||||
:key="i"
|
|
||||||
@click="addQueryItem('firstName', qi)"
|
|
||||||
>
|
|
||||||
<span class="person-text">{{ qi }}</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-for="(a, i) in config.altNames"
|
|
||||||
:key="a.key"
|
|
||||||
class="form-floating mb-3"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
class="form-control form-control-lg"
|
|
||||||
:id="a.key"
|
|
||||||
:value="personAltNamesLabels[i]"
|
|
||||||
@input="onAltNameInput"
|
|
||||||
/>
|
|
||||||
<label :for="a.key">{{ localizeString(a.labels) }}</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- TODO fix placeholder if undefined
|
|
||||||
-->
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<select class="form-select form-select-lg" id="gender" v-model="gender">
|
|
||||||
<option selected disabled>
|
|
||||||
{{ trans(PERSON_MESSAGES_PERSON_GENDER_PLACEHOLDER) }}
|
|
||||||
</option>
|
|
||||||
<option v-for="g in config.genders" :value="g.id" :key="g.id">
|
|
||||||
{{ g.label }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<label>{{ trans(PERSON_MESSAGES_PERSON_GENDER_TITLE) }}</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="form-floating mb-3"
|
|
||||||
v-if="showCenters && config.centers.length > 1"
|
|
||||||
>
|
|
||||||
<select class="form-select form-select-lg" id="center" v-model="center">
|
|
||||||
<option selected disabled>
|
|
||||||
{{ trans(PERSON_MESSAGES_PERSON_CENTER_PLACEHOLDER) }}
|
|
||||||
</option>
|
|
||||||
<option v-for="c in config.centers" :value="c" :key="c.id">
|
|
||||||
{{ c.name }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<label>{{ trans(PERSON_MESSAGES_PERSON_CENTER_TITLE) }}</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<select
|
|
||||||
class="form-select form-select-lg"
|
|
||||||
id="civility"
|
|
||||||
v-model="civility"
|
|
||||||
>
|
|
||||||
<option selected disabled>
|
|
||||||
{{ trans(PERSON_MESSAGES_PERSON_CIVILITY_PLACEHOLDER) }}
|
|
||||||
</option>
|
|
||||||
<option v-for="c in config.civilities" :value="c.id" :key="c.id">
|
|
||||||
{{ localizeString(c.name) }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<label>{{ trans(PERSON_MESSAGES_PERSON_CIVILITY_TITLE) }}</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="input-group mb-3">
|
|
||||||
<span class="input-group-text" id="phonenumber">
|
|
||||||
<i class="fa fa-fw fa-phone"></i>
|
|
||||||
</span>
|
|
||||||
<input
|
|
||||||
class="form-control form-control-lg"
|
|
||||||
v-model="phonenumber"
|
|
||||||
:placeholder="trans(PERSON_MESSAGES_PERSON_PHONENUMBER)"
|
|
||||||
:aria-label="trans(PERSON_MESSAGES_PERSON_PHONENUMBER)"
|
|
||||||
aria-describedby="phonenumber"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="input-group mb-3">
|
|
||||||
<span class="input-group-text" id="mobilenumber">
|
|
||||||
<i class="fa fa-fw fa-mobile"></i>
|
|
||||||
</span>
|
|
||||||
<input
|
|
||||||
class="form-control form-control-lg"
|
|
||||||
v-model="mobilenumber"
|
|
||||||
:placeholder="trans(PERSON_MESSAGES_PERSON_MOBILENUMBER)"
|
|
||||||
:aria-label="trans(PERSON_MESSAGES_PERSON_MOBILENUMBER)"
|
|
||||||
aria-describedby="mobilenumber"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="input-group mb-3">
|
|
||||||
<span class="input-group-text" id="email">
|
|
||||||
<i class="fa fa-fw fa-at"></i>
|
|
||||||
</span>
|
|
||||||
<input
|
|
||||||
class="form-control form-control-lg"
|
|
||||||
v-model="email"
|
|
||||||
:placeholder="trans(PERSON_MESSAGES_PERSON_EMAIL)"
|
|
||||||
:aria-label="trans(PERSON_MESSAGES_PERSON_EMAIL)"
|
|
||||||
aria-describedby="email"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="action === 'create'" class="input-group mb-3 form-check">
|
|
||||||
<input
|
|
||||||
class="form-check-input"
|
|
||||||
type="checkbox"
|
|
||||||
v-model="showAddressForm"
|
|
||||||
name="showAddressForm"
|
|
||||||
/>
|
|
||||||
<label class="form-check-label">
|
|
||||||
{{ trans(PERSON_MESSAGES_PERSON_ADDRESS_SHOW_ADDRESS_FORM) }}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="action === 'create' && showAddressFormValue"
|
|
||||||
class="form-floating mb-3"
|
|
||||||
>
|
|
||||||
<p>{{ trans(PERSON_MESSAGES_PERSON_ADDRESS_WARNING) }}</p>
|
|
||||||
<AddAddress
|
|
||||||
:context="addAddress.context"
|
|
||||||
:options="addAddress.options"
|
|
||||||
:addressChangedCallback="submitNewAddress"
|
|
||||||
ref="addAddress"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="alert alert-warning" v-if="errors.length">
|
|
||||||
<ul>
|
|
||||||
<li v-for="(e, i) in errors" :key="i">{{ e }}</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { ref, reactive, computed, onMounted } from "vue";
|
import { ref, onMounted } from "vue";
|
||||||
import {
|
import { getPerson } from "../../_api/OnTheFly";
|
||||||
getCentersForPersonCreation,
|
|
||||||
getCivilities,
|
|
||||||
getGenders,
|
|
||||||
getPerson,
|
|
||||||
getPersonAltNames,
|
|
||||||
} from "../../_api/OnTheFly";
|
|
||||||
import PersonRenderBox from "../Entity/PersonRenderBox.vue";
|
import PersonRenderBox from "../Entity/PersonRenderBox.vue";
|
||||||
import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue";
|
import PersonEdit from "./PersonEdit.vue";
|
||||||
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
|
import type { Person } from "ChillPersonAssets/types";
|
||||||
import {
|
|
||||||
trans,
|
|
||||||
PERSON_MESSAGES_PERSON_LASTNAME,
|
|
||||||
PERSON_MESSAGES_PERSON_FIRSTNAME,
|
|
||||||
PERSON_MESSAGES_PERSON_GENDER_PLACEHOLDER,
|
|
||||||
PERSON_MESSAGES_PERSON_GENDER_TITLE,
|
|
||||||
PERSON_MESSAGES_PERSON_CENTER_PLACEHOLDER,
|
|
||||||
PERSON_MESSAGES_PERSON_CENTER_TITLE,
|
|
||||||
PERSON_MESSAGES_PERSON_CIVILITY_PLACEHOLDER,
|
|
||||||
PERSON_MESSAGES_PERSON_CIVILITY_TITLE,
|
|
||||||
PERSON_MESSAGES_PERSON_PHONENUMBER,
|
|
||||||
PERSON_MESSAGES_PERSON_MOBILENUMBER,
|
|
||||||
PERSON_MESSAGES_PERSON_EMAIL,
|
|
||||||
PERSON_MESSAGES_PERSON_ADDRESS_SHOW_ADDRESS_FORM,
|
|
||||||
PERSON_MESSAGES_PERSON_ADDRESS_WARNING,
|
|
||||||
} from "translator";
|
|
||||||
|
|
||||||
const props = defineProps({
|
interface Props {
|
||||||
id: [String, Number],
|
id: string | number;
|
||||||
type: String,
|
type?: string;
|
||||||
action: String,
|
action: "show" | "edit" | "create";
|
||||||
query: String,
|
query?: string;
|
||||||
});
|
|
||||||
|
|
||||||
const person = reactive({
|
|
||||||
type: "person",
|
|
||||||
lastName: "",
|
|
||||||
firstName: "",
|
|
||||||
altNames: [],
|
|
||||||
addressId: null,
|
|
||||||
center: null,
|
|
||||||
gender: null,
|
|
||||||
civility: null,
|
|
||||||
birthdate: null,
|
|
||||||
phonenumber: "",
|
|
||||||
mobilenumber: "",
|
|
||||||
email: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
const config = reactive({
|
|
||||||
altNames: [],
|
|
||||||
civilities: [],
|
|
||||||
centers: [],
|
|
||||||
genders: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
const showCenters = ref(false);
|
|
||||||
const showAddressFormValue = ref(false);
|
|
||||||
const errors = ref([]);
|
|
||||||
|
|
||||||
const addAddress = reactive({
|
|
||||||
options: {
|
|
||||||
button: {
|
|
||||||
text: { create: "person.address.create_address" },
|
|
||||||
size: "btn-sm",
|
|
||||||
},
|
|
||||||
title: { create: "person.address.create_address" },
|
|
||||||
},
|
|
||||||
context: {
|
|
||||||
target: {},
|
|
||||||
edit: false,
|
|
||||||
addressId: null,
|
|
||||||
defaults: window.addaddress,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const firstName = computed({
|
|
||||||
get: () => person.firstName,
|
|
||||||
set: (value) => {
|
|
||||||
person.firstName = value;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const lastName = computed({
|
|
||||||
get: () => person.lastName,
|
|
||||||
set: (value) => {
|
|
||||||
person.lastName = value;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const gender = computed({
|
|
||||||
get: () => (person.gender ? person.gender.id : null),
|
|
||||||
set: (value) => {
|
|
||||||
person.gender = { id: value, type: "chill_main_gender" };
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const civility = computed({
|
|
||||||
get: () => (person.civility ? person.civility.id : null),
|
|
||||||
set: (value) => {
|
|
||||||
person.civility = { id: value, type: "chill_main_civility" };
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const birthDate = computed({
|
|
||||||
get: () => (person.birthdate ? person.birthdate.datetime.split("T")[0] : ""),
|
|
||||||
set: (value) => {
|
|
||||||
if (person.birthdate) {
|
|
||||||
person.birthdate.datetime = value + "T00:00:00+0100";
|
|
||||||
} else {
|
|
||||||
person.birthdate = { datetime: value + "T00:00:00+0100" };
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const phonenumber = computed({
|
|
||||||
get: () => person.phonenumber,
|
|
||||||
set: (value) => {
|
|
||||||
person.phonenumber = value;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const mobilenumber = computed({
|
|
||||||
get: () => person.mobilenumber,
|
|
||||||
set: (value) => {
|
|
||||||
person.mobilenumber = value;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const email = computed({
|
|
||||||
get: () => person.email,
|
|
||||||
set: (value) => {
|
|
||||||
person.email = value;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const showAddressForm = computed({
|
|
||||||
get: () => showAddressFormValue.value,
|
|
||||||
set: (value) => {
|
|
||||||
showAddressFormValue.value = value;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const center = computed({
|
|
||||||
get: () => {
|
|
||||||
const c = config.centers.find(
|
|
||||||
(c) => person.center !== null && person.center.id === c.id,
|
|
||||||
);
|
|
||||||
return typeof c === "undefined" ? null : c;
|
|
||||||
},
|
|
||||||
set: (value) => {
|
|
||||||
person.center = { id: value.id, type: value.type };
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const genderClass = computed(() => {
|
|
||||||
switch (person.gender && person.gender.id) {
|
|
||||||
case "woman":
|
|
||||||
return "fa-venus";
|
|
||||||
case "man":
|
|
||||||
return "fa-mars";
|
|
||||||
case "both":
|
|
||||||
return "fa-neuter";
|
|
||||||
case "unknown":
|
|
||||||
return "fa-genderless";
|
|
||||||
default:
|
|
||||||
return "fa-genderless";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const genderTranslation = computed(() => {
|
|
||||||
switch (person.gender && person.gender.genderTranslation) {
|
|
||||||
case "woman":
|
|
||||||
return PERSON_MESSAGES_PERSON_GENDER_WOMAN;
|
|
||||||
case "man":
|
|
||||||
return PERSON_MESSAGES_PERSON_GENDER_MAN;
|
|
||||||
case "neutral":
|
|
||||||
return PERSON_MESSAGES_PERSON_GENDER_NEUTRAL;
|
|
||||||
case "unknown":
|
|
||||||
return PERSON_MESSAGES_PERSON_GENDER_UNKNOWN;
|
|
||||||
default:
|
|
||||||
return PERSON_MESSAGES_PERSON_GENDER_UNKNOWN;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const feminized = computed(() =>
|
|
||||||
person.gender && person.gender.id === "woman" ? "e" : "",
|
|
||||||
);
|
|
||||||
const personAltNamesLabels = computed(() =>
|
|
||||||
person.altNames.map((a) => (a ? a.label : "")),
|
|
||||||
);
|
|
||||||
const queryItems = computed(() =>
|
|
||||||
props.query ? props.query.split(" ") : null,
|
|
||||||
);
|
|
||||||
|
|
||||||
function checkErrors() {
|
|
||||||
errors.value = [];
|
|
||||||
if (person.lastName === "") {
|
|
||||||
errors.value.push("Le nom ne doit pas être vide.");
|
|
||||||
}
|
|
||||||
if (person.firstName === "") {
|
|
||||||
errors.value.push("Le prénom ne doit pas être vide.");
|
|
||||||
}
|
|
||||||
if (!person.gender) {
|
|
||||||
errors.value.push("Le genre doit être renseigné");
|
|
||||||
}
|
|
||||||
if (showCenters.value && person.center === null) {
|
|
||||||
errors.value.push("Le centre doit être renseigné");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadData() {
|
const props = defineProps<Props>();
|
||||||
getPerson(props.id).then((p) => {
|
|
||||||
Object.assign(person, p);
|
const person = ref<Person | null>(null);
|
||||||
|
|
||||||
|
function loadData(): void {
|
||||||
|
if (props.id === undefined || props.id === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const idNum = typeof props.id === "string" ? Number(props.id) : props.id;
|
||||||
|
if (!Number.isFinite(idNum)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getPerson(idNum as number).then((p) => {
|
||||||
|
person.value = p;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onAltNameInput(event) {
|
|
||||||
const key = event.target.id;
|
|
||||||
const label = event.target.value;
|
|
||||||
let updateAltNames = person.altNames.filter((a) => a.key !== key);
|
|
||||||
updateAltNames.push({ key: key, label: label });
|
|
||||||
person.altNames = updateAltNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addQueryItem(field, queryItem) {
|
|
||||||
switch (field) {
|
|
||||||
case "lastName":
|
|
||||||
person.lastName = person.lastName
|
|
||||||
? (person.lastName += ` ${queryItem}`)
|
|
||||||
: queryItem;
|
|
||||||
break;
|
|
||||||
case "firstName":
|
|
||||||
person.firstName = person.firstName
|
|
||||||
? (person.firstName += ` ${queryItem}`)
|
|
||||||
: queryItem;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function submitNewAddress(payload) {
|
|
||||||
person.addressId = payload.addressId;
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getPersonAltNames().then((altNames) => {
|
|
||||||
config.altNames = altNames;
|
|
||||||
});
|
|
||||||
getCivilities().then((civilities) => {
|
|
||||||
if ("results" in civilities) {
|
|
||||||
config.civilities = civilities.results;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
getGenders().then((genders) => {
|
|
||||||
if ("results" in genders) {
|
|
||||||
config.genders = genders.results;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (props.action !== "create") {
|
if (props.action !== "create") {
|
||||||
loadData();
|
loadData();
|
||||||
} else {
|
|
||||||
getCentersForPersonCreation().then((params) => {
|
|
||||||
config.centers = params.centers.filter((c) => c.isActive);
|
|
||||||
showCenters.value = params.showCenters;
|
|
||||||
if (showCenters.value && config.centers.length === 1) {
|
|
||||||
person.center = config.centers[0];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
defineExpose(genderClass, genderTranslation, feminized, birthDate);
|
|
||||||
</script>
|
</script>
|
||||||
|
@@ -0,0 +1,455 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="form-floating mb-3">
|
||||||
|
<input
|
||||||
|
class="form-control form-control-lg"
|
||||||
|
id="lastname"
|
||||||
|
v-model="lastName"
|
||||||
|
:placeholder="trans(PERSON_MESSAGES_PERSON_LASTNAME)"
|
||||||
|
@change="checkErrors"
|
||||||
|
/>
|
||||||
|
<label for="lastname">{{ trans(PERSON_MESSAGES_PERSON_LASTNAME) }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="queryItems">
|
||||||
|
<ul class="list-suggest add-items inline">
|
||||||
|
<li
|
||||||
|
v-for="(qi, i) in queryItems"
|
||||||
|
:key="i"
|
||||||
|
@click="addQueryItem('lastName', qi)"
|
||||||
|
>
|
||||||
|
<span class="person-text">{{ qi }}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-floating mb-3">
|
||||||
|
<input
|
||||||
|
class="form-control form-control-lg"
|
||||||
|
id="firstname"
|
||||||
|
v-model="firstName"
|
||||||
|
:placeholder="trans(PERSON_MESSAGES_PERSON_FIRSTNAME)"
|
||||||
|
@change="checkErrors"
|
||||||
|
/>
|
||||||
|
<label for="firstname">{{
|
||||||
|
trans(PERSON_MESSAGES_PERSON_FIRSTNAME)
|
||||||
|
}}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="queryItems">
|
||||||
|
<ul class="list-suggest add-items inline">
|
||||||
|
<li
|
||||||
|
v-for="(qi, i) in queryItems"
|
||||||
|
:key="i"
|
||||||
|
@click="addQueryItem('firstName', qi)"
|
||||||
|
>
|
||||||
|
<span class="person-text">{{ qi }}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-for="(a, i) in config.altNames"
|
||||||
|
:key="a.key"
|
||||||
|
class="form-floating mb-3"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="form-control form-control-lg"
|
||||||
|
:id="a.key"
|
||||||
|
:value="personAltNamesLabels[i]"
|
||||||
|
@input="onAltNameInput"
|
||||||
|
/>
|
||||||
|
<label :for="a.key">{{ localizeString(a.labels) }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-floating mb-3">
|
||||||
|
<select class="form-select form-select-lg" id="gender" v-model="gender">
|
||||||
|
<option selected disabled>
|
||||||
|
{{ trans(PERSON_MESSAGES_PERSON_GENDER_PLACEHOLDER) }}
|
||||||
|
</option>
|
||||||
|
<option v-for="g in config.genders" :value="g.id" :key="g.id">
|
||||||
|
{{ g.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<label>{{ trans(PERSON_MESSAGES_PERSON_GENDER_TITLE) }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="form-floating mb-3"
|
||||||
|
v-if="showCenters && config.centers.length > 1"
|
||||||
|
>
|
||||||
|
<select class="form-select form-select-lg" id="center" v-model="center">
|
||||||
|
<option selected disabled>
|
||||||
|
{{ trans(PERSON_MESSAGES_PERSON_CENTER_PLACEHOLDER) }}
|
||||||
|
</option>
|
||||||
|
<option v-for="c in config.centers" :value="c" :key="c.id">
|
||||||
|
{{ c.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<label>{{ trans(PERSON_MESSAGES_PERSON_CENTER_TITLE) }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-floating mb-3">
|
||||||
|
<select
|
||||||
|
class="form-select form-select-lg"
|
||||||
|
id="civility"
|
||||||
|
v-model="civility"
|
||||||
|
>
|
||||||
|
<option selected disabled>
|
||||||
|
{{ trans(PERSON_MESSAGES_PERSON_CIVILITY_PLACEHOLDER) }}
|
||||||
|
</option>
|
||||||
|
<option v-for="c in config.civilities" :value="c.id" :key="c.id">
|
||||||
|
{{ localizeString(c.name) }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<label>{{ trans(PERSON_MESSAGES_PERSON_CIVILITY_TITLE) }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input-group mb-3">
|
||||||
|
<span class="input-group-text" id="phonenumber">
|
||||||
|
<i class="fa fa-fw fa-phone"></i>
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
class="form-control form-control-lg"
|
||||||
|
v-model="phonenumber"
|
||||||
|
:placeholder="trans(PERSON_MESSAGES_PERSON_PHONENUMBER)"
|
||||||
|
:aria-label="trans(PERSON_MESSAGES_PERSON_PHONENUMBER)"
|
||||||
|
aria-describedby="phonenumber"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input-group mb-3">
|
||||||
|
<span class="input-group-text" id="mobilenumber">
|
||||||
|
<i class="fa fa-fw fa-mobile"></i>
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
class="form-control form-control-lg"
|
||||||
|
v-model="mobilenumber"
|
||||||
|
:placeholder="trans(PERSON_MESSAGES_PERSON_MOBILENUMBER)"
|
||||||
|
:aria-label="trans(PERSON_MESSAGES_PERSON_MOBILENUMBER)"
|
||||||
|
aria-describedby="mobilenumber"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input-group mb-3">
|
||||||
|
<span class="input-group-text" id="email">
|
||||||
|
<i class="fa fa-fw fa-at"></i>
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
class="form-control form-control-lg"
|
||||||
|
v-model="email"
|
||||||
|
:placeholder="trans(PERSON_MESSAGES_PERSON_EMAIL)"
|
||||||
|
:aria-label="trans(PERSON_MESSAGES_PERSON_EMAIL)"
|
||||||
|
aria-describedby="email"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="action === 'create'" class="input-group mb-3 form-check">
|
||||||
|
<input
|
||||||
|
class="form-check-input"
|
||||||
|
type="checkbox"
|
||||||
|
v-model="showAddressForm"
|
||||||
|
name="showAddressForm"
|
||||||
|
/>
|
||||||
|
<label class="form-check-label">
|
||||||
|
{{ trans(PERSON_MESSAGES_PERSON_ADDRESS_SHOW_ADDRESS_FORM) }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="action === 'create' && showAddressFormValue"
|
||||||
|
class="form-floating mb-3"
|
||||||
|
>
|
||||||
|
<p>{{ trans(PERSON_MESSAGES_PERSON_ADDRESS_WARNING) }}</p>
|
||||||
|
<AddAddress
|
||||||
|
:context="addAddress.context"
|
||||||
|
:options="addAddress.options"
|
||||||
|
:addressChangedCallback="submitNewAddress"
|
||||||
|
ref="addAddress"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="alert alert-warning" v-if="errors.length">
|
||||||
|
<ul>
|
||||||
|
<li v-for="(e, i) in errors" :key="i">{{ e }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, computed, onMounted } from "vue";
|
||||||
|
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
|
||||||
|
import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue";
|
||||||
|
import {
|
||||||
|
getCentersForPersonCreation,
|
||||||
|
getCivilities,
|
||||||
|
getGenders,
|
||||||
|
getPerson,
|
||||||
|
getPersonAltNames,
|
||||||
|
} from "../../_api/OnTheFly";
|
||||||
|
import {
|
||||||
|
trans,
|
||||||
|
PERSON_MESSAGES_PERSON_LASTNAME,
|
||||||
|
PERSON_MESSAGES_PERSON_FIRSTNAME,
|
||||||
|
PERSON_MESSAGES_PERSON_GENDER_PLACEHOLDER,
|
||||||
|
PERSON_MESSAGES_PERSON_GENDER_TITLE,
|
||||||
|
PERSON_MESSAGES_PERSON_CENTER_PLACEHOLDER,
|
||||||
|
PERSON_MESSAGES_PERSON_CENTER_TITLE,
|
||||||
|
PERSON_MESSAGES_PERSON_CIVILITY_PLACEHOLDER,
|
||||||
|
PERSON_MESSAGES_PERSON_CIVILITY_TITLE,
|
||||||
|
PERSON_MESSAGES_PERSON_PHONENUMBER,
|
||||||
|
PERSON_MESSAGES_PERSON_MOBILENUMBER,
|
||||||
|
PERSON_MESSAGES_PERSON_EMAIL,
|
||||||
|
PERSON_MESSAGES_PERSON_ADDRESS_SHOW_ADDRESS_FORM,
|
||||||
|
PERSON_MESSAGES_PERSON_ADDRESS_WARNING,
|
||||||
|
} from "translator";
|
||||||
|
import {
|
||||||
|
Center,
|
||||||
|
Civility,
|
||||||
|
Gender,
|
||||||
|
DateTimeCreate,
|
||||||
|
} from "ChillMainAssets/types";
|
||||||
|
import { AltName } from "ChillPersonAssets/types";
|
||||||
|
|
||||||
|
interface PersonState {
|
||||||
|
type: "person";
|
||||||
|
lastName: string;
|
||||||
|
firstName: string;
|
||||||
|
altNames: { key: string; label: string }[];
|
||||||
|
addressId: number | null;
|
||||||
|
center: { id: number; type: string } | null;
|
||||||
|
gender: { id: string; type: string } | null;
|
||||||
|
civility: { id: number; type: string } | null;
|
||||||
|
birthdate: DateTimeCreate | null;
|
||||||
|
phonenumber: string;
|
||||||
|
mobilenumber: string;
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PersonEditComponentConfig {
|
||||||
|
id?: number | null;
|
||||||
|
type?: string;
|
||||||
|
action: "edit" | "create";
|
||||||
|
query: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<PersonEditComponentConfig>(), {
|
||||||
|
id: null,
|
||||||
|
type: "TODO",
|
||||||
|
});
|
||||||
|
|
||||||
|
const person = reactive<PersonState>({
|
||||||
|
type: "person",
|
||||||
|
lastName: "",
|
||||||
|
firstName: "",
|
||||||
|
altNames: [],
|
||||||
|
addressId: null,
|
||||||
|
center: null,
|
||||||
|
gender: null,
|
||||||
|
civility: null,
|
||||||
|
birthdate: null,
|
||||||
|
phonenumber: "",
|
||||||
|
mobilenumber: "",
|
||||||
|
email: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const config = reactive<{
|
||||||
|
altNames: AltName[];
|
||||||
|
civilities: Civility[];
|
||||||
|
centers: Center[];
|
||||||
|
genders: Gender[];
|
||||||
|
}>({
|
||||||
|
altNames: [],
|
||||||
|
civilities: [],
|
||||||
|
centers: [],
|
||||||
|
genders: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const showCenters = ref(false);
|
||||||
|
const showAddressFormValue = ref(false);
|
||||||
|
const errors = ref<string[]>([]);
|
||||||
|
|
||||||
|
const addAddress = reactive({
|
||||||
|
options: {
|
||||||
|
button: {
|
||||||
|
text: { create: "person.address.create_address" },
|
||||||
|
size: "btn-sm",
|
||||||
|
},
|
||||||
|
title: { create: "person.address.create_address" },
|
||||||
|
},
|
||||||
|
context: {
|
||||||
|
target: {},
|
||||||
|
edit: false,
|
||||||
|
addressId: null as number | null,
|
||||||
|
defaults: (window as any).addaddress,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const firstName = computed({
|
||||||
|
get: () => person.firstName,
|
||||||
|
set: (value: string) => {
|
||||||
|
person.firstName = value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const lastName = computed({
|
||||||
|
get: () => person.lastName,
|
||||||
|
set: (value: string) => {
|
||||||
|
person.lastName = value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const gender = computed({
|
||||||
|
get: () => (person.gender ? person.gender.id : null),
|
||||||
|
set: (value: string | null) => {
|
||||||
|
person.gender = value ? { id: value, type: "chill_main_gender" } : null;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const civility = computed({
|
||||||
|
get: () => (person.civility ? person.civility.id : null),
|
||||||
|
set: (value: number | null) => {
|
||||||
|
person.civility =
|
||||||
|
value !== null ? { id: value, type: "chill_main_civility" } : null;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const birthDate = computed({
|
||||||
|
get: () => (person.birthdate ? person.birthdate.datetime.split("T")[0] : ""),
|
||||||
|
set: (value: string) => {
|
||||||
|
if (person.birthdate) {
|
||||||
|
person.birthdate.datetime = value + "T00:00:00+0100";
|
||||||
|
} else {
|
||||||
|
person.birthdate = { datetime: value + "T00:00:00+0100" };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const phonenumber = computed({
|
||||||
|
get: () => person.phonenumber,
|
||||||
|
set: (value: string) => {
|
||||||
|
person.phonenumber = value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const mobilenumber = computed({
|
||||||
|
get: () => person.mobilenumber,
|
||||||
|
set: (value: string) => {
|
||||||
|
person.mobilenumber = value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const email = computed({
|
||||||
|
get: () => person.email,
|
||||||
|
set: (value: string) => {
|
||||||
|
person.email = value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const showAddressForm = computed({
|
||||||
|
get: () => showAddressFormValue.value,
|
||||||
|
set: (value: boolean) => {
|
||||||
|
showAddressFormValue.value = value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const center = computed({
|
||||||
|
get: () => {
|
||||||
|
const c = config.centers.find(
|
||||||
|
(c) => person.center !== null && person.center.id === c.id,
|
||||||
|
);
|
||||||
|
return typeof c === "undefined" ? null : c;
|
||||||
|
},
|
||||||
|
set: (value: Center | null) => {
|
||||||
|
if (value) {
|
||||||
|
person.center = {
|
||||||
|
id: value.id,
|
||||||
|
type: (value as any).type ?? "chill_main_center",
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
person.center = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const personAltNamesLabels = computed(() =>
|
||||||
|
person.altNames.map((a) => (a ? a.label : "")),
|
||||||
|
);
|
||||||
|
const queryItems = computed(() =>
|
||||||
|
props.query ? props.query.split(" ") : null,
|
||||||
|
);
|
||||||
|
|
||||||
|
function checkErrors() {
|
||||||
|
errors.value = [];
|
||||||
|
if (person.lastName === "") {
|
||||||
|
errors.value.push("Le nom ne doit pas être vide.");
|
||||||
|
}
|
||||||
|
if (person.firstName === "") {
|
||||||
|
errors.value.push("Le prénom ne doit pas être vide.");
|
||||||
|
}
|
||||||
|
if (!person.gender) {
|
||||||
|
errors.value.push("Le genre doit être renseigné");
|
||||||
|
}
|
||||||
|
if (showCenters.value && person.center === null) {
|
||||||
|
errors.value.push("Le centre doit être renseigné");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadData() {
|
||||||
|
if (props.id !== undefined && props.id !== null) {
|
||||||
|
getPerson(props.id as any).then((p: any) => {
|
||||||
|
Object.assign(person, p);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAltNameInput(event: Event) {
|
||||||
|
const target = event.target as HTMLInputElement;
|
||||||
|
const key = target.id;
|
||||||
|
const label = target.value;
|
||||||
|
const updateAltNames = person.altNames.filter((a) => a.key !== key);
|
||||||
|
updateAltNames.push({ key, label });
|
||||||
|
person.altNames = updateAltNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addQueryItem(field: "lastName" | "firstName", queryItem: string) {
|
||||||
|
switch (field) {
|
||||||
|
case "lastName":
|
||||||
|
person.lastName = person.lastName
|
||||||
|
? (person.lastName += ` ${queryItem}`)
|
||||||
|
: queryItem;
|
||||||
|
break;
|
||||||
|
case "firstName":
|
||||||
|
person.firstName = person.firstName
|
||||||
|
? (person.firstName += ` ${queryItem}`)
|
||||||
|
: queryItem;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitNewAddress(payload: { addressId: number }) {
|
||||||
|
person.addressId = payload.addressId;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getPersonAltNames().then((altNames: any) => {
|
||||||
|
config.altNames = altNames;
|
||||||
|
});
|
||||||
|
getCivilities().then((civilities: any) => {
|
||||||
|
if ("results" in civilities) {
|
||||||
|
config.civilities = civilities.results;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
getGenders().then((genders: any) => {
|
||||||
|
if ("results" in genders) {
|
||||||
|
config.genders = genders.results;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (props.action !== "create") {
|
||||||
|
loadData();
|
||||||
|
} else {
|
||||||
|
getCentersForPersonCreation().then((params: any) => {
|
||||||
|
config.centers = params.centers.filter((c: any) => c.isActive);
|
||||||
|
showCenters.value = params.showCenters;
|
||||||
|
if (showCenters.value && config.centers.length === 1) {
|
||||||
|
// if there is only one center, preselect it
|
||||||
|
person.center = {
|
||||||
|
id: config.centers[0].id,
|
||||||
|
type: (config.centers[0] as any).type ?? "chill_main_center",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
Reference in New Issue
Block a user