ldc-boutique-cnc/integration/resources/js/components/TimeSlotPicker.vue
Olivier Legat d93553b396 Squashed commit of the following:
commit a962eca9b609623804bd8cfe57c246a61e77a382
Author: Olivier Legat <olivier.legat@ldc.fr>
Date:   Thu Mar 4 17:41:46 2021 +0100

    responsive

commit a44ff3bde60c2af1db3169115a90741b8e868037
Author: Olivier Legat <olivier.legat@ldc.fr>
Date:   Wed Mar 3 17:50:58 2021 +0100

    end tunnel

commit 4c40e47ae861909f76b92b0440d48b378ee621c2
Author: Olivier Legat <olivier.legat@ldc.fr>
Date:   Tue Mar 2 18:10:17 2021 +0100

    heure de collecte

commit e05d598006060880f79573108e0c66fccfcfc62c
Author: Olivier Legat <olivier.legat@ldc.fr>
Date:   Mon Mar 1 17:47:48 2021 +0100

    tunnel page 3

commit b85f96a655e868096aa42e9f99b2f67c49a041c3
Author: Olivier Legat <olivier.legat@ldc.fr>
Date:   Fri Feb 26 13:16:05 2021 +0100

    Tunnel d'achat start

commit cdf9a38e8f5d38ffcc1728415f0b58b22ff455df
Author: Olivier Legat <olivier.legat@ldc.fr>
Date:   Thu Feb 25 20:35:44 2021 +0100

    cart full

commit 9db34a8ab6881b1b88adebaa6426b6944608de47
Author: Olivier Legat <olivier.legat@ldc.fr>
Date:   Wed Feb 24 17:40:18 2021 +0100

    work in progress - cart panel

commit 0a698cb62eb26b52f3b48f5ac8a39b89c34617f4
Author: Olivier Legat <olivier.legat@ldc.fr>
Date:   Tue Feb 23 17:05:13 2021 +0100

    sassification des css

commit 5c277ae10d9ae8e0225a0f7d57d81146e43da146
Author: Olivier Legat <olivier.legat@ldc.fr>
Date:   Tue Feb 23 16:37:01 2021 +0100

    integration bato
2021-03-05 11:49:20 +01:00

256 lines
9.5 KiB
Vue

