summaryrefslogtreecommitdiff
path: root/src/components/DateSelector.astro
diff options
context:
space:
mode:
authorJoão Augusto Costa Branco Marado Torres <torres.dev@disroot.org>2025-06-24 12:08:41 -0300
committerJoão Augusto Costa Branco Marado Torres <torres.dev@disroot.org>2025-06-24 12:50:43 -0300
commitf9a77c5c27aede4e5978eb55d9b7af781b680a1d (patch)
treed545e325ba1ae756fc2eac66fac1001b6753c40d /src/components/DateSelector.astro
feat!: initial commit
Signed-off-by: João Augusto Costa Branco Marado Torres <torres.dev@disroot.org>
Diffstat (limited to 'src/components/DateSelector.astro')
-rw-r--r--src/components/DateSelector.astro141
1 files changed, 141 insertions, 0 deletions
diff --git a/src/components/DateSelector.astro b/src/components/DateSelector.astro
new file mode 100644
index 0000000..324bc41
--- /dev/null
+++ b/src/components/DateSelector.astro
@@ -0,0 +1,141 @@
+---
+interface Props {
+ date: Date;
+ years: number[];
+ months: number[];
+ days?: number[];
+}
+
+const { date, years, months, days } = Astro.props;
+
+const y = date.getFullYear();
+const m = date.getMonth() + 1;
+const d = date.getDate();
+let yI = 0;
+let mI = 0;
+let dI = 0;
+
+const list = new Intl.ListFormat("pt-PT", { type: "unit", style: "narrow" });
+
+const pad = (n: number) => String(n).padStart(2, "0");
+---
+<nav>
+ <span role="list">
+ Anos:{" "}
+ {
+ list.formatToParts(years.map((y) =>
+ new Intl.DateTimeFormat("pt-PT", { year: "2-digit" }).format(
+ new Date(
+ Date.UTC(
+ y,
+ 0,
+ 1,
+ date.getTimezoneOffset() / 60,
+ date.getTimezoneOffset() % 60,
+ ),
+ ),
+ )
+ )).map(({ type, value }: { type: string; value: string }) => {
+ switch (type) {
+ case "element": {
+ const year = years[yI++];
+ return (
+ <span role="listitem"><a
+ class:list={[{ active: year === y }]}
+ href={`/blog/${year}`}
+ >{value}</a></span>
+ );
+ }
+ case "literal": {
+ return (
+ <span>{value}</span>
+ );
+ }
+ }
+ })
+ }
+ </span>
+ <br />
+ <span role="list">
+ Meses:{" "}
+ {
+ list.formatToParts(months.map((m) =>
+ new Intl.DateTimeFormat("pt-PT", { month: "short" }).format(
+ new Date(
+ Date.UTC(
+ y,
+ m - 1,
+ 1,
+ date.getTimezoneOffset() / 60,
+ date.getTimezoneOffset() % 60,
+ ),
+ ),
+ )
+ )).map(({ type, value }: { type: string; value: string }) => {
+ switch (type) {
+ case "element": {
+ const month = months[mI++];
+ return (
+ <span role="listitem"><a
+ class:list={[{ active: month === m }]}
+ href={`/blog/${y}/${pad(month)}`}
+ >{value}</a></span>
+ );
+ }
+ case "literal": {
+ return (
+ <span>{value}</span>
+ );
+ }
+ }
+ })
+ }
+ </span>
+ {
+ days &&
+ (
+ <><br /><span role="list">
+ Dias:{" "}
+ {
+ list.formatToParts(days.map((d) => {
+ return new Intl.DateTimeFormat("pt-PT", { day: "numeric" })
+ .format(
+ new Date(
+ Date.UTC(
+ y,
+ m - 1,
+ d,
+ date.getTimezoneOffset() / 60,
+ date.getTimezoneOffset() % 60,
+ ),
+ ),
+ );
+ })).map(({ type, value }: { type: string; value: string }) => {
+ switch (type) {
+ case "element": {
+ const day = days[dI++];
+ return (
+ <span role="listitem"><a
+ class:list={[{ active: day === d }]}
+ href={`/blog/${y}/${pad(m)}/${pad(d)}`}
+ >{value}</a></span>
+ );
+ }
+ case "literal": {
+ return (
+ <span>{value}</span>
+ );
+ }
+ }
+ })
+ }
+ </span></>
+ )
+ }
+</nav>
+
+<style>
+ a.active {
+ font-weight: bolder;
+ }
+</style>