Compare commits

...

3 commits

Author SHA1 Message Date
bb71291278
fix(booking): restore stripe payment link button handler
Some checks failed
CI / checks (push) Has been cancelled
2026-02-18 19:00:22 +01:00
e138d493ab
fix(api): return bookingURL only from sync endpoint 2026-02-18 18:39:43 +01:00
df1cd66cf1
chore: wire APP_OPENAI_MODEL and upgrade Go/deps 2026-02-18 18:32:01 +01:00
16 changed files with 295 additions and 256 deletions

View file

@ -1,11 +1,12 @@
DATABASE_URL= APP_DATABASE_URL=
DEBUG= APP_DEBUG=
LOG_LEVEL= APP_LOG_LEVEL=
ORIGINS= APP_ORIGINS=
PORT= APP_PORT=
SENTRY_DSN= APP_SENTRY_DSN=
ADMIN= APP_ADMIN=
ADMIN_SECRET= APP_ADMIN_SECRET=
API_KEY= APP_API_KEY=
SECRET_KEY= APP_SECRET_KEY=
SESSION_SECRET= APP_SESSION_SECRET=
APP_OPENAI_MODEL=gpt-5-nano

View file

@ -1,52 +1,43 @@
# Repository Guidelines # Repository Guidelines
## Project Structure & Module Organization ## Project Structure & Module Organization
- `main.go`: application entrypoint (HTTP server).
- `main.go`: Application entrypoint (HTTP server on `:8000`). - `internal/`: core app code by layer:
- `internal/`: Private app code (e.g., `server/`, `service/`, `repository/`, `driver/`, - `server/` (HTTP handlers/routes), `service/` (business logic), `repository/` (data access), `driver/` (external integrations), `config/` (env config), `view/` (templ views/viewmodels).
`config/`, `view/`). Templ views live in `internal/view` and generate `*_templ.go`. - `internal/view/*.templ` are source templates; generated files are `internal/view/*_templ.go`.
- `pkg/`: Reusable packages shared across app layers. - `cmd/cron/`: cron entrypoint.
- `cmd/`: Optional binaries/entrypoints. - `assets/`: static assets. `docs/`: documentation/images. `scripts/` and `tmp/`: tooling/artifacts.
- `assets/`: Static assets and images. - Tests live next to code as `*_test.go`.
- `docs/`: Project documentation.
- `scripts/`, `tmp/`: Dev tooling and build artifacts (Air uses `tmp/`).
## Build, Test, and Development Commands ## Build, Test, and Development Commands
- `make dev`: run local dev stack with Docker Compose and hot reload.
- `make dev`: Start dev container with live reload (Air) on `http://localhost:8000`. - `make run`: build and run production image locally.
- `make run`: Build and run the Docker image with `PORT` and `DATABASE_URL`. - `make test`: run `go test ./...`.
- `make test`: Run `go test ./...` inside the running dev container. - `make format`: run `templ generate`, `templ fmt`, and `go fmt`.
- `make format`: Run `templ generate`, `templ fmt`, and `go fmt`. - `make lint`: run `golangci-lint run ./...`.
- `make lint`: Run `golangci-lint`. - `make stop`: stop dev containers.
- Local alternative: `air -c .air.toml`, `go test ./...`, `go run .`. - Local (without Docker): `go run .`, `go test ./...`.
## Coding Style & Naming Conventions ## Coding Style & Naming Conventions
- Go style is standard `go fmt` (tabs, canonical imports).
- Go formatting: Use `go fmt` (tabs, standard import ordering). CI helpers: - Package names: lowercase, no underscores.
`make format`. - File names: lowercase with underscores when needed.
- Linting: `golangci-lint run ./...` via `make lint` (fix issues before PR). - Exported identifiers: `PascalCase`; unexported: `camelCase`.
- Packages: lowercase, no underscores; files: lowercase with underscores; exported - Keep handler/controller code thin; place business rules in `internal/service`.
identifiers: `PascalCase`; unexported: `camelCase`.
- Templ: keep `.templ` in `internal/view`; commit sources, not generated `*_templ.go`.
## Testing Guidelines ## Testing Guidelines
- Use Go `testing` with table-driven tests where practical.
- Framework: standard `testing` with table-driven tests. - Name files `*_test.go`; tests `TestXxx`; benchmarks `BenchmarkXxx`.
- Files: `*_test.go`; functions: `TestXxx`, benchmarks: `BenchmarkXxx`. - Cover success and failure paths for changed logic.
- Run: `make test` (in container) or `go test ./...` locally. - Run `make test` (or `go test ./...`) before opening a PR.
- Aim for meaningful coverage on new/changed code; include error paths.
## Commit & Pull Request Guidelines ## Commit & Pull Request Guidelines
- Prefer Conventional Commits: `feat(scope): ...`, `fix(scope): ...`, `chore: ...`.
- Messages: Prefer Conventional Commits (e.g., `feat(parser): ...`, - Keep commits focused and atomic.
`fix(config): ...`). Short, imperative first line; scope optional. - PRs should include: clear summary, linked issue (e.g., `#51`), and screenshots for UI changes.
- PRs: Provide clear description, link issues (e.g., `#45`), include screenshots - Call out config/env changes and any migration or deployment impact.
for UI, and note breaking changes/migrations.
- Keep diffs focused; run `make format` and `make lint` before opening.
## Security & Configuration Tips ## Security & Configuration Tips
- Config is environment-driven with `APP_` prefix (see `internal/config/config.go`).
- Environment: Use `.env`/`prod.env`; never commit secrets. - Example parser model override: `APP_OPENAI_MODEL=gpt-5-nano`.
Example: `DATABASE_URL="host=... user=... database=..."`. - Never commit secrets; keep them in local `.env` / deployment secret manager.
- Ports: default `8000`; configure via `PORT`.
- Dependencies: use `go mod tidy` and `make up-deps` when updating.

