|
|
@@ -1,131 +1,138 @@
|
|
|
<template>
|
|
|
<div>
|
|
|
<h3 class="center-align">Modifier un créneau</h3>
|
|
|
- <div class="row center-align">
|
|
|
- <a class="btn-small" v-on:click="emitCreationOrder"
|
|
|
- ><i class="material-icons right">create</i>Nouveau</a
|
|
|
- >
|
|
|
- <a
|
|
|
- class="btn-small"
|
|
|
+ <div class="actions">
|
|
|
+ <button class="btn small primary" v-on:click="emitCreationOrder">
|
|
|
+ <i class="material-icons right">create</i>Nouveau
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ class="btn small primary"
|
|
|
:class="{ disabled: creneau === undefined }"
|
|
|
v-on:click="emitDuplicateOrder"
|
|
|
- ><i class="material-icons right">content_copy</i>Dupliquer</a
|
|
|
>
|
|
|
- <a
|
|
|
- class="btn-small red"
|
|
|
+ <i class="material-icons right">content_copy</i>Dupliquer
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ class="btn small error"
|
|
|
:class="{ disabled: creneau === null }"
|
|
|
v-on:click="emitDeleteOrder"
|
|
|
- style="margin-top: 4px"
|
|
|
- ><i class="material-icons right">delete_forever</i>Supprimer</a
|
|
|
>
|
|
|
+ <i class="material-icons right">delete_forever</i>Supprimer
|
|
|
+ </button>
|
|
|
</div>
|
|
|
<div class="center-align" v-if="creneau === undefined">Veuillez selectioner un creneau.</div>
|
|
|
<form v-else>
|
|
|
- <div class="input-field col s12">
|
|
|
- <input
|
|
|
- id="last_name"
|
|
|
- type="text"
|
|
|
- class="validate"
|
|
|
- value="creneau.title"
|
|
|
- @input="inputListener('title')"
|
|
|
- />
|
|
|
- <label for="last_name">Titre</label>
|
|
|
- </div>
|
|
|
+ <styled-input
|
|
|
+ label="Titre"
|
|
|
+ id="last_name"
|
|
|
+ type="text"
|
|
|
+ :modelValue="creneau.title"
|
|
|
+ @input="inputListener($event, 'title')"
|
|
|
+ />
|
|
|
+ <styled-input
|
|
|
+ class="small"
|
|
|
+ label="Date"
|
|
|
+ id="creneauDate"
|
|
|
+ type="text"
|
|
|
+ placeholder="yyyy-mm-dd"
|
|
|
+ v-model.lazy="jour"
|
|
|
+ />
|
|
|
+ <styled-input
|
|
|
+ class="small"
|
|
|
+ label="Heure"
|
|
|
+ id="creneauHeure"
|
|
|
+ type="text"
|
|
|
+ placeholder="hh:mm"
|
|
|
+ v-model.lazy="heure"
|
|
|
+ />
|
|
|
+ <styled-input
|
|
|
+ class="small"
|
|
|
+ label="Durée (min)"
|
|
|
+ id="creneauDuree"
|
|
|
+ type="number"
|
|
|
+ v-model.lazy="duree"
|
|
|
+ />
|
|
|
+ <styled-input
|
|
|
+ class="small"
|
|
|
+ label="Heure fin"
|
|
|
+ id="disabled"
|
|
|
+ type="text"
|
|
|
+ :modelValue="endHour"
|
|
|
+ disabled
|
|
|
+ />
|
|
|
+ <styled-input
|
|
|
+ class="small"
|
|
|
+ label="Bénévole minimum"
|
|
|
+ id="minAttendee"
|
|
|
+ type="number"
|
|
|
+ :modelValue="creneau.minAttendee"
|
|
|
+ @input="inputListener($event, 'minAttendee')"
|
|
|
+ />
|
|
|
+ <styled-input
|
|
|
+ class="small"
|
|
|
+ label="Bénévole minimum"
|
|
|
+ id="minAttendee"
|
|
|
+ type="number"
|
|
|
+ :optional="true"
|
|
|
+ :modelValue="creneau.maxAttendee"
|
|
|
+ @input="inputListener($event, 'maxAttendee')"
|
|
|
+ />
|
|
|
+ <styled-input
|
|
|
+ label="Pénibilité"
|
|
|
+ id="penibility"
|
|
|
+ type="number"
|
|
|
+ class="small"
|
|
|
+ :modelValue="creneau.penibility"
|
|
|
+ @input="inputListener($event, 'penibility')"
|
|
|
+ />
|
|
|
|
|
|
- <div class="input-field col s6">
|
|
|
- <input id="creneauDate" type="text" class="datepicker" v-model.lazy="jour" />
|
|
|
- <label for="creneauDate">Date</label>
|
|
|
- </div>
|
|
|
- <div class="input-field col s3">
|
|
|
- <input id="creneauHeure" type="text" class="timepicker" v-model.lazy="heure" />
|
|
|
- <label for="creneauHeure">Heure</label>
|
|
|
- </div>
|
|
|
- <div class="input-field col s3">
|
|
|
- <input id="creneauDuree" type="number" class="validate" v-model="duree" />
|
|
|
- <label for="creneauDuree">Duree (min)</label>
|
|
|
- </div>
|
|
|
- <div class="input-field col s6">
|
|
|
- <input
|
|
|
- id="penibility"
|
|
|
- type="number"
|
|
|
- class="validate"
|
|
|
- :value="creneau.penibility"
|
|
|
- @input="inputListener('penibility')"
|
|
|
- />
|
|
|
- <label for="penibility">Pénébilité</label>
|
|
|
- </div>
|
|
|
- <div class="input-field col s3">
|
|
|
- <input disabled id="disabled" type="text" class="validate" v-model="endHour" />
|
|
|
- <label for="disabled">Heure fin</label>
|
|
|
- </div>
|
|
|
- <div class="input-field col s6">
|
|
|
- <input
|
|
|
- id="minAttendee"
|
|
|
- type="number"
|
|
|
- class="validate"
|
|
|
- :value="creneau.minAttendee"
|
|
|
- @input="inputListener('minAttendee')"
|
|
|
- />
|
|
|
- <label for="minAttendee">Bénévole minimum</label>
|
|
|
- </div>
|
|
|
- <div class="input-field col s6">
|
|
|
- <input
|
|
|
- id="maxAttendee"
|
|
|
- type="number"
|
|
|
- class="validate"
|
|
|
- :value="creneau.maxAttendee"
|
|
|
- @input="inputListener('maxAttendee')"
|
|
|
- />
|
|
|
- <label for="maxAttendee">Bénévole maximum (opt)</label>
|
|
|
- </div>
|
|
|
- <div class="input-field col s12">
|
|
|
- <textarea
|
|
|
- id="description"
|
|
|
- type="text"
|
|
|
- class="materialize-textarea"
|
|
|
- v-model="creneau.description"
|
|
|
- ></textarea>
|
|
|
- <label for="description">Description</label>
|
|
|
- </div>
|
|
|
- <div class="col s12">
|
|
|
- <chips-input
|
|
|
- title="Compétences & préférences associées"
|
|
|
- id="compétence_selection"
|
|
|
- place-holder="Choisir une condition"
|
|
|
- secondary-placeholder="+ compétence"
|
|
|
- :autocomplete-list="autocompleteCompetencesList"
|
|
|
- :strict-autocomplete="true"
|
|
|
- :value="creneau.competencesIdList"
|
|
|
- @input="inputListener('competencesIdList')"
|
|
|
- ></chips-input>
|
|
|
- </div>
|
|
|
- <div class="col s12">
|
|
|
- <chips-input
|
|
|
- title="Bénévoles"
|
|
|
- id="bénevole_selection"
|
|
|
- place-holder="Choisir un bénévole"
|
|
|
- secondary-placeholder="+ bénévole"
|
|
|
- :autocomplete-list="autocompleteBenevolesList"
|
|
|
- :strict-autocomplete="true"
|
|
|
- :value="creneau.benevoleIdList"
|
|
|
- @input="inputListener('benevoleIdList')"
|
|
|
- ></chips-input>
|
|
|
- </div>
|
|
|
+ <styled-input
|
|
|
+ label="Description"
|
|
|
+ id="description"
|
|
|
+ type="textarea"
|
|
|
+ class="materialize-textarea"
|
|
|
+ :modelValue="creneau.description"
|
|
|
+ @input="inputListener($event, 'description')"
|
|
|
+ >
|
|
|
+ </styled-input>
|
|
|
+ <chips-input
|
|
|
+ label="Compétences & préférences associées"
|
|
|
+ id="compétence_selection"
|
|
|
+ placeholder="Choisir une condition"
|
|
|
+ secondary-placeholder="+ compétence"
|
|
|
+ :autocomplete-list="autocompleteCompetencesList"
|
|
|
+ :strict-autocomplete="true"
|
|
|
+ :value="creneau.competencesIdList"
|
|
|
+ @input="inputListener($event, 'competencesIdList')"
|
|
|
+ ></chips-input>
|
|
|
+ <chips-input
|
|
|
+ label="Bénévoles"
|
|
|
+ id="bénevole_selection"
|
|
|
+ placeholder="Choisir un bénévole"
|
|
|
+ secondary-placeholder="+ bénévole"
|
|
|
+ :autocomplete-list="autocompleteBenevolesList"
|
|
|
+ :strict-autocomplete="true"
|
|
|
+ :value="creneau.benevoleIdList"
|
|
|
+ @input="inputListener($event, 'benevoleIdList')"
|
|
|
+ ></chips-input>
|
|
|
</form>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts">
|
|
|
-import { defineComponent } from "vue";
|
|
|
+import { defineComponent, PropType } from "vue";
|
|
|
import Creneau from "@/models/Creneau";
|
|
|
-import { MutationTypes } from "@/store/Mutations";
|
|
|
import AutocompleteOptions from "@/models/AutocompleteOptions";
|
|
|
+import styledInput from "./input.vue";
|
|
|
+import chipsInput from "../components/SelectChipInput.vue";
|
|
|
+import dayjs from "dayjs";
|
|
|
|
|
|
export default defineComponent({
|
|
|
name: "EditeurCreneau",
|
|
|
+ components: { "chips-input": chipsInput, styledInput },
|
|
|
props: {
|
|
|
- creneauId: {
|
|
|
- type: String,
|
|
|
+ creneau: {
|
|
|
+ type: Object as PropType<Creneau>,
|
|
|
},
|
|
|
},
|
|
|
data: function () {
|
|
|
@@ -136,7 +143,10 @@ export default defineComponent({
|
|
|
};
|
|
|
},
|
|
|
watch: {
|
|
|
- creneauId() {
|
|
|
+ "creneau.start": function () {
|
|
|
+ this.updateForm();
|
|
|
+ },
|
|
|
+ "creneau.end": function () {
|
|
|
this.updateForm();
|
|
|
},
|
|
|
jour: function () {
|
|
|
@@ -153,21 +163,30 @@ export default defineComponent({
|
|
|
duration(): number {
|
|
|
return parseFloat(this.duree) ?? 0;
|
|
|
},
|
|
|
- formStartTime(): number {
|
|
|
- const input = this.jour + "T" + this.heure;
|
|
|
- return new Date(input).getTime();
|
|
|
+ concatStart(): string {
|
|
|
+ return (
|
|
|
+ this.jour +
|
|
|
+ "T" +
|
|
|
+ this.heure
|
|
|
+ .split(":")
|
|
|
+ .map((c) => ("0" + c).slice(-2))
|
|
|
+ .join(":")
|
|
|
+ );
|
|
|
+ },
|
|
|
+ validStart(): boolean {
|
|
|
+ return /\d{4}-\d{1,2}-\d{1,2}/.test(this.jour) && dayjs(this.concatStart).isValid();
|
|
|
},
|
|
|
- endStartTime(): number {
|
|
|
- return this.formStartTime + this.duration * 60 * 1000;
|
|
|
+ startDate(): Date {
|
|
|
+ return new Date(this.concatStart);
|
|
|
+ },
|
|
|
+ endDate(): Date {
|
|
|
+ return dayjs(this.startDate).add(this.duration, "m").toDate();
|
|
|
},
|
|
|
endHour(): string {
|
|
|
- return new Date(this.endStartTime).toLocaleTimeString().substring(0, 5);
|
|
|
+ return this.endDate.toTimeString().substring(0, 5);
|
|
|
},
|
|
|
validDuree(): boolean {
|
|
|
- return isNaN(parseInt(this.duree));
|
|
|
- },
|
|
|
- creneau(): Creneau | undefined {
|
|
|
- return this.$store.getters.getCreneauById(this.creneauId || "");
|
|
|
+ return !isNaN(parseFloat(this.duree));
|
|
|
},
|
|
|
autocompleteBenevolesList(): Array<AutocompleteOptions> {
|
|
|
return this.$store.state.benevoleList.map((benevole) => {
|
|
|
@@ -182,31 +201,34 @@ export default defineComponent({
|
|
|
},
|
|
|
methods: {
|
|
|
updateDates: function (): void {
|
|
|
- if (this.creneauId) {
|
|
|
- this.updateCreneau("start", new Date(this.formStartTime));
|
|
|
- this.updateCreneau("end", new Date(this.endStartTime));
|
|
|
+ if (this.creneau && this.validDuree && this.validStart) {
|
|
|
+ if (Math.abs(this.startDate.getTime() - this.creneau.start.getTime()) > 1000)
|
|
|
+ this.updateCreneau("start", this.startDate);
|
|
|
+ if (Math.abs(this.endDate.getTime() - this.creneau.end.getTime()) > 1000)
|
|
|
+ this.updateCreneau("end", this.endDate);
|
|
|
}
|
|
|
},
|
|
|
updateCreneau<K extends keyof Creneau>(field: K, value: Creneau[K]) {
|
|
|
- if (this.creneauId)
|
|
|
- this.$store.commit(MutationTypes.editCreneau, {
|
|
|
- id: this.creneauId,
|
|
|
+ if (this.creneau) {
|
|
|
+ const payload = {
|
|
|
+ id: this.creneau.id,
|
|
|
field: field,
|
|
|
value: value,
|
|
|
- });
|
|
|
+ };
|
|
|
+ this.$emit("edit", payload);
|
|
|
+ }
|
|
|
},
|
|
|
- inputListener(field: keyof Creneau): (e: InputEvent) => void {
|
|
|
- return (e: InputEvent) => {
|
|
|
- this.updateCreneau(field, (e.target as HTMLInputElement).value);
|
|
|
- };
|
|
|
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
+ inputListener(event: any, field: keyof Creneau) {
|
|
|
+ this.updateCreneau(field, event.target.value);
|
|
|
},
|
|
|
updateForm: function () {
|
|
|
if (this.creneau) {
|
|
|
- const startDate = this.creneau.event.start;
|
|
|
- this.jour = startDate.toISOString().substr(0, 10);
|
|
|
- this.heure = startDate.toTimeString().substr(0, 5);
|
|
|
+ const startDate = dayjs(this.creneau.start);
|
|
|
+ this.jour = startDate.format("YYYY-MM-DD");
|
|
|
+ this.heure = startDate.format("HH:mm");
|
|
|
this.duree = Math.round(
|
|
|
- (this.creneau.event.end.getTime() - this.creneau.event.start.getTime()) / 1000 / 60
|
|
|
+ (this.creneau.end.getTime() - this.creneau.start.getTime()) / 1000 / 60
|
|
|
).toString();
|
|
|
}
|
|
|
},
|
|
|
@@ -220,7 +242,36 @@ export default defineComponent({
|
|
|
this.$emit("delete", this.creneau);
|
|
|
},
|
|
|
},
|
|
|
+ mounted() {
|
|
|
+ this.updateForm();
|
|
|
+ },
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
-<style scoped></style>
|
|
|
+<style scoped>
|
|
|
+.actions {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+.actions > * {
|
|
|
+ margin: 8px;
|
|
|
+}
|
|
|
+.small {
|
|
|
+ max-width: calc(50% - 8px);
|
|
|
+}
|
|
|
+form > * {
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+form {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ flex-wrap: wrap;
|
|
|
+}
|
|
|
+h3 {
|
|
|
+ margin-top: 0px;
|
|
|
+ margin-bottom: 8px;
|
|
|
+}
|
|
|
+.formcontrol:not(:last-child) {
|
|
|
+ margin-bottom: 4px;
|
|
|
+}
|
|
|
+</style>
|