defmodule Localiser.Web.Controllers.RoomController do use Phoenix.Controller, formats: [:json] use OpenApiSpex.ControllerSpecs alias Localiser.Domain.Rooms alias Localiser.Web.Schemas tags ["Rooms"] security [%{"bearerAuth" => []}] operation :index, summary: "List rooms for a floor", parameters: [floor_id: [in: :path, type: :integer, required: true]], responses: [ ok: {"Room list", "application/json", %OpenApiSpex.Schema{type: :array, items: Schemas.Room}}, unauthorized: {"Unauthorized", "application/json", Schemas.Error} ] operation :show, summary: "Get a room", parameters: [ floor_id: [in: :path, type: :integer, required: true], id: [in: :path, type: :integer, required: true] ], responses: [ ok: {"Room", "application/json", Schemas.Room}, unauthorized: {"Unauthorized", "application/json", Schemas.Error} ] operation :create, summary: "Create a room", parameters: [floor_id: [in: :path, type: :integer, required: true]], request_body: {"Room params", "application/json", Schemas.RoomParams, required: true}, responses: [ created: {"Created room", "application/json", Schemas.Room}, unauthorized: {"Unauthorized", "application/json", Schemas.Error}, unprocessable_entity: {"Validation errors", "application/json", Schemas.ValidationErrors} ] operation :update, summary: "Update a room", parameters: [ floor_id: [in: :path, type: :integer, required: true], id: [in: :path, type: :integer, required: true] ], request_body: {"Room params", "application/json", Schemas.RoomUpdateParams}, responses: [ ok: {"Updated room", "application/json", Schemas.Room}, unauthorized: {"Unauthorized", "application/json", Schemas.Error}, unprocessable_entity: {"Validation errors", "application/json", Schemas.ValidationErrors} ] operation :delete, summary: "Delete a room (also unenrols sensors)", parameters: [ floor_id: [in: :path, type: :integer, required: true], id: [in: :path, type: :integer, required: true] ], responses: [ no_content: "Deleted", unauthorized: {"Unauthorized", "application/json", Schemas.Error} ] def index(conn, %{"floor_id" => floor_id}) do rooms = Rooms.list_rooms_for_floor(floor_id) json(conn, Enum.map(rooms, &render_room/1)) end def show(conn, %{"id" => id}) do room = Rooms.get_room!(id) json(conn, render_room(room)) end def create(conn, %{"floor_id" => floor_id} = params) do attrs = Map.put(params, "floor_id", floor_id) case Rooms.create_room(attrs) do {:ok, room} -> conn |> put_status(:created) |> json(render_room(room)) {:error, changeset} -> conn |> put_status(:unprocessable_entity) |> json(%{errors: format_errors(changeset)}) end end def update(conn, %{"id" => id} = params) do room = Rooms.get_room!(id) attrs = Map.drop(params, ["id", "floor_id"]) case Rooms.update_room(room, attrs) do {:ok, updated} -> json(conn, render_room(updated)) {:error, changeset} -> conn |> put_status(:unprocessable_entity) |> json(%{errors: format_errors(changeset)}) end end def delete(conn, %{"id" => id}) do room = Rooms.get_room!(id) {:ok, _} = Rooms.delete_room(room) send_resp(conn, :no_content, "") end defp render_room(room) do %{ id: room.id, name: room.name, floor_id: room.floor_id, x: room.x, y: room.y, width: room.width, height: room.height } end defp format_errors(changeset) do Ecto.Changeset.traverse_errors(changeset, fn {msg, opts} -> Enum.reduce(opts, msg, fn {key, val}, acc -> String.replace(acc, "%{#{key}}", to_string(val)) end) end) end end