View file

@ -1,4 +1,4 @@
FROM golang:1.25-alpine AS builder FROM golang:1.26-alpine AS builder
RUN apk update && apk add --no-cache \ RUN apk update && apk add --no-cache \
build-base \ build-base \

View file

@ -1,5 +1,5 @@
# ----------- Builder Stage ----------- # ----------- Builder Stage -----------
FROM golang:1.25-alpine AS builder FROM golang:1.26-alpine AS builder
WORKDIR /app WORKDIR /app
RUN apk add --no-cache build-base RUN apk add --no-cache build-base
@ -22,7 +22,7 @@ RUN --mount=type=cache,target=/root/.cache/go-build \
go build -ldflags="-s -w" -o rentease main.go go build -ldflags="-s -w" -o rentease main.go
# ----------- Dev Stage ----------- # ----------- Dev Stage -----------
FROM golang:1.25-alpine AS dev FROM golang:1.26-alpine AS dev
WORKDIR /app WORKDIR /app
# Install runtime dependencies # Install runtime dependencies

View file

@ -83,6 +83,7 @@ APP_ORIGINS=http://localhost:8000
APP_PORT=8000 APP_PORT=8000
APP_DEBUG=true APP_DEBUG=true
APP_LOG_LEVEL=debug APP_LOG_LEVEL=debug
APP_OPENAI_MODEL=gpt-5-nano
APP_STRIPE_SECRET_KEY= APP_STRIPE_SECRET_KEY=
APP_STRIPE_WEBHOOK_SECRET= APP_STRIPE_WEBHOOK_SECRET=
APP_SENTRY_DSN= APP_SENTRY_DSN=

View file

@ -15,6 +15,7 @@ services:
APP_LOG_LEVEL: debug APP_LOG_LEVEL: debug
APP_PORT: 8000 APP_PORT: 8000
APP_ORIGINS: http://localhost:8000 APP_ORIGINS: http://localhost:8000
APP_OPENAI_MODEL: gpt-5-nano
APP_DATABASE_URL: postgres://rentease:rentease@db:5432/rentease?sslmode=disable APP_DATABASE_URL: postgres://rentease:rentease@db:5432/rentease?sslmode=disable
APP_ADMIN: admin@example.com APP_ADMIN: admin@example.com
APP_ADMIN_SECRET: supersecret APP_ADMIN_SECRET: supersecret

10
go.mod
View file

