tangled
alpha
login
or
join now
leaflet.pub
/
leaflet
289
fork
atom
a tool for shared writing and social publishing
289
fork
atom
overview
issues
29
pulls
pipelines
add some loaders
awarm.space
10 months ago
ff1acf2c
10876942
+31
-2
3 changed files
expand all
collapse all
unified
split
app
lish
createPub
CreatePubForm.tsx
UpdatePubForm.tsx
components
utils
DotLoader.tsx
+5
-1
app/lish/createPub/CreatePubForm.tsx
···
11
11
import { theme } from "tailwind.config";
12
12
import { getBasePublicationURL, getPublicationURL } from "./getPublicationURL";
13
13
import { string } from "zod";
14
14
+
import { DotLoader } from "components/utils/DotLoader";
14
15
15
16
type DomainState =
16
17
| { status: "empty" }
···
20
21
| { status: "error"; message: string };
21
22
22
23
export const CreatePubForm = () => {
24
24
+
let [formState, setFormState] = useState<"normal" | "loading">("normal");
23
25
let [nameValue, setNameValue] = useState("");
24
26
let [descriptionValue, setDescriptionValue] = useState("");
25
27
let [logoFile, setLogoFile] = useState<File | null>(null);
···
37
39
onSubmit={async (e) => {
38
40
e.preventDefault();
39
41
if (!subdomainValidator.safeParse(domainValue).success) return;
42
42
+
setFormState("loading");
40
43
let data = await createPublication({
41
44
name: nameValue,
42
45
description: descriptionValue,
···
45
48
});
46
49
// Show a spinner while this is happening! Maybe a progress bar?
47
50
setTimeout(() => {
51
51
+
setFormState("normal");
48
52
if (data?.publication)
49
53
router.push(`${getBasePublicationURL(data.publication)}/dashboard`);
50
54
}, 500);
···
121
125
!nameValue || !domainValue || domainState.status !== "valid"
122
126
}
123
127
>
124
124
-
Create Publication!
128
128
+
{formState === "loading" ? <DotLoader /> : "Create Publication!"}
125
129
</ButtonPrimary>
126
130
</div>
127
131
</form>
+8
-1
app/lish/createPub/UpdatePubForm.tsx
···
10
10
import { PubLeafletPublication } from "lexicons/api";
11
11
import { mutate } from "swr";
12
12
import { AddTiny } from "components/Icons/AddTiny";
13
13
+
import { DotLoader } from "components/utils/DotLoader";
14
14
+
import { useToaster } from "components/Toast";
13
15
14
16
export const EditPubForm = () => {
15
17
let pubData = usePublicationData();
16
18
let record = pubData?.record as PubLeafletPublication.Record;
19
19
+
let [formState, setFormState] = useState<"normal" | "loading">("normal");
17
20
18
21
let [nameValue, setNameValue] = useState(record?.name || "");
19
22
let [descriptionValue, setDescriptionValue] = useState(
···
31
34
`url(https://bsky.social/xrpc/com.atproto.sync.getBlob?did=${pubData.identity_did}&cid=${(record.icon.ref as unknown as { $link: string })["$link"]})`,
32
35
);
33
36
}, [pubData]);
37
37
+
let toast = useToaster();
34
38
35
39
return (
36
40
<form
···
38
42
onSubmit={async (e) => {
39
43
if (!pubData) return;
40
44
e.preventDefault();
45
45
+
setFormState("loading");
41
46
let data = await updatePublication({
42
47
uri: pubData.uri,
43
48
name: nameValue,
44
49
description: descriptionValue,
45
50
iconFile: iconFile,
46
51
});
52
52
+
toast({ type: "success", content: "Updated!" });
53
53
+
setFormState("normal");
47
54
mutate("publication-data");
48
55
}}
49
56
>
···
108
115
/>
109
116
110
117
<ButtonPrimary className="place-self-end" type="submit">
111
111
-
Update Publication
118
118
+
{formState === "loading" ? <DotLoader /> : "Update Publication"}
112
119
</ButtonPrimary>
113
120
</form>
114
121
);
+18
components/utils/DotLoader.tsx
···
1
1
+
import { useEffect, useState } from "react";
2
2
+
3
3
+
export function DotLoader() {
4
4
+
let [dots, setDots] = useState(1);
5
5
+
useEffect(() => {
6
6
+
let id = setInterval(() => {
7
7
+
setDots((count) => (count + 1) % 4);
8
8
+
}, 250);
9
9
+
return () => {
10
10
+
clearInterval(id);
11
11
+
};
12
12
+
}, []);
13
13
+
return (
14
14
+
<div className="w-[26px] text-center text-sm">
15
15
+
{".".repeat(dots) + "\u00a0".repeat(3 - dots)}
16
16
+
</div>
17
17
+
);
18
18
+
}