/* * SPDX-FileCopyrightText: 2023 jordi fita mas * SPDX-License-Identifier: AGPL-3.0-only */ package campsite import ( "context" "net/http" "time" "golang.org/x/text/language" "dev.tandem.ws/tandem/camper/pkg/auth" "dev.tandem.ws/tandem/camper/pkg/campsite/types" "dev.tandem.ws/tandem/camper/pkg/carousel" "dev.tandem.ws/tandem/camper/pkg/database" httplib "dev.tandem.ws/tandem/camper/pkg/http" "dev.tandem.ws/tandem/camper/pkg/locale" "dev.tandem.ws/tandem/camper/pkg/season" "dev.tandem.ws/tandem/camper/pkg/template" ) type PublicHandler struct { types *types.PublicHandler } func NewPublicHandler() *PublicHandler { return &PublicHandler{ types: &types.PublicHandler{}, } } func (h *PublicHandler) Handler(user *auth.User, company *auth.Company, conn *database.Conn) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var head string head, r.URL.Path = httplib.ShiftPath(r.URL.Path) switch head { case "types": h.types.Handler(user, company, conn).ServeHTTP(w, r) case "calendar": h.calendarHandler(user, company, conn).ServeHTTP(w, r) default: page, err := newPublicPage(r.Context(), company, conn, user.Locale, head) if database.ErrorIsNotFound(err) { http.NotFound(w, r) return } else if err != nil { panic(err) } head, r.URL.Path = httplib.ShiftPath(r.URL.Path) switch head { case "": switch r.Method { case http.MethodGet: page.MustRender(w, r, user, company, conn) default: httplib.MethodNotAllowed(w, r, http.MethodGet) } default: http.NotFound(w, r) } } }) } func (h *PublicHandler) calendarHandler(user *auth.User, company *auth.Company, conn *database.Conn) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var head string head, r.URL.Path = httplib.ShiftPath(r.URL.Path) switch head { case "": switch r.Method { case http.MethodGet: year := season.GetCalendarYear(r.URL.Query()) month := season.GetCalendarMonth(r.URL.Query()) date := time.Date(year, month, 1, 0, 0, 0, 0, time.UTC).AddDate(0, 1, 0) calendar, err := season.CollectSeasonCalendar(r.Context(), company, conn, date.Year(), date.Month(), 3) if err != nil { panic(err) } template.MustRenderPublicNoLayout(w, r, user, company, "campsite/calendar.gohtml", calendar) default: httplib.MethodNotAllowed(w, r, http.MethodGet) } default: http.NotFound(w, r) } }) } type publicPage struct { *template.PublicPage TypeName string Label string Carousel []*carousel.Slide Features []*feature Info []string } func newPublicPage(ctx context.Context, company *auth.Company, conn *database.Conn, loc *locale.Locale, label string) (*publicPage, error) { page := &publicPage{ PublicPage: template.NewPublicPage(), Label: label, Carousel: mustCollectSlides(ctx, conn, company, loc, label), } row := conn.QueryRow(ctx, ` select coalesce(type_i18n.name, campsite_type.name) as l10n_type_name , array[coalesce(campsite_i18n.info1, campsite.info1)::text, coalesce(campsite_i18n.info2, campsite.info2)::text] as info from campsite join campsite_type using (campsite_type_id) left join campsite_type_i18n as type_i18n on campsite_type.campsite_type_id = type_i18n.campsite_type_id and type_i18n.lang_tag = $1 left join campsite_i18n on campsite.campsite_id = campsite_i18n.campsite_id and campsite_i18n.lang_tag = $1 where campsite_type.company_id = $2 and label = $3 and campsite.active `, loc.Language, company.ID, label) if err := row.Scan(&page.TypeName, &page.Info); err != nil { return nil, err } var err error page.Features, err = collectFeatures(ctx, conn, company, loc.Language, label) if err != nil { return nil, err } return page, nil } func (p *publicPage) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) { p.Setup(r, user, company, conn) template.MustRenderPublic(w, r, user, company, "campsite/page.gohtml", p) } type feature struct { Icon string Name string } func collectFeatures(ctx context.Context, conn *database.Conn, company *auth.Company, language language.Tag, label string) ([]*feature, error) { rows, err := conn.Query(ctx, ` select feature.icon_name , coalesce(i18n.name, feature.name) as l10n_name from campsite_feature as feature join campsite using (campsite_id) left join campsite_feature_i18n as i18n on feature.campsite_feature_id = i18n.campsite_feature_id and i18n.lang_tag = $1 where campsite.label = $2 and campsite.company_id = $3 order by feature.position `, language, label, company.ID) if err != nil { return nil, err } var features []*feature for rows.Next() { f := &feature{} if err = rows.Scan(&f.Icon, &f.Name); err != nil { return nil, err } features = append(features, f) } return features, nil }