From 3ad9b2955f34fedc762acfe6fa3b7330886b1715 Mon Sep 17 00:00:00 2001 From: Brandon Dyck Date: Sun, 4 Oct 2020 14:54:41 -0600 Subject: [PATCH] Show respondent names on admin page --- back/store.go | 15 ++++++----- back/store_test.go | 64 ++++++++++++++++++++++++++++------------------ front/server.go | 11 ++++++-- todo.txt | 1 - 4 files changed, 56 insertions(+), 35 deletions(-) diff --git a/back/store.go b/back/store.go index 61c3680..5758372 100644 --- a/back/store.go +++ b/back/store.go @@ -215,8 +215,8 @@ type GetEventResponseSummaryQuery struct { } type GetEventResponseSummaryResult struct { - TotalResponses int - PerHourCounts map[date.Date]map[int]int + RespondentNames []string + PerHourCounts map[date.Date]map[int]int } func (s *Store) GetEventResponseSummary(ctx context.Context, query GetEventResponseSummaryQuery) (GetEventResponseSummaryResult, error) { @@ -242,13 +242,14 @@ func (s *Store) GetEventResponseSummary(ctx context.Context, query GetEventRespo } var result GetEventResponseSummaryResult - const responseCountQuery = ` - SELECT COUNT(*) + const respondentNameQuery = ` + SELECT guest_name FROM response - WHERE event_id = ?;` - err = sqlitex.Exec(conn, responseCountQuery, + WHERE event_id = ? + ORDER BY guest_name ASC;` + err = sqlitex.Exec(conn, respondentNameQuery, func(stmt *sqlite.Stmt) error { - result.TotalResponses = stmt.ColumnInt(0) + result.RespondentNames = append(result.RespondentNames, stmt.ColumnText(0)) return nil }, query.EventID) if err != nil { diff --git a/back/store_test.go b/back/store_test.go index 84d3998..e390cf4 100644 --- a/back/store_test.go +++ b/back/store_test.go @@ -2,7 +2,10 @@ package back_test import ( "context" + "math/rand" + "sort" "testing" + "time" "github.com/matryer/is" "github.com/rickb777/date" @@ -61,29 +64,6 @@ func TestGetEventResponseSummary(t *testing.T) { return event.EventID } - getTotalResponses := func(is *is.I, eventID string) int { - responses, err := store.GetEventResponseSummary(context.Background(), back.GetEventResponseSummaryQuery{ - EventID: eventID, - }) - is.NoErr(err) - return responses.TotalResponses - } - - t.Run("TotalResponses counts the number of responses created", func(t *testing.T) { - is := is.New(t) - - eventID := createEvent(is) - is.Equal(getTotalResponses(is, eventID), 0) - const respondTimes = 5 - for i := 1; i <= respondTimes; i++ { - _, err = store.CreateEventResponse(context.Background(), back.CreateEventResponseCommand{ - EventID: eventID, - }) - is.NoErr(err) - is.Equal(getTotalResponses(is, eventID), i) - } - }) - t.Run("does not include responses to other events", func(t *testing.T) { is := is.New(t) @@ -109,11 +89,45 @@ func TestGetEventResponseSummary(t *testing.T) { is.NoErr(err) is.Equal(summary, back.GetEventResponseSummaryResult{ - TotalResponses: 0, - PerHourCounts: map[date.Date]map[int]int{}, + RespondentNames: nil, + PerHourCounts: map[date.Date]map[int]int{}, }) }) + t.Run("RespondentNames lists all respondents alphabetically", func(t *testing.T) { + is := is.New(t) + + var names = []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"} + rand.Shuffle(len(names), func(i, j int) { + names[i], names[j] = names[j], names[i] + }) + + d := date.New(1963, time.May, 1) + event, err := store.CreateEvent(context.Background(), back.CreateEventCommand{ + Name: "It's my party!", + Description: "I can cry if I want to.", + Latest: d, + Earliest: d, + }) + is.NoErr(err) + + for _, name := range names { + _, err = store.CreateEventResponse(context.Background(), back.CreateEventResponseCommand{ + EventID: event.EventID, + GuestName: name, + }) + is.NoErr(err) + } + + summary, err := store.GetEventResponseSummary(context.Background(), back.GetEventResponseSummaryQuery{ + EventID: event.EventID, + }) + is.NoErr(err) + + sort.Strings(names) + is.Equal(summary.RespondentNames, names) + }) + t.Run("PerHourCounts counts votes per hour", func(t *testing.T) { is := is.New(t) diff --git a/front/server.go b/front/server.go index fdb0219..633c610 100644 --- a/front/server.go +++ b/front/server.go @@ -365,6 +365,12 @@ func (h *handler) handleAdmin(w http.ResponseWriter, r *http.Request) { return } + // Build the respondents list + respondentsList := e.Ul()() + for _, r := range summary.RespondentNames { + respondentsList.Children = append(respondentsList.Children, e.Li()(hm.Text(r))) + } + // Build the counts table dateSpan := metadata.Latest.Sub(metadata.Earliest) var dates []date.Date @@ -426,8 +432,9 @@ func (h *handler) handleAdmin(w http.ResponseWriter, r *http.Request) { a.Disabled(true), ), ), - e.H3()(hm.Text("Responses")), - e.P()(hm.Text(strconv.Itoa(summary.TotalResponses))), + e.H3()(hm.Text("Respondents")), + respondentsList, + e.H3()(hm.Text("Results")), countsTable, } _ = h.writePage(w, "Edit your event", body) diff --git a/todo.txt b/todo.txt index d067ff0..f9d259a 100644 --- a/todo.txt +++ b/todo.txt @@ -1,7 +1,6 @@ Essential: ------------ Show response after submission -Show respondent names on admin page Make earliest and latest dates required for creation Prevent blank event names and guest names Consider some front-end, regex-based field validation