From 8d215f88810ffa4088c9752ff31805da056807e9 Mon Sep 17 00:00:00 2001 From: illyum Date: Tue, 3 Sep 2024 23:36:02 -0600 Subject: [PATCH] Fix answer submission failing --- main.go | 344 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 174 insertions(+), 170 deletions(-) diff --git a/main.go b/main.go index eeb1c76..1352837 100644 --- a/main.go +++ b/main.go @@ -1,204 +1,208 @@ package main import ( - "database/sql" - "fmt" - "html/template" - "log" - "net/http" - _ "github.com/mattn/go-sqlite3" + "database/sql" + "fmt" + "html/template" + "log" + "net/http" + + _ "github.com/mattn/go-sqlite3" ) - type Question struct { - ID int - QuestionText string - QuestionType string + ID int + QuestionText string + QuestionType string } var db *sql.DB func renderForm(w http.ResponseWriter, r *http.Request) { - rows, err := db.Query("SELECT question_text, question_type FROM questions ORDER BY question_order") - if err != nil { - log.Printf("Error fetching questions: %v\n", err) - http.Error(w, "Failed to fetch form questions", http.StatusInternalServerError) - return - } - defer rows.Close() + rows, err := db.Query("SELECT id, question_text, question_type FROM questions ORDER BY question_order") + if err != nil { + log.Printf("Error fetching questions: %v\n", err) + http.Error(w, "Failed to fetch form questions", http.StatusInternalServerError) + return + } + defer rows.Close() - var questions []Question + var questions []Question - for rows.Next() { - var question Question - err := rows.Scan(&question.QuestionText, &question.QuestionType) - if err != nil { - log.Printf("Error scanning question: %v\n", err) - continue - } - questions = append(questions, question) - } + for rows.Next() { + var question Question + err := rows.Scan(&question.ID, &question.QuestionText, &question.QuestionType) + if err != nil { + log.Printf("Error scanning question: %v\n", err) + continue + } + questions = append(questions, question) + } - tmpl := template.Must(template.ParseFiles("index.html")) - tmpl.Execute(w, questions) + tmpl := template.Must(template.ParseFiles("index.html")) + tmpl.Execute(w, questions) } func handleFormSubmit(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodPost { - http.Error(w, "Invalid request method", http.StatusMethodNotAllowed) - return - } + if r.Method != http.MethodPost { + http.Error(w, "Invalid request method", http.StatusMethodNotAllowed) + 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") - if err != nil { - log.Printf("Error fetching questions: %v\n", err) - http.Error(w, "Failed to fetch questions", http.StatusInternalServerError) - return - } - defer rows.Close() + tx, err := db.Begin() + if err != nil { + log.Printf("Error starting transaction: %v\n", err) + http.Error(w, "Failed to save answers", http.StatusInternalServerError) + return + } + defer func() { + if err != nil { + tx.Rollback() + } else { + tx.Commit() + } + }() - var questionID int - for rows.Next() { - err := rows.Scan(&questionID) - if err != nil { - log.Printf("Error scanning question ID: %v\n", err) - continue - } - fieldName := fmt.Sprintf("custom_%d", questionID) - fieldValue := r.FormValue(fieldName) + for key, values := range r.Form { + if len(key) > 7 && key[:7] == "custom_" { + var questionID int + _, err := fmt.Sscanf(key, "custom_%d", &questionID) + if err != nil { + log.Printf("Error parsing question ID from field name %s: %v\n", key, err) + continue + } - if fieldValue != "" { - insertQuery := `INSERT INTO answers (question_id, answer) VALUES (?, ?)` - _, err = db.Exec(insertQuery, questionID, fieldValue) - if err != nil { - log.Printf("Error saving answer: %v\n", err) - http.Error(w, "Failed to save answer", http.StatusInternalServerError) - return - } - } else { - log.Printf("No answer found for question %d", questionID) - } - } - - fmt.Fprintf(w, "Thank you for your submission!") + answer := values[0] + _, err = tx.Exec(insertAnswerQuery, questionID, answer) + if err != nil { + log.Printf("Error saving answer for question %d: %v\n", questionID, err) + http.Error(w, "Failed to save answers", http.StatusInternalServerError) + return + } + } + } + fmt.Fprintf(w, "Thank you for your submission!") } - func handleAdmin(w http.ResponseWriter, r *http.Request) { - rows, err := db.Query(` - SELECT q.question_text, a.answer - FROM answers a - JOIN questions q ON a.question_id = q.id - ORDER BY q.question_order - `) - if err != nil { - log.Printf("Error fetching submissions: %v\n", err) - http.Error(w, "Failed to fetch submissions", http.StatusInternalServerError) - return - } - defer rows.Close() + rows, err := db.Query(` + SELECT q.question_text, a.answer + FROM answers a + JOIN questions q ON a.question_id = q.id + ORDER BY q.question_order + `) + if err != nil { + log.Printf("Error fetching submissions: %v\n", err) + http.Error(w, "Failed to fetch submissions", http.StatusInternalServerError) + return + } + defer rows.Close() - var submissions []struct { - QuestionText string - Answer string - } + var submissions []struct { + QuestionText string + Answer string + } - for rows.Next() { - var submission struct { - QuestionText string - Answer string - } - err := rows.Scan(&submission.QuestionText, &submission.Answer) - if err != nil { - log.Printf("Error scanning submission: %v\n", err) - continue - } - submissions = append(submissions, submission) - } + for rows.Next() { + var submission struct { + QuestionText string + Answer string + } + err := rows.Scan(&submission.QuestionText, &submission.Answer) + if err != nil { + log.Printf("Error scanning submission: %v\n", err) + continue + } + submissions = append(submissions, submission) + } - tmpl := template.Must(template.ParseFiles("admin.html")) - tmpl.Execute(w, submissions) + tmpl := template.Must(template.ParseFiles("admin.html")) + tmpl.Execute(w, submissions) } func handleAddQuestion(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodPost { - http.Error(w, "Invalid request method", http.StatusMethodNotAllowed) - return - } + if r.Method != http.MethodPost { + http.Error(w, "Invalid request method", http.StatusMethodNotAllowed) + return + } - r.ParseForm() - questionText := r.FormValue("question_text") + r.ParseForm() + 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));` - _, err := db.Exec(insertQuery, questionText) - if err != nil { - log.Printf("Error adding new question: %v\n", err) - http.Error(w, "Failed to add question", http.StatusInternalServerError) - return - } + 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) + if err != nil { + log.Printf("Error adding new question: %v\n", err) + http.Error(w, "Failed to add question", http.StatusInternalServerError) + return + } - http.Redirect(w, r, "/manage", http.StatusSeeOther) + http.Redirect(w, r, "/manage", http.StatusSeeOther) } - func handleManage(w http.ResponseWriter, r *http.Request) { - rows, err := db.Query("SELECT id, question_text, question_type FROM questions ORDER BY question_order") - if err != nil { - log.Printf("Error fetching questions: %v\n", err) - http.Error(w, "Failed to fetch questions", http.StatusInternalServerError) - return - } - defer rows.Close() + rows, err := db.Query("SELECT id, question_text, question_type FROM questions ORDER BY question_order") + if err != nil { + log.Printf("Error fetching questions: %v\n", err) + http.Error(w, "Failed to fetch questions", http.StatusInternalServerError) + return + } + defer rows.Close() - var questions []Question + var questions []Question - for rows.Next() { - var question Question - err := rows.Scan(&question.ID, &question.QuestionText, &question.QuestionType) - if err != nil { - log.Printf("Error scanning question: %v\n", err) - continue - } - questions = append(questions, question) - } + for rows.Next() { + var question Question + err := rows.Scan(&question.ID, &question.QuestionText, &question.QuestionType) + if err != nil { + log.Printf("Error scanning question: %v\n", err) + continue + } + questions = append(questions, question) + } - if len(questions) == 0 { - log.Println("No questions found") - } + if len(questions) == 0 { + log.Println("No questions found") + } - tmpl := template.Must(template.ParseFiles("manage.html")) - err = tmpl.Execute(w, questions) - if err != nil { - log.Printf("Error executing template: %v\n", err) - } + tmpl := template.Must(template.ParseFiles("manage.html")) + err = tmpl.Execute(w, questions) + if err != nil { + log.Printf("Error executing template: %v\n", err) + } } 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 = ?` - _, err := db.Exec(deleteQuery, questionID) - if err != nil { - log.Printf("Error removing question: %v\n", err) - http.Error(w, "Failed to remove question", http.StatusInternalServerError) - return - } + deleteQuery := `DELETE FROM questions WHERE id = ?` + _, err := db.Exec(deleteQuery, questionID) + if err != nil { + log.Printf("Error removing question: %v\n", err) + http.Error(w, "Failed to remove question", http.StatusInternalServerError) + return + } - http.Redirect(w, r, "/manage", http.StatusSeeOther) + http.Redirect(w, r, "/manage", http.StatusSeeOther) } - func main() { - var err error + var err error - db, err = sql.Open("sqlite3", "./formdata.db") - if err != nil { - log.Fatal(err) - } + db, err = sql.Open("sqlite3", "./formdata.db") + if err != nil { + log.Fatal(err) + } - createTableQueries := ` + createTableQueries := ` CREATE TABLE IF NOT EXISTS questions ( id INTEGER PRIMARY KEY AUTOINCREMENT, question_text TEXT NOT NULL, @@ -207,29 +211,29 @@ func main() { ); CREATE TABLE IF NOT EXISTS answers ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - question_id INTEGER NOT NULL, - answer TEXT NOT NULL, - FOREIGN KEY (question_id) REFERENCES questions(id) - ); + id INTEGER PRIMARY KEY AUTOINCREMENT, + question_id INTEGER NOT NULL, + answer TEXT NOT NULL, + FOREIGN KEY (question_id) REFERENCES questions(id) +); ` - _, err = db.Exec(createTableQueries) - if err != nil { - log.Fatal(err) - return - } + _, err = db.Exec(createTableQueries) + if err != nil { + log.Fatal(err) + 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("/submit", handleFormSubmit) - http.HandleFunc("/admin", handleAdmin) - http.HandleFunc("/manage", handleManage) - http.HandleFunc("/manage/add", handleAddQuestion) - http.HandleFunc("/manage/remove", handleRemoveQuestion) + http.HandleFunc("/", renderForm) + http.HandleFunc("/submit", handleFormSubmit) + http.HandleFunc("/admin", handleAdmin) + http.HandleFunc("/manage", handleManage) + http.HandleFunc("/manage/add", handleAddQuestion) + 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)) }