Merge remote-tracking branch 'origin/ticket-app-master' into ticket-app-master

This commit is contained in:
2025-06-20 12:45:33 +02:00
47 changed files with 2646 additions and 2400 deletions

View File

@@ -27,18 +27,18 @@
<div v-if="parent">
<div class="parent-info">
<i class="fa fa-li fa-hand-o-right" />
<b class="me-2">{{ $t("child_of") }}</b>
<b class="me-2">{{ trans(THIRDPARTY_MESSAGES_CHILD_OF) }}</b>
<span class="chill-entity badge-thirdparty">{{
parent.text
}}</span>
</div>
</div>
<div class="form-floating mb-3" v-else-if="kind !== 'child'">
<div class="form-floating mb-3" v-else-if="kind.value !== 'child'">
<div class="form-check">
<input
class="form-check-input mt-0"
type="radio"
v-model="kind"
v-model="kind.value"
value="company"
id="tpartyKindInstitution"
/>
@@ -53,7 +53,7 @@
<input
class="form-check-input mt-0"
type="radio"
v-model="kind"
v-model="kind.value"
value="contact"
id="tpartyKindContact"
/>
@@ -95,7 +95,7 @@
v-model="thirdparty.civility"
>
<option selected disabled :value="null">
{{ $t("thirdparty.civility") }}
{{ trans(THIRDPARTY_MESSAGES_THIRDPARTY_CIVILITY) }}
</option>
<option
v-for="civility in civilities"
@@ -110,8 +110,12 @@
<input
class="form-control form-control-lg"
v-model="thirdparty.profession"
:placeholder="$t('thirdparty.profession')"
:aria-label="$t('thirdparty.profession')"
:placeholder="
trans(THIRDPARTY_MESSAGES_THIRDPARTY_PROFESSION)
"
:aria-label="
trans(THIRDPARTY_MESSAGES_THIRDPARTY_PROFESSION)
"
aria-describedby="profession"
/>
</div>
@@ -123,10 +127,12 @@
class="form-control form-control-lg"
id="firstname"
v-model="thirdparty.firstname"
:placeholder="$t('thirdparty.firstname')"
:placeholder="
trans(THIRDPARTY_MESSAGES_THIRDPARTY_FIRSTNAME)
"
/>
<label for="firstname">{{
$t("thirdparty.firstname")
trans(THIRDPARTY_MESSAGES_THIRDPARTY_FIRSTNAME)
}}</label>
</div>
<div v-if="queryItems">
@@ -147,10 +153,12 @@
class="form-control form-control-lg"
id="name"
v-model="thirdparty.name"
:placeholder="$t('thirdparty.lastname')"
:placeholder="
trans(THIRDPARTY_MESSAGES_THIRDPARTY_LASTNAME)
"
/>
<label for="name">{{
$t("thirdparty.lastname")
trans(THIRDPARTY_MESSAGES_THIRDPARTY_LASTNAME)
}}</label>
</div>
<div v-if="queryItems">
@@ -174,9 +182,11 @@
class="form-control form-control-lg"
id="name"
v-model="thirdparty.name"
:placeholder="$t('thirdparty.name')"
:placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_NAME)"
/>
<label for="name">{{ $t("thirdparty.name") }}</label>
<label for="name">{{
trans(THIRDPARTY_MESSAGES_THIRDPARTY_NAME)
}}</label>
</div>
<div v-if="query">
<ul class="list-suggest add-items inline">
@@ -188,7 +198,7 @@
</div>
<template v-if="thirdparty.kind !== 'child'">
<add-address
<AddAddress
key="thirdparty"
:context="context"
:options="addAddress.options"
@@ -204,8 +214,8 @@
<input
class="form-control form-control-lg"
v-model="thirdparty.email"
:placeholder="$t('thirdparty.email')"
:aria-label="$t('thirdparty.email')"
:placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_EMAIL)"
:aria-label="trans(THIRDPARTY_MESSAGES_THIRDPARTY_EMAIL)"
aria-describedby="email"
/>
</div>
@@ -217,8 +227,8 @@
<input
class="form-control form-control-lg"
v-model="thirdparty.telephone"
:placeholder="$t('thirdparty.phonenumber')"
:aria-label="$t('thirdparty.phonenumber')"
:placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER)"
:aria-label="trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER)"
aria-describedby="phonenumber"
/>
</div>
@@ -230,8 +240,10 @@
<input
class="form-control form-control-lg"
v-model="thirdparty.telephone2"
:placeholder="$t('thirdparty.phonenumber2')"
:aria-label="$t('thirdparty.phonenumber2')"
:placeholder="
trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER2)
"
:aria-label="trans(THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER2)"
aria-describedby="phonenumber2"
/>
</div>
@@ -243,7 +255,7 @@
/></span>
<textarea
class="form-control form-control-lg"
:placeholder="$t('thirdparty.comment')"
:placeholder="trans(THIRDPARTY_MESSAGES_THIRDPARTY_COMMENT)"
v-model="thirdparty.comment"
/>
</div>
@@ -251,173 +263,178 @@
</div>
</template>
<script>
<script setup>
import { ref, reactive, computed, onMounted, getCurrentInstance } from "vue";
import ThirdPartyRenderBox from "../Entity/ThirdPartyRenderBox.vue";
import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress";
import { getThirdparty } from "../../_api/OnTheFly";
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
import { localizeString as _localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
import {
trans,
THIRDPARTY_MESSAGES_THIRDPARTY_FIRSTNAME,
THIRDPARTY_MESSAGES_THIRDPARTY_LASTNAME,
THIRDPARTY_MESSAGES_THIRDPARTY_NAME,
THIRDPARTY_MESSAGES_THIRDPARTY_EMAIL,
THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER,
THIRDPARTY_MESSAGES_THIRDPARTY_PHONENUMBER2,
THIRDPARTY_MESSAGES_THIRDPARTY_COMMENT,
THIRDPARTY_MESSAGES_THIRDPARTY_PROFESSION,
THIRDPARTY_MESSAGES_THIRDPARTY_CIVILITY,
THIRDPARTY_MESSAGES_CHILD_OF,
} from "translator";
// Props
const props = defineProps(["id", "type", "action", "query", "parent"]);
export default {
name: "OnTheFlyThirdParty",
props: ["id", "type", "action", "query", "parent"],
components: {
ThirdPartyRenderBox,
AddAddress,
BadgeEntity,
},
data() {
return {
//context: {}, <--
thirdparty: {
type: "thirdparty",
address: null,
kind: "company",
firstname: "",
name: "",
telephone: "",
telephone2: "",
civility: null,
profession: "",
},
civilities: [],
addAddress: {
options: {
openPanesInModal: true,
onlyButton: false,
button: {
size: "btn-sm",
},
title: {
create: "add_an_address_title",
edit: "edit_address",
},
},
},
};
},
computed: {
kind: {
get() {
// note: there are also default to 'institution' set in the "mounted" method
if (this.$data.thirdparty.kind !== undefined) {
return this.$data.thirdparty.kind;
} else {
return "company";
}
},
set(v) {
this.$data.thirdparty.kind = v;
},
// Instance for $t and $toast
const { proxy } = getCurrentInstance();
// State
const thirdparty = reactive({
type: "thirdparty",
address: null,
kind: "company",
firstname: "",
name: "",
telephone: "",
telephone2: "",
civility: null,
profession: "",
comment: "",
parent: props.parent ? props.parent : undefined,
});
const civilities = ref([]);
const addAddress = reactive({
options: {
openPanesInModal: true,
onlyButton: false,
button: {
size: "btn-sm",
},
context() {
let context = {
target: {
name: this.type,
id: this.id,
},
edit: false,
addressId: null,
defaults: window.addaddress,
};
if (
!(
this.thirdparty.address === undefined ||
this.thirdparty.address === null
) &&
this.thirdparty.address.address_id !== null
) {
// to complete
context.addressId = this.thirdparty.address.address_id;
context.edit = true;
}
//this.context = context; <--
return context;
},
queryItems() {
return this.query ? this.query.split(" ") : null;
title: {
create: "add_an_address_title",
edit: "edit_address",
},
},
methods: {
localizeString,
loadData() {
return getThirdparty(this.id).then(
(thirdparty) =>
new Promise((resolve) => {
this.thirdparty = thirdparty;
this.thirdparty.kind = thirdparty.kind;
if (this.action !== "show") {
if (thirdparty.address !== null) {
// bof! we force getInitialAddress because addressId not available when mounted
this.$refs.addAddress.getInitialAddress(
thirdparty.address.address_id,
);
}
}
resolve();
}),
);
});
const addAddressRef = ref(null);
// Kind as computed ref
const kind = computed({
get() {
return thirdparty.kind !== undefined ? thirdparty.kind : "company";
},
set(v) {
thirdparty.kind = v;
},
});
// Context as computed
const context = computed(() => {
let ctx = {
target: {
name: props.type,
id: props.id,
},
loadCivilities() {
const url = `/api/1.0/main/civility.json`;
return makeFetch("GET", url)
.then((response) => {
this.$data.civilities = response.results;
return Promise.resolve();
})
.catch((error) => {
console.log(error);
this.$toast.open({ message: error.body });
});
},
submitAddress(payload) {
console.log("submitAddress", payload);
if (typeof payload.addressId !== "undefined") {
// <--
this.context.edit = true;
this.context.addressId = payload.addressId; // bof! use legacy and not legacy in payload
this.thirdparty.address = payload.address; // <--
console.log("switch address to edit mode", this.context);
}
},
addQueryItem(field, queryItem) {
switch (field) {
case "name":
if (this.thirdparty.name) {
this.thirdparty.name += ` ${queryItem}`;
} else {
this.thirdparty.name = queryItem;
edit: false,
addressId: null,
defaults: window.addaddress,
};
if (
!(thirdparty.address === undefined || thirdparty.address === null) &&
thirdparty.address.address_id !== null
) {
ctx.addressId = thirdparty.address.address_id;
ctx.edit = true;
}
return ctx;
});
// Query items
const queryItems = computed(() =>
props.query ? props.query.split(" ") : null,
);
// Methods
function localizeString(str) {
return _localizeString(str);
}
function loadData() {
return getThirdparty(props.id).then(
(tp) =>
new Promise((resolve) => {
Object.assign(thirdparty, tp);
thirdparty.kind = tp.kind;
if (props.action !== "show") {
if (tp.address !== null && addAddressRef.value) {
addAddressRef.value.getInitialAddress(
tp.address.address_id,
);
}
break;
case "firstName":
this.thirdparty.firstname = queryItem;
break;
}
resolve();
}),
);
}
function loadCivilities() {
const url = `/api/1.0/main/civility.json`;
return makeFetch("GET", url)
.then((response) => {
civilities.value = response.results;
return Promise.resolve();
})
.catch((error) => {
console.log(error);
proxy.$toast.open({ message: error.body });
});
}
function submitAddress(payload) {
if (typeof payload.addressId !== "undefined") {
context.value.edit = true;
context.value.addressId = payload.addressId;
thirdparty.address = payload.address;
}
}
function addQueryItem(field, queryItem) {
switch (field) {
case "name":
if (thirdparty.name) {
thirdparty.name += ` ${queryItem}`;
} else {
thirdparty.name = queryItem;
}
},
addQuery(query) {
this.thirdparty.name = query;
},
},
mounted() {
let dependencies = [];
dependencies.push(this.loadCivilities());
if (this.action !== "create") {
if (this.id) {
dependencies.push(this.loadData());
// here we can do something when all promises are resolve, with
// Promise.all(dependencies).then(() => { /* do something */ });
}
if (this.action === "addContact") {
this.$data.thirdparty.kind = "child";
// this.$data.thirdparty.parent = this.parent.id
this.$data.thirdparty.address = null;
}
} else {
this.thirdparty.kind = "company";
break;
case "firstName":
thirdparty.firstname = queryItem;
break;
}
}
function addQuery(query) {
thirdparty.name = query;
}
// Lifecycle
onMounted(() => {
let dependencies = [];
dependencies.push(loadCivilities());
if (props.action !== "create") {
if (props.id) {
dependencies.push(loadData());
}
},
};
if (props.action === "addContact") {
thirdparty.kind = "child";
thirdparty.address = null;
}
} else {
thirdparty.kind = "company";
}
});
</script>
<style lang="scss" scoped>

View File

@@ -155,3 +155,16 @@ Telephone2: Autre téléphone
Contact email: Courrier électronique du contact
Contact address: Adresse du contact
Contact profession: Profession du contact
thirdpartyMessages:
thirdparty:
firstname: "Prénom"
lastname: "Nom"
name: "Dénomination"
email: "Courriel"
phonenumber: "Téléphone"
phonenumber2: "Autre numéro de téléphone"
comment: "Commentaire"
profession: "Qualité"
civility: "Civilité"
child_of: "Contact de: "
children: "Personnes de contact: "