๐Ÿ“ฆ cloudflare / vinext

๐Ÿ“„ page.tsx ยท 102 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102import { headers, cookies } from "next/headers";
import Link from "next/link";
import type { Metadata } from "next";
import { addGuestbookEntry } from "../actions.js";
import { getGuestbookEntries } from "../_guestbook.js";
import { s } from "../_styles.js";

export const metadata: Metadata = {
  title: "About",
  description: "About page demonstrating next/headers and cookies",
};

export default async function AboutPage() {
  // next/headers โ€” read request headers
  const h = await headers();
  const userAgent = h.get("user-agent") ?? "unknown";
  const acceptLanguage = h.get("accept-language") ?? "unknown";

  // next/headers โ€” read cookies
  const c = await cookies();
  const theme = c.get("theme")?.value ?? "not set";
  const visitCount = c.get("visit-count")?.value ?? "0";

  const entries = getGuestbookEntries();

  return (
    <main style={s.page}>
      <div>
        <h1 style={s.title}>About</h1>
        <p style={s.subtitle}>
          This page demonstrates <code>headers()</code>,{" "}
          <code>cookies()</code>, and server actions.
        </p>
      </div>

      {/* Demonstrates headers() */}
      <section style={s.card}>
        <h2 style={s.label}>headers()</h2>
        <dl style={s.dl}>
          <dt style={s.dt}>User-Agent</dt>
          <dd data-testid="user-agent" style={s.dd}>
            {userAgent.slice(0, 80)}
          </dd>
          <dt style={s.dt}>Accept-Language</dt>
          <dd data-testid="accept-language" style={s.dd}>
            {acceptLanguage}
          </dd>
        </dl>
      </section>

      {/* Demonstrates cookies() */}
      <section style={s.card}>
        <h2 style={s.label}>cookies()</h2>
        <dl style={s.dl}>
          <dt style={s.dt}>Theme</dt>
          <dd data-testid="theme-cookie" style={s.dd}>
            {theme}
          </dd>
          <dt style={s.dt}>Visit Count</dt>
          <dd data-testid="visit-count" style={s.dd}>
            {visitCount}
          </dd>
        </dl>
      </section>

      {/* Server action โ€” form with "use server" action */}
      <section style={s.card}>
        <h2 style={s.label}>Server Action</h2>
        <form
          action={addGuestbookEntry}
          style={{ display: "flex", gap: "0.5rem" }}
        >
          <input
            name="name"
            placeholder="Sign the guestbook..."
            required
            data-testid="guestbook-input"
            style={s.input}
          />
          <button type="submit" data-testid="guestbook-submit" style={s.btn}>
            Sign
          </button>
        </form>
        {entries.length > 0 && (
          <ul
            data-testid="guestbook-list"
            style={{ marginTop: "0.75rem", listStyle: "none", display: "flex", gap: "0.5rem", flexWrap: "wrap" }}
          >
            {entries.map((entry, i) => (
              <li key={i} style={s.tag}>
                {entry}
              </li>
            ))}
          </ul>
        )}
      </section>

      <Link href="/">โ† Back to home</Link>
    </main>
  );
}