<template>
<div class="timeslot-container">
<div class="calendar">
<h2><span @click="prevMonth()"><img src="/images/chevron_prev.svg"></span>{{ months[currentmonth] }} {{ currentyear }}<span @click="nextMonth()"><img src="/images/chevron_next.svg"></span></h2>
<header>
<div v-for="day in days">{{ short(day) }}</div>
</header>
<section class="content">
<div v-for="tile in tiles" :class="style(tile)" @click="showCreneaux(tile)">
<span>{{ getday(tile.date) }}</span>
</div>
</section>
</div>
<div class="creneaux">
<header>Horaires disponibles le {{selectedDay}}</header>
<section class="creneaux__list">
<div class="scroll-up" @click="scroll('up')" :class="{active: (this.scrollCounter>0)}"><img src="/images/chevron_up.svg"></div>
<section class="creneaux__slots" ref="creneaux__slots" :class="{hasDown: (creneaux.length>3 && this.scrollCounter<(creneaux.length/2-1)), hasUp: (this.scrollCounter>0)}">
<div v-for="(creneau,index) in creneaux" :class="styleCren(creneau)" @click="selectSlot(creneau)" ref="cren" :key="index">
<span>{{creneau.horaire}}</span>
</div>
</section>
<div class="scroll-down" @click="scroll('down')" :class="{active: (creneaux.length>3 && this.scrollCounter<(creneaux.length/2-1)) }"><img src="/images/chevron_down.svg"></div>
</section>
</div>
</div>
</template>
<script>
export default {
props: {
day: {
type: Number,
default: function() {
return new Date().getDay();
}
},
month : {
type: Number,
default: function() {
return new Date().getMonth();
}
},
year : {
type: Number,
default: function() {
return new Date().getFullYear();
}
},
weekend: {
type: Array,
default: function() {
return [5,6];
}
},
days: {
type: Array,
default : function() {
return ['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche'];
}
},
months: {
type: Array,
default: function() {
return ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octore', 'Novembre', 'Décembre'];
}
},
maxtiles: {
type: Number,
default : 34 //soit 5 semaines
},
defaultCreneaux: {
type: Array,
default: function() {
var x = 15; //minutes interval
var times = []; // time array
var tt = 0; // start time
var ap = ['AM', 'PM']; // AM-PM
//loop to increment the time and push results in array
for (var i=0;tt<24*60; i++) {
var hh = Math.floor(tt/60); // getting hours of day in 0-24 format
var mm = (tt%60); // getting minutes of the hour in 0-55 format
times[i] = ("0" + hh).slice(-2) + ':' + ("0" + mm).slice(-2) //+ ap[Math.floor(hh/12)]; // pushing data in array in [00:00 - 12:00 AM/PM format]
tt = tt + x;
}
return times;
}
},
dbavailablecreneaux: {
type: String,
},
showOnlyAvailables: {
type: Boolean,
default: false
}
},
computed: {
date() { return new Date(this.currentyear, this.currentmonth, 1);},
startday() {return this.date.getDay() < 1 ? 6 : this.date.getDay() - 1;},
dayscount() {return new Date(this.currentyear, this.currentmonth + 1, 0).getDate();},
tiles() { return this.prepare(); },
creneaux: {
get: function(){ return this.listCreneaux(); },
}
},
watch: {
},
data() {
return {
currentmonth: null,
currentyear: this.year,
selectedDay : new Date().toLocaleDateString(),
selectedCreneau : null,
current: new Date(),
availableCreneaux: [],
scrollCounter: 0,
}
},
mounted() {
this.availableCreneaux = JSON.parse(this.dbavailablecreneaux);
//this.availableCrenaux = this.dbavailablecreneaux;
this.selectedDay = this.current.toLocaleDateString();
this.currentmonth = this.month; //this.months.indexOf(this.month);
},
methods: {
nextMonth() {
if(this.currentmonth == 11) {
this.currentmonth = 0;
this.currentyear+=1;
} else {
this.currentmonth+=1;
}
},
prevMonth() {
if(this.currentmonth == 0) {
this.currentmonth = 11;
this.currentyear-=1;
} else {
this.currentmonth-=1;
}
},
short(value) { return value.substring(0, 3) },
getday(value) { return new Date(value).getDate() },
style(tile) {
return {
'last': tile.last,
'next': tile.next,
'current': tile.current,
'selected' : tile.selected,
'grey': tile.grey
}
},
styleCren(creneau) {
return {
'dispo' : creneau.dispo,
'selected' : creneau.selected
}
},
prepare() {
let before = [];
let current = [];
let daycount = 1;
for (let i = 0; i <= this.maxtiles; i++) {
let date = new Date(this.currentyear, this.currentmonth, (i < this.startday) ? -i : daycount);
let day = date.getDay() < 1 ? 6 : date.getDay() - 1;
let obj = {
//this day is from lastmonth
last: (i < this.startday) ? true : false,
//this day is next month
next: i >= this.dayscount + this.startday,
//this is a weekend day
grey: this.weekend.find((item) => item === day) ? true : false,
//this is today
current: (new Date(this.currentyear, this.currentmonth, daycount).toDateString() == this.current.toDateString()) ? true : false,
//selected
selected: (date.toLocaleDateString() == this.selectedDay) ? true : false,
//this tile's date
date: date
};
if (i < this.startday)
before.push(obj);
else {
current.push(obj);
daycount++;
}
}
return before.reverse().concat(current);
},
showCreneaux(tile){
this.selectedDay = tile.date.toLocaleDateString();
//this.selectedCreneau = null;
//this.creneaux = this.listCreneaux();
},
selectSlot(creneau){
this.selectedCreneau = this.selectedDay+"-"+creneau.horaire;
},
listCreneaux() {
let todaysAvailable = [];
if(this.selectedDay in this.availableCreneaux) {
todaysAvailable = this.availableCreneaux[""+this.selectedDay];
}
let crens = [];
//filtrer les créneaux dispos
this.defaultCreneaux.forEach(element => {
let obj = {
//day: index,
horaire: element,
dispo: todaysAvailable.includes(element),
selected: (this.selectedCreneau == this.selectedDay+"-"+element) ? true : false
};
//option pour ne générer que les créneaux disponibles
if(this.showOnlyAvailables) {
if (obj.dispo) {
crens.push(obj);
}
} else {
crens.push(obj);
}
});
return crens;
},
//animation
scroll(way) {
if (way == 'down') {
//ici on limite le nombre de click down
//1 er click on scroll 2 crans
//2 eme click on scroll 2 crans, etx
//et on démarre à 0 donc, -1
if (this.scrollCounter < (this.creneaux.length/2)-1) {
this.scrollCounter = this.scrollCounter + 1;
this.fixScrolling();
}
} else if (way == 'up') {
if (this.scrollCounter > 0) {
this.scrollCounter = this.scrollCounter - 1;
this.fixScrolling()
}
}
},
fixScrolling(){
const divH = this.$refs.cren[this.scrollCounter].clientHeight;
if(this.scrollCounter==1) {
//cas du premier on va faire apparaite le bouton pour remonter, et réduire la taille du viewport de l'element
this.$refs.creneaux__slots.scrollTop = divH * this.scrollCounter + divH;
} else {
this.$refs.creneaux__slots.scrollTop = 2 * divH * this.scrollCounter;
}
},
}
}
</script>