@ -1,11 +1,11 @@
module github.com/rjNemo/rentease module github.com/rjNemo/rentease
go 1.25.4 go 1.26
require ( require (
github.com/a-h/templ v0.3.977 github.com/a-h/templ v0.3.977
github.com/getsentry/sentry-go v0.40.0 github.com/getsentry/sentry-go v0.42.0
github.com/go-chi/chi/v5 v5.2.3 github.com/go-chi/chi/v5 v5.2.5
github.com/go-chi/cors v1.2.2 github.com/go-chi/cors v1.2.2
github.com/gorilla/sessions v1.4.0 github.com/gorilla/sessions v1.4.0
github.com/joho/godotenv v1.5.1 github.com/joho/godotenv v1.5.1
@ -36,6 +36,6 @@ require (
github.com/openai/openai-go v1.12.0 github.com/openai/openai-go v1.12.0
github.com/sethvargo/go-envconfig v1.3.0 github.com/sethvargo/go-envconfig v1.3.0
golang.org/x/sync v0.19.0 // indirect golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.40.0 // indirect golang.org/x/sys v0.41.0 // indirect
golang.org/x/text v0.32.0 golang.org/x/text v0.34.0
) )

16
go.sum
View file

@ -5,10 +5,10 @@ github.com/a-h/templ v0.3.977/go.mod h1:oCZcnKRf5jjsGpf2yELzQfodLphd2mwecwG4Crk5
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/getsentry/sentry-go v0.40.0 h1:VTJMN9zbTvqDqPwheRVLcp0qcUcM+8eFivvGocAaSbo= github.com/getsentry/sentry-go v0.42.0 h1:eeFMACuZTbUQf90RE8dE4tXeSe4CZyfvR1MBL7RLEt8=
github.com/getsentry/sentry-go v0.40.0/go.mod h1:eRXCoh3uvmjQLY6qu63BjUZnaBu5L5WhMV1RwYO8W5s= github.com/getsentry/sentry-go v0.42.0/go.mod h1:eRXCoh3uvmjQLY6qu63BjUZnaBu5L5WhMV1RwYO8W5s=
github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE= github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
github.com/go-chi/cors v1.2.2 h1:Jmey33TE+b+rB7fT8MUy1u0I4L+NARQlK6LhzKPSyQE= github.com/go-chi/cors v1.2.2 h1:Jmey33TE+b+rB7fT8MUy1u0I4L+NARQlK6LhzKPSyQE=
github.com/go-chi/cors v1.2.2/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-chi/cors v1.2.2/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
@ -75,10 +75,10 @@ golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View file

@ -25,6 +25,8 @@ type Config struct {
Port int `env:"PORT, default=4200"` Port int `env:"PORT, default=4200"`
// SentryDsn is the DSN for Sentry error reporting // SentryDsn is the DSN for Sentry error reporting
SentryDsn string `env:"SENTRY_DSN"` SentryDsn string `env:"SENTRY_DSN"`
// OpenAIModel is the OpenAI model used by the booking parser
OpenAIModel string `env:"OPENAI_MODEL, default=gpt-5-nano"`
// Auth // Auth
// Admin is the email used to access the admin panel // Admin is the email used to access the admin panel
Admin string `env:"ADMIN, required"` Admin string `env:"ADMIN, required"`

View file

@ -16,11 +16,13 @@ import (
type BookingAgentParser struct { type BookingAgentParser struct {
systemPrompt string systemPrompt string
llmClient openai.Client llmClient openai.Client
model string
} }
func NewBookingAgentParser() *BookingAgentParser { func NewBookingAgentParser(model string) *BookingAgentParser {
return &BookingAgentParser{ return &BookingAgentParser{
llmClient: openai.NewClient(), llmClient: openai.NewClient(),
model: model,
systemPrompt: ` Extract the following fields from the booking content and return a JSON object with this exact structure (all fields required, use null or empty string if not available): systemPrompt: ` Extract the following fields from the booking content and return a JSON object with this exact structure (all fields required, use null or empty string if not available):
{ {
@ -71,7 +73,7 @@ func (p *BookingAgentParser) Parse(rawContent string) (*booking.Booking, error)
resp, err := p.llmClient.Responses.New(ctx, responses.ResponseNewParams{ resp, err := p.llmClient.Responses.New(ctx, responses.ResponseNewParams{
Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(prompt)}, Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(prompt)},
Model: openai.ChatModelChatgpt4oLatest, Model: p.model,
}) })
if err != nil { if err != nil {
return nil, fmt.Errorf("error sending request to OpenAI: %w", err) return nil, fmt.Errorf("error sending request to OpenAI: %w", err)

View file

@ -47,7 +47,7 @@ func TestBookingAgentParser_Parse(t *testing.T) {
Les conversations avec vos clients apparaîtront ici. Les conversations avec vos clients apparaîtront ici.
Booking.com reçoit tous les messages écrits ici et les traite selon sa Charte de confidentialité et informations sur les cookies Conditions ` Booking.com reçoit tous les messages écrits ici et les traite selon sa Charte de confidentialité et informations sur les cookies Conditions `
parser := NewBookingAgentParser() parser := NewBookingAgentParser("gpt-5-nano")
booking, err := parser.Parse(input) booking, err := parser.Parse(input)
if err != nil { if err != nil {
t.Fatalf("Parse failed: %v", err) t.Fatalf("Parse failed: %v", err)

View file

@ -165,7 +165,7 @@ func buildPaymentLinkCreateParams(params CreatePaymentLinkParams) (*stripe.Payme
ProductData: &stripe.PaymentLinkCreateLineItemPriceDataProductDataParams{ ProductData: &stripe.PaymentLinkCreateLineItemPriceDataProductDataParams{
Name: stripe.String(strings.TrimSpace(params.Description)), Name: stripe.String(strings.TrimSpace(params.Description)),
}, },
UnitAmount: stripe.Int64(amountCents), UnitAmount: new(amountCents),
}, },
Quantity: stripe.Int64(1), Quantity: stripe.Int64(1),
}, },

View file

@ -50,7 +50,7 @@ func handleSync(bs *booking.Service) http.HandlerFunc {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated) w.WriteHeader(http.StatusCreated)
if err := json.NewEncoder(w).Encode(fmt.Sprintf("👍 %s", bookingURL)); err != nil { if err := json.NewEncoder(w).Encode(map[string]string{"bookingURL": bookingURL}); err != nil {
slog.Error("failed to write response", slog.Any("error", err)) slog.Error("failed to write response", slog.Any("error", err))
} }
} }

View file

@ -49,6 +49,9 @@ templ BookingById(booking *BookingViewModel) {
type="button" type="button"
class="btn btn-ghost btn-sm btn-square" class="btn btn-ghost btn-sm btn-square"
data-payment-link-url={ booking.StripePaymentLinkUrl } data-payment-link-url={ booking.StripePaymentLinkUrl }
data-payment-link-failed={ i18n.Localize(ctx, "booking.payment_link_failed") }
data-payment-link-unavailable={ i18n.Localize(ctx, "booking.payment_link_unavailable") }
data-payment-link-unexpected={ i18n.Localize(ctx, "booking.payment_link_unexpected") }
aria-label="Create Stripe payment link" aria-label="Create Stripe payment link"
onclick="createStripePaymentLink(event)" onclick="createStripePaymentLink(event)"
> >
@ -129,10 +132,6 @@ templ BookingById(booking *BookingViewModel) {
</form> </form>
</div> </div>
<script> <script>
const paymentLinkFailedMessage = "{ i18n.Localize(ctx, "booking.payment_link_failed") }";
const paymentLinkUnavailableMessage = "{ i18n.Localize(ctx, "booking.payment_link_unavailable") }";
const paymentLinkUnexpectedMessage = "{ i18n.Localize(ctx, "booking.payment_link_unexpected") }";
async function createStripePaymentLink(event) { async function createStripePaymentLink(event) {
const button = event.currentTarget; const button = event.currentTarget;
if (!button) { if (!button) {
@ -142,6 +141,9 @@ templ BookingById(booking *BookingViewModel) {
if (!endpoint) { if (!endpoint) {
return; return;
} }
const failedMessage = button.dataset.paymentLinkFailed || "Unable to create the Stripe payment link. Please try again.";
const unavailableMessage = button.dataset.paymentLinkUnavailable || "Unable to create the Stripe payment link.";
const unexpectedMessage = button.dataset.paymentLinkUnexpected || "Unexpected error while creating payment link.";
button.disabled = true; button.disabled = true;
button.classList.add("loading"); button.classList.add("loading");
try { try {
@ -152,7 +154,7 @@ templ BookingById(booking *BookingViewModel) {
}, },
}); });
if (!response.ok) { if (!response.ok) {
const message = await extractStripePaymentLinkError(response); const message = await extractStripePaymentLinkError(response, unavailableMessage, unexpectedMessage);
alert(message); alert(message);
return; return;
} }
@ -162,14 +164,14 @@ templ BookingById(booking *BookingViewModel) {
} }
} catch (error) { } catch (error) {
console.error("Failed to create Stripe payment link", error); console.error("Failed to create Stripe payment link", error);
alert(paymentLinkFailedMessage); alert(failedMessage);
} finally { } finally {
button.disabled = false; button.disabled = false;
button.classList.remove("loading"); button.classList.remove("loading");
} }
} }
async function extractStripePaymentLinkError(response) { async function extractStripePaymentLinkError(response, unavailableMessage, unexpectedMessage) {
try { try {
const payload = await response.json(); const payload = await response.json();
if (payload && payload.message) { if (payload && payload.message) {
@ -177,9 +179,9 @@ templ BookingById(booking *BookingViewModel) {
} }
} catch (_error) { } catch (_error) {
// ignore parsing errors // ignore parsing errors
return paymentLinkUnexpectedMessage; return unexpectedMessage;
} }
return paymentLinkUnavailableMessage; return unavailableMessage;
} }
</script> </script>
@PaymentModal(booking.PaymentUrl) @PaymentModal(booking.PaymentUrl)

View file

@ -201,53 +201,53 @@ func BookingById(booking *BookingViewModel) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\" aria-label=\"Create Stripe payment link\" onclick=\"createStripePaymentLink(event)\"><img src=\"/static/icons/stripe.png\" class=\"w-6 h-6\"></button></div></hgroup><div class=\"overflow-x-auto mb-6\"><table class=\"table w-full\"><thead><tr><th>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\" data-payment-link-failed=\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var13 string var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.item")) templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.payment_link_failed"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 63, Col: 52} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 52, Col: 82}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</th><th>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\" data-payment-link-unavailable=\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var14 string var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.quantity")) templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.payment_link_unavailable"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 64, Col: 56} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 53, Col: 92}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</th><th>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\" data-payment-link-unexpected=\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var15 string var templ_7745c5c3_Var15 string
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.price")) templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.payment_link_unexpected"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 65, Col: 53} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 54, Col: 90}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, " (€)</th><th>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "\" aria-label=\"Create Stripe payment link\" onclick=\"createStripePaymentLink(event)\"><img src=\"/static/icons/stripe.png\" class=\"w-6 h-6\"></button></div></hgroup><div class=\"overflow-x-auto mb-6\"><table class=\"table w-full\"><thead><tr><th>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var16 string var templ_7745c5c3_Var16 string
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.payment_method")) templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.item"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 66, Col: 62} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 66, Col: 52}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -258,7 +258,7 @@ func BookingById(booking *BookingViewModel) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var17 string var templ_7745c5c3_Var17 string
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.subtotal")) templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.quantity"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 67, Col: 56} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 67, Col: 56}
} }
@ -266,20 +266,59 @@ func BookingById(booking *BookingViewModel) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, " (€)</th><th class=\"text-right\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</th><th>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var18 string var templ_7745c5c3_Var18 string
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.actions")) templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.price"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 68, Col: 74} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 68, Col: 53}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</th></tr></thead>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, " (€)</th><th>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var19 string
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.payment_method"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 69, Col: 62}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</th><th>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var20 string
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.subtotal"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 70, Col: 56}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, " (€)</th><th class=\"text-right\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var21 string
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.actions"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 71, Col: 74}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</th></tr></thead>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -287,147 +326,147 @@ func BookingById(booking *BookingViewModel) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "<tfoot><tr><td colspan=\"4\" class=\"text-right font-bold\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "<tfoot><tr><td colspan=\"4\" class=\"text-right font-bold\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var19 string
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.total"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 74, Col: 94}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, ":</td><td colspan=\"2\" class=\"font-bold\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var20 string
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(booking.Total)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 75, Col: 56}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</td></tr></tfoot></table></div></section><div class=\"border-t pt-4 border-base-content/10\"><h3 class=\"text-lg font-semibold mb-3\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var21 string
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.add_line_item_title"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 82, Col: 98}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</h3><form hx-post=\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var22 string var templ_7745c5c3_Var22 string
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%s/items", booking.Url)) templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.total"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 84, Col: 50} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 77, Col: 94}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "\" hx-target=\"#line-items\" hx-swap=\"afterend\" hx-on::after-request=\"if(event.detail.successful) this.reset()\" class=\"grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-4 items-end\"><div class=\"form-control w-full\"><label class=\"label\" for=\"new-line-item\"><span class=\"label-text\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, ":</td><td colspan=\"2\" class=\"font-bold\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var23 string var templ_7745c5c3_Var23 string
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.item")) templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(booking.Total)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 92, Col: 72} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 78, Col: 56}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</span></label> <select class=\"select select-bordered w-full\" name=\"item\" id=\"new-line-item\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</td></tr></tfoot></table></div></section><div class=\"border-t pt-4 border-base-content/10\"><h3 class=\"text-lg font-semibold mb-3\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
for _, item := range booking.ItemList { var templ_7745c5c3_Var24 string
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<option value=\"") templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.add_line_item_title"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 85, Col: 98}
}
var templ_7745c5c3_Var24 string
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(item)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 96, Col: 27}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var25 string
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(item)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 96, Col: 36}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "</option>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "</select></div><div class=\"form-control w-full\"><label class=\"label\" for=\"new-line-quantity\"><span class=\"label-text\">") _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</h3><form hx-post=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var25 string
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%s/items", booking.Url))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 87, Col: 50}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "\" hx-target=\"#line-items\" hx-swap=\"afterend\" hx-on::after-request=\"if(event.detail.successful) this.reset()\" class=\"grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-4 items-end\"><div class=\"form-control w-full\"><label class=\"label\" for=\"new-line-item\"><span class=\"label-text\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var26 string var templ_7745c5c3_Var26 string
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.quantity")) templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.item"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 102, Col: 76} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 95, Col: 72}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "</span></label> <input type=\"number\" name=\"quantity\" id=\"new-line-quantity\" required class=\"input input-bordered w-full\"></div><div class=\"form-control w-full\"><label class=\"label\" for=\"new-line-price\"><span class=\"label-text\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "</span></label> <select class=\"select select-bordered w-full\" name=\"item\" id=\"new-line-item\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var27 string for _, item := range booking.ItemList {
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.price")) templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "<option value=\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 114, Col: 73} return templ_7745c5c3_Err
}
var templ_7745c5c3_Var27 string
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(item)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 99, Col: 27}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var28 string
templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(item)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 99, Col: 36}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "</option>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</select></div><div class=\"form-control w-full\"><label class=\"label\" for=\"new-line-quantity\"><span class=\"label-text\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, " (€)</span></label> <input type=\"number\" name=\"price\" inputmode=\"decimal\" step=\"0.01\" id=\"new-line-price\" required class=\"input input-bordered w-full\"></div><div class=\"flex justify-end md:justify-start\"><button type=\"submit\" class=\"btn btn-secondary\">") var templ_7745c5c3_Var29 string
templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.quantity"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 105, Col: 76}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var28 string templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</span></label> <input type=\"number\" name=\"quantity\" id=\"new-line-quantity\" required class=\"input input-bordered w-full\"></div><div class=\"form-control w-full\"><label class=\"label\" for=\"new-line-price\"><span class=\"label-text\">")
templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.add_line_item"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 127, Col: 103}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</button></div></form></div><script>\n\t\t\tconst paymentLinkFailedMessage = \"{ i18n.Localize(ctx, \"booking.payment_link_failed\") }\";\n\t\t\tconst paymentLinkUnavailableMessage = \"{ i18n.Localize(ctx, \"booking.payment_link_unavailable\") }\";\n\t\t\tconst paymentLinkUnexpectedMessage = \"{ i18n.Localize(ctx, \"booking.payment_link_unexpected\") }\";\n\n\t\t\tasync function createStripePaymentLink(event) {\n\t\t\t\tconst button = event.currentTarget;\n\t\t\t\tif (!button) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst endpoint = button.dataset.paymentLinkUrl;\n\t\t\t\tif (!endpoint) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tbutton.disabled = true;\n\t\t\t\tbutton.classList.add(\"loading\");\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await fetch(endpoint, {\n\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Accept\": \"application/json\",\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tif (!response.ok) {\n\t\t\t\t\t\tconst message = await extractStripePaymentLinkError(response);\n\t\t\t\t\t\talert(message);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst data = await response.json();\n\t\t\t\t\tif (data && data.url) {\n\t\t\t\t\t\twindow.open(data.url, \"_blank\", \"noopener\");\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(\"Failed to create Stripe payment link\", error);\n\t\t\t\t\talert(paymentLinkFailedMessage);\n\t\t\t\t} finally {\n\t\t\t\t\tbutton.disabled = false;\n\t\t\t\t\tbutton.classList.remove(\"loading\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tasync function extractStripePaymentLinkError(response) {\n\t\t\t\ttry {\n\t\t\t\t\tconst payload = await response.json();\n\t\t\t\t\tif (payload && payload.message) {\n\t\t\t\t\t\treturn payload.message;\n\t\t\t\t\t}\n\t\t\t\t} catch (_error) {\n\t\t\t\t\t// ignore parsing errors\n\t\t\t\t\treturn paymentLinkUnexpectedMessage;\n\t\t\t\t}\n\t\t\t\treturn paymentLinkUnavailableMessage;\n\t\t\t}\n\t\t</script> ") var templ_7745c5c3_Var30 string
templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.price"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 117, Col: 73}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, " (€)</span></label> <input type=\"number\" name=\"price\" inputmode=\"decimal\" step=\"0.01\" id=\"new-line-price\" required class=\"input input-bordered w-full\"></div><div class=\"flex justify-end md:justify-start\"><button type=\"submit\" class=\"btn btn-secondary\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var31 string
templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "booking.view.add_line_item"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 130, Col: 103}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "</button></div></form></div><script>\n\t\t\tasync function createStripePaymentLink(event) {\n\t\t\t\tconst button = event.currentTarget;\n\t\t\t\tif (!button) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst endpoint = button.dataset.paymentLinkUrl;\n\t\t\t\tif (!endpoint) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst failedMessage = button.dataset.paymentLinkFailed || \"Unable to create the Stripe payment link. Please try again.\";\n\t\t\t\tconst unavailableMessage = button.dataset.paymentLinkUnavailable || \"Unable to create the Stripe payment link.\";\n\t\t\t\tconst unexpectedMessage = button.dataset.paymentLinkUnexpected || \"Unexpected error while creating payment link.\";\n\t\t\t\tbutton.disabled = true;\n\t\t\t\tbutton.classList.add(\"loading\");\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await fetch(endpoint, {\n\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Accept\": \"application/json\",\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tif (!response.ok) {\n\t\t\t\t\t\tconst message = await extractStripePaymentLinkError(response, unavailableMessage, unexpectedMessage);\n\t\t\t\t\t\talert(message);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst data = await response.json();\n\t\t\t\t\tif (data && data.url) {\n\t\t\t\t\t\twindow.open(data.url, \"_blank\", \"noopener\");\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(\"Failed to create Stripe payment link\", error);\n\t\t\t\t\talert(failedMessage);\n\t\t\t\t} finally {\n\t\t\t\t\tbutton.disabled = false;\n\t\t\t\t\tbutton.classList.remove(\"loading\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tasync function extractStripePaymentLinkError(response, unavailableMessage, unexpectedMessage) {\n\t\t\t\ttry {\n\t\t\t\t\tconst payload = await response.json();\n\t\t\t\t\tif (payload && payload.message) {\n\t\t\t\t\t\treturn payload.message;\n\t\t\t\t\t}\n\t\t\t\t} catch (_error) {\n\t\t\t\t\t// ignore parsing errors\n\t\t\t\t\treturn unexpectedMessage;\n\t\t\t\t}\n\t\t\t\treturn unavailableMessage;\n\t\t\t}\n\t\t</script> ")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -461,142 +500,142 @@ func PaymentModal(paymentUrl string) templ.Component {
}() }()
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var29 := templ.GetChildren(ctx) templ_7745c5c3_Var32 := templ.GetChildren(ctx)
if templ_7745c5c3_Var29 == nil { if templ_7745c5c3_Var32 == nil {
templ_7745c5c3_Var29 = templ.NopComponent templ_7745c5c3_Var32 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "<dialog id=\"payment_modal\" class=\"modal\"><div class=\"modal-box\"><h3 class=\"text-lg font-bold\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "<dialog id=\"payment_modal\" class=\"modal\"><div class=\"modal-box\"><h3 class=\"text-lg font-bold\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var30 string
templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.modal.title"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 192, Col: 76}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "</h3><form class=\"py-4 space-y-4\" hx-post=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var31 string
templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(paymentUrl)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 195, Col: 24}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "\" hx-target=\"#payment-lines\" hx-swap=\"outerHTML\" hx-on::after-request=\"if(event.detail.successful) payment_modal.close()\"><div class=\"form-control w-full\"><label class=\"label\"><span class=\"label-text\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var32 string
templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.modal.amount"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 202, Col: 75}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "</span></label> <input type=\"number\" step=\"0.01\" name=\"amount\" class=\"input input-bordered w-full\" required autofocus></div><div class=\"form-control w-full\"><label class=\"label\"><span class=\"label-text\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var33 string var templ_7745c5c3_Var33 string
templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.modal.method")) templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.modal.title"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 208, Col: 75} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 194, Col: 76}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "</span></label> <select name=\"paymentMethod\" class=\"select select-bordered w-full\" required><option value=\"\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "</h3><form class=\"py-4 space-y-4\" hx-post=\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var34 string var templ_7745c5c3_Var34 string
templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.modal.select_method")) templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(paymentUrl)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 211, Col: 74} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 197, Col: 24}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "</option> <option value=\"Cash\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "\" hx-target=\"#payment-lines\" hx-swap=\"outerHTML\" hx-on::after-request=\"if(event.detail.successful) payment_modal.close()\"><div class=\"form-control w-full\"><label class=\"label\"><span class=\"label-text\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var35 string var templ_7745c5c3_Var35 string
templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.method.cash")) templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.modal.amount"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 212, Col: 70} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 204, Col: 75}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "</option> <option value=\"Card\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "</span></label> <input type=\"number\" step=\"0.01\" name=\"amount\" class=\"input input-bordered w-full\" required autofocus></div><div class=\"form-control w-full\"><label class=\"label\"><span class=\"label-text\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var36 string var templ_7745c5c3_Var36 string
templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.method.card")) templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.modal.method"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 213, Col: 70} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 210, Col: 75}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "</option> <option value=\"Cheque\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "</span></label> <select name=\"paymentMethod\" class=\"select select-bordered w-full\" required><option value=\"\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var37 string var templ_7745c5c3_Var37 string
templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.method.cheque")) templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.modal.select_method"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 214, Col: 74} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 213, Col: 74}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var37)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var37))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</option> <option value=\"Transfer\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</option> <option value=\"Cash\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var38 string var templ_7745c5c3_Var38 string
templ_7745c5c3_Var38, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.method.transfer")) templ_7745c5c3_Var38, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.method.cash"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 215, Col: 78} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 214, Col: 70}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var38)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var38))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "</option></select></div><button type=\"submit\" class=\"btn btn-primary\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "</option> <option value=\"Card\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var39 string var templ_7745c5c3_Var39 string
templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.modal.submit")) templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.method.card"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 218, Col: 94} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 215, Col: 70}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var39)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var39))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "</button></form></div></dialog>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "</option> <option value=\"Cheque\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var40 string
templ_7745c5c3_Var40, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.method.cheque"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 216, Col: 74}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var40))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "</option> <option value=\"Transfer\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var41 string
templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.method.transfer"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 217, Col: 78}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var41))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "</option></select></div><button type=\"submit\" class=\"btn btn-primary\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var42 string
templ_7745c5c3_Var42, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.Localize(ctx, "payment.modal.submit"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/booking_by_id.templ`, Line: 220, Col: 94}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var42))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "</button></form></div></dialog>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

View file

@ -71,7 +71,7 @@ func run(ctx context.Context, appConfig *config.Config, appLogger *slog.Logger)
return fmt.Errorf("error starting pdf client %w", err) return fmt.Errorf("error starting pdf client %w", err)
} }
parsingClient := parser.NewBookingAgentParser() parsingClient := parser.NewBookingAgentParser(appConfig.OpenAIModel)
var stripeClient payment.StripeClient var stripeClient payment.StripeClient
if appConfig.StripeSecretKey != "" { if appConfig.StripeSecretKey != "" {