defmodule Localiser.Web.Schemas do alias OpenApiSpex.Schema defmodule User do require OpenApiSpex OpenApiSpex.schema(%{ title: "User", type: :object, properties: %{ id: %Schema{type: :integer}, username: %Schema{type: :string}, is_admin: %Schema{type: :boolean} }, required: [:id, :username, :is_admin] }) end defmodule Floor do require OpenApiSpex OpenApiSpex.schema(%{ title: "Floor", type: :object, properties: %{ id: %Schema{type: :integer}, name: %Schema{type: :string}, width: %Schema{type: :number, format: :float}, height: %Schema{type: :number, format: :float} }, required: [:id, :name, :width, :height] }) end defmodule Room do require OpenApiSpex OpenApiSpex.schema(%{ title: "Room", type: :object, properties: %{ id: %Schema{type: :integer}, name: %Schema{type: :string}, floor_id: %Schema{type: :integer}, x: %Schema{type: :number, format: :float}, y: %Schema{type: :number, format: :float}, width: %Schema{type: :number, format: :float}, height: %Schema{type: :number, format: :float} }, required: [:id, :name, :floor_id, :x, :y, :width, :height] }) end defmodule Sensor do require OpenApiSpex OpenApiSpex.schema(%{ title: "Sensor", type: :object, properties: %{ id: %Schema{type: :integer}, sensor_id: %Schema{type: :string}, confirmed: %Schema{type: :boolean}, room_id: %Schema{type: :integer, nullable: true}, floor_x: %Schema{type: :number, format: :float, nullable: true}, floor_y: %Schema{type: :number, format: :float, nullable: true}, rssi_ref: %Schema{type: :number, format: :float, nullable: true} }, required: [:id, :sensor_id, :confirmed] }) end defmodule Tag do require OpenApiSpex OpenApiSpex.schema(%{ title: "Tag", type: :object, properties: %{ id: %Schema{type: :integer}, tag_id: %Schema{type: :string}, name: %Schema{type: :string}, color: %Schema{type: :string, nullable: true}, room_id: %Schema{type: :integer, nullable: true}, last_seen: %Schema{type: :string, format: :"date-time", nullable: true} }, required: [:id, :tag_id, :name, :color, :room_id, :last_seen] }) end defmodule OnboardingStatus do require OpenApiSpex OpenApiSpex.schema(%{ title: "OnboardingStatus", type: :object, properties: %{ has_admin: %Schema{type: :boolean}, has_floors: %Schema{type: :boolean}, has_rooms: %Schema{type: :boolean}, has_sensors_placed: %Schema{type: :boolean}, has_tags: %Schema{type: :boolean} }, required: [:has_admin, :has_floors, :has_rooms, :has_sensors_placed, :has_tags] }) end defmodule TokenResponse do require OpenApiSpex OpenApiSpex.schema(%{ title: "TokenResponse", type: :object, properties: %{ token: %Schema{type: :string}, user: User }, required: [:token, :user] }) end defmodule Error do require OpenApiSpex OpenApiSpex.schema(%{ title: "Error", type: :object, properties: %{error: %Schema{type: :string}}, required: [:error] }) end defmodule ValidationErrors do require OpenApiSpex OpenApiSpex.schema(%{ title: "ValidationErrors", type: :object, properties: %{ errors: %Schema{ type: :object, additionalProperties: %Schema{type: :array, items: %Schema{type: :string}} } } }) end defmodule CommandSent do require OpenApiSpex OpenApiSpex.schema(%{ title: "CommandSent", type: :object, properties: %{status: %Schema{type: :string, enum: ["ok"]}}, required: [:status] }) end defmodule CalibrationStatus do require OpenApiSpex OpenApiSpex.schema(%{ title: "CalibrationStatus", type: :object, properties: %{status: %Schema{type: :string, enum: ["calibrating", "idle"]}}, required: [:status] }) end # ── Request body schemas ──────────────────────────────────────────────────── defmodule SetupParams do require OpenApiSpex OpenApiSpex.schema(%{ title: "SetupParams", type: :object, properties: %{ username: %Schema{type: :string}, password: %Schema{type: :string, format: :password} }, required: [:username, :password] }) end defmodule SessionParams do require OpenApiSpex OpenApiSpex.schema(%{ title: "SessionParams", type: :object, properties: %{ username: %Schema{type: :string}, password: %Schema{type: :string, format: :password} }, required: [:username, :password] }) end defmodule UserCreateParams do require OpenApiSpex OpenApiSpex.schema(%{ title: "UserCreateParams", type: :object, properties: %{ username: %Schema{type: :string}, password: %Schema{type: :string, format: :password}, is_admin: %Schema{type: :boolean, default: false} }, required: [:username, :password] }) end defmodule UserUpdateParams do require OpenApiSpex OpenApiSpex.schema(%{ title: "UserUpdateParams", type: :object, properties: %{ username: %Schema{type: :string}, password: %Schema{type: :string, format: :password} } }) end defmodule FloorParams do require OpenApiSpex OpenApiSpex.schema(%{ title: "FloorParams", type: :object, properties: %{ name: %Schema{type: :string}, width: %Schema{type: :number, format: :float}, height: %Schema{type: :number, format: :float} }, required: [:name, :width, :height] }) end defmodule FloorUpdateParams do require OpenApiSpex OpenApiSpex.schema(%{ title: "FloorUpdateParams", type: :object, properties: %{ name: %Schema{type: :string}, width: %Schema{type: :number, format: :float}, height: %Schema{type: :number, format: :float} } }) end defmodule RoomParams do require OpenApiSpex OpenApiSpex.schema(%{ title: "RoomParams", type: :object, properties: %{ name: %Schema{type: :string}, x: %Schema{type: :number, format: :float}, y: %Schema{type: :number, format: :float}, width: %Schema{type: :number, format: :float}, height: %Schema{type: :number, format: :float} }, required: [:name, :x, :y, :width, :height] }) end defmodule RoomUpdateParams do require OpenApiSpex OpenApiSpex.schema(%{ title: "RoomUpdateParams", type: :object, properties: %{ name: %Schema{type: :string}, x: %Schema{type: :number, format: :float}, y: %Schema{type: :number, format: :float}, width: %Schema{type: :number, format: :float}, height: %Schema{type: :number, format: :float} } }) end defmodule SensorEnrollParams do require OpenApiSpex OpenApiSpex.schema(%{ title: "SensorEnrollParams", type: :object, properties: %{sensor_id: %Schema{type: :string}}, required: [:sensor_id] }) end defmodule SensorReconfigureParams do require OpenApiSpex OpenApiSpex.schema(%{ title: "SensorReconfigureParams", type: :object, properties: %{ ssid: %Schema{type: :string}, password: %Schema{type: :string, format: :password}, mqtt_broker: %Schema{type: :string, required: false}, mqtt_port: %Schema{type: :integer, required: false} } }) end defmodule SensorUpdateParams do require OpenApiSpex OpenApiSpex.schema(%{ title: "SensorUpdateParams", type: :object, properties: %{rssi_ref: %Schema{type: :number, format: :float}} }) end defmodule SensorPlaceParams do require OpenApiSpex OpenApiSpex.schema(%{ title: "SensorPlaceParams", type: :object, properties: %{ room_id: %Schema{type: :integer}, x: %Schema{type: :number, format: :float}, y: %Schema{type: :number, format: :float} }, required: [:room_id, :x, :y] }) end defmodule CalibrationStartParams do require OpenApiSpex OpenApiSpex.schema(%{ title: "CalibrationStartParams", type: :object, properties: %{ reference_distance: %Schema{ type: :number, format: :float, description: "Known tag-to-sensor distance in metres" } }, required: [:reference_distance] }) end defmodule TagOccupancy do require OpenApiSpex OpenApiSpex.schema(%{ title: "TagOccupancy", type: :object, properties: %{ id: %Schema{type: :integer}, tag_id: %Schema{type: :string}, name: %Schema{type: :string}, room_id: %Schema{type: :integer, nullable: true} }, required: [:id, :tag_id, :name, :room_id] }) end defmodule TagParams do require OpenApiSpex OpenApiSpex.schema(%{ title: "TagParams", type: :object, properties: %{ tag_id: %Schema{type: :string, description: "BLE MAC address or device ID"}, name: %Schema{type: :string}, color: %Schema{type: :string} }, required: [:tag_id, :name] }) end defmodule TagUpdateParams do require OpenApiSpex OpenApiSpex.schema(%{ title: "TagUpdateParams", type: :object, properties: %{ name: %Schema{type: :string}, color: %Schema{type: :string} } }) end end