Commit Graph

108 Commits

Author SHA1 Message Date
jordi fita mas 950bae16e1 Make address, postcode, and city require for booking
Customer changed their mind.
2024-02-24 20:03:11 +01:00
jordi fita mas a159bc75f0 Show a disclaimer on top of book button that it is in fact a prebooking 2024-02-15 15:54:22 +01:00
jordi fita mas f2143cd0e6 Add the admin page to see payments
Had to do a couple of changes to the database: add the currency_code to
the payment relation, to format the price according to the payment’s
currency instead of the company’s; and the reference SQL function, to
replace the equivalent golang function, so that i can use it to index
payments.

The rest is mostly the same as any other page, except that the
individual payment’s page is not a form, but a regular info dump.

I also moved the payment settings as a sub-route of payments, as i
believe this makes more sense than an additional user menu item.
2024-02-14 04:54:42 +01:00
jordi fita mas bd84df8169 Add down payment
Customer wants to require a down payment of 30 % for bookings made
one week or more before the actual date, and to make the full payment
otherwise.

This would require yet another relation to keep these values. Fuck it;
i added them to the function, as they are very unlikely to change.

That forced me to change the test for draft_payment to use relative
dates, otherwise there is no way i can have stable results in the
future.
2024-02-13 23:45:25 +01:00
jordi fita mas 0f76351ae9 Move down HTMx attributes for booking form
Otherwise, it reloads the form while customers are writing their
details, removing the focus from the form; **very** annoying.

On the plus side, there is nothing to compute when entering these
fields, thus no redundant work is done now.
2024-02-13 05:59:07 +01:00
jordi fita mas 15dde3f491 Add ready_payment function and use their slug as URL
Now that the payments have slug, i can use them in the URL to show the
actual data of a payment, and kickstart the payment process with Redsys.
2024-02-12 18:06:17 +01:00
jordi fita mas e4636592c5 Add payment relation and use it to compute the booking’s cart
I had to add the payment concept separate from the booking, unlike other
eCommerce solutions that subsume the two into a single “order”, like
WooCommerce, because bookings should be done in a separate Camper
instance that will sync to the public instance, but the payment is done
by the public instance.  There will be a queue or something between
the public and the private instance to pass along the booking
information once the payment is complete, but the public instance still
needs to keep track of payments without creating bookings.

To compute the total for that payment i had to do the same as was doing
until now for the cart.  To prevent duplications, or having functions
with complex return types, i now create a “draft” payment while the
user is filling in the form, and compute the cart there; from Go i only
have to retrieve the data from the relation, that simplifies the work,
actually.

Since the payment is computed way before customers enter their details,
i can not have that data in the same payment relation, unless i allow
NULL values.  Allowing NULL values means that i can create a payment
without customer, thus i moved all customer details to a separate
relation.  It still allows payment without customer, but at least there
are no NULL values.

Draft payments should be removed after a time, but i believe this needs
to be done in a cronjob or similar, not in the Go application.

To update the same payment while filling the same booking form, i now
have a hidden field with the payment slug.  A competent developer would
have used a cookie or something like that; i am not competent.
2024-02-12 05:21:00 +01:00
jordi fita mas d22fe39c80 Add a small note to the booking form when there is overflow
Customer wants to warn customers that plots are not guaranteed to be
next to each other.
2024-02-11 22:06:00 +01:00
jordi fita mas ea997a4154 Allow campsite type option to be just per unit, not per unit per night
Customer told us that there are some options, such as towels, that have
a fixed price for the whole stay, not a per night price.  Thus, had to
add a boolean to know whether to use sum or max when computing the
cart’s total for each option.
2024-02-11 21:45:00 +01:00
jordi fita mas e5023a2a41 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.
2024-02-10 03:49:44 +01:00
oriol carbonell pujolàs b915ba1559 Change “Discover the environment” to “Discover” 2024-02-06 10:55:29 +01:00
jordi fita mas 2c36e45663 Compute and show the “cart” for the booking form
I have to ask number and age ranges of hosts of guests for all campsite
types, not only those that have price options for adults, children, etc.
because i must compute the tourist tax for adults.  These numbers will
be used to generate de rows for guests when actually creating the
booking, which is not done already.

To satisfy the campsite types that do have a price per guest, not only
per night, i had to add the prices for each range in the
campsite_type_cost relation.  If a campsite type does not have price
per person, then that should be zero; the website then does not display
the price.

The minimal price for any campsite type is one adult for one night,
thus to compute the price i need at least the campsite type, the dates,
and the number of adults, that has a minimum of one.  I changed the
order of the form to ask for these values first, so i can compute the
initial price as soon as possible.  To help further, i show the
<fieldset>s progressively when visitors select options.
2024-02-04 06:37:25 +01:00
jordi fita mas 8d08a78d4c Add titles to credit card logos in booking page
No need to translated them: they are proper names.
2024-02-03 01:41:44 +01:00
jordi fita mas de03443c25 Replace + with 00 to the address in the bottom, too
Customer requested it
2024-02-03 01:04:25 +01:00
jordi fita mas 4c4b9d8d02 Make submenus collapsible on mobile too
Had to change the link to the current language version of the page by a
button, to prevent following a link when trying to expand the submenu.

