JetZig Transportation Management System project - view layer
Writing a view in Jetzig was very similar to writing views in other frameworks like Rails or Django.
The delivery_orders view manages DeliveryOrders, and inherits from the
main layout for templating by declaring a layout variable that Jetzig picks
up.
The main request object that Jetzig passes as a parameter to view functions,
includes a .repo field that is used to connect to the database and execute
queries (among other functions).
Index View
pub const layout = "main";
pub fn index(request: *jetzig.Request) !jetzig.View {
const delivery_orders = jetzig.database.Query(
.DeliveryOrder,
).include(
.pickup_location,
.{},
).include(
.dropoff_location,
.{},
).orderBy(
.{ .id = .descending },
).all(request.repo);
var root = try request.data(.object);
try root.put("delivery_orders", delivery_orders);
return request.render(.ok);
}
The main logic for the DeliveryOrders index template is just a table that we
iterate through all the delivery_orders results.
<h3>Delivery Orders</h3>
<a class="btn btn-primary" href="/delivery_orders/new" role="button">Create New Delivery Order</a>
<table id="delivery_orders" class="table table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Pickup Location</th>
<th scope="col">Dropoff Location</th>
<th scope="col">Created At</th>
<th scope="col">Updated At</th>
</tr>
</thead>
<tbody>
@for ($.delivery_orders) |order| {
<tr>
<td scope="row"><a href="/delivery_orders/{{order.id}}">{{order.id}}</a></td>
<td><a href="/locations/{{order.pickup_location_id}}">{{order.pickup_location.name}}</a></td>
<td><a href="/locations/{{order.dropoff_location_id}}">{{order.dropoff_location.name}}</a></td>
<td>{{order.created_at}}</td>
<td>{{order.updated_at}}</td>
</tr>
}
</tbody>
</table>
Detail view
The get is very similar to the index but focuses on a single DeliveryOrder
and fetches related objects via foreign key. All the containers in the database
are also retrieved, in order for additional containers to be added to a
DeliveryOrder after it has been created.
pub fn get(id: []const u8, request: *jetzig.Request) !jetzig.View {
var root = try request.data(.object);
const delivery_order = jetzig.database.Query(
.DeliveryOrder,
).include(
.pickup_location,
.{},
).include(
.dropoff_location,
.{},
).find(
id,
).execute(
request.repo,
);
const delivery_order_containers = jetzig.database.Query(
.DeliveryOrderContainer,
).where(
.{ .delivery_order_id = id },
).all(
request.repo,
);
const containers = jetzig.database.Query(.Container).all(request.repo);
const attachments = jetzig.database.Query(.Attachment).where(
.{ .delivery_order_id = id },
).all(
request.repo,
);
try root.put("delivery_order", delivery_order);
try root.put("delivery_order_containers", delivery_order_containers);
try root.put("containers", containers);
try root.put("attachments", attachments);
return request.render(.ok);
}
<span><h2>Delivery Order {{.delivery_order.id}}</h2></span>
<div class="row">
<div class="col">
<h3>Pickup</h3>
<input type="hidden" id="from_location_lat" value="{{.delivery_order.pickup_location.lat}}">
<input type="hidden" id="from_location_lon" value="{{.delivery_order.pickup_location.lon}}">
<p><h5>Location Name:</h5></p>
<p>{{.delivery_order.pickup_location.name }}</p>
<p><h5>Address:</h5></p>
<p>{{.delivery_order.pickup_location.address }}</p>
</div>
<div class="col">
<h3>Dropoff</h3>
<input type="hidden" id="to_location_lat" value="{{.delivery_order.dropoff_location.lat}}">
<input type="hidden" id="to_location_lon" value="{{.delivery_order.dropoff_location.lon}}">
<p><h5>Location Name:</h5></p>
<p>{{.delivery_order.dropoff_location.name }}</p>
<p><h5>Address:</h5></p>
<p>{{.delivery_order.dropoff_location.address }}</p>
</div>
</div>
<div id="map" style="height: 400px;">
</div>
<div>
<h2>Documents</h2>
<table id="attachments" class="table table-striped">
<thead>
<tr>
<th scope="col"></th>
</tr>
</thead>
<tbody>
@for ($.attachments) |attachment| {
<tr>
<td><embed src="{{attachment.url}}" /></td>
</tr>
}
</tbody>
</table>
</div>
<h5>Add Document to Delivery Order</h5>
<form class="row g-3" action="/attachments" method="POST" id="attachments">
<div class="col-md-6">
<input type="hidden" name="delivery_order" value="{{.delivery_order.id}}">
<label for="attachment" class="form-label">Upload document</label>
<input class="form-control" type="file" name="attachment">
<input class="form-control form-control-lg" type="submit" value="Upload">
</div>
</form>
<div>
<h2>Containers</h2>
<table id="containers" class="table table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
</tr>
</thead>
<tbody>
@for ($.delivery_order_containers) |container| {
<tr>
<td scope="row"><a href="/containers/{{container.id}}">{{container.id}}</a></td>
<td>{{container.container_number}}</td>
</tr>
}
</tbody>
</table>
</div>
<div>
<h5>Add Container to Delivery Order</h5>
<form class="row g-3" action="/delivery_orders_containers" method="POST" id="delivery_order">
@partial partials/datalist_from_objects($.containers, "containerOptions")
<div class="col-md-6">
<label for="containerInput" class="form-label">Container</label>
<input class="form-control" list="containerOptions" name="containerInput" placeholder="Type to search...">
<input type="hidden" name="delivery_order" value="{{.delivery_order.id}}">
<input type="submit" class="form-control" value="Save">
</div>
</form>
</div>