Graphical PDS migrator for AT Protocol
1import { useEffect, useState } from "preact/hooks";
2import { IS_BROWSER } from "fresh/runtime";
3import { Link } from "../components/Link.tsx";
4
5/**
6 * The user interface for the ticket component.
7 * @type {User}
8 */
9interface User {
10 did: string;
11 handle?: string;
12}
13
14/**
15 * The ticket component for the landing page.
16 * @returns The ticket component
17 * @component
18 */
19export default function Ticket() {
20 const [user, setUser] = useState<User | null>(null);
21
22 useEffect(() => {
23 if (!IS_BROWSER) return;
24
25 const fetchUser = async () => {
26 try {
27 const response = await fetch("/api/me", {
28 credentials: "include",
29 });
30 if (!response.ok) {
31 throw new Error("Failed to fetch user profile");
32 }
33 const userData = await response.json();
34 setUser(
35 userData
36 ? {
37 did: userData.did,
38 handle: userData.handle,
39 }
40 : null,
41 );
42 } catch (error) {
43 console.error("Failed to fetch user:", error);
44 setUser(null);
45 }
46 };
47
48 fetchUser();
49 }, []);
50
51 return (
52 <div class="max-w-4xl mx-auto">
53 <div class="ticket mb-8 bg-white dark:bg-slate-800 p-6 relative before:absolute before:bg-white dark:before:bg-slate-800 before:-z-10 after:absolute after:inset-0 after:bg-slate-200 dark:after:bg-slate-700 after:-z-20 [clip-path:polygon(0_0,20px_0,100%_0,100%_calc(100%-20px),calc(100%-20px)_100%,0_100%,0_calc(100%-20px),20px_100%)] after:[clip-path:polygon(0_0,20px_0,100%_0,100%_calc(100%-20px),calc(100%-20px)_100%,0_100%,0_calc(100%-20px),20px_100%)]">
54 <div class="boarding-label text-amber-500 dark:text-amber-400 font-mono font-bold tracking-wider text-sm mb-4">
55 BOARDING PASS
56 </div>
57 <div class="flex justify-between items-start mb-4">
58 <h3 class="text-2xl font-mono">WHAT IS AIRPORT?</h3>
59 <div class="text-sm font-mono text-gray-500 dark:text-gray-400">
60 GATE A1
61 </div>
62 </div>
63 <div class="passenger-info text-slate-600 dark:text-slate-300 font-mono text-sm mb-4">
64 PASSENGER: {(user?.handle || "UNKNOWN").toUpperCase()}
65 <br />
66 DESTINATION: NEW PDS
67 </div>
68 <p class="mb-4">
69 ATP Airport is your digital terminal for AT Protocol account actions.
70 We help you smoothly transfer your PDS account between different
71 providers – no lost luggage, just a first-class experience for your
72 data's journey to its new home.
73 </p>
74 <p>
75 Think you might need to migrate in the future but your PDS might be
76 hostile or offline? No worries! You can go to the{" "}
77 <Link
78 href="/ticket-booth"
79 isExternal
80 class="text-blue-600 dark:text-blue-400"
81 >
82 ticket booth
83 </Link>{" "}
84 and get a PLC key to use for account recovery in the future. Soon
85 you'll also be able to go to baggage claim (take the air shuttle to
86 terminal four) and get a downloadable backup of all your current PDS
87 data in case that were to happen.
88 </p>
89 </div>
90
91 <div class="ticket mb-8 bg-white dark:bg-slate-800 p-6 relative before:absolute before:bg-white dark:before:bg-slate-800 before:-z-10 after:absolute after:inset-0 after:bg-slate-200 dark:after:bg-slate-700 after:-z-20 [clip-path:polygon(0_0,20px_0,100%_0,100%_calc(100%-20px),calc(100%-20px)_100%,0_100%,0_calc(100%-20px),20px_100%)] after:[clip-path:polygon(0_0,20px_0,100%_0,100%_calc(100%-20px),calc(100%-20px)_100%,0_100%,0_calc(100%-20px),20px_100%)]">
92 <div class="boarding-label text-amber-500 dark:text-amber-400 font-mono font-bold tracking-wider text-sm mb-4">
93 FLIGHT DETAILS
94 </div>
95 <div class="flex justify-between items-start mb-4">
96 <h3 class="text-2xl font-mono">GET READY TO FLY</h3>
97 <div class="text-sm font-mono text-gray-500 dark:text-gray-400">
98 SEAT: 1A
99 </div>
100 </div>
101 <div class="passenger-info mb-4 text-slate-600 dark:text-slate-300 font-mono text-sm">
102 CLASS: FIRST CLASS MIGRATION
103 <br />
104 FLIGHT: ATP-2024
105 </div>
106 <ol class="list-decimal list-inside space-y-3">
107 <li>Check in with your current PDS credentials</li>
108 <li>Select your destination PDS</li>
109 <li>Go through security</li>
110 <li>Sit back while we handle your data transfer</li>
111 </ol>
112 <div class="mt-6 text-sm text-gray-600 dark:text-gray-400 border-t border-dashed pt-4 border-slate-200 dark:border-slate-700">
113 Coming from a Bluesky PDS? This is currently a ONE WAY TICKET because
114 Bluesky doesn't support transfers back yet. Although they claim they
115 will support it in the future, assume you won't be able to.
116 </div>
117 <div class="flight-info mt-6 flex items-center justify-between text-slate-600 dark:text-slate-300 font-mono text-sm">
118 <div>
119 <div class="text-xs text-gray-500 dark:text-gray-400">FROM</div>
120 <div>CURRENT PDS</div>
121 </div>
122 <div class="text-amber-500 dark:text-amber-400 text-4xl">➜</div>
123 <div class="content-end">
124 <div class="text-xs text-gray-500 dark:text-gray-400">TO</div>
125 <div>NEW PDS</div>
126 </div>
127 </div>
128 </div>
129 </div>
130 );
131}