At first i did this with an `onclick="return false"` bullshit, but the
link was the wrong thing to do here, and it was there only to satisfy
Google et al. They will have to with the links in head.

Also made the link and buttons larger to make it easier to hit them with
finger.
2024-02-03 00:16:29 +01:00
jordi fita mas 313e5aa6c5 Use company trade name variable in copyright statement 2024-02-02 21:58:18 +01:00
jordi fita mas b6044a7d4a Advance min dates of departure and arrival one day
Apparently, expecting people to book at least one day in advance is
being “too optimistic”.
2024-02-02 02:59:41 +01:00
jordi fita mas 4adad7fa7d Replace min_nights from campsite_type_costs to range in campsite_type
Customer told us that the minimum number of nights is per campsite type,
not per season.  And he wants this, along with the maximum number of
nights, in order to limit the range of departure dates that guests can
choose when booking.
2024-01-31 23:06:45 +01:00
jordi fita mas 4f04d973c2 Dynamically set min and max to arrival and departure date inputs
The departure must be at list one day after the arrival, but no longer
than seven, due to campground’s policy.
2024-01-31 20:00:38 +01:00
jordi fita mas d5b61e7283 Translate map’s legend 2024-01-29 14:37:27 +01:00
jordi fita mas e320636ce1 Replace <div>s in legend with more semantically meaningful elements 2024-01-29 14:02:31 +01:00
oriol carbonell pujolàs 72f9e25140 Add map legend 2024-01-29 13:42:24 +01:00
jordi fita mas 23be6ff26c Add ask_zone_preferences and overflow_allowed to campsite_type
The “overflow” is for when people want to book plots for more guests
than is permitted, which the system would need to add a new plot to the
“shopping cart”, as it were; not implemented yet.

The ask zone preferences is to whether show the corresponding input on
the booking form, that it was done implicitly when the campsite type had
options, because up until now it was only for plots, but it is no longer
the case, thus i need to know when to show it; now it is explicit.
2024-01-29 03:38:11 +01:00
jordi fita mas eeaa3b415e Add amenities section and public page
This is more or less the same as the campsites, as public information
goes, but for buildings and other amenities that the camping provides
that are not campsites.
2024-01-27 22:51:41 +01:00
jordi fita mas c284230436 Add public pages for each individual accommodation
A small page with a brief description, carousel, and feature list of
each individual accommodation.

Most of the relations and functions for carousel and features are like
the ones for campsite types, but i had to use the accommodation’s label
to find them, because they do not have slugs; i did not even though
these would be public, and they already have a label, although not
unique for all companies, like UUID slugs are.
2024-01-26 22:27:54 +01:00
jordi fita mas 8d49857dae Add a polygon around each accommodation on the public map
I can not use <a> in that map because Leaflet handles the mouse over
before the anchors sees it, thus it is impossible to click on them; i
have to use a Leaflet layer.

Fortunately, i can just use the <path>’s coordinates as
the polygon points, because with CRS.Simple the coordinates map to
pixel, except for the reversed Y/latitude coordinate. Unfortunately,
<path> coordinates are not straightforward to get: I have to follow the
drawing coordinates, taking into account the current transformation
(CTM), and keeping the last point around for relative coordinates.
Bézier curves are simplified to a straight line from start to end.

There is one single accommodation that started with a relative move
command (m), which apparently have to be treated as an absolute
move (M), but subsequent pairs are treated as relative coordinates[0].

It was easier for me to convert that relative move to absolute and add
a relative lineto command (l) to the next pair.

For now, all i do is highlight the accommodation and zoom it on click,
because i do not know how i should the accommodation’s information.

[0]: https://www.w3.org/TR/SVG11/paths.html#PathDataMovetoCommands
2024-01-25 04:28:51 +01:00
jordi fita mas 0da6845bde Use L.CRS.Simple in leaflet, that maps coordinates to pixels 2024-01-25 02:16:16 +01:00
jordi fita mas dc7098daf3 Correct latitude (y) and longitude (x) coordinates of map
I had them reversed.
2024-01-25 02:15:51 +01:00
jordi fita mas f514f9132e Add ad management for surroundings
They only want a single ad (for now, i guess).
2024-01-23 14:53:15 +01:00
jordi fita mas e34f253620 Make the slogan user-editable and translatable
Because God forbid we have any performance; everything —**everything**—
must be user editable.
2024-01-23 11:52:39 +01:00
jordi fita mas 1f2ab494dd Add check_in and check_out fields to campsite_type
Apparently, each campsite type could have different check-in and
check-out times, thus i need them in the database.

