240 lines
6.0 KiB
Go
240 lines
6.0 KiB
Go
package main
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"html/template"
|
|
"log"
|
|
"net/http"
|
|
|
|
_ "github.com/mattn/go-sqlite3"
|
|
)
|
|
|
|
type Question struct {
|
|
ID int
|
|
QuestionText string
|
|
QuestionType string
|
|
}
|
|
|
|
var db *sql.DB
|
|
|
|
func renderForm(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 form questions", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
|
|
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)
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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 (?, ?)`
|
|
|
|
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()
|
|
}
|
|
}()
|
|
|
|
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
|
|
}
|
|
|
|
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()
|
|
|
|
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)
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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()
|
|
|
|
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)
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
func handleRemoveQuestion(w http.ResponseWriter, r *http.Request) {
|
|
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
|
|
}
|
|
|
|
http.Redirect(w, r, "/manage", http.StatusSeeOther)
|
|
}
|
|
|
|
func main() {
|
|
var err error
|
|
|
|
db, err = sql.Open("sqlite3", "./formdata.db")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
createTableQueries := `
|
|
CREATE TABLE IF NOT EXISTS questions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
question_text TEXT NOT NULL,
|
|
question_type TEXT NOT NULL DEFAULT 'text',
|
|
question_order INTEGER NOT NULL
|
|
);
|
|
|
|
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)
|
|
);
|
|
`
|
|
|
|
_, err = db.Exec(createTableQueries)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
return
|
|
}
|
|
|
|
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)
|
|
|
|
fmt.Println("Server started at :8080")
|
|
|
|
log.Fatal(http.ListenAndServe(":8080", nil))
|
|
}
|