Handle the booking cart entirely with HTMx
Besides the dynamic final cart, that was already handled by HTMx, i had to check the maximum number of guests, whether the accommodation allows “overflow”, whether dogs are allowed, and that the booking dates were within the campground’s opening and closing dates. I could do all of this with AlpineJS, but then i would have to add the same validation to the backend, prior to accept the payment. Would not make more sense to have them in a single place, namely the backend? With HTMx i can do that. However, i now have to create the form “piecemeal”, because i may not have the whole information when the visitor arrives to the booking page, and i still had the same problem as in commit d2858302efa—parsing the whole form as is would leave guests and options field empty, rather than at their minimum values. One of the fieldsets in that booking form are the arrival and departure dates, that are the sames we use in the campsite type’s page to “preselect” these values. Since now are in a separate struct, i can reuse the same type and validation logic for both pages, making my JavaScript code useless, but requiring HTMx. I think this is a good tradeoff, in fact.
This commit is contained in:
parent
b915ba1559
commit
e5023a2a41
|
@ -2,49 +2,19 @@ package booking
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v4"
|
"github.com/jackc/pgx/v4"
|
||||||
|
|
||||||
"dev.tandem.ws/tandem/camper/pkg/auth"
|
|
||||||
"dev.tandem.ws/tandem/camper/pkg/database"
|
"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/locale"
|
||||||
"dev.tandem.ws/tandem/camper/pkg/template"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleBookingCart(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
|
|
||||||
var head string
|
|
||||||
head, r.URL.Path = httplib.ShiftPath(r.URL.Path)
|
|
||||||
|
|
||||||
switch head {
|
|
||||||
case "":
|
|
||||||
switch r.Method {
|
|
||||||
case http.MethodGet:
|
|
||||||
f := newBookingForm(r.Context(), company, conn, user.Locale)
|
|
||||||
if err := f.Parse(r); err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if cart, err := computeCart(r.Context(), conn, f); err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
cart.MustRender(w, r, user, company)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
httplib.MethodNotAllowed(w, r, http.MethodGet)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
http.NotFound(w, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type bookingCart struct {
|
type bookingCart struct {
|
||||||
Lines []*cartLine
|
Lines []*cartLine
|
||||||
Total string
|
Total string
|
||||||
|
Enabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type cartLine struct {
|
type cartLine struct {
|
||||||
|
@ -53,41 +23,43 @@ type cartLine struct {
|
||||||
Subtotal string
|
Subtotal string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cart *bookingCart) MustRender(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company) {
|
func newBookingCart(ctx context.Context, conn *database.Conn, f *bookingForm, campsiteType string) (*bookingCart, error) {
|
||||||
template.MustRenderPublicNoLayout(w, r, user, company, "booking/cart.gohtml", cart)
|
|
||||||
}
|
|
||||||
|
|
||||||
func computeCart(ctx context.Context, conn *database.Conn, f *bookingForm) (*bookingCart, error) {
|
|
||||||
cart := &bookingCart{
|
cart := &bookingCart{
|
||||||
Total: "0.0",
|
Total: "0.0",
|
||||||
}
|
}
|
||||||
campsiteType := f.CampsiteType.String()
|
if f.Dates == nil {
|
||||||
if campsiteType == "" {
|
|
||||||
return cart, nil
|
return cart, nil
|
||||||
}
|
}
|
||||||
arrivalDate, err := time.Parse(database.ISODateFormat, f.ArrivalDate.Val)
|
arrivalDate, err := time.Parse(database.ISODateFormat, f.Dates.ArrivalDate.Val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cart, nil
|
return cart, nil
|
||||||
}
|
}
|
||||||
departureDate, err := time.Parse(database.ISODateFormat, f.DepartureDate.Val)
|
departureDate, err := time.Parse(database.ISODateFormat, f.Dates.DepartureDate.Val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cart, nil
|
return cart, nil
|
||||||
}
|
}
|
||||||
numAdults, err := strconv.Atoi(f.NumberAdults.Val)
|
|
||||||
|
if f.Guests == nil {
|
||||||
|
return cart, nil
|
||||||
|
}
|
||||||
|
numAdults, err := strconv.Atoi(f.Guests.NumberAdults.Val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cart, nil
|
return cart, nil
|
||||||
}
|
}
|
||||||
numTeenagers, err := strconv.Atoi(f.NumberTeenagers.Val)
|
numTeenagers, err := strconv.Atoi(f.Guests.NumberTeenagers.Val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cart, nil
|
return cart, nil
|
||||||
}
|
}
|
||||||
numChildren, err := strconv.Atoi(f.NumberChildren.Val)
|
numChildren, err := strconv.Atoi(f.Guests.NumberChildren.Val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cart, nil
|
return cart, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
optionMap := make(map[int]*campsiteTypeOption)
|
optionMap := make(map[int]*campsiteTypeOption)
|
||||||
typeOptions := f.CampsiteTypeOptions[campsiteType]
|
var typeOptions []*campsiteTypeOption
|
||||||
|
if f.Options != nil {
|
||||||
|
typeOptions = f.Options.Options
|
||||||
|
}
|
||||||
optionIDs := make([]int, 0, len(typeOptions))
|
optionIDs := make([]int, 0, len(typeOptions))
|
||||||
optionUnits := make([]int, 0, len(typeOptions))
|
optionUnits := make([]int, 0, len(typeOptions))
|
||||||
for _, option := range typeOptions {
|
for _, option := range typeOptions {
|
||||||
|
@ -103,7 +75,7 @@ func computeCart(ctx context.Context, conn *database.Conn, f *bookingForm) (*boo
|
||||||
row := conn.QueryRow(ctx, `
|
row := conn.QueryRow(ctx, `
|
||||||
with per_person as (
|
with per_person as (
|
||||||
select count(*) as num_nights
|
select count(*) as num_nights
|
||||||
, sum(cost_per_night)::integer as nights
|
, sum(cost_per_night * ceiling(($4::numeric + $5::numeric + $6::numeric) / max_campers::numeric)::integer)::integer as nights
|
||||||
, sum(cost_per_adult * $4)::integer as adults
|
, sum(cost_per_adult * $4)::integer as adults
|
||||||
, sum(cost_per_teenager * $5)::integer as teenagers
|
, sum(cost_per_teenager * $5)::integer as teenagers
|
||||||
, sum(cost_per_child * $6)::integer as children
|
, sum(cost_per_child * $6)::integer as children
|
||||||
|
@ -121,10 +93,10 @@ func computeCart(ctx context.Context, conn *database.Conn, f *bookingForm) (*boo
|
||||||
select campsite_type_option_id
|
select campsite_type_option_id
|
||||||
, sum(cost_per_night * units)::integer as option_cost
|
, sum(cost_per_night * units)::integer as option_cost
|
||||||
from generate_series($1, $2, interval '1 day') as date(day)
|
from generate_series($1, $2, interval '1 day') as date(day)
|
||||||
join season_calendar on season_range @> date.day::date
|
join season_calendar on season_range @> date.day::date
|
||||||
join campsite_type_option_cost using (season_id)
|
join campsite_type_option_cost using (season_id)
|
||||||
join unnest($7::integer[], $8::integer[]) as option_units(campsite_type_option_id, units) using (campsite_type_option_id)
|
join unnest($7::integer[], $8::integer[]) as option_units(campsite_type_option_id, units) using (campsite_type_option_id)
|
||||||
group by campsite_type_option_id
|
group by campsite_type_option_id
|
||||||
union all select -1, 0
|
union all select -1, 0
|
||||||
)
|
)
|
||||||
select num_nights
|
select num_nights
|
||||||
|
@ -195,6 +167,7 @@ func computeCart(ctx context.Context, conn *database.Conn, f *bookingForm) (*boo
|
||||||
|
|
||||||
if total != "" {
|
if total != "" {
|
||||||
cart.Total = total
|
cart.Total = total
|
||||||
|
cart.Enabled = f.Guests.Error == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return cart, nil
|
return cart, nil
|
||||||
|
|
|
@ -9,8 +9,11 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"dev.tandem.ws/tandem/camper/pkg/auth"
|
"dev.tandem.ws/tandem/camper/pkg/auth"
|
||||||
"dev.tandem.ws/tandem/camper/pkg/database"
|
"dev.tandem.ws/tandem/camper/pkg/database"
|
||||||
|
@ -37,19 +40,17 @@ func (h *PublicHandler) Handler(user *auth.User, company *auth.Company, conn *da
|
||||||
case "":
|
case "":
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
page := newPublicPage(r.Context(), company, conn, user.Locale)
|
page, err := newPublicPage(r, company, conn, user.Locale)
|
||||||
_ = r.ParseForm()
|
if err != nil {
|
||||||
page.Form.CampsiteType.FillValue(r)
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
page.Form.ArrivalDate.FillValue(r)
|
return
|
||||||
page.Form.DepartureDate.FillValue(r)
|
}
|
||||||
page.MustRender(w, r, user, company, conn)
|
page.MustRender(w, r, user, company, conn)
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
makeReservation(w, r, user, company, conn)
|
makeReservation(w, r, user, company, conn)
|
||||||
default:
|
default:
|
||||||
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPost)
|
httplib.MethodNotAllowed(w, r, http.MethodGet, http.MethodPost)
|
||||||
}
|
}
|
||||||
case "cart":
|
|
||||||
handleBookingCart(w, r, user, company, conn)
|
|
||||||
case "success":
|
case "success":
|
||||||
handleSuccessfulPayment(w, r, user, company, conn)
|
handleSuccessfulPayment(w, r, user, company, conn)
|
||||||
case "failure":
|
case "failure":
|
||||||
|
@ -61,8 +62,8 @@ func (h *PublicHandler) Handler(user *auth.User, company *auth.Company, conn *da
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeReservation(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
|
func makeReservation(w http.ResponseWriter, r *http.Request, user *auth.User, company *auth.Company, conn *database.Conn) {
|
||||||
f := newBookingForm(r.Context(), company, conn, user.Locale)
|
f, err := newBookingForm(r, company, conn, user.Locale)
|
||||||
if err := f.Parse(r); err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -76,17 +77,12 @@ func makeReservation(w http.ResponseWriter, r *http.Request, user *auth.User, co
|
||||||
page.MustRender(w, r, user, company, conn)
|
page.MustRender(w, r, user, company, conn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cart, err := computeCart(r.Context(), conn, f)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
schema := httplib.Protocol(r)
|
schema := httplib.Protocol(r)
|
||||||
authority := httplib.Host(r)
|
authority := httplib.Host(r)
|
||||||
request := &redsys.Request{
|
request := &redsys.Request{
|
||||||
TransactionType: redsys.TransactionTypeCharge,
|
TransactionType: redsys.TransactionTypeCharge,
|
||||||
Amount: cart.Total,
|
Amount: f.Cart.Total,
|
||||||
OrderNumber: randomOrderNumber(),
|
OrderNumber: randomOrderNumber(),
|
||||||
Product: "Test Booking",
|
Product: "Test Booking",
|
||||||
SuccessURL: fmt.Sprintf("%s://%s/%s/booking/success", schema, authority, user.Locale.Language),
|
SuccessURL: fmt.Sprintf("%s://%s/%s/booking/success", schema, authority, user.Locale.Language),
|
||||||
|
@ -113,11 +109,14 @@ func randomOrderNumber() string {
|
||||||
type publicPage struct {
|
type publicPage struct {
|
||||||
*template.PublicPage
|
*template.PublicPage
|
||||||
Form *bookingForm
|
Form *bookingForm
|
||||||
Cart *bookingCart
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPublicPage(ctx context.Context, company *auth.Company, conn *database.Conn, l *locale.Locale) *publicPage {
|
func newPublicPage(r *http.Request, company *auth.Company, conn *database.Conn, l *locale.Locale) (*publicPage, error) {
|
||||||
return newPublicPageWithForm(newBookingForm(ctx, company, conn, l))
|
f, err := newBookingForm(r, company, conn, l)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return newPublicPageWithForm(f), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPublicPageWithForm(form *bookingForm) *publicPage {
|
func newPublicPageWithForm(form *bookingForm) *publicPage {
|
||||||
|
@ -130,32 +129,52 @@ func newPublicPageWithForm(form *bookingForm) *publicPage {
|
||||||
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)
|
||||||
var err error
|
var err error
|
||||||
p.Cart, err = computeCart(r.Context(), conn, p.Form)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
template.MustRenderPublicFiles(w, r, user, company, p, "booking/form.gohtml", "booking/cart.gohtml")
|
if httplib.IsHTMxRequest(r) {
|
||||||
|
template.MustRenderPublicNoLayout(w, r, user, company, "booking/fields.gohtml", p)
|
||||||
|
} else {
|
||||||
|
template.MustRenderPublicFiles(w, r, user, company, p, "booking/page.gohtml", "booking/fields.gohtml")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type bookingForm struct {
|
type bookingForm struct {
|
||||||
FullName *form.Input
|
CampsiteType *form.Select
|
||||||
Address *form.Input
|
Dates *DateFields
|
||||||
PostalCode *form.Input
|
Guests *bookingGuestFields
|
||||||
City *form.Input
|
Options *bookingOptionFields
|
||||||
Country *form.Select
|
Customer *bookingCustomerFields
|
||||||
Email *form.Input
|
Cart *bookingCart
|
||||||
Phone *form.Input
|
}
|
||||||
CampsiteType *form.Select
|
|
||||||
CampsiteTypeOptions map[string][]*campsiteTypeOption
|
type DateFields struct {
|
||||||
ArrivalDate *form.Input
|
MinNights int
|
||||||
DepartureDate *form.Input
|
MaxNights int
|
||||||
NumberAdults *form.Input
|
ArrivalDate *bookingDateInput
|
||||||
NumberTeenagers *form.Input
|
DepartureDate *bookingDateInput
|
||||||
NumberChildren *form.Input
|
}
|
||||||
NumberDogs *form.Input
|
|
||||||
ZonePreferences map[string]*form.Input
|
type bookingDateInput struct {
|
||||||
ACSICard *form.Checkbox
|
*form.Input
|
||||||
Agreement *form.Checkbox
|
MinDate time.Time
|
||||||
|
MaxDate time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type bookingGuestFields struct {
|
||||||
|
MaxGuests int
|
||||||
|
OverflowAllowed bool
|
||||||
|
NumberAdults *form.Input
|
||||||
|
NumberTeenagers *form.Input
|
||||||
|
NumberChildren *form.Input
|
||||||
|
NumberDogs *form.Input
|
||||||
|
Error error
|
||||||
|
}
|
||||||
|
|
||||||
|
type bookingOptionFields struct {
|
||||||
|
Legend string
|
||||||
|
ZonePreferences *form.Input
|
||||||
|
Options []*campsiteTypeOption
|
||||||
}
|
}
|
||||||
|
|
||||||
type campsiteTypeOption struct {
|
type campsiteTypeOption struct {
|
||||||
|
@ -166,46 +185,331 @@ type campsiteTypeOption struct {
|
||||||
Input *form.Input
|
Input *form.Input
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBookingForm(ctx context.Context, company *auth.Company, conn *database.Conn, l *locale.Locale) *bookingForm {
|
type bookingCustomerFields struct {
|
||||||
var typeSelectOptions []*form.Option
|
FullName *form.Input
|
||||||
zonePreferences := make(map[string]*form.Input)
|
Address *form.Input
|
||||||
rows, err := conn.Query(ctx, `
|
PostalCode *form.Input
|
||||||
select type.slug
|
City *form.Input
|
||||||
, coalesce(i18n.name, type.name) as l10n_name
|
Country *form.Select
|
||||||
, ask_zone_preferences
|
Email *form.Input
|
||||||
from campsite_type as type
|
Phone *form.Input
|
||||||
left join campsite_type_i18n as i18n
|
ACSICard *form.Checkbox
|
||||||
on type.campsite_type_id = i18n.campsite_type_id
|
Agreement *form.Checkbox
|
||||||
and i18n.lang_tag = $1
|
}
|
||||||
where company_id = $2
|
|
||||||
and active
|
|
||||||
order by position, l10n_name
|
|
||||||
`, l.Language, company.ID)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
for rows.Next() {
|
func newBookingForm(r *http.Request, company *auth.Company, conn *database.Conn, l *locale.Locale) (*bookingForm, error) {
|
||||||
option := &form.Option{}
|
if err := r.ParseForm(); err != nil {
|
||||||
var ask bool
|
return nil, err
|
||||||
if err = rows.Scan(&option.Value, &option.Label, &ask); err != nil {
|
}
|
||||||
panic(err)
|
|
||||||
|
f := &bookingForm{
|
||||||
|
CampsiteType: &form.Select{
|
||||||
|
Name: "campsite_type",
|
||||||
|
Options: form.MustGetOptions(r.Context(), conn, "select type.slug, coalesce(i18n.name, type.name) as l10n_name from campsite_type as type left join campsite_type_i18n as i18n on type.campsite_type_id = i18n.campsite_type_id and i18n.lang_tag = $1 where company_id = $2 and active order by position, l10n_name", l.Language, company.ID),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
f.CampsiteType.FillValue(r)
|
||||||
|
campsiteType := f.CampsiteType.String()
|
||||||
|
if campsiteType == "" {
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
if !f.CampsiteType.ValidOptionsSelected() {
|
||||||
|
f.CampsiteType.Error = errors.New(l.Gettext("Selected campsite type is not valid."))
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
f.Dates, err = NewDateFields(r.Context(), conn, campsiteType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f.Dates.FillValues(r, l)
|
||||||
|
if f.Dates.ArrivalDate.Val == "" || f.Dates.ArrivalDate.Error != nil || f.Dates.DepartureDate.Val == "" || f.Dates.DepartureDate.Error != nil {
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Guests, err = newBookingGuestFields(r.Context(), conn, campsiteType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f.Guests.FillValues(r, l)
|
||||||
|
|
||||||
|
f.Options, err = newBookingOptionFields(r.Context(), conn, campsiteType, l)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if f.Options != nil {
|
||||||
|
f.Options.FillValues(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Customer = newBookingCustomerFields(r.Context(), conn, l)
|
||||||
|
f.Customer.FillValues(r)
|
||||||
|
|
||||||
|
f.Cart, err = newBookingCart(r.Context(), conn, f, campsiteType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *bookingForm) Valid(ctx context.Context, conn *database.Conn, l *locale.Locale) (bool, error) {
|
||||||
|
v := form.NewValidator(l)
|
||||||
|
|
||||||
|
if f.Dates == nil {
|
||||||
|
return false, errors.New("no booking date fields")
|
||||||
|
}
|
||||||
|
if f.Guests == nil {
|
||||||
|
return false, errors.New("no guests fields")
|
||||||
|
}
|
||||||
|
if f.Customer == nil {
|
||||||
|
return false, errors.New("no customer fields")
|
||||||
|
}
|
||||||
|
|
||||||
|
v.CheckSelectedOptions(f.CampsiteType, l.GettextNoop("Selected campsite type is not valid."))
|
||||||
|
f.Dates.Valid(v, l)
|
||||||
|
f.Guests.Valid(v, l)
|
||||||
|
f.Options.Valid(v, l)
|
||||||
|
if f.Options != nil {
|
||||||
|
if err := f.Customer.Valid(ctx, conn, v, l); err != nil {
|
||||||
|
return false, err
|
||||||
}
|
}
|
||||||
typeSelectOptions = append(typeSelectOptions, option)
|
}
|
||||||
if ask {
|
return v.AllOK, nil
|
||||||
zonePreferences[option.Value] = &form.Input{
|
}
|
||||||
Name: "zone_preferences_" + option.Value,
|
|
||||||
|
func NewDateFields(ctx context.Context, conn *database.Conn, campsiteType string) (*DateFields, error) {
|
||||||
|
row := conn.QueryRow(ctx, `
|
||||||
|
select lower(bookable_nights),
|
||||||
|
upper(bookable_nights) - 1,
|
||||||
|
greatest(min(lower(season_range)), current_timestamp::date),
|
||||||
|
max(upper(season_range))
|
||||||
|
from campsite_type
|
||||||
|
join campsite_type_cost using (campsite_type_id)
|
||||||
|
join season_calendar using (season_id)
|
||||||
|
where campsite_type.slug = $1
|
||||||
|
and season_range >> daterange(date_trunc('year', current_timestamp)::date, date_trunc('year', current_timestamp)::date + 1)
|
||||||
|
group by bookable_nights;
|
||||||
|
`, campsiteType)
|
||||||
|
f := &DateFields{
|
||||||
|
ArrivalDate: &bookingDateInput{
|
||||||
|
Input: &form.Input{Name: "arrival_date"},
|
||||||
|
},
|
||||||
|
DepartureDate: &bookingDateInput{
|
||||||
|
Input: &form.Input{Name: "departure_date"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err := row.Scan(&f.MinNights, &f.MaxNights, &f.ArrivalDate.MinDate, &f.DepartureDate.MaxDate); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f.ArrivalDate.MaxDate = f.DepartureDate.MaxDate.AddDate(0, 0, -f.MinNights)
|
||||||
|
f.DepartureDate.MinDate = f.ArrivalDate.MinDate.AddDate(0, 0, f.MinNights)
|
||||||
|
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *DateFields) FillValues(r *http.Request, l *locale.Locale) {
|
||||||
|
f.ArrivalDate.FillValue(r)
|
||||||
|
f.DepartureDate.FillValue(r)
|
||||||
|
|
||||||
|
if f.ArrivalDate.Val != "" {
|
||||||
|
arrivalDate, err := time.Parse(database.ISODateFormat, f.ArrivalDate.Val)
|
||||||
|
if err != nil {
|
||||||
|
f.ArrivalDate.Error = errors.New(l.Gettext("Arrival date must be a valid date."))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f.DepartureDate.MinDate = arrivalDate.AddDate(0, 0, f.MinNights)
|
||||||
|
maxDate := arrivalDate.AddDate(0, 0, f.MaxNights)
|
||||||
|
if maxDate.Before(f.DepartureDate.MaxDate) {
|
||||||
|
f.DepartureDate.MaxDate = maxDate
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.DepartureDate.Val == "" {
|
||||||
|
f.DepartureDate.Val = f.DepartureDate.MinDate.Format(database.ISODateFormat)
|
||||||
|
} else {
|
||||||
|
departureDate, err := time.Parse(database.ISODateFormat, f.DepartureDate.Val)
|
||||||
|
if err != nil {
|
||||||
|
f.DepartureDate.Error = errors.New(l.Gettext("Departure date must be a valid date."))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if departureDate.Before(f.DepartureDate.MinDate) {
|
||||||
|
f.DepartureDate.Val = f.DepartureDate.MinDate.Format(database.ISODateFormat)
|
||||||
|
} else if departureDate.After(f.DepartureDate.MaxDate) {
|
||||||
|
f.DepartureDate.Val = f.DepartureDate.MaxDate.Format(database.ISODateFormat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if rows.Err() != nil {
|
}
|
||||||
panic(rows.Err())
|
|
||||||
|
func (f *DateFields) Valid(v *form.Validator, l *locale.Locale) {
|
||||||
|
var validBefore bool
|
||||||
|
if v.CheckRequired(f.ArrivalDate.Input, l.GettextNoop("Arrival date can not be empty")) {
|
||||||
|
if v.CheckValidDate(f.ArrivalDate.Input, l.GettextNoop("Arrival date must be a valid date.")) {
|
||||||
|
if v.CheckMinDate(f.ArrivalDate.Input, f.ArrivalDate.MinDate, fmt.Sprintf(l.Gettext("Arrival date must be %s or after."), f.ArrivalDate.MinDate.Format(database.ISODateFormat))) {
|
||||||
|
v.CheckMaxDate(f.ArrivalDate.Input, f.ArrivalDate.MaxDate, fmt.Sprintf(l.Gettext("Arrival date must be %s or before."), f.ArrivalDate.MaxDate.Format(database.ISODateFormat)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v.CheckRequired(f.DepartureDate.Input, l.GettextNoop("Departure date can not be empty")) {
|
||||||
|
if v.CheckValidDate(f.DepartureDate.Input, l.GettextNoop("Departure date must be a valid date.")) && validBefore {
|
||||||
|
if v.CheckMinDate(f.DepartureDate.Input, f.DepartureDate.MinDate, fmt.Sprintf(l.Gettext("Departure date must be %s or after."), f.DepartureDate.MinDate.Format(database.ISODateFormat))) {
|
||||||
|
v.CheckMaxDate(f.DepartureDate.Input, f.DepartureDate.MaxDate, fmt.Sprintf(l.Gettext("Departure date must be %s or before."), f.DepartureDate.MaxDate.Format(database.ISODateFormat)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBookingGuestFields(ctx context.Context, conn *database.Conn, campsiteType string) (*bookingGuestFields, error) {
|
||||||
|
f := &bookingGuestFields{
|
||||||
|
NumberAdults: &form.Input{Name: "number_adults"},
|
||||||
|
NumberTeenagers: &form.Input{Name: "number_teenagers"},
|
||||||
|
NumberChildren: &form.Input{Name: "number_children"},
|
||||||
|
}
|
||||||
|
row := conn.QueryRow(ctx, `
|
||||||
|
select max_campers
|
||||||
|
, overflow_allowed
|
||||||
|
, dogs_allowed
|
||||||
|
from campsite_type
|
||||||
|
where slug = $1
|
||||||
|
`, campsiteType)
|
||||||
|
var dogsAllowed bool
|
||||||
|
if err := row.Scan(&f.MaxGuests, &f.OverflowAllowed, &dogsAllowed); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if dogsAllowed {
|
||||||
|
f.NumberDogs = &form.Input{Name: "number_dogs"}
|
||||||
|
}
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *bookingGuestFields) FillValues(r *http.Request, l *locale.Locale) {
|
||||||
|
numGuests := 0
|
||||||
|
numGuests += fillNumericField(f.NumberAdults, r, 1)
|
||||||
|
numGuests += fillNumericField(f.NumberTeenagers, r, 0)
|
||||||
|
numGuests += fillNumericField(f.NumberChildren, r, 0)
|
||||||
|
if f.NumberDogs != nil {
|
||||||
|
fillNumericField(f.NumberDogs, r, 0)
|
||||||
|
}
|
||||||
|
if !f.OverflowAllowed && numGuests > f.MaxGuests {
|
||||||
|
f.Error = fmt.Errorf(l.Gettext("There can be at most %d guests in this accommodation."), f.MaxGuests)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fillNumericField(input *form.Input, r *http.Request, min int) int {
|
||||||
|
input.FillValue(r)
|
||||||
|
if input.Val == "" {
|
||||||
|
input.Val = strconv.Itoa(min)
|
||||||
|
return min
|
||||||
|
}
|
||||||
|
val, err := strconv.Atoi(input.Val)
|
||||||
|
if err != nil {
|
||||||
|
input.Val = strconv.Itoa(min)
|
||||||
|
val = min
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *bookingGuestFields) Valid(v *form.Validator, l *locale.Locale) {
|
||||||
|
if v.CheckRequired(f.NumberAdults, l.GettextNoop("Number of adults can not be empty")) {
|
||||||
|
if v.CheckValidInteger(f.NumberAdults, l.GettextNoop("Number of adults must be an integer.")) {
|
||||||
|
v.CheckMinInteger(f.NumberAdults, 1, l.GettextNoop("There must be at least one adult."))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v.CheckRequired(f.NumberTeenagers, l.GettextNoop("Number of teenagers can not be empty")) {
|
||||||
|
if v.CheckValidInteger(f.NumberTeenagers, l.GettextNoop("Number of teenagers must be an integer.")) {
|
||||||
|
v.CheckMinInteger(f.NumberTeenagers, 0, l.GettextNoop("Number of teenagers can not be negative."))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v.CheckRequired(f.NumberChildren, l.GettextNoop("Number of children can not be empty")) {
|
||||||
|
if v.CheckValidInteger(f.NumberChildren, l.GettextNoop("Number of children must be an integer.")) {
|
||||||
|
v.CheckMinInteger(f.NumberChildren, 0, l.GettextNoop("Number of children can not be negative."))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v.CheckRequired(f.NumberDogs, l.GettextNoop("Number of dogs can not be empty")) {
|
||||||
|
if v.CheckValidInteger(f.NumberDogs, l.GettextNoop("Number of dogs must be an integer.")) {
|
||||||
|
v.CheckMinInteger(f.NumberDogs, 0, l.GettextNoop("Number of dogs can not be negative."))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBookingOptionFields(ctx context.Context, conn *database.Conn, campsiteType string, l *locale.Locale) (*bookingOptionFields, error) {
|
||||||
|
f := &bookingOptionFields{}
|
||||||
|
|
||||||
|
row := conn.QueryRow(ctx, `
|
||||||
|
select coalesce(i18n.name, campsite_type.name)
|
||||||
|
, ask_zone_preferences
|
||||||
|
from campsite_type
|
||||||
|
left join campsite_type_i18n as i18n on i18n.campsite_type_id = campsite_type.campsite_type_id and i18n.lang_tag = $1
|
||||||
|
where slug = $2
|
||||||
|
`, l.Language, campsiteType)
|
||||||
|
var askZonePreferences bool
|
||||||
|
if err := row.Scan(&f.Legend, &askZonePreferences); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if askZonePreferences {
|
||||||
|
f.ZonePreferences = &form.Input{Name: "zone_preferences"}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &bookingForm{
|
rows, err := conn.Query(ctx, `
|
||||||
CampsiteTypeOptions: mustGetCampsiteTypeOptions(ctx, conn, company, l),
|
select option.campsite_type_option_id
|
||||||
ZonePreferences: zonePreferences,
|
, 'campsite_type_option_' || option.campsite_type_option_id
|
||||||
|
, coalesce(i18n.name, option.name) as l10_name
|
||||||
|
, lower(range)::text
|
||||||
|
, lower(range)
|
||||||
|
, upper(range)
|
||||||
|
from campsite_type_option as option
|
||||||
|
join campsite_type using (campsite_type_id)
|
||||||
|
left join campsite_type_option_i18n as i18n on i18n.campsite_type_option_id = option.campsite_type_option_id and i18n.lang_tag = $1
|
||||||
|
where slug = $2
|
||||||
|
and campsite_type.active
|
||||||
|
order by option.position, l10_name
|
||||||
|
`, l.Language, campsiteType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
for rows.Next() {
|
||||||
|
option := &campsiteTypeOption{
|
||||||
|
Input: &form.Input{},
|
||||||
|
}
|
||||||
|
if err = rows.Scan(&option.ID, &option.Input.Name, &option.Label, &option.Input.Val, &option.Min, &option.Max); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f.Options = append(f.Options, option)
|
||||||
|
}
|
||||||
|
if rows.Err() != nil {
|
||||||
|
return nil, rows.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.ZonePreferences == nil && len(f.Options) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *bookingOptionFields) FillValues(r *http.Request) {
|
||||||
|
if f.ZonePreferences != nil {
|
||||||
|
f.ZonePreferences.FillValue(r)
|
||||||
|
}
|
||||||
|
for _, option := range f.Options {
|
||||||
|
fillNumericField(option.Input, r, option.Min)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *bookingOptionFields) Valid(v *form.Validator, l *locale.Locale) {
|
||||||
|
for _, option := range f.Options {
|
||||||
|
if v.CheckRequired(option.Input, fmt.Sprintf(l.Gettext("%s can not be empty"), option.Label)) {
|
||||||
|
if v.CheckValidInteger(option.Input, fmt.Sprintf(l.Gettext("%s must be an integer."), option.Label)) {
|
||||||
|
if v.CheckMinInteger(option.Input, option.Min, fmt.Sprintf(l.Gettext("%s must be %d or greater."), option.Label, option.Min)) {
|
||||||
|
v.CheckMaxInteger(option.Input, option.Max, fmt.Sprintf(l.Gettext("%s must be at most %d."), option.Label, option.Max))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBookingCustomerFields(ctx context.Context, conn *database.Conn, l *locale.Locale) *bookingCustomerFields {
|
||||||
|
return &bookingCustomerFields{
|
||||||
FullName: &form.Input{
|
FullName: &form.Input{
|
||||||
Name: "full_name",
|
Name: "full_name",
|
||||||
},
|
},
|
||||||
|
@ -228,32 +532,6 @@ func newBookingForm(ctx context.Context, company *auth.Company, conn *database.C
|
||||||
Phone: &form.Input{
|
Phone: &form.Input{
|
||||||
Name: "phone",
|
Name: "phone",
|
||||||
},
|
},
|
||||||
CampsiteType: &form.Select{
|
|
||||||
Name: "campsite_type",
|
|
||||||
Options: typeSelectOptions,
|
|
||||||
},
|
|
||||||
ArrivalDate: &form.Input{
|
|
||||||
Name: "arrival_date",
|
|
||||||
},
|
|
||||||
DepartureDate: &form.Input{
|
|
||||||
Name: "departure_date",
|
|
||||||
},
|
|
||||||
NumberAdults: &form.Input{
|
|
||||||
Name: "number_adults",
|
|
||||||
Val: "1",
|
|
||||||
},
|
|
||||||
NumberTeenagers: &form.Input{
|
|
||||||
Name: "number_teenagers",
|
|
||||||
Val: "0",
|
|
||||||
},
|
|
||||||
NumberChildren: &form.Input{
|
|
||||||
Name: "number_children",
|
|
||||||
Val: "0",
|
|
||||||
},
|
|
||||||
NumberDogs: &form.Input{
|
|
||||||
Name: "number_dogs",
|
|
||||||
Val: "0",
|
|
||||||
},
|
|
||||||
ACSICard: &form.Checkbox{
|
ACSICard: &form.Checkbox{
|
||||||
Name: "acsi_card",
|
Name: "acsi_card",
|
||||||
},
|
},
|
||||||
|
@ -263,47 +541,7 @@ func newBookingForm(ctx context.Context, company *auth.Company, conn *database.C
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustGetCampsiteTypeOptions(ctx context.Context, conn *database.Conn, company *auth.Company, l *locale.Locale) map[string][]*campsiteTypeOption {
|
func (f *bookingCustomerFields) FillValues(r *http.Request) {
|
||||||
rows, err := conn.Query(ctx, `
|
|
||||||
select option.campsite_type_option_id
|
|
||||||
, 'campsite_type_option_' || option.campsite_type_option_id
|
|
||||||
, slug
|
|
||||||
, coalesce(i18n.name, option.name) as l10_name
|
|
||||||
, lower(range)::text
|
|
||||||
, lower(range)
|
|
||||||
, upper(range)
|
|
||||||
from campsite_type_option as option
|
|
||||||
join campsite_type using (campsite_type_id)
|
|
||||||
left join campsite_type_option_i18n as i18n on i18n.campsite_type_option_id = option.campsite_type_option_id and i18n.lang_tag = $1
|
|
||||||
where company_id = $2
|
|
||||||
and campsite_type.active
|
|
||||||
order by option.position, l10_name
|
|
||||||
`, l.Language, company.ID)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
options := make(map[string][]*campsiteTypeOption)
|
|
||||||
for rows.Next() {
|
|
||||||
var slug string
|
|
||||||
option := &campsiteTypeOption{
|
|
||||||
Input: &form.Input{},
|
|
||||||
}
|
|
||||||
if err = rows.Scan(&option.ID, &option.Input.Name, &slug, &option.Label, &option.Input.Val, &option.Min, &option.Max); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
options[slug] = append(options[slug], option)
|
|
||||||
}
|
|
||||||
if rows.Err() != nil {
|
|
||||||
panic(rows.Err())
|
|
||||||
}
|
|
||||||
return options
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *bookingForm) Parse(r *http.Request) error {
|
|
||||||
if err := r.ParseForm(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
f.FullName.FillValue(r)
|
f.FullName.FillValue(r)
|
||||||
f.Address.FillValue(r)
|
f.Address.FillValue(r)
|
||||||
f.PostalCode.FillValue(r)
|
f.PostalCode.FillValue(r)
|
||||||
|
@ -311,29 +549,11 @@ func (f *bookingForm) Parse(r *http.Request) error {
|
||||||
f.Country.FillValue(r)
|
f.Country.FillValue(r)
|
||||||
f.Email.FillValue(r)
|
f.Email.FillValue(r)
|
||||||
f.Phone.FillValue(r)
|
f.Phone.FillValue(r)
|
||||||
f.CampsiteType.FillValue(r)
|
|
||||||
f.ArrivalDate.FillValue(r)
|
|
||||||
f.DepartureDate.FillValue(r)
|
|
||||||
f.NumberAdults.FillValue(r)
|
|
||||||
f.NumberTeenagers.FillValue(r)
|
|
||||||
f.NumberChildren.FillValue(r)
|
|
||||||
f.NumberDogs.FillValue(r)
|
|
||||||
f.ACSICard.FillValue(r)
|
f.ACSICard.FillValue(r)
|
||||||
f.Agreement.FillValue(r)
|
f.Agreement.FillValue(r)
|
||||||
for _, preferences := range f.ZonePreferences {
|
|
||||||
preferences.FillValue(r)
|
|
||||||
}
|
|
||||||
for _, options := range f.CampsiteTypeOptions {
|
|
||||||
for _, option := range options {
|
|
||||||
option.Input.FillValue(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *bookingForm) Valid(ctx context.Context, conn *database.Conn, l *locale.Locale) (bool, error) {
|
func (f *bookingCustomerFields) Valid(ctx context.Context, conn *database.Conn, v *form.Validator, l *locale.Locale) error {
|
||||||
v := form.NewValidator(l)
|
|
||||||
|
|
||||||
var country string
|
var country string
|
||||||
if v.CheckSelectedOptions(f.Country, l.GettextNoop("Selected country is not valid.")) {
|
if v.CheckSelectedOptions(f.Country, l.GettextNoop("Selected country is not valid.")) {
|
||||||
country = f.Country.Selected[0]
|
country = f.Country.Selected[0]
|
||||||
|
@ -345,7 +565,7 @@ func (f *bookingForm) Valid(ctx context.Context, conn *database.Conn, l *locale.
|
||||||
|
|
||||||
if country != "" && f.PostalCode.Val != "" {
|
if country != "" && f.PostalCode.Val != "" {
|
||||||
if _, err := v.CheckValidPostalCode(ctx, conn, f.PostalCode, country, l.GettextNoop("This postal code is not valid.")); err != nil {
|
if _, err := v.CheckValidPostalCode(ctx, conn, f.PostalCode, country, l.GettextNoop("This postal code is not valid.")); err != nil {
|
||||||
return false, err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if v.CheckRequired(f.Email, l.GettextNoop("Email can not be empty.")) {
|
if v.CheckRequired(f.Email, l.GettextNoop("Email can not be empty.")) {
|
||||||
|
@ -353,53 +573,10 @@ func (f *bookingForm) Valid(ctx context.Context, conn *database.Conn, l *locale.
|
||||||
}
|
}
|
||||||
if v.CheckRequired(f.Phone, l.GettextNoop("Phone can not be empty.")) {
|
if v.CheckRequired(f.Phone, l.GettextNoop("Phone can not be empty.")) {
|
||||||
if _, err := v.CheckValidPhone(ctx, conn, f.Phone, country, l.GettextNoop("This phone number is not valid.")); err != nil {
|
if _, err := v.CheckValidPhone(ctx, conn, f.Phone, country, l.GettextNoop("This phone number is not valid.")); err != nil {
|
||||||
return false, err
|
return err
|
||||||
}
|
|
||||||
}
|
|
||||||
var validBefore bool
|
|
||||||
v.CheckSelectedOptions(f.CampsiteType, l.GettextNoop("Selected campsite type is not valid."))
|
|
||||||
if v.CheckRequired(f.ArrivalDate, l.GettextNoop("Arrival date can not be empty")) {
|
|
||||||
if v.CheckValidDate(f.ArrivalDate, l.GettextNoop("Arrival date must be a valid date.")) {
|
|
||||||
validBefore = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if v.CheckRequired(f.DepartureDate, l.GettextNoop("Departure date can not be empty")) {
|
|
||||||
if v.CheckValidDate(f.DepartureDate, l.GettextNoop("Departure date must be a valid date.")) && validBefore {
|
|
||||||
v.CheckDateAfter(f.DepartureDate, f.ArrivalDate, l.GettextNoop("The departure date must be after the arrival date."))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.CheckRequired(f.NumberAdults, l.GettextNoop("Number of adults can not be empty")) {
|
|
||||||
if v.CheckValidInteger(f.NumberAdults, l.GettextNoop("Number of adults must be an integer.")) {
|
|
||||||
v.CheckMinInteger(f.NumberAdults, 1, l.GettextNoop("There must be at least one adult."))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if v.CheckRequired(f.NumberTeenagers, l.GettextNoop("Number of teenagers can not be empty")) {
|
|
||||||
if v.CheckValidInteger(f.NumberTeenagers, l.GettextNoop("Number of teenagers must be an integer.")) {
|
|
||||||
v.CheckMinInteger(f.NumberTeenagers, 0, l.GettextNoop("Number of teenagers can not be negative."))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if v.CheckRequired(f.NumberTeenagers, l.GettextNoop("Number of children can not be empty")) {
|
|
||||||
if v.CheckValidInteger(f.NumberTeenagers, l.GettextNoop("Number of children must be an integer.")) {
|
|
||||||
v.CheckMinInteger(f.NumberTeenagers, 0, l.GettextNoop("Number of children can not be negative."))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if v.CheckRequired(f.NumberTeenagers, l.GettextNoop("Number of dogs can not be empty")) {
|
|
||||||
if v.CheckValidInteger(f.NumberTeenagers, l.GettextNoop("Number of dogs must be an integer.")) {
|
|
||||||
v.CheckMinInteger(f.NumberTeenagers, 0, l.GettextNoop("Number of dogs can not be negative."))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v.Check(f.Agreement, f.Agreement.Checked, l.GettextNoop("It is mandatory to agree to the reservation conditions."))
|
v.Check(f.Agreement, f.Agreement.Checked, l.GettextNoop("It is mandatory to agree to the reservation conditions."))
|
||||||
for _, options := range f.CampsiteTypeOptions {
|
return nil
|
||||||
for _, option := range options {
|
|
||||||
if v.CheckRequired(option.Input, fmt.Sprintf(l.Gettext("%s can not be empty"), option.Label)) {
|
|
||||||
if v.CheckValidInteger(option.Input, fmt.Sprintf(l.Gettext("%s must be an integer."), option.Label)) {
|
|
||||||
if v.CheckMinInteger(option.Input, option.Min, fmt.Sprintf(l.Gettext("%s must be %d or greater."), option.Label, option.Min)) {
|
|
||||||
v.CheckMaxInteger(option.Input, option.Max, fmt.Sprintf(l.Gettext("%s must be at most %d."), option.Label, option.Max))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return v.AllOK, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,14 +7,15 @@ package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/jackc/pgx/v4"
|
|
||||||
gotemplate "html/template"
|
gotemplate "html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/jackc/pgx/v4"
|
||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
|
|
||||||
"dev.tandem.ws/tandem/camper/pkg/auth"
|
"dev.tandem.ws/tandem/camper/pkg/auth"
|
||||||
|
"dev.tandem.ws/tandem/camper/pkg/booking"
|
||||||
"dev.tandem.ws/tandem/camper/pkg/carousel"
|
"dev.tandem.ws/tandem/camper/pkg/carousel"
|
||||||
"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"
|
||||||
|
@ -54,6 +55,21 @@ func (h *PublicHandler) Handler(user *auth.User, company *auth.Company, conn *da
|
||||||
default:
|
default:
|
||||||
httplib.MethodNotAllowed(w, r, http.MethodGet)
|
httplib.MethodNotAllowed(w, r, http.MethodGet)
|
||||||
}
|
}
|
||||||
|
case "dates":
|
||||||
|
switch r.Method {
|
||||||
|
case http.MethodGet:
|
||||||
|
bookingDates, err := booking.NewDateFields(r.Context(), conn, typeUuid)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if err := r.ParseForm(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
bookingDates.FillValues(r, user.Locale)
|
||||||
|
template.MustRenderPublicNoLayout(w, r, user, company, "campsite/dates.gohtml", bookingDates)
|
||||||
|
default:
|
||||||
|
httplib.MethodNotAllowed(w, r, http.MethodGet)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
}
|
}
|
||||||
|
@ -78,8 +94,7 @@ type publicPage struct {
|
||||||
AdditionalInfo gotemplate.HTML
|
AdditionalInfo gotemplate.HTML
|
||||||
CheckIn string
|
CheckIn string
|
||||||
CheckOut string
|
CheckOut string
|
||||||
MinNights int
|
BookingDates *booking.DateFields
|
||||||
MaxNights int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type typePrice struct {
|
type typePrice struct {
|
||||||
|
@ -124,8 +139,6 @@ func newPublicPage(ctx context.Context, company *auth.Company, conn *database.Co
|
||||||
, coalesce(i18n.additional_info, campsite_type.additional_info)::text as l10n_description
|
, coalesce(i18n.additional_info, campsite_type.additional_info)::text as l10n_description
|
||||||
, coalesce(i18n.check_in, campsite_type.check_in)::text as l10n_check_in
|
, coalesce(i18n.check_in, campsite_type.check_in)::text as l10n_check_in
|
||||||
, coalesce(i18n.check_out, campsite_type.check_out)::text as l10n_check_out
|
, coalesce(i18n.check_out, campsite_type.check_out)::text as l10n_check_out
|
||||||
, lower(bookable_nights)
|
|
||||||
, upper(bookable_nights) - 1
|
|
||||||
, dogs_allowed
|
, dogs_allowed
|
||||||
, '3.50' as dogs_prices
|
, '3.50' as dogs_prices
|
||||||
from campsite_type
|
from campsite_type
|
||||||
|
@ -142,8 +155,6 @@ func newPublicPage(ctx context.Context, company *auth.Company, conn *database.Co
|
||||||
&page.AdditionalInfo,
|
&page.AdditionalInfo,
|
||||||
&page.CheckIn,
|
&page.CheckIn,
|
||||||
&page.CheckOut,
|
&page.CheckOut,
|
||||||
&page.MinNights,
|
|
||||||
&page.MaxNights,
|
|
||||||
&page.DogsAllowed,
|
&page.DogsAllowed,
|
||||||
&page.DogsPrice,
|
&page.DogsPrice,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
|
@ -152,6 +163,10 @@ func newPublicPage(ctx context.Context, company *auth.Company, conn *database.Co
|
||||||
if err = conn.QueryRow(ctx, "select to_price(tourist_tax, $1) from company where company_id = $2", company.DecimalDigits, company.ID).Scan(&page.TouristTax); err != nil {
|
if err = conn.QueryRow(ctx, "select to_price(tourist_tax, $1) from company where company_id = $2", company.DecimalDigits, company.ID).Scan(&page.TouristTax); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
page.BookingDates, err = booking.NewDateFields(ctx, conn, slug)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
page.Prices, err = collectPrices(ctx, conn, loc.Language, slug, page.Name)
|
page.Prices, err = collectPrices(ctx, conn, loc.Language, slug, page.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -280,5 +295,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.MustRenderPublicFiles(w, r, user, company, p, "campsite/type.gohtml", "campsite/calendar.gohtml")
|
template.MustRenderPublicFiles(w, r, user, company, p, "campsite/type.gohtml", "campsite/calendar.gohtml", "campsite/dates.gohtml")
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ func (s *Select) FillValue(r *http.Request) {
|
||||||
s.Selected = r.Form[s.Name]
|
s.Selected = r.Form[s.Name]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Select) validOptionsSelected() bool {
|
func (s *Select) ValidOptionsSelected() bool {
|
||||||
for _, selected := range s.Selected {
|
for _, selected := range s.Selected {
|
||||||
if !s.isValidOption(selected) {
|
if !s.isValidOption(selected) {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -130,12 +130,22 @@ func (v *Validator) CheckDateAfter(field *Input, beforeField *Input, message str
|
||||||
return v.Check(field, date.After(before), message)
|
return v.Check(field, date.After(before), message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *Validator) CheckMinDate(field *Input, min time.Time, message string) bool {
|
||||||
|
date, _ := time.Parse(database.ISODateFormat, field.Val)
|
||||||
|
return v.Check(field, !date.Before(min), message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Validator) CheckMaxDate(field *Input, max time.Time, message string) bool {
|
||||||
|
date, _ := time.Parse(database.ISODateFormat, field.Val)
|
||||||
|
return v.Check(field, !date.After(max), message)
|
||||||
|
}
|
||||||
|
|
||||||
func (v *Validator) CheckPasswordConfirmation(password *Input, confirm *Input, message string) bool {
|
func (v *Validator) CheckPasswordConfirmation(password *Input, confirm *Input, message string) bool {
|
||||||
return v.Check(confirm, password.Val == confirm.Val, message)
|
return v.Check(confirm, password.Val == confirm.Val, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Validator) CheckSelectedOptions(field *Select, message string) bool {
|
func (v *Validator) CheckSelectedOptions(field *Select, message string) bool {
|
||||||
return v.Check(field, field.validOptionsSelected(), message)
|
return v.Check(field, field.ValidOptionsSelected(), message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Validator) CheckImageFile(field *File, message string) bool {
|
func (v *Validator) CheckImageFile(field *File, message string) bool {
|
||||||
|
|
|
@ -107,11 +107,8 @@ func mustRenderLayout(w io.Writer, user *auth.User, company *auth.Company, templ
|
||||||
"formatDate": func(time time.Time) template.HTML {
|
"formatDate": func(time time.Time) template.HTML {
|
||||||
return template.HTML(`<time datetime="` + time.Format(database.ISODateFormat) + `">` + time.Format("02/01/2006") + "</time>")
|
return template.HTML(`<time datetime="` + time.Format(database.ISODateFormat) + `">` + time.Format("02/01/2006") + "</time>")
|
||||||
},
|
},
|
||||||
"today": func() string {
|
"formatDateAttr": func(time time.Time) string {
|
||||||
return time.Now().Format(database.ISODateFormat)
|
return time.Format(database.ISODateFormat)
|
||||||
},
|
|
||||||
"tomorrow": func() string {
|
|
||||||
return time.Now().AddDate(0, 0, 1).Format(database.ISODateFormat)
|
|
||||||
},
|
},
|
||||||
"queryEscape": func(s string) string {
|
"queryEscape": func(s string) string {
|
||||||
return url.QueryEscape(s)
|
return url.QueryEscape(s)
|
||||||
|
|
264
po/ca.po
264
po/ca.po
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: camper\n"
|
"Project-Id-Version: camper\n"
|
||||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||||
"POT-Creation-Date: 2024-02-04 06:23+0100\n"
|
"POT-Creation-Date: 2024-02-10 03:29+0100\n"
|
||||||
"PO-Revision-Date: 2024-02-06 10:04+0100\n"
|
"PO-Revision-Date: 2024-02-06 10:04+0100\n"
|
||||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||||
"Language-Team: Catalan <ca@dodds.net>\n"
|
"Language-Team: Catalan <ca@dodds.net>\n"
|
||||||
|
@ -95,7 +95,7 @@ msgid "The campsite offers many different services."
|
||||||
msgstr "El càmping disposa de diversos serveis."
|
msgstr "El càmping disposa de diversos serveis."
|
||||||
|
|
||||||
#: web/templates/public/amenity.gohtml:39
|
#: web/templates/public/amenity.gohtml:39
|
||||||
#: web/templates/public/campsite/type.gohtml:113
|
#: web/templates/public/campsite/type.gohtml:106
|
||||||
#: web/templates/public/campsite/page.gohtml:39
|
#: web/templates/public/campsite/page.gohtml:39
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Features"
|
msgid "Features"
|
||||||
|
@ -154,89 +154,79 @@ msgstr "A menys d’una hora de <strong>Girona</strong>, a una de <strong>La Bis
|
||||||
msgid "Discover"
|
msgid "Discover"
|
||||||
msgstr "Descobreix"
|
msgstr "Descobreix"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:41
|
#: web/templates/public/campsite/type.gohtml:49
|
||||||
msgctxt "input"
|
#: web/templates/public/booking/fields.gohtml:240
|
||||||
msgid "Check-in Date"
|
|
||||||
msgstr "Data d’entrada"
|
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:47
|
|
||||||
msgctxt "input"
|
|
||||||
msgid "Check-out Date"
|
|
||||||
msgstr "Data de sortida"
|
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:56
|
|
||||||
#: web/templates/public/booking/cart.gohtml:25
|
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Book"
|
msgid "Book"
|
||||||
msgstr "Reserva"
|
msgstr "Reserva"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:64
|
#: web/templates/public/campsite/type.gohtml:57
|
||||||
#: web/templates/admin/season/index.gohtml:54
|
#: web/templates/admin/season/index.gohtml:54
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Calendar"
|
msgid "Calendar"
|
||||||
msgstr "Calendari"
|
msgstr "Calendari"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:75
|
#: web/templates/public/campsite/type.gohtml:68
|
||||||
#: web/templates/admin/campsite/type/form.gohtml:143
|
#: web/templates/admin/campsite/type/form.gohtml:143
|
||||||
#: web/templates/admin/campsite/type/option/form.gohtml:70
|
#: web/templates/admin/campsite/type/option/form.gohtml:70
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Prices"
|
msgid "Prices"
|
||||||
msgstr "Preus"
|
msgstr "Preus"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:88
|
#: web/templates/public/campsite/type.gohtml:81
|
||||||
msgid "%s: %s/night"
|
msgid "%s: %s/night"
|
||||||
msgstr "%s: %s/nit"
|
msgstr "%s: %s/nit"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:90
|
#: web/templates/public/campsite/type.gohtml:83
|
||||||
msgid "%s/night"
|
msgid "%s/night"
|
||||||
msgstr "%s/nit"
|
msgstr "%s/nit"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:95
|
#: web/templates/public/campsite/type.gohtml:88
|
||||||
msgid "*Minimum %d nights per stay"
|
msgid "*Minimum %d nights per stay"
|
||||||
msgstr "*Mínim %d nits per estada"
|
msgstr "*Mínim %d nits per estada"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:100
|
#: web/templates/public/campsite/type.gohtml:93
|
||||||
msgid "10 % VAT included."
|
msgid "10 % VAT included."
|
||||||
msgstr "IVA del 10 % inclòs."
|
msgstr "IVA del 10 % inclòs."
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:101
|
#: web/templates/public/campsite/type.gohtml:94
|
||||||
msgid "Tourist tax: %s/night per person aged 17 or older."
|
msgid "Tourist tax: %s/night per person aged 17 or older."
|
||||||
msgstr "Impost turístic: %s/nit per persona major de 16 anys."
|
msgstr "Impost turístic: %s/nit per persona major de 16 anys."
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:103
|
#: web/templates/public/campsite/type.gohtml:96
|
||||||
msgid "Dogs: %s/night, tied, accompanied, and minimal barking."
|
msgid "Dogs: %s/night, tied, accompanied, and minimal barking."
|
||||||
msgstr "Gossos: %s/nit, lligats, acompanyats i el mínim de lladrucs."
|
msgstr "Gossos: %s/nit, lligats, acompanyats i el mínim de lladrucs."
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:105
|
#: web/templates/public/campsite/type.gohtml:98
|
||||||
msgid "No dogs allowed."
|
msgid "No dogs allowed."
|
||||||
msgstr "No es permeten gossos."
|
msgstr "No es permeten gossos."
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:124
|
#: web/templates/public/campsite/type.gohtml:117
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Info"
|
msgid "Info"
|
||||||
msgstr "Informació"
|
msgstr "Informació"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:128
|
#: web/templates/public/campsite/type.gohtml:121
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Facilities"
|
msgid "Facilities"
|
||||||
msgstr "Equipaments"
|
msgstr "Equipaments"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:132
|
#: web/templates/public/campsite/type.gohtml:125
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Descripció"
|
msgstr "Descripció"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:136
|
#: web/templates/public/campsite/type.gohtml:129
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Additional Information"
|
msgid "Additional Information"
|
||||||
msgstr "Informació addicional"
|
msgstr "Informació addicional"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:139
|
#: web/templates/public/campsite/type.gohtml:132
|
||||||
msgctxt "time"
|
msgctxt "time"
|
||||||
msgid "Check-in"
|
msgid "Check-in"
|
||||||
msgstr "Entrada"
|
msgstr "Entrada"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:143
|
#: web/templates/public/campsite/type.gohtml:136
|
||||||
msgctxt "time"
|
msgctxt "time"
|
||||||
msgid "Check-out"
|
msgid "Check-out"
|
||||||
msgstr "Sortida"
|
msgstr "Sortida"
|
||||||
|
@ -283,6 +273,18 @@ msgctxt "day"
|
||||||
msgid "Sun"
|
msgid "Sun"
|
||||||
msgstr "dg"
|
msgstr "dg"
|
||||||
|
|
||||||
|
#: web/templates/public/campsite/dates.gohtml:4
|
||||||
|
#: web/templates/public/booking/fields.gohtml:26
|
||||||
|
msgctxt "input"
|
||||||
|
msgid "Arrival date"
|
||||||
|
msgstr "Data d’arribada"
|
||||||
|
|
||||||
|
#: web/templates/public/campsite/dates.gohtml:15
|
||||||
|
#: web/templates/public/booking/fields.gohtml:37
|
||||||
|
msgctxt "input"
|
||||||
|
msgid "Departure date"
|
||||||
|
msgstr "Data de sortida"
|
||||||
|
|
||||||
#: web/templates/public/surroundings.gohtml:30
|
#: web/templates/public/surroundings.gohtml:30
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "What to Do Outside the Campsite?"
|
msgid "What to Do Outside the Campsite?"
|
||||||
|
@ -516,8 +518,7 @@ msgid "Campsites"
|
||||||
msgstr "Allotjaments"
|
msgstr "Allotjaments"
|
||||||
|
|
||||||
#: web/templates/public/layout.gohtml:70
|
#: web/templates/public/layout.gohtml:70
|
||||||
#: web/templates/public/booking/form.gohtml:7
|
#: web/templates/public/booking/page.gohtml:7
|
||||||
#: web/templates/public/booking/form.gohtml:16
|
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Booking"
|
msgid "Booking"
|
||||||
msgstr "Reserva"
|
msgstr "Reserva"
|
||||||
|
@ -536,119 +537,113 @@ msgstr "Obertura"
|
||||||
msgid "<abbr title=\"Catalonia Tourism Registry\">RTC</abbr> <abbr title=\"Number\">#</abbr>%s"
|
msgid "<abbr title=\"Catalonia Tourism Registry\">RTC</abbr> <abbr title=\"Number\">#</abbr>%s"
|
||||||
msgstr "<abbr title=\"Número\">Núm.</abbr> <abbr title=\"Registre de Turisme de Catalunya\">RTC</abbr> %s"
|
msgstr "<abbr title=\"Número\">Núm.</abbr> <abbr title=\"Registre de Turisme de Catalunya\">RTC</abbr> %s"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:29
|
#: web/templates/public/booking/fields.gohtml:13
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Accommodation"
|
msgid "Accommodation"
|
||||||
msgstr "Allotjaments"
|
msgstr "Allotjaments"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:43
|
#: web/templates/public/booking/fields.gohtml:23
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Booking Period"
|
msgid "Booking Period"
|
||||||
msgstr "Període de reserva"
|
msgstr "Període de reserva"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:46
|
#: web/templates/public/booking/fields.gohtml:50
|
||||||
msgctxt "input"
|
|
||||||
msgid "Arrival date"
|
|
||||||
msgstr "Data d’arribada"
|
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:57
|
|
||||||
msgctxt "input"
|
|
||||||
msgid "Departure date"
|
|
||||||
msgstr "Data de sortida"
|
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:72
|
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Guests"
|
msgid "Guests"
|
||||||
msgstr "Hostes"
|
msgstr "Hostes"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:76
|
#: web/templates/public/booking/fields.gohtml:54
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Adults aged 17 or older"
|
msgid "Adults aged 17 or older"
|
||||||
msgstr "Adults de 17 anys o més"
|
msgstr "Adults de 17 anys o més"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:86
|
#: web/templates/public/booking/fields.gohtml:65
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Teenagers from 11 to 16 years old"
|
msgid "Teenagers from 11 to 16 years old"
|
||||||
msgstr "Adolescents d’entre 11 i 16 anys"
|
msgstr "Adolescents d’entre 11 i 16 anys"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:96
|
#: web/templates/public/booking/fields.gohtml:76
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Children from 2 to 10 years old"
|
msgid "Children from 2 to 10 years old"
|
||||||
msgstr "Nens d’entre 2 i 10 anys)"
|
msgstr "Nens d’entre 2 i 10 anys)"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:106
|
#: web/templates/public/booking/fields.gohtml:91
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Dogs"
|
msgid "Dogs"
|
||||||
msgstr "Gossos"
|
msgstr "Gossos"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:127
|
#: web/templates/public/booking/fields.gohtml:100
|
||||||
|
msgid "Note: This accommodation does <strong>not</strong> allow dogs."
|
||||||
|
msgstr "Nota: A aquest allotjament <strong>no</strong> s’hi permeten gossos."
|
||||||
|
|
||||||
|
#: web/templates/public/booking/fields.gohtml:110
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Area preferences (optional)"
|
msgid "Area preferences (optional)"
|
||||||
msgstr "Preferències d’àrea (opcional)"
|
msgstr "Preferències d’àrea (opcional)"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:129
|
#: web/templates/public/booking/fields.gohtml:112
|
||||||
msgid "Campground map"
|
msgid "Campground map"
|
||||||
msgstr "Mapa del càmping"
|
msgstr "Mapa del càmping"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:156
|
#: web/templates/public/booking/fields.gohtml:135
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Customer Details"
|
msgid "Customer Details"
|
||||||
msgstr "Detalls del client"
|
msgstr "Detalls del client"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:159
|
#: web/templates/public/booking/fields.gohtml:138
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Full name"
|
msgid "Full name"
|
||||||
msgstr "Nom i cognoms"
|
msgstr "Nom i cognoms"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:168
|
#: web/templates/public/booking/fields.gohtml:147
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Address (optional)"
|
msgid "Address (optional)"
|
||||||
msgstr "Adreça (opcional)"
|
msgstr "Adreça (opcional)"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:177
|
#: web/templates/public/booking/fields.gohtml:156
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Postcode (optional)"
|
msgid "Postcode (optional)"
|
||||||
msgstr "Codi postal (opcional)"
|
msgstr "Codi postal (opcional)"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:186
|
#: web/templates/public/booking/fields.gohtml:165
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Town or village (optional)"
|
msgid "Town or village (optional)"
|
||||||
msgstr "Població (opcional)"
|
msgstr "Població (opcional)"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:195
|
#: web/templates/public/booking/fields.gohtml:174
|
||||||
#: web/templates/admin/taxDetails.gohtml:101
|
#: web/templates/admin/taxDetails.gohtml:101
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Country"
|
msgid "Country"
|
||||||
msgstr "País"
|
msgstr "País"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:198
|
#: web/templates/public/booking/fields.gohtml:177
|
||||||
msgid "Choose a country"
|
msgid "Choose a country"
|
||||||
msgstr "Esculli un país"
|
msgstr "Esculli un país"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:206
|
#: web/templates/public/booking/fields.gohtml:185
|
||||||
#: web/templates/admin/login.gohtml:27 web/templates/admin/profile.gohtml:38
|
#: web/templates/admin/login.gohtml:27 web/templates/admin/profile.gohtml:38
|
||||||
#: web/templates/admin/taxDetails.gohtml:53
|
#: web/templates/admin/taxDetails.gohtml:53
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr "Correu-e"
|
msgstr "Correu-e"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:215
|
#: web/templates/public/booking/fields.gohtml:194
|
||||||
#: web/templates/admin/taxDetails.gohtml:45
|
#: web/templates/admin/taxDetails.gohtml:45
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Phone"
|
msgid "Phone"
|
||||||
msgstr "Telèfon"
|
msgstr "Telèfon"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:226
|
#: web/templates/public/booking/fields.gohtml:205
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "ACSI card? (optional)"
|
msgid "ACSI card? (optional)"
|
||||||
msgstr "Targeta ACSI? (opcional)"
|
msgstr "Targeta ACSI? (opcional)"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:233
|
#: web/templates/public/booking/fields.gohtml:212
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "I have read and I accept %[1]sthe reservation conditions%[2]s"
|
msgid "I have read and I accept %[1]sthe reservation conditions%[2]s"
|
||||||
msgstr "He llegit i accepto %[1]sles condicions de reserves%[2]s"
|
msgstr "He llegit i accepto %[1]sles condicions de reserves%[2]s"
|
||||||
|
|
||||||
#: web/templates/public/booking/cart.gohtml:14
|
#: web/templates/public/booking/fields.gohtml:229
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Total"
|
msgid "Total"
|
||||||
msgstr "Total"
|
msgstr "Total"
|
||||||
|
@ -1973,12 +1968,12 @@ msgid "Slide image must be an image media type."
|
||||||
msgstr "La imatge de la diapositiva ha de ser un mèdia de tipus imatge."
|
msgstr "La imatge de la diapositiva ha de ser un mèdia de tipus imatge."
|
||||||
|
|
||||||
#: pkg/app/login.go:56 pkg/app/user.go:246 pkg/company/admin.go:217
|
#: pkg/app/login.go:56 pkg/app/user.go:246 pkg/company/admin.go:217
|
||||||
#: pkg/booking/public.go:351
|
#: pkg/booking/public.go:571
|
||||||
msgid "Email can not be empty."
|
msgid "Email can not be empty."
|
||||||
msgstr "No podeu deixar el correu-e en blanc."
|
msgstr "No podeu deixar el correu-e en blanc."
|
||||||
|
|
||||||
#: pkg/app/login.go:57 pkg/app/user.go:247 pkg/company/admin.go:218
|
#: pkg/app/login.go:57 pkg/app/user.go:247 pkg/company/admin.go:218
|
||||||
#: pkg/booking/public.go:352
|
#: pkg/booking/public.go:572
|
||||||
msgid "This email is not valid. It should be like name@domain.com."
|
msgid "This email is not valid. It should be like name@domain.com."
|
||||||
msgstr "Aquest correu-e no és vàlid. Hauria de ser similar a nom@domini.com."
|
msgstr "Aquest correu-e no és vàlid. Hauria de ser similar a nom@domini.com."
|
||||||
|
|
||||||
|
@ -2150,22 +2145,23 @@ msgstr "El preu per nen ha de ser un número decimal."
|
||||||
msgid "Price per child must be zero or greater."
|
msgid "Price per child must be zero or greater."
|
||||||
msgstr "El preu per nen ha de ser com a mínim zero."
|
msgstr "El preu per nen ha de ser com a mínim zero."
|
||||||
|
|
||||||
#: pkg/campsite/types/public.go:229
|
#: pkg/campsite/types/public.go:244
|
||||||
msgctxt "header"
|
msgctxt "header"
|
||||||
msgid "Adults"
|
msgid "Adults"
|
||||||
msgstr "Adults"
|
msgstr "Adults"
|
||||||
|
|
||||||
#: pkg/campsite/types/public.go:235
|
#: pkg/campsite/types/public.go:250
|
||||||
msgctxt "header"
|
msgctxt "header"
|
||||||
msgid "Teenagers (aged 11 to 16)"
|
msgid "Teenagers (aged 11 to 16)"
|
||||||
msgstr "Adolescents (entre 11 i 16 anys)"
|
msgstr "Adolescents (entre 11 i 16 anys)"
|
||||||
|
|
||||||
#: pkg/campsite/types/public.go:241
|
#: pkg/campsite/types/public.go:256
|
||||||
msgctxt "header"
|
msgctxt "header"
|
||||||
msgid "Children (aged 2 to 10)"
|
msgid "Children (aged 2 to 10)"
|
||||||
msgstr "Mainada (entre 2 i 10 anys)"
|
msgstr "Mainada (entre 2 i 10 anys)"
|
||||||
|
|
||||||
#: pkg/campsite/admin.go:275 pkg/booking/public.go:360
|
#: pkg/campsite/admin.go:275 pkg/booking/public.go:217
|
||||||
|
#: pkg/booking/public.go:269
|
||||||
msgid "Selected campsite type is not valid."
|
msgid "Selected campsite type is not valid."
|
||||||
msgstr "El tipus d’allotjament escollit no és vàlid."
|
msgstr "El tipus d’allotjament escollit no és vàlid."
|
||||||
|
|
||||||
|
@ -2321,7 +2317,7 @@ msgstr "No podeu deixar l’adreça de l’enllaç en blanc."
|
||||||
msgid "This web address is not valid. It should be like https://domain.com/."
|
msgid "This web address is not valid. It should be like https://domain.com/."
|
||||||
msgstr "Aquesta adreça web no és vàlida. Hauria de ser similar a https://domini.com/."
|
msgstr "Aquesta adreça web no és vàlida. Hauria de ser similar a https://domini.com/."
|
||||||
|
|
||||||
#: pkg/company/admin.go:200 pkg/booking/public.go:338
|
#: pkg/company/admin.go:200 pkg/booking/public.go:558
|
||||||
msgid "Selected country is not valid."
|
msgid "Selected country is not valid."
|
||||||
msgstr "El país escollit no és vàlid."
|
msgstr "El país escollit no és vàlid."
|
||||||
|
|
||||||
|
@ -2341,11 +2337,11 @@ msgstr "No podeu deixar el NIF en blanc."
|
||||||
msgid "This VAT number is not valid."
|
msgid "This VAT number is not valid."
|
||||||
msgstr "Aquest NIF no és vàlid."
|
msgstr "Aquest NIF no és vàlid."
|
||||||
|
|
||||||
#: pkg/company/admin.go:212 pkg/booking/public.go:354
|
#: pkg/company/admin.go:212 pkg/booking/public.go:574
|
||||||
msgid "Phone can not be empty."
|
msgid "Phone can not be empty."
|
||||||
msgstr "No podeu deixar el telèfon en blanc."
|
msgstr "No podeu deixar el telèfon en blanc."
|
||||||
|
|
||||||
#: pkg/company/admin.go:213 pkg/booking/public.go:355
|
#: pkg/company/admin.go:213 pkg/booking/public.go:575
|
||||||
msgid "This phone number is not valid."
|
msgid "This phone number is not valid."
|
||||||
msgstr "Aquest número de telèfon no és vàlid."
|
msgstr "Aquest número de telèfon no és vàlid."
|
||||||
|
|
||||||
|
@ -2365,7 +2361,7 @@ msgstr "No podeu deixar la província en blanc."
|
||||||
msgid "Postal code can not be empty."
|
msgid "Postal code can not be empty."
|
||||||
msgstr "No podeu deixar el codi postal en blanc."
|
msgstr "No podeu deixar el codi postal en blanc."
|
||||||
|
|
||||||
#: pkg/company/admin.go:227 pkg/booking/public.go:347
|
#: pkg/company/admin.go:227 pkg/booking/public.go:567
|
||||||
msgid "This postal code is not valid."
|
msgid "This postal code is not valid."
|
||||||
msgstr "Aquest codi postal no és vàlid."
|
msgstr "Aquest codi postal no és vàlid."
|
||||||
|
|
||||||
|
@ -2405,27 +2401,27 @@ msgstr "No podeu deixar el fitxer del mèdia en blanc."
|
||||||
msgid "Filename can not be empty."
|
msgid "Filename can not be empty."
|
||||||
msgstr "No podeu deixar el nom del fitxer en blanc."
|
msgstr "No podeu deixar el nom del fitxer en blanc."
|
||||||
|
|
||||||
#: pkg/booking/cart.go:171
|
#: pkg/booking/cart.go:142
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Night"
|
msgid "Night"
|
||||||
msgstr "Nit"
|
msgstr "Nit"
|
||||||
|
|
||||||
#: pkg/booking/cart.go:172
|
#: pkg/booking/cart.go:143
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Adult"
|
msgid "Adult"
|
||||||
msgstr "Adult"
|
msgstr "Adult"
|
||||||
|
|
||||||
#: pkg/booking/cart.go:173
|
#: pkg/booking/cart.go:144
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Teenager"
|
msgid "Teenager"
|
||||||
msgstr "Adolescent"
|
msgstr "Adolescent"
|
||||||
|
|
||||||
#: pkg/booking/cart.go:174
|
#: pkg/booking/cart.go:145
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Child"
|
msgid "Child"
|
||||||
msgstr "Nen"
|
msgstr "Nen"
|
||||||
|
|
||||||
#: pkg/booking/cart.go:193
|
#: pkg/booking/cart.go:164
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Tourist tax"
|
msgid "Tourist tax"
|
||||||
msgstr "Impost turístic"
|
msgstr "Impost turístic"
|
||||||
|
@ -2487,106 +2483,138 @@ msgstr "La integració escollida no és vàlida."
|
||||||
msgid "The merchant key is not valid."
|
msgid "The merchant key is not valid."
|
||||||
msgstr "Aquesta clau del comerç no és vàlid."
|
msgstr "Aquesta clau del comerç no és vàlid."
|
||||||
|
|
||||||
#: pkg/booking/public.go:342
|
#: pkg/booking/public.go:318 pkg/booking/public.go:347
|
||||||
msgid "Full name can not be empty."
|
|
||||||
msgstr "No podeu deixar el nom i els cognoms en blanc."
|
|
||||||
|
|
||||||
#: pkg/booking/public.go:343
|
|
||||||
msgid "Full name must have at least one letter."
|
|
||||||
msgstr "El nom i els cognoms han de tenir com a mínim una lletra."
|
|
||||||
|
|
||||||
#: pkg/booking/public.go:361
|
|
||||||
msgid "Arrival date can not be empty"
|
|
||||||
msgstr "No podeu deixar la data d’arribada en blanc."
|
|
||||||
|
|
||||||
#: pkg/booking/public.go:362
|
|
||||||
msgid "Arrival date must be a valid date."
|
msgid "Arrival date must be a valid date."
|
||||||
msgstr "La data d’arribada ha de ser una data vàlida."
|
msgstr "La data d’arribada ha de ser una data vàlida."
|
||||||
|
|
||||||
#: pkg/booking/public.go:366
|
#: pkg/booking/public.go:332 pkg/booking/public.go:354
|
||||||
msgid "Departure date can not be empty"
|
|
||||||
msgstr "No podeu deixar la data de sortida en blanc."
|
|
||||||
|
|
||||||
#: pkg/booking/public.go:367
|
|
||||||
msgid "Departure date must be a valid date."
|
msgid "Departure date must be a valid date."
|
||||||
msgstr "La data de sortida ha de ser una data vàlida."
|
msgstr "La data de sortida ha de ser una data vàlida."
|
||||||
|
|
||||||
#: pkg/booking/public.go:368
|
#: pkg/booking/public.go:346
|
||||||
msgid "The departure date must be after the arrival date."
|
msgid "Arrival date can not be empty"
|
||||||
msgstr "La data de sortida ha de ser posterior a la d’arribada."
|
msgstr "No podeu deixar la data d’arribada en blanc."
|
||||||
|
|
||||||
#: pkg/booking/public.go:372
|
#: pkg/booking/public.go:348
|
||||||
|
#, c-format
|
||||||
|
msgid "Arrival date must be %s or after."
|
||||||
|
msgstr "La data d’arribada ha de ser igual o posterior a %s."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:349
|
||||||
|
#, c-format
|
||||||
|
msgid "Arrival date must be %s or before."
|
||||||
|
msgstr "La data d’arribada ha de ser anterior o igual a %s."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:353
|
||||||
|
msgid "Departure date can not be empty"
|
||||||
|
msgstr "No podeu deixar la data de sortida en blanc."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:355
|
||||||
|
#, c-format
|
||||||
|
msgid "Departure date must be %s or after."
|
||||||
|
msgstr "La data de sortida ha de ser igual o posterior a %s."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:356
|
||||||
|
#, c-format
|
||||||
|
msgid "Departure date must be %s or before."
|
||||||
|
msgstr "La data de sortida ha de ser anterior o igual a %s."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:394
|
||||||
|
#, c-format
|
||||||
|
msgid "There can be at most %d guests in this accommodation."
|
||||||
|
msgstr "Hi poden haver com a màxim %d convidats a aquest allotjament."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:413
|
||||||
msgid "Number of adults can not be empty"
|
msgid "Number of adults can not be empty"
|
||||||
msgstr "No podeu deixar el número d’adults en blanc."
|
msgstr "No podeu deixar el número d’adults en blanc."
|
||||||
|
|
||||||
#: pkg/booking/public.go:373
|
#: pkg/booking/public.go:414
|
||||||
msgid "Number of adults must be an integer."
|
msgid "Number of adults must be an integer."
|
||||||
msgstr "El número d’adults ha de ser enter."
|
msgstr "El número d’adults ha de ser enter."
|
||||||
|
|
||||||
#: pkg/booking/public.go:374
|
#: pkg/booking/public.go:415
|
||||||
msgid "There must be at least one adult."
|
msgid "There must be at least one adult."
|
||||||
msgstr "Hi ha d’haver com a mínim un adult."
|
msgstr "Hi ha d’haver com a mínim un adult."
|
||||||
|
|
||||||
#: pkg/booking/public.go:377
|
#: pkg/booking/public.go:418
|
||||||
msgid "Number of teenagers can not be empty"
|
msgid "Number of teenagers can not be empty"
|
||||||
msgstr "No podeu deixar el número d’adolescents en blanc."
|
msgstr "No podeu deixar el número d’adolescents en blanc."
|
||||||
|
|
||||||
#: pkg/booking/public.go:378
|
#: pkg/booking/public.go:419
|
||||||
msgid "Number of teenagers must be an integer."
|
msgid "Number of teenagers must be an integer."
|
||||||
msgstr "El número d’adolescents ha de ser enter."
|
msgstr "El número d’adolescents ha de ser enter."
|
||||||
|
|
||||||
#: pkg/booking/public.go:379
|
#: pkg/booking/public.go:420
|
||||||
msgid "Number of teenagers can not be negative."
|
msgid "Number of teenagers can not be negative."
|
||||||
msgstr "El número d’adolescents no pot ser negatiu."
|
msgstr "El número d’adolescents no pot ser negatiu."
|
||||||
|
|
||||||
#: pkg/booking/public.go:382
|
#: pkg/booking/public.go:423
|
||||||
msgid "Number of children can not be empty"
|
msgid "Number of children can not be empty"
|
||||||
msgstr "No podeu deixar el número de nens en blanc."
|
msgstr "No podeu deixar el número de nens en blanc."
|
||||||
|
|
||||||
#: pkg/booking/public.go:383
|
#: pkg/booking/public.go:424
|
||||||
msgid "Number of children must be an integer."
|
msgid "Number of children must be an integer."
|
||||||
msgstr "El número de nens ha de ser enter."
|
msgstr "El número de nens ha de ser enter."
|
||||||
|
|
||||||
#: pkg/booking/public.go:384
|
#: pkg/booking/public.go:425
|
||||||
msgid "Number of children can not be negative."
|
msgid "Number of children can not be negative."
|
||||||
msgstr "El número de nens no pot ser negatiu."
|
msgstr "El número de nens no pot ser negatiu."
|
||||||
|
|
||||||
#: pkg/booking/public.go:387
|
#: pkg/booking/public.go:428
|
||||||
msgid "Number of dogs can not be empty"
|
msgid "Number of dogs can not be empty"
|
||||||
msgstr "No podeu deixar el número de gossos en blanc."
|
msgstr "No podeu deixar el número de gossos en blanc."
|
||||||
|
|
||||||
#: pkg/booking/public.go:388
|
#: pkg/booking/public.go:429
|
||||||
msgid "Number of dogs must be an integer."
|
msgid "Number of dogs must be an integer."
|
||||||
msgstr "El número de gossos ha de ser enter."
|
msgstr "El número de gossos ha de ser enter."
|
||||||
|
|
||||||
#: pkg/booking/public.go:389
|
#: pkg/booking/public.go:430
|
||||||
msgid "Number of dogs can not be negative."
|
msgid "Number of dogs can not be negative."
|
||||||
msgstr "El número de gossos no pot ser negatiu."
|
msgstr "El número de gossos no pot ser negatiu."
|
||||||
|
|
||||||
#: pkg/booking/public.go:392
|
#: pkg/booking/public.go:501
|
||||||
msgid "It is mandatory to agree to the reservation conditions."
|
|
||||||
msgstr "És obligatori acceptar les condicions de reserves."
|
|
||||||
|
|
||||||
#: pkg/booking/public.go:395
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s can not be empty"
|
msgid "%s can not be empty"
|
||||||
msgstr "No podeu deixar %s en blanc."
|
msgstr "No podeu deixar %s en blanc."
|
||||||
|
|
||||||
#: pkg/booking/public.go:396
|
#: pkg/booking/public.go:502
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s must be an integer."
|
msgid "%s must be an integer."
|
||||||
msgstr "%s ha de ser un número enter."
|
msgstr "%s ha de ser un número enter."
|
||||||
|
|
||||||
#: pkg/booking/public.go:397
|
#: pkg/booking/public.go:503
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s must be %d or greater."
|
msgid "%s must be %d or greater."
|
||||||
msgstr "El valor de %s ha de ser com a mínim %d."
|
msgstr "El valor de %s ha de ser com a mínim %d."
|
||||||
|
|
||||||
#: pkg/booking/public.go:398
|
#: pkg/booking/public.go:504
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s must be at most %d."
|
msgid "%s must be at most %d."
|
||||||
msgstr "El valor de %s ha de ser com a màxim %d."
|
msgstr "El valor de %s ha de ser com a màxim %d."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:562
|
||||||
|
msgid "Full name can not be empty."
|
||||||
|
msgstr "No podeu deixar el nom i els cognoms en blanc."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:563
|
||||||
|
msgid "Full name must have at least one letter."
|
||||||
|
msgstr "El nom i els cognoms han de tenir com a mínim una lletra."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:580
|
||||||
|
msgid "It is mandatory to agree to the reservation conditions."
|
||||||
|
msgstr "És obligatori acceptar les condicions de reserves."
|
||||||
|
|
||||||
|
#~ msgctxt "input"
|
||||||
|
#~ msgid "Check-in Date"
|
||||||
|
#~ msgstr "Data d’entrada"
|
||||||
|
|
||||||
|
#~ msgctxt "input"
|
||||||
|
#~ msgid "Check-out Date"
|
||||||
|
#~ msgstr "Data de sortida"
|
||||||
|
|
||||||
|
#~ msgid "The departure date must be after the arrival date."
|
||||||
|
#~ msgstr "La data de sortida ha de ser posterior a la d’arribada."
|
||||||
|
|
||||||
#~ msgid "Campsite Montagut is an ideal starting point for quiet outings, climbing, swimming in the river and gorges, volcanoes, the Fageda d’en Jordà, cycle tours for all ages…."
|
#~ msgid "Campsite Montagut is an ideal starting point for quiet outings, climbing, swimming in the river and gorges, volcanoes, the Fageda d’en Jordà, cycle tours for all ages…."
|
||||||
#~ msgstr "El Càmping Montagut és ideal com a punt de partida d’excursions tranquil·les, escalada, banyar-se en el riu i gorgues, volcans, la Fageda d’en Jordà, sortides amb bicicleta per a tots els nivells…."
|
#~ msgstr "El Càmping Montagut és ideal com a punt de partida d’excursions tranquil·les, escalada, banyar-se en el riu i gorgues, volcans, la Fageda d’en Jordà, sortides amb bicicleta per a tots els nivells…."
|
||||||
|
|
||||||
|
|
263
po/es.po
263
po/es.po
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: camper\n"
|
"Project-Id-Version: camper\n"
|
||||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||||
"POT-Creation-Date: 2024-02-04 06:23+0100\n"
|
"POT-Creation-Date: 2024-02-10 03:31+0100\n"
|
||||||
"PO-Revision-Date: 2024-02-06 10:04+0100\n"
|
"PO-Revision-Date: 2024-02-06 10:04+0100\n"
|
||||||
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
"Last-Translator: jordi fita mas <jordi@tandem.blog>\n"
|
||||||
"Language-Team: Spanish <es@tp.org.es>\n"
|
"Language-Team: Spanish <es@tp.org.es>\n"
|
||||||
|
@ -95,7 +95,7 @@ msgid "The campsite offers many different services."
|
||||||
msgstr "El camping dispone de varios servicios."
|
msgstr "El camping dispone de varios servicios."
|
||||||
|
|
||||||
#: web/templates/public/amenity.gohtml:39
|
#: web/templates/public/amenity.gohtml:39
|
||||||
#: web/templates/public/campsite/type.gohtml:113
|
#: web/templates/public/campsite/type.gohtml:106
|
||||||
#: web/templates/public/campsite/page.gohtml:39
|
#: web/templates/public/campsite/page.gohtml:39
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Features"
|
msgid "Features"
|
||||||
|
@ -154,89 +154,79 @@ msgstr "A menos de una hora de <strong>Girona</strong>, a una de <strong>La Bisb
|
||||||
msgid "Discover"
|
msgid "Discover"
|
||||||
msgstr "Descubre"
|
msgstr "Descubre"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:41
|
#: web/templates/public/campsite/type.gohtml:49
|
||||||
msgctxt "input"
|
#: web/templates/public/booking/fields.gohtml:240
|
||||||
msgid "Check-in Date"
|
|
||||||
msgstr "Fecha de entrada"
|
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:47
|
|
||||||
msgctxt "input"
|
|
||||||
msgid "Check-out Date"
|
|
||||||
msgstr "Fecha de salida"
|
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:56
|
|
||||||
#: web/templates/public/booking/cart.gohtml:25
|
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Book"
|
msgid "Book"
|
||||||
msgstr "Reservar"
|
msgstr "Reservar"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:64
|
#: web/templates/public/campsite/type.gohtml:57
|
||||||
#: web/templates/admin/season/index.gohtml:54
|
#: web/templates/admin/season/index.gohtml:54
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Calendar"
|
msgid "Calendar"
|
||||||
msgstr "Calendario"
|
msgstr "Calendario"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:75
|
#: web/templates/public/campsite/type.gohtml:68
|
||||||
#: web/templates/admin/campsite/type/form.gohtml:143
|
#: web/templates/admin/campsite/type/form.gohtml:143
|
||||||
#: web/templates/admin/campsite/type/option/form.gohtml:70
|
#: web/templates/admin/campsite/type/option/form.gohtml:70
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Prices"
|
msgid "Prices"
|
||||||
msgstr "Precios"
|
msgstr "Precios"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:88
|
#: web/templates/public/campsite/type.gohtml:81
|
||||||
msgid "%s: %s/night"
|
msgid "%s: %s/night"
|
||||||
msgstr "%s: %s/noche"
|
msgstr "%s: %s/noche"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:90
|
#: web/templates/public/campsite/type.gohtml:83
|
||||||
msgid "%s/night"
|
msgid "%s/night"
|
||||||
msgstr "%s/noche"
|
msgstr "%s/noche"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:95
|
#: web/templates/public/campsite/type.gohtml:88
|
||||||
msgid "*Minimum %d nights per stay"
|
msgid "*Minimum %d nights per stay"
|
||||||
msgstr "*Mínimo %d noches por estancia"
|
msgstr "*Mínimo %d noches por estancia"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:100
|
#: web/templates/public/campsite/type.gohtml:93
|
||||||
msgid "10 % VAT included."
|
msgid "10 % VAT included."
|
||||||
msgstr "IVA del 10 % incluido."
|
msgstr "IVA del 10 % incluido."
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:101
|
#: web/templates/public/campsite/type.gohtml:94
|
||||||
msgid "Tourist tax: %s/night per person aged 17 or older."
|
msgid "Tourist tax: %s/night per person aged 17 or older."
|
||||||
msgstr "Impuesto turístico: %s/noche por persona mayor de 16 años."
|
msgstr "Impuesto turístico: %s/noche por persona mayor de 16 años."
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:103
|
#: web/templates/public/campsite/type.gohtml:96
|
||||||
msgid "Dogs: %s/night, tied, accompanied, and minimal barking."
|
msgid "Dogs: %s/night, tied, accompanied, and minimal barking."
|
||||||
msgstr "Perros: %s/noche, atados, acompañados y con mínimo de ladrido."
|
msgstr "Perros: %s/noche, atados, acompañados y con mínimo de ladrido."
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:105
|
#: web/templates/public/campsite/type.gohtml:98
|
||||||
msgid "No dogs allowed."
|
msgid "No dogs allowed."
|
||||||
msgstr "No se permiten perros"
|
msgstr "No se permiten perros"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:124
|
#: web/templates/public/campsite/type.gohtml:117
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Info"
|
msgid "Info"
|
||||||
msgstr "Información"
|
msgstr "Información"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:128
|
#: web/templates/public/campsite/type.gohtml:121
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Facilities"
|
msgid "Facilities"
|
||||||
msgstr "Equipamiento"
|
msgstr "Equipamiento"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:132
|
#: web/templates/public/campsite/type.gohtml:125
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Descripción"
|
msgstr "Descripción"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:136
|
#: web/templates/public/campsite/type.gohtml:129
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Additional Information"
|
msgid "Additional Information"
|
||||||
msgstr "Información adicional"
|
msgstr "Información adicional"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:139
|
#: web/templates/public/campsite/type.gohtml:132
|
||||||
msgctxt "time"
|
msgctxt "time"
|
||||||
msgid "Check-in"
|
msgid "Check-in"
|
||||||
msgstr "Entrada"
|
msgstr "Entrada"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:143
|
#: web/templates/public/campsite/type.gohtml:136
|
||||||
msgctxt "time"
|
msgctxt "time"
|
||||||
msgid "Check-out"
|
msgid "Check-out"
|
||||||
msgstr "Salida"
|
msgstr "Salida"
|
||||||
|
@ -283,6 +273,18 @@ msgctxt "day"
|
||||||
msgid "Sun"
|
msgid "Sun"
|
||||||
msgstr "do"
|
msgstr "do"
|
||||||
|
|
||||||
|
#: web/templates/public/campsite/dates.gohtml:4
|
||||||
|
#: web/templates/public/booking/fields.gohtml:26
|
||||||
|
msgctxt "input"
|
||||||
|
msgid "Arrival date"
|
||||||
|
msgstr "Fecha de llegada"
|
||||||
|
|
||||||
|
#: web/templates/public/campsite/dates.gohtml:15
|
||||||
|
#: web/templates/public/booking/fields.gohtml:37
|
||||||
|
msgctxt "input"
|
||||||
|
msgid "Departure date"
|
||||||
|
msgstr "Fecha de salida"
|
||||||
|
|
||||||
#: web/templates/public/surroundings.gohtml:30
|
#: web/templates/public/surroundings.gohtml:30
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "What to Do Outside the Campsite?"
|
msgid "What to Do Outside the Campsite?"
|
||||||
|
@ -516,8 +518,7 @@ msgid "Campsites"
|
||||||
msgstr "Alojamientos"
|
msgstr "Alojamientos"
|
||||||
|
|
||||||
#: web/templates/public/layout.gohtml:70
|
#: web/templates/public/layout.gohtml:70
|
||||||
#: web/templates/public/booking/form.gohtml:7
|
#: web/templates/public/booking/page.gohtml:7
|
||||||
#: web/templates/public/booking/form.gohtml:16
|
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Booking"
|
msgid "Booking"
|
||||||
msgstr "Reserva"
|
msgstr "Reserva"
|
||||||
|
@ -536,119 +537,113 @@ msgstr "Apertura"
|
||||||
msgid "<abbr title=\"Catalonia Tourism Registry\">RTC</abbr> <abbr title=\"Number\">#</abbr>%s"
|
msgid "<abbr title=\"Catalonia Tourism Registry\">RTC</abbr> <abbr title=\"Number\">#</abbr>%s"
|
||||||
msgstr "<abbr title=\"Número\">Nº</abbr> <abbr title=\"Registro de Turismo de Cataluña\">RTC</abbr> %s"
|
msgstr "<abbr title=\"Número\">Nº</abbr> <abbr title=\"Registro de Turismo de Cataluña\">RTC</abbr> %s"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:29
|
#: web/templates/public/booking/fields.gohtml:13
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Accommodation"
|
msgid "Accommodation"
|
||||||
msgstr "Alojamientos"
|
msgstr "Alojamientos"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:43
|
#: web/templates/public/booking/fields.gohtml:23
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Booking Period"
|
msgid "Booking Period"
|
||||||
msgstr "Periodo de reserva"
|
msgstr "Periodo de reserva"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:46
|
#: web/templates/public/booking/fields.gohtml:50
|
||||||
msgctxt "input"
|
|
||||||
msgid "Arrival date"
|
|
||||||
msgstr "Fecha de llegada"
|
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:57
|
|
||||||
msgctxt "input"
|
|
||||||
msgid "Departure date"
|
|
||||||
msgstr "Fecha de salida"
|
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:72
|
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Guests"
|
msgid "Guests"
|
||||||
msgstr "Huéspedes"
|
msgstr "Huéspedes"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:76
|
#: web/templates/public/booking/fields.gohtml:54
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Adults aged 17 or older"
|
msgid "Adults aged 17 or older"
|
||||||
msgstr "Adultos de 17 años o más"
|
msgstr "Adultos de 17 años o más"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:86
|
#: web/templates/public/booking/fields.gohtml:65
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Teenagers from 11 to 16 years old"
|
msgid "Teenagers from 11 to 16 years old"
|
||||||
msgstr "Adolescentes de 11 a 16 años"
|
msgstr "Adolescentes de 11 a 16 años"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:96
|
#: web/templates/public/booking/fields.gohtml:76
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Children from 2 to 10 years old"
|
msgid "Children from 2 to 10 years old"
|
||||||
msgstr "Niños de 2 a 10 años"
|
msgstr "Niños de 2 a 10 años"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:106
|
#: web/templates/public/booking/fields.gohtml:91
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Dogs"
|
msgid "Dogs"
|
||||||
msgstr "Perros"
|
msgstr "Perros"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:127
|
#: web/templates/public/booking/fields.gohtml:100
|
||||||
|
msgid "Note: This accommodation does <strong>not</strong> allow dogs."
|
||||||
|
msgstr "Nota: En este alojamiento <strong>no</strong se permiten perros."
|
||||||
|
|
||||||
|
#: web/templates/public/booking/fields.gohtml:110
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Area preferences (optional)"
|
msgid "Area preferences (optional)"
|
||||||
msgstr "Preferencias de área (opcional)"
|
msgstr "Preferencias de área (opcional)"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:129
|
#: web/templates/public/booking/fields.gohtml:112
|
||||||
msgid "Campground map"
|
msgid "Campground map"
|
||||||
msgstr "Mapa del camping"
|
msgstr "Mapa del camping"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:156
|
#: web/templates/public/booking/fields.gohtml:135
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Customer Details"
|
msgid "Customer Details"
|
||||||
msgstr "Detalles del cliente"
|
msgstr "Detalles del cliente"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:159
|
#: web/templates/public/booking/fields.gohtml:138
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Full name"
|
msgid "Full name"
|
||||||
msgstr "Nombre y apellidos"
|
msgstr "Nombre y apellidos"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:168
|
#: web/templates/public/booking/fields.gohtml:147
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Address (optional)"
|
msgid "Address (optional)"
|
||||||
msgstr "Dirección (opcional)"
|
msgstr "Dirección (opcional)"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:177
|
#: web/templates/public/booking/fields.gohtml:156
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Postcode (optional)"
|
msgid "Postcode (optional)"
|
||||||
msgstr "Código postal (opcional)"
|
msgstr "Código postal (opcional)"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:186
|
#: web/templates/public/booking/fields.gohtml:165
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Town or village (optional)"
|
msgid "Town or village (optional)"
|
||||||
msgstr "Población (opcional)"
|
msgstr "Población (opcional)"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:195
|
#: web/templates/public/booking/fields.gohtml:174
|
||||||
#: web/templates/admin/taxDetails.gohtml:101
|
#: web/templates/admin/taxDetails.gohtml:101
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Country"
|
msgid "Country"
|
||||||
msgstr "País"
|
msgstr "País"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:198
|
#: web/templates/public/booking/fields.gohtml:177
|
||||||
msgid "Choose a country"
|
msgid "Choose a country"
|
||||||
msgstr "Escoja un país"
|
msgstr "Escoja un país"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:206
|
#: web/templates/public/booking/fields.gohtml:185
|
||||||
#: web/templates/admin/login.gohtml:27 web/templates/admin/profile.gohtml:38
|
#: web/templates/admin/login.gohtml:27 web/templates/admin/profile.gohtml:38
|
||||||
#: web/templates/admin/taxDetails.gohtml:53
|
#: web/templates/admin/taxDetails.gohtml:53
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr "Correo-e"
|
msgstr "Correo-e"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:215
|
#: web/templates/public/booking/fields.gohtml:194
|
||||||
#: web/templates/admin/taxDetails.gohtml:45
|
#: web/templates/admin/taxDetails.gohtml:45
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Phone"
|
msgid "Phone"
|
||||||
msgstr "Teléfono"
|
msgstr "Teléfono"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:226
|
#: web/templates/public/booking/fields.gohtml:205
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "ACSI card? (optional)"
|
msgid "ACSI card? (optional)"
|
||||||
msgstr "¿Tarjeta ACSI? (opcional)"
|
msgstr "¿Tarjeta ACSI? (opcional)"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:233
|
#: web/templates/public/booking/fields.gohtml:212
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "I have read and I accept %[1]sthe reservation conditions%[2]s"
|
msgid "I have read and I accept %[1]sthe reservation conditions%[2]s"
|
||||||
msgstr "He leído y acepto %[1]slas condiciones de reserva%[2]s"
|
msgstr "He leído y acepto %[1]slas condiciones de reserva%[2]s"
|
||||||
|
|
||||||
#: web/templates/public/booking/cart.gohtml:14
|
#: web/templates/public/booking/fields.gohtml:229
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Total"
|
msgid "Total"
|
||||||
msgstr "Total"
|
msgstr "Total"
|
||||||
|
@ -1973,12 +1968,12 @@ msgid "Slide image must be an image media type."
|
||||||
msgstr "La imagen de la diapositiva tiene que ser un medio de tipo imagen."
|
msgstr "La imagen de la diapositiva tiene que ser un medio de tipo imagen."
|
||||||
|
|
||||||
#: pkg/app/login.go:56 pkg/app/user.go:246 pkg/company/admin.go:217
|
#: pkg/app/login.go:56 pkg/app/user.go:246 pkg/company/admin.go:217
|
||||||
#: pkg/booking/public.go:351
|
#: pkg/booking/public.go:571
|
||||||
msgid "Email can not be empty."
|
msgid "Email can not be empty."
|
||||||
msgstr "No podéis dejar el correo-e en blanco."
|
msgstr "No podéis dejar el correo-e en blanco."
|
||||||
|
|
||||||
#: pkg/app/login.go:57 pkg/app/user.go:247 pkg/company/admin.go:218
|
#: pkg/app/login.go:57 pkg/app/user.go:247 pkg/company/admin.go:218
|
||||||
#: pkg/booking/public.go:352
|
#: pkg/booking/public.go:572
|
||||||
msgid "This email is not valid. It should be like name@domain.com."
|
msgid "This email is not valid. It should be like name@domain.com."
|
||||||
msgstr "Este correo-e no es válido. Tiene que ser parecido a nombre@dominio.com."
|
msgstr "Este correo-e no es válido. Tiene que ser parecido a nombre@dominio.com."
|
||||||
|
|
||||||
|
@ -2150,22 +2145,23 @@ msgstr "El precio por niño tiene que ser un número decimal."
|
||||||
msgid "Price per child must be zero or greater."
|
msgid "Price per child must be zero or greater."
|
||||||
msgstr "El precio por niño tiene que ser como mínimo cero."
|
msgstr "El precio por niño tiene que ser como mínimo cero."
|
||||||
|
|
||||||
#: pkg/campsite/types/public.go:229
|
#: pkg/campsite/types/public.go:244
|
||||||
msgctxt "header"
|
msgctxt "header"
|
||||||
msgid "Adults"
|
msgid "Adults"
|
||||||
msgstr "Adultos"
|
msgstr "Adultos"
|
||||||
|
|
||||||
#: pkg/campsite/types/public.go:235
|
#: pkg/campsite/types/public.go:250
|
||||||
msgctxt "header"
|
msgctxt "header"
|
||||||
msgid "Teenagers (aged 11 to 16)"
|
msgid "Teenagers (aged 11 to 16)"
|
||||||
msgstr "Adolescentes (de 11 a 16 años)"
|
msgstr "Adolescentes (de 11 a 16 años)"
|
||||||
|
|
||||||
#: pkg/campsite/types/public.go:241
|
#: pkg/campsite/types/public.go:256
|
||||||
msgctxt "header"
|
msgctxt "header"
|
||||||
msgid "Children (aged 2 to 10)"
|
msgid "Children (aged 2 to 10)"
|
||||||
msgstr "Niños (de 2 a 10 años)"
|
msgstr "Niños (de 2 a 10 años)"
|
||||||
|
|
||||||
#: pkg/campsite/admin.go:275 pkg/booking/public.go:360
|
#: pkg/campsite/admin.go:275 pkg/booking/public.go:217
|
||||||
|
#: pkg/booking/public.go:269
|
||||||
msgid "Selected campsite type is not valid."
|
msgid "Selected campsite type is not valid."
|
||||||
msgstr "El tipo de alojamiento escogido no es válido."
|
msgstr "El tipo de alojamiento escogido no es válido."
|
||||||
|
|
||||||
|
@ -2321,7 +2317,7 @@ msgstr "No podéis dejar la dirección del enlace en blanco."
|
||||||
msgid "This web address is not valid. It should be like https://domain.com/."
|
msgid "This web address is not valid. It should be like https://domain.com/."
|
||||||
msgstr "Esta dirección web no es válida. Tiene que ser parecido a https://dominio.com/."
|
msgstr "Esta dirección web no es válida. Tiene que ser parecido a https://dominio.com/."
|
||||||
|
|
||||||
#: pkg/company/admin.go:200 pkg/booking/public.go:338
|
#: pkg/company/admin.go:200 pkg/booking/public.go:558
|
||||||
msgid "Selected country is not valid."
|
msgid "Selected country is not valid."
|
||||||
msgstr "El país escogido no es válido."
|
msgstr "El país escogido no es válido."
|
||||||
|
|
||||||
|
@ -2341,11 +2337,11 @@ msgstr "No podéis dejar el NIF en blanco."
|
||||||
msgid "This VAT number is not valid."
|
msgid "This VAT number is not valid."
|
||||||
msgstr "Este NIF no es válido."
|
msgstr "Este NIF no es válido."
|
||||||
|
|
||||||
#: pkg/company/admin.go:212 pkg/booking/public.go:354
|
#: pkg/company/admin.go:212 pkg/booking/public.go:574
|
||||||
msgid "Phone can not be empty."
|
msgid "Phone can not be empty."
|
||||||
msgstr "No podéis dejar el teléfono en blanco."
|
msgstr "No podéis dejar el teléfono en blanco."
|
||||||
|
|
||||||
#: pkg/company/admin.go:213 pkg/booking/public.go:355
|
#: pkg/company/admin.go:213 pkg/booking/public.go:575
|
||||||
msgid "This phone number is not valid."
|
msgid "This phone number is not valid."
|
||||||
msgstr "Este teléfono no es válido."
|
msgstr "Este teléfono no es válido."
|
||||||
|
|
||||||
|
@ -2365,7 +2361,7 @@ msgstr "No podéis dejar la provincia en blanco."
|
||||||
msgid "Postal code can not be empty."
|
msgid "Postal code can not be empty."
|
||||||
msgstr "No podéis dejar el código postal en blanco."
|
msgstr "No podéis dejar el código postal en blanco."
|
||||||
|
|
||||||
#: pkg/company/admin.go:227 pkg/booking/public.go:347
|
#: pkg/company/admin.go:227 pkg/booking/public.go:567
|
||||||
msgid "This postal code is not valid."
|
msgid "This postal code is not valid."
|
||||||
msgstr "Este código postal no es válido."
|
msgstr "Este código postal no es válido."
|
||||||
|
|
||||||
|
@ -2405,27 +2401,27 @@ msgstr "No podéis dejar el archivo del medio en blanco."
|
||||||
msgid "Filename can not be empty."
|
msgid "Filename can not be empty."
|
||||||
msgstr "No podéis dejar el nombre del archivo en blanco."
|
msgstr "No podéis dejar el nombre del archivo en blanco."
|
||||||
|
|
||||||
#: pkg/booking/cart.go:171
|
#: pkg/booking/cart.go:142
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Night"
|
msgid "Night"
|
||||||
msgstr "Noche"
|
msgstr "Noche"
|
||||||
|
|
||||||
#: pkg/booking/cart.go:172
|
#: pkg/booking/cart.go:143
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Adult"
|
msgid "Adult"
|
||||||
msgstr "Adulto"
|
msgstr "Adulto"
|
||||||
|
|
||||||
#: pkg/booking/cart.go:173
|
#: pkg/booking/cart.go:144
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Teenager"
|
msgid "Teenager"
|
||||||
msgstr "Adolescente"
|
msgstr "Adolescente"
|
||||||
|
|
||||||
#: pkg/booking/cart.go:174
|
#: pkg/booking/cart.go:145
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Child"
|
msgid "Child"
|
||||||
msgstr "Niño"
|
msgstr "Niño"
|
||||||
|
|
||||||
#: pkg/booking/cart.go:193
|
#: pkg/booking/cart.go:164
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Tourist tax"
|
msgid "Tourist tax"
|
||||||
msgstr "Impuesto turístico"
|
msgstr "Impuesto turístico"
|
||||||
|
@ -2487,106 +2483,137 @@ msgstr "La integración escogida no es válida."
|
||||||
msgid "The merchant key is not valid."
|
msgid "The merchant key is not valid."
|
||||||
msgstr "Esta clave del comercio no es válida."
|
msgstr "Esta clave del comercio no es válida."
|
||||||
|
|
||||||
#: pkg/booking/public.go:342
|
#: pkg/booking/public.go:318 pkg/booking/public.go:347
|
||||||
msgid "Full name can not be empty."
|
|
||||||
msgstr "No podéis dejar el nombre y los apellidos en blanco."
|
|
||||||
|
|
||||||
#: pkg/booking/public.go:343
|
|
||||||
msgid "Full name must have at least one letter."
|
|
||||||
msgstr "El nombre y los apellidos tienen que tener como mínimo una letra."
|
|
||||||
|
|
||||||
#: pkg/booking/public.go:361
|
|
||||||
msgid "Arrival date can not be empty"
|
|
||||||
msgstr "No podéis dejar la fecha de llegada en blanco."
|
|
||||||
|
|
||||||
#: pkg/booking/public.go:362
|
|
||||||
msgid "Arrival date must be a valid date."
|
msgid "Arrival date must be a valid date."
|
||||||
msgstr "La fecha de llegada tiene que ser una fecha válida."
|
msgstr "La fecha de llegada tiene que ser una fecha válida."
|
||||||
|
|
||||||
#: pkg/booking/public.go:366
|
#: pkg/booking/public.go:332 pkg/booking/public.go:354
|
||||||
msgid "Departure date can not be empty"
|
|
||||||
msgstr "No podéis dejar la fecha de partida en blanco."
|
|
||||||
|
|
||||||
#: pkg/booking/public.go:367
|
|
||||||
msgid "Departure date must be a valid date."
|
msgid "Departure date must be a valid date."
|
||||||
msgstr "La fecha de partida tiene que ser una fecha válida."
|
msgstr "La fecha de partida tiene que ser una fecha válida."
|
||||||
|
|
||||||
#: pkg/booking/public.go:368
|
#: pkg/booking/public.go:346
|
||||||
msgid "The departure date must be after the arrival date."
|
msgid "Arrival date can not be empty"
|
||||||
msgstr "La fecha de partida tiene que ser posterior a la de llegada."
|
msgstr "No podéis dejar la fecha de llegada en blanco."
|
||||||
|
|
||||||
#: pkg/booking/public.go:372
|
#: pkg/booking/public.go:348
|
||||||
|
msgid "Arrival date must be %s or after."
|
||||||
|
msgstr "La fecha de llegada tiene que ser igual o posterior a %s."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:349
|
||||||
|
#, c-format
|
||||||
|
msgid "Arrival date must be %s or before."
|
||||||
|
msgstr "La fecha de llegada tiene que ser anterior o igual a %s."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:353
|
||||||
|
msgid "Departure date can not be empty"
|
||||||
|
msgstr "No podéis dejar la fecha de partida en blanco."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:355
|
||||||
|
#, c-format
|
||||||
|
msgid "Departure date must be %s or after."
|
||||||
|
msgstr "La fecha de partida tiene que igual o posterior a %s."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:356
|
||||||
|
#, c-format
|
||||||
|
msgid "Departure date must be %s or before."
|
||||||
|
msgstr "La fecha de partida tiene que ser anterior o igual a %s."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:394
|
||||||
|
#, c-format
|
||||||
|
msgid "There can be at most %d guests in this accommodation."
|
||||||
|
msgstr "Solo puede haber como máximo %d invitados en este alojamiento."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:413
|
||||||
msgid "Number of adults can not be empty"
|
msgid "Number of adults can not be empty"
|
||||||
msgstr "No podéis dejar el número de adultos blanco."
|
msgstr "No podéis dejar el número de adultos blanco."
|
||||||
|
|
||||||
#: pkg/booking/public.go:373
|
#: pkg/booking/public.go:414
|
||||||
msgid "Number of adults must be an integer."
|
msgid "Number of adults must be an integer."
|
||||||
msgstr "El número de adultos tiene que ser entero."
|
msgstr "El número de adultos tiene que ser entero."
|
||||||
|
|
||||||
#: pkg/booking/public.go:374
|
#: pkg/booking/public.go:415
|
||||||
msgid "There must be at least one adult."
|
msgid "There must be at least one adult."
|
||||||
msgstr "Tiene que haber como mínimo un adulto."
|
msgstr "Tiene que haber como mínimo un adulto."
|
||||||
|
|
||||||
#: pkg/booking/public.go:377
|
#: pkg/booking/public.go:418
|
||||||
msgid "Number of teenagers can not be empty"
|
msgid "Number of teenagers can not be empty"
|
||||||
msgstr "No podéis dejar el número de adolescentes en blanco."
|
msgstr "No podéis dejar el número de adolescentes en blanco."
|
||||||
|
|
||||||
#: pkg/booking/public.go:378
|
#: pkg/booking/public.go:419
|
||||||
msgid "Number of teenagers must be an integer."
|
msgid "Number of teenagers must be an integer."
|
||||||
msgstr "El número de adolescentes tiene que ser entero."
|
msgstr "El número de adolescentes tiene que ser entero."
|
||||||
|
|
||||||
#: pkg/booking/public.go:379
|
#: pkg/booking/public.go:420
|
||||||
msgid "Number of teenagers can not be negative."
|
msgid "Number of teenagers can not be negative."
|
||||||
msgstr "El número de adolescentes no puede ser negativo."
|
msgstr "El número de adolescentes no puede ser negativo."
|
||||||
|
|
||||||
#: pkg/booking/public.go:382
|
#: pkg/booking/public.go:423
|
||||||
msgid "Number of children can not be empty"
|
msgid "Number of children can not be empty"
|
||||||
msgstr "No podéis dejar el número de niños en blanco."
|
msgstr "No podéis dejar el número de niños en blanco."
|
||||||
|
|
||||||
#: pkg/booking/public.go:383
|
#: pkg/booking/public.go:424
|
||||||
msgid "Number of children must be an integer."
|
msgid "Number of children must be an integer."
|
||||||
msgstr "El número de niños tiene que ser entero."
|
msgstr "El número de niños tiene que ser entero."
|
||||||
|
|
||||||
#: pkg/booking/public.go:384
|
#: pkg/booking/public.go:425
|
||||||
msgid "Number of children can not be negative."
|
msgid "Number of children can not be negative."
|
||||||
msgstr "El número de niños no puede ser negativo."
|
msgstr "El número de niños no puede ser negativo."
|
||||||
|
|
||||||
#: pkg/booking/public.go:387
|
#: pkg/booking/public.go:428
|
||||||
msgid "Number of dogs can not be empty"
|
msgid "Number of dogs can not be empty"
|
||||||
msgstr "No podéis dejar el número de perros en blanco."
|
msgstr "No podéis dejar el número de perros en blanco."
|
||||||
|
|
||||||
#: pkg/booking/public.go:388
|
#: pkg/booking/public.go:429
|
||||||
msgid "Number of dogs must be an integer."
|
msgid "Number of dogs must be an integer."
|
||||||
msgstr "El número de perros tiene que ser entero."
|
msgstr "El número de perros tiene que ser entero."
|
||||||
|
|
||||||
#: pkg/booking/public.go:389
|
#: pkg/booking/public.go:430
|
||||||
msgid "Number of dogs can not be negative."
|
msgid "Number of dogs can not be negative."
|
||||||
msgstr "El número de perros no puede ser negativo."
|
msgstr "El número de perros no puede ser negativo."
|
||||||
|
|
||||||
#: pkg/booking/public.go:392
|
#: pkg/booking/public.go:501
|
||||||
msgid "It is mandatory to agree to the reservation conditions."
|
|
||||||
msgstr "Es obligatorio aceptar las condiciones de reserva."
|
|
||||||
|
|
||||||
#: pkg/booking/public.go:395
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s can not be empty"
|
msgid "%s can not be empty"
|
||||||
msgstr "No podéis dejar %s en blanco."
|
msgstr "No podéis dejar %s en blanco."
|
||||||
|
|
||||||
#: pkg/booking/public.go:396
|
#: pkg/booking/public.go:502
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s must be an integer."
|
msgid "%s must be an integer."
|
||||||
msgstr "%s tiene que ser un número entero."
|
msgstr "%s tiene que ser un número entero."
|
||||||
|
|
||||||
#: pkg/booking/public.go:397
|
#: pkg/booking/public.go:503
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s must be %d or greater."
|
msgid "%s must be %d or greater."
|
||||||
msgstr "%s tiene que ser como mínimo %d."
|
msgstr "%s tiene que ser como mínimo %d."
|
||||||
|
|
||||||
#: pkg/booking/public.go:398
|
#: pkg/booking/public.go:504
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s must be at most %d."
|
msgid "%s must be at most %d."
|
||||||
msgstr "%s tiene que ser como máximo %d"
|
msgstr "%s tiene que ser como máximo %d"
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:562
|
||||||
|
msgid "Full name can not be empty."
|
||||||
|
msgstr "No podéis dejar el nombre y los apellidos en blanco."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:563
|
||||||
|
msgid "Full name must have at least one letter."
|
||||||
|
msgstr "El nombre y los apellidos tienen que tener como mínimo una letra."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:580
|
||||||
|
msgid "It is mandatory to agree to the reservation conditions."
|
||||||
|
msgstr "Es obligatorio aceptar las condiciones de reserva."
|
||||||
|
|
||||||
|
#~ msgctxt "input"
|
||||||
|
#~ msgid "Check-in Date"
|
||||||
|
#~ msgstr "Fecha de entrada"
|
||||||
|
|
||||||
|
#~ msgctxt "input"
|
||||||
|
#~ msgid "Check-out Date"
|
||||||
|
#~ msgstr "Fecha de salida"
|
||||||
|
|
||||||
|
#~ msgid "The departure date must be after the arrival date."
|
||||||
|
#~ msgstr "La fecha de partida tiene que ser posterior a la de llegada."
|
||||||
|
|
||||||
#~ msgid "Campsite Montagut is an ideal starting point for quiet outings, climbing, swimming in the river and gorges, volcanoes, the Fageda d’en Jordà, cycle tours for all ages…."
|
#~ msgid "Campsite Montagut is an ideal starting point for quiet outings, climbing, swimming in the river and gorges, volcanoes, the Fageda d’en Jordà, cycle tours for all ages…."
|
||||||
#~ msgstr "El Camping Montagut es ideal como punto de salida de excursiones tranquilas, escalada, bañarse en el río y piletones, volcanes, la Fageda d’en Jordà, salidas en bicicleta para todos los niveles…."
|
#~ msgstr "El Camping Montagut es ideal como punto de salida de excursiones tranquilas, escalada, bañarse en el río y piletones, volcanes, la Fageda d’en Jordà, salidas en bicicleta para todos los niveles…."
|
||||||
|
|
||||||
|
|
264
po/fr.po
264
po/fr.po
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: camper\n"
|
"Project-Id-Version: camper\n"
|
||||||
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
"Report-Msgid-Bugs-To: jordi@tandem.blog\n"
|
||||||
"POT-Creation-Date: 2024-02-04 06:23+0100\n"
|
"POT-Creation-Date: 2024-02-10 03:31+0100\n"
|
||||||
"PO-Revision-Date: 2024-02-06 10:05+0100\n"
|
"PO-Revision-Date: 2024-02-06 10:05+0100\n"
|
||||||
"Last-Translator: Oriol Carbonell <info@oriolcarbonell.cat>\n"
|
"Last-Translator: Oriol Carbonell <info@oriolcarbonell.cat>\n"
|
||||||
"Language-Team: French <traduc@traduc.org>\n"
|
"Language-Team: French <traduc@traduc.org>\n"
|
||||||
|
@ -95,7 +95,7 @@ msgid "The campsite offers many different services."
|
||||||
msgstr "Le camping propose de nombreux services différents."
|
msgstr "Le camping propose de nombreux services différents."
|
||||||
|
|
||||||
#: web/templates/public/amenity.gohtml:39
|
#: web/templates/public/amenity.gohtml:39
|
||||||
#: web/templates/public/campsite/type.gohtml:113
|
#: web/templates/public/campsite/type.gohtml:106
|
||||||
#: web/templates/public/campsite/page.gohtml:39
|
#: web/templates/public/campsite/page.gohtml:39
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Features"
|
msgid "Features"
|
||||||
|
@ -154,89 +154,79 @@ msgstr "À moins d’une heure de <strong>Gérone</strong>, un de <strong>La Bis
|
||||||
msgid "Discover"
|
msgid "Discover"
|
||||||
msgstr "Découvrir"
|
msgstr "Découvrir"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:41
|
#: web/templates/public/campsite/type.gohtml:49
|
||||||
msgctxt "input"
|
#: web/templates/public/booking/fields.gohtml:240
|
||||||
msgid "Check-in Date"
|
|
||||||
msgstr "Date d'arrivée"
|
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:47
|
|
||||||
msgctxt "input"
|
|
||||||
msgid "Check-out Date"
|
|
||||||
msgstr "Date de départ"
|
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:56
|
|
||||||
#: web/templates/public/booking/cart.gohtml:25
|
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Book"
|
msgid "Book"
|
||||||
msgstr "Réserver"
|
msgstr "Réserver"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:64
|
#: web/templates/public/campsite/type.gohtml:57
|
||||||
#: web/templates/admin/season/index.gohtml:54
|
#: web/templates/admin/season/index.gohtml:54
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Calendar"
|
msgid "Calendar"
|
||||||
msgstr "Calendrier"
|
msgstr "Calendrier"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:75
|
#: web/templates/public/campsite/type.gohtml:68
|
||||||
#: web/templates/admin/campsite/type/form.gohtml:143
|
#: web/templates/admin/campsite/type/form.gohtml:143
|
||||||
#: web/templates/admin/campsite/type/option/form.gohtml:70
|
#: web/templates/admin/campsite/type/option/form.gohtml:70
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Prices"
|
msgid "Prices"
|
||||||
msgstr "Prix"
|
msgstr "Prix"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:88
|
#: web/templates/public/campsite/type.gohtml:81
|
||||||
msgid "%s: %s/night"
|
msgid "%s: %s/night"
|
||||||
msgstr "%s : %s/nuit"
|
msgstr "%s : %s/nuit"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:90
|
#: web/templates/public/campsite/type.gohtml:83
|
||||||
msgid "%s/night"
|
msgid "%s/night"
|
||||||
msgstr "%s/nuit"
|
msgstr "%s/nuit"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:95
|
#: web/templates/public/campsite/type.gohtml:88
|
||||||
msgid "*Minimum %d nights per stay"
|
msgid "*Minimum %d nights per stay"
|
||||||
msgstr "*Minimum %d nuits par séjour"
|
msgstr "*Minimum %d nuits par séjour"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:100
|
#: web/templates/public/campsite/type.gohtml:93
|
||||||
msgid "10 % VAT included."
|
msgid "10 % VAT included."
|
||||||
msgstr "10 % TVA incluse."
|
msgstr "10 % TVA incluse."
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:101
|
#: web/templates/public/campsite/type.gohtml:94
|
||||||
msgid "Tourist tax: %s/night per person aged 17 or older."
|
msgid "Tourist tax: %s/night per person aged 17 or older."
|
||||||
msgstr "Taxe touristique: %s/nuit par personne de plus de 16 ans."
|
msgstr "Taxe touristique: %s/nuit par personne de plus de 16 ans."
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:103
|
#: web/templates/public/campsite/type.gohtml:96
|
||||||
msgid "Dogs: %s/night, tied, accompanied, and minimal barking."
|
msgid "Dogs: %s/night, tied, accompanied, and minimal barking."
|
||||||
msgstr "Chiens : %s/nuit, attachés, accompagnés et aboiements minimes."
|
msgstr "Chiens : %s/nuit, attachés, accompagnés et aboiements minimes."
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:105
|
#: web/templates/public/campsite/type.gohtml:98
|
||||||
msgid "No dogs allowed."
|
msgid "No dogs allowed."
|
||||||
msgstr "Chiens interdits."
|
msgstr "Chiens interdits."
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:124
|
#: web/templates/public/campsite/type.gohtml:117
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Info"
|
msgid "Info"
|
||||||
msgstr "Info"
|
msgstr "Info"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:128
|
#: web/templates/public/campsite/type.gohtml:121
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Facilities"
|
msgid "Facilities"
|
||||||
msgstr "Installations"
|
msgstr "Installations"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:132
|
#: web/templates/public/campsite/type.gohtml:125
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Description"
|
msgstr "Description"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:136
|
#: web/templates/public/campsite/type.gohtml:129
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Additional Information"
|
msgid "Additional Information"
|
||||||
msgstr "Informations Complémentaires"
|
msgstr "Informations Complémentaires"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:139
|
#: web/templates/public/campsite/type.gohtml:132
|
||||||
msgctxt "time"
|
msgctxt "time"
|
||||||
msgid "Check-in"
|
msgid "Check-in"
|
||||||
msgstr "Arrivée"
|
msgstr "Arrivée"
|
||||||
|
|
||||||
#: web/templates/public/campsite/type.gohtml:143
|
#: web/templates/public/campsite/type.gohtml:136
|
||||||
msgctxt "time"
|
msgctxt "time"
|
||||||
msgid "Check-out"
|
msgid "Check-out"
|
||||||
msgstr "Départ"
|
msgstr "Départ"
|
||||||
|
@ -283,6 +273,18 @@ msgctxt "day"
|
||||||
msgid "Sun"
|
msgid "Sun"
|
||||||
msgstr "Dim."
|
msgstr "Dim."
|
||||||
|
|
||||||
|
#: web/templates/public/campsite/dates.gohtml:4
|
||||||
|
#: web/templates/public/booking/fields.gohtml:26
|
||||||
|
msgctxt "input"
|
||||||
|
msgid "Arrival date"
|
||||||
|
msgstr "Date d’arrivée"
|
||||||
|
|
||||||
|
#: web/templates/public/campsite/dates.gohtml:15
|
||||||
|
#: web/templates/public/booking/fields.gohtml:37
|
||||||
|
msgctxt "input"
|
||||||
|
msgid "Departure date"
|
||||||
|
msgstr "Date de depart"
|
||||||
|
|
||||||
#: web/templates/public/surroundings.gohtml:30
|
#: web/templates/public/surroundings.gohtml:30
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "What to Do Outside the Campsite?"
|
msgid "What to Do Outside the Campsite?"
|
||||||
|
@ -516,8 +518,7 @@ msgid "Campsites"
|
||||||
msgstr "Locatifs"
|
msgstr "Locatifs"
|
||||||
|
|
||||||
#: web/templates/public/layout.gohtml:70
|
#: web/templates/public/layout.gohtml:70
|
||||||
#: web/templates/public/booking/form.gohtml:7
|
#: web/templates/public/booking/page.gohtml:7
|
||||||
#: web/templates/public/booking/form.gohtml:16
|
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Booking"
|
msgid "Booking"
|
||||||
msgstr "Réservation"
|
msgstr "Réservation"
|
||||||
|
@ -536,119 +537,113 @@ msgstr "Ouverture"
|
||||||
msgid "<abbr title=\"Catalonia Tourism Registry\">RTC</abbr> <abbr title=\"Number\">#</abbr>%s"
|
msgid "<abbr title=\"Catalonia Tourism Registry\">RTC</abbr> <abbr title=\"Number\">#</abbr>%s"
|
||||||
msgstr "<abbr title=\"Registre du tourisme de Catalogne\"># RTC</abbr> %s"
|
msgstr "<abbr title=\"Registre du tourisme de Catalogne\"># RTC</abbr> %s"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:29
|
#: web/templates/public/booking/fields.gohtml:13
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Accommodation"
|
msgid "Accommodation"
|
||||||
msgstr "Hébergement"
|
msgstr "Hébergement"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:43
|
#: web/templates/public/booking/fields.gohtml:23
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Booking Period"
|
msgid "Booking Period"
|
||||||
msgstr "Période de réservation"
|
msgstr "Période de réservation"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:46
|
#: web/templates/public/booking/fields.gohtml:50
|
||||||
msgctxt "input"
|
|
||||||
msgid "Arrival date"
|
|
||||||
msgstr "Date d’arrivée"
|
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:57
|
|
||||||
msgctxt "input"
|
|
||||||
msgid "Departure date"
|
|
||||||
msgstr "Date de depart"
|
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:72
|
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Guests"
|
msgid "Guests"
|
||||||
msgstr "Personnes logeant"
|
msgstr "Personnes logeant"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:76
|
#: web/templates/public/booking/fields.gohtml:54
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Adults aged 17 or older"
|
msgid "Adults aged 17 or older"
|
||||||
msgstr "Adultes âgés 17 ans ou plus"
|
msgstr "Adultes âgés 17 ans ou plus"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:86
|
#: web/templates/public/booking/fields.gohtml:65
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Teenagers from 11 to 16 years old"
|
msgid "Teenagers from 11 to 16 years old"
|
||||||
msgstr "Adolescents de 11 à 16 ans"
|
msgstr "Adolescents de 11 à 16 ans"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:96
|
#: web/templates/public/booking/fields.gohtml:76
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Children from 2 to 10 years old"
|
msgid "Children from 2 to 10 years old"
|
||||||
msgstr "Enfants de 2 à 10 ans"
|
msgstr "Enfants de 2 à 10 ans"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:106
|
#: web/templates/public/booking/fields.gohtml:91
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Dogs"
|
msgid "Dogs"
|
||||||
msgstr "Chiens"
|
msgstr "Chiens"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:127
|
#: web/templates/public/booking/fields.gohtml:100
|
||||||
|
msgid "Note: This accommodation does <strong>not</strong> allow dogs."
|
||||||
|
msgstr "Remarque: Dans cet hébergement les chiens <strong>ne</strong> sont pas autorisés."
|
||||||
|
|
||||||
|
#: web/templates/public/booking/fields.gohtml:110
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Area preferences (optional)"
|
msgid "Area preferences (optional)"
|
||||||
msgstr "Préférences de zone (facultatif)"
|
msgstr "Préférences de zone (facultatif)"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:129
|
#: web/templates/public/booking/fields.gohtml:112
|
||||||
msgid "Campground map"
|
msgid "Campground map"
|
||||||
msgstr "Plan du camping"
|
msgstr "Plan du camping"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:156
|
#: web/templates/public/booking/fields.gohtml:135
|
||||||
msgctxt "title"
|
msgctxt "title"
|
||||||
msgid "Customer Details"
|
msgid "Customer Details"
|
||||||
msgstr "Détails du client"
|
msgstr "Détails du client"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:159
|
#: web/templates/public/booking/fields.gohtml:138
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Full name"
|
msgid "Full name"
|
||||||
msgstr "Nom et prénom"
|
msgstr "Nom et prénom"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:168
|
#: web/templates/public/booking/fields.gohtml:147
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Address (optional)"
|
msgid "Address (optional)"
|
||||||
msgstr "Adresse (Facultatif)"
|
msgstr "Adresse (Facultatif)"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:177
|
#: web/templates/public/booking/fields.gohtml:156
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Postcode (optional)"
|
msgid "Postcode (optional)"
|
||||||
msgstr "Code postal (Facultatif)"
|
msgstr "Code postal (Facultatif)"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:186
|
#: web/templates/public/booking/fields.gohtml:165
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Town or village (optional)"
|
msgid "Town or village (optional)"
|
||||||
msgstr "Ville (Facultatif)"
|
msgstr "Ville (Facultatif)"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:195
|
#: web/templates/public/booking/fields.gohtml:174
|
||||||
#: web/templates/admin/taxDetails.gohtml:101
|
#: web/templates/admin/taxDetails.gohtml:101
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Country"
|
msgid "Country"
|
||||||
msgstr "Pays"
|
msgstr "Pays"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:198
|
#: web/templates/public/booking/fields.gohtml:177
|
||||||
msgid "Choose a country"
|
msgid "Choose a country"
|
||||||
msgstr "Choisissez un pays"
|
msgstr "Choisissez un pays"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:206
|
#: web/templates/public/booking/fields.gohtml:185
|
||||||
#: web/templates/admin/login.gohtml:27 web/templates/admin/profile.gohtml:38
|
#: web/templates/admin/login.gohtml:27 web/templates/admin/profile.gohtml:38
|
||||||
#: web/templates/admin/taxDetails.gohtml:53
|
#: web/templates/admin/taxDetails.gohtml:53
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr "E-mail"
|
msgstr "E-mail"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:215
|
#: web/templates/public/booking/fields.gohtml:194
|
||||||
#: web/templates/admin/taxDetails.gohtml:45
|
#: web/templates/admin/taxDetails.gohtml:45
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "Phone"
|
msgid "Phone"
|
||||||
msgstr "Téléphone"
|
msgstr "Téléphone"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:226
|
#: web/templates/public/booking/fields.gohtml:205
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "ACSI card? (optional)"
|
msgid "ACSI card? (optional)"
|
||||||
msgstr "Carte ACSI ? (Facultatif)"
|
msgstr "Carte ACSI ? (Facultatif)"
|
||||||
|
|
||||||
#: web/templates/public/booking/form.gohtml:233
|
#: web/templates/public/booking/fields.gohtml:212
|
||||||
msgctxt "input"
|
msgctxt "input"
|
||||||
msgid "I have read and I accept %[1]sthe reservation conditions%[2]s"
|
msgid "I have read and I accept %[1]sthe reservation conditions%[2]s"
|
||||||
msgstr "J’ai lu et j’accepte %[1]sles conditions de réservation%[2]s"
|
msgstr "J’ai lu et j’accepte %[1]sles conditions de réservation%[2]s"
|
||||||
|
|
||||||
#: web/templates/public/booking/cart.gohtml:14
|
#: web/templates/public/booking/fields.gohtml:229
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Total"
|
msgid "Total"
|
||||||
msgstr "Totale"
|
msgstr "Totale"
|
||||||
|
@ -1973,12 +1968,12 @@ msgid "Slide image must be an image media type."
|
||||||
msgstr "L’image de la diapositive doit être de type média d’image."
|
msgstr "L’image de la diapositive doit être de type média d’image."
|
||||||
|
|
||||||
#: pkg/app/login.go:56 pkg/app/user.go:246 pkg/company/admin.go:217
|
#: pkg/app/login.go:56 pkg/app/user.go:246 pkg/company/admin.go:217
|
||||||
#: pkg/booking/public.go:351
|
#: pkg/booking/public.go:571
|
||||||
msgid "Email can not be empty."
|
msgid "Email can not be empty."
|
||||||
msgstr "L’e-mail ne peut pas être vide."
|
msgstr "L’e-mail ne peut pas être vide."
|
||||||
|
|
||||||
#: pkg/app/login.go:57 pkg/app/user.go:247 pkg/company/admin.go:218
|
#: pkg/app/login.go:57 pkg/app/user.go:247 pkg/company/admin.go:218
|
||||||
#: pkg/booking/public.go:352
|
#: pkg/booking/public.go:572
|
||||||
msgid "This email is not valid. It should be like name@domain.com."
|
msgid "This email is not valid. It should be like name@domain.com."
|
||||||
msgstr "Cette adresse e-mail n’est pas valide. Il devrait en être name@domain.com."
|
msgstr "Cette adresse e-mail n’est pas valide. Il devrait en être name@domain.com."
|
||||||
|
|
||||||
|
@ -2150,22 +2145,23 @@ msgstr "Le prix par enfant doit être un nombre décimal."
|
||||||
msgid "Price per child must be zero or greater."
|
msgid "Price per child must be zero or greater."
|
||||||
msgstr "Le prix par enfant doit être égal ou supérieur."
|
msgstr "Le prix par enfant doit être égal ou supérieur."
|
||||||
|
|
||||||
#: pkg/campsite/types/public.go:229
|
#: pkg/campsite/types/public.go:244
|
||||||
msgctxt "header"
|
msgctxt "header"
|
||||||
msgid "Adults"
|
msgid "Adults"
|
||||||
msgstr "Adultes"
|
msgstr "Adultes"
|
||||||
|
|
||||||
#: pkg/campsite/types/public.go:235
|
#: pkg/campsite/types/public.go:250
|
||||||
msgctxt "header"
|
msgctxt "header"
|
||||||
msgid "Teenagers (aged 11 to 16)"
|
msgid "Teenagers (aged 11 to 16)"
|
||||||
msgstr "Adolescents (de 11 à 16 anys)"
|
msgstr "Adolescents (de 11 à 16 anys)"
|
||||||
|
|
||||||
#: pkg/campsite/types/public.go:241
|
#: pkg/campsite/types/public.go:256
|
||||||
msgctxt "header"
|
msgctxt "header"
|
||||||
msgid "Children (aged 2 to 10)"
|
msgid "Children (aged 2 to 10)"
|
||||||
msgstr "Enfants (de 2 à 10 anys)"
|
msgstr "Enfants (de 2 à 10 anys)"
|
||||||
|
|
||||||
#: pkg/campsite/admin.go:275 pkg/booking/public.go:360
|
#: pkg/campsite/admin.go:275 pkg/booking/public.go:217
|
||||||
|
#: pkg/booking/public.go:269
|
||||||
msgid "Selected campsite type is not valid."
|
msgid "Selected campsite type is not valid."
|
||||||
msgstr "Le type d’emplacement sélectionné n’est pas valide."
|
msgstr "Le type d’emplacement sélectionné n’est pas valide."
|
||||||
|
|
||||||
|
@ -2321,7 +2317,7 @@ msgstr "L’addresse du lien ne peut pas être vide."
|
||||||
msgid "This web address is not valid. It should be like https://domain.com/."
|
msgid "This web address is not valid. It should be like https://domain.com/."
|
||||||
msgstr "Cette adresse web n’est pas valide. Il devrait en être https://domain.com/."
|
msgstr "Cette adresse web n’est pas valide. Il devrait en être https://domain.com/."
|
||||||
|
|
||||||
#: pkg/company/admin.go:200 pkg/booking/public.go:338
|
#: pkg/company/admin.go:200 pkg/booking/public.go:558
|
||||||
msgid "Selected country is not valid."
|
msgid "Selected country is not valid."
|
||||||
msgstr "Le pays sélectionné n’est pas valide."
|
msgstr "Le pays sélectionné n’est pas valide."
|
||||||
|
|
||||||
|
@ -2341,11 +2337,11 @@ msgstr "Le numéro de TVA ne peut pas être vide."
|
||||||
msgid "This VAT number is not valid."
|
msgid "This VAT number is not valid."
|
||||||
msgstr "Ce numéro de TVA n’est pas valide."
|
msgstr "Ce numéro de TVA n’est pas valide."
|
||||||
|
|
||||||
#: pkg/company/admin.go:212 pkg/booking/public.go:354
|
#: pkg/company/admin.go:212 pkg/booking/public.go:574
|
||||||
msgid "Phone can not be empty."
|
msgid "Phone can not be empty."
|
||||||
msgstr "Le téléphone ne peut pas être vide."
|
msgstr "Le téléphone ne peut pas être vide."
|
||||||
|
|
||||||
#: pkg/company/admin.go:213 pkg/booking/public.go:355
|
#: pkg/company/admin.go:213 pkg/booking/public.go:575
|
||||||
msgid "This phone number is not valid."
|
msgid "This phone number is not valid."
|
||||||
msgstr "Ce numéro de téléphone n’est pas valide."
|
msgstr "Ce numéro de téléphone n’est pas valide."
|
||||||
|
|
||||||
|
@ -2365,7 +2361,7 @@ msgstr "La province ne peut pas être vide."
|
||||||
msgid "Postal code can not be empty."
|
msgid "Postal code can not be empty."
|
||||||
msgstr "Le code postal ne peut pas être vide."
|
msgstr "Le code postal ne peut pas être vide."
|
||||||
|
|
||||||
#: pkg/company/admin.go:227 pkg/booking/public.go:347
|
#: pkg/company/admin.go:227 pkg/booking/public.go:567
|
||||||
msgid "This postal code is not valid."
|
msgid "This postal code is not valid."
|
||||||
msgstr "Ce code postal n’est pas valide."
|
msgstr "Ce code postal n’est pas valide."
|
||||||
|
|
||||||
|
@ -2405,27 +2401,27 @@ msgstr "Le fichier téléchargé ne peut pas être vide."
|
||||||
msgid "Filename can not be empty."
|
msgid "Filename can not be empty."
|
||||||
msgstr "Le nom de fichier ne peut pas être vide."
|
msgstr "Le nom de fichier ne peut pas être vide."
|
||||||
|
|
||||||
#: pkg/booking/cart.go:171
|
#: pkg/booking/cart.go:142
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Night"
|
msgid "Night"
|
||||||
msgstr "Nuit"
|
msgstr "Nuit"
|
||||||
|
|
||||||
#: pkg/booking/cart.go:172
|
#: pkg/booking/cart.go:143
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Adult"
|
msgid "Adult"
|
||||||
msgstr "Adulte"
|
msgstr "Adulte"
|
||||||
|
|
||||||
#: pkg/booking/cart.go:173
|
#: pkg/booking/cart.go:144
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Teenager"
|
msgid "Teenager"
|
||||||
msgstr "Adolescent"
|
msgstr "Adolescent"
|
||||||
|
|
||||||
#: pkg/booking/cart.go:174
|
#: pkg/booking/cart.go:145
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Child"
|
msgid "Child"
|
||||||
msgstr "Enfant"
|
msgstr "Enfant"
|
||||||
|
|
||||||
#: pkg/booking/cart.go:193
|
#: pkg/booking/cart.go:164
|
||||||
msgctxt "cart"
|
msgctxt "cart"
|
||||||
msgid "Tourist tax"
|
msgid "Tourist tax"
|
||||||
msgstr "Taxe touristique"
|
msgstr "Taxe touristique"
|
||||||
|
@ -2487,106 +2483,138 @@ msgstr "L’intégration sélectionnée n’est pas valide."
|
||||||
msgid "The merchant key is not valid."
|
msgid "The merchant key is not valid."
|
||||||
msgstr "La clé marchand n’est pas valide."
|
msgstr "La clé marchand n’est pas valide."
|
||||||
|
|
||||||
#: pkg/booking/public.go:342
|
#: pkg/booking/public.go:318 pkg/booking/public.go:347
|
||||||
msgid "Full name can not be empty."
|
|
||||||
msgstr "Le nom complet ne peut pas être vide."
|
|
||||||
|
|
||||||
#: pkg/booking/public.go:343
|
|
||||||
msgid "Full name must have at least one letter."
|
|
||||||
msgstr "Le nom complet doit comporter au moins une lettre."
|
|
||||||
|
|
||||||
#: pkg/booking/public.go:361
|
|
||||||
msgid "Arrival date can not be empty"
|
|
||||||
msgstr "La date d’arrivée ne peut pas être vide"
|
|
||||||
|
|
||||||
#: pkg/booking/public.go:362
|
|
||||||
msgid "Arrival date must be a valid date."
|
msgid "Arrival date must be a valid date."
|
||||||
msgstr "La date d’arrivée doit être une date valide."
|
msgstr "La date d’arrivée doit être une date valide."
|
||||||
|
|
||||||
#: pkg/booking/public.go:366
|
#: pkg/booking/public.go:332 pkg/booking/public.go:354
|
||||||
msgid "Departure date can not be empty"
|
|
||||||
msgstr "La date de départ ne peut pas être vide"
|
|
||||||
|
|
||||||
#: pkg/booking/public.go:367
|
|
||||||
msgid "Departure date must be a valid date."
|
msgid "Departure date must be a valid date."
|
||||||
msgstr "La date de départ doit être une date valide."
|
msgstr "La date de départ doit être une date valide."
|
||||||
|
|
||||||
#: pkg/booking/public.go:368
|
#: pkg/booking/public.go:346
|
||||||
msgid "The departure date must be after the arrival date."
|
msgid "Arrival date can not be empty"
|
||||||
msgstr "La date de départ doit être postérieure à la date d’arrivée."
|
msgstr "La date d’arrivée ne peut pas être vide"
|
||||||
|
|
||||||
#: pkg/booking/public.go:372
|
#: pkg/booking/public.go:348
|
||||||
|
#, c-format
|
||||||
|
msgid "Arrival date must be %s or after."
|
||||||
|
msgstr "La date d’arrivée doit être égale ou postérieure à %s."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:349
|
||||||
|
#, c-format
|
||||||
|
msgid "Arrival date must be %s or before."
|
||||||
|
msgstr "La date d’arrivée doit être antérieure ou égale à %s."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:353
|
||||||
|
msgid "Departure date can not be empty"
|
||||||
|
msgstr "La date de départ ne peut pas être vide"
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:355
|
||||||
|
#, c-format
|
||||||
|
msgid "Departure date must be %s or after."
|
||||||
|
msgstr "La date de départ doit être égale ou postérieure à %s."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:356
|
||||||
|
#, c-format
|
||||||
|
msgid "Departure date must be %s or before."
|
||||||
|
msgstr "La date de départ doit être antérieure ou égale à %s."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:394
|
||||||
|
#, c-format
|
||||||
|
msgid "There can be at most %d guests in this accommodation."
|
||||||
|
msgstr "Il peut y avoir au plus %d invités dans cet hébergement."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:413
|
||||||
msgid "Number of adults can not be empty"
|
msgid "Number of adults can not be empty"
|
||||||
msgstr "Le nombre d’adultes ne peut pas être vide."
|
msgstr "Le nombre d’adultes ne peut pas être vide."
|
||||||
|
|
||||||
#: pkg/booking/public.go:373
|
#: pkg/booking/public.go:414
|
||||||
msgid "Number of adults must be an integer."
|
msgid "Number of adults must be an integer."
|
||||||
msgstr "Le nombre d’adultes doit être un entier."
|
msgstr "Le nombre d’adultes doit être un entier."
|
||||||
|
|
||||||
#: pkg/booking/public.go:374
|
#: pkg/booking/public.go:415
|
||||||
msgid "There must be at least one adult."
|
msgid "There must be at least one adult."
|
||||||
msgstr "Il doit y avoir au moins un adulte."
|
msgstr "Il doit y avoir au moins un adulte."
|
||||||
|
|
||||||
#: pkg/booking/public.go:377
|
#: pkg/booking/public.go:418
|
||||||
msgid "Number of teenagers can not be empty"
|
msgid "Number of teenagers can not be empty"
|
||||||
msgstr "Le nombre d’adolescents ne peut pas être vide."
|
msgstr "Le nombre d’adolescents ne peut pas être vide."
|
||||||
|
|
||||||
#: pkg/booking/public.go:378
|
#: pkg/booking/public.go:419
|
||||||
msgid "Number of teenagers must be an integer."
|
msgid "Number of teenagers must be an integer."
|
||||||
msgstr "Le nombre d’adolescents doit être un entier."
|
msgstr "Le nombre d’adolescents doit être un entier."
|
||||||
|
|
||||||
#: pkg/booking/public.go:379
|
#: pkg/booking/public.go:420
|
||||||
msgid "Number of teenagers can not be negative."
|
msgid "Number of teenagers can not be negative."
|
||||||
msgstr "Le nombre d’adolescents ne peut pas être négatif."
|
msgstr "Le nombre d’adolescents ne peut pas être négatif."
|
||||||
|
|
||||||
#: pkg/booking/public.go:382
|
#: pkg/booking/public.go:423
|
||||||
msgid "Number of children can not be empty"
|
msgid "Number of children can not be empty"
|
||||||
msgstr "Le nombre d’enfants ne peut pas être vide."
|
msgstr "Le nombre d’enfants ne peut pas être vide."
|
||||||
|
|
||||||
#: pkg/booking/public.go:383
|
#: pkg/booking/public.go:424
|
||||||
msgid "Number of children must be an integer."
|
msgid "Number of children must be an integer."
|
||||||
msgstr "Le nombre d’enfants doit être un entier."
|
msgstr "Le nombre d’enfants doit être un entier."
|
||||||
|
|
||||||
#: pkg/booking/public.go:384
|
#: pkg/booking/public.go:425
|
||||||
msgid "Number of children can not be negative."
|
msgid "Number of children can not be negative."
|
||||||
msgstr "Le nombre d’enfants ne peut pas être négatif."
|
msgstr "Le nombre d’enfants ne peut pas être négatif."
|
||||||
|
|
||||||
#: pkg/booking/public.go:387
|
#: pkg/booking/public.go:428
|
||||||
msgid "Number of dogs can not be empty"
|
msgid "Number of dogs can not be empty"
|
||||||
msgstr "Le nombre de chiens ne peut pas être vide."
|
msgstr "Le nombre de chiens ne peut pas être vide."
|
||||||
|
|
||||||
#: pkg/booking/public.go:388
|
#: pkg/booking/public.go:429
|
||||||
msgid "Number of dogs must be an integer."
|
msgid "Number of dogs must be an integer."
|
||||||
msgstr "Le nombre de chiens nuits être un entier."
|
msgstr "Le nombre de chiens nuits être un entier."
|
||||||
|
|
||||||
#: pkg/booking/public.go:389
|
#: pkg/booking/public.go:430
|
||||||
msgid "Number of dogs can not be negative."
|
msgid "Number of dogs can not be negative."
|
||||||
msgstr "Le nombre de chiens ne peut pas être négatif."
|
msgstr "Le nombre de chiens ne peut pas être négatif."
|
||||||
|
|
||||||
#: pkg/booking/public.go:392
|
#: pkg/booking/public.go:501
|
||||||
msgid "It is mandatory to agree to the reservation conditions."
|
|
||||||
msgstr "Il est obligatoire d’accepter les conditions de réservation."
|
|
||||||
|
|
||||||
#: pkg/booking/public.go:395
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s can not be empty"
|
msgid "%s can not be empty"
|
||||||
msgstr "%s ne peut pas être vide"
|
msgstr "%s ne peut pas être vide"
|
||||||
|
|
||||||
#: pkg/booking/public.go:396
|
#: pkg/booking/public.go:502
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s must be an integer."
|
msgid "%s must be an integer."
|
||||||
msgstr "%s doit être un entier."
|
msgstr "%s doit être un entier."
|
||||||
|
|
||||||
#: pkg/booking/public.go:397
|
#: pkg/booking/public.go:503
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s must be %d or greater."
|
msgid "%s must be %d or greater."
|
||||||
msgstr "%s doit être %d ou plus."
|
msgstr "%s doit être %d ou plus."
|
||||||
|
|
||||||
#: pkg/booking/public.go:398
|
#: pkg/booking/public.go:504
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s must be at most %d."
|
msgid "%s must be at most %d."
|
||||||
msgstr "%s doit être tout au plus %d."
|
msgstr "%s doit être tout au plus %d."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:562
|
||||||
|
msgid "Full name can not be empty."
|
||||||
|
msgstr "Le nom complet ne peut pas être vide."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:563
|
||||||
|
msgid "Full name must have at least one letter."
|
||||||
|
msgstr "Le nom complet doit comporter au moins une lettre."
|
||||||
|
|
||||||
|
#: pkg/booking/public.go:580
|
||||||
|
msgid "It is mandatory to agree to the reservation conditions."
|
||||||
|
msgstr "Il est obligatoire d’accepter les conditions de réservation."
|
||||||
|
|
||||||
|
#~ msgctxt "input"
|
||||||
|
#~ msgid "Check-in Date"
|
||||||
|
#~ msgstr "Date d'arrivée"
|
||||||
|
|
||||||
|
#~ msgctxt "input"
|
||||||
|
#~ msgid "Check-out Date"
|
||||||
|
#~ msgstr "Date de départ"
|
||||||
|
|
||||||
|
#~ msgid "The departure date must be after the arrival date."
|
||||||
|
#~ msgstr "La date de départ doit être postérieure à la date d’arrivée."
|
||||||
|
|
||||||
#~ msgid "Campsite Montagut is an ideal starting point for quiet outings, climbing, swimming in the river and gorges, volcanoes, the Fageda d’en Jordà, cycle tours for all ages…."
|
#~ msgid "Campsite Montagut is an ideal starting point for quiet outings, climbing, swimming in the river and gorges, volcanoes, the Fageda d’en Jordà, cycle tours for all ages…."
|
||||||
#~ msgstr "Le camping Montagut est un point de départ idéal pour des sorties tranquilles, de l’escalade, des baignades dans la rivière et les gorges, les volcans, la Fageda dâen Jordã, des randonnées à vélo pour tous les âges…."
|
#~ msgstr "Le camping Montagut est un point de départ idéal pour des sorties tranquilles, de l’escalade, des baignades dans la rivière et les gorges, les volcans, la Fageda dâen Jordã, des randonnées à vélo pour tous les âges…."
|
||||||
|
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
(function () {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
function updateDepartureDate(arrivalDateField) {
|
|
||||||
const arrivalDate = new Date(arrivalDateField.value);
|
|
||||||
if (isNaN(arrivalDate.getTime())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const departureDateField = document.querySelector('[name="departure_date"]');
|
|
||||||
if (!departureDateField) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateDepartureDate(date) {
|
|
||||||
departureDateField.value = date;
|
|
||||||
departureDateField.dispatchEvent(new Event('input', {bubbles: true}));
|
|
||||||
}
|
|
||||||
|
|
||||||
const minNights = Math.max(1, parseInt(departureDateField.dataset.minNights, 10) || 0);
|
|
||||||
arrivalDate.setUTCDate(arrivalDate.getUTCDate() + minNights);
|
|
||||||
const minDate = formatDate(arrivalDate);
|
|
||||||
|
|
||||||
departureDateField.setAttribute('min', minDate);
|
|
||||||
const departureDate = new Date(departureDateField.value);
|
|
||||||
const validDepartureDate = !isNaN(departureDate.getTime())
|
|
||||||
if (!validDepartureDate || departureDate < arrivalDate) {
|
|
||||||
updateDepartureDate(minDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
const maxNights = parseInt(departureDateField.dataset.maxNights, 10) || 0;
|
|
||||||
if (maxNights > 0) {
|
|
||||||
arrivalDate.setUTCDate(arrivalDate.getUTCDate() + maxNights - minNights);
|
|
||||||
const maxDate = formatDate(arrivalDate);
|
|
||||||
departureDateField.setAttribute('max', maxDate);
|
|
||||||
if (validDepartureDate && departureDate >= arrivalDate) {
|
|
||||||
updateDepartureDate(maxDate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatDate(date) {
|
|
||||||
return `${date.getFullYear()}-${zeroPad(date.getMonth() + 1)}-${zeroPad(date.getDate())}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function zeroPad(num) {
|
|
||||||
return `${num < 10 ? '0' : ''}${num}`
|
|
||||||
}
|
|
||||||
|
|
||||||
const arrivalDateField = document.querySelector('[name="arrival_date"]');
|
|
||||||
if (!arrivalDateField) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
arrivalDateField.addEventListener('change', function (event) {
|
|
||||||
updateDepartureDate(event.target);
|
|
||||||
});
|
|
||||||
|
|
||||||
updateDepartureDate(arrivalDateField);
|
|
||||||
})();
|
|
|
@ -673,8 +673,8 @@ dl, .nature > div, .outside_activities > div, .campsite_info {
|
||||||
@media (max-width: 48rem) {
|
@media (max-width: 48rem) {
|
||||||
|
|
||||||
.campsite_type_title {
|
.campsite_type_title {
|
||||||
padding-bottom: 6rem;
|
padding-bottom: 6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel {
|
.carousel {
|
||||||
overflow: unset;
|
overflow: unset;
|
||||||
|
@ -1290,6 +1290,10 @@ button {
|
||||||
color: var(--contrast);
|
color: var(--contrast);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button[disabled] {
|
||||||
|
background-color: var(--contrast-3);
|
||||||
|
border-color: var(--contrast-3);
|
||||||
|
}
|
||||||
|
|
||||||
/* radio buttins + checkbox */
|
/* radio buttins + checkbox */
|
||||||
|
|
||||||
|
@ -1371,14 +1375,6 @@ input[type="checkbox"]:focus {
|
||||||
flex: .33;
|
flex: .33;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 13rem;
|
top: 13rem;
|
||||||
opacity: 0;
|
|
||||||
visibility: hidden;
|
|
||||||
transition: opacity .5s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
#booking > footer.is-visible {
|
|
||||||
opacity: 1;
|
|
||||||
visibility: visible;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#booking br {
|
#booking br {
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,245 +0,0 @@
|
||||||
<!--
|
|
||||||
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
|
|
||||||
SPDX-FileCopyrightText: 2023 Oriol Carbonell <info@oriolcarbonell.cat>
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
-->
|
|
||||||
{{ define "title" -}}
|
|
||||||
{{( pgettext "Booking" "title" )}}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{ define "head" -}}
|
|
||||||
{{ template "alpineScript" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{ define "content" -}}
|
|
||||||
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/booking.publicPage*/ -}}
|
|
||||||
<h2>{{( pgettext "Booking" "title" )}}</h2>
|
|
||||||
{{ with .Form -}}
|
|
||||||
<form id="booking" action="/{{ currentLocale }}/booking" method="post"
|
|
||||||
x-data="{campsiteType: '', arrivalDate: '', departureDate: '', hasCampsite() { return this.campsiteType !== '' }, hasDates() { return this.arrivalDate !== '' && this.departureDate !== ''} }"
|
|
||||||
x-init="campsiteType = (document.querySelector('[x-model=campsiteType]:checked') || {}).value || ''"
|
|
||||||
>
|
|
||||||
<fieldset
|
|
||||||
data-hx-get="/{{ currentLocale }}/booking/cart"
|
|
||||||
data-hx-include="#booking"
|
|
||||||
data-hx-trigger="load,change"
|
|
||||||
data-hx-target="#booking footer"
|
|
||||||
>
|
|
||||||
<fieldset class="accommodation">
|
|
||||||
<legend>{{( pgettext "Accommodation" "title" )}}</legend>
|
|
||||||
{{ range .CampsiteType.Options -}}
|
|
||||||
<label><input type="radio" name="{{ $.Form.CampsiteType.Name }}" value="{{ .Value }}"
|
|
||||||
x-model="campsiteType"
|
|
||||||
{{ if $.Form.CampsiteType.IsSelected .Value }}checked{{ end }}
|
|
||||||
> {{ .Label }}</label><br>
|
|
||||||
{{- end }}
|
|
||||||
{{ template "error-message" .CampsiteType }}
|
|
||||||
</fieldset>
|
|
||||||
<fieldset class="booking-period"
|
|
||||||
x-cloak
|
|
||||||
x-show="hasCampsite()"
|
|
||||||
x-transition.duration.250ms
|
|
||||||
>
|
|
||||||
<legend>{{( pgettext "Booking Period" "title" )}}</legend>
|
|
||||||
{{ with .ArrivalDate -}}
|
|
||||||
<label>
|
|
||||||
{{( pgettext "Arrival date" "input" )}}<br>
|
|
||||||
<input type="date" required
|
|
||||||
min="{{ today }}"
|
|
||||||
name="{{ .Name }}" value="{{ .Val }}" {{ template "error-attrs" . }}
|
|
||||||
x-model.fill="arrivalDate"
|
|
||||||
><br>
|
|
||||||
</label>
|
|
||||||
{{ template "error-message" . }}
|
|
||||||
{{- end }}
|
|
||||||
{{ with .DepartureDate -}}
|
|
||||||
<label>
|
|
||||||
{{( pgettext "Departure date" "input" )}}<br>
|
|
||||||
<input type="date" required
|
|
||||||
min="{{ tomorrow }}"
|
|
||||||
name="{{ .Name }}" value="{{ .Val }}" {{ template "error-attrs" . }}
|
|
||||||
x-model.fill="departureDate"
|
|
||||||
><br>
|
|
||||||
</label>
|
|
||||||
{{ template "error-message" . }}
|
|
||||||
{{- end }}
|
|
||||||
</fieldset>
|
|
||||||
<fieldset class="guests campsite-options"
|
|
||||||
x-cloak
|
|
||||||
x-show="hasCampsite() && hasDates()"
|
|
||||||
x-transition.duration.250ms
|
|
||||||
>
|
|
||||||
<legend>{{( pgettext "Guests" "title" )}}</legend>
|
|
||||||
|
|
||||||
{{ with .NumberAdults -}}
|
|
||||||
<label>
|
|
||||||
{{( pgettext "Adults aged 17 or older" "input" )}}<br>
|
|
||||||
<input type="number" required
|
|
||||||
name="{{ .Name }}" value="{{ .Val }}" min="1"
|
|
||||||
{{ template "error-attrs" . }}
|
|
||||||
><br>
|
|
||||||
</label>
|
|
||||||
{{ template "error-message" . }}
|
|
||||||
{{- end }}
|
|
||||||
{{ with .NumberTeenagers -}}
|
|
||||||
<label>
|
|
||||||
{{( pgettext "Teenagers from 11 to 16 years old" "input" )}}<br>
|
|
||||||
<input type="number" required
|
|
||||||
name="{{ .Name }}" value="{{ .Val }}" min="0"
|
|
||||||
{{ template "error-attrs" . }}
|
|
||||||
><br>
|
|
||||||
</label>
|
|
||||||
{{ template "error-message" . }}
|
|
||||||
{{- end }}
|
|
||||||
{{ with .NumberChildren -}}
|
|
||||||
<label>
|
|
||||||
{{( pgettext "Children from 2 to 10 years old" "input" )}}<br>
|
|
||||||
<input type="number" required
|
|
||||||
name="{{ .Name }}" value="{{ .Val }}" min="0"
|
|
||||||
{{ template "error-attrs" . }}
|
|
||||||
><br>
|
|
||||||
</label>
|
|
||||||
{{ template "error-message" . }}
|
|
||||||
{{- end }}
|
|
||||||
{{ with .NumberDogs -}}
|
|
||||||
<label>
|
|
||||||
{{( pgettext "Dogs" "input" )}}<br>
|
|
||||||
<input type="number" required
|
|
||||||
name="{{ .Name }}" value="{{ .Val }}" min="0"
|
|
||||||
{{ template "error-attrs" . }}
|
|
||||||
><br>
|
|
||||||
</label>
|
|
||||||
{{ template "error-message" . }}
|
|
||||||
{{- end }}
|
|
||||||
</fieldset>
|
|
||||||
{{ range $campsiteType := .CampsiteType.Options -}}
|
|
||||||
{{ $options := index $.Form.CampsiteTypeOptions .Value }}
|
|
||||||
{{ $zonePreferences := index $.Form.ZonePreferences .Value }}
|
|
||||||
{{ if or $options $zonePreferences }}
|
|
||||||
<fieldset class="campsite-options"
|
|
||||||
x-cloak
|
|
||||||
x-show="campsiteType === '{{ $campsiteType.Value }}' && hasDates()"
|
|
||||||
x-transition.duration.250ms>
|
|
||||||
<legend>{{ .Label }}</legend>
|
|
||||||
{{ with $zonePreferences -}}
|
|
||||||
<label>
|
|
||||||
<span>
|
|
||||||
{{( pgettext "Area preferences (optional)" "input" )}}
|
|
||||||
<a href="/{{ currentLocale }}/campground?zones"
|
|
||||||
target="_blank">{{( gettext "Campground map" )}}</a>
|
|
||||||
</span><br>
|
|
||||||
<input type="text"
|
|
||||||
name="{{ .Name }}" value="{{ .Val }}" {{ template "error-attrs" . }}
|
|
||||||
><br>
|
|
||||||
</label>
|
|
||||||
{{ template "error-message" . }}
|
|
||||||
{{- end }}
|
|
||||||
{{ range $options -}}
|
|
||||||
<label>
|
|
||||||
{{ .Label }}<br>
|
|
||||||
<input type="number" required
|
|
||||||
name="{{ .Input.Name }}" value="{{ .Input.Val }}"
|
|
||||||
min="{{ .Min }}" max="{{ .Max }}"
|
|
||||||
{{ template "error-attrs" .Input }}
|
|
||||||
><br>
|
|
||||||
</label>
|
|
||||||
{{ template "error-message" .Input }}
|
|
||||||
{{- end }}
|
|
||||||
</fieldset>
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
<fieldset class="customer-details"
|
|
||||||
x-cloak
|
|
||||||
x-show="hasCampsite() && hasDates()"
|
|
||||||
x-transition.duration.250ms
|
|
||||||
>
|
|
||||||
<legend>{{( pgettext "Customer Details" "title" )}}</legend>
|
|
||||||
{{ with .FullName -}}
|
|
||||||
<label>
|
|
||||||
{{( pgettext "Full name" "input" )}}<br>
|
|
||||||
<input type="text" required autocomplete="name" minlength="2"
|
|
||||||
name="{{ .Name }}" value="{{ .Val }}" {{ template "error-attrs" . }}
|
|
||||||
><br>
|
|
||||||
</label>
|
|
||||||
{{ template "error-message" . }}
|
|
||||||
{{- end }}
|
|
||||||
{{ with .Address -}}
|
|
||||||
<label>
|
|
||||||
{{( pgettext "Address (optional)" "input" )}}<br>
|
|
||||||
<input type="text" autocomplete="billing street-address"
|
|
||||||
name="{{ .Name }}" value="{{ .Val }}" {{ template "error-attrs" . }}
|
|
||||||
><br>
|
|
||||||
</label>
|
|
||||||
{{ template "error-message" . }}
|
|
||||||
{{- end }}
|
|
||||||
{{ with .PostalCode -}}
|
|
||||||
<label>
|
|
||||||
{{( pgettext "Postcode (optional)" "input" )}}<br>
|
|
||||||
<input type="text" autocomplete="billing postal-code"
|
|
||||||
name="{{ .Name }}" value="{{ .Val }}" {{ template "error-attrs" . }}
|
|
||||||
><br>
|
|
||||||
</label>
|
|
||||||
{{ template "error-message" . }}
|
|
||||||
{{- end }}
|
|
||||||
{{ with .City -}}
|
|
||||||
<label>
|
|
||||||
{{( pgettext "Town or village (optional)" "input" )}}<br>
|
|
||||||
<input type="text"
|
|
||||||
name="{{ .Name }}" value="{{ .Val }}" {{ template "error-attrs" . }}
|
|
||||||
><br>
|
|
||||||
</label>
|
|
||||||
{{ template "error-message" . }}
|
|
||||||
{{- end }}
|
|
||||||
{{ with .Country -}}
|
|
||||||
<label>
|
|
||||||
{{( pgettext "Country" "input" )}}<br>
|
|
||||||
<select name="{{ .Name }}"
|
|
||||||
required autocomplete="country">
|
|
||||||
<option>{{( gettext "Choose a country" )}}</option>
|
|
||||||
{{ template "error-attrs" . }}>{{ template "list-options" . }}
|
|
||||||
</select><br>
|
|
||||||
</label>
|
|
||||||
{{ template "error-message" . }}
|
|
||||||
{{- end }}
|
|
||||||
{{ with .Email -}}
|
|
||||||
<label>
|
|
||||||
{{( pgettext "Email" "input" )}}<br>
|
|
||||||
<input type="email" required autocomplete="email"
|
|
||||||
name="{{ .Name }}" value="{{ .Val }}" {{ template "error-attrs" . }}
|
|
||||||
><br>
|
|
||||||
</label>
|
|
||||||
{{ template "error-message" . }}
|
|
||||||
{{- end }}
|
|
||||||
{{ with .Phone -}}
|
|
||||||
<label>
|
|
||||||
{{( pgettext "Phone" "input" )}}<br>
|
|
||||||
<input type="tel" required autocomplete="tel"
|
|
||||||
name="{{ .Name }}" value="{{ .Val }}" {{ template "error-attrs" . }}
|
|
||||||
><br>
|
|
||||||
</label>
|
|
||||||
{{ template "error-message" . }}
|
|
||||||
{{- end }}
|
|
||||||
{{ with .ACSICard -}}
|
|
||||||
<label class="full-row">
|
|
||||||
<input type="checkbox" name="{{ .Name }}" {{ if .Checked}}checked{{ end }}
|
|
||||||
{{ template "error-attrs" . }}
|
|
||||||
> {{( pgettext "ACSI card? (optional)" "input" )}}</label><br>
|
|
||||||
{{ template "error-message" . }}
|
|
||||||
{{- end }}
|
|
||||||
{{ with .Agreement -}}
|
|
||||||
<label class="full-row">
|
|
||||||
<input type="checkbox" required name="{{ .Name }}" {{ if .Checked}}checked{{ end }}
|
|
||||||
{{ template "error-attrs" . }}
|
|
||||||
> {{ printf ( pgettext "I have read and I accept %[1]sthe reservation conditions%[2]s" "input" ) (printf "<a href=\"/%s/legal/reservation\" rel=\"terms-of-service\" target=\"_blank\">" currentLocale) (print "</a>") | raw }}
|
|
||||||
</label><br>
|
|
||||||
{{ template "error-message" . }}
|
|
||||||
{{- end }}
|
|
||||||
</fieldset>
|
|
||||||
</fieldset>
|
|
||||||
<footer :class="hasCampsite() && hasDates() && 'is-visible'">
|
|
||||||
{{ template "cart.gohtml" $.Cart }}
|
|
||||||
</footer>
|
|
||||||
</form>
|
|
||||||
{{- end }}
|
|
||||||
<script src="/static/booking-dates.js"></script>
|
|
||||||
{{- end }}
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: 2023 jordi fita mas <jordi@tandem.blog>
|
||||||
|
SPDX-FileCopyrightText: 2023 Oriol Carbonell <info@oriolcarbonell.cat>
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
-->
|
||||||
|
{{ define "title" -}}
|
||||||
|
{{( pgettext "Booking" "title" )}}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{ define "content" -}}
|
||||||
|
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/booking.publicPage*/ -}}
|
||||||
|
<h2>{{ template "title" . }}</h2>
|
||||||
|
<form id="booking" action="/{{ currentLocale }}/booking" method="post"
|
||||||
|
data-hx-include="this"
|
||||||
|
data-hx-target="this"
|
||||||
|
data-hx-replace-url="true"
|
||||||
|
>
|
||||||
|
{{ template "fields.gohtml" . }}
|
||||||
|
</form>
|
||||||
|
{{- end }}
|
|
@ -0,0 +1,23 @@
|
||||||
|
{{- /*gotype: dev.tandem.ws/tandem/camper/pkg/booking.DateFields*/ -}}
|
||||||
|
{{ with .ArrivalDate -}}
|
||||||
|
<label>
|
||||||
|
{{( pgettext "Arrival date" "input" )}}<br>
|
||||||
|
<input type="date" required
|
||||||
|
min="{{ formatDateAttr .MinDate }}"
|
||||||
|
max="{{ formatDateAttr .MaxDate }}"
|
||||||
|
name="{{ .Name }}" value="{{ .Val }}" {{ template "error-attrs" . }}
|
||||||
|
><br>
|
||||||
|
</label>
|
||||||
|
{{ template "error-message" . }}
|
||||||
|
{{- end }}
|
||||||
|
{{ with .DepartureDate -}}
|
||||||
|
<label>
|
||||||
|
{{( pgettext "Departure date" "input" )}}<br>
|
||||||
|
<input type="date" required
|
||||||
|
min="{{ formatDateAttr .MinDate }}"
|
||||||
|
max="{{ formatDateAttr .MaxDate }}"
|
||||||
|
name="{{ .Name }}" value="{{ .Val }}" {{ template "error-attrs" . }}
|
||||||
|
><br>
|
||||||
|
</label>
|
||||||
|
{{ template "error-message" . }}
|
||||||
|
{{- end }}
|
|
@ -34,23 +34,16 @@
|
||||||
</div>
|
</div>
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
<form action="/{{ currentLocale }}/booking" method="get" class="campsite_type_booking">
|
<form action="/{{ currentLocale }}/booking" method="get" class="campsite_type_booking"
|
||||||
|
data-hx-include="this"
|
||||||
|
>
|
||||||
<input type="hidden" name="campsite_type" value="{{ .Slug }}">
|
<input type="hidden" name="campsite_type" value="{{ .Slug }}">
|
||||||
<fieldset>
|
<fieldset
|
||||||
<label>
|
data-hx-get="/{{ currentLocale }}/campsites/types/{{ .Slug }}/dates"
|
||||||
{{( pgettext "Check-in Date" "input")}}
|
data-hx-trigger="change"
|
||||||
<br>
|
data-hx-target="this"
|
||||||
<input name="arrival_date" type="date" min="{{ today }}" required>
|
>
|
||||||
<br>
|
{{ template "dates.gohtml" .BookingDates }}
|
||||||
</label>
|
|
||||||
<label>
|
|
||||||
{{( pgettext "Check-out Date" "input")}}
|
|
||||||
<br>
|
|
||||||
<input name="departure_date" type="date" min="{{ tomorrow }}"
|
|
||||||
data-min-nights="{{ .MinNights}}" data-max-nights="{{ .MaxNights }}"
|
|
||||||
>
|
|
||||||
<br>
|
|
||||||
</label>
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<footer>
|
<footer>
|
||||||
<button type="submit">{{( pgettext "Book" "action" )}} <span>→</span></button>
|
<button type="submit">{{( pgettext "Book" "action" )}} <span>→</span></button>
|
||||||
|
@ -91,8 +84,8 @@
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</dd>
|
</dd>
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{ if gt $.MinNights 1 -}}
|
{{ if gt $.BookingDates.MinNights 1 -}}
|
||||||
<dd x-show="open">{{ printf (gettext "*Minimum %d nights per stay") $.MinNights }}</dd>
|
<dd x-show="open">{{ printf (gettext "*Minimum %d nights per stay") $.BookingDates.MinNights }}</dd>
|
||||||
{{- end }}
|
{{- end }}
|
||||||
</div>
|
</div>
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
@ -164,6 +157,16 @@
|
||||||
const right = calendar.querySelector('header button:last-of-type');
|
const right = calendar.querySelector('header button:last-of-type');
|
||||||
right.addEventListener('click', () => carousel.scrollLeft += month.clientWidth);
|
right.addEventListener('click', () => carousel.scrollLeft += month.clientWidth);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
const arrivalDate = document.querySelector('input[name="arrival_date"]');
|
||||||
|
if (arrivalDate && arrivalDate.value !== '') {
|
||||||
|
const load = htmx.on('htmx:load', function () {
|
||||||
|
htmx.off('htmx:load', load);
|
||||||
|
htmx.trigger(arrivalDate, 'change', {bubbles: true});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
<script src="/static/booking-dates.js?v={{ camperVersion }}"></script>
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
Loading…
Reference in New Issue