Commit bfa97f5a authored by Laurent Lecluse's avatar Laurent Lecluse
Browse files

WIP Suivi

parent 5de97182
Loading
Loading
Loading
Loading
+63 −9
Original line number Diff line number Diff line
@@ -29,14 +29,27 @@
                    <div class="num-jour badge bg-secondary rounded-circle">{{ jour < 10 ? '0' + jour.toString() : jour }}</div>
                </th>
                <td>
                    <div>
                        <div class="alert alert-info" v-for="event in eventsByJour(jour)">
                            <component :is="event.component" :event="event"/>
                    <div class="event" :style="'border-color:'+event.color" v-for="(event,index) in eventsByJour(jour)" :key="index">
                        <div class="event-content">
                            <component :is="event.component" :event="event"></component>
                        </div>
                        <div class="event-actions">
                            <div class="btn-group btn-group-sm">
                                <button class="btn btn-light" @click="editEvent" :data-index="index">
                                    <u-icon name="pen-to-square"/>
                                </button>
                                <button class="btn btn-light" @click="deleteEvent" :data-index="index">
                                    <u-icon name="trash-can" class="text-danger"/>
                                </button>
                            </div>
                        </div>
                    </div>

                    <div v-if="canAddEvent">
                        <button @click="addEvent" :data-jour="jour" class="btn btn-light btn-sm"><u-icon name="plus" /> Nouvel événement</button>
                        <button @click="addEvent" :data-jour="jour" class="btn btn-light btn-sm">
                            <u-icon name="plus"/>
                            Nouvel événement
                        </button>
                    </div>
                </td>
            </tr>
