src/pages/art-calendar.astro 5.0 K raw
1
---
2
export const prerender = false;
3
4
import PageLayout from "@/layouts/Base.astro";
5
import { getFormattedDate } from "@/utils";
6
7
type Artwork = {
8
	date: string;
9
	artwork_id: number;
10
	title: string;
11
	artist_display: string | null;
12
	date_display: string | null;
13
	medium_display: string | null;
14
	dimensions: string | null;
15
	place_of_origin: string | null;
16
	credit_line: string | null;
17
	short_description: string | null;
18
	image_id: string | null;
19
	image_url: string | null;
20
	source_url: string | null;
21
};
22
23
const meta = {
24
	title: "/art-calendar",
25
	description:
26
		"A different painting every day from the Art Institute of Chicago.",
27
};
28
29
const FEED_URL = "https://easel.stevedylan.dev/feed.xml";
30
const today = new Date();
31
32
let artwork: Artwork | null = null;
33
let error: string | null = null;
34
35
try {
36
	const res = await fetch("https://easel.stevedylan.dev/api/today", {
37
		headers: { Accept: "application/json" },
38
	});
39
	if (!res.ok) throw new Error(`easel returned ${res.status}`);
40
	artwork = (await res.json()) as Artwork;
41
} catch (e) {
42
	error = e instanceof Error ? e.message : "Failed to reach easel API";
43
}
44
45
Astro.response.headers.set(
46
	"Cache-Control",
47
	"public, max-age=3600, s-maxage=86400",
48
);
49
---
50
51
<PageLayout meta={meta}>
52
  <div class="flex min-h-screen flex-col items-start justify-start gap-6">
53
    <div class="flex flex-col gap-1 w-full">
54
      <div class="flex flex-row justify-between items-center w-full">
55
        <h1 class="title">/art-calendar</h1>
56
        <div class="flex gap-2 items-center">
57
          <a
58
            class="inline-block p-2 sm:hover:text-link"
59
            href={FEED_URL}
60
            target="_blank"
61
            rel="noopener noreferrer"
62
          >
63
            <svg
64
              xmlns="http://www.w3.org/2000/svg"
65
              class="h-6 w-6"
66
              viewBox="0 0 24 24"
67
              stroke-width="1.5"
68
              stroke="currentColor"
69
              fill="none"
70
              stroke-linecap="round"
71
              stroke-linejoin="round"
72
            >
73
              <g
74
                fill="none"
75
                stroke="currentColor"
76
                stroke-linecap="round"
77
                stroke-linejoin="round"
78
                stroke-width="2"
79
                ><path d="M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16"
80
                ></path><circle cx="5" cy="19" r="1"></circle></g
81
              >
82
            </svg>
83
            <span class="sr-only">RSS</span>
84
          </a>
85
        </div>
86
      </div>
87
      <p class="text-sm opacity-70">
88
        {getFormattedDate(today)}
89
      </p>
90
    </div>
91
    {
92
      error || !artwork ? (
93
        <p class="text-red-400 text-sm">
94
          Couldn't load today's painting{error ? `: ${error}` : ""}.
95
        </p>
96
      ) : (
97
        <article class="flex flex-col w-full gap-6">
98
          {artwork.image_url && (
99
            <img
100
              src={artwork.image_url}
101
              alt={artwork.title}
102
              loading="eager"
103
              class="w-full h-auto"
104
            />
105
          )}
106
          <div class="flex flex-col gap-1">
107
            <h2 class="text-xl italic text-accent-2">{artwork.title}</h2>
108
            {artwork.artist_display && (
109
              <p class="text-sm whitespace-pre-line">
110
                {artwork.artist_display}
111
              </p>
112
            )}
113
          </div>
114
          <dl class="grid grid-cols-1 sm:grid-cols-[max-content_1fr] gap-x-6 gap-y-2 text-sm">
115
            {artwork.date_display && (
116
              <>
117
                <dt class="opacity-50 uppercase tracking-widest text-xs">
118
                  Date
119
                </dt>
120
                <dd>{artwork.date_display}</dd>
121
              </>
122
            )}
123
            {artwork.place_of_origin && (
124
              <>
125
                <dt class="opacity-50 uppercase tracking-widest text-xs">
126
                  Origin
127
                </dt>
128
                <dd>{artwork.place_of_origin}</dd>
129
              </>
130
            )}
131
            {artwork.medium_display && (
132
              <>
133
                <dt class="opacity-50 uppercase tracking-widest text-xs">
134
                  Medium
135
                </dt>
136
                <dd>{artwork.medium_display}</dd>
137
              </>
138
            )}
139
            {artwork.dimensions && (
140
              <>
141
                <dt class="opacity-50 uppercase tracking-widest text-xs">
142
                  Dimensions
143
                </dt>
144
                <dd>{artwork.dimensions}</dd>
145
              </>
146
            )}
147
            {artwork.credit_line && (
148
              <>
149
                <dt class="opacity-50 uppercase tracking-widest text-xs">
150
                  Credit
151
                </dt>
152
                <dd>{artwork.credit_line}</dd>
153
              </>
154
            )}
155
          </dl>
156
          {artwork.short_description && (
157
            <p class="text-sm">{artwork.short_description}</p>
158
          )}
159
          {artwork.source_url && (
160
            <a
161
              class="style-link self-start"
162
              href={artwork.source_url}
163
              target="_blank"
164
              rel="noopener"
165
            >
166
              View on artic.edu
167
            </a>
168
          )}
169
        </article>
170
      )
171
    }
172
  </div>
173
</PageLayout>