● Zion Boggan
repos/Stepping App/apps/web/src/app/page.tsx
zionboggan.com ↗
237 lines · tsx
History for this file →
1
import Link from "next/link";
2
import { serverCaller } from "@/lib/trpc/server";
3
import { Marquee } from "@/components/marquee";
4
import { SteppingCouple } from "@/components/stepping-couple";
5
import { MobileNav } from "@/components/mobile-nav";
6
import { Wordmark } from "@/components/wordmark";
7
 
8
export const dynamic = "force-dynamic";
9
 
10
const COUNT = ["6", "·", "COUNT", "·", "8"];
11
 
12
const COMING = [
13
  "Little Rock",
14
  "St. Louis",
15
  "Huntsville",
16
  "Montgomery",
17
  "New Orleans",
18
  "Las Vegas",
19
];
20
 
21
const YARD = [
22
  { k: "Stepping groups", d: "The groups that keep each city stepping." },
23
  { k: "DJs", d: "Who is spinning the set, and where." },
24
  { k: "Promoters", d: "The people who host the sets and weekenders." },
25
  { k: "Classes", d: "Lessons and instructors, beginner on up." },
26
];
27
 
28
function fmt(d: Date | null) {
29
  if (!d) return "DATE TBD";
30
  return new Date(d)
31
    .toLocaleString("en-US", {
32
      month: "short",
33
      day: "numeric",
34
      hour: "numeric",
35
      minute: "2-digit",
36
    })
37
    .toUpperCase();
38
}
39
 