@@ -74,7 +87,7 @@ export default {
            let nombreJours = dateObj.getDate();

            return Array.from({length: nombreJours}, (v, k) => k + 1)
        }
        },
    },
    watch: {
        date: function (newVal, oldVal) { // watch it
@@ -137,11 +150,23 @@ export default {
        addEvent(event)
        {
            const dateObj = new Date(this.date);
            dateObj.setDate(event.target.dataset.jour);
            dateObj.setDate(event.currentTarget.dataset.jour);

            this.$emit('addEvent', dateObj);
        },

        editEvent(event)
        {
            const index = event.currentTarget.dataset.index;
            this.$emit('editEvent', this.events[index]);
        },

        deleteEvent(event)
        {
            const index = event.currentTarget.dataset.index;
            this.$emit('deleteEvent', this.events[index]);
        },

        prevMois()
        {
            const dateObj = new Date(this.date);
@@ -162,14 +187,14 @@ export default {
        {
            const dateObj = new Date(this.date);

            let res = [];
            let res = {};
            for (let e in this.events) {
                let event = this.events[e];
                if (event.date.getFullYear() === dateObj.getFullYear()
                    && event.date.getMonth() + 1 === dateObj.getMonth() + 1
                    && event.date.getDate() === jour
                ) {
                    res.push(event);
                    res[e] = event;
                }
            }
            return res;
@@ -180,8 +205,14 @@ export default {

<style scoped>

.table tr {
    background-color: #f4f4f4;
    border-left: 1px #ddd solid;
    border-right: 1px #ddd solid;
}

.table-hover tr:hover {
    background-color:lightyellow;
    background-color: #f7f7f7;
}

.recherche {
@@ -199,6 +230,7 @@ export default {

th.nom-jour {
    width: 1%;
    padding-left: 3px;
}

th.numero-jour {
@@ -211,4 +243,26 @@ th.numero-jour {
    padding-bottom: 5px;
}


.event {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 3px;
    border-left: 10px #bbb solid;
    border-right: 10px #bbb solid;
}

.event:hover {
    background-color: white;
}

.event-content {
    flex-grow: 1;
}

.event-actions {
    align-self: flex-start;
}

</style>
 No newline at end of file
+45 −0
Original line number Diff line number Diff line
<template>
    <div class="mb-2">
        <label :for="id ? id : name" class="form-label">{{ label }}</label>
        <input type="date" :name="name" :id="id ? id : name" class="form-control" v-model="dateVal" :disabled="disabled"/>
    </div>
</template>

<script>
export default {
    name: "UFormDate",
    props: {
        id: {type: String, required: false},
        name: {type: String, required: true},
        label: {type: String, required: true, default: 'Inconnu'},
        modelValue: {required: true, default: undefined},
        disabled: {type: Boolean, required: false, default: false},
    },
    data()
    {
        return {
            dateVal: undefined
        };
    },
    watch: {
        modelValue: function (val) {
            let value = val;
            if (val instanceof Date) {
                value = Util.dateToString(val);
            }
            if (val instanceof String) {
                value = val.slice(0, 10);
            }

            this.dateVal = value;
        },
        dateVal: function (val) {
            this.$emit("update:modelValue", new Date(val));
        },
    }
}
</script>

<style scoped>

</style>
 No newline at end of file
+1 −1
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ export default {
    methods: {
        ajout(event)
        {
            modAjax(event.target, (widget) => {
            modAjax(event.currentTarget, (widget) => {
                this.reload();
            });
        },
+10 −10
Original line number Diff line number Diff line
@@ -212,46 +212,46 @@ export default {
        },
        saisie(event)
        {
            modAjax(event.target, (widget) => {
            modAjax(event.currentTarget, (widget) => {
                this.refresh();
            });
        },
        supprimer(event)
        {
            popConfirm(event.target, (response) => {
            popConfirm(event.currentTarget, (response) => {
                this.$emit('supprimer', this.mission);
            });
        },
        valider(event)
        {
            popConfirm(event.target, (response) => {
            popConfirm(event.currentTarget, (response) => {
                this.$emit('refresh', response.data);
            });
        },
        devalider(event)
        {
            popConfirm(event.target, (response) => {
            popConfirm(event.currentTarget, (response) => {
                this.$emit('refresh', response.data);
            });
        },
        volumeHoraireSupprimer(event)
        {
            event.target.href = Util.url('mission/volume-horaire/supprimer/:missionVolumeHoraire', {missionVolumeHoraire: event.target.dataset.id});
            popConfirm(event.target, (response) => {
            event.currentTarget.href = Util.url('mission/volume-horaire/supprimer/:missionVolumeHoraire', {missionVolumeHoraire: event.currentTarget.dataset.id});
            popConfirm(event.currentTarget, (response) => {
                this.$emit('refresh', response.data);
            });
        },
        volumeHoraireValider(event)
        {
            event.target.href = Util.url('mission/volume-horaire/valider/:missionVolumeHoraire', {missionVolumeHoraire: event.target.dataset.id});
            popConfirm(event.target, (response) => {
            event.currentTarget.href = Util.url('mission/volume-horaire/valider/:missionVolumeHoraire', {missionVolumeHoraire: event.currentTarget.dataset.id});
            popConfirm(event.currentTarget, (response) => {
                this.$emit('refresh', response.data);
            });
        },
        volumeHoraireDevalider(event)
        {
            event.target.href = Util.url('mission/volume-horaire/devalider/:missionVolumeHoraire', {missionVolumeHoraire: event.target.dataset.id});
            popConfirm(event.target, (response) => {
            event.currentTarget.href = Util.url('mission/volume-horaire/devalider/:missionVolumeHoraire', {missionVolumeHoraire: event.currentTarget.dataset.id});
            popConfirm(event.currentTarget, (response) => {
                this.$emit('refresh', response.data);
            });
        },
+148 −96
Original line number Diff line number Diff line
<template>
    <u-calendar :date="date" @changeDate="changeDate" @addEvent="addVolumeHoraire" :events="realise"/>
    <u-modal id="suivi-form" title="Suivi">
    <u-calendar :date="date" @changeDate="changeDate" @addEvent="addVolumeHoraire" @editEvent="editVolumeHoraire" @deleteEvent="deleteVolumeHoraire"
                :can-add-event="true"
                :events="realise"/>
    <u-modal id="suivi-form" ref="suiviForm" title="Suivi">
        <template #body>
            <u-tabs :tab="vhr.type" @changeTab="changeTab" :tabs="{mission:'Mission',formation:'Formation',conges:'Congés'}">
                <template #mission>
            <div class="mb-2">
                <label for="mission" class="form-label">Mission</label>
                <select name="mission" id="mission" class="form-select" v-model="vhr.missionId">
@@ -12,13 +12,16 @@
            </div>

            <div class="row">
                        <div class="col-md-6">
                <div class="col-md-4">
                    <u-form-date name="date" label="Date" v-model="vhr.date" />
                </div>
                <div class="col-md-4">
                    <div class="mb-2">
                        <label for="horaire-debut" class="form-label">Horaire de début</label>
                        <input type="time" name="horaire-debut" id="horaire-debut" class="form-control" v-model="vhr.horaireDebut"/>
                    </div>
                </div>
                        <div class="col-md-6">
                <div class="col-md-4">
                    <div class="mb-2">
                        <label for="horaire-fin" class="form-label">Horaire de fin</label>
                        <input type="time" name="horaire-fin" id="horaire-fin" class="form-control" v-model="vhr.horaireFin"/>
@@ -26,51 +29,31 @@
                </div>
            </div>
            <div class="row">
                        <div class="col-md-6">
                <div class="col-md-4">
                    <div class="mb-2">
                        <label for="heures" class="form-label">Nombre d'heures</label>
                                <input type="number" step="0.01" name="heures" id="heures" class="form-control" v-model="vhr.heures"/>
                        <input type="number" step="0.01" min="0" name="heures" id="heures" class="form-control" v-model="vhr.heures"/>
                    </div>
                </div>
                        <div class="col-md-6">
                <div class="col-md-4">
                    <div class="mb-2">
                                <label class="form-label" for="nocturne">Horaire nocturne</label><br/>
                        <label class="form-label">&nbsp;</label>
                        <div class="form-check">
                            <label class="form-label" for="nocturne">Horaire nocturne</label>
                            <input type="checkbox" class="form-check-input" id="nocturne" v-model="vhr.nocturne"/>
                        </div>
                    </div>
                </div>
                    </div>

                </template>
                <template #formation>
                <div class="col-md-4">
                    <div class="mb-2">
                        <label for="heures-formation" class="form-label">Nombre d'heures</label>
                        <input type="number" step="0.01" name="heures-formation" id="heures-formation" class="form-control" v-model="vhr.heuresFormation"/>
                        <label class="form-label">&nbsp;</label>
                        <div class="form-check">
                            <label class="form-label" for="formation">formation</label>
                            <input type="checkbox" class="form-check-input" id="formation" v-model="vhr.formation"/>
                        </div>
                    </div>
                </div>
                </template>
                <template #conges>
                    <div>
                        <label for="periode-conges" class="form-label">Période des congés</label>
                    </div>
                    <div class="btn-group" role="group" aria-label="Période de congés">
                        <input type="radio" class="btn-check" autocomplete="off"
                               name="conges-periode" id="conges-matin" value="matin"
                               :checked="vhr.congesPeriode == 'matin'">
                        <label class="btn btn-outline-primary" for="conges-matin" @click="changeCongesPeriode" data-value="matin">Matin</label>

                        <input type="radio" class="btn-check" autocomplete="off"
                               name="conges-periode" id="conges-aprem" value="aprem"
                               :checked="vhr.congesPeriode == 'aprem'">
                        <label class="btn btn-outline-primary" for="conges-aprem" @click="changeCongesPeriode" data-value="aprem">Après-midi</label>

                        <input type="radio" class="btn-check" autocomplete="off"
                               name="conges-periode" id="conges-jour" value="jour"
                               :checked="vhr.congesPeriode == 'jour'">
                        <label class="btn btn-outline-primary" for="conges-jour" @click="changeCongesPeriode" data-value="jour">Toute la journée</label>
            </div>
                </template>
            </u-tabs>
            <div class="mb-2">
                <label for="description" class="form-label">Description</label>
                <textarea name="description" id="description" class="form-control" v-model="vhr.description"/>
@@ -79,7 +62,7 @@
            {{ vhr }}
        </template>
        <template #footer>
            <button class="btn btn-primary">Enregistrer</button>
            <button class="btn btn-primary" @click="saveVolumeHoraire">Enregistrer</button>
        </template>
    </u-modal>
</template>
@@ -88,48 +71,91 @@

import SuiviEvent from './SuiviEvent.vue';

// markRaw utile pour éviter de scanner les changements et préserver les perfs
import { markRaw } from "vue";

export default {
    name: 'Suivi',
    props: {
        intervenant: {type: Number, required: true},
        missions: {type: Array, required: true}
        missions: {type: Object, required: true}
    },
    mounted() {
        this.modal = new bootstrap.Modal(this.$refs.suiviForm.$el,{
            keyboard: false
        });
    },
    data()
    {
        return {
            date: new Date(),
            vhr: {
        const newVhr = {
            component: markRaw(SuiviEvent),
            color: 'yellow',
            date: null,
            missionId: null,
            horaireDebut: null,
            horaireFin: null,
                type: "mission",
                missionId: null,
                nocturne: false,
            heures: null,
                heuresFormation: null,
                congesPeriode: "jour",
            nocturne: false,
            formation: false,
            description: null,
            },
        };

        return {
            modal: null,
            date: new Date(),
            newVhr: newVhr,
            vhr: { ...this.newVhr}, // vhr = clone de newVhr
            vhrIndex: null,
            suiviForm: new Form({
                missionId: {required: true}
            }),
            realise: [
                {
                    component: SuiviEvent,
                    component: markRaw(SuiviEvent),
                    color: 'yellow',
                    date: new Date(2023, 1, 5),
                    texte: 'Coucou, le 50 février 2023',
                    missionId: null,
                    horaireDebut: null,
                    horaireFin: null,
                    heures: null,
                    nocturne: false,
                    formation: false,
                    description: '5',
                },
                {
                    component: SuiviEvent,
                    date: new Date(2023, 1, 5),
                    texte: 'Coucou, le 505 février 2023',
                    component: markRaw(SuiviEvent),
                    color: 'red',
                    date: new Date(2023, 1, 6),
                    missionId: null,
                    horaireDebut: null,
                    horaireFin: null,
                    heures: null,
                    nocturne: false,
                    formation: false,
                    description: '6',
                },
                {
                    component: SuiviEvent,
                    date: new Date(2023, 1, 6),
                    texte: 'Coucou, le 60 février 2023'
                    component: markRaw(SuiviEvent),
                    date: new Date(2023, 1, 7),
                    color: '#d5a515',
                    missionId: null,
                    horaireDebut: null,
                    horaireFin: null,
                    heures: null,
                    nocturne: false,
                    formation: false,
                    description: '7',
                },
                {
                    component: SuiviEvent,
                    date: new Date(2023, 2, 6),
                    texte: 'Coucou, le 6 mars 2023',
                    component: markRaw(SuiviEvent),
                    date: new Date(2023, 2, 8),
                    missionId: null,
                    horaireDebut: null,
                    horaireFin: null,
                    heures: null,
                    nocturne: false,
                    formation: false,
                    description: '8',
                },
            ]
        };
@@ -141,20 +167,46 @@ export default {
            this.date = dateObj;
        },

        changeTab(tab)
        addVolumeHoraire(dateObj)
        {
            this.vhr.type = tab;
            this.vhr = { ...this.newVhr };
            this.vhr.date = dateObj;
            this.vhrIndex = undefined;
            this.modal.show();
        },

        changeCongesPeriode(event)
        editVolumeHoraire(calEvent)
        {
            this.vhr.congesPeriode = event.target.dataset['value'];
            this.vhr = { ...calEvent }; // on clone pour éviter de modifier avant d'enregistrer
            this.vhrIndex = this.realise.indexOf(calEvent);

            this.modal.show();
        },

        addVolumeHoraire(dateObj)
        saveVolumeHoraire()
        {
            console.log(dateObj);
            let ok = true;

            if (this.suiviForm.isValid(this.vhr)){
                this.modal.hide();
                if (this.vhrIndex === undefined){
                    this.realise.push(this.vhr);
                }else{
                    this.realise[this.vhrIndex] = this.vhr;
                }
            }else{
                console.log(this.suiviForm.errors);
            }

            // reste le passage et le retour du serveur...
        },

        deleteVolumeHoraire(calEvent)
        {
            const index = this.realise.indexOf(calEvent);
            this.realise.splice(index,1);
            console.log(index);
            console.log(this.realise);
        },
    }
}
Loading