Skip to content

Commit 98f069a

Browse files
committed
feat: improve ui responsiveness
1 parent 781d242 commit 98f069a

File tree

15 files changed

+277
-70
lines changed

15 files changed

+277
-70
lines changed

.dockerignore

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# This file excludes paths from the Docker build context.
2+
#
3+
# By default, Docker's build context includes all files (and folders) in the
4+
# current directory. Even if a file isn't copied into the container it is still sent to
5+
# the Docker daemon.
6+
#
7+
# There are multiple reasons to exclude files from the build context:
8+
#
9+
# 1. Prevent nested folders from being copied into the container (ex: exclude
10+
# /assets/node_modules when copying /assets)
11+
# 2. Reduce the size of the build context and improve build time (ex. /build, /deps, /doc)
12+
# 3. Avoid sending files containing sensitive information
13+
#
14+
# More information on using .dockerignore is available here:
15+
# https://docs.docker.com/engine/reference/builder/#dockerignore-file
16+
17+
.dockerignore
18+
19+
# Ignore git, but keep git HEAD and refs to access current commit hash if needed:
20+
#
21+
# $ cat .git/HEAD | awk '{print ".git/"$2}' | xargs cat
22+
# d0b8727759e1e0e7aa3d41707d12376e373d5ecc
23+
.git
24+
!.git/HEAD
25+
!.git/refs
26+
27+
# Common development/test artifacts
28+
/cover/
29+
/doc/
30+
/test/
31+
/tmp/
32+
.elixir_ls
33+
34+
# Mix artifacts
35+
/_build/
36+
/deps/
37+
*.ez
38+
39+
# Generated on crash by the VM
40+
erl_crash.dump
41+
42+
# Static artifacts - These should be fetched and built inside the Docker image
43+
# https://hexdocs.pm/phoenix/Mix.Tasks.Phx.Gen.Release.html#module-docker
44+
/assets/node_modules/
45+
/priv/static/assets/
46+
/priv/static/cache_manifest.json

