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.
128 lines
3.4 KiB
Go
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
|
|
}
|