PhoenixKitLocations

Hex.pmLicense

Locations module for PhoenixKit — manage physical locations with custom types, multilingual fields, and a full admin interface.

Features

Installation

Add phoenix_kit_locations to your list of dependencies in mix.exs:

def deps do
  [
    {:phoenix_kit_locations, "~> 0.1"}
  ]
end

The module is auto-discovered by PhoenixKit — no manual router configuration needed. Run the PhoenixKit migrations to create the required database tables.

Usage

Admin Interface

Once installed, the admin dashboard adds a Locations tab with two subtabs:

Routes are registered automatically:

Path Description
/admin/locations Locations list
/admin/locations/new Create location
/admin/locations/:uuid/edit Edit location
/admin/locations/types Types list
/admin/locations/types/new Create type
/admin/locations/types/:uuid/edit Edit type

Programmatic Access

All business logic lives in the PhoenixKitLocations.Locations context:

alias PhoenixKitLocations.Locations

# Locations
Locations.list_locations()
Locations.create_location(%{name: "HQ", city: "Berlin", country: "DE"})
Locations.list_locations(status: "active", type_uuid: some_uuid)

# Location types
Locations.list_location_types()
Locations.create_location_type(%{name: "Office"})

# Type assignments (take location_uuid, not the struct)
Locations.sync_location_types(location.uuid, [type_uuid_1, type_uuid_2])
Locations.has_type?(location.uuid, type_uuid)

Error Handling

Non-changeset errors returned by PhoenixKitLocations.Locations are atoms (:location_not_found, :type_assignment_failed, …). At the UI boundary, LiveViews translate them via PhoenixKitLocations.Errors.message/1, which wraps each mapping in gettext so flashes render in the user's locale.

case Locations.delete_location(loc, actor_uuid: user.uuid) do
  {:ok, _} -> :ok
  {:error, _changeset} -> {:error, PhoenixKitLocations.Errors.message(:location_delete_failed)}
end

Activity Logging

Every mutating context function logs a business-level activity to PhoenixKit.Activity when an actor_uuid: opt is passed. Logging is fire-and-forget — failures (e.g. host hasn't run core's V90 migration) never crash the primary operation. The action format is "resource.verb": location.created, location.updated, location.deleted, location.types_synced, location_type.created, etc.

Location Features

Locations support a set of boolean feature flags stored as a JSONB map:

wheelchair_accessible, elevator, parking, public_transport, loading_dock, air_conditioning, wifi, restrooms, security, cctv

Locations.create_location(%{
  name: "Warehouse",
  features: %{"loading_dock" => true, "parking" => true, "cctv" => true}
})

Database Schemas

All schemas use UUIDv7 primary keys. Tables are created by PhoenixKit migrations.

Table Description
phoenix_kit_locations Locations with address, contact, features, and multilang data
phoenix_kit_location_types User-defined location categories
phoenix_kit_location_type_assignments Many-to-many join table

Development

mix deps.get          # Install dependencies
mix test              # Run tests
mix precommit         # compile + format + credo + dialyzer
mix quality           # format + credo + dialyzer
mix quality.ci        # format --check-formatted + credo + dialyzer

License

MIT — see LICENSE for details.