@@ -13,12 +13,13 @@ defmodule AlgoraWeb.ContractLive do
13
13
alias Algora.Organizations.Member
14
14
alias Algora.Payments
15
15
alias Algora.Repo
16
+ alias Algora.Types.USD
16
17
alias Algora.Util
17
18
alias Algora.Workspace
18
19
19
20
require Logger
20
21
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 } ]
22
23
23
24
defmodule RewardBountyForm do
24
25
@ moduledoc false
@@ -28,7 +29,7 @@ defmodule AlgoraWeb.ContractLive do
28
29
29
30
@ primary_key false
30
31
embedded_schema do
31
- field :amount , Algora.Types. USD
32
+ field :amount , USD
32
33
field :tip_percentage , :decimal
33
34
end
34
35
@@ -108,8 +109,7 @@ defmodule AlgoraWeb.ContractLive do
108
109
109
110
ticket_body_html = Algora.Markdown . render ( bounty . ticket . description )
110
111
111
- reward_changeset =
112
- RewardBountyForm . changeset ( % RewardBountyForm { } , % { amount: bounty . amount } )
112
+ reward_changeset = RewardBountyForm . changeset ( % RewardBountyForm { } , % { amount: bounty . amount , tip_percentage: 0 } )
113
113
114
114
{ :ok , thread } = Chat . get_or_create_bounty_thread ( bounty )
115
115
messages = thread . id |> Chat . list_messages ( ) |> Repo . preload ( :sender )
@@ -138,6 +138,7 @@ defmodule AlgoraWeb.ContractLive do
138
138
|> assign ( :total_paid , total_paid )
139
139
|> assign ( :ticket_body_html , ticket_body_html )
140
140
|> assign ( :show_reward_modal , false )
141
+ |> assign ( :show_authorize_modal , false )
141
142
|> assign ( :selected_context , nil )
142
143
|> assign ( :line_items , [ ] )
143
144
|> assign ( :thread , thread )
@@ -146,7 +147,7 @@ defmodule AlgoraWeb.ContractLive do
146
147
|> assign ( :reward_form , to_form ( reward_changeset ) )
147
148
|> assign_contractor ( bounty . shared_with )
148
149
|> assign_transactions ( )
149
- |> assign_line_items ( ) }
150
+ |> assign_line_items ( reward_changeset ) }
150
151
end
151
152
152
153
@ impl true
@@ -200,22 +201,24 @@ defmodule AlgoraWeb.ContractLive do
200
201
{ :noreply , assign ( socket , :show_reward_modal , true ) }
201
202
end
202
203
204
+ @ impl true
205
+ def handle_event ( "authorize" , _params , socket ) do
206
+ { :noreply , assign ( socket , :show_authorize_modal , true ) }
207
+ end
208
+
203
209
@ impl true
204
210
def handle_event ( "close_drawer" , _params , socket ) do
205
211
{ :noreply , close_drawers ( socket ) }
206
212
end
207
213
208
214
@ impl true
209
215
def handle_event ( "validate_reward" , % { "reward_bounty_form" => params } , socket ) do
216
+ changeset = RewardBountyForm . changeset ( % RewardBountyForm { } , params )
217
+
210
218
{ :noreply ,
211
219
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 ) }
219
222
end
220
223
221
224
@ impl true
@@ -345,9 +348,11 @@ defmodule AlgoraWeb.ContractLive do
345
348
<% end %>
346
349
347
350
<%= 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 >
351
356
<% end %>
352
357
</ div >
353
358
</ . card_content >
@@ -404,7 +409,7 @@ defmodule AlgoraWeb.ContractLive do
404
409
</ div >
405
410
</ dt >
406
411
</ div >
407
- < . button phx-click = "reward " >
412
+ < . button phx-click = "authorize " >
408
413
Authorize
409
414
</ . button >
410
415
</ dl >
@@ -414,7 +419,16 @@ defmodule AlgoraWeb.ContractLive do
414
419
< . card :if = { length ( @ transactions ) > 0 } >
415
420
< . card_header >
416
421
< . 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 >
418
432
</ . card_title >
419
433
</ . card_header >
420
434
< . card_content class = "pt-0 " >
@@ -589,7 +603,7 @@ defmodule AlgoraWeb.ContractLive do
589
603
</ div >
590
604
</ div >
591
605
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 " >
593
607
< . drawer_header >
594
608
< . drawer_title > Authorize payment</ . drawer_title >
595
609
< . drawer_description >
@@ -612,8 +626,88 @@ defmodule AlgoraWeb.ContractLive do
612
626
field = { @ reward_form [ :amount ] }
613
627
disabled
614
628
/>
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
+ />
615
709
616
- <%!-- < div>
710
+ < div >
617
711
< . label > Tip</ . label >
618
712
< div class = "mt-2 " >
619
713
< . radio_group
@@ -622,7 +716,7 @@ defmodule AlgoraWeb.ContractLive do
622
716
options = { tip_options ( ) }
623
717
/>
624
718
</ div >
625
- </div> --%>
719
+ </ div >
626
720
</ div >
627
721
</ . card_content >
628
722
</ . card >
@@ -674,7 +768,7 @@ defmodule AlgoraWeb.ContractLive do
674
768
Cancel
675
769
</ . button >
676
770
< . 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 " />
678
772
</ . button >
679
773
</ div >
680
774
</ div >
@@ -684,12 +778,12 @@ defmodule AlgoraWeb.ContractLive do
684
778
"""
685
779
end
686
780
687
- defp assign_line_items ( socket ) do
781
+ defp assign_line_items ( socket , changeset ) do
688
782
line_items =
689
783
Bounties . generate_line_items (
690
784
% {
691
785
owner: socket . assigns . bounty . owner ,
692
- amount: calculate_final_amount ( socket . assigns . reward_form . source )
786
+ amount: calculate_final_amount ( changeset )
693
787
} ,
694
788
bounty: socket . assigns . bounty ,
695
789
ticket_ref: socket . assigns . ticket_ref ,
@@ -728,7 +822,9 @@ defmodule AlgoraWeb.ContractLive do
728
822
end
729
823
730
824
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 )
732
828
end
733
829
734
830
defp assign_contractor ( socket , shared_with ) do
0 commit comments