Skip to content

Commit

Permalink
WIP commit on some vote capture ideas.
Browse files Browse the repository at this point in the history
  • Loading branch information
zorn committed May 29, 2024
1 parent 77acb60 commit 163d0a8
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 1 deletion.
Empty file added lib/flick/votes.ex
Empty file.
17 changes: 17 additions & 0 deletions lib/flick/votes/answer.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
defmodule Flick.Votes.Answer do
@moduledoc """
TBD
"""

use Ecto.Schema

import Ecto.Changeset

embedded_schema do
field :question_id, :binary_id
field :ranked_answer_ids, {:array, :binary_id}
end

# TODO: When capturing a vote, do we want to validate that all the supplied answer_ids match actual answers for the question in the ballot?
# Maybe we could store a vitual field for the question so we can check it's answers during changeset? reference
end
31 changes: 31 additions & 0 deletions lib/flick/votes/vote.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
defmodule Flick.Votes.Vote do
@moduledoc """
A vote is a collection of ranked answers for a `Flick.Ballots.Ballot` question.
"""

use Ecto.Schema

import Ecto.Changeset

alias Flick.Ballots.Ballot
alias Flick.Votes.Answer

@type id :: Ecto.UUID.t()

@typedoc """
A type for a persisted `Flick.Votes.Vote` entity.
"""
@type t :: %__MODULE__{
id: Ecto.UUID.t(),
ballot_id: Ballot.id()
}

@primary_key {:id, :binary_id, autogenerate: true}
schema "votes" do
field :ballot_id, :binary_id
embeds_many :answers, Answer, on_replace: :delete
timestamps(type: :utc_datetime_usec)
end

# TODO: Should the changelog of a vote require we have an answer for each question?
end
7 changes: 6 additions & 1 deletion lib/flick_web/live/ballots/index_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ defmodule FlickWeb.Ballots.IndexLive do
<%= ballot.title %>
</:col>
<:col :let={ballot} label="published at">
<%= ballot.published_at || "Not Published" %>
<%= if ballot.published_at do %>
<%= ballot.published_at %>
<.link navigate={~p"/vote/#{ballot.id}"}>Voting Page</.link>
<% else %>
Not Published
<% end %>
</:col>
<:col :let={ballot} label="details">
<.link navigate={~p"/ballots/#{ballot.id}"}>View Details</.link>
Expand Down
87 changes: 87 additions & 0 deletions lib/flick_web/live/vote/vote_capture_live.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
defmodule FlickWeb.Vote.VoteCaptureLive do
@moduledoc """
A live view that presents a ranked voting form for a published
`Flick.Ballots.Ballot` entity.
"""

use FlickWeb, :live_view

alias Flick.Ballots

@impl Phoenix.LiveView
def mount(params, _session, socket) do
%{"ballot_id" => ballot_id} = params

ballot = Ballots.get_ballot!(ballot_id)

socket
|> verify_ballot_is_published(ballot)
|> assign(:page_title, "Vote: #{ballot.title}")
|> assign(:ballot, ballot)
|> ok()
end

defp verify_ballot_is_published(socket, ballot) do
if ballot.published_at do
socket
else
# TODO: We can make this a better user experience in the future.
throw("can not vote on an unpublished ballot")
end
end

@impl Phoenix.LiveView
def render(assigns) do
~H"""
<div>
<div>The Question</div>
<div class="grid grid-cols-5">
<div>
<!-- empty -->
</div>
<div>1st Choice</div>
<div>2nd Choice</div>
<div>3rd Choice</div>
<div>4th Choice</div>
<div>Answer Option A</div>
<div>input</div>
<div>input</div>
<div>input</div>
<div>input</div>
<div>Answer Option B</div>
<div>input</div>
<div>input</div>
<div>input</div>
<div>input</div>
<div>Answer Option C</div>
<div>input</div>
<div>input</div>
<div>input</div>
<div>input</div>
<div>Answer Option D</div>
<div>input</div>
<div>input</div>
<div>input</div>
<div>input</div>
<div>Answer Option E</div>
<div>input</div>
<div>input</div>
<div>input</div>
<div>input</div>
<div>Answer Option F</div>
<div>input</div>
<div>input</div>
<div>input</div>
<div>input</div>
</div>
</div>
"""
end
end
2 changes: 2 additions & 0 deletions lib/flick_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ defmodule FlickWeb.Router do
live "/ballots/new", Ballots.EditorLive, :new
live "/ballots/:ballot_id/edit", Ballots.EditorLive, :edit
live "/ballots/:ballot_id", Ballots.ViewerLive, :show

live "/vote/:ballot_id", Vote.VoteCaptureLive, :new
end

# Other scopes may use custom stacks.
Expand Down

0 comments on commit 163d0a8

Please sign in to comment.