Преглед на файлове

deploy dateTimePicker & cleanPlanning

tripeur преди 4 години
родител
ревизия
806ac4aeee
променени са 5 файла, в които са добавени 164 реда и са изтрити 88 реда
  1. 1 37
      src/App.vue
  2. 34 0
      src/assets/css/main.css
  3. 48 36
      src/components/date-picker.vue
  4. 1 0
      src/components/input.vue
  5. 80 15
      src/views/Home.vue

+ 1 - 37
src/App.vue

@@ -133,7 +133,6 @@ export default defineComponent({
       }
     },
     importJsonState(obj: StateJSON, preserve = false) {
-      console.log(obj);
       // Remove previous content and load the main event title
       if (preserve == false) {
         this.$store.commit(MutationTypes.resetState, undefined);
@@ -197,39 +196,4 @@ export default defineComponent({
 });
 </script>
 
-<style>
-.modal {
-  display: flex;
-  justify-content: center;
-  position: fixed;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  background: rgba(0, 0, 0, 0.5);
-  z-index: 100;
-}
-.modal-content {
-  background: white;
-  padding: 16px 32px;
-  margin-top: 100px;
-  height: min-content;
-  border-radius: 2px;
-}
-.spinner {
-  color: var(--color-accent-400);
-  text-align: center;
-}
-.spinner > .material-icons {
-  font-size: 3rem;
-  animation: spin 2s linear infinite;
-}
-@keyframes spin {
-  0% {
-    transform: rotateZ(360deg);
-  }
-  100% {
-    transform: rotateZ(0deg);
-  }
-}
-</style>
+<style></style>

+ 34 - 0
src/assets/css/main.css

@@ -183,3 +183,37 @@ body {
 .formcontrol--success .formcontrol-help {
   color: #08875b;
 }
+.modal {
+  display: flex;
+  justify-content: center;
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: rgba(0, 0, 0, 0.5);
+  z-index: 100;
+}
+.modal-content {
+  background: white;
+  padding: 16px 32px;
+  margin-top: 100px;
+  height: min-content;
+  border-radius: 2px;
+}
+.spinner {
+  color: var(--color-accent-400);
+  text-align: center;
+}
+.spinner > .material-icons {
+  font-size: 3rem;
+  animation: spin 2s linear infinite;
+}
+@keyframes spin {
+  0% {
+    transform: rotateZ(360deg);
+  }
+  100% {
+    transform: rotateZ(0deg);
+  }
+}

+ 48 - 36
src/components/date-picker.vue

@@ -1,12 +1,14 @@
 <template>
-  <div class="formcontrol date-input-control">
+  <div class="formcontrol date-input-control" :class="{ 'formcontrol--error': !isValid }">
     <div class="formcontrol-label">{{ label }}</div>
     <div class="input-wrapper" @click="openPicker">
       <input
         class="date-input"
+        :class="{ 'date-input--invalid': !isValid }"
         type="text"
-        placeholder="yyyy/mm/dd"
+        :placeholder="placeholder"
         v-model="textValue"
+        @change="parseNewText"
         @focus="openPicker"
       />
     </div>
@@ -165,8 +167,9 @@ export default defineComponent({
     },
   },
   data: function () {
-    const now = dayjs().startOf("day");
+    const now = dayjs();
     return {
+      isValid: true,
       today: now,
       currentMonth: now.startOf("month"),
       zoom: "month" as "day" | "month" | "year" | "decade",
@@ -177,6 +180,9 @@ export default defineComponent({
     };
   },
   computed: {
+    placeholder(): string {
+      return "yyyy/mm/dd" + (this.target == "hour" ? " HH:mm" : "");
+    },
     currentZoomParameter(): ZoomParameter {
       return datepickerParameter[this.zoom];
     },
@@ -210,39 +216,23 @@ export default defineComponent({
   watch: {
     modelValue: function (val) {
       if (["object", "string", "number"].includes(typeof val)) {
-        this.valueObject = dayjs(val);
-      }
-    },
-    textValue: function (val, oldVal) {
-      const l = val.length;
-      if (l > 10 || !/^[0-9/]*$/.test(val)) {
-        this.textValue = val === "Invalid Date" ? "" : val.slice(0, 10);
-      }
-      if (l < oldVal.length) {
-        this.textValue = oldVal.charAt(oldVal.length - 1) === "/" ? val.slice(0, -1) : val;
-      } else if ([4, 7].includes(l)) {
-        this.textValue = val + "/";
-      }
-      if (/^\d{4}/.test(val)) {
-        this.currentMonth = this.currentMonth.year(parseInt(val.slice(0, 4)));
-      }
-      const re = /\/(0?[0-9]|(?:1[0-2]))\//.exec(val);
-      if (re) {
-        this.currentMonth = this.currentMonth.month(parseInt(re[1]) - 1);
-      }
-      if (this.textRegex.test(val)) {
-        this.valueObject = dayjs(val, "YYYY/M/D");
+        const d = dayjs(val);
+        if (!this.valueObject?.isSame(d)) {
+          this.valueObject = dayjs(val);
+        }
       }
     },
-    valueObject: function (v) {
-      if (v) {
-        this.textValue = v.format("YYYY/MM/DD");
-        this.$emit("update:modelValue", this.textValue);
+    valueObject(v: Dayjs) {
+      if (v.isValid()) {
+        this.currentMonth = v;
         if (this.target == "day") {
+          this.textValue = v.format("YYYY/MM/DD");
           this.zoom = "month";
         } else {
+          this.textValue = v.format("YYYY/MM/DD HH:mm");
           this.zoom = "day";
         }
+        this.$emit("update:modelValue", v);
       } else {
         this.textValue = "";
       }
@@ -262,6 +252,26 @@ export default defineComponent({
     isOut(d: Dayjs): boolean {
       return this.currentZoomParameter.outOfCurrentZoom(this.currentMonth, d);
     },
+    inputEventLintener(event: InputEvent) {
+      this.parseNewText((event.target as HTMLInputElement).value);
+    },
+    parseNewText(newValue: string) {
+      let candidate: Dayjs | null = null;
+      if (this.target == "day") {
+        candidate = dayjs(newValue, "YYYY/M/D");
+      } else {
+        candidate = dayjs(newValue, "YYYY/M/D HH:mm");
+      }
+      if (candidate && candidate.isValid() && !this.valueObject?.isSame(candidate)) {
+        this.valueObject = candidate;
+        this.isValid = true;
+      }
+      if (candidate && !candidate.isValid()) {
+        this.isValid = false;
+      } else {
+        this.isValid = true;
+      }
+    },
     selectItem: function (i: number): void {
       const d = this.pickerContent[i];
       if (
@@ -302,13 +312,7 @@ export default defineComponent({
         window.removeEventListener("focusin", this.loseFocusListener);
         window.removeEventListener("click", this.loseFocusListener);
         this.isPickerOpen = false;
-        const d = dayjs(this.textValue, "YYYY/MM/DD");
-        if (d.isValid()) {
-          this.valueObject = d;
-          this.textValue = d.format("YYYY/MM/DD");
-        } else {
-          this.$emit("update:modelValue", "");
-        }
+        this.parseNewText(this.textValue);
       }
     },
   },
@@ -318,6 +322,7 @@ export default defineComponent({
         this.valueObject = dayjs(this.modelValue);
       }
     }
+    this.zoom = "month";
   },
 });
 </script>
@@ -379,6 +384,13 @@ export default defineComponent({
 .date-input[type="text"]:hover + .datepicker-container {
   display: block;
 }
+.date-input--invalid {
+  box-shadow: 0 -1px 0 0 #e93255 inset !important;
+}
+[type="text"].date-input--invalid:focus {
+  box-shadow: 0 0 0 2px #e93255 !important;
+  border-bottom: 0;
+}
 .datepicker-container {
   position: absolute;
   width: 315px;

+ 1 - 0
src/components/input.vue

@@ -19,6 +19,7 @@
       <input
         v-else
         class="input"
+        :class="inputClass"
         id="id"
         :type="type"
         :placeholder="placeholder"

+ 80 - 15
src/views/Home.vue

@@ -8,14 +8,8 @@
         :modelValue="evenement.name"
         @input="inputListener($event, 'name')"
       />
-
-      <styled-input
-        label="Début"
-        :modelValue="evenement.start"
-        @input="dateListener($event, 'start')"
-      />
-      <datepicker />
-      <styled-input label="Fin" :modelValue="evenement.end" @input="dateListener($event, 'end')" />
+      <datepicker label="Début" target="hour" v-model="start" />
+      <datepicker label="Fin" target="hour" v-model="end" />
 
       <div class="actions" style="text-align: center">
         <button class="btn success" @click="$emit('solve')">
@@ -32,6 +26,9 @@
         <button class="btn primary small" @click="clickInput">
           <i class="material-icons">upload</i>Import des données
         </button>
+        <button class="btn small icon error" @click="toggleModal">
+          <i class="material-icons">event_busy</i>
+        </button>
         <input
           ref="input"
           style="display: none"
@@ -41,33 +38,88 @@
         />
       </div>
     </div>
+    <div v-if="showModal" class="modal" @click="toggleModal">
+      <div class="modal-content" @click="(e) => e.stopPropagation()">
+        <h3>Confirmer la suppression des créneaux</h3>
+        <p>
+          Êtes vous sûr de vouloir supprimer tout les créneaux qui ne sont pas entre le<br />
+          {{ start.format("dddd DD MMMM YYYY, HH:mm") }}<br />
+          et le <br />{{ end.format("dddd DD MMMM YYYY, HH:mm") }}
+        </p>
+        <div class="actions" style="margin-top: 8px; text-align: right">
+          <button class="btn error small" @click="clearCreneau">
+            <i class="material-icons">delete_forever</i>Confirmer
+          </button>
+          <button class="btn primary small" @click="toggleModal">
+            <i class="material-icons">close</i>Annuler
+          </button>
+        </div>
+      </div>
+    </div>
   </div>
 </template>
 
 <script lang="ts">
 import Evenement from "@/models/Evenement";
 import { MutationTypes } from "@/store/Mutations";
-import dayjs from "dayjs";
+import { Dayjs } from "dayjs";
 import { defineComponent } from "vue";
 import styledInput from "../components/input.vue";
 import datepicker from "../components/date-picker.vue";
 export default defineComponent({
   components: { styledInput, datepicker },
+  data() {
+    return {
+      start: null as Dayjs | null,
+      end: null as Dayjs | null,
+      showModal: false,
+    };
+  },
+  watch: {
+    start(val: Dayjs, oldval) {
+      if (oldval && !val.isSame(this.evenement.startingDate)) {
+        this.$store.commit(MutationTypes.editEvenement, {
+          field: "start",
+          value: val.toDate(),
+        });
+      }
+    },
+    end(val: Dayjs, oldval) {
+      if (oldval && !val.isSame(this.evenement.endingDate)) {
+        this.$store.commit(MutationTypes.editEvenement, {
+          field: "end",
+          value: val.subtract(1, "h").endOf("h").toDate(),
+        });
+      }
+    },
+    "evenement.start": function () {
+      this.initDate();
+    },
+    "evenement.end": function () {
+      this.initDate();
+    },
+  },
   computed: {
     evenement(): Evenement {
       return this.$store.state.evenement;
     },
   },
   methods: {
-    // eslint-disable-next-line @typescript-eslint/no-explicit-any
-    dateListener(event: any, field: keyof Evenement) {
-      const new_date = dayjs(event.target.value);
-      if (new_date.isValid())
-        this.$store.commit(MutationTypes.editEvenement, { field: field, value: new_date.toDate() });
+    toggleModal() {
+      this.showModal = !this.showModal;
+    },
+    initDate() {
+      if (this.evenement) {
+        this.start = this.evenement.startingDate;
+        this.end = this.evenement.endingDate;
+      }
     },
     // eslint-disable-next-line @typescript-eslint/no-explicit-any
     inputListener(event: any, field: keyof Evenement) {
-      this.$store.commit(MutationTypes.editEvenement, { field: field, value: event.target.value });
+      this.$store.commit(MutationTypes.editEvenement, {
+        field: field,
+        value: event.target.value,
+      });
     },
     exportStateToJson() {
       this.$emit("export");
@@ -89,6 +141,19 @@ export default defineComponent({
         }
       }
     },
+    clearCreneau() {
+      this.showModal = false;
+      const max = this.$store.state.evenement.end;
+      const min = this.$store.state.evenement.start;
+      const toBeRemoved = this.$store.state.creneauList.filter((c) => max < c.start || c.end < min);
+
+      for (let elt of toBeRemoved) {
+        this.$store.commit(MutationTypes.removeCreneau, elt);
+      }
+    },
+  },
+  mounted() {
+    this.initDate();
   },
 });
 </script>