diff --git a/package-lock.json b/package-lock.json index d0f592f..05f5aef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,6 @@ "@tailwindcss/forms": "^0.5.7", "@tailwindcss/typography": "^0.5.0", "alpinejs": "^3.13.5", - "dayjs": "^1.11.10", "flowbite": "^2.5.2", "flowbite-datepicker": "^1.2.6" }, @@ -20,9 +19,11 @@ "@spiriit/vite-plugin-svg-spritemap": "^2.2.4", "autoprefixer": "^10.4.0", "axios": "^1.7.7", + "dayjs": "^1.11.13", "postcss": "^8.4.4", "tailwind-clip-path": "^1.0.0", "tailwindcss": "latest", + "tippy.js": "^6.3.7", "toastify-js": "^1.12.0", "vite": "^5.0", "vite-plugin-live-reload": "^3.0" @@ -1227,7 +1228,8 @@ "node_modules/dayjs": { "version": "1.11.13", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==" + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "dev": true }, "node_modules/deepmerge": { "version": "4.3.1", @@ -2479,6 +2481,15 @@ "node": ">=0.8" } }, + "node_modules/tippy.js": { + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", + "integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==", + "dev": true, + "dependencies": { + "@popperjs/core": "^2.9.0" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", diff --git a/package.json b/package.json index 61ce5e9..ae1470c 100644 --- a/package.json +++ b/package.json @@ -19,9 +19,11 @@ "@spiriit/vite-plugin-svg-spritemap": "^2.2.4", "autoprefixer": "^10.4.0", "axios": "^1.7.7", + "dayjs": "^1.11.13", "postcss": "^8.4.4", "tailwind-clip-path": "^1.0.0", "tailwindcss": "latest", + "tippy.js": "^6.3.7", "toastify-js": "^1.12.0", "vite": "^5.0", "vite-plugin-live-reload": "^3.0" @@ -30,7 +32,6 @@ "@tailwindcss/forms": "^0.5.7", "@tailwindcss/typography": "^0.5.0", "alpinejs": "^3.13.5", - "dayjs": "^1.11.10", "flowbite": "^2.5.2", "flowbite-datepicker": "^1.2.6" } diff --git a/partials/anfrage/default.htm b/partials/anfrage/default.htm index bca7e89..9be8369 100644 --- a/partials/anfrage/default.htm +++ b/partials/anfrage/default.htm @@ -11,7 +11,7 @@
- +
diff --git a/resources/css/app.css b/resources/css/app.css index 4c74fc2..4fda214 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -33,3 +33,17 @@ transform: rotate(360deg); } } + +.tippy-box[data-theme~='success'] { + @apply bg-green-800 text-green-100 font-semibold; +} +.tippy-box[data-theme~='success'] .tippy-arrow { + @apply text-green-800; +} + +.tippy-box[data-theme~='error'] { + @apply bg-red-800 text-red-100 font-semibold; +} +.tippy-box[data-theme~='error'] .tippy-arrow { + @apply text-red-800; +} diff --git a/resources/js/app.js b/resources/js/app.js index 0b9d580..a4bfa4a 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -7,9 +7,13 @@ import customParseFormat from 'dayjs/plugin/customParseFormat'; dayjs.extend(customParseFormat); import axios from 'axios'; import {error} from './toast.js'; +import tippy from 'tippy.js'; import '../css/toastify.css'; import '../css/app.css'; +import 'tippy.js/dist/tippy.css'; + +dayjs.extend(customParseFormat); function initDatepicker(el) { new Datepicker(el, { @@ -54,6 +58,35 @@ Alpine.data('form', () => ({ return dayjs(this.value.birthday, 'DD.MM.YYYY').add(18, 'year').isAfter(dayjs(this.value.date, 'DD.MM.YYYY')); }, + onChangeDate: async function (n) { + const date = dayjs(this.value.date, 'DD.MM.YYYY'); + + if (!date.isValid()) { + return; + } + + const response = await axios.post( + window.location.pathname, + {date: date.format('YYYY-MM-DD')}, + { + headers: { + 'X-Winter-Request-Handler': 'anfrage::onDateValidation', + 'X-Requested-With': 'XMLHttpRequest', + }, + } + ); + + tippy('[data-tippy-target]', { + content: response.data.result ? 'Dieser Termin ist verfügbar' : 'Dieser Termin ist leider nicht buchbar', + showOnCreate: true, + trigger: 'manual', + theme: response.data.result ? 'success' : 'error', + placement: 'top', + onShown: function (t) { + window.setTimeout(() => t.hide(), 3000); + }, + }); + }, submit: async function () { if (this.sending === true) { return;