Skip to content

Commit cf8a6f4

Browse files
committed
Add edit seasons
1 parent 45ad4a5 commit cf8a6f4

File tree

5 files changed

+211
-120
lines changed

5 files changed

+211
-120
lines changed

services/app/apps/codebattle/lib/codebattle_web/controllers/ext_api/task_pack_controller.ex

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ defmodule CodebattleWeb.ExtApi.TaskPackController do
3838

3939
case find_or_create_task_pack(params) do
4040
{:ok, _task_pack} ->
41-
send_resp(conn, 201, "Created task pack with name: #{params.name}, task_ids: #{task_ids}")
41+
send_resp(
42+
conn,
43+
201,
44+
"Created task pack with name: #{inspect(params.name)}, task_ids: #{inspect(task_ids)}"
45+
)
4246

4347
{:error, %{errors: errors}} ->
4448
errors = Map.new(errors, fn {k, {v, _}} -> {k, v} end)
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
defmodule CodebattleWeb.Live.Admin.Season.EditView do
2+
use CodebattleWeb, :live_view
3+
4+
alias Codebattle.Season
5+
6+
@impl true
7+
def mount(%{"id" => id}, _session, socket) do
8+
season = Season.get!(id)
9+
changeset = Season.changeset(season)
10+
11+
{:ok,
12+
assign(socket,
13+
season: season,
14+
changeset: changeset,
15+
layout: {CodebattleWeb.LayoutView, :empty}
16+
)}
17+
end
18+
19+
@impl true
20+
def handle_event("validate", %{"season" => season_params}, socket) do
21+
changeset =
22+
socket.assigns.season
23+
|> Season.changeset(season_params)
24+
|> Map.put(:action, :validate)
25+
26+
{:noreply, assign(socket, changeset: changeset)}
27+
end
28+
29+
def handle_event("update", %{"season" => season_params}, socket) do
30+
case Season.update(socket.assigns.season, season_params) do
31+
{:ok, _season} ->
32+
{:noreply,
33+
socket
34+
|> put_flash(:info, "Season updated successfully")
35+
|> push_navigate(to: Routes.admin_season_index_view_path(socket, :index))}
36+
37+
{:error, changeset} ->
38+
{:noreply, assign(socket, changeset: changeset)}
39+
end
40+
end
41+
42+
def handle_event("cancel", _params, socket) do
43+
{:noreply, push_navigate(socket, to: Routes.admin_season_index_view_path(socket, :index))}
44+
end
45+
46+
@impl true
47+
def render(assigns) do
48+
~H"""
49+
<div class="container mt-5">
50+
<div class="d-flex justify-content-between align-items-center mb-4">
51+
<h1>
52+
<i class="bi bi-pencil-square"></i> Edit Season
53+
</h1>
54+
<a
55+
href={Routes.admin_season_index_view_path(@socket, :index)}
56+
class="btn btn-outline-secondary"
57+
>
58+
<i class="bi bi-arrow-left"></i> Back to List
59+
</a>
60+
</div>
61+
62+
<div class="card shadow-sm">
63+
<div class="card-header bg-primary text-white">
64+
<span><i class="bi bi-pencil"></i> Season Information</span>
65+
</div>
66+
<div class="card-body">
67+
<.form :let={f} for={@changeset} phx-change="validate" phx-submit="update" class="row g-3">
68+
<div class="col-md-6">
69+
{label(f, :name, class: "form-label")}
70+
{text_input(f, :name, class: "form-control", placeholder: "e.g., Spring Season")}
71+
{error_tag(f, :name)}
72+
</div>
73+
74+
<div class="col-md-6">
75+
{label(f, :year, class: "form-label")}
76+
{number_input(f, :year, class: "form-control", placeholder: "e.g., 2024")}
77+
{error_tag(f, :year)}
78+
</div>
79+
80+
<div class="col-md-6">
81+
{label(f, :starts_at, "Start Date", class: "form-label")}
82+
{date_input(f, :starts_at, class: "form-control")}
83+
{error_tag(f, :starts_at)}
84+
</div>
85+
86+
<div class="col-md-6">
87+
{label(f, :ends_at, "End Date", class: "form-label")}
88+
{date_input(f, :ends_at, class: "form-control")}
89+
{error_tag(f, :ends_at)}
90+
</div>
91+
92+
<div class="col-12">
93+
<div class="btn-group" role="group">
94+
{submit("Save Changes", class: "btn btn-primary", phx_disable_with: "Saving...")}
95+
<button type="button" class="btn btn-secondary" phx-click="cancel">
96+
Cancel
97+
</button>
98+
</div>
99+
</div>
100+
</.form>
101+
</div>
102+
</div>
103+
104+
<div class="card shadow-sm mt-4">
105+
<div class="card-header bg-light">
106+
<span><i class="bi bi-info-circle"></i> Current Values</span>
107+
</div>
108+
<div class="card-body">
109+
<div class="row">
110+
<div class="col-md-6 mb-3">
111+
<label class="form-label text-muted">ID</label>
112+
<div class="fw-bold">{@season.id}</div>
113+
</div>
114+
115+
<div class="col-md-6 mb-3">
116+
<label class="form-label text-muted">Duration</label>
117+
<div class="fw-bold">
118+
{Date.diff(@season.ends_at, @season.starts_at)} days
119+
</div>
120+
</div>
121+
122+
<div class="col-12 mb-3">
123+
<label class="form-label text-muted">Status</label>
124+
<div>
125+
<%= cond do %>
126+
<% Date.compare(@season.starts_at, Date.utc_today()) == :gt -> %>
127+
<span class="badge bg-info">
128+
<i class="bi bi-clock"></i> Upcoming
129+
</span>
130+
<% Date.compare(@season.ends_at, Date.utc_today()) == :lt -> %>
131+
<span class="badge bg-secondary">
132+
<i class="bi bi-check-circle"></i> Completed
133+
</span>
134+
<% true -> %>
135+
<span class="badge bg-success">
136+
<i class="bi bi-play-circle"></i> Active
137+
</span>
138+
<% end %>
139+
</div>
140+
</div>
141+
</div>
142+
</div>
143+
</div>
144+
</div>
145+
"""
146+
end
147+
end

