Skip to content

Commit 088ccbf

Browse files
committed
feat: implement GitHub contribution heatmaps for match cards
- Add heatmap data fetching to assign_applicants function - Fetch heatmaps for all developers using AlgoraCloud.Profiles.list_heatmaps - Add async heatmap syncing for users without existing heatmap data - Implement heatmap_display component with 17-week contribution grid - Add contribution color coding from green (low) to dark green (high) - Include total contributions count and date tooltips - Only show heatmaps for non-anonymized matches - Improve candidate evaluation with visual contribution history
1 parent d52feab commit 088ccbf

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

lib/algora_web/live/org/job_live.ex

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)