jordi fita mas eeaa3b415e Add amenities section and public page
This is more or less the same as the campsites, as public information
goes, but for buildings and other amenities that the camping provides
that are not campsites.
2024-01-27 22:51:41 +01:00

128 lines
3.4 KiB
Go

/*
* SPDX-FileCopyrightText: 2023 jordi fita mas <jfita@peritasoft.com>
* SPDX-License-Identifier: AGPL-3.0-only
*/
package amenity
import (
"context"
"net/http"
"golang.org/x/text/language"
"dev.tandem.ws/tandem/camper/pkg/auth"
"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/template"
)
type PublicHandler struct {
}
func NewPublicHandler() *PublicHandler {
return &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)
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)
}
})
}
type publicPage struct {
*template.PublicPage
Name 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(i18n.name, amenity.name) as l10n_name
, array[coalesce(i18n.info1, amenity.info1)::text, coalesce(i18n.info2, amenity.info2)::text] as info
from amenity
left join amenity_i18n i18n on amenity.amenity_id = i18n.amenity_id and i18n.lang_tag = $1
where amenity.company_id = $2
and label = $3
and amenity.active
`, loc.Language, company.ID, label)
if err := row.Scan(&page.Name, &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, "amenity.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 amenity_feature as feature
join amenity using (amenity_id)
left join amenity_feature_i18n as i18n on feature.amenity_feature_id = i18n.amenity_feature_id and i18n.lang_tag = $1
where amenity.label = $2
and amenity.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
}