Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

363 find a way to add images to delivery sign up #391

Merged
merged 11 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion lib/bike_brigade/delivery/program.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@

alias BikeBrigade.Delivery.{Item, Campaign, ProgramLatestCampaign}

defenum(SpreadsheetLayout,

Check warning on line 9 in lib/bike_brigade/delivery/program.ex

View workflow job for this annotation

GitHub Actions / Build and test

the underscored variable "_t" is used after being set. A leading underscore indicates that the value of the variable should be ignored. If this is intended please rename the variable to remove the underscore

Check warning on line 9 in lib/bike_brigade/delivery/program.ex

View workflow job for this annotation

GitHub Actions / Build and test

the underscored variable "_t" is used after being set. A leading underscore indicates that the value of the variable should be ignored. If this is intended please rename the variable to remove the underscore
foodshare: "foodshare",
map: "map"
)

defmodule Schedule do

Check warning on line 14 in lib/bike_brigade/delivery/program.ex

View workflow job for this annotation

GitHub Actions / Build and test

the underscored variable "_t" is used after being set. A leading underscore indicates that the value of the variable should be ignored. If this is intended please rename the variable to remove the underscore

Check warning on line 14 in lib/bike_brigade/delivery/program.ex

View workflow job for this annotation

GitHub Actions / Build and test

the underscored variable "_t" is used after being set. A leading underscore indicates that the value of the variable should be ignored. If this is intended please rename the variable to remove the underscore
use BikeBrigade.Schema

embedded_schema do
Expand All @@ -36,6 +36,8 @@
field :spreadsheet_layout, SpreadsheetLayout, default: :foodshare
field :active, :boolean, default: true
field :start_date, :date
field :photo_description, :string
field :photos, {:array, :string}, default: []

# Default to public false before we launch
field :public, :boolean, default: false
Expand Down Expand Up @@ -74,7 +76,9 @@
:public,
:hide_pickup_address,
:spreadsheet_layout,
:start_date
:start_date,
:photo_description,
:photos
])
|> validate_required([:name, :start_date])
|> foreign_key_constraint(:lead_id)
Expand Down
4 changes: 2 additions & 2 deletions lib/bike_brigade_web/core_components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -872,10 +872,10 @@ defmodule BikeBrigadeWeb.CoreComponents do
<div class="px-4 py-6 bg-gray-50 sm:px-6">
<div class="flex items-start justify-between space-x-3">
<header :if={@title != []} class="space-y-1">
<h1 class="text-lg font-medium text-gray-900" id={"#{@id}-title"}>
<h1 class="text-lg font-medium leading-8 text-gray-900" id={"#{@id}-title"}>
<%= render_slot(@title) %>
</h1>
<p :if={@subtitle != []} class="text-sm text-gray-500">
<p :if={@subtitle != []} class="text-sm leading-6 text-gray-500">
<%= render_slot(@subtitle) %>
</p>
</header>
Expand Down
21 changes: 18 additions & 3 deletions lib/bike_brigade_web/live/campaign_signup_live/show.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
<span :if={@campaign.program.campaign_blurb}>- <%= @campaign.program.campaign_blurb %></span>
</:subtitle>
</.header>

<!-- Desktop Table of tasks -->
<section class="hidden md:block">
<.table id="tasks" rows={@tasks}>
Expand Down Expand Up @@ -37,9 +36,7 @@
</:action>
</.table>
</section>

<!-- Mobile list of tasks -->

<ul class="flex flex-col text-xs md:hidden">
<li :for={t <- @tasks} class="w-full mb-8">
<div class="flex justify-between px-4 py-3 font-bold bg-slate-200">
Expand Down Expand Up @@ -74,3 +71,21 @@
</div>
</li>
</ul>
<div
:if={!Enum.empty?(@campaign.program.photos)}
class="mt-4 overflow-hidden bg-white rounded-lg shadow"
>
<div class="px-4 py-5 sm:p-6">
<.header>
Delivery photos
<:subtitle>
<%= @campaign.program.photo_description %>
</:subtitle>
</.header>
<div class="grid grid-cols-3 gap-4 mt-4">
<figure :for={url <- @campaign.program.photos}>
<img class="w-64" src={url} />
</figure>
</div>
</div>
</div>
59 changes: 58 additions & 1 deletion lib/bike_brigade_web/live/program_live/form_component.ex
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
defmodule BikeBrigadeWeb.ProgramLive.FormComponent do
use BikeBrigadeWeb, :live_component