40
export default async function Home() {
41
  const caller = serverCaller();
42
  const cities = await caller.city.listLaunched();
43
  const byCity = new Map(cities.map((c) => [c.id, c]));
44
  const lists = await Promise.all(
45
    cities.map((c) => caller.event.list({ cityId: c.id })),
46
  );
47
  const lineup = lists
48
    .flat()
49
    .sort(
50
      (a, b) =>
51
        (a.startsAt ? +new Date(a.startsAt) : Infinity) -
52
        (b.startsAt ? +new Date(b.startsAt) : Infinity),
53
    )
54
    .slice(0, 6);
55
 
56
  return (
57
    <div className="relative">
58
      <header className="fixed top-0 z-50 flex w-full items-center justify-between px-5 py-4 sm:px-8">
59
        <Link href="/" className="text-lg">
60
          <Wordmark />
61
        </Link>
62
        <nav className="hidden gap-7 sm:flex">
63
          <a href="#sets" className="kicker hover:text-bone">
64
            The Sets
65
          </a>
66
          <a href="#floor" className="kicker hover:text-bone">
67
            The Floor
68
          </a>
69
          <a href="#road" className="kicker hover:text-bone">
70
            The Road
71
          </a>
72
        </nav>
73
        <MobileNav />
74
      </header>
75
 
76
      {}
77
      <section className="relative flex min-h-[100svh] flex-col justify-center px-5 sm:px-10">
78
        <div className="pointer-events-none relative order-1 mx-auto mt-24 h-[34vh] w-[84%] max-w-[300px] sm:absolute sm:inset-y-0 sm:right-[2%] sm:order-none sm:mx-0 sm:mt-0 sm:h-auto sm:w-[38%] sm:max-w-none">
79
          <div
80
            className="absolute left-1/2 top-1/2 h-[78%] w-[78%] -translate-x-1/2 -translate-y-1/2 rounded-full blur-3xl"
81
            style={{ background: "radial-gradient(circle, rgba(61,90,254,0.14) 0%, transparent 62%)" }}
82
          />
83
          <SteppingCouple className="absolute inset-0 flex items-center justify-center py-[4%]" />
84
        </div>
85
 
86
        <p className="kicker beat-in b1 order-2 mt-6 sm:absolute sm:left-10 sm:top-24 sm:mt-0">
87
          The partner dance <span className="text-gold">/</span> Born in Chicago
88
        </p>
89
 
90
        <div className="relative z-10 order-3 mt-3 select-none sm:mt-0 sm:-ml-[2vw]">
91
          <h1 className="display" style={{ lineHeight: 0.82, letterSpacing: "-0.04em", fontSize: "clamp(3rem, 13.5vw, 17rem)" }}>
92
            <span className="block beat-in b1">STEP.</span>
93
            <span className="block text-gold beat-in b2">GLIDE.</span>
94
            <span className="serif block italic font-normal beat-in b3">spin.</span>
95
          </h1>
96
        </div>
97
 
98
        <div className="beat-in b4 relative z-10 order-4 mt-6 max-w-md sm:mt-8">
99
          <p className="serif text-2xl leading-snug text-bone sm:text-3xl">
100
            Chicago Stepping. Your City.
101
          </p>
102
          <p className="serif mt-3 text-lg leading-snug text-bone/75 sm:text-xl">
103
            The sets, the people, and the road between cities, in one place.
104
          </p>
105
        </div>
106
 
107
        <div className="beat-in b5 order-5 mt-8 flex flex-wrap items-center gap-x-6 gap-y-2">
108
          {cities.map((c) => (
109
            <Link key={c.id} href={`/city/${c.slug}`} className="kicker text-bone hover:text-gold">
110
              {c.name}
111
            </Link>
112
          ))}
113
        </div>
114
        <p className="beat-in b5 order-6 mt-4 max-w-2xl text-sm leading-relaxed text-ash">
115
          <span className="kicker">More cities coming</span>
116
          <span className="mx-2 text-gold">/</span>
117
          {COMING.map((name, i) => (
118
            <span key={name}>
119
              <span className="whitespace-nowrap">{name}</span>
120
              {i < COMING.length - 1 && " · "}
121
            </span>
122
          ))}
123
        </p>
124
      </section>
125
 
126
      <Marquee />
127
 
128
      {}
129
      <section className="flex flex-wrap items-baseline justify-center gap-6 px-5 py-10 sm:px-8">
130
        {COUNT.map((g, i) => (
131
          <span
132
            key={i}
133
            className="display text-3xl text-bone/70 sm:text-4xl"
134
          >
135
            {g}
136
          </span>
137
        ))}
138
      </section>
139
 
140
      {}
141
      <section
142
        id="sets"
143
        className="border-t border-[var(--line)] px-5 py-16 sm:px-8"
144
      >
145
        <div className="flex items-end justify-between">
146
          <h2 className="display text-5xl sm:text-7xl">The Sets</h2>
147
          <span className="kicker">01 / Sets</span>
148
        </div>
149
        <ul className="mt-10">
150
          {lineup.length === 0 && (
151
            <li className="kicker text-ash">No sets posted yet.</li>
152
          )}
153
          {lineup.map((e, i) => (
154
            <li key={e.id}>
155
              <Link
156
                href={`/city/${byCity.get(e.cityId)?.slug ?? ""}`}
157
                className="group flex items-center gap-5 border-b border-[var(--line)] py-6"
158
              >
159
                <span className="kicker w-10 text-gold">
160
                  {String(i + 1).padStart(2, "0")}
161
                </span>
162
                <span className="display flex-1 text-2xl text-bone group-hover:text-gold sm:text-4xl">
163
                  {e.title}
164
                </span>
165
                <span className="kicker hidden sm:block">
166
                  {byCity.get(e.cityId)?.name}
167
                </span>
168
                <span className="kicker w-28 text-right text-ash">
169
                  {fmt(e.startsAt)}
170
                </span>
171
              </Link>
172
            </li>
173
          ))}
174
        </ul>
175
      </section>
176
 
177
      {}
178
      <section
179
        id="floor"
180
        className="border-t border-[var(--line)] px-5 py-16 sm:px-8"
181
      >
182
        <div className="flex items-end justify-between">
183
          <h2 className="display text-5xl sm:text-7xl">The Floor</h2>
184
          <span className="kicker">02 / Community</span>
185
        </div>
186
        <div className="mt-10 grid gap-px sm:grid-cols-2 lg:grid-cols-3">
187
          {YARD.map((y) => (
188
            <div key={y.k} className="py-6 pr-6">
189
              <h3 className="display text-3xl">{y.k}</h3>
190
              <p className="serif mt-2 text-lg text-bone/70">{y.d}</p>
191
            </div>
192
          ))}
193
        </div>
194
      </section>
195
 
196
      {}
197
      <section
198
        id="road"
199
        className="border-t border-[var(--line)] px-5 py-16 sm:px-8"
200
      >
201
        <div className="flex items-end justify-between">
202
          <h2 className="display text-5xl sm:text-7xl">The Road</h2>
203
          <span className="kicker">03 / Cities</span>
204
        </div>
205
        <div className="mt-10 grid gap-px sm:grid-cols-2">
206
          {cities.map((c) => (
207
            <Link
208
              key={c.id}
209
              href={`/city/${c.slug}`}
210
              className="group flex items-end justify-between border-t border-[var(--line)] py-10"
211
            >
212
              <div>
213
                <span className="kicker text-ash">{c.metroLabel}</span>
214
                <h3 className="display mt-2 text-5xl group-hover:text-gold sm:text-6xl">
215
                  {c.name}
216
                </h3>
217
              </div>
218
              <span className="kicker text-gold">Enter →</span>
219
            </Link>
220
          ))}
221
        </div>
222
      </section>
223
 
224
      <footer className="flex flex-wrap items-center justify-between gap-3 border-t border-[var(--line)] px-5 py-8 sm:px-8">
225
        <Link href="/" className="text-xl">
226
          <Wordmark />
227
        </Link>
228
        <div className="flex items-center gap-6">
229
          <Link href="/about" className="kicker text-bone hover:text-gold">
230
            About
231
          </Link>
232
          <span className="kicker text-ash">Chicago Stepping. Your City.</span>
233
        </div>
234
      </footer>
235
    </div>
236
  );
237
}