@@ -5,7 +5,6 @@ defmodule AlgoraWeb.BountyLive do
55 import Ecto.Changeset
66
77 alias Algora.Accounts
8- alias Algora.Accounts.User
98 alias Algora.Bounties
109 alias Algora.Bounties.Bounty
1110 alias Algora.Bounties.LineItem
@@ -43,6 +42,25 @@ defmodule AlgoraWeb.BountyLive do
4342 end
4443 end
4544
45+ defmodule ExclusiveBountyForm do
46+ @ moduledoc false
47+ use Ecto.Schema
48+
49+ import Ecto.Changeset
50+
51+ @ primary_key false
52+ embedded_schema do
53+ field :github_handle , :string
54+ field :deadline , :date
55+ end
56+
57+ def changeset ( form , attrs ) do
58+ form
59+ |> cast ( attrs , [ :github_handle , :deadline ] )
60+ |> validate_required ( [ :github_handle , :deadline ] )
61+ end
62+ end
63+
4664 @ impl true
4765 def mount ( % { "id" => bounty_id } , _session , socket ) do
4866 bounty =
@@ -65,12 +83,18 @@ defmodule AlgoraWeb.BountyLive do
6583
6684 contexts = contexts ( bounty )
6785
68- changeset =
86+ reward_changeset =
6987 RewardBountyForm . changeset ( % RewardBountyForm { } , % {
7088 tip_percentage: 0 ,
7189 amount: Money . to_decimal ( bounty . amount )
7290 } )
7391
92+ exclusive_changeset =
93+ ExclusiveBountyForm . changeset ( % ExclusiveBountyForm { } , % {
94+ github_handle: "" ,
95+ deadline: Date . utc_today ( )
96+ } )
97+
7498 { :ok ,
7599 socket
76100 |> assign ( :page_title , bounty . ticket . title )
@@ -80,9 +104,11 @@ defmodule AlgoraWeb.BountyLive do
80104 |> assign ( :ticket_body_html , ticket_body_html )
81105 |> assign ( :contexts , contexts )
82106 |> assign ( :show_reward_modal , false )
107+ |> assign ( :show_exclusive_modal , false )
83108 |> assign ( :selected_context , nil )
84109 |> assign ( :line_items , [ ] )
85- |> assign ( :reward_form , to_form ( changeset ) ) }
110+ |> assign ( :reward_form , to_form ( reward_changeset ) )
111+ |> assign ( :exclusive_form , to_form ( exclusive_changeset ) ) }
86112 end
87113
88114 @ impl true
@@ -103,8 +129,12 @@ defmodule AlgoraWeb.BountyLive do
103129 { :noreply , assign ( socket , :show_reward_modal , true ) }
104130 end
105131
132+ def handle_event ( "exclusive" , _params , socket ) do
133+ { :noreply , assign ( socket , :show_exclusive_modal , true ) }
134+ end
135+
106136 def handle_event ( "close_drawer" , _params , socket ) do
107- { :noreply , assign ( socket , :show_reward_modal , false ) }
137+ { :noreply , close_drawers ( socket ) }
108138 end
109139
110140 def handle_event ( "validate_reward" , % { "reward_bounty_form" => params } , socket ) do
@@ -133,6 +163,35 @@ defmodule AlgoraWeb.BountyLive do
133163 end
134164 end
135165
166+ def handle_event ( "validate_exclusive" , % { "exclusive_bounty_form" => params } , socket ) do
167+ { :noreply ,
168+ socket
169+ |> assign ( :exclusive_form , to_form ( ExclusiveBountyForm . changeset ( % ExclusiveBountyForm { } , params ) ) )
170+ |> assign_line_items ( ) }
171+ end
172+
173+ def handle_event ( "share_exclusive" , % { "exclusive_bounty_form" => params } , socket ) do
174+ changeset = ExclusiveBountyForm . changeset ( % ExclusiveBountyForm { } , params )
175+ bounty = socket . assigns . bounty
176+
177+ case apply_action ( changeset , :save ) do
178+ { :ok , data } ->
179+ case bounty
180+ |> Bounty . settings_changeset ( % { shared_with: Enum . uniq ( bounty . shared_with ++ [ data . github_handle ] ) } )
181+ |> Repo . update ( ) do
182+ { :ok , _ } ->
183+ { :noreply , socket |> put_flash ( :info , "Bounty shared" ) |> close_drawers ( ) }
184+
185+ { :error , _reason } ->
186+ Logger . error ( "Failed to share bounty: #{ inspect ( _reason ) } " )
187+ { :noreply , put_flash ( socket , :error , "Something went wrong" ) }
188+ end
189+
190+ { :error , changeset } ->
191+ { :noreply , assign ( socket , :exclusive_form , to_form ( changeset ) ) }
192+ end
193+ end
194+
136195 defp assign_selected_context ( socket , context_id ) do
137196 case Enum . find ( socket . assigns . contexts , & ( & 1 . id == context_id ) ) do
138197 nil ->
@@ -144,13 +203,17 @@ defmodule AlgoraWeb.BountyLive do
144203 end
145204
146205 defp assign_line_items ( socket ) do
147- line_items =
148- Bounties . generate_line_items (
149- % { amount: calculate_final_amount ( socket . assigns . reward_form . source ) } ,
150- ticket_ref: ticket_ref ( socket ) ,
151- recipient: socket . assigns . selected_context
152- )
153-
206+ # line_items =
207+ # Bounties.generate_line_items(
208+ # %{
209+ # owner: socket.assigns.selected_context,
210+ # amount: calculate_final_amount(socket.assigns.reward_form.source)
211+ # },
212+ # ticket_ref: ticket_ref(socket),
213+ # recipient: socket.assigns.selected_context
214+ # )
215+
216+ line_items = [ ]
154217 assign ( socket , :line_items , line_items )
155218 end
156219
@@ -264,14 +327,14 @@ defmodule AlgoraWeb.BountyLive do
264327 < . card_title >
265328 Shared with
266329 </ . card_title >
267- < . button phx-click = "invite " >
268- Invite
330+ < . button phx-click = "exclusive " >
331+ Share Exclusive
269332 </ . button >
270333 </ div >
271334 </ . card_header >
272335 < . card_content >
273336 < div class = "space-y-4 " >
274- < div class = "flex justify-between text-sm " >
337+ <%!-- < div class="flex justify-between text-sm">
275338 <span>
276339 <div class="flex items-center gap-4">
277340 <.avatar>
@@ -307,12 +370,12 @@ defmodule AlgoraWeb.BountyLive do
307370 </div>
308371 </span>
309372 </div>
310- <% end %>
311- <%= for user <- invited_users ( @ bounty ) do %>
373+ <% end %> --%>
374+ <%= for user <- @ bounty . shared_with do %>
312375 < div class = "flex justify-between text-sm " >
313376 < span >
314377 < div class = "flex items-center gap-4 " >
315- < . icon name = "tabler-mail " class = "h-10 w-10 text-muted-foreground " />
378+ < . icon name = "github " class = "h-10 w-10 text-muted-foreground " />
316379 < div >
317380 < p class = "font-medium " > { user } </ p >
318381 </ div >
@@ -327,6 +390,37 @@ defmodule AlgoraWeb.BountyLive do
327390 </ div >
328391 </ div >
329392
393+ < . drawer
394+ :if = { @ current_user }
395+ show = { @ show_exclusive_modal }
396+ on_cancel = "close_drawer "
397+ direction = "right "
398+ >
399+ < . drawer_header >
400+ < . drawer_title > Share Exclusive</ . drawer_title >
401+ < . drawer_description >
402+ Make this bounty exclusive to specific users
403+ </ . drawer_description >
404+ </ . drawer_header >
405+ < . drawer_content class = "mt-4 " >
406+ < . form for = { @ exclusive_form } phx-change = "validate_exclusive " phx-submit = "share_exclusive " >
407+ < div class = "flex flex-col gap-8 " >
408+ < div class = "space-y-4 " >
409+ < . input label = "GitHub handle " field = { @ exclusive_form [ :github_handle ] } />
410+ < . input type = "date " label = "Deadline " field = { @ exclusive_form [ :deadline ] } />
411+ </ div >
412+ < div class = "ml-auto flex gap-4 " >
413+ < . button variant = "secondary " phx-click = "close_drawer " type = "button " >
414+ Cancel
415+ </ . button >
416+ < . button type = "submit " >
417+ Submit
418+ </ . button >
419+ </ div >
420+ </ div >
421+ </ . form >
422+ </ . drawer_content >
423+ </ . drawer >
330424 < . drawer :if = { @ current_user } show = { @ show_reward_modal } on_cancel = "close_drawer " >
331425 < . drawer_header >
332426 < . drawer_title > Reward Bounty</ . drawer_title >
@@ -464,4 +558,10 @@ defmodule AlgoraWeb.BountyLive do
464558 defp bounty_frequency ( _bounty ) do
465559 "Monthly"
466560 end
561+
562+ defp close_drawers ( socket ) do
563+ socket
564+ |> assign ( :show_reward_modal , false )
565+ |> assign ( :show_exclusive_modal , false )
566+ end
467567end
0 commit comments