alias BikeBrigade.Delivery
alias BikeBrigade.{Delivery, MediaStorage}

alias BikeBrigadeWeb.ProgramLive.ProgramForm

@impl Phoenix.LiveComponent
def mount(socket) do
socket =
socket
|> allow_upload(:photos, accept: ~w(.gif .png .jpg .jpeg), max_entries: 10)

{:ok, socket}
end

@impl Phoenix.LiveComponent
def update(%{program: program} = assigns, socket) do
program = BikeBrigade.Repo.preload(program, [:items])
Expand Down Expand Up @@ -83,6 +92,24 @@ defmodule BikeBrigadeWeb.ProgramLive.FormComponent do
{:noreply, assign(socket, :changeset, changeset)}
end

def handle_event("delete_photo", %{"index" => index}, socket) do
changeset = socket.assigns.changeset
program = Ecto.Changeset.get_field(changeset, :program)

photos =
program.photos
|> List.delete_at(index)

changeset =
changeset
|> Ecto.Changeset.change(
program:
program
|> Delivery.Program.changeset(%{photos: photos})
)
{:noreply, assign(socket, :changeset, changeset)}
end

@impl Phoenix.LiveComponent
def handle_event("validate", %{"program_form" => program_form_params}, socket) do
changeset =
Expand All @@ -95,9 +122,35 @@ defmodule BikeBrigadeWeb.ProgramLive.FormComponent do

@impl Phoenix.LiveComponent
def handle_event("save", %{"program_form" => program_form_params}, socket) do
photos =
consume_uploaded_entries(socket, :photos, fn %{path: path}, %{client_type: content_type} ->
# TODO do some guards on content type here
{:ok, MediaStorage.upload_file!(path, content_type)}
end)

photo_urls = Enum.map(photos, &Map.get(&1, :url))

program_form_params =
program_form_params
|> update_in(
["program", "photos"],
fn
nil ->
photo_urls

photos when is_list(photos) ->
photos ++ photo_urls
end
)

save_program(socket, socket.assigns.action, program_form_params)
end

@impl Phoenix.LiveComponent
def handle_event("cancel_upload", %{"ref" => ref}, socket) do
{:noreply, cancel_upload(socket, :photos, ref)}
end

defp save_program(socket, :edit, program_form_params) do
changeset =
socket.assigns.program_form
Expand Down Expand Up @@ -134,4 +187,8 @@ defmodule BikeBrigadeWeb.ProgramLive.FormComponent do
{:noreply, assign(socket, changeset: changeset |> Map.put(:action, :insert))}
end
end

defp error_to_string(:too_large), do: "Too large"
defp error_to_string(:too_many_files), do: "You have selected too many files"
defp error_to_string(:not_accepted), do: "You have selected an unacceptable file type"
end
67 changes: 67 additions & 0 deletions lib/bike_brigade_web/live/program_live/form_component.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,73 @@
</:action>
</.table>
</div>
<.header small>
Photos
<:subtitle>
To be shown to riders when signing up
</:subtitle>
</.header>
<.input
type="text"
field={{f, :photo_description}}
label="Photo Descriotion"
placeholder="Typical delivery size"
/>
<div class="grid grid-cols-3 gap-4 mt-2">
<figure :for={{url, i} <- Enum.with_index(Phoenix.HTML.Form.input_value(f, :photos))}>
<img class="w-32" src={url} />
<input
type="hidden"
name={"#{Phoenix.HTML.Form.input_name(f, :photos)}[]"}
value={url}
/>
<figcaption class="flex mt-1">
<.button
color={:lightred}
size={:xsmall}
phx-click={JS.push("delete_photo", value: %{index: i}, target: @myself)}
type="button"
>
Delete
</.button>
</figcaption>
</figure>
</div>
<div class="flex justify-center px-6 py-10 mt-2 border border-dashed rounded-lg border-gray-900/25">
<div class="text-center">
<Heroicons.photo solid class="w-12 h-12 mx-auto text-gray-300" />

