diff --git a/assets/src/models/detoursList.ts b/assets/src/models/detoursList.ts index b15359de0..e5333f423 100644 --- a/assets/src/models/detoursList.ts +++ b/assets/src/models/detoursList.ts @@ -60,10 +60,24 @@ export interface GroupedSimpleDetours { past: SimpleDetour[] } +const MyNormalizedType = type({ + my_id: detourId, + my_route: string(), + my_via_variant: string(), + my_direction: string(), + my_name: string(), + my_intersection: string(), + my_updated_at: number(), + my_activated_at: coerce(date(), string(), (dateStr) => new Date(dateStr)), + my_estimated_duration: string(), +}) + +type MyNormalizedType = Infer + export const GroupedDetoursData = type({ - active: array(ActivatedDetourData), - draft: array(SimpleDetourData), - past: array(SimpleDetourData), + active: array(MyNormalizedType), + draft: array(MyNormalizedType), + past: array(MyNormalizedType), }) export type GroupedDetoursData = Infer @@ -72,8 +86,50 @@ export const groupedDetoursFromData = ( groupedDetours: GroupedDetoursData ): GroupedSimpleDetours => ({ active: groupedDetours.active + .map(fromNormalizedToActivatedData) .map(simpleDetourFromActivatedData) .sort((a, b) => b.activatedAt.getTime() - a.activatedAt.getTime()), - draft: groupedDetours.draft.map((detour) => simpleDetourFromData(detour)), - past: groupedDetours.past.map((detour) => simpleDetourFromData(detour)), + draft: groupedDetours.draft.map(fromNormalizedToSimple).map((detour) => simpleDetourFromData(detour)), + past: groupedDetours.past.map(fromNormalizedToSimple).map((detour) => simpleDetourFromData(detour)), +}) + +const fromNormalizedToSimple = ({ + my_id, + my_route, + my_via_variant, + my_direction, + my_name, + my_intersection, + my_updated_at, +}: MyNormalizedType): SimpleDetourData => ({ + id: my_id, + route: my_route, + via_variant: my_via_variant, + direction: my_direction, + name: my_name, + intersection: my_intersection, + updated_at: my_updated_at +}) + +const fromNormalizedToActivatedData = ({ + my_id, + my_route, + my_via_variant, + my_direction, + my_name, + my_intersection, + my_updated_at, + my_activated_at, + my_estimated_duration }: MyNormalizedType): ActivatedDetourData => ({ + activated_at: my_activated_at, + estimated_duration: my_estimated_duration, + details: { + id: my_id, + route: my_route, + via_variant: my_via_variant, + direction: my_direction, + name: my_name, + intersection: my_intersection, + updated_at: my_updated_at + } }) diff --git a/lib/skate/detours/detours.ex b/lib/skate/detours/detours.ex index 5d9c4922b..57909b2cf 100644 --- a/lib/skate/detours/detours.ex +++ b/lib/skate/detours/detours.ex @@ -445,4 +445,137 @@ defmodule Skate.Detours.Detours do |> DateTime.from_naive!("Etc/UTC") |> DateTime.to_unix() end + + @spec normalize_from_frontend(map(), any()) :: %{ + :author_id => binary(), + :state => map(), + optional(:activated_at) => any(), + optional(:deactivated_at) => any(), + optional(:id) => any(), + optional(:status) => :active | :draft | :past + } + def normalize_from_frontend(params, author_id) do + allowed_params = Map.take(params, ["id", "state", "activated_at", "deactivated_at"]) + + normalized_params = + Map.merge( + %{"id" => nil, "state" => nil, "activated_at" => nil, "deactivated_at" => nil}, + allowed_params + ) + + do_normalize_from_frontend(normalized_params, author_id) + end + + # create + defp do_normalize_from_frontend(%{"id" => nil, "state" => state}, author_id) do + %{ + state: state, + author_id: author_id, + status: :draft + } + end + + # update + defp do_normalize_from_frontend( + %{"id" => id, "state" => state, "activated_at" => nil}, + author_id + ) do + %{ + id: id, + state: state, + author_id: author_id + } + end + + # activate + defp do_normalize_from_frontend( + %{"id" => id, "state" => state, "activated_at" => activated_at, "deactivated_at" => nil}, + author_id + ) + when not is_nil(activated_at) do + %{ + id: id, + state: state, + author_id: author_id, + activated_at: activated_at, + status: :active + } + end + + # de-activate + defp do_normalize_from_frontend( + %{"id" => id, "state" => state, "deactivated_at" => deactivated_at}, + author_id + ) + when not is_nil(deactivated_at) do + %{ + id: id, + state: state, + author_id: author_id, + deactivated_at: deactivated_at, + status: :past + } + end + + @spec normalize_from_backend( + Skate.Detours.Detour.WithState.t() + | Skate.Detours.Detour.Detailed.t() + | %{ + active: [Skate.Detours.Detour.Detailed.t()], + draft: [Skate.Detours.Detour.Detailed.t()], + past: [Skate.Detours.Detour.Detailed.t()] + } + ) :: %{ + my_activated_at: nil, + my_direction: nil, + my_estimated_duration: nil, + my_id: nil, + my_intersection: nil, + my_name: nil, + my_route: nil, + my_updated_at: nil, + my_via_variant: nil + } + def normalize_from_backend(%Skate.Detours.Detour.WithState{} = _detour) do + # unpack data into decided upon interface from current struct type + %{ + my_id: nil, + my_route: nil, + my_via_variant: nil, + my_direction: nil, + my_name: nil, + my_intersection: nil, + my_updated_at: nil, + my_activated_at: nil, + my_estimated_duration: nil + } + end + + def normalize_from_backend(%{active: active, draft: draft, past: past}) do + %{ + active: normalize_from_backend(active), + draft: normalize_from_backend(draft), + past: normalize_from_backend(past) + } + end + + def normalize_from_backend(nil), do: nil + + def normalize_from_backend([%Skate.Detours.Detour.Detailed{} | _] = detours), + do: Enum.map(detours, &normalize_from_backend/1) + + def normalize_from_backend(%Skate.Detours.Detour.Detailed{} = _detour) do + # unpack data into decided upon interface from current struct type + %{ + my_id: nil, + my_route: nil, + my_via_variant: nil, + my_direction: nil, + my_name: nil, + my_intersection: nil, + my_updated_at: nil, + my_activated_at: nil, + my_estimated_duration: nil + } + end end diff --git a/lib/skate_web/controllers/detours_controller.ex b/lib/skate_web/controllers/detours_controller.ex index f9a784247..8b35d6df3 100644 --- a/lib/skate_web/controllers/detours_controller.ex +++ b/lib/skate_web/controllers/detours_controller.ex @@ -14,6 +14,9 @@ defmodule SkateWeb.DetoursController do def update_snapshot(conn, %{"snapshot" => snapshot}) do %{id: user_id} = AuthManager.Plug.current_resource(conn) + # normalized_request = Detours.normalize_from_frontend(snapshot, user_id) + # {:ok, %{id: returned_uuid}} = Detours.upsert(normalized_request) + {:ok, %Skate.Detours.Db.Detour{id: returned_uuid}} = Detours.upsert_from_snapshot(user_id, snapshot) @@ -24,6 +27,9 @@ defmodule SkateWeb.DetoursController do def detour(conn, %{"detour_id" => detour_id}) do detour = Detours.get_detour_with_state!(detour_id) + # normalized_detour = Detours.normalize_from_backend(detour) + # json(conn, %{data: normalized_detour}) + json(conn, %{data: detour}) end @@ -33,6 +39,9 @@ defmodule SkateWeb.DetoursController do detours = Detours.grouped_detours(user_id) + # normalized_detours = Enum.map(detours, &Detours.normalize_from_backend/1) + # json(conn, %{data: normalized_detours}) + json(conn, %{data: detours}) end