mirror of
https://github.com/ClaperCo/Claper.git
synced 2026-08-29 01:58:48 +02:00
Use native datetime-local instead of AirDatepicker
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
@import 'air-datepicker/air-datepicker.css';
|
||||
@import 'animate.css/animate.min.css';
|
||||
|
||||
@import 'tailwindcss';
|
||||
@@ -545,20 +544,6 @@
|
||||
transform:rotate(-20deg);
|
||||
}
|
||||
|
||||
/* Air datepicker */
|
||||
.air-datepicker-body--day-name {
|
||||
color: var(--color-primary-600);
|
||||
}
|
||||
|
||||
.air-datepicker-cell.-selected-, .air-datepicker-cell.-selected-.-current- {
|
||||
background-color: var(--color-primary-500);
|
||||
color: var(--color-white);
|
||||
}
|
||||
|
||||
.air-datepicker-cell.-current- {
|
||||
color: var(--color-secondary-500);
|
||||
}
|
||||
|
||||
.animate__slow_slow {
|
||||
--animate-duration: 5s;
|
||||
}
|
||||
|
||||
@@ -6,14 +6,6 @@ import { LiveSocket } from "phoenix_live_view";
|
||||
import topbar from "../vendor/topbar";
|
||||
import Alpine from "alpinejs";
|
||||
import moment from "moment-timezone";
|
||||
import AirDatepicker from "air-datepicker";
|
||||
import airdatepickerLocaleEn from "air-datepicker/locale/en";
|
||||
import airdatepickerLocaleFr from "air-datepicker/locale/fr";
|
||||
import airdatepickerLocaleDe from "air-datepicker/locale/de";
|
||||
import airdatepickerLocaleEs from "air-datepicker/locale/es";
|
||||
import airdatepickerLocaleNl from "air-datepicker/locale/nl";
|
||||
import airdatepickerLocaleIt from "air-datepicker/locale/it";
|
||||
import airdatepickerLocaleHu from "air-datepicker/locale/hu";
|
||||
import "moment/locale/de";
|
||||
import "moment/locale/fr";
|
||||
import "moment/locale/es";
|
||||
@@ -42,43 +34,19 @@ const supportedLocales = window.claperConfig?.supportedLocales || [
|
||||
"lv",
|
||||
];
|
||||
|
||||
const airdatePickrSupportedLocales = window.claperConfig?.supportedLocales || [
|
||||
"en",
|
||||
"fr",
|
||||
"de",
|
||||
"es",
|
||||
"nl",
|
||||
"it",
|
||||
"hu",
|
||||
];
|
||||
|
||||
var locale =
|
||||
document.querySelector("html").getAttribute("lang") ||
|
||||
navigator.language.split("-")[0];
|
||||
|
||||
var airdatepickrLocale = locale;
|
||||
|
||||
if (!supportedLocales.includes(locale)) {
|
||||
locale = "en";
|
||||
}
|
||||
if (!airdatePickrSupportedLocales.includes(airdatepickrLocale)) {
|
||||
airdatepickrLocale = "en";
|
||||
}
|
||||
|
||||
window.moment.locale("en");
|
||||
window.moment.locale(locale);
|
||||
window.Alpine = Alpine;
|
||||
Alpine.start();
|
||||
|
||||
let airdatePickrLocales = {
|
||||
en: airdatepickerLocaleEn,
|
||||
fr: airdatepickerLocaleFr,
|
||||
de: airdatepickerLocaleDe,
|
||||
es: airdatepickerLocaleEs,
|
||||
nl: airdatepickerLocaleNl,
|
||||
it: airdatepickerLocaleIt,
|
||||
hu: airdatepickerLocaleHu,
|
||||
};
|
||||
let csrfToken = document
|
||||
.querySelector("meta[name='csrf-token']")
|
||||
.getAttribute("content");
|
||||
@@ -450,31 +418,52 @@ Hooks.CalendarLocalDate = {
|
||||
this.el.innerHTML = moment.utc(this.el.dataset.date).local().calendar();
|
||||
},
|
||||
};
|
||||
Hooks.Pickr = {
|
||||
Hooks.DateTimeLocal = {
|
||||
mounted() {
|
||||
const localTime = this.el.querySelector("input[type=text]");
|
||||
const utcTime = this.el.querySelector("input[type=hidden]");
|
||||
localTime.value = moment
|
||||
.utc(utcTime.value)
|
||||
.local()
|
||||
.format("DD-MM-YYYY HH:mm");
|
||||
this.pickr = new AirDatepicker(localTime, {
|
||||
dateFormat: "dd-MM-yyyy",
|
||||
timepicker: true,
|
||||
minutesStep: 5,
|
||||
minDate: moment(),
|
||||
timeFormat: "HH:mm",
|
||||
selectedDates: [moment(localTime.value, "DD-MM-YYYY HH:mm").toDate()],
|
||||
onSelect: ({ date }) => {
|
||||
const utc = moment(date).utc().format("YYYY-MM-DDTHH:mm:ss");
|
||||
utcTime.value = utc;
|
||||
},
|
||||
locale: airdatePickrLocales[airdatepickrLocale] || airdatePickrLocales["en"],
|
||||
});
|
||||
this.localTime = this.el.querySelector("input[type=datetime-local]");
|
||||
this.utcTime = this.el.querySelector("input[type=hidden]");
|
||||
this.syncLocalTime();
|
||||
|
||||
this.handleInput = ({ target }) => {
|
||||
if (target === this.localTime) this.syncUtcTime();
|
||||
};
|
||||
this.el.addEventListener("input", this.handleInput);
|
||||
},
|
||||
updated() {
|
||||
this.localTime = this.el.querySelector("input[type=datetime-local]");
|
||||
this.utcTime = this.el.querySelector("input[type=hidden]");
|
||||
this.syncLocalTime();
|
||||
},
|
||||
syncLocalTime() {
|
||||
if (!this.utcTime.value) {
|
||||
this.localTime.value = "";
|
||||
return;
|
||||
}
|
||||
|
||||
const value = this.utcTime.value.replace(" ", "T").replace(/Z$/, "");
|
||||
const date = new Date(`${value}Z`);
|
||||
|
||||
if (!Number.isNaN(date.getTime())) {
|
||||
const pad = (part) => String(part).padStart(2, "0");
|
||||
this.localTime.value =
|
||||
`${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}` +
|
||||
`T${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
||||
}
|
||||
},
|
||||
syncUtcTime() {
|
||||
if (!this.localTime.value) {
|
||||
this.utcTime.value = "";
|
||||
return;
|
||||
}
|
||||
|
||||
const date = new Date(this.localTime.value);
|
||||
|
||||
if (!Number.isNaN(date.getTime())) {
|
||||
this.utcTime.value = date.toISOString().slice(0, 19);
|
||||
}
|
||||
},
|
||||
updated() {},
|
||||
destroyed() {
|
||||
if (this.pickr) this.pickr.destroy();
|
||||
this.el.removeEventListener("input", this.handleInput);
|
||||
},
|
||||
};
|
||||
Hooks.UpdateAttendees = {
|
||||
|
||||
11
assets/package-lock.json
generated
11
assets/package-lock.json
generated
@@ -5,7 +5,6 @@
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"air-datepicker": "^3.5.0",
|
||||
"animate.css": "^4.1.1",
|
||||
"chart.js": "^4.4.0",
|
||||
"chartjs-adapter-moment": "^1.0.1",
|
||||
@@ -896,11 +895,6 @@
|
||||
"integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/air-datepicker": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/air-datepicker/-/air-datepicker-3.5.0.tgz",
|
||||
"integrity": "sha512-WOpn1MaSl5drcXSwkXg5Gh/jXX/VFfamNnIb8E43AY4UKuW/bNEW06e3GGsiWLDBQLabD22L6b6cP7KHnAy54w=="
|
||||
},
|
||||
"node_modules/alpinejs": {
|
||||
"version": "3.13.8",
|
||||
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.13.8.tgz",
|
||||
@@ -1930,11 +1924,6 @@
|
||||
"integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==",
|
||||
"dev": true
|
||||
},
|
||||
"air-datepicker": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/air-datepicker/-/air-datepicker-3.5.0.tgz",
|
||||
"integrity": "sha512-WOpn1MaSl5drcXSwkXg5Gh/jXX/VFfamNnIb8E43AY4UKuW/bNEW06e3GGsiWLDBQLabD22L6b6cP7KHnAy54w=="
|
||||
},
|
||||
"alpinejs": {
|
||||
"version": "3.13.8",
|
||||
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.13.8.tgz",
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"tailwindcss": "^4.1.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"air-datepicker": "^3.5.0",
|
||||
"animate.css": "^4.1.1",
|
||||
"chart.js": "^4.4.0",
|
||||
"chartjs-adapter-moment": "^1.0.1",
|
||||
|
||||
@@ -259,14 +259,12 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-1" phx-update="ignore" id="date-picker">
|
||||
<div class="flex flex-col gap-1" id="date-picker">
|
||||
<ClaperWeb.Component.Input.date
|
||||
form={f}
|
||||
key={:started_at}
|
||||
name={gettext("Start date and time")}
|
||||
required="true"
|
||||
from={Date.add(Date.utc_today(), -1)}
|
||||
to={Date.add(Date.utc_today(), 365)}
|
||||
/>
|
||||
<p class="text-xs text-base-content/60">{gettext("Shown in your local time.")}</p>
|
||||
</div>
|
||||
|
||||
@@ -277,14 +277,16 @@ defmodule ClaperWeb.Component.Input do
|
||||
|
||||
~H"""
|
||||
<div>
|
||||
<div class="relative" id="date" phx-hook="Pickr">
|
||||
{label(@form, @key, @name, class: "block text-sm font-bold text-base-content")}
|
||||
<div class="relative" id={"#{input_id(@form, @key)}-picker"} phx-hook="DateTimeLocal">
|
||||
{label(@form, :local_date, @name, class: "block text-sm font-bold text-base-content")}
|
||||
<div class="mt-1 relative">
|
||||
{hidden_input(@form, @key)}
|
||||
{text_input(@form, :local_date,
|
||||
{datetime_local_input(@form, :local_date,
|
||||
required: @required,
|
||||
readonly: @readonly,
|
||||
autofocus: @autofocus,
|
||||
placeholder: @placeholder,
|
||||
autocomplete: false,
|
||||
autocomplete: "off",
|
||||
step: 300,
|
||||
class:
|
||||
"input h-12 w-full bg-white px-4 read-only:opacity-50 #{if Keyword.has_key?(@form.errors, @key), do: "input-error", else: ""}"
|
||||
)}
|
||||
|
||||
@@ -44,6 +44,13 @@ defmodule ClaperWeb.EventLiveTest do
|
||||
assert has_element?(edit_live, "#event-editor-title", "Edit event")
|
||||
assert has_element?(edit_live, "#presentation-heading", "Presentation")
|
||||
assert has_element?(edit_live, "#event-details-heading", "Event details")
|
||||
assert has_element?(edit_live, ~s(#date-picker input[type="datetime-local"]))
|
||||
|
||||
assert has_element?(
|
||||
edit_live,
|
||||
~s(#date-picker input[name="event[started_at]"][type="hidden"])
|
||||
)
|
||||
|
||||
assert has_element?(edit_live, "#facilitators-section")
|
||||
assert has_element?(edit_live, "#event-danger-zone", "Delete event")
|
||||
assert has_element?(edit_live, ~s(button[form="event-form"]), "Save changes")
|
||||
|
||||
Reference in New Issue
Block a user