diff --git a/src/components/admin/comm/banners/BannersForm.svelte b/src/components/admin/comm/banners/BannersForm.svelte index be60e5cd..d2000761 100644 --- a/src/components/admin/comm/banners/BannersForm.svelte +++ b/src/components/admin/comm/banners/BannersForm.svelte @@ -2,7 +2,7 @@ import { actions } from "astro:actions"; import { locale, t } from "../../../../i18n/store"; - import { formatDate } from "../../../../utils/dates"; + import { endOfDay, formatDate, startOfDay } from "../../../../utils/dates"; import ActionableButton from "../../../library/buttons/ActionableButton.svelte"; import DateInput from "../../../library/inputs/DateInput.svelte"; import TextArea from "../../../library/inputs/TextArea.svelte"; @@ -23,9 +23,20 @@ let fieldErrors: FieldErrors = $state({}); - function handleDateSelect(date: Date) { + function normalizeDate(field: "startsAt" | "endsAt", date: Date) { const now = new Date(); - date.setHours(now.getHours(), now.getMinutes(), now.getSeconds(), now.getMilliseconds()); + const isToday = + date.getFullYear() === now.getFullYear() && + date.getMonth() === now.getMonth() && + date.getDate() === now.getDate(); + + // Ends always run to the end of their day. Start dates run from their + // midnight, except when the day is today the current time is used so it + // passes the "no earlier than now" validation. DateInput binds the same + // object, so the normalized time is applied in place. + const normalized = field === "endsAt" ? endOfDay(date) : isToday ? now : startOfDay(date); + + date.setTime(normalized.getTime()); } async function submit() { @@ -110,7 +121,7 @@ placeholder={$t("pages.admin.comm.banners.fields.startDatePlaceholder")} error={fieldErrors.startsAt && $t(fieldErrors.startsAt, { date: formatDate(new Date(), $locale) })} - onInput={handleDateSelect} + onInput={(date) => normalizeDate("startsAt", date)} /> normalizeDate("endsAt", date)} /> diff --git a/src/components/home/HomeBanners.svelte b/src/components/home/HomeBanners.svelte new file mode 100644 index 00000000..6376e3a1 --- /dev/null +++ b/src/components/home/HomeBanners.svelte @@ -0,0 +1,26 @@ + + +{#if banners.length > 0} +
+ {#each banners as banner} + + {/each} +
+{/if} diff --git a/src/i18n/locales/es.json b/src/i18n/locales/es.json index 9556aaba..dc85c962 100644 --- a/src/i18n/locales/es.json +++ b/src/i18n/locales/es.json @@ -27,7 +27,7 @@ "expectedUrl": "No es una URL" }, "date": { - "greaterThan": "La fecha debe ser igual o mayor que el {{ date }}" + "greaterThan": "La fecha debe ser mayor que el {{ date }}" }, "file": { "maxAllowedSize": "Tamaño máximo permitido {{ size }}", diff --git a/src/pages/[...locale]/index.astro b/src/pages/[...locale]/index.astro index 01c24dea..ace5ab63 100644 --- a/src/pages/[...locale]/index.astro +++ b/src/pages/[...locale]/index.astro @@ -8,7 +8,7 @@ import Stats from "../../components/home/Stats.astro"; import FeaturedPromoters from "../../components/home/FeaturedPromoters.astro"; import Blog from "../../components/home/Blog.astro"; import Matchfunding from "../../components/home/Matchfunding.astro"; -import HomeBanner from "../../components/home/HomeBanner.svelte"; +import Banners from "../../components/home/HomeBanners.svelte"; // Disabled sections, re-enable the import along with the component below: // import Stories from "../../components/home/Stories.svelte"; // import Resources from "../../components/home/Resources.astro"; @@ -35,23 +35,7 @@ const activeBanners = (await bannerRepository.getActive()).filter( - { - activeBanners.length > 0 && ( -
- {activeBanners.map((banner) => ( - - ))} -
- ) - } + diff --git a/src/utils/dates.ts b/src/utils/dates.ts index 7e17e017..b290015e 100644 --- a/src/utils/dates.ts +++ b/src/utils/dates.ts @@ -10,6 +10,27 @@ export function formatDate(date: Date, locale: Locale) { return date.toLocaleDateString(locale, options); } +/** + * The first instant of the day for the given date (midnight, 00:00). + * @param date The date to normalize + * @returns A new Date set to the start of the given day + */ +export function startOfDay(date: Date): Date { + return new Date(date.getFullYear(), date.getMonth(), date.getDate()); +} + +/** + * The last instant of the day for the given date (23:59:59.999). + * Derived from the start of the following day rather than hardcoding the end-of-day time. + * @param date The date to normalize + * @returns A new Date set to the end of the given day + */ +export function endOfDay(date: Date): Date { + // Start of the next day, minus a single millisecond + const nextDay = new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1); + return new Date(nextDay.getTime() - 1); +} + /** * Get a date `n` ms from now * @param offset Milliseconds since now until future date