<div class="flex mt-4 text-sm leading-6 text-gray-600">
<label
for={@uploads.photos.ref}
class="relative font-semibold text-indigo-600 bg-white rounded-md cursor-pointer focus-within:outline-none focus-within:ring-2 focus-within:ring-indigo-600 focus-within:ring-offset-2 hover:text-indigo-500"
>
<span>Upload a file</span>
<.live_file_input upload={@uploads.photos} class="sr-only" />
</label>
<p class="pl-1">or drag and drop</p>
</div>
<p class="text-xs leading-5 text-gray-600">PNG, JPG, GIF up to 10MB</p>
</div>
</div>
<div class="grid grid-cols-3 gap-4 mt-2">
<figure :for={entry <- @uploads.photos.entries}>
<.live_img_preview entry={entry} class="w-32" />
<figcaption class="flex">
<div class="mr-1"><%= entry.client_name %></div>
<button
type="button"
phx-click={JS.push("cancel_upload", value: %{ref: entry.ref}, target: @myself)}
aria-label="cancel"
>
&times;
</button>
</figcaption>
<p :for={err <- upload_errors(@uploads.photos, entry)} class="text-sm text-red-600">
<%= error_to_string(err) %>
</p>
</figure>
</div>

<.input
type="text"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule BikeBrigade.Repo.Migrations.AddPhotosToPrograms do
use Ecto.Migration

def change do
alter table(:programs) do
add(:photos, {:array, :string}, default: [])
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule BikeBrigade.Repo.Migrations.AddPhotoDescriptionToPrograms do
use Ecto.Migration

def change do
alter table(:programs) do
add(:photo_description, :string)
end
end
end
24 changes: 19 additions & 5 deletions test/bike_brigade_web/live/campaign_signup_live_test.exs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
defmodule BikeBrigadeWeb.CampaignSignupLiveTest do
use BikeBrigadeWeb.ConnCase, async: false
alias BikeBrigade.{LocalizedDateTime, History}
alias BikeBrigade.{Delivery, LocalizedDateTime, History}

import Phoenix.LiveViewTest

Expand Down Expand Up @@ -192,14 +192,15 @@ defmodule BikeBrigadeWeb.CampaignSignupLiveTest do
assert live |> has_element?("#signup-btn-mobile-task-over-#{task.id}")
end

test "Rider sees message about texting dispatch if unassigning from a campaign that's today", ctx do

test "Rider sees message about texting dispatch if unassigning from a campaign that's today",
ctx do
{:ok, live, html} = live(ctx.conn, ~p"/campaigns/signup/#{ctx.campaign.id}/")
assert html =~ "Sign up"
html = live |> element("#signup-btn-desktop-sign-up-task-#{ctx.task.id}") |> render_click()
assert html =~ "Unassign me"
assert html =~ "This delivery starts today. If you need to unassign yourself, please also text dispatch to let us know!"

assert html =~
"This delivery starts today. If you need to unassign yourself, please also text dispatch to let us know!"

campaign = make_campaign_in_future(ctx.program.id)
task = fixture(:task, %{campaign: campaign, rider: nil})
Expand All @@ -208,7 +209,9 @@ defmodule BikeBrigadeWeb.CampaignSignupLiveTest do

html = live |> element("#signup-btn-desktop-sign-up-task-#{task.id}") |> render_click()
assert html =~ "Unassign me"
refute html =~ "This delivery starts today. If you need to unassign yourself, please also text dispatch to let us know!"

refute html =~
"This delivery starts today. If you need to unassign yourself, please also text dispatch to let us know!"
end

test "we see pertinent task information", ctx do
Expand All @@ -223,7 +226,18 @@ defmodule BikeBrigadeWeb.CampaignSignupLiveTest do
# We show the name and description of the item
assert html =~ "Burrito"
assert html =~ "a large burrito with all the fixings"
end

test "we see campaign photos and description if available", ctx do
{:ok, live, html} = live(ctx.conn, ~p"/campaigns/signup/#{ctx.campaign.id}/")
refute html =~ "Delivery photos"

Delivery.update_program(ctx.program, %{photos: ["https://example.com/photo.jpg"], photo_description: "a typical meal"})

{:ok, live, html} = live(ctx.conn, ~p"/campaigns/signup/#{ctx.campaign.id}/")
assert html =~ "Delivery photos"
assert html =~ "https://example.com/photo.jpg"
assert html =~ "a typical meal"
end

test "Invalid route for campaign shows flash and redirects", ctx do
Expand Down
Loading