Skip to content
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
1 change: 1 addition & 0 deletions assets/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

@theme {
--color-primary: #ee7749;
--color-app-bg: #F9F9F9;
}


Expand Down
6 changes: 6 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ config :yearbook,
ecto_repos: [Yearbook.Repo],
generators: [timestamp_type: :utc_datetime, binary_id: true]

# Waffle configuration
config :waffle,
storage: Waffle.Storage.Local,
storage_dir_prefix: "priv",
asset_host: {:system, "ASSET_HOST"}

# Configures the endpoint
config :yearbook, YearbookWeb.Endpoint,
url: [host: "localhost"],
Expand Down
28 changes: 28 additions & 0 deletions lib/yearbook/entries.ex
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,34 @@ defmodule Yearbook.Entries do
}
end

@doc """
Returns a paginated map of accepted entries based on filters and page.
"""
def list_accepted_entries_pagination(params \\ %{}) do
query = from e in Entry, where: e.status == :accepted

query =
case Map.get(params, "masters") do
"true" -> from e in query, where: e.masters == true
"false" -> from e in query, where: e.masters == false
_ -> query
end

query =
case Map.get(params, "year") do
year_str when year_str in [nil, ""] ->
query

year_str ->
year_int = if is_binary(year_str), do: String.to_integer(year_str), else: year_str
from e in query, where: e.year == ^year_int
end

query = from e in query, order_by: [asc: e.name]

paginate(query, params)
end

