Finishing up rsvp creation and confirmation from clients
This commit is contained in:
parent
8f1fb324a0
commit
f1b10e172c
6 changed files with 165 additions and 21 deletions
|
|
@ -6,23 +6,29 @@
|
|||
<body>
|
||||
<h1 class="title fontXL textCenter backgroundLightGreen colorWhite">Collin and Lucy's Wedding</h1>
|
||||
<div class="contents fontM">
|
||||
<form action="/api/rsvp" method="post">
|
||||
<form id="rsvps" action="/api/rsvps" method="post">
|
||||
<p>
|
||||
<label for="name-0">Name:</label>
|
||||
<input type="text" id="name-0" name="name"/>
|
||||
Attending:
|
||||
<label for="attending-yes">Yes</label>
|
||||
<input type="radio" id="attending-yes" name="attending" value="true" required/>
|
||||
<label for="attending-no">No</label>
|
||||
<input type="radio" id="attending-no" name="attending" value="false" required/>
|
||||
</p>
|
||||
<p>
|
||||
Age:
|
||||
<label for="age-child-0">Child</label>
|
||||
<input type="radio" id="age-child-0" name="child" value="true"/>
|
||||
<label for="age-adult-0">Adult</label>
|
||||
<input type="radio" id="age-adult-0" name="child" value="false"/>
|
||||
</p>
|
||||
<p>
|
||||
<label for="diet-0">Dietary preferences:</label>
|
||||
<textarea id="diet-0" name="dietaryPreferences"></textarea>
|
||||
<label for="party-size">Party Size:</label>
|
||||
<select name="party-size" name="party-size" id="party-size">
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
<option value="3">3</option>
|
||||
<option value="4">4</option>
|
||||
<option value="5">5</option>
|
||||
</select>
|
||||
</p>
|
||||
<div class="members">
|
||||
</div>
|
||||
<button>RSVP</button>
|
||||
</form>
|
||||
</div>
|
||||
<script src="/rsvp.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
79
client/rsvp.js
Normal file
79
client/rsvp.js
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
let partySize = 0;
|
||||
|
||||
function createNewMember(id) {
|
||||
const memberDiv = document.createElement("div");
|
||||
memberDiv.classList.add("member");
|
||||
|
||||
const innerDiv = document.createElement("div");
|
||||
|
||||
const nameP = document.createElement("p");
|
||||
|
||||
const nameLabel = document.createElement("label");
|
||||
nameLabel.htmlFor = `name-${id}`;
|
||||
nameLabel.innerHTML = "Name:";
|
||||
|
||||
const nameInput = document.createElement("input");
|
||||
nameInput.type = "text";
|
||||
nameInput.id = `name-${id}`;
|
||||
nameInput.name = `name-${id}`;
|
||||
nameInput.required = true;
|
||||
|
||||
nameP.appendChild(nameLabel);
|
||||
nameP.appendChild(nameInput);
|
||||
|
||||
const childP = document.createElement("p");
|
||||
|
||||
const childLabel = document.createElement("label");
|
||||
childLabel.htmlFor = `child-${id}`;
|
||||
childLabel.innerHTML = "Child:";
|
||||
|
||||
const childInput = document.createElement("input");
|
||||
childInput.type = "checkbox";
|
||||
childInput.id = `child-${id}`;
|
||||
childInput.name = `child-${id}`;
|
||||
|
||||
childP.appendChild(childLabel);
|
||||
childP.appendChild(childInput);
|
||||
|
||||
innerDiv.appendChild(nameP);
|
||||
innerDiv.appendChild(childP);
|
||||
|
||||
const dietP = document.createElement("p");
|
||||
|
||||
const dietLabel = document.createElement("label");
|
||||
dietLabel.htmlFor = `diet-${id}`;
|
||||
dietLabel.innerHTML = "Dietary preferences:";
|
||||
|
||||
const dietInput = document.createElement("textarea");
|
||||
dietInput.id = `diet-${id}`;
|
||||
dietInput.name = `dietaryPreferences-${id}`;
|
||||
|
||||
dietP.appendChild(dietLabel);
|
||||
dietP.appendChild(dietInput);
|
||||
|
||||
memberDiv.appendChild(innerDiv);
|
||||
memberDiv.appendChild(dietP);
|
||||
|
||||
document.querySelector("div.members").appendChild(memberDiv);
|
||||
}
|
||||
|
||||
function updatePartySize(newPartySize) {
|
||||
if (newPartySize > partySize) {
|
||||
for (let i = partySize; i < newPartySize; i++) {
|
||||
createNewMember(partySize);
|
||||
}
|
||||
} else if (newPartySize < partySize) {
|
||||
for (let i = partySize; i > newPartySize; i--) {
|
||||
document.querySelector("div.members").lastChild.remove();
|
||||
}
|
||||
}
|
||||
partySize = newPartySize;
|
||||
}
|
||||
|
||||
window.onload = function () {
|
||||
const partySizeDropdown = document.querySelector("select#party-size");
|
||||
partySizeDropdown.addEventListener("change", () => {
|
||||
updatePartySize(Number.parseInt(partySizeDropdown.value));
|
||||
});
|
||||
updatePartySize(1);
|
||||
};
|
||||
15
client/rsvp_confirmed.html
Normal file
15
client/rsvp_confirmed.html
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="title fontXL textCenter backgroundLightGreen colorWhite">Collin and Lucy's Wedding</h1>
|
||||
<div class="contents fontM">
|
||||
See you there!
|
||||
<br/>
|
||||
<a href="/">Back</a>
|
||||
</div>
|
||||
<script src="/rsvp_confirmed.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -146,7 +146,7 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
/* #endregion
|
||||
/* #endregion */
|
||||
|
||||
/* #region rsvp */
|
||||
.rsvpButton {
|
||||
|
|
@ -161,4 +161,24 @@ body {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
form#rsvps {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
form#rsvps div#members {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
form#rsvps div.members {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
form#rsvps div.members div.member div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
/* #endregion */
|
||||
|
|
@ -2,10 +2,10 @@ package main
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
|
@ -24,7 +24,6 @@ func getStaticFile(relPath string, contentType string, w http.ResponseWriter) {
|
|||
|
||||
w.Header().Add("Content-Type", contentType)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Printf("%s\n", w.Header().Get("Content-Type"))
|
||||
w.Write(file)
|
||||
}
|
||||
|
||||
|
|
@ -38,9 +37,15 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
case r.Method == "GET" && r.URL.Path == "/rsvp":
|
||||
getStaticFile("../client/rsvp.html", "text/html", w)
|
||||
|
||||
case r.Method == "GET" && r.URL.Path == "/rsvp_confirmed":
|
||||
getStaticFile("../client/rsvp_confirmed.html", "text/html", w)
|
||||
|
||||
case r.Method == "GET" && r.URL.Path == "/index.js":
|
||||
getStaticFile("../client/index.js", "text/javascript", w)
|
||||
|
||||
case r.Method == "GET" && r.URL.Path == "/rsvp.js":
|
||||
getStaticFile("../client/rsvp.js", "text/javascript", w)
|
||||
|
||||
case r.Method == "GET" && r.URL.Path == "/style.css":
|
||||
getStaticFile("../client/style.css", "text/css", w)
|
||||
|
||||
|
|
@ -56,9 +61,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
fmt.Fprintf(w, "%#v", rsvps)
|
||||
|
||||
case r.Method == "POST" && r.URL.Path == "/api/rsvps":
|
||||
var rsvp Rsvp
|
||||
|
||||
err := json.NewDecoder(r.Body).Decode(&rsvp)
|
||||
err := r.ParseForm()
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
|
|
@ -66,8 +69,29 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
attending := r.Form.Get("attending") == "true"
|
||||
partySize, err := strconv.ParseInt(r.Form.Get("party-size"), 10, 1)
|
||||
|
||||
partyMembers := make([]Member, partySize)
|
||||
for i := range partySize {
|
||||
name := r.Form.Get(fmt.Sprintf("name-%d", i))
|
||||
child := r.Form.Has(fmt.Sprintf("child-%d", i)) && r.Form.Get(fmt.Sprintf("child-%d", i)) == "true"
|
||||
dietaryPreferences := r.Form.Get(fmt.Sprintf("diet-%d", i))
|
||||
member := Member{
|
||||
Name: name,
|
||||
Child: child,
|
||||
DietaryPreferences: dietaryPreferences,
|
||||
}
|
||||
partyMembers[i] = member
|
||||
}
|
||||
|
||||
rsvp := Rsvp{
|
||||
Attending: attending,
|
||||
PartySize: partySize,
|
||||
PartyMembers: partyMembers,
|
||||
}
|
||||
|
||||
_, err = rsvp.CreateRsvp(h.db)
|
||||
fmt.Printf("%#v\n", rsvp)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
|
|
@ -78,7 +102,8 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
if h.ntfy != nil {
|
||||
SendRsvpNotification(h.ntfy, &rsvp)
|
||||
}
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
w.Header().Add("Location", "/rsvp_confirmed")
|
||||
w.WriteHeader(http.StatusSeeOther)
|
||||
default:
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,6 @@ func (rsvp *Rsvp) CreateRsvp(db *sql.DB) (int64, error) {
|
|||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
fmt.Printf("%s\n", partyMembersBytes)
|
||||
|
||||
result, err := db.Exec(
|
||||
"INSERT INTO rsvps (attending, partySize, partyMembers) VALUES (?, ?, ?);",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue