shift73k/lib/shift73k_web/controllers/user_shifts_csv_controller.ex

92 lines
2.3 KiB
Elixir
Raw Permalink Normal View History

defmodule Shift73kWeb.UserShiftsCsvController do
use Shift73kWeb, :controller
alias Shift73k.Shifts
alias Shift73k.Shifts.Shift
def new(conn, _params) do
render(conn, "new.html", page_title: "CSV Export")
end
def export(conn, %{"csv_export" => request_params}) do
case Map.get(request_params, "user_id") == conn.assigns.current_user.id do
true ->
export_csv(conn, request_params)
false ->
conn
|> put_flash(:danger, "Unauthorized CSV export request")
|> redirect(to: "/")
|> halt()
end
end
defp export_csv(conn, %{"date_min" => date_min, "date_max" => date_max}) do
date_range = Date.range(Date.from_iso8601!(date_min), Date.from_iso8601!(date_max))
csv_content = build_csv_content(conn.assigns.current_user.id, date_range)
filename_dt = DateTime.utc_now() |> Calendar.strftime("%Y%m%dT%H%M%S")
filename = "#{conn.assigns.current_user.id}_#{filename_dt}.csv"
conn
|> put_resp_content_type("text/csv")
|> put_resp_header("content-disposition", "attachment; filename=\"#{filename}\"")
|> send_resp(200, csv_content)
end
def build_csv_content(user_id, date_range) do
[csv_headers() | csv_data(user_id, date_range)]
|> NimbleCSV.RFC4180.dump_to_iodata()
|> to_string()
end
def csv_data(user_id, date_range) do
user_id
|> Shifts.list_shifts_by_user_in_date_range(date_range)
|> Enum.map(&csv_shift_row/1)
end
def csv_headers do
[
"Subject",
"Start Date",
"Start Time",
"End Date",
"End Time",
"All Day Event",
"Description",
"Location",
"Private"
]
end
defp csv_shift_row(%Shift{} = s) do
dt_start = DateTime.new!(s.date, s.time_start, s.time_zone)
shift_length_s = Shifts.shift_length(s) * 60
dt_end = DateTime.add(dt_start, shift_length_s)
[
s.subject,
csv_date_string(dt_start),
csv_time_string(dt_start),
csv_date_string(dt_end),
csv_time_string(dt_end),
false,
s.description,
s.location,
false
]
end
defp csv_date_string(%DateTime{} = dt) do
dt
|> DateTime.to_date()
|> Calendar.strftime("%m/%d/%Y")
end
defp csv_time_string(%DateTime{} = dt) do
dt
|> DateTime.to_time()
|> Calendar.strftime("%-I:%M %p")
end
end