github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/server/frontend/bv/src/shared/fields/DateField.vue (about) 1 <template> 2 <b-form-group 3 :label="label" 4 :invalid-feedback="invalidFeedback" 5 :state="state" 6 > 7 <b-form-row> 8 <b-col cols="4"> 9 <b-form-input 10 type="number" 11 placeholder="JJ" 12 required 13 min="1" 14 max="31" 15 v-model.number="date.day" 16 @change="onInput" 17 :disabled="disabled" 18 > 19 </b-form-input> 20 </b-col> 21 <b-col cols="4"> 22 <b-form-input 23 type="number" 24 placeholder="MM" 25 required 26 min="1" 27 max="12" 28 v-model.number="date.month" 29 @change="onInput" 30 :disabled="disabled" 31 > 32 </b-form-input> 33 </b-col> 34 <b-col cols="4"> 35 <b-form-input 36 type="number" 37 placeholder="AAAA" 38 min="1900" 39 max="2100" 40 required 41 v-model.number="date.year" 42 @change="onInput" 43 :disabled="disabled" 44 ref="year" 45 > 46 </b-form-input> 47 </b-col> 48 </b-form-row> 49 </b-form-group> 50 </template> 51 52 <script lang="ts"> 53 import Vue from "vue"; 54 import Component from "vue-class-component"; 55 import { isNullTime } from "../logic/utils"; 56 import { Watch } from "vue-property-decorator"; 57 import { BFormInput } from "bootstrap-vue"; 58 import { Date_ } from "../logic/types"; 59 60 const DateFieldProps = Vue.extend({ 61 props: { 62 dateString: (String as unknown) as () => Date_, 63 label: String, 64 invalidFeedback: String, 65 required: Boolean, 66 checkMajeur: Boolean, 67 validated: Boolean, 68 disabled: Boolean 69 }, 70 model: { 71 prop: "dateString", 72 event: "change" 73 } 74 }); 75 76 interface InnerDate { 77 day: number | null; 78 month: number | null; 79 year: number | null; 80 } 81 82 @Component({}) 83 export default class DateField extends DateFieldProps { 84 date: InnerDate = this.parseDate(); 85 86 $refs!: { 87 year: HTMLInputElement; 88 }; 89 90 @Watch("dateString") 91 onChange() { 92 this.date = this.parseDate(); 93 } 94 95 parseDate() { 96 if (isNullTime(this.dateString)) { 97 return { day: null, month: null, year: null }; 98 } 99 const d = new Date(this.dateString); 100 101 return { 102 day: d.getDate(), 103 month: d.getMonth() + 1, 104 year: d.getFullYear() 105 }; 106 } 107 108 get state() { 109 if (!this.validated) return null; 110 if (this.required || this.checkMajeur) { 111 if (this.currentDate == null) return false; 112 if (this.checkMajeur) { 113 return this.age(this.currentDate) >= 18; 114 } 115 } 116 return true; 117 } 118 119 age(date: Date) { 120 const diff = new Date(Date.now() - date.valueOf()); 121 diff.setHours(0, 0, 0, 0); // attention au jour d'anniversaire 122 return diff.getFullYear() - 1970; 123 } 124 125 get currentDate(): Date | null { 126 if (!(this.date.year && this.date.month && this.date.day)) return null; 127 return new Date( 128 Date.UTC(this.date.year, this.date.month - 1, this.date.day) 129 ); 130 } 131 132 onInput() { 133 // reset custom validity 134 this.$refs.year.setCustomValidity(""); 135 136 if (this.currentDate == null) return; // date en train d'être tappée 137 138 if (this.checkMajeur) { 139 this.$refs.year.setCustomValidity( 140 this.state === false ? "not-majeur" : "" 141 ); 142 } 143 let v = ""; 144 if (!isNaN(this.currentDate.getTime())) { 145 v = this.currentDate.toISOString().split("T")[0]; 146 } 147 this.$emit("change", v); 148 } 149 } 150 </script> 151 152 <style scoped></style>