diff --git a/Gemfile b/Gemfile index a26be3baf..aa67caa0b 100644 --- a/Gemfile +++ b/Gemfile @@ -27,6 +27,9 @@ gem "turbo-rails" # Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev] gem "stimulus-rails" +# A framework for creating reusable, testable & encapsulated view components +gem "view_component" + # Build JSON APIs with ease [https://github.com/rails/jbuilder] gem "jbuilder" diff --git a/Gemfile.lock b/Gemfile.lock index 6a3c37deb..75e4c61b0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -443,6 +443,10 @@ GEM tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (2.4.2) + view_component (3.7.0) + activesupport (>= 5.2.0, < 8.0) + concurrent-ruby (~> 1.0) + method_source (~> 1.0) warden (1.2.9) rack (>= 2.0.9) web-console (4.2.0) @@ -516,6 +520,7 @@ DEPENDENCIES traceroute turbo-rails tzinfo-data + view_component web-console RUBY VERSION diff --git a/app/assets/stylesheets/custom.scss b/app/assets/stylesheets/custom.scss index 2953fee98..21a7b34c9 100644 --- a/app/assets/stylesheets/custom.scss +++ b/app/assets/stylesheets/custom.scss @@ -1,7 +1,7 @@ /** * Custom Styling * ----------------------------------------------------------------------------- -* [NOTE] Please avoid writing custom css if you can help it! +* [NOTE] Please avoid writing custom css if you can help it! * Prefer to use the Bootstrap utility classes to override styles or follow * the theme. * ----------------------------------------------------------------------------- @@ -9,3 +9,7 @@ label.required:after { content: " *"; } + +.cursor-pointer { + cursor: pointer; +} diff --git a/app/components/avatar_component.rb b/app/components/avatar_component.rb new file mode 100644 index 000000000..b22f49d63 --- /dev/null +++ b/app/components/avatar_component.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +# Use Avatar::Component to represent users with image or initials. +class AvatarComponent < ViewComponent::Base + SIZES = { + x_small: "avatar-xs", + small: "avatar-sm", + medium: "avatar-md", + large: "avatar-lg", + x_large: "avatar-xl", + xx_large: "avatar-xxl" + }.freeze + + # + # @example 1|Show avatar with initials + # <%= component "avatar", alt: "JT" %> + # + # @example 2|Show avatar with image_tag + # <%= component "avatar", src: "avatar_#{@order.subject.gender}.svg", + # size: :medium) %> + # + # @example 2|Show avatar with image_tag with default params + # <%= component "avatar", src: "avatar_#{@order.subject.gender}.svg"%> + # + # @param src [String] Specifies the URL of the image. + # @param alt[String] Alternate text for an image, if the image cannot be displayed. + + def initialize(alt: "avatar", size: :medium, **system_arguments) + @alt = alt + @system_arguments = system_arguments + @classes = "rounded-circle cursor-pointer avatar #{SIZES.fetch(size)}" + end + + def avatar_with_image + image_tag @system_arguments[:src], class: @classes, alt: @alt + end + + def avatar_with_initials + tag.div(tag.span(@alt), class: @classes, style: "background-color: #{avatar_color(@alt)}; display: flex; align-items: center; justify-content: center;") + end + + def avatar_color(text) + avatar_colors = ["#feb2b2", "#b3e4fc", "#d6bcfa", "#faf089", "#9ae6b4", "#f0e2ba", "#fbb6ce", "#dadada"] + + avatar_colors[text.ord % avatar_colors.length] + end + + def call + if @system_arguments[:src].present? + avatar_with_image + else + avatar_with_initials + end + end +end diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index 90ee61c6e..e3c390f00 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -27,18 +27,18 @@