summaryrefslogtreecommitdiff
path: root/haunt
diff options
context:
space:
mode:
authorJakob L. Kreuze <zerodaysfordays@sdf.org>2022-04-12 20:05:58 -0400
committerJakob L. Kreuze <zerodaysfordays@sdf.org>2022-05-08 19:10:19 -0400
commitc3ef51bc753f48607032e77d0b344453c7142141 (patch)
tree67dcba87051ad42d67393e3f63886ea3954a722c /haunt
parentf6bd35e8e10faf4db80d6c8ccb45a5beae44c2be (diff)
[scheme] Initial RSVP implementation
Diffstat (limited to 'haunt')
-rw-r--r--haunt/pages/rsvp.sxml37
-rw-r--r--haunt/static/css/style.css16
-rw-r--r--haunt/static/js/rsvp.js118
3 files changed, 171 insertions, 0 deletions
diff --git a/haunt/pages/rsvp.sxml b/haunt/pages/rsvp.sxml
new file mode 100644
index 0000000..617350f
--- /dev/null
+++ b/haunt/pages/rsvp.sxml
@@ -0,0 +1,37 @@
+(use-modules (jakob theme)
+ (jakob utils sxml))
+
+(theme
+ #:title "You've Been Invited to an Event!"
+ #:content
+ `((div (@ (id "rsvp"))
+ (div (@ (id "loading"))
+ ,(image "hourglass.gif")
+ (p "Loading..."))
+ (div (@ (id "event-info")))
+ (form (@ (id "rsvp-input") (hidden #t))
+ (fieldset
+ (legend "Your Info")
+ (label (@ (for "name")) "Name:")
+ (input (@ (type "text") (id "name") (name "name") (required #t) (size 24)))
+ (label (@ (for "email")) "Email:")
+ (input (@ (type "text") (id "email") (name "email") (required #t) (size 24))))
+ (fieldset
+ (legend "RSVP Status")
+ (input (@ (type "radio") (id "attending") (name "rsvp")))
+ (label (@ (for "attending")) "Attending")
+ (input (@ (type "radio") (id "tentative") (name "rsvp")))
+ (label (@ (for "tentative")) "Tentative")
+ (input (@ (type "radio") (id "not-attending") (name "rsvp")))
+ (label (@ (for "not-attending")) "Not Attending"))
+ (fieldset
+ (legend "Guests")
+ (div (@ (id "guest-view")))
+ (input (@ (type "button") (id "add-entry") (value "+")))
+ (input (@ (type "button") (id "remove-entry") (value "-"))))
+ (fieldset
+ (legend "All Set?")
+ (input (@ (type "button") (id "submit-form") (value "Submit")))))
+ (div (@ (id "rsvp-global"))))
+
+ ,(script "rsvp.js")))
diff --git a/haunt/static/css/style.css b/haunt/static/css/style.css
index f6a1c08..58db3a9 100644
--- a/haunt/static/css/style.css
+++ b/haunt/static/css/style.css
@@ -408,3 +408,19 @@ button {
background-position: 1.5em 50%;
padding: 0.25em 1em 0.25em 7em;
}
+
+#loading {
+ border: 1px solid;
+ width: fit-content;
+ padding: 5px;
+ margin: auto;
+}
+
+fieldset {
+ padding: 12px;
+ margin: 15px;
+}
+
+#rsvp-input input {
+ margin: 0px 16px;
+}
diff --git a/haunt/static/js/rsvp.js b/haunt/static/js/rsvp.js
new file mode 100644
index 0000000..9ba98ac
--- /dev/null
+++ b/haunt/static/js/rsvp.js
@@ -0,0 +1,118 @@
+/*
+ * rsvp.js -- Simple web-based RSVP tool.
+ * Copyright © 2022 Jakob L. Kreuze <zerodaysfordays@sdf.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+const urlParams = new URLSearchParams(window.location.search);
+if (!urlParams.get("i")) {
+ document.getElementById("loading").remove();
+ let elem = document.createElement("p");
+ elem.innerHTML = "No invitation code provided.";
+ document.getElementById("rsvp").appendChild(elem);
+} else {
+ let xhr = new XMLHttpRequest();
+ xhr.open("GET", `http://localhost:8081/api/rsvp/event-info?i=${urlParams.get("i")}`);
+ xhr.send();
+ xhr.onload = function(data) {
+ document.getElementById("loading").remove();
+ if (xhr.status != 200) {
+ let elem = document.createElement("p");
+ elem.innerHTML = "Invalid invitation code.";
+ document.getElementById("rsvp").appendChild(elem);
+ } else {
+ document.getElementById("rsvp-input").hidden = false;
+
+ let response = JSON.parse(xhr.response);
+
+ let elem = document.createElement("h1");
+ elem.innerHTML = response.title;
+ document.getElementById("event-info").appendChild(elem);
+
+ elem = document.createElement("p");
+ elem.innerHTML = `Where: ${response.location}`;
+ document.getElementById("event-info").appendChild(elem);
+
+ elem = document.createElement("p");
+ elem.innerHTML = `When: ${response.date}`;
+ document.getElementById("event-info").appendChild(elem);
+
+ elem = document.createElement("p");
+ elem.innerHTML = response.description;
+ document.getElementById("event-info").appendChild(elem);
+
+ if (response.hasOwnProperty("rsvps")) {
+ elem = document.createElement("h2");
+ elem.innerHTML = "Current RSVPs";
+ document.getElementById("rsvp-global").appendChild(elem);
+
+ elem = document.createElement("table");
+ document.getElementById("rsvp-global").appendChild(elem);
+
+ for (let rsvp of response.rsvps) {
+ console.log(rsvp.name);
+ let container = document.createElement("tr");
+ let field = document.createElement("td");
+ field.textContent = rsvp.name;
+ container.append(field);
+ field = document.createElement("td");
+ field.textContent = rsvp.email;
+ container.append(field);
+ field = document.createElement("td");
+ field.textContent = rsvp.guests.replace(',', ', ');
+ container.append(field);
+ field = document.createElement("td");
+ field.textContent = rsvp.attending;
+ container.append(field);
+ elem.appendChild(container);
+ }
+ }
+
+ console.log(response);
+ }
+ }
+ xhr.onerror = function(error) {
+ throw new Error(`Request failed: ${error}`);
+ }
+}
+
+const guestView = document.getElementById("guest-view");
+const addEntry = document.getElementById("add-entry");
+const removeEntry = document.getElementById("remove-entry");
+const submitButton = document.getElementById("submit-form");
+const form = document.getElementById("rsvp-input");
+
+addEntry.addEventListener("click", () => {
+ let i = guestView.childNodes.length;
+ let elem = document.createElement("input");
+ elem.type = "text";
+ elem.id = `guest-${i}`;
+ guestView.appendChild(elem);
+});
+
+removeEntry.addEventListener("click", () => {
+ if (guestView.lastChild) {
+ guestView.lastChild.remove();
+ }
+});
+
+function submitForm() {
+ let data = new FormData(form);
+ console.log(data);
+}
+
+submitButton.addEventListener("click", submitForm);
+submitButton.addEventListener("submit", submitForm);