Add the calendar to the public campsite type page
I had to export the Calendar type from Season to use it from campsite/types, and also renamed them because season.SeasonCalendar is a bit redundant compared to just season.Calendar. I still have not added the HTMx code to switch year because i am not sure whether Oriol will want to show a whole year or just half a year. The calculation for the text color taking into account the contrast with the background is from [0]. [0]: https://www.smashingmagazine.com/2020/07/css-techniques-legibility/#foreground-contrast
This commit is contained in:
parent
e1575c6edd
commit
852acaccc3
|
@ -9,6 +9,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
gotemplate "html/template"
|
gotemplate "html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@ import (
|
||||||
"dev.tandem.ws/tandem/camper/pkg/database"
|
"dev.tandem.ws/tandem/camper/pkg/database"
|
||||||
httplib "dev.tandem.ws/tandem/camper/pkg/http"
|
httplib "dev.tandem.ws/tandem/camper/pkg/http"
|
||||||
"dev.tandem.ws/tandem/camper/pkg/locale"
|
"dev.tandem.ws/tandem/camper/pkg/locale"
|
||||||
|
"dev.tandem.ws/tandem/camper/pkg/season"
|
||||||
"dev.tandem.ws/tandem/camper/pkg/template"
|
"dev.tandem.ws/tandem/camper/pkg/template"
|
||||||
"dev.tandem.ws/tandem/camper/pkg/uuid"
|
"dev.tandem.ws/tandem/camper/pkg/uuid"
|
||||||
)
|
)
|
||||||
|
@ -35,7 +37,7 @@ func (h *PublicHandler) Handler(user *auth.User, company *auth.Company, conn *da
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
page, err := newPublicPage(r.Context(), conn, user.Locale, head)
|
page, err := newPublicPage(r.Context(), company, conn, user.Locale, head)
|
||||||
if database.ErrorIsNotFound(err) {
|
if database.ErrorIsNotFound(err) {
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
return
|
return
|
||||||
|
@ -55,6 +57,7 @@ type publicPage struct {
|
||||||
Carousel []*carousel.Slide
|
Carousel []*carousel.Slide
|
||||||
Prices []*typePrice
|
Prices []*typePrice
|
||||||
Features []*typeFeature
|
Features []*typeFeature
|
||||||
|
Calendar *season.Calendar
|
||||||
Spiel gotemplate.HTML
|
Spiel gotemplate.HTML
|
||||||
Info gotemplate.HTML
|
Info gotemplate.HTML
|
||||||
Facilities gotemplate.HTML
|
Facilities gotemplate.HTML
|
||||||
|
@ -74,7 +77,7 @@ type typeFeature struct {
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPublicPage(ctx context.Context, conn *database.Conn, loc *locale.Locale, slug string) (*publicPage, error) {
|
func newPublicPage(ctx context.Context, company *auth.Company, conn *database.Conn, loc *locale.Locale, slug string) (*publicPage, error) {
|
||||||
prices, err := collectPrices(ctx, conn, loc.Language, slug)
|
prices, err := collectPrices(ctx, conn, loc.Language, slug)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -83,9 +86,14 @@ func newPublicPage(ctx context.Context, conn *database.Conn, loc *locale.Locale,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
calendar, err := season.CollectSeasonCalendar(ctx, company, conn, time.Now().Year())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
page := &publicPage{
|
page := &publicPage{
|
||||||
PublicPage: template.NewPublicPage(),
|
PublicPage: template.NewPublicPage(),
|
||||||
Carousel: mustCollectSlides(ctx, conn, loc, slug),
|
Carousel: mustCollectSlides(ctx, conn, loc, slug),
|
||||||
|
Calendar: calendar,
|
||||||
Prices: prices,
|
Prices: prices,
|
||||||
Features: features,
|
Features: features,
|
||||||
}
|
}
|
||||||
|
@ -129,7 +137,13 @@ func collectPrices(ctx context.Context, conn *database.Conn, language language.T
|
||||||
group by season_id
|
group by season_id
|
||||||
) as option on option.season_id = season.season_id
|
) as option on option.season_id = season.season_id
|
||||||
where season.active
|
where season.active
|
||||||
`, language, slug)
|
union all
|
||||||
|
select $3
|
||||||
|
, to_color($4)::text
|
||||||
|
, 1
|
||||||
|
, ''
|
||||||
|
, false
|
||||||
|
`, language, slug, locale.PgettextNoop("Closed", "season"), season.UnsetColor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -171,5 +185,5 @@ func collectFeatures(ctx context.Context, conn *database.Conn, language language
|
||||||
|
|
||||||
func (p *publicPage) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
|
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)
|
p.Setup(r, user, company, conn)
|
||||||
template.MustRenderPublic(w, r, user, company, "campsite/type.gohtml", p)
|
template.MustRenderPublicFiles(w, r, user, company, p, "campsite/type.gohtml", "campsite/calendar.gohtml")
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ import (
|
||||||
"dev.tandem.ws/tandem/camper/pkg/uuid"
|
"dev.tandem.ws/tandem/camper/pkg/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
const unsetColor = 0xd1d0df
|
const UnsetColor = 0xd1d0df
|
||||||
|
|
||||||
type AdminHandler struct {
|
type AdminHandler struct {
|
||||||
locales locale.Locales
|
locales locale.Locales
|
||||||
|
@ -124,7 +124,7 @@ func serveSeasonIndex(w http.ResponseWriter, r *http.Request, user *auth.User, c
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
calendar, err := collectSeasonCalendar(r.Context(), company, conn, getCalendarYear(r.URL.Query()))
|
calendar, err := CollectSeasonCalendar(r.Context(), company, conn, getCalendarYear(r.URL.Query()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ var longMonthNames = []string{
|
||||||
locale.PgettextNoop("December", "month"),
|
locale.PgettextNoop("December", "month"),
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectSeasonCalendar(ctx context.Context, company *auth.Company, conn *database.Conn, year int) (*seasonCalendar, error) {
|
func CollectSeasonCalendar(ctx context.Context, company *auth.Company, conn *database.Conn, year int) (*Calendar, error) {
|
||||||
firstDay := time.Date(year, time.January, 1, 0, 0, 0, 0, time.UTC)
|
firstDay := time.Date(year, time.January, 1, 0, 0, 0, 0, time.UTC)
|
||||||
lastDay := time.Date(year, time.December, 31, 23, 59, 59, 0, time.UTC)
|
lastDay := time.Date(year, time.December, 31, 23, 59, 59, 0, time.UTC)
|
||||||
rows, err := conn.Query(ctx, `
|
rows, err := conn.Query(ctx, `
|
||||||
|
@ -222,19 +222,19 @@ func collectSeasonCalendar(ctx context.Context, company *auth.Company, conn *dat
|
||||||
from generate_series($2, $3, interval '1 day') as t(day)
|
from generate_series($2, $3, interval '1 day') as t(day)
|
||||||
left join season_calendar on season_range @> t.day::date
|
left join season_calendar on season_range @> t.day::date
|
||||||
left join season on season.season_id = season_calendar.season_id and company_id = $4
|
left join season on season.season_id = season_calendar.season_id and company_id = $4
|
||||||
`, unsetColor, firstDay, lastDay, company.ID)
|
`, UnsetColor, firstDay, lastDay, company.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var month *seasonMonth
|
var month *Month
|
||||||
var week seasonWeek
|
var week Week
|
||||||
calendar := &seasonCalendar{
|
calendar := &Calendar{
|
||||||
Year: year,
|
Year: year,
|
||||||
}
|
}
|
||||||
weekday := int(time.Monday)
|
weekday := int(time.Monday)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
day := &seasonDay{}
|
day := &Day{}
|
||||||
if err = rows.Scan(&day.Date, &day.Color); err != nil {
|
if err = rows.Scan(&day.Date, &day.Color); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -242,32 +242,32 @@ func collectSeasonCalendar(ctx context.Context, company *auth.Company, conn *dat
|
||||||
if month == nil || month.Month != dayMonth {
|
if month == nil || month.Month != dayMonth {
|
||||||
if month != nil {
|
if month != nil {
|
||||||
for ; weekday != int(time.Sunday); weekday = (weekday + 1) % 7 {
|
for ; weekday != int(time.Sunday); weekday = (weekday + 1) % 7 {
|
||||||
week = append(week, &seasonDay{})
|
week = append(week, &Day{})
|
||||||
}
|
}
|
||||||
month.Weeks = append(month.Weeks, week)
|
month.Weeks = append(month.Weeks, week)
|
||||||
calendar.Months = append(calendar.Months, month)
|
calendar.Months = append(calendar.Months, month)
|
||||||
}
|
}
|
||||||
month = &seasonMonth{
|
month = &Month{
|
||||||
Month: dayMonth,
|
Month: dayMonth,
|
||||||
Name: longMonthNames[dayMonth-1],
|
Name: longMonthNames[dayMonth-1],
|
||||||
}
|
}
|
||||||
week = seasonWeek{}
|
week = Week{}
|
||||||
weekday = int(time.Monday)
|
weekday = int(time.Monday)
|
||||||
dayWeekday := int(day.Date.Weekday())
|
dayWeekday := int(day.Date.Weekday())
|
||||||
for ; weekday != dayWeekday; weekday = (weekday + 1) % 7 {
|
for ; weekday != dayWeekday; weekday = (weekday + 1) % 7 {
|
||||||
week = append(week, &seasonDay{})
|
week = append(week, &Day{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
week = append(week, day)
|
week = append(week, day)
|
||||||
weekday = (weekday + 1) % 7
|
weekday = (weekday + 1) % 7
|
||||||
if weekday == int(time.Monday) {
|
if weekday == int(time.Monday) {
|
||||||
month.Weeks = append(month.Weeks, week)
|
month.Weeks = append(month.Weeks, week)
|
||||||
week = seasonWeek{}
|
week = Week{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if month != nil {
|
if month != nil {
|
||||||
for ; weekday != int(time.Sunday); weekday = (weekday + 1) % 7 {
|
for ; weekday != int(time.Sunday); weekday = (weekday + 1) % 7 {
|
||||||
week = append(week, &seasonDay{})
|
week = append(week, &Day{})
|
||||||
}
|
}
|
||||||
month.Weeks = append(month.Weeks, week)
|
month.Weeks = append(month.Weeks, week)
|
||||||
calendar.Months = append(calendar.Months, month)
|
calendar.Months = append(calendar.Months, month)
|
||||||
|
@ -276,28 +276,28 @@ func collectSeasonCalendar(ctx context.Context, company *auth.Company, conn *dat
|
||||||
return calendar, nil
|
return calendar, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type seasonCalendar struct {
|
type Calendar struct {
|
||||||
Year int
|
Year int
|
||||||
Months []*seasonMonth
|
Months []*Month
|
||||||
Form *calendarForm
|
Form *calendarForm
|
||||||
}
|
}
|
||||||
|
|
||||||
type seasonMonth struct {
|
type Month struct {
|
||||||
Month time.Month
|
Month time.Month
|
||||||
Name string
|
Name string
|
||||||
Weeks []seasonWeek
|
Weeks []Week
|
||||||
}
|
}
|
||||||
|
|
||||||
type seasonWeek []*seasonDay
|
type Week []*Day
|
||||||
|
|
||||||
type seasonDay struct {
|
type Day struct {
|
||||||
Date time.Time
|
Date time.Time
|
||||||
Color string
|
Color string
|
||||||
}
|
}
|
||||||
|
|
||||||
type seasonIndex struct {
|
type seasonIndex struct {
|
||||||
Seasons []*seasonEntry
|
Seasons []*seasonEntry
|
||||||
Calendar *seasonCalendar
|
Calendar *Calendar
|
||||||
}
|
}
|
||||||
|
|
||||||
func (page *seasonIndex) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
func (page *seasonIndex) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
||||||
|
@ -457,7 +457,7 @@ func mustCollectCalendarSeasons(ctx context.Context, company *auth.Company, conn
|
||||||
from season
|
from season
|
||||||
where company_id = $3
|
where company_id = $3
|
||||||
and active
|
and active
|
||||||
order by sort, name`, locale.PgettextNoop("Unset", "action"), unsetColor, company.ID)
|
order by sort, name`, locale.PgettextNoop("Unset", "action"), UnsetColor, company.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -498,7 +498,7 @@ func (f *calendarForm) Valid(l *locale.Locale) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *calendarForm) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn, year int) {
|
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)
|
calendar, err := CollectSeasonCalendar(r.Context(), company, conn, year)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"dev.tandem.ws/tandem/camper/pkg/auth"
|
"dev.tandem.ws/tandem/camper/pkg/auth"
|
||||||
|
@ -94,6 +95,10 @@ func mustRenderLayout(w io.Writer, user *auth.User, company *auth.Company, templ
|
||||||
"dec": func(i int) int {
|
"dec": func(i int) int {
|
||||||
return i - 1
|
return i - 1
|
||||||
},
|
},
|
||||||
|
"hexToDec": func(s string) int {
|
||||||
|
num, _ := strconv.ParseInt(s, 16, 0)
|
||||||
|
return int(num)
|
||||||
|
},
|
||||||
})
|
})
|
||||||
templates = append(templates, "form.gohtml")
|
templates = append(templates, "form.gohtml")
|
||||||
files := make([]string, len(templates))
|
files := make([]string, len(templates))
|
||||||
|
|
|
@ -821,6 +821,94 @@ dt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.campsite_type_calendar button {
|
||||||
|
display: flex;
|
||||||
|
gap: 1em;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.campsite_type_calendar form button:first-child, .campsite_type_calendar > header button {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.campsite_type_calendar > header {
|
||||||
|
display: flex;
|
||||||
|
gap: 2rem;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.campsite_type_calendar > header button:first-of-type {
|
||||||
|
order: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.campsite_type_calendar > header button:first-of-type::before {
|
||||||
|
content: "←";
|
||||||
|
}
|
||||||
|
|
||||||
|
.campsite_type_calendar > header button:last-of-type::before {
|
||||||
|
content: "→";
|
||||||
|
}
|
||||||
|
|
||||||
|
.campsite_type_calendar > div {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(27rem, 1fr));
|
||||||
|
grid-auto-rows: 1fr;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: start;
|
||||||
|
gap: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 48rem) {
|
||||||
|
.campsite_type_calendar > div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.campsite_type_calendar table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.campsite_type_calendar table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.campsite_type_calendar td {
|
||||||
|
width: calc(100% / 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.campsite_type_calendar time {
|
||||||
|
--aa-brightness: calc(((var(--red) * 299) + (var(--green) * 587) + (var(--blue) * 114)) / 1000);
|
||||||
|
--aa-color: calc((var(--aa-brightness) - 128) * -1000);
|
||||||
|
background: rgb(var(--red), var(--green), var(--blue));
|
||||||
|
color: rgb(var(--aa-color), var(--aa-color), var(--aa-color));
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 3rem;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.campsite_type_calendar [aria-checked] {
|
||||||
|
border: 2px solid var(--camper--color--black);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.campsite_type_calendar [aria-checked]::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
display: block;
|
||||||
|
background-color: var(--camper--color--black);
|
||||||
|
border-radius: 50%;
|
||||||
|
width: .8rem;
|
||||||
|
height: .8rem;
|
||||||
|
}
|
||||||
|
|
||||||
body > footer {
|
body > footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<article class="season-calendar" data-hx-target="this" data-hx-swap="outerHTML">
|
<article class="season-calendar" data-hx-target="this" data-hx-swap="outerHTML">
|
||||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/season.seasonCalendar*/ -}}
|
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/season.Calendar*/ -}}
|
||||||
<header>
|
<header>
|
||||||
<h3>{{ .Year }}</h3>
|
<h3>{{ .Year }}</h3>
|
||||||
<button type="button"
|
<button type="button"
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
-->
|
||||||
|
<article class="campsite_type_calendar">
|
||||||
|
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/season.Calendar*/ -}}
|
||||||
|
<header>
|
||||||
|
<h3>{{ .Year }}</h3>
|
||||||
|
<button type="button"
|
||||||
|
data-hx-get="/{{ currentLocale }}/seasons/calendar?year={{ dec .Year }}"
|
||||||
|
><span class="sr-only">{{ pgettext "Prev" "navigation" }}</span></button>
|
||||||
|
<button type="button"
|
||||||
|
data-hx-get="/{{ currentLocale }}/seasons/calendar?year={{ inc .Year }}"
|
||||||
|
><span class="sr-only">{{ pgettext "Next" "navigation" }}</span></button>
|
||||||
|
</header>
|
||||||
|
<div>
|
||||||
|
{{ range .Months -}}
|
||||||
|
<table class="month">
|
||||||
|
<caption>{{ pgettext .Name "month" }}</caption>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">{{(pgettext "Mon" "day" )}}</th>
|
||||||
|
<th scope="col">{{(pgettext "Tue" "day" )}}</th>
|
||||||
|
<th scope="col">{{(pgettext "Wed" "day" )}}</th>
|
||||||
|
<th scope="col">{{(pgettext "Thu" "day" )}}</th>
|
||||||
|
<th scope="col">{{(pgettext "Fri" "day" )}}</th>
|
||||||
|
<th scope="col">{{(pgettext "Sat" "day" )}}</th>
|
||||||
|
<th scope="col">{{(pgettext "Sun" "day" )}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{ range .Weeks }}
|
||||||
|
<tr>
|
||||||
|
{{- range . }}
|
||||||
|
<td>
|
||||||
|
{{- if .Color -}}
|
||||||
|
<time style="--red: {{ slice .Color 1 3 | hexToDec }}; --green: {{ slice .Color 3 5 | hexToDec }}; --blue: {{ slice .Color 5 7 | hexToDec }}"
|
||||||
|
datetime="{{ .Date.Format "2006-01-02" }}"
|
||||||
|
>{{ .Date.Format "2" }}</time>
|
||||||
|
{{- end -}}
|
||||||
|
</td>
|
||||||
|
{{- end }}
|
||||||
|
</tr>
|
||||||
|
{{- end }}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{{- end }}
|
||||||
|
</div>
|
||||||
|
</article>
|
|
@ -69,7 +69,7 @@
|
||||||
</dt>
|
</dt>
|
||||||
{{ if .HasOptions -}}
|
{{ if .HasOptions -}}
|
||||||
<dd>{{ printf (gettext "Starting from %s €/night") .PricePerNight }}</dd>
|
<dd>{{ printf (gettext "Starting from %s €/night") .PricePerNight }}</dd>
|
||||||
{{- else -}}
|
{{- else if .PricePerNight -}}
|
||||||
<dd>{{ printf (gettext "%s €/night") .PricePerNight }}</dd>
|
<dd>{{ printf (gettext "%s €/night") .PricePerNight }}</dd>
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{ if gt .MinNights 1 -}}
|
{{ if gt .MinNights 1 -}}
|
||||||
|
@ -82,8 +82,7 @@
|
||||||
{{- end }}
|
{{- end }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="campsite_type_calendar">
|
{{ template "calendar.gohtml" .Calendar }}
|
||||||
</div>
|
|
||||||
|
|
||||||
{{ with .Features -}}
|
{{ with .Features -}}
|
||||||
<article class="campsite_type_features">
|
<article class="campsite_type_features">
|
||||||
|
|
Loading…
Reference in New Issue