@doc """
Gets a single entry.

Expand Down
10 changes: 8 additions & 2 deletions lib/yearbook/entries/entry.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,29 @@ defmodule Yearbook.Entries.Entry do
use Ecto.Schema
import Ecto.Changeset

@required_fields ~w(photo name text)a
@optional_fields ~w(status)a
@required_fields ~w(photo name text year)a
@optional_fields ~w(status masters)a
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "entries" do
field :photo, :string
field :name, :string
field :text, :string
field :status, Ecto.Enum, values: [:accepted, :pending, :denied], default: :pending
field :masters, :boolean, default: false
field :year, :integer

timestamps(type: :utc_datetime)
end

@doc false
def changeset(entry, attrs) do
current_year = Date.utc_today().year

entry
|> cast(attrs, @required_fields ++ @optional_fields)
|> validate_required(@required_fields)
|> validate_number(:year, greater_than: 2020, less_than_or_equal_to: current_year)
|> validate_length(:text, max: 200)
end
end
27 changes: 27 additions & 0 deletions lib/yearbook/schema.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule Yearbook.Schema do
@moduledoc """
Base schema module.
"""
defmacro __using__(_) do
quote do
use Ecto.Schema
use Waffle.Ecto.Schema

import Ecto.Changeset

alias Yearbook.Uploaders

@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id

def validate_url(changeset, field) do
changeset
|> validate_format(
field,
~r/^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)$/,
message: "must start with http:// or https:// and have a valid domain"
)
end
end
end
end
15 changes: 15 additions & 0 deletions lib/yearbook/uploader.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
defmodule Yearbook.Uploader do
@moduledoc """
Base uploader module.
"""
defmacro __using__(_) do
quote do
use Waffle.Definition
use Waffle.Ecto.Definition

def s3_object_headers(_version, {file, _scope}) do
[content_type: MIME.from_path(file.file_name)]
end
end
end
end
10 changes: 10 additions & 0 deletions lib/yearbook_web.ex
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ defmodule YearbookWeb do
end
end

def component do
quote do
use Phoenix.Component

unquote(html_helpers())
end
end

def auth_view do
quote do
use Phoenix.LiveView,
Expand Down Expand Up @@ -120,6 +128,8 @@ defmodule YearbookWeb do

# Routes generation with the ~p sigil
unquote(verified_routes())

alias Yearbook.Uploaders
end
end

Expand Down
44 changes: 29 additions & 15 deletions lib/yearbook_web/components/core_components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -521,27 +521,41 @@ defmodule YearbookWeb.CoreComponents do
phx-mounted={@show && show_modal(@id)}
phx-remove={hide_modal(@id)}
data-cancel={JS.exec(@on_cancel, "phx-remove") |> hide_modal(@id)}
class="relative z-60 hidden"
class="relative z-50 hidden"
>
<div
id={"#{@id}-bg"}
class="bg-black/60 backdrop-blur-sm fixed inset-0 transition-opacity"
aria-hidden="true"
class="fixed inset-0 bg-black/50 backdrop-blur-md transition-opacity"
/>
<div class="fixed inset-0 overflow-y-auto">
<div class="flex min-h-full items-center justify-center p-4">
<div
id={"#{@id}-container"}
phx-click-away={JS.exec("data-cancel", to: "##{@id}")}
class="relative bg-white rounded-xl max-w-sm w-full shadow-2xl p-8 text-center transition"

<div class="fixed inset-0 flex min-h-full items-start justify-center overflow-y-auto px-4 py-6 sm:items-center sm:py-10">
<div
id={"#{@id}-container"}
phx-click-away={JS.exec("data-cancel", to: "##{@id}")}
class="
relative w-full max-w-2xl
bg-white rounded-3xl
shadow-[0_20px_60px_rgba(0,0,0,0.15)]
border border-gray-100
p-6 sm:p-10

animate-in fade-in zoom-in-95 duration-200
"
>
<button
phx-click={JS.exec("data-cancel", to: "##{@id}")}
class="
absolute top-5 right-5
w-9 h-9 flex items-center justify-center
text-gray-500 hover:text-gray-700
transition-all focus:outline-none
cursor-pointer
"
>
<button
phx-click={JS.exec("data-cancel", to: "##{@id}")}
class="absolute top-4 right-4 text-gray-400 hover:text-gray-600 transition-colors cursor-pointer"
>
<.icon name="hero-x-mark" class="size-5" />
</button>
<.icon name="hero-x-mark" class="size-5" />
</button>

<div class="text-left">
{render_slot(@inner_block)}
</div>
</div>
Expand Down
25 changes: 13 additions & 12 deletions lib/yearbook_web/components/entry_card.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,25 @@ defmodule YearbookWeb.Components.EntryCard do

def entry_card(assigns) do
~H"""
<div class="flex flex-col items-center gap-2 p-2 overflow-auto bg-white rounded-xl shadow-md w-full min-h-56 sm:min-h-72 lg:min-h-96">
<div class="w-full shrink-0 overflow-hidden aspect-square sm:aspect-4/3">
<div class="flex flex-col items-center gap-3 p-4 bg-white rounded-2xl border border-gray-100 w-full h-full transition-all">
<div class="w-full aspect-square overflow-hidden rounded-xl border border-gray-50">
<%= if @src do %>
<img
src={@src}
alt={@name}
class="w-full h-full object-cover rounded-md"
/>
<img src={@src} alt={@name} class="w-full h-full object-cover" />
<% else %>
<div class="flex items-center justify-center w-full h-full rounded-xl bg-gray-300 text-white font-bold text-2xl">
<div class="flex items-center justify-center w-full h-full bg-gray-100 text-gray-400 font-bold text-xl">
{get_initials(@name)}
</div>
<% end %>
</div>
<h1 class="text-center w-full wrap-break-word font-bold px-2 text-md sm:text-lg lg:text-xl">
{@name}
</h1>
<p class="flex-1 place-items-center p-2 text-sm sm:text-md lg:text-lg">{@text}</p>

<div class="text-center w-full">
<h1 class="font-bold text-gray-900 text-sm md:text-base leading-tight">
{@name}
</h1>
<p class="italic text-[11px] md:text-xs text-gray-500 mt-2 line-clamp-3 leading-relaxed">
"{@text}"
</p>
</div>
</div>
"""
end
Expand Down
Loading
Loading