Scratch space for learning atproto app development
1import { AtUri } from '@atproto/syntax'
2import type { Status } from '#/db/schema'
3import { html } from '../view'
4import { shell } from './shell'
5
6const STATUS_OPTIONS = [
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
36type Props = {
37 statuses: Status[]
38 didHandleMap: Record<string, string>
39 profile?: { displayName?: string; handle: string }
40}
41
42export function home(props: Props) {
43 return shell({
44 title: 'Home',
45 content: content(props),
46 })
47}
48
49function content({ statuses, didHandleMap, profile }: Props) {
50 return html`<div id="root">
51 <div class="error"></div>
52 <div id="header">
53 <h1>Statusphere</h1>
54 <p>Set your status on the Atmosphere.</p>
55 </div>
56 <div class="container">
57 <div class="card">
58 ${profile
59 ? html`<form action="/logout" method="post" class="session-form">
60 <div>
61 Hi, <strong>${profile.displayName || profile.handle}</strong>.
62 what's your status today?
63 </div>
64 <div>
65 <button type="submit">Log out</button>
66 </div>
67 </form>`
68 : html`<p><a href="/login">Log in</a> to set your status!</p>`}
69 </div>
70 <div class="">
71 <div class="status-options">
72 ${STATUS_OPTIONS.map(
73 (status) =>
74 html`<div class="status-option" data-value="${status}">
75 ${status}
76 </div>`
77 )}
78 </div>
79 </div>
80 <div class="status-line no-line">
81 <div class="status">👍</div>
82 <div class="desc">
83 <a class="author" href="/">@pfrazee.com</a>
84 is feeling 👍 on Aug 12, 2024
85 </div>
86 </div>
87 <div class="status-line">
88 <div class="status">👍</div>
89 <div class="desc">
90 <a class="author" href="/">@pfrazee.com</a>
91 is feeling 👍 on Aug 12, 2024
92 </div>
93 </div>
94 <div class="status-line">
95 <div class="status">👍</div>
96 <div class="desc">
97 <a class="author" href="/">@pfrazee.com</a>
98 is feeling 👍 on Aug 12, 2024
99 </div>
100 </div>
101 <div class="status-line">
102 <div class="status">👍</div>
103 <div class="desc">
104 <a class="author" href="/">@pfrazee.com</a>
105 is feeling 👍 on Aug 12, 2024
106 </div>
107 </div>
108 <div class="status-line">
109 <div class="status">👍</div>
110 <div class="desc">
111 <a class="author" href="/">@pfrazee.com</a>
112 is feeling 👍 on Aug 12, 2024
113 </div>
114 </div>
115 <div class="status-line">
116 <div class="status">👍</div>
117 <div class="desc">
118 <a class="author" href="/">@pfrazee.com</a>
119 is feeling 👍 on Aug 12, 2024
120 </div>
121 </div>
122 ${statuses.map((status, i) => {
123 const handle = didHandleMap[status.authorDid] || status.authorDid
124 return html`
125 <div class=${i === 0 ? 'status-line no-line' : 'status-line'}>
126 <div>
127 <div class="status">${status.status}</div>
128 </div>
129 <div class="desc">
130 <a class="author" href=${toBskyLink(handle)}>@${handle}</a>
131 is feeling ${status.status} on ${ts(status)}
132 </div>
133 </div>
134 `
135 })}
136 </div>
137 <script src="/public/home.js"></script>
138 </div>`
139}
140
141function toBskyLink(did: string) {
142 return `https://bsky.app/profile/${did}`
143}
144
145function ts(status: Status) {
146 const indexedAt = new Date(status.indexedAt)
147 const updatedAt = new Date(status.updatedAt)
148 if (updatedAt > indexedAt) return updatedAt.toDateString()
149 return indexedAt.toDateString()
150}