Improve date inputs UI when creating / editing events

This commit is contained in:
Remmy Cat Stock 2022-11-05 00:05:00 +01:00 committed by Remmy Cat Stock
parent 88e0649e79
commit a6f62fa7b3
2 changed files with 78 additions and 65 deletions

View File

@ -57,6 +57,7 @@ import {
import { MapPoolSelector } from "~/components/MapPoolSelector";
import { Tags } from "./components/Tags";
import { isDefined } from "~/utils/arrays";
import { CrossIcon } from "~/components/icons/Cross";
const MIN_DATE = new Date(Date.UTC(2015, 4, 28));
@ -288,6 +289,16 @@ function DescriptionTextarea() {
);
}
function AddButton({ onAdd, id }: { onAdd: () => void; id?: string }) {
const { t } = useTranslation();
return (
<Button tiny variant="outlined" onClick={onAdd} id={id}>
{t("actions.add")}
</Button>
);
}
function DatesInput() {
const { t } = useTranslation(["common", "calendar"]);
const { eventToEdit } = useLoaderData<typeof loader>();
@ -332,8 +343,7 @@ function DatesInput() {
const lastValidDate = current
.map((e) => e.date)
.filter(isDefined)
.reverse()
.at(0);
.reverse()[0];
const addedDate = lastValidDate
? getDateWithHoursOffset(lastValidDate, NEW_CALENDAR_EVENT_HOURS_OFFSET)
@ -344,64 +354,70 @@ function DatesInput() {
return (
<div className="stack md items-start">
<div>
<Label htmlFor="date" required>
{t("calendar:forms.dates")}
</Label>
<div className="stack sm">
{datesInputState.map(({ date, key }, i) => {
return (
<div key={key} className="stack horizontal sm items-center">
<DateInput
id={`date-input-${key}`}
name="date"
defaultValue={date ?? undefined}
min={MIN_DATE}
max={MAX_DATE}
required
onChange={(newDate: Date | null) => {
setDatesInputState((current) =>
current.map((entry) =>
entry.key === key ? { ...entry, date: newDate } : entry
)
);
}}
/>
{i === datesCount - 1 && (
<>
{/* "Add" button */}
<fieldset>
<legend>
{t("calendar:forms.dates")} <span className="text-error">*</span>
</legend>
<div className="stack sm items-start">
<div className="stack sm">
{datesInputState.map(({ date, key }, i) => {
return (
<div key={key} className="stack horizontal sm items-center">
<label
id={`date-input-${key}-label`}
className="calendar-new__day-label"
htmlFor={`date-input-${key}`}
>
{t("calendar:day", {
number: i + 1,
})}
</label>
<DateInput
id={`date-input-${key}`}
name="date"
defaultValue={date ?? undefined}
min={MIN_DATE}
max={MAX_DATE}
required
onChange={(newDate: Date | null) => {
setDatesInputState((current) =>
current.map((entry) =>
entry.key === key
? { ...entry, date: newDate }
: entry
)
);
}}
/>
{/* "Remove" button */}
{datesCount > 1 && (
<Button
tiny
disabled={
datesCount === CALENDAR_EVENT.MAX_AMOUNT_OF_DATES
}
onClick={addDate}
>
{t("common:actions.add")}
</Button>
{/* "Remove" button */}
{datesCount > 1 && (
<Button
tiny
onClick={() => {
setDatesInputState((current) => current.slice(0, -1));
}}
variant="destructive"
>
{t("common:actions.remove")}
</Button>
)}
</>
)}
</div>
);
})}
onClick={() => {
setDatesInputState((current) =>
current.filter((e) => e.key !== key)
);
}}
aria-controls={`date-input-${key}`}
aria-label={t("common:actions.remove")}
aria-describedby={`date-input-${key}-label`}
title={t("common:actions.remove")}
icon={<CrossIcon />}
variant="minimal-destructive"
/>
)}
</div>
);
})}
</div>
{datesCount < CALENDAR_EVENT.MAX_AMOUNT_OF_DATES && (
<AddButton onAdd={addDate} />
)}
<FormMessage type="info" className={clsx({ invisible: !isMounted })}>
{t("calendar:inYourTimeZone")} {usersTimeZone}
</FormMessage>
</div>
<FormMessage type="info" className={clsx({ invisible: !isMounted })}>
{t("calendar:inYourTimeZone")} {usersTimeZone}
</FormMessage>
</div>
</fieldset>
</div>
);
}
@ -590,14 +606,7 @@ function MapPoolSection() {
) : (
<div>
<label htmlFor={id}>{t("common:maps.mapPool")}</label>
<Button
id={id}
variant="outlined"
tiny
onClick={() => setIncludeMapPool(true)}
>
{t("common:actions.add")}
</Button>
<AddButton onAdd={() => setIncludeMapPool(true)} id={id} />
</div>
);
}

View File

@ -14,3 +14,7 @@
font-size: var(--fonts-sm);
font-weight: var(--semi-bold);
}
.calendar-new__day-label {
margin: 0;
}