Fix answer submission failing

This commit is contained in:
illyum 2024-09-03 23:36:02 -06:00
parent 62f2f6002b
commit 8d215f8881

344
main.go
View File

@ -1,204 +1,208 @@
package main package main
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"html/template" "html/template"
"log" "log"
"net/http" "net/http"
_ "github.com/mattn/go-sqlite3"
_ "github.com/mattn/go-sqlite3"
) )
type Question struct { type Question struct {
ID int ID int
QuestionText string QuestionText string
QuestionType string QuestionType string
} }
var db *sql.DB var db *sql.DB
func renderForm(w http.ResponseWriter, r *http.Request) { func renderForm(w http.ResponseWriter, r *http.Request) {
rows, err := db.Query("SELECT question_text, question_type FROM questions ORDER BY question_order") rows, err := db.Query("SELECT id, question_text, question_type FROM questions ORDER BY question_order")
if err != nil { if err != nil {
log.Printf("Error fetching questions: %v\n", err) log.Printf("Error fetching questions: %v\n", err)
http.Error(w, "Failed to fetch form questions", http.StatusInternalServerError) http.Error(w, "Failed to fetch form questions", http.StatusInternalServerError)
return return
} }
defer rows.Close() defer rows.Close()
var questions []Question var questions []Question
for rows.Next() { for rows.Next() {
var question Question var question Question
err := rows.Scan(&question.QuestionText, &question.QuestionType) err := rows.Scan(&question.ID, &question.QuestionText, &question.QuestionType)
if err != nil { if err != nil {
log.Printf("Error scanning question: %v\n", err) log.Printf("Error scanning question: %v\n", err)
continue continue
} }
questions = append(questions, question) questions = append(questions, question)
} }
tmpl := template.Must(template.ParseFiles("index.html")) tmpl := template.Must(template.ParseFiles("index.html"))
tmpl.Execute(w, questions) tmpl.Execute(w, questions)
} }
func handleFormSubmit(w http.ResponseWriter, r *http.Request) { func handleFormSubmit(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost { if r.Method != http.MethodPost {
http.Error(w, "Invalid request method", http.StatusMethodNotAllowed) http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
return return
} }
r.ParseForm() err := r.ParseForm()
if err != nil {
log.Printf("Error parsing form: %v\n", err)
http.Error(w, "Failed to parse form", http.StatusInternalServerError)
return
}
insertAnswerQuery := `INSERT INTO answers (question_id, answer) VALUES (?, ?)`
rows, err := db.Query("SELECT id FROM questions") tx, err := db.Begin()
if err != nil { if err != nil {
log.Printf("Error fetching questions: %v\n", err) log.Printf("Error starting transaction: %v\n", err)
http.Error(w, "Failed to fetch questions", http.StatusInternalServerError) http.Error(w, "Failed to save answers", http.StatusInternalServerError)
return return
} }
defer rows.Close() defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
var questionID int for key, values := range r.Form {
for rows.Next() { if len(key) > 7 && key[:7] == "custom_" {
err := rows.Scan(&questionID) var questionID int
if err != nil { _, err := fmt.Sscanf(key, "custom_%d", &questionID)
log.Printf("Error scanning question ID: %v\n", err) if err != nil {
continue log.Printf("Error parsing question ID from field name %s: %v\n", key, err)
} continue
fieldName := fmt.Sprintf("custom_%d", questionID) }
fieldValue := r.FormValue(fieldName)
if fieldValue != "" { answer := values[0]
insertQuery := `INSERT INTO answers (question_id, answer) VALUES (?, ?)` _, err = tx.Exec(insertAnswerQuery, questionID, answer)
_, err = db.Exec(insertQuery, questionID, fieldValue) if err != nil {
if err != nil { log.Printf("Error saving answer for question %d: %v\n", questionID, err)
log.Printf("Error saving answer: %v\n", err) http.Error(w, "Failed to save answers", http.StatusInternalServerError)
http.Error(w, "Failed to save answer", http.StatusInternalServerError) return
return }
} }
} else { }
log.Printf("No answer found for question %d", questionID) fmt.Fprintf(w, "Thank you for your submission!")
}
}
fmt.Fprintf(w, "Thank you for your submission!")
} }
func handleAdmin(w http.ResponseWriter, r *http.Request) { func handleAdmin(w http.ResponseWriter, r *http.Request) {
rows, err := db.Query(` rows, err := db.Query(`
SELECT q.question_text, a.answer SELECT q.question_text, a.answer
FROM answers a FROM answers a
JOIN questions q ON a.question_id = q.id JOIN questions q ON a.question_id = q.id
ORDER BY q.question_order ORDER BY q.question_order
`) `)
if err != nil { if err != nil {
log.Printf("Error fetching submissions: %v\n", err) log.Printf("Error fetching submissions: %v\n", err)
http.Error(w, "Failed to fetch submissions", http.StatusInternalServerError) http.Error(w, "Failed to fetch submissions", http.StatusInternalServerError)
return return
} }
defer rows.Close() defer rows.Close()
var submissions []struct { var submissions []struct {
QuestionText string QuestionText string
Answer string Answer string
} }
for rows.Next() { for rows.Next() {
var submission struct { var submission struct {
QuestionText string QuestionText string
Answer string Answer string
} }
err := rows.Scan(&submission.QuestionText, &submission.Answer) err := rows.Scan(&submission.QuestionText, &submission.Answer)
if err != nil { if err != nil {
log.Printf("Error scanning submission: %v\n", err) log.Printf("Error scanning submission: %v\n", err)
continue continue
} }
submissions = append(submissions, submission) submissions = append(submissions, submission)
} }
tmpl := template.Must(template.ParseFiles("admin.html")) tmpl := template.Must(template.ParseFiles("admin.html"))
tmpl.Execute(w, submissions) tmpl.Execute(w, submissions)
} }
func handleAddQuestion(w http.ResponseWriter, r *http.Request) { func handleAddQuestion(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost { if r.Method != http.MethodPost {
http.Error(w, "Invalid request method", http.StatusMethodNotAllowed) http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
return return
} }
r.ParseForm() r.ParseForm()
questionText := r.FormValue("question_text") questionText := r.FormValue("question_text")
insertQuery := `INSERT INTO questions (question_text, question_type, question_order) VALUES (?, 'text', (SELECT IFNULL(MAX(question_order), 0) + 1 FROM questions));` insertQuery := `INSERT INTO questions (question_text, question_type, question_order) VALUES (?, 'text', (SELECT IFNULL(MAX(question_order), 0) + 1 FROM questions));`
_, err := db.Exec(insertQuery, questionText) _, err := db.Exec(insertQuery, questionText)
if err != nil { if err != nil {
log.Printf("Error adding new question: %v\n", err) log.Printf("Error adding new question: %v\n", err)
http.Error(w, "Failed to add question", http.StatusInternalServerError) http.Error(w, "Failed to add question", http.StatusInternalServerError)
return return
} }
http.Redirect(w, r, "/manage", http.StatusSeeOther) http.Redirect(w, r, "/manage", http.StatusSeeOther)
} }
func handleManage(w http.ResponseWriter, r *http.Request) { func handleManage(w http.ResponseWriter, r *http.Request) {
rows, err := db.Query("SELECT id, question_text, question_type FROM questions ORDER BY question_order") rows, err := db.Query("SELECT id, question_text, question_type FROM questions ORDER BY question_order")
if err != nil { if err != nil {
log.Printf("Error fetching questions: %v\n", err) log.Printf("Error fetching questions: %v\n", err)
http.Error(w, "Failed to fetch questions", http.StatusInternalServerError) http.Error(w, "Failed to fetch questions", http.StatusInternalServerError)
return return
} }
defer rows.Close() defer rows.Close()
var questions []Question var questions []Question
for rows.Next() { for rows.Next() {
var question Question var question Question
err := rows.Scan(&question.ID, &question.QuestionText, &question.QuestionType) err := rows.Scan(&question.ID, &question.QuestionText, &question.QuestionType)
if err != nil { if err != nil {
log.Printf("Error scanning question: %v\n", err) log.Printf("Error scanning question: %v\n", err)
continue continue
} }
questions = append(questions, question) questions = append(questions, question)
} }
if len(questions) == 0 { if len(questions) == 0 {
log.Println("No questions found") log.Println("No questions found")
} }
tmpl := template.Must(template.ParseFiles("manage.html")) tmpl := template.Must(template.ParseFiles("manage.html"))
err = tmpl.Execute(w, questions) err = tmpl.Execute(w, questions)
if err != nil { if err != nil {
log.Printf("Error executing template: %v\n", err) log.Printf("Error executing template: %v\n", err)
} }
} }
func handleRemoveQuestion(w http.ResponseWriter, r *http.Request) { func handleRemoveQuestion(w http.ResponseWriter, r *http.Request) {
questionID := r.URL.Query().Get("id") questionID := r.URL.Query().Get("id")
deleteQuery := `DELETE FROM questions WHERE id = ?` deleteQuery := `DELETE FROM questions WHERE id = ?`
_, err := db.Exec(deleteQuery, questionID) _, err := db.Exec(deleteQuery, questionID)
if err != nil { if err != nil {
log.Printf("Error removing question: %v\n", err) log.Printf("Error removing question: %v\n", err)
http.Error(w, "Failed to remove question", http.StatusInternalServerError) http.Error(w, "Failed to remove question", http.StatusInternalServerError)
return return
} }
http.Redirect(w, r, "/manage", http.StatusSeeOther) http.Redirect(w, r, "/manage", http.StatusSeeOther)
} }
func main() { func main() {
var err error var err error
db, err = sql.Open("sqlite3", "./formdata.db") db, err = sql.Open("sqlite3", "./formdata.db")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
createTableQueries := ` createTableQueries := `
CREATE TABLE IF NOT EXISTS questions ( CREATE TABLE IF NOT EXISTS questions (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
question_text TEXT NOT NULL, question_text TEXT NOT NULL,
@ -207,29 +211,29 @@ func main() {
); );
CREATE TABLE IF NOT EXISTS answers ( CREATE TABLE IF NOT EXISTS answers (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
question_id INTEGER NOT NULL, question_id INTEGER NOT NULL,
answer TEXT NOT NULL, answer TEXT NOT NULL,
FOREIGN KEY (question_id) REFERENCES questions(id) FOREIGN KEY (question_id) REFERENCES questions(id)
); );
` `
_, err = db.Exec(createTableQueries) _, err = db.Exec(createTableQueries)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
return return
} }
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
http.HandleFunc("/", renderForm) http.HandleFunc("/", renderForm)
http.HandleFunc("/submit", handleFormSubmit) http.HandleFunc("/submit", handleFormSubmit)
http.HandleFunc("/admin", handleAdmin) http.HandleFunc("/admin", handleAdmin)
http.HandleFunc("/manage", handleManage) http.HandleFunc("/manage", handleManage)
http.HandleFunc("/manage/add", handleAddQuestion) http.HandleFunc("/manage/add", handleAddQuestion)
http.HandleFunc("/manage/remove", handleRemoveQuestion) http.HandleFunc("/manage/remove", handleRemoveQuestion)
fmt.Println("Server started at :8080") fmt.Println("Server started at :8080")
log.Fatal(http.ListenAndServe(":8080", nil)) log.Fatal(http.ListenAndServe(":8080", nil))
} }