From f706d2818ac82d02d48ae55eebabdf2c05d1b849 Mon Sep 17 00:00:00 2001
From: Teal Bauer <git@teal.is>
Date: Fri, 24 May 2024 15:12:30 +0200
Subject: [PATCH] colorful avatars

---
 app/models/user.rb                            | 29 +++++++++++++++++++
 app/views/application/_user_avatar.html.erb   |  3 ++
 app/views/conferences/show.html.erb           |  2 +-
 app/views/sessions/_assignment_form.html.erb  |  2 +-
 app/views/sessions/show.html.erb              |  2 +-
 ...0240524124124_add_avatar_color_to_users.rb |  5 ++++
 db/schema.rb                                  |  3 +-
 db/seeds.rb                                   |  1 +
 8 files changed, 43 insertions(+), 4 deletions(-)
 create mode 100644 app/views/application/_user_avatar.html.erb
 create mode 100644 db/migrate/20240524124124_add_avatar_color_to_users.rb

diff --git a/app/models/user.rb b/app/models/user.rb
index 379658a..429f19a 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,2 +1,31 @@
 class User < ApplicationRecord
+  after_initialize :set_avatar_color
+
+  def text_color
+    r, g, b = avatar_color.delete_prefix('#').chars.each_slice(2).map { |hex| hex.join.to_i(16) }
+
+    # Calculate relative luminance (WCAG 2.0 formula)
+    luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255
+
+    # Choose text color based on luminance threshold
+    luminance > 0.5 ? "#000000" : "#ffffff"
+  end
+
+  def initials
+    name.split(/\s+/).map(&:first).join('')
+  end
+
+  def set_avatar_color
+    return unless self.avatar_color.nil?
+
+    r = rand(256)
+    g = rand(256)
+    b = rand(256)
+
+    # r = [r, 128].max
+    # g = [g, 128].max
+    # b = [b, 128].max
+
+    self.avatar_color = "##{r.to_s(16).rjust(2, '0')}#{g.to_s(16).rjust(2, '0')}#{b.to_s(16).rjust(2, '0')}"
+  end
 end
diff --git a/app/views/application/_user_avatar.html.erb b/app/views/application/_user_avatar.html.erb
new file mode 100644
index 0000000..ff2f9b4
--- /dev/null
+++ b/app/views/application/_user_avatar.html.erb
@@ -0,0 +1,3 @@
+<div class="relative inline-flex items-center justify-center h-8 p-2 overflow-hidden rounded-full" style="background-color: <%= user.avatar_color %>" title="<%= user.name %>">
+    <span class="font-medium" style="color: <%= user.text_color %>"><%= user.name %></span>
+</div>
diff --git a/app/views/conferences/show.html.erb b/app/views/conferences/show.html.erb
index 767c8a1..8cba38a 100644
--- a/app/views/conferences/show.html.erb
+++ b/app/views/conferences/show.html.erb
@@ -59,7 +59,7 @@ current_time = @sessions_by_date[@conference.days.first].first.starts_at.advance
               <ul class="list-disc">
                 <% session.assignments.each do |assignment| %>
                   <li>
-                    <span class="assigned-user"><%= assignment.user.name %></span>
+                    <span class="assigned-user"><%= render partial: 'application/user_avatar', locals: { user: assignment.user } %></span>
                     <%= link_to '[Remove]', conference_session_assignments_path(session.conference, session, user_id: assignment.user_id), data: { turbo_method: :delete, confirm: 'Are you sure?' } %>
                   </li>
                 <% end %>
diff --git a/app/views/sessions/_assignment_form.html.erb b/app/views/sessions/_assignment_form.html.erb
index 3092c10..d9a4d98 100644
--- a/app/views/sessions/_assignment_form.html.erb
+++ b/app/views/sessions/_assignment_form.html.erb
@@ -1,5 +1,5 @@
 <%= form_with url: conference_session_assignments_path(session.conference, session), method: :post, local: true do |f| %>
-  <%= f.select :user_id, options_from_collection_for_select(@users, :id, :name) %>
+  <%= f.select :user_id, options_from_collection_for_select(@users - session.assignments.collect(&:user), :id, :name) %>
   <%= f.submit "Assign", class: 'primary' %>
   <% if @assignment&.errors&.any? %>
     <div class="alert alert-danger">
diff --git a/app/views/sessions/show.html.erb b/app/views/sessions/show.html.erb
index c77f779..e98f422 100644
--- a/app/views/sessions/show.html.erb
+++ b/app/views/sessions/show.html.erb
@@ -10,7 +10,7 @@
   <ul>
     <% @session.assignments.each do |assignment| %>
       <li>
-        <%= assignment.user.name %>
+        <%= render partial: 'application/user_avatar', locals: { user: assignment.user } %>
         <%= link_to '[Remove]', conference_session_assignments_path(@session.conference, @session, user_id: assignment.user_id), data: { turbo_method: :delete, confirm: 'Are you sure?' } %>
       </li>
     <% end %>
diff --git a/db/migrate/20240524124124_add_avatar_color_to_users.rb b/db/migrate/20240524124124_add_avatar_color_to_users.rb
new file mode 100644
index 0000000..c082e37
--- /dev/null
+++ b/db/migrate/20240524124124_add_avatar_color_to_users.rb
@@ -0,0 +1,5 @@
+class AddAvatarColorToUsers < ActiveRecord::Migration[7.1]
+  def change
+    add_column :users, :avatar_color, :string
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index eff275d..322e2d2 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema[7.1].define(version: 2024_05_24_091736) do
+ActiveRecord::Schema[7.1].define(version: 2024_05_24_124124) do
   create_table "assignments", force: :cascade do |t|
     t.integer "user_id", null: false
     t.integer "session_id", null: false
@@ -187,6 +187,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_05_24_091736) do
     t.string "email"
     t.datetime "created_at", null: false
     t.datetime "updated_at", null: false
+    t.string "avatar_color"
   end
 
   add_foreign_key "assignments", "sessions"
diff --git a/db/seeds.rb b/db/seeds.rb
index 766011b..20d6c02 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -32,4 +32,5 @@ end
 
 User.find_or_create_by!(email: "teal@teal.is") do |user|
   user.name = "Teal"
+  user.avatar_color = "#14bfb5"
 end
-- 
GitLab