From a0826ce054d7468444c67306191cc7e2fe734eb0 Mon Sep 17 00:00:00 2001 From: physcik Date: Tue, 14 Apr 2026 18:27:22 +0500 Subject: ranged weapons CRUD --- backend/src/API/ErrorDescription.zig | 3 + backend/src/API/WeaponsAPI.zig | 49 +++++++++++++-- backend/src/Database/Connection.zig | 1 + backend/src/Database/RangedWeaponsAccessLayer.zig | 74 +++++++++++++++++++++++ 4 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 backend/src/API/ErrorDescription.zig (limited to 'backend/src') diff --git a/backend/src/API/ErrorDescription.zig b/backend/src/API/ErrorDescription.zig new file mode 100644 index 0000000..922eb6f --- /dev/null +++ b/backend/src/API/ErrorDescription.zig @@ -0,0 +1,3 @@ +pub const ErrorDescriptor = struct { + Message: []const u8 +}; diff --git a/backend/src/API/WeaponsAPI.zig b/backend/src/API/WeaponsAPI.zig index d095944..1b0ae00 100644 --- a/backend/src/API/WeaponsAPI.zig +++ b/backend/src/API/WeaponsAPI.zig @@ -2,12 +2,15 @@ const std = @import("std"); const httpz = @import("httpz"); const model = @import("../Models/RangedWeapon.zig"); const db = @import("../Database/Connection.zig"); +const errDesc = @import("ErrorDescription.zig"); pub fn RegisterEndpoints(router: *httpz.Router(void, *const fn (*httpz.request.Request, *httpz.response.Response) anyerror!void)) void { router.get("/weapons", testEndpoint, .{}); + router.get("/weapons/ranged", getAllRangedWeapons, .{}); router.post("/weapons/ranged", newRangedWeapon, .{}); router.get("/weapons/ranged/:id", getRangedWeaponById, .{}); - router.get("/weapons/ranged", getAllRangedWeapons, .{}); + router.put("/weapons/ranged/:id", updateRangedWeapon, .{}); + router.delete("/weapons/ranged/:id", deleteRangedWeapon, .{}); } fn testEndpoint(_: *httpz.Request, res: *httpz.Response) !void { @@ -57,9 +60,45 @@ fn getRangedWeaponById(req: *httpz.Request, res: *httpz.Response) !void { } fn newRangedWeapon(req: *httpz.Request, res: *httpz.Response) !void { - if (try req.json(model.RangedWeaponType)) |new| { - try res.json(new, .{}); + var body = try req.json(model.RangedWeaponType) orelse { + res.status = 400; + return; + }; + + db.RangedWeapons.Create(&body) catch |err| { + if (err == db.ResultErrors.AlreadyExists) { + res.status = 400; + try res.json(errDesc.ErrorDescriptor { + .Message = "A weapon with that ID already exists" + }, .{}); + return; + } + return err; + }; + + res.status = 201; +} + + +fn updateRangedWeapon(req: *httpz.Request, res: *httpz.Response) !void { + const id = req.param("id") orelse { + res.status = 400; + return; + }; + + var body = try req.json(model.RangedWeaponType) orelse { + res.status = 400; + return; + }; + + try db.RangedWeapons.Update(id, &body); +} + +fn deleteRangedWeapon(req: *httpz.Request, res: *httpz.Response) !void { + const id = req.param("id") orelse { + res.status = 400; return; - } - res.status = 502; + }; + + try db.RangedWeapons.Delete(id); } diff --git a/backend/src/Database/Connection.zig b/backend/src/Database/Connection.zig index 623165f..e08760c 100644 --- a/backend/src/Database/Connection.zig +++ b/backend/src/Database/Connection.zig @@ -4,6 +4,7 @@ const dotenv = @import("dotenv"); pub const ResultErrors = error { NotFound, + AlreadyExists }; pub var pool: *pg.Pool = undefined; diff --git a/backend/src/Database/RangedWeaponsAccessLayer.zig b/backend/src/Database/RangedWeaponsAccessLayer.zig index ca41197..ff75244 100644 --- a/backend/src/Database/RangedWeaponsAccessLayer.zig +++ b/backend/src/Database/RangedWeaponsAccessLayer.zig @@ -29,3 +29,77 @@ pub fn GetByDisplayName(allocator: std.mem.Allocator, displayName: []const u8) ! try row.deinit(); return outp; } + +pub fn Update(displayName: []const u8, updatedModel: *model.RangedWeaponType) !void { + const query = + \\ UPDATE RangedWeapons SET + \\ id = $1, + \\ name = $2, + \\ weapon_type = $3, + \\ accuracy = $4, + \\ concealability = $5, + \\ availability = $6, + \\ damage = $7, + \\ ammunition = $8, + \\ number_of_shots = $9, + \\ rate_of_fire = $10, + \\ reliability = $11, + \\ updated_at = CURRENT_TIMESTAMP + \\ WHERE id = $12 + ; + + _ = try conn.pool.exec(query, .{ + updatedModel.Id, + updatedModel.Name, + updatedModel.WeaponType, + updatedModel.Accuracy, + updatedModel.Concealability, + updatedModel.Avaliability, + updatedModel.Damage, + updatedModel.Ammunition, + updatedModel.NumberOfShots, + updatedModel.RateOfFire, + updatedModel.Reliability, + displayName, + }); +} + +pub fn Create(NewWeapon: *model.RangedWeaponType) !void { + if (try Exists(NewWeapon.Id)) return conn.ResultErrors.AlreadyExists; + const query = + \\ INSERT INTO RangedWeapons + \\ (id, name, weapon_type, accuracy, concealability, availability, damage, ammunition, number_of_shots, rate_of_fire, reliability) + \\ VALUES + \\ ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) + ; + + _ = try conn.pool.exec(query, .{ + NewWeapon.Id, + NewWeapon.Name, + NewWeapon.WeaponType, + NewWeapon.Accuracy, + NewWeapon.Concealability, + NewWeapon.Avaliability, + NewWeapon.Damage, + NewWeapon.Ammunition, + NewWeapon.NumberOfShots, + NewWeapon.RateOfFire, + NewWeapon.Reliability, + }); +} + +pub fn Exists(displayName: []const u8) !bool { + const query = "SELECT Id FROM RangedWeapons WHERE Id = $1"; + var row = try conn.pool.row(query, .{displayName}) orelse { + return false; + }; + try row.deinit(); + return true; +} + +pub fn Delete(displayName: []const u8) !void { + const query = "DELETE FROM RangedWeapons WHERE Id = $1"; + _ = try conn.pool.exec(query, .{ + displayName, + }); +} -- cgit v1.3