Public
HTTP
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Readme

DNDoodle

My DND group has used doodle for ages to schedule our sessions, but it never really worked that great for us. We just didn't need that many features. This was my very first val and honestly, I couldn't be happier with it.

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
/**
* This enhanced DNDoodle app now includes a feature for the poll creator to set the end date of the poll,
* and a checkbox for users to indicate if they are the DM. The DM's availability is treated as special
* and is displayed differently in the results view.
* The app uses React for the frontend and SQLite for data persistence.
* It features improved styling, interactive elements, and email functionality.
*/
/** @jsxImportSource https://esm.sh/react */
import { addDays, format, parse } from "https://esm.sh/date-fns";
import React, { useEffect, useState } from "https://esm.sh/react";
import { createRoot } from "https://esm.sh/react-dom/client";
function App() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [creatorEmail, setCreatorEmail] = useState("");
const [groupCode, setGroupCode] = useState("");
const [groupName, setGroupName] = useState("");
const [availability, setAvailability] = useState({});
const [groupAvailability, setGroupAvailability] = useState({});
const [bestDate, setBestDate] = useState("");
const [isCreatingGroup, setIsCreatingGroup] = useState(false);
const [createdGroupCode, setCreatedGroupCode] = useState("");
const [createdGroupName, setCreatedGroupName] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [message, setMessage] = useState("");
const [editToken, setEditToken] = useState("");
const [editLink, setEditLink] = useState("");
const [groupShareLink, setGroupShareLink] = useState("");
const [confirmNoEmail, setConfirmNoEmail] = useState(false);
const [allRespondents, setAllRespondents] = useState([]);
const [totalResponses, setTotalResponses] = useState(0);
const [sessionJoined, setSessionJoined] = useState(false);
const [pollDuration, setPollDuration] = useState(2); // Default to 2 weeks
const [pollEndDate, setPollEndDate] = useState("");
const [isDM, setIsDM] = useState(false);
const [showDatesWithoutDM, setShowDatesWithoutDM] = useState(false);
useEffect(() => {
const params = new URLSearchParams(window.location.search);
const code = params.get("code");
const token = params.get("token");
if (code) {
setGroupCode(code);
fetchGroupAvailability(code);
}
if (token) {
setEditToken(token);
fetchUserAvailability(token);
}
}, []);
const fetchGroupAvailability = async (code) => {
setIsLoading(true);
try {
const response = await fetch(`/availability?code=${code}`);
if (!response.ok) {
throw new Error("Session Poll not found");
}
const data = await response.json();
setGroupAvailability(data.availability);
setBestDate(data.bestDate);
setGroupName(data.groupName);
setAllRespondents(data.allRespondents);
setTotalResponses(data.totalResponses);
setPollEndDate(data.pollEndDate);
setSessionJoined(true);
} catch (error) {
setMessage(
error.message === "Session Poll not found"
? "This session poll doesn't exist. Please check the code and try again."
: "Failed to load session poll data. Please try again.",
);
setGroupCode("");
setSessionJoined(false);
} finally {
setIsLoading(false);
}
};
const fetchUserAvailability = async (token) => {
setIsLoading(true);
try {
const response = await fetch(`/user-availability?token=${token}`);
const data = await response.json();
setName(data.name);
setEmail(data.email);
setAvailability(data.availability);
setGroupCode(data.groupCode);
setIsDM(data.isDM);
fetchGroupAvailability(data.groupCode);
setMessage("Your availability data loaded successfully!");
setTimeout(() => setMessage(""), 3000);
} catch (error) {
setMessage("Failed to load your availability data. Please try again.");
} finally {
setIsLoading(false);
}
};
csl_-dndoodle.web.val.run
August 26, 2024