I thought about using an integer or a datetime field, but customer seems
to want a text field to maybe add “before” and “after” there as well.
Translatable text it is.
2024-01-22 20:19:19 +01:00
jordi fita mas fe9abf7d75 Add rel="terms-of-service" to booking form’s link to conditions
I also changed the translatable link to not include any HTML, because it
meant that i had to retranslate them just to add a new attribute, that
does not make much sense—the attribute is not even translatable, thus
all translations must include it verbatim.
2024-01-22 03:41:54 +01:00
jordi fita mas 6ddc41e293 Remove trailing slash from <link> in public layout 2024-01-21 21:12:12 +01:00
jordi fita mas cf527ce070 Add the application’s version to the footer
This is mostly because it is required for the “Digital Kit”, but it also
works in our favor because now i can version the URL to the static
resources.

Go 1.18 adds the info from git if the package is build from a git
repository, but this is not the case in OBS, so i instead relay on a
constant for the version number.  This constant is “updated” by Debian’s
rules, mostly due to the discussion in [0].

[0]: https://github.com/golang/go/issues/22706
2024-01-21 20:50:16 +01:00
jordi fita mas c484e9bbfc Fix the age of touristic tax
It is for people aged 17 or olded, not 16.  I was confused by the
expression “over 16”, that **seems** to mean 17 or older, but actually
includes people aged 16, too.
2024-01-18 15:29:09 +01:00
jordi fita mas 962996be0b Clean up a bit the credit card div from booking page 2024-01-17 13:40:32 +01:00
oriol carbonell pujolàs 10e89c16df Add credit card logos to booking page 2024-01-17 13:31:33 +01:00
jordi fita mas 41fd940108 Enable autoplay to cover’s carousel 2024-01-17 13:26:33 +01:00
jordi fita mas 76d94f76f0 Change cover’s carousel to slick, and move arrows of all to top-right
Oriol did not like that this carousel was different from the rest, and
wanted to have it like the rest, but showing only one slide at a time,
like the customer wants.

He also wanted the arrows for **all** carousels to be in the top-right
corner instead of bottom-right, mostly because the customer complains
that she does not see the arrows if they are on the bottom, and Oriol
does not like the arrows to the sides.
2024-01-17 13:22:47 +01:00
jordi fita mas b1e3f5017f Add home’s cover carousel
This is a separate carousel from the one displayed at the bottom with
location info; it is, i suppose, a carousel for the hero image.

For the database, it works exactly as the home carousel, but on the
front had to use AlpineJS instead of Slick because it needs to show a
text popping up from the bottom when the slide is show, something i do
not know how to do in Slick.

It now makes no sense to have the carousel inside the “nature” section,
because the heading is no longer in there, and moved it out into a new
“hero” div.

Since i now have two carousels in home, i had to add additional
attributes to carousel.AdminHandler to know which URL to point to when
POSTing, PUTting, or redirecting.
2024-01-16 21:05:52 +01:00
jordi fita mas 0928e78bed Added copyright statement to files modified by Oriol 2024-01-16 17:58:49 +01:00
jordi fita mas a0f9c10193 Add management of surroundings’ highlights (points of interest)
Customer does not want the new “masonry-like” design of the surroundings
page, and wants the same style they already had: a regular list with
text and photo, alternating the photo’s side.

And, of course, they want to be able to add and edit them themselves. It
is like another carousel, but with an additional rich-text description.

The photos that we had in that page are no longer of use.
2024-01-16 01:26:35 +01:00
jordi fita mas 0ed6c1b121 Added note about dogs to the campsite type page
The pets icon is just the same as the notpet but without the diagonal
bar.

The price is hardcoded in the query for now, as there is no field
in the campsite type.
2024-01-15 02:07:32 +01:00
jordi fita mas 0beb0bb315 Add VAT and tourist tax information
Since i need the number of decimals to format the price in the template,
i added them to the company, and used them in the call to price_parse().
2024-01-15 01:45:58 +01:00
jordi fita mas 76456aa9b2 Add check-in and check-out time information to campsite type’s page 2024-01-15 01:02:50 +01:00
jordi fita mas dabd197f02 Add additional information field to campsite types
This is actually just to have a fourth column in order to “balance”
lists for types that have a long descriptions.
2024-01-15 00:28:34 +01:00
jordi fita mas 81b6edbc7b Show campground map using leaflet
It is better for mobile users, as they can zoom and pan the map in their
small screens.

Had to increase header’s z-index or the zoom controls would be on top
of it.
2024-01-14 22:31:13 +01:00
jordi fita mas 9b96a355a4 Automatically select the departure date when arrival changes
By default, it selects the next day, unless the new arrival date is
before the current departure, in which case is left as is, because the
idea is to help people avoid useless calendar selections when booking
for next three or four months: they would need to change the month
twice, and now only at most one.
2024-01-13 02:03:27 +01:00
jordi fita mas a226d17aa7 Add the campsite type’s name in front of price if it has options
Customer wants to explicitly show that the first price, the one on top
of the options, is for the campsite type.
2024-01-13 01:37:11 +01:00
jordi fita mas 4d0d7a44ab Add slides to show parameter to carouselInit template
Customer wants four slides in home’s carousel, while keeping three in
the rest of the carousels.

In mobile screen, Oriol told me to always have a single slide, but in
tablet it is the given number minus one.
2024-01-11 21:04:32 +01:00