services/app/apps/codebattle/lib/codebattle_web/live/admin/season_index_view.ex

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,12 @@ defmodule CodebattleWeb.Live.Admin.Season.IndexView do
165165
>
166166
<i class="bi bi-eye"></i> View
167167
</a>
168+
<a
169+
href={Routes.admin_season_edit_view_path(@socket, :edit, season.id)}
170+
class="btn btn-sm btn-outline-secondary"
171+
>
172+
<i class="bi bi-pencil"></i> Edit
173+
</a>
168174
<button
169175
class="btn btn-sm btn-outline-danger"
170176
phx-click="delete"

services/app/apps/codebattle/lib/codebattle_web/live/admin/season_show_view.ex

Lines changed: 52 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -6,48 +6,15 @@ defmodule CodebattleWeb.Live.Admin.Season.ShowView do
66
@impl true
77
def mount(%{"id" => id}, _session, socket) do
88
season = Season.get!(id)
9-
changeset = Season.changeset(season)
109

1110
{:ok,
1211
assign(socket,
1312
season: season,
14-
changeset: changeset,
15-
editing: false,
1613
layout: {CodebattleWeb.LayoutView, :empty}
1714
)}
1815
end
1916

2017
@impl true
21-
def handle_event("toggle_edit", _params, socket) do
22-
editing = !socket.assigns.editing
23-
changeset = Season.changeset(socket.assigns.season)
24-
{:noreply, assign(socket, editing: editing, changeset: changeset)}
25-
end
26-
27-
def handle_event("validate", %{"season" => season_params}, socket) do
28-
changeset =
29-
socket.assigns.season
30-
|> Season.changeset(season_params)
31-
|> Map.put(:action, :validate)
32-
33-
{:noreply, assign(socket, changeset: changeset)}
34-
end
35-
36-
def handle_event("update", %{"season" => season_params}, socket) do
37-
case Season.update(socket.assigns.season, season_params) do
38-
{:ok, season} ->
39-
changeset = Season.changeset(season)
40-
41-
{:noreply,
42-
socket
43-
|> assign(season: season, changeset: changeset, editing: false)
44-
|> put_flash(:info, "Season updated successfully")}
45-
46-
{:error, changeset} ->
47-
{:noreply, assign(socket, changeset: changeset)}
48-
end
49-
end
50-
5118
def handle_event("delete", _params, socket) do
5219
case Season.delete(socket.assigns.season) do
5320
{:ok, _season} ->
@@ -81,110 +48,76 @@ defmodule CodebattleWeb.Live.Admin.Season.ShowView do
8148
<div class="card-header bg-primary text-white">
8249
<div class="d-flex justify-content-between align-items-center">
8350
<span><i class="bi bi-info-circle"></i> Season Information</span>
84-
<button :if={!@editing} class="btn btn-sm btn-outline-light" phx-click="toggle_edit">
51+
<a
52+
href={Routes.admin_season_edit_view_path(@socket, :edit, @season.id)}
53+
class="btn btn-sm btn-outline-light"
54+
>
8555
<i class="bi bi-pencil"></i> Edit
86-
</button>
56+
</a>
8757
</div>
8858
</div>
8959
<div class="card-body">
90-
<%= if @editing do %>
91-
<.form :let={f} for={@changeset} phx-change="validate" phx-submit="update" class="row g-3">
92-
<div class="col-md-6">
93-
{label(f, :name, class: "form-label")}
94-
{text_input(f, :name, class: "form-control")}
95-
{error_tag(f, :name)}
96-
</div>
97-
98-
<div class="col-md-6">
99-
{label(f, :year, class: "form-label")}
100-
{number_input(f, :year, class: "form-control")}
101-
{error_tag(f, :year)}
102-
</div>
103-
104-
<div class="col-md-6">
105-
{label(f, :starts_at, "Start Date", class: "form-label")}
106-
{date_input(f, :starts_at, class: "form-control")}
107-
{error_tag(f, :starts_at)}
108-
</div>
109-
110-
<div class="col-md-6">
111-
{label(f, :ends_at, "End Date", class: "form-label")}
112-
{date_input(f, :ends_at, class: "form-control")}
113-
{error_tag(f, :ends_at)}
114-
</div>
115-
116-
<div class="col-12">
117-
<div class="btn-group" role="group">
118-
{submit("Save Changes", class: "btn btn-primary", phx_disable_with: "Saving...")}
119-
<button type="button" class="btn btn-secondary" phx-click="toggle_edit">
120-
Cancel
121-
</button>
122-
</div>
123-
</div>
124-
</.form>
125-
<% else %>
126-
<div class="row">
127-
<div class="col-md-6 mb-3">
128-
<label class="form-label text-muted">ID</label>
129-
<div class="fw-bold">{@season.id}</div>
130-
</div>
60+
<div class="row">
61+
<div class="col-md-6 mb-3">
62+
<label class="form-label text-muted">ID</label>
63+
<div class="fw-bold">{@season.id}</div>
64+
</div>
13165
132-
<div class="col-md-6 mb-3">
133-
<label class="form-label text-muted">Name</label>
134-
<div class="fw-bold">{@season.name}</div>
135-
</div>
66+
<div class="col-md-6 mb-3">
67+
<label class="form-label text-muted">Name</label>
68+
<div class="fw-bold">{@season.name}</div>
69+
</div>
13670
137-
<div class="col-md-6 mb-3">
138-
<label class="form-label text-muted">Year</label>
139-
<div class="fw-bold">{@season.year}</div>
140-
</div>
71+
<div class="col-md-6 mb-3">
72+
<label class="form-label text-muted">Year</label>
73+
<div class="fw-bold">{@season.year}</div>
74+
</div>
14175
142-
<div class="col-md-6 mb-3">
143-
<label class="form-label text-muted">Duration</label>
144-
<div class="fw-bold">
145-
{Date.diff(@season.ends_at, @season.starts_at)} days
146-
</div>
76+
<div class="col-md-6 mb-3">
77+
<label class="form-label text-muted">Duration</label>
78+
<div class="fw-bold">
79+
{Date.diff(@season.ends_at, @season.starts_at)} days
14780
</div>
81+
</div>
14882
149-
<div class="col-md-6 mb-3">
150-
<label class="form-label text-muted">Start Date</label>
151-
<div class="fw-bold">
152-
{Calendar.strftime(@season.starts_at, "%B %d, %Y")}
153-
</div>
83+
<div class="col-md-6 mb-3">
84+
<label class="form-label text-muted">Start Date</label>
85+
<div class="fw-bold">
86+
{Calendar.strftime(@season.starts_at, "%B %d, %Y")}
15487
</div>
88+
</div>
15589
156-
<div class="col-md-6 mb-3">
157-
<label class="form-label text-muted">End Date</label>
158-
<div class="fw-bold">
159-
{Calendar.strftime(@season.ends_at, "%B %d, %Y")}
160-
</div>
90+
<div class="col-md-6 mb-3">
91+
<label class="form-label text-muted">End Date</label>
92+
<div class="fw-bold">
93+
{Calendar.strftime(@season.ends_at, "%B %d, %Y")}
16194
</div>
95+
</div>
16296
163-
<div class="col-12 mb-3">
164-
<label class="form-label text-muted">Status</label>
165-
<div>
166-
<%= cond do %>
167-
<% Date.compare(@season.starts_at, Date.utc_today()) == :gt -> %>
168-
<span class="badge bg-info">
169-
<i class="bi bi-clock"></i> Upcoming
170-
</span>
171-
<% Date.compare(@season.ends_at, Date.utc_today()) == :lt -> %>
172-
<span class="badge bg-secondary">
173-
<i class="bi bi-check-circle"></i> Completed
174-
</span>
175-
<% true -> %>
176-
<span class="badge bg-success">
177-
<i class="bi bi-play-circle"></i> Active
178-
</span>
179-
<% end %>
180-
</div>
97+
<div class="col-12 mb-3">
98+
<label class="form-label text-muted">Status</label>
99+
<div>
100+
<%= cond do %>
101+
<% Date.compare(@season.starts_at, Date.utc_today()) == :gt -> %>
102+
<span class="badge bg-info">
103+
<i class="bi bi-clock"></i> Upcoming
104+
</span>
105+
<% Date.compare(@season.ends_at, Date.utc_today()) == :lt -> %>
106+
<span class="badge bg-secondary">
107+
<i class="bi bi-check-circle"></i> Completed
108+
</span>
109+
<% true -> %>
110+
<span class="badge bg-success">
111+
<i class="bi bi-play-circle"></i> Active
112+
</span>
113+
<% end %>
181114
</div>
182115
</div>
183-
<% end %>
116+
</div>
184117
</div>
185118
</div>
186119
187-
<div :if={!@editing} class="card shadow-sm border-danger">
120+
<div class="card shadow-sm border-danger">
188121
<div class="card-header bg-danger text-white">
189122
<i class="bi bi-exclamation-triangle"></i> Danger Zone
190123
</div>

services/app/apps/codebattle/lib/codebattle_web/router.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ defmodule CodebattleWeb.Router do
8585
live("/users", CodebattleWeb.Live.Admin.User.IndexView, :index)
8686
live("/users/:id", CodebattleWeb.Live.Admin.UserShowView, :show)
8787
live("/seasons", CodebattleWeb.Live.Admin.Season.IndexView, :index)
88+
live("/seasons/:id/edit", CodebattleWeb.Live.Admin.Season.EditView, :edit)
8889
live("/seasons/:id", CodebattleWeb.Live.Admin.Season.ShowView, :show)
8990
end
9091

0 commit comments

Comments
 (0)