aboutsummaryrefslogtreecommitdiffstats
path: root/src/web/web.zig
diff options
context:
space:
mode:
authorsadbeast <sadbeast@sadbeast.com>2024-06-23 15:36:59 -0700
committersadbeast <sadbeast@sadbeast.com>2024-07-13 21:58:23 -0700
commit8d018d996c1eddb882dc64ebbd228bb0135944f3 (patch)
treed01956546a77dbae33357c9a5d174f511ac9b282 /src/web/web.zig
downloadteamdraft-8d018d996c1eddb882dc64ebbd228bb0135944f3.tar.gz
teamdraft-8d018d996c1eddb882dc64ebbd228bb0135944f3.tar.bz2
Diffstat (limited to 'src/web/web.zig')
-rw-r--r--src/web/web.zig109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/web/web.zig b/src/web/web.zig
new file mode 100644
index 0000000..184a1a3
--- /dev/null
+++ b/src/web/web.zig
@@ -0,0 +1,109 @@
+pub const Templates = std.StringHashMap(Template);
+
+pub var templates: Templates = undefined;
+
+pub fn start(app: *App) !void {
+ const allocator = app.allocator;
+
+ var server = try httpz.ServerCtx(*const Dispatcher, *Env).init(allocator, .{
+ .address = "0.0.0.0",
+ .port = 5882,
+ }, undefined);
+ defer server.deinit();
+
+ templates = Templates.init(allocator);
+ defer {
+ var it = templates.valueIterator();
+ while (it.next()) |t| {
+ t.deinit(allocator);
+ }
+ templates.deinit();
+ }
+
+ inline for (config.templates) |template| {
+ try templates.put(template, try loadTemplate(allocator, template));
+ }
+
+ server.dispatcher(Dispatcher.dispatch);
+
+ var router = server.router();
+ {
+ var routes = router.group("", .{ .ctx = &Dispatcher{ .app = app } });
+ routes.get("/", index);
+ routes.get("/about", about);
+ routes.get("/drafts/:id", @import("drafts/show.zig").handler);
+ routes.get("/drafts/:id/pick", @import("drafts/pick.zig").handler);
+ routes.get("/leagues/:id", @import("leagues/show.zig").handler);
+ routes.post("/leagues", @import("leagues/create.zig").handler);
+ routes.get("/invites/:id", @import("leagues/invite.zig").handler);
+ }
+
+ // use get/post/put/head/patch/options/delete
+ // you can also use "all" to attach to all methods
+
+ // start the server in the current thread, blocking.
+ try server.listen();
+}
+
+fn pick(_: *Env, req: *httpz.Request, res: *httpz.Response) !void {
+ try render("pick", req, res);
+}
+
+fn about(_: *Env, req: *httpz.Request, res: *httpz.Response) !void {
+ // try render(templates.get("about").?, req, res);
+ try renderWithData("about", .{ .title = "foo" }, req, res);
+}
+
+fn index(_: *Env, req: *httpz.Request, res: *httpz.Response) !void {
+ try render("index", req, res);
+}
+
+fn loadTemplate(allocator: std.mem.Allocator, comptime template_name: []const u8) !Template {
+ return switch (try mustache.parseText(allocator, @embedFile("../views/" ++ template_name ++ ".mustache"), .{}, .{ .copy_strings = false })) {
+ .success => |t| t,
+ .parse_error => @panic("layout parse error"),
+ };
+}
+
+fn loadTemplateFile(allocator: std.mem.Allocator, template_name: []const u8) !Template {
+ const file = std.fs.cwd().openFile(try std.fmt.allocPrint(allocator, "src/views/{s}.mustache", .{template_name}), .{}) catch @panic("could not find template");
+ defer file.close();
+ const template_bytes = file.readToEndAlloc(allocator, std.math.maxInt(usize)) catch @panic("couldn't read template file ");
+
+ return switch (try mustache.parseText(allocator, template_bytes, .{}, .{ .copy_strings = false })) {
+ .success => |t| t,
+ .parse_error => @panic("layout parse error"),
+ };
+}
+
+pub fn renderWithDataPartials(template_name: []const u8, partials: anytype, data: anytype, req: *httpz.Request, res: *httpz.Response) !void {
+ var template: Template = undefined;
+ if (config.dev) {
+ template = try loadTemplateFile(res.arena, template_name);
+ } else {
+ template = templates.get(template_name).?;
+ }
+ const content = try mustache.allocRenderPartials(res.arena, template, partials, data);
+ if (req.header("hx-request")) |_| {
+ res.body = content;
+ } else {
+ res.body = try mustache.allocRender(res.arena, templates.get("layout").?, .{ .content = content });
+ }
+}
+
+pub fn renderWithData(template_name: []const u8, data: anytype, req: *httpz.Request, res: *httpz.Response) !void {
+ try renderWithDataPartials(template_name, .{}, data, req, res);
+}
+
+pub fn render(template_name: []const u8, req: *httpz.Request, res: *httpz.Response) !void {
+ try renderWithData(template_name, .{}, req, res);
+}
+
+const config = @import("config");
+const App = @import("../app.zig").App;
+const Env = @import("../env.zig").Env;
+const httpz = @import("httpz");
+const mustache = @import("mustache");
+const Template = mustache.Template;
+const std = @import("std");
+const Dispatcher = @import("dispatcher.zig").Dispatcher;