@@ -13,12 +13,13 @@ defmodule AlgoraWeb.ContractLive do
1313 alias Algora.Organizations.Member
1414 alias Algora.Payments
1515 alias Algora.Repo
16+ alias Algora.Types.USD
1617 alias Algora.Util
1718 alias Algora.Workspace
1819
1920 require Logger
2021
21- # defp tip_options, do: [{"None", 0}, {"10%", 10}, {"20%", 20}, {"50%", 50}]
22+ defp tip_options , do: [ { "None" , 0 } , { "10%" , 10 } , { "20%" , 20 } , { "50%" , 50 } ]
2223
2324 defmodule RewardBountyForm do
2425 @ moduledoc false
@@ -28,7 +29,7 @@ defmodule AlgoraWeb.ContractLive do
2829
2930 @ primary_key false
3031 embedded_schema do
31- field :amount , Algora.Types. USD
32+ field :amount , USD
3233 field :tip_percentage , :decimal
3334 end
3435
@@ -108,8 +109,7 @@ defmodule AlgoraWeb.ContractLive do
108109
109110 ticket_body_html = Algora.Markdown . render ( bounty . ticket . description )
110111
111- reward_changeset =
112- RewardBountyForm . changeset ( % RewardBountyForm { } , % { amount: bounty . amount } )
112+ reward_changeset = RewardBountyForm . changeset ( % RewardBountyForm { } , % { amount: bounty . amount , tip_percentage: 0 } )
113113
114114 { :ok , thread } = Chat . get_or_create_bounty_thread ( bounty )
115115 messages = thread . id |> Chat . list_messages ( ) |> Repo . preload ( :sender )
@@ -138,6 +138,7 @@ defmodule AlgoraWeb.ContractLive do
138138 |> assign ( :total_paid , total_paid )
139139 |> assign ( :ticket_body_html , ticket_body_html )
140140 |> assign ( :show_reward_modal , false )
141+ |> assign ( :show_authorize_modal , false )
141142 |> assign ( :selected_context , nil )
142143 |> assign ( :line_items , [ ] )
143144 |> assign ( :thread , thread )
@@ -146,7 +147,7 @@ defmodule AlgoraWeb.ContractLive do
146147 |> assign ( :reward_form , to_form ( reward_changeset ) )
147148 |> assign_contractor ( bounty . shared_with )
148149 |> assign_transactions ( )
149- |> assign_line_items ( ) }
150+ |> assign_line_items ( reward_changeset ) }
150151 end
151152
152153 @ impl true
@@ -200,22 +201,24 @@ defmodule AlgoraWeb.ContractLive do
200201 { :noreply , assign ( socket , :show_reward_modal , true ) }
201202 end
202203
204+ @ impl true
205+ def handle_event ( "authorize" , _params , socket ) do
206+ { :noreply , assign ( socket , :show_authorize_modal , true ) }
207+ end
208+
203209 @ impl true
204210 def handle_event ( "close_drawer" , _params , socket ) do
205211 { :noreply , close_drawers ( socket ) }
206212 end
207213
208214 @ impl true
209215 def handle_event ( "validate_reward" , % { "reward_bounty_form" => params } , socket ) do
216+ changeset = RewardBountyForm . changeset ( % RewardBountyForm { } , params )
217+
210218 { :noreply ,
211219 socket
212- |> assign ( :reward_form , to_form ( RewardBountyForm . changeset ( % RewardBountyForm { } , params ) ) )
213- |> assign_line_items ( ) }
214- end
215-
216- @ impl true
217- def handle_event ( "assign_line_items" , % { "reward_bounty_form" => _params } , socket ) do
218- { :noreply , assign_line_items ( socket ) }
220+ |> assign ( :reward_form , to_form ( changeset ) )
221+ |> assign_line_items ( changeset ) }
219222 end
220223
221224 @ impl true
@@ -345,9 +348,11 @@ defmodule AlgoraWeb.ContractLive do
345348 <% end %>
346349
347350 <%= if _transaction = Enum . find ( @ transactions , fn tx -> tx . type = = :debit end ) do %>
348- < . badge variant = "success " class = "mb-auto " >
349- Active
350- </ . badge >
351+ < div class = "flex flex-col gap-4 items-end " >
352+ < . badge variant = "success " class = "mb-auto " >
353+ Active
354+ </ . badge >
355+ </ div >
351356 <% end %>
352357 </ div >
353358 </ . card_content >
@@ -404,7 +409,7 @@ defmodule AlgoraWeb.ContractLive do
404409 </ div >
405410 </ dt >
406411 </ div >
407- < . button phx-click = "reward " >
412+ < . button phx-click = "authorize " >
408413 Authorize
409414 </ . button >
410415 </ dl >
@@ -414,7 +419,16 @@ defmodule AlgoraWeb.ContractLive do
414419 < . card :if = { length ( @ transactions ) > 0 } >
415420 < . card_header >
416421 < . card_title >
417- Timeline
422+ < div class = "flex justify-between gap-4 " >
423+ Timeline
424+ <%= if @ can_create_bounty do %>
425+ <%= if _transaction = Enum . find ( @ transactions , fn tx -> tx . type = = :debit and tx . status = = :succeeded end ) do %>
426+ < . button phx-click = "reward " >
427+ Make payment
428+ </ . button >
429+ <% end %>
430+ <% end %>
431+ </ div >
418432 </ . card_title >
419433 </ . card_header >
420434 < . card_content class = "pt-0 " >
@@ -589,7 +603,7 @@ defmodule AlgoraWeb.ContractLive do
589603 </ div >
590604 </ div >
591605
592- < . drawer :if = { @ current_user } show = { @ show_reward_modal } on_cancel = "close_drawer " >
606+ < . drawer :if = { @ current_user } show = { @ show_authorize_modal } on_cancel = "close_drawer " >
593607 < . drawer_header >
594608 < . drawer_title > Authorize payment</ . drawer_title >
595609 < . drawer_description >
@@ -612,8 +626,88 @@ defmodule AlgoraWeb.ContractLive do
612626 field = { @ reward_form [ :amount ] }
613627 disabled
614628 />
629+ </ div >
630+ </ . card_content >
631+ </ . card >
632+ < . card >
633+ < . card_header >
634+ < . card_title > Payment Summary</ . card_title >
635+ </ . card_header >
636+ < . card_content class = "pt-0 " >
637+ < dl class = "space-y-4 " >
638+ <%= for line_item <- @ line_items do %>
639+ < div class = "flex justify-between " >
640+ < dt class = "flex items-center gap-4 " >
641+ <%= if line_item . image do %>
642+ < . avatar >
643+ < . avatar_image src = { line_item . image } />
644+ < . avatar_fallback >
645+ { Util . initials ( line_item . title ) }
646+ </ . avatar_fallback >
647+ </ . avatar >
648+ <% else %>
649+ < div class = "w-10 " />
650+ <% end %>
651+ < div >
652+ < div class = "font-medium " > { line_item . title } </ div >
653+ < div class = "text-muted-foreground text-sm " > { line_item . description } </ div >
654+ </ div >
655+ </ dt >
656+ < dd class = "font-display font-semibold tabular-nums " >
657+ { Money . to_string! ( line_item . amount ) }
658+ </ dd >
659+ </ div >
660+ <% end %>
661+ < div class = "h-px bg-border " />
662+ < div class = "flex justify-between " >
663+ < dt class = "flex items-center gap-4 " >
664+ < div class = "w-10 " />
665+ < div class = "font-medium " > Total due</ div >
666+ </ dt >
667+ < dd class = "font-display font-semibold tabular-nums " >
668+ { LineItem . gross_amount ( @ line_items ) }
669+ </ dd >
670+ </ div >
671+ </ dl >
672+ </ . card_content >
673+ </ . card >
674+ </ div >
675+ < div class = "ml-auto flex gap-4 " >
676+ < . button variant = "secondary " phx-click = "close_drawer " type = "button " >
677+ Cancel
678+ </ . button >
679+ < . button type = "submit " >
680+ Authorize with Stripe < . icon name = "tabler-arrow-right " class = "-mr-1 ml-2 h-4 w-4 " />
681+ </ . button >
682+ </ div >
683+ </ div >
684+ </ . form >
685+ </ . drawer_content >
686+ </ . drawer >
687+ < . drawer :if = { @ current_user } show = { @ show_reward_modal } on_cancel = "close_drawer " >
688+ < . drawer_header >
689+ < . drawer_title > Pay contract</ . drawer_title >
690+ < . drawer_description >
691+ You can pay any amount at any time.
692+ </ . drawer_description >
693+ </ . drawer_header >
694+ < . drawer_content class = "mt-4 " >
695+ < . form for = { @ reward_form } phx-change = "validate_reward " phx-submit = "pay_with_stripe " >
696+ < div class = "flex flex-col gap-8 " >
697+ < div class = "grid grid-cols-2 gap-8 " >
698+ < . card >
699+ < . card_header >
700+ < . card_title > Payment Details</ . card_title >
701+ </ . card_header >
702+ < . card_content class = "pt-0 " >
703+ < div class = "space-y-4 " >
704+ < . input
705+ label = "Amount "
706+ icon = "tabler-currency-dollar "
707+ field = { @ reward_form [ :amount ] }
708+ />
615709
616- <%!-- < div>
710+ < div >
617711 < . label > Tip</ . label >
618712 < div class = "mt-2 " >
619713 < . radio_group
@@ -622,7 +716,7 @@ defmodule AlgoraWeb.ContractLive do
622716 options = { tip_options ( ) }
623717 />
624718 </ div >
625- </div> --%>
719+ </ div >
626720 </ div >
627721 </ . card_content >
628722 </ . card >
@@ -674,7 +768,7 @@ defmodule AlgoraWeb.ContractLive do
674768 Cancel
675769 </ . button >
676770 < . button type = "submit " >
677- Authorize with Stripe < . icon name = "tabler-arrow-right " class = "-mr-1 ml-2 h-4 w-4 " />
771+ Pay with Stripe < . icon name = "tabler-arrow-right " class = "-mr-1 ml-2 h-4 w-4 " />
678772 </ . button >
679773 </ div >
680774 </ div >
@@ -684,12 +778,12 @@ defmodule AlgoraWeb.ContractLive do
684778 """
685779 end
686780
687- defp assign_line_items ( socket ) do
781+ defp assign_line_items ( socket , changeset ) do
688782 line_items =
689783 Bounties . generate_line_items (
690784 % {
691785 owner: socket . assigns . bounty . owner ,
692- amount: calculate_final_amount ( socket . assigns . reward_form . source )
786+ amount: calculate_final_amount ( changeset )
693787 } ,
694788 bounty: socket . assigns . bounty ,
695789 ticket_ref: socket . assigns . ticket_ref ,
@@ -728,7 +822,9 @@ defmodule AlgoraWeb.ContractLive do
728822 end
729823
730824 defp close_drawers ( socket ) do
731- assign ( socket , :show_reward_modal , false )
825+ socket
826+ |> assign ( :show_reward_modal , false )
827+ |> assign ( :show_authorize_modal , false )
732828 end
733829
734830 defp assign_contractor ( socket , shared_with ) do
0 commit comments