@@ -287,6 +287,7 @@ defmodule AlgoraWeb.Org.JobLive do
287287 contributions = { Map . get ( @ contributions_map , match . user . id , [ ] ) }
288288 contract_type = "bring_your_own "
289289 anonymized = { @ current_org . hiring_subscription != :active }
290+ heatmap_data = { Map . get ( @ heatmaps_map , match . user . id ) }
290291 />
291292 </ div >
292293 <% end %>
@@ -608,12 +609,39 @@ defmodule AlgoraWeb.Org.JobLive do
608609
609610 contributions_map = fetch_applicants_contributions ( developers , socket . assigns . job . tech_stack )
610611
612+ # Fetch heatmaps for all developers
613+ heatmaps_map =
614+ developers
615+ |> Enum . map ( & & 1 . id )
616+ |> AlgoraCloud.Profiles . list_heatmaps ( )
617+ |> Map . new ( fn heatmap -> { heatmap . user_id , heatmap . data } end )
618+
619+ # Trigger async sync for missing heatmaps if connected
620+ if connected? ( socket ) do
621+ missing_heatmap_users =
622+ developers
623+ |> Enum . reject ( & Map . has_key? ( heatmaps_map , & 1 . id ) )
624+
625+ if length ( missing_heatmap_users ) > 0 do
626+ enqueue_heatmap_sync ( missing_heatmap_users )
627+ end
628+ end
629+
611630 socket
612631 |> assign ( :developers , developers )
613632 |> assign ( :applicants , sort_by_contributions ( socket . assigns . job , all_applicants , contributions_map ) )
614633 |> assign ( :matches , matches )
615634 |> assign ( :truncated_matches , truncated_matches )
616635 |> assign ( :contributions_map , contributions_map )
636+ |> assign ( :heatmaps_map , heatmaps_map )
637+ end
638+
639+ defp enqueue_heatmap_sync ( users ) do
640+ Task . start ( fn ->
641+ for user <- users do
642+ AlgoraCloud.Profiles . sync_heatmap_by ( id: user . id )
643+ end
644+ end )
617645 end
618646
619647 defp enqueue_screening ( socket , users ) do
@@ -969,11 +997,56 @@ defmodule AlgoraWeb.Org.JobLive do
969997 <% end %>
970998 </ div >
971999 </ div >
1000+
1001+ < . heatmap_display :if = { @ heatmap_data && not @ anonymized } heatmap_data = { @ heatmap_data } />
1002+ </ div >
1003+ </ div >
1004+ """
1005+ end
1006+
1007+ defp heatmap_display ( assigns ) do
1008+ ~H"""
1009+ < div class = "mt-4 " >
1010+ < div class = "flex items-center justify-between mb-2 " >
1011+ < div class = "text-xs text-muted-foreground uppercase font-semibold " >
1012+ { get_in ( @ heatmap_data , [ "totalContributions" ] ) } contributions in the last year
1013+ </ div >
1014+ </ div >
1015+ < div class = "grid grid-cols-[repeat(17,1fr)] gap-1 " >
1016+ <%= for week <- get_in ( @ heatmap_data , [ "weeks" ] ) |> Enum . take ( - 17 ) do %>
1017+ < div class = "grid grid-rows-7 gap-1 " >
1018+ <%= for day <- week [ "contributionDays" ] do %>
1019+ < div
1020+ class = { "h-3 w-3 rounded-sm #{ get_contribution_color ( day [ "contributionCount" ] ) } " }
1021+ title = { "#{ day [ "contributionCount" ] } contributions on #{ format_date ( day [ "date" ] ) } " }
1022+ >
1023+ </ div >
1024+ <% end %>
1025+ </ div >
1026+ <% end %>
9721027 </ div >
9731028 </ div >
9741029 """
9751030 end
9761031
1032+ defp get_contribution_color ( count ) do
1033+ cond do
1034+ count == 0 -> "bg-muted/50"
1035+ count in 1 .. 5 -> "bg-success-400/40"
1036+ count in 6 .. 10 -> "bg-success-400/50"
1037+ count in 11 .. 15 -> "bg-success-400/70"
1038+ count in 16 .. 20 -> "bg-success-400/90"
1039+ true -> "bg-success-400"
1040+ end
1041+ end
1042+
1043+ defp format_date ( date_string ) do
1044+ date_string
1045+ |> String . replace ( "T00:00:00.000+00:00" , "" )
1046+ |> Date . from_iso8601! ( )
1047+ |> Calendar . strftime ( "%B %d, %Y" )
1048+ end
1049+
9771050 defp social_links do
9781051 [
9791052 { :website , "tabler-world" } ,
0 commit comments