015
This commit is contained in:
@@ -4,13 +4,12 @@ import veb
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
@['/controller/booking/create'; post]
|
@['/controller/booking/create'; post]
|
||||||
pub fn (mut app App) controller_create_booking(mut ctx Context, to string, from string, name string, price int, status string, departure string) veb.Result {
|
pub fn (mut app App) controller_create_booking(mut ctx Context, to string, from string, name string, price int, departure string) veb.Result {
|
||||||
fields := {
|
fields := {
|
||||||
'to': to
|
'to': to
|
||||||
'from': from
|
'from': from
|
||||||
'name': name
|
'name': name
|
||||||
'price': price.str()
|
'price': price.str()
|
||||||
'status': status
|
|
||||||
'departure': departure
|
'departure': departure
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,26 +21,93 @@ pub fn (mut app App) controller_create_booking(mut ctx Context, to string, from
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If any fields are empty, return field-specific error messages
|
||||||
|
if empty_fields.len > 0 {
|
||||||
|
mut response := '<script>'
|
||||||
|
|
||||||
|
// Reset all field errors first
|
||||||
|
response += 'document.querySelectorAll(".text-danger").forEach(el => el.textContent = "");'
|
||||||
|
response += 'document.querySelectorAll("input, select").forEach(el => el.classList.remove("input-error"));'
|
||||||
|
|
||||||
|
// Set error for each empty field
|
||||||
|
for field in empty_fields {
|
||||||
|
response += 'document.querySelector(".' + field + '-error").textContent = "(Required)";'
|
||||||
|
response += 'document.querySelector("[name=' + field +
|
||||||
|
']").classList.add("input-error");'
|
||||||
|
}
|
||||||
|
|
||||||
|
response += '</script>'
|
||||||
|
response += '<div class="alert alert-danger">Please fill in all required fields</div>'
|
||||||
|
|
||||||
|
return ctx.html(response)
|
||||||
|
}
|
||||||
|
|
||||||
user_token := ctx.get_cookie('token') or { '' }
|
user_token := ctx.get_cookie('token') or { '' }
|
||||||
token := app.auth.find_token(user_token) or { return ctx.text('User not logged in') }
|
token := app.auth.find_token(user_token) or {
|
||||||
|
return ctx.html('<div class="alert alert-danger">User not logged in. Please <a href="/login">login</a> to continue.</div>')
|
||||||
|
}
|
||||||
|
|
||||||
if token.user_id == 0 {
|
if token.user_id == 0 {
|
||||||
return ctx.text('User not logged in')
|
return ctx.html('<div class="alert alert-danger">User not logged in. Please <a href="/login">login</a> to continue.</div>')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse with specific format
|
// Parse with specific format
|
||||||
departure_time := time.parse_format(departure, 'YYYY-MM-DD') or {
|
departure_time := time.parse_format(departure, 'YYYY-MM-DD') or {
|
||||||
println('Parse error: ${err}')
|
println('Parse error: ${err}')
|
||||||
return ctx.text('Invalid departure time format.')
|
return ctx.html('<div class="alert alert-danger">Invalid departure date format. Please use YYYY-MM-DD format.</div>')
|
||||||
}
|
}
|
||||||
|
|
||||||
flight := app.service_add_flight(from, to, departure_time, price) or {
|
flight := app.service_add_flight(from, to, departure_time, price) or {
|
||||||
return ctx.text('Flight not added')
|
return ctx.html('<div class="alert alert-danger">Error creating flight: ${err}</div>')
|
||||||
}
|
}
|
||||||
|
|
||||||
app.service_add_booking(name, token.user_id, flight.id, status) or {
|
app.service_add_booking(name, token.user_id, flight.id) or {
|
||||||
return ctx.text('Booking not added')
|
return ctx.html('<div class="alert alert-danger">Error creating booking: ${err}</div>')
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx.text('Booking created')
|
// Return success message with HTML
|
||||||
|
success_html := '<div class="alert alert-success">
|
||||||
|
<h4>Booking created successfully!</h4>
|
||||||
|
<p>Your flight from ${from} to ${to} has been booked.</p>
|
||||||
|
<p>Passenger: ${name}</p>
|
||||||
|
<a href="/" class="btn btn-primary mt-3">Return to Home</a>
|
||||||
|
</div>'
|
||||||
|
|
||||||
|
return ctx.html(success_html)
|
||||||
|
}
|
||||||
|
|
||||||
|
@['/controller/booking/user']
|
||||||
|
pub fn (app &App) controller_get_user_bookings(mut ctx Context) veb.Result {
|
||||||
|
user_token := ctx.get_cookie('token') or { '' }
|
||||||
|
token := app.auth.find_token(user_token) or {
|
||||||
|
return ctx.html('<div class="alert alert-danger">User not logged in. Please <a href="/login">login</a> to continue.</div>')
|
||||||
|
}
|
||||||
|
|
||||||
|
if token.user_id == 0 {
|
||||||
|
return ctx.html('<div class="alert alert-danger">User not logged in. Please <a href="/login">login</a> to continue.</div>')
|
||||||
|
}
|
||||||
|
|
||||||
|
bookings := app.service_get_user_bookings(token.user_id) or {
|
||||||
|
return ctx.html('<div class="alert alert-danger">Error fetching bookings: ${err}</div>')
|
||||||
|
}
|
||||||
|
|
||||||
|
mut html := ''
|
||||||
|
for booking in bookings {
|
||||||
|
flight := app.service_get_flight(booking.flight_id) or { continue }
|
||||||
|
|
||||||
|
html += '<div class="alert alert-info">
|
||||||
|
<h4>Booking ID: ${booking.id}</h4>
|
||||||
|
<p>Flight from ${flight.from} to ${flight.to}</p>
|
||||||
|
<p>Departure: ${flight.departure.format()}</p>
|
||||||
|
<p>Passenger: ${booking.name}</p>
|
||||||
|
<p>Status: ${booking.status}</p>
|
||||||
|
<a href="/controller/booking/delete/${booking.id}" class="btn btn-danger">Delete</a>
|
||||||
|
</div>'
|
||||||
|
}
|
||||||
|
|
||||||
|
if html == '' {
|
||||||
|
html = '<div class="alert alert-info">No bookings found</div>'
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.html(html)
|
||||||
}
|
}
|
||||||
|
@@ -2,12 +2,12 @@ module main
|
|||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
fn (app &App) service_add_booking(name string, user_id int, flight_id int, status string) ! {
|
fn (app &App) service_add_booking(name string, user_id int, flight_id int) ! {
|
||||||
booking := Booking{
|
booking := Booking{
|
||||||
name: name
|
name: name
|
||||||
user_id: user_id
|
user_id: user_id
|
||||||
flight_id: flight_id
|
flight_id: flight_id
|
||||||
status: status
|
status: 'conformed'
|
||||||
created_at: time.now()
|
created_at: time.now()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15,3 +15,11 @@ fn (app &App) service_add_booking(name string, user_id int, flight_id int, statu
|
|||||||
insert booking into Booking
|
insert booking into Booking
|
||||||
}!
|
}!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (app &App) service_get_user_bookings(user_id int) ![]Booking {
|
||||||
|
bookings := sql app.db {
|
||||||
|
select from Booking where user_id == user_id order by created_at desc
|
||||||
|
}!
|
||||||
|
|
||||||
|
return bookings
|
||||||
|
}
|
||||||
|
7
src/booking_view.v
Normal file
7
src/booking_view.v
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
import veb
|
||||||
|
|
||||||
|
pub fn (app &App) booking(mut ctx Context) veb.Result {
|
||||||
|
return $veb.html()
|
||||||
|
}
|
@@ -23,3 +23,11 @@ fn (app &App) service_add_flight(from string, to string, departure time.Time, pr
|
|||||||
|
|
||||||
return flight[0]
|
return flight[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (app &App) service_get_flight(id int) !Flight {
|
||||||
|
flight := sql app.db {
|
||||||
|
select from Flight where id == id
|
||||||
|
}!
|
||||||
|
|
||||||
|
return flight[0]
|
||||||
|
}
|
||||||
|
147
src/templates/booking.html
Normal file
147
src/templates/booking.html
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
@include 'header.html'
|
||||||
|
|
||||||
|
<div class="container mt-5">
|
||||||
|
<header class="text-center mb-4">
|
||||||
|
<h1>Create New Booking</h1>
|
||||||
|
<p>Book your next flight with us</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card shadow">
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<form
|
||||||
|
id="booking-form"
|
||||||
|
hx-trigger="submit"
|
||||||
|
hx-post="/controller/booking/create"
|
||||||
|
hx-target="#form-response"
|
||||||
|
hx-swap="innerHTML"
|
||||||
|
hx-indicator="#form-spinner"
|
||||||
|
>
|
||||||
|
<!-- Response container at the top of the form -->
|
||||||
|
<div id="form-response"></div>
|
||||||
|
|
||||||
|
<!-- Loading indicator -->
|
||||||
|
<div
|
||||||
|
id="form-spinner"
|
||||||
|
class="htmx-indicator"
|
||||||
|
style="display: none"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="spinner-border text-primary"
|
||||||
|
role="status"
|
||||||
|
>
|
||||||
|
<span class="visually-hidden">Loading...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="from" class="form-label"
|
||||||
|
>From
|
||||||
|
<span class="text-danger from-error"></span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="from"
|
||||||
|
name="from"
|
||||||
|
placeholder="Departure city"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="to" class="form-label"
|
||||||
|
>To
|
||||||
|
<span class="text-danger to-error"></span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="to"
|
||||||
|
name="to"
|
||||||
|
placeholder="Arrival city"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="name" class="form-label"
|
||||||
|
>Passenger Name
|
||||||
|
<span class="text-danger name-error"></span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="name"
|
||||||
|
name="name"
|
||||||
|
placeholder="Enter passenger name"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="price" class="form-label"
|
||||||
|
>Price
|
||||||
|
<span
|
||||||
|
class="text-danger price-error"
|
||||||
|
></span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
class="form-control"
|
||||||
|
id="price"
|
||||||
|
name="price"
|
||||||
|
placeholder="Enter price"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="departure" class="form-label">
|
||||||
|
Departure Date & Time
|
||||||
|
<span
|
||||||
|
class="text-danger departure-error"
|
||||||
|
></span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="datetime-local"
|
||||||
|
class="form-control"
|
||||||
|
id="departure"
|
||||||
|
name="departure"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="status" class="form-label"
|
||||||
|
>Status
|
||||||
|
<span
|
||||||
|
class="text-danger status-error"
|
||||||
|
></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-grid gap-2">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-primary btn-lg"
|
||||||
|
>
|
||||||
|
Create Booking
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.htmx-request .htmx-indicator {
|
||||||
|
display: inline-block !important;
|
||||||
|
}
|
||||||
|
.input-error {
|
||||||
|
border-color: #dc3545;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
@include 'footer.html'
|
@@ -1,35 +1,46 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Air Bookings</title>
|
<title>Air Bookings</title>
|
||||||
@css '/static/css/bootstrap.css'
|
@css '/static/css/bootstrap.css'
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css">
|
<link
|
||||||
</head>
|
rel="stylesheet"
|
||||||
<body>
|
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css"
|
||||||
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
|
/>
|
||||||
<div class="container">
|
@js 'https://unpkg.com/htmx.org@2.0.4'
|
||||||
<a class="navbar-brand" href="/">Air Bookings</a>
|
</head>
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
<body>
|
||||||
<span class="navbar-toggler-icon"></span>
|
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
|
||||||
</button>
|
<div class="container">
|
||||||
<div class="collapse navbar-collapse" id="navbarNav">
|
<a class="navbar-brand" href="/">Air Bookings</a>
|
||||||
<ul class="navbar-nav ms-auto">
|
<button
|
||||||
<li class="nav-item">
|
class="navbar-toggler"
|
||||||
<a class="nav-link" href="/">Home</a>
|
type="button"
|
||||||
</li>
|
data-bs-toggle="collapse"
|
||||||
<li class="nav-item">
|
data-bs-target="#navbarNav"
|
||||||
<a class="nav-link" href="/profile">Profile</a>
|
>
|
||||||
</li>
|
<span class="navbar-toggler-icon"></span>
|
||||||
<li class="nav-item">
|
</button>
|
||||||
<a class="nav-link" href="/login">Login</a>
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
</li>
|
<ul class="navbar-nav ms-auto">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="/signup">Sign Up</a>
|
<a class="nav-link" href="/">Home</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/profile">Profile</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/login">Login</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/signup">Sign Up</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</nav>
|
||||||
</nav>
|
<main></main>
|
||||||
<main>
|
</body>
|
||||||
|
</html>
|
||||||
|
@@ -11,7 +11,10 @@
|
|||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<h4>@{user.first_name} @{user.last_name}</h4>
|
<h4>@{user.first_name} @{user.last_name}</h4>
|
||||||
<p><i class="bi bi-envelope"></i> @{user.email}</p>
|
<p><i class="bi bi-envelope"></i> @{user.email}</p>
|
||||||
<p><i class="bi bi-gender-ambiguous"></i> @{user.gender}</p>
|
<p>
|
||||||
|
<i class="bi bi-gender-ambiguous"></i>
|
||||||
|
@{user.gender}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
@@ -19,29 +22,71 @@
|
|||||||
<h5>Update Profile</h5>
|
<h5>Update Profile</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form action="/controller/user/update" method="post">
|
<form
|
||||||
<input type="hidden" name="id" value="@{user.id}">
|
action="/controller/user/update"
|
||||||
|
method="post"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
name="id"
|
||||||
|
value="@{user.id}"
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="first_name" class="form-label">First Name</label>
|
<label for="first_name" class="form-label"
|
||||||
<input type="text" class="form-control" id="first_name" name="first_name" value="@{user.first_name}">
|
>First Name</label
|
||||||
<div class="text-danger first_name-error field-error"></div>
|
>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="first_name"
|
||||||
|
name="first_name"
|
||||||
|
value="@{user.first_name}"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="text-danger first_name-error field-error"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="last_name" class="form-label">Last Name</label>
|
<label for="last_name" class="form-label"
|
||||||
<input type="text" class="form-control" id="last_name" name="last_name" value="@{user.last_name}">
|
>Last Name</label
|
||||||
<div class="text-danger last_name-error field-error"></div>
|
>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="last_name"
|
||||||
|
name="last_name"
|
||||||
|
value="@{user.last_name}"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="text-danger last_name-error field-error"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="password" class="form-label">New Password (leave empty to keep current)</label>
|
<label for="password" class="form-label"
|
||||||
<input type="password" class="form-control" id="password" name="password">
|
>New Password (leave empty to keep
|
||||||
<div class="text-danger password-error field-error"></div>
|
current)</label
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
class="form-control"
|
||||||
|
id="password"
|
||||||
|
name="password"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="text-danger password-error field-error"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="d-grid">
|
<div class="d-grid">
|
||||||
<button type="submit" class="btn btn-primary">Update Profile</button>
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-primary"
|
||||||
|
>
|
||||||
|
Update Profile
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -53,7 +98,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="d-grid gap-2">
|
<div class="d-grid gap-2">
|
||||||
<a href="/logout" class="btn btn-danger">Logout</a>
|
<a href="/logout" class="btn btn-danger"
|
||||||
|
>Logout</a
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -75,11 +122,53 @@
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
body: formData,
|
body: formData,
|
||||||
})
|
})
|
||||||
.then((response) => response.text())
|
.then((response) => response.text())
|
||||||
.then((html) => {
|
.then((html) => {
|
||||||
document.getElementById("response-container").innerHTML = html;
|
document.getElementById("response-container").innerHTML = html;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@include 'footer.html'
|
<div class="card mt-4">
|
||||||
|
<div class="card-header">
|
||||||
|
<h5>My Bookings</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
@if bookings.len > 0
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>From</th>
|
||||||
|
<th>To</th>
|
||||||
|
<th>Departure</th>
|
||||||
|
<th>Price</th>
|
||||||
|
<th>Status</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@for flight in flights
|
||||||
|
<tr>
|
||||||
|
<td>@{flight.from}</td>
|
||||||
|
<td>@{flight.to}</td>
|
||||||
|
<td>@{flight.departure}</td>
|
||||||
|
<td>$@{flight.price}</td>
|
||||||
|
<td>
|
||||||
|
@if flight.bookings[0].status == 'confirmed'
|
||||||
|
<span class="badge bg-success">Confirmed</span>
|
||||||
|
@else
|
||||||
|
<span class="badge bg-warning">Pending</span>
|
||||||
|
@end
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@end
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<p class="text-center text-muted">No bookings found</p>
|
||||||
|
@end
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@include 'footer.html'
|
||||||
|
@@ -33,6 +33,13 @@ pub fn (app &App) profile(mut ctx Context) veb.Result {
|
|||||||
}
|
}
|
||||||
|
|
||||||
user := app.service_get_user(token.user_id) or { return ctx.redirect('/login') }
|
user := app.service_get_user(token.user_id) or { return ctx.redirect('/login') }
|
||||||
|
bookings := app.service_get_user_bookings(token.user_id) or { []Booking{} }
|
||||||
|
|
||||||
|
mut flights := []Flight{}
|
||||||
|
for booking in bookings {
|
||||||
|
flight := app.service_get_flight(booking.flight_id) or { continue }
|
||||||
|
flights << flight
|
||||||
|
}
|
||||||
|
|
||||||
return $veb.html()
|
return $veb.html()
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user