diff --git a/pkg/season/admin.go b/pkg/season/admin.go
index a2268e5..5ab5e38 100644
--- a/pkg/season/admin.go
+++ b/pkg/season/admin.go
@@ -9,6 +9,9 @@ import (
"context"
"fmt"
"net/http"
+ "net/url"
+ "strconv"
+ "strings"
"time"
"github.com/jackc/pgtype"
@@ -56,10 +59,12 @@ func (h *AdminHandler) Handler(user *auth.User, company *auth.Company, conn *dat
}
case "range":
switch r.Method {
+ case http.MethodGet:
+ serveSeasonCalendar(w, r, user, company, conn)
case http.MethodPut:
updateSeasonCalendar(w, r, user, company, conn)
default:
- httplib.MethodNotAllowed(w, r, http.MethodGet)
+ httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPut)
}
default:
if !uuid.Valid(head) {
@@ -91,7 +96,7 @@ func serveSeasonIndex(w http.ResponseWriter, r *http.Request, user *auth.User, c
if err != nil {
panic(err)
}
- calendar, err := collectSeasonCalendar(r.Context(), company, conn, 2023)
+ calendar, err := collectSeasonCalendar(r.Context(), company, conn, getCalendarYear(r.URL.Query()))
if err != nil {
panic(err)
}
@@ -103,6 +108,16 @@ func serveSeasonIndex(w http.ResponseWriter, r *http.Request, user *auth.User, c
page.MustRender(w, r, user, company)
}
+func getCalendarYear(query url.Values) int {
+ yearStr := strings.TrimSpace(query.Get("year"))
+ if yearStr != "" {
+ if year, err := strconv.Atoi(yearStr); err == nil {
+ return year
+ }
+ }
+ return time.Now().Year()
+}
+
func collectSeasonEntries(ctx context.Context, company *auth.Company, conn *database.Conn) ([]*seasonEntry, error) {
rows, err := conn.Query(ctx, `
select slug
@@ -167,7 +182,9 @@ func collectSeasonCalendar(ctx context.Context, company *auth.Company, conn *dat
var month *seasonMonth
var week seasonWeek
- calendar := &seasonCalendar{}
+ calendar := &seasonCalendar{
+ Year: year,
+ }
weekday := int(time.Monday)
for rows.Next() {
day := &seasonDay{}
@@ -213,6 +230,7 @@ func collectSeasonCalendar(ctx context.Context, company *auth.Company, conn *dat
}
type seasonCalendar struct {
+ Year int
Months []*seasonMonth
Form *calendarForm
}
@@ -327,6 +345,11 @@ func (f *seasonForm) MustRender(w http.ResponseWriter, r *http.Request, user *au
template.MustRenderAdmin(w, r, user, company, "season/form.gohtml", f)
}
+func serveSeasonCalendar(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
+ f := newCalendarForm(r.Context(), company, conn)
+ f.MustRender(w, r, user, company, conn, getCalendarYear(r.URL.Query()))
+}
+
func updateSeasonCalendar(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
f := newCalendarForm(r.Context(), company, conn)
if ok, err := form.Handle(f, w, r, user); err != nil {
@@ -346,7 +369,7 @@ func updateSeasonCalendar(w http.ResponseWriter, r *http.Request, user *auth.Use
f.StartDate.Val = ""
f.EndDate.Val = ""
}
- f.MustRender(w, r, user, company, conn)
+ f.MustRender(w, r, user, company, conn, getCalendarYear(r.Form))
}
type calendarForm struct {
@@ -427,8 +450,8 @@ func (f *calendarForm) Valid(l *locale.Locale) bool {
return v.AllOK
}
-func (f *calendarForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
- calendar, err := collectSeasonCalendar(r.Context(), company, conn, 2023)
+func (f *calendarForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, year int) {
+ calendar, err := collectSeasonCalendar(r.Context(), company, conn, year)
if err != nil {
panic(err)
}
diff --git a/pkg/template/render.go b/pkg/template/render.go
index 3a89e82..ca645e0 100644
--- a/pkg/template/render.go
+++ b/pkg/template/render.go
@@ -78,6 +78,12 @@ func mustRenderLayout(w io.Writer, user *auth.User, company *auth.Company, templ
"queryEscape": func(s string) string {
return url.QueryEscape(s)
},
+ "inc": func(i int) int {
+ return i + 1
+ },
+ "dec": func(i int) int {
+ return i - 1
+ },
})
templates = append(templates, "form.gohtml")
files := make([]string, len(templates))
diff --git a/web/static/camper.css b/web/static/camper.css
index fb8defe..4418d6b 100644
--- a/web/static/camper.css
+++ b/web/static/camper.css
@@ -228,14 +228,14 @@ body > a[href="#content"]:focus {
}
/* header */
-header {
+body > header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: var(--camper--header--background-color);
}
-header, body > nav a {
+body > header, body > nav a {
padding: 0 3rem;
}
@@ -497,7 +497,38 @@ textarea {
background-color: #ffeeaa;
}
-.season-calendar {
+/* calendar */
+.season-calendar button {
+ display: flex;
+ gap: 1em;
+ border: none;
+ cursor: pointer;
+}
+
+.season-calendar form button:first-child, .season-calendar > header button {
+ min-width: 0;
+}
+
+.season-calendar > header {
+ display: flex;
+ gap: 2rem;
+ justify-content: center;
+ align-items: center;
+}
+
+.season-calendar > header button:first-of-type {
+ order: -1;
+}
+
+.season-calendar > header button:first-of-type::before {
+ content: "←";
+}
+
+.season-calendar > header button:last-of-type::before {
+ content: "→";
+}
+
+.season-calendar > div {
display: grid;
grid-template-columns: repeat(3, auto);
grid-auto-rows: 1fr;
@@ -507,11 +538,11 @@ textarea {
}
@media (max-width: 48rem) {
- .season-calendar {
+ .season-calendar > div {
display: flex;
flex-direction: column;
}
-
+
.season-calendar table {
width: 100%;
}
@@ -553,22 +584,14 @@ textarea {
height: .8rem;
}
-.season-calendar form button {
- display: flex;
- gap: 1em;
- border: none;
- cursor: pointer;
-}
-
.season-calendar form button:first-child {
- min-width: 0;
position: absolute;
top: 0;
right: 0;
background-color: transparent;
}
-.season-calendar form button:hover, .season-calendar form button:first-child:hover {
+.season-calendar form button:hover, .season-calendar form button:first-child:hover {
background-color: var(--camper--color--hay);
}
diff --git a/web/templates/admin/season/calendar.gohtml b/web/templates/admin/season/calendar.gohtml
index ce33880..2b44d5b 100644
--- a/web/templates/admin/season/calendar.gohtml
+++ b/web/templates/admin/season/calendar.gohtml
@@ -1,58 +1,69 @@
-
+
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/season.seasonCalendar*/ -}}
- {{ range .Months -}}
-
- {{ pgettext .Name "month" }}
-
-
- {{(pgettext "Mon" "day" )}} |
- {{(pgettext "Tue" "day" )}} |
- {{(pgettext "Wed" "day" )}} |
- {{(pgettext "Thu" "day" )}} |
- {{(pgettext "Fri" "day" )}} |
- {{(pgettext "Sat" "day" )}} |
- {{(pgettext "Sun" "day" )}} |
-
-
-
- {{ range .Weeks }}
+
+ {{ .Year }}
+
+
+
+
+ {{ range .Months -}}
+
+ {{ pgettext .Name "month" }}
+
- {{- range . }}
-
- {{- if .Color -}}
-
- {{- end -}}
- |
- {{- end }}
+ {{(pgettext "Mon" "day" )}} |
+ {{(pgettext "Tue" "day" )}} |
+ {{(pgettext "Wed" "day" )}} |
+ {{(pgettext "Thu" "day" )}} |
+ {{(pgettext "Fri" "day" )}} |
+ {{(pgettext "Sat" "day" )}} |
+ {{(pgettext "Sun" "day" )}} |
- {{- end }}
-
-
- {{- end }}
- {{ with .Form }}
-
- {{ end }}
+
+
+ {{ range .Weeks }}
+
+ {{- range . }}
+
+ {{- if .Color -}}
+
+ {{- end -}}
+ |
+ {{- end }}
+
+ {{- end }}
+
+
+ {{- end }}
+ {{ with .Form }}
+
+ {{ end }}
+
-
+