Dockerfile

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Find eligible builder and runner images on Docker Hub. We use Ubuntu/Debian
2+
# instead of Alpine to avoid DNS resolution issues in production.
3+
#
4+
# https://hub.docker.com/r/hexpm/elixir/tags?name=ubuntu
5+
# https://hub.docker.com/_/ubuntu/tags
6+
#
7+
# This file is based on these images:
8+
#
9+
# - https://hub.docker.com/r/hexpm/elixir/tags - for the build image
10+
# - https://hub.docker.com/_/debian/tags?name=trixie-20251208-slim - for the release image
11+
# - https://pkgs.org/ - resource for finding needed packages
12+
# - Ex: docker.io/hexpm/elixir:1.15.7-erlang-26.2.1-debian-trixie-20251208-slim
13+
#
14+
ARG ELIXIR_VERSION=1.15.7
15+
ARG OTP_VERSION=26.2.1
16+
ARG DEBIAN_VERSION=trixie-20251208-slim
17+
18+
ARG BUILDER_IMAGE="docker.io/hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}"
19+
ARG RUNNER_IMAGE="docker.io/debian:${DEBIAN_VERSION}"
20+
21+
FROM ${BUILDER_IMAGE} AS builder
22+
23+
# install build dependencies
24+
RUN apt-get update \
25+
&& apt-get install -y --no-install-recommends build-essential git \
26+
&& rm -rf /var/lib/apt/lists/*
27+
28+
# prepare build dir
29+
WORKDIR /app
30+
31+
# install hex + rebar
32+
RUN mix local.hex --force \
33+
&& mix local.rebar --force
34+
35+
# set build ENV
36+
ENV MIX_ENV="prod"
37+
38+
# install mix dependencies
39+
COPY mix.exs mix.lock ./
40+
RUN mix deps.get --only $MIX_ENV
41+
RUN mkdir config
42+
43+
# copy compile-time config files before we compile dependencies
44+
# to ensure any relevant config change will trigger the dependencies
45+
# to be re-compiled.
46+
COPY config/config.exs config/${MIX_ENV}.exs config/
47+
RUN mix deps.compile
48+
49+
RUN mix assets.setup
50+
51+
COPY priv priv
52+
53+
COPY lib lib
54+
55+
# Compile the release
56+
RUN mix compile
57+
58+
COPY assets assets
59+
60+
# compile assets
61+
RUN mix assets.deploy
62+
63+
# Changes to config/runtime.exs don't require recompiling the code
64+
COPY config/runtime.exs config/
65+
66+
COPY rel rel
67+
RUN mix release
68+
69+
# start a new build stage so that the final image will only contain
70+
# the compiled release and other runtime necessities
71+
FROM ${RUNNER_IMAGE} AS final
72+
73+
RUN apt-get update \
74+
&& apt-get install -y --no-install-recommends libstdc++6 openssl libncurses6 locales ca-certificates \
75+
&& rm -rf /var/lib/apt/lists/*
76+
77+
# Set the locale
78+
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen \
79+
&& locale-gen
80+
81+
ENV LANG=en_US.UTF-8
82+
ENV LANGUAGE=en_US:en
83+
ENV LC_ALL=en_US.UTF-8
84+
85+
WORKDIR "/app"
86+
RUN chown nobody /app
87+
88+
# set runner ENV
89+
ENV MIX_ENV="prod"
90+
91+
# Only copy the final release from the build stage
92+
COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/ares ./
93+
94+
USER nobody
95+
96+
# If using an environment that doesn't automatically reap zombie processes, it is
97+
# advised to add an init process such as tini via `apt-get install`
98+
# above and adding an entrypoint. See https://github.com/krallin/tini for details
99+
# ENTRYPOINT ["/tini", "--"]
100+
101+
CMD ["/app/bin/server"]

assets/package-lock.json

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

assets/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"dependencies": {
3+
"tailwindcss": "^4.1.18"
4+
}
5+
}

lib/ares/release.ex

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
defmodule Ares.Release do
2+
@moduledoc """
3+
Used for executing DB release tasks when run in production without Mix
4+
installed.
5+
"""
6+
@app :ares
7+
8+
def migrate do
9+
load_app()
10+
11+
for repo <- repos() do
12+
{:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true))
13+
end
14+
end
15+
16+
def rollback(repo, version) do
17+
load_app()
18+
{:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :down, to: version))
19+
end
20+
21+
defp repos do
22+
Application.fetch_env!(@app, :ecto_repos)
23+
end
24+
25+
defp load_app do
26+
# Many platforms require SSL when connecting to the database
27+
Application.ensure_all_started(:ssl)
28+
Application.ensure_loaded(@app)
29+
end
30+
end

lib/ares_web/components/core_components.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ defmodule AresWeb.CoreComponents do
5757
id={@id}
5858
phx-click={JS.push("lv:clear-flash", value: %{key: @kind}) |> hide("##{@id}")}
5959
role="alert"
60-
class="toast toast-top toast-end z-50"
60+
class="toast toast-top toast-end z-100"
6161
{@rest}
6262
>
6363
<div class={[

lib/ares_web/components/layouts/root.html.heex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
</script>
3232
</head>
3333
<body class="text-white font-vt323">
34-
<.navbar user={if @current_scope, do: @current_scope.user} fixed />
34+
<.navbar user={if @current_scope, do: @current_scope.user} />
3535
<div class="mt-24">
3636
{@inner_content}
3737
</div>

lib/ares_web/components/navbar.ex

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,17 @@ defmodule AresWeb.Components.Navbar do
99
@doc """
1010
Renders the navigation header with mobile menu support.
1111
"""
12-
attr :fixed, :boolean, default: false
1312
attr :user, :map, default: nil
1413

1514
def navbar(assigns) do
1615
~H"""
1716
<header
1817
id="page-header"
19-
class={[
20-
"z-50 flex w-full items-center justify-between border-b border-white/10 px-4 sm:px-6 md:px-8 py-3 sm:py-4 text-white font-inter",
21-
if(@fixed,
22-
do: "fixed-header fixed top-0 bg-black shadow-lg",
23-
else: "absolute bottom-0"
24-
)
25-
]}
18+
class="z-60 flex w-full h-24 items-center justify-between px-4 sm:px-6 md:px-8 py-3 sm:py-4 text-white font-inter fixed top-0 backdrop-blur bg-linear-to-b from-black/90 to-black/30"
2619
>
27-
<a class="flex items-center gap-2 sm:gap-4 hover:text-primary" href="/">
20+
<.link class="flex items-center gap-2 sm:gap-4 hover:text-primary" navigate="/">
2821
<img src="/images/logo-cesium.svg" alt="Cesium" class="object-fill w-32" />
29-
</a>
22+
</.link>
3023
<div>
3124
<div class="flex items-center gap-4 sm:gap-6">
3225
<nav class="hidden sm:block">
@@ -50,17 +43,17 @@ defmodule AresWeb.Components.Navbar do
5043
</.link>
5144
</li>
5245
<li>
53-
<a class="hover:text-primary transition-colors" href="/faqs">
46+
<.link class="hover:text-primary transition-colors" navigate="/faqs">
5447
FAQs
55-
</a>
48+
</.link>
5649
</li>
5750
<li>
58-
<a
51+
<.link
5952
class="hover:text-primary transition-colors"
60-
href="https://2024.bugsbyte.org/"
53+
href="https://2025.bugsbyte.org/"
6154
>
6255
Previous edition
63-
</a>
56+
</.link>
6457
</li>
6558
<li>
6659
<.link
@@ -72,12 +65,12 @@ defmodule AresWeb.Components.Navbar do
7265
</li>
7366
<%= if @user && @user.is_admin do %>
7467
<li>
75-
<a
68+
<.link
7669
class="hover:text-primary transition-colors text-white"
77-
href="/admin"
70+
navigate="/admin"
7871
>
7972
Admin
80-
</a>
73+
</.link>
8174
</li>
8275
<% end %>
8376
<li class="relative">
@@ -121,9 +114,12 @@ defmodule AresWeb.Components.Navbar do
121114
<button
122115
id="open-nav-button"
123116
type="button"
124-
class="btn sm:hidden text-white bg-black bg-opacity-70 p-2 rounded hover:bg-opacity-90 border border-white border-opacity-30"
117+
class="sm:hidden text-white p-2 rounded hover:bg-opacity-90"
125118
aria-label="Navigation"
126-
phx-click={JS.toggle(to: "#menu-modal")}
119+
phx-click={
120+
JS.toggle(to: "#menu-modal")
121+
|> JS.add_class("overflow-hidden", to: "body")
122+
}
127123
>
128124
<svg class="w-6 h-6 sm:w-8 sm:h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
129125
<path
@@ -140,16 +136,16 @@ defmodule AresWeb.Components.Navbar do
140136
141137
<div
142138
id="menu-modal"
143-
class="hidden fixed inset-0 bg-black px-4 sm:px-8 py-4 text-white z-[100] font-inter"
139+
class="hidden fixed inset-0 bg-black px-4 sm:px-8 py-4 text-white z-100 font-inter"
144140
>
145141
<div class="space-y-4 w-full h-full" role="dialog" aria-modal="true">
146142
<header class="text-right">
147143
<button
148144
id="close-nav-button"
149145
type="button"
150-
class="btn text-white bg-black bg-opacity-70 p-2 rounded hover:bg-opacity-90 border border-white border-opacity-30"
146+
class="text-white p-2 rounded hover:bg-opacity-90"
151147
aria-label="Close navigation"
152-
phx-click={JS.toggle(to: "#menu-modal")}
148+
phx-click={JS.toggle(to: "#menu-modal") |> JS.remove_class("overflow-hidden", to: "body")}
153149
>
154150
<svg
155151
class="w-6 h-6 sm:w-8 sm:h-8"
@@ -225,12 +221,12 @@ defmodule AresWeb.Components.Navbar do
225221
</a>
226222
</li>
227223
<li>
228-
<a
224+
<.link
229225
class="block py-3 sm:py-4 text-center text-lg sm:text-xl hover:text-primary transition-colors"
230-
href="https://2024.bugsbyte.org/"
226+
href="https://2025.bugsbyte.org/"
231227
>
232228
Previous edition
233-
</a>
229+
</.link>
234230
</li>
235231
<li>
236232
<.link

lib/ares_web/live/app/team-formation.ex

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,18 +121,16 @@ defmodule AresWeb.AppLive.TeamFormation do
121121
<% end %>
122122
<%= if @tab == "join" do %>
123123
<div class="mb-12">
124-
<div class="mb-8 flex flex-row justify-between items-center">
124+
<div class="mb-8 flex flex-col sm:flex-row gap-6 justify-between items-center">
125125
<div>
126126
<h2 class="text-3xl font-resegrg mb-2">Join a Team</h2>
127127
<p class="text-xl text-gray-400">
128128
Browse available teams and find your perfect match
129129
</p>
130130
</div>
131-
<div class="">
132-
<.button phx-click="use-code" class="btn btn-primary text-xl uppercase">
131+
<.button phx-click="use-code" class="btn btn-primary w-full sm:w-auto text-xl uppercase">
133132
<.icon name="hero-key" class="w-5 h-5 mr-2" /> Use code
134133
</.button>
135-
</div>
136134
</div>
137135
138136
<%= if Enum.empty?(@available_teams) do %>
@@ -237,13 +235,13 @@ defmodule AresWeb.AppLive.TeamFormation do
237235
<% end %>
238236
<div class="bg-gray rounded-lg p-8 border border-gray-800">
239237
<div class="flex items-center gap-3 mb-6">
240-
<.icon name="hero-information-circle" class="w-8 h-8 text-pink" />
238+
<.icon name="hero-information-circle" class="w-8 h-8 text-primary" />
241239
<h3 class="text-2xl uppercase">Important Information</h3>
242240
</div>
243241
244242
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 font-inter text-sm">
245243
<div class="flex items-start gap-4">
246-
<div class="flex-shrink-0 w-10 h-10 bg-pink rounded-lg flex items-center justify-center">
244+
<div class="shrink-0 w-10 h-10 bg-primary rounded-lg flex items-center justify-center">
247245
<.icon name="hero-users" class="w-5 h-5 text-white" />
248246
</div>
249247
<div>
@@ -253,7 +251,7 @@ defmodule AresWeb.AppLive.TeamFormation do
253251
</div>
254252
255253
<div class="flex items-start gap-4">
256-
<div class="flex-shrink-0 w-10 h-10 bg-pink rounded-lg flex items-center justify-center">
254+
<div class="shrink-0 w-10 h-10 bg-primary rounded-lg flex items-center justify-center">
257255
<.icon name="hero-clipboard-document-check" class="w-5 h-5 text-white" />
258256
</div>
259257
<div>
@@ -265,7 +263,7 @@ defmodule AresWeb.AppLive.TeamFormation do
265263
</div>
266264
267265
<div class="flex items-start gap-4">
268-
<div class="flex-shrink-0 w-10 h-10 bg-pink rounded-lg flex items-center justify-center">
266+
<div class="shrink-0 w-10 h-10 bg-primary rounded-lg flex items-center justify-center">
269267
<.icon name="hero-magnifying-glass" class="w-5 h-5 text-white" />
270268
</div>
271269
<div>

0 commit comments

Comments
 (0)