diff --git a/Gemfile b/Gemfile index c5e2aa88..0d5e9e97 100644 --- a/Gemfile +++ b/Gemfile @@ -29,6 +29,7 @@ gem "bcrypt", "~> 3.1.20" # Other gem "bootsnap", require: false +gem "inline_svg" gem "puma", ">= 5.0" gem "tzinfo-data", platforms: %i[windows jruby] gem "validates_timeliness", "~> 7.0.0.beta1" diff --git a/Gemfile.lock b/Gemfile.lock index b845e5a0..727505a6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -223,6 +223,9 @@ GEM actionpack (>= 6.0.0) activesupport (>= 6.0.0) railties (>= 6.0.0) + inline_svg (1.9.0) + activesupport (>= 3.0) + nokogiri (>= 1.6) io-console (0.7.2) irb (1.13.2) rdoc (>= 4.0.0) @@ -347,7 +350,7 @@ GEM regexp_parser (2.9.2) reline (0.5.9) io-console (~> 0.5) - rexml (3.3.1) + rexml (3.3.2) strscan rouge (4.3.0) rspec (3.13.0) @@ -514,6 +517,7 @@ DEPENDENCIES faker fuubar importmap-rails + inline_svg letter_opener (~> 1.10) mission_control-jobs propshaft diff --git a/app/assets/images/main-logo-with-date.svg b/app/assets/images/main-logo-with-date.svg new file mode 100644 index 00000000..2826793c --- /dev/null +++ b/app/assets/images/main-logo-with-date.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/main-logo.svg b/app/assets/images/main-logo.svg new file mode 100644 index 00000000..7f7b2d51 --- /dev/null +++ b/app/assets/images/main-logo.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/app/assets/stylesheets/application.tailwind.css b/app/assets/stylesheets/application.tailwind.css index bd6213e1..47e74961 100644 --- a/app/assets/stylesheets/application.tailwind.css +++ b/app/assets/stylesheets/application.tailwind.css @@ -1,3 +1,14 @@ @tailwind base; @tailwind components; -@tailwind utilities; \ No newline at end of file +@tailwind utilities; + +div.field_with_errors > label { + @apply mb-2 italic font-bold text-red; +} + +div.field_with_errors > input { + @apply w-full bg-transparent border-2 border-red + rounded-md text-white placeholder:text-white/50 + focus:bg-white focus:text-black focus:placeholder-gray + focus:border-white focus:ring-white mb-2 +} \ No newline at end of file diff --git a/app/controllers/concerns/authentication.rb b/app/controllers/concerns/authentication.rb index 6414e533..6995625b 100644 --- a/app/controllers/concerns/authentication.rb +++ b/app/controllers/concerns/authentication.rb @@ -27,7 +27,7 @@ def authenticate_user! authenticate_user if !user_signed_in? - redirect_to new_session_path, alert: t("controllers.concerns.authentication.unauthorized") + redirect_to new_session_path end end diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb index c98a8eaa..88181c28 100644 --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -1,6 +1,4 @@ class MainController < ApplicationController - allow_unauthenticated_access - def index end end diff --git a/app/controllers/password_resets_controller.rb b/app/controllers/password_resets_controller.rb index 8e4429f4..0aecfa0a 100644 --- a/app/controllers/password_resets_controller.rb +++ b/app/controllers/password_resets_controller.rb @@ -19,7 +19,7 @@ def create ).password_reset.deliver_later end - redirect_to new_session_path, notice: t("controllers.password_resets.create.notice") + redirect_to post_submit_password_reset_path end def update diff --git a/app/helpers/navigation_helper.rb b/app/helpers/navigation_helper.rb new file mode 100644 index 00000000..3aaa18e5 --- /dev/null +++ b/app/helpers/navigation_helper.rb @@ -0,0 +1,6 @@ +module NavigationHelper + # Todo: A better approach would be to support authenticated root and unauthenticated root in routes.rb + def homepage_link + user_signed_in? ? root_path : new_session_path + end +end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 251755fe..5d6c07b8 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,28 +1,37 @@ - - - RailsWorld - - <%= csrf_meta_tags %> - <%= csp_meta_tag %> - <%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %> + + + RailsWorld + + <%= csrf_meta_tags %> + <%= csp_meta_tag %> + <%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %> - <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> - <%= javascript_importmap_tags %> - + <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> + <%= javascript_importmap_tags %> + - -
-
<%= notice %>
-
<%= alert %>
- <% if user_signed_in? %> - <%= link_to "Edit Password", edit_password_path %> - <%= button_to "Log out", session_path, method: :delete %> - <% else %> - <%= link_to "Sign Up", new_registration_path %> - <%= link_to "Log in", new_session_path %> - <% end %> - <%= yield %> -
- + +
+ <% if !current_page?(new_session_path) %> +
+
+ <%= link_to homepage_link do %> + <%= inline_svg_tag("main-logo.svg", class: "w-full") %> + <% end %> +
+
+ <% end %> + <% flash.each do |type, message| %> + <% if message.present? && message.is_a?(String) %> +
<%= notice %>
+
<%= alert %>
+ <% end %> + <% end %> + <%= yield %> + <% if user_signed_in? %> + <%= button_to "Log out", session_path, method: :delete %> + <% end %> +
+ diff --git a/app/views/password_resets/edit.html.erb b/app/views/password_resets/edit.html.erb index 333edd06..92fdb96b 100644 --- a/app/views/password_resets/edit.html.erb +++ b/app/views/password_resets/edit.html.erb @@ -1,23 +1,30 @@ -

Reset Your Password

+
+ <%= form_with model: @user, url: password_reset_path(token: params[:token]), class: "flex flex-col h-full justify-between w-full max-w-screen-sm" do |form| %> +
+
+

Reset your password

+
-<%= form_with model: @user, url: password_reset_path(token: params[:token]) do |form| %> - <% if form.object.errors.any? %> - <% form.object.errors.full_messages.each do |message| %> -
<%= message %>
- <% end %> - <% end %> +
+ <%= render partial: "shared/form_errors", locals: { errors: form.object.errors.full_messages } %> -
- <%= form.label :password %> - <%= form.password_field :password %> -
+
+
+ <%= form.label :password, class: "text-white italic font-bold mb-2" %> + <%= form.password_field :password, required: true, placeholder: "You know how a strong password goes, right?", class: "bg-transparent border border-2 border-white rounded-md text-white placeholder-white focus:bg-white focus:text-black focus:placeholder-gray focus:border-white focus:ring-white" %> +
-
- <%= form.label :password_confirmation %> - <%= form.password_field :password_confirmation %> -
+
+ <%= form.label :password_confirmation, class: "text-white italic font-bold mb-2" %> + <%= form.password_field :password_confirmation, required: true, placeholder: "Confirm strong password", class: "bg-transparent border border-2 border-white rounded-md text-white placeholder-white focus:bg-white focus:text-black focus:placeholder-gray focus:border-white focus:ring-white" %> +
+
-
- <%= form.submit "Reset Your Password" %> -
-<% end %> +
+ Just remembered your password? <%= link_to "Log in instead", new_session_path, class: "font-black italic underline text-white" %> +
+
+
+ <%= form.button "Reset Your Password", type: "submit", class: "w-full bg-red py-4 text-white font-black italic rounded-[10px] uppercase" %> + <% end %> +
diff --git a/app/views/password_resets/new.html.erb b/app/views/password_resets/new.html.erb index ea64ecff..e15b7a13 100644 --- a/app/views/password_resets/new.html.erb +++ b/app/views/password_resets/new.html.erb @@ -1,12 +1,23 @@ -

Reset Your Password

+
+ <%= form_with model: @user, url: password_reset_path, class: "flex flex-col h-full w-full max-w-screen-sm justify-between" do |form| %> +
+
+

Forgot Password

+

We'll send you a link to create a new password to the email address of your choice

+
-<%= form_with model: @user, url: password_reset_path do |form| %> -
- <%= form.label :email %> - <%= form.email_field :email %> -
+
+
+ <%= form.label :email, class: "text-white italic font-bold mb-2" %> + <%= form.email_field :email, required: true, placeholder: "email@example.com", class: "bg-transparent border border-2 border-white rounded-md text-white placeholder-white focus:bg-white focus:text-black focus:placeholder-gray focus:border-white focus:ring-white", data: { test_id: "email_field" } %> +
-
- <%= form.submit "Reset password" %> -
-<% end %> +
+ Just remembered your password? <%= link_to "Log in instead", new_session_path, class: "font-black italic underline text-white" %> +
+
+
+ + <%= form.button "Send recovery email", type: "submit", class: "w-full bg-red py-4 text-white font-black italic rounded-[10px] uppercase" %> + <% end %> +
diff --git a/app/views/password_resets/post_submit.html.erb b/app/views/password_resets/post_submit.html.erb new file mode 100644 index 00000000..925627aa --- /dev/null +++ b/app/views/password_resets/post_submit.html.erb @@ -0,0 +1,10 @@ +
+
+
+

Check your inbox

+

We've sent you a link to recover your password to the email you provided.

+
+ + <%= link_to "Return to login", new_session_path, class: "w-full bg-red py-4 text-white text-center font-black italic rounded-[10px] uppercase" %> +
+
diff --git a/app/views/registrations/new.html.erb b/app/views/registrations/new.html.erb index f1a6c724..bcab28d5 100644 --- a/app/views/registrations/new.html.erb +++ b/app/views/registrations/new.html.erb @@ -1,28 +1,37 @@ -

Sign Up

+
+ <%= form_with model: @user, url: registration_path, class: "flex flex-col h-full justify-between w-full max-w-screen-sm" do |form| %> +
+
+

Sign Up

+
-<%= form_with model: @user, url: registration_path do |form| %> - <% if form.object.errors.any? %> - <% form.object.errors.full_messages.each do |message| %> -
<%= message %>
- <% end %> - <% end %> +
+ <%= render partial: "shared/form_errors", locals: { errors: form.object.errors.full_messages } %> + +
+
+ <%= form.label :email, class: "text-white italic font-bold mb-2" %> + <%= form.email_field :email, required: true, placeholder: "email@example.com", data: { test_id: "email_field" }, class: "bg-transparent border border-2 border-white rounded-md text-white placeholder:text-white/50 focus:bg-white focus:text-black focus:placeholder-gray focus:border-white focus:ring-white" %> +
-
- <%= form.label :email %> - <%= form.email_field :email, data: { test_id: "email_field" } %> -
+
+ <%= form.label :password, class: "text-white italic font-bold mb-2" %> + <%= form.password_field :password, required: true, data: { test_id: "password_field" }, placeholder: "You know how a strong password goes, right?", class: "bg-transparent border border-2 border-white rounded-md text-white placeholder:text-white/50 focus:bg-white focus:text-black focus:placeholder-gray focus:border-white focus:ring-white mb-2" %> +

Password should contain at least 8 characters

+
-
- <%= form.label :password %> - <%= form.password_field :password, data: { test_id: "password_field" } %> -
+
+ <%= form.label :password_confirmation, class: "text-white italic font-bold mb-2" %> + <%= form.password_field :password_confirmation, required: true, data: { test_id: "password_confirmation_field" }, placeholder: "Confirm strong password", class: "bg-transparent border border-2 border-white rounded-md text-white placeholder:text-white/50 focus:bg-white focus:text-black focus:placeholder-gray focus:border-white focus:ring-white" %> +
+
-
- <%= form.label :password_confirmation %> - <%= form.password_field :password_confirmation, data: { test_id: "password_confirmation_field" } %> -
+
+ Already have an account? <%= link_to "Log in instead", new_session_path, class: "font-black italic underline text-white" %> +
+
+
-
- <%= form.submit "Sign Up", data: { test_id: "sign_up_button" } %> -
-<% end %> + <%= form.button "Sign Up", type: "submit", data: { test_id: "sign_up_button" }, class: "w-full bg-red py-4 text-white font-black italic rounded-[10px] uppercase" %> + <% end %> +
diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb index ef79ab62..7c40df9f 100644 --- a/app/views/sessions/new.html.erb +++ b/app/views/sessions/new.html.erb @@ -1,19 +1,33 @@ -

Log in

+
+ <%= form_with model: @user, url: session_path, class: "flex flex-col h-full justify-between w-full max-w-screen-sm" do |form| %> +
+ <%= inline_svg_tag("main-logo-with-date.svg", class: "w-full mb-10") %> +
+

Welcome!

+

Please log in to continue

+
-<%= form_with model: @user, url: session_path do |form| %> -
- <%= form.label :email %> - <%= form.email_field :email, data: { test_id: "email_field" } %> -
+
+
+
+ <%= form.label :email, class: "text-white italic font-bold mb-2" %> + <%= form.email_field :email, required: true, placeholder: "email@example.com", data: { test_id: "email_field" }, class: "bg-transparent border border-2 border-white rounded-md text-white placeholder-white focus:bg-white focus:text-black focus:placeholder-gray focus:border-white focus:ring-white transition-all" %> +
-
- <%= form.label :password %> - <%= form.password_field :password, data: { test_id: "password_field" } %> -
+
+ <%= form.label :password, class: "text-white italic font-bold mb-2" %> + <%= form.password_field :password, required: true, placeholder: "Password", data: { test_id: "password_field" }, class: "bg-transparent border border-2 border-white rounded-md text-white placeholder-white focus:bg-white focus:text-black focus:placeholder-gray focus:border-white focus:ring-white transition-all" %> +
+
-
- <%= form.submit "Log in", data: { test_id: "sign_in_button" } %> -
-<% end %> - -<%= link_to "Forgot your password?", new_password_reset_path %> +
+ <%= link_to "Forgot password?", new_password_reset_path, class: "font-black italic underline text-white mb-10" %> + <%= link_to "Sign up", new_registration_path, class: "font-black italic underline text-white" %> +
+
+
+
+ <%= form.button "Log in", type: "submit", data: { test_id: "sign_in_button" }, class: "w-full bg-red py-4 text-white font-black italic rounded-[10px] uppercase" %> +
+ <% end %> +
diff --git a/app/views/shared/_form_errors.html.erb b/app/views/shared/_form_errors.html.erb new file mode 100644 index 00000000..dd31f64c --- /dev/null +++ b/app/views/shared/_form_errors.html.erb @@ -0,0 +1,10 @@ +<% if local_assigns[:errors].any? %> +
+

The following errors were found:

+
    + <% local_assigns[:errors].each do |message| %> +
  1. <%= message %>
  2. + <% end %> +
+
+<% end %> diff --git a/config/environments/development.rb b/config/environments/development.rb index d6d3d088..c5d02975 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -63,6 +63,9 @@ # Highlight code that triggered database queries in logs. config.active_record.verbose_query_logs = true + config.assets.debug = true + config.assets.digest = false + # Highlight code that enqueued background job in logs. config.active_job.verbose_enqueue_logs = true diff --git a/config/locales/en.yml b/config/locales/en.yml index 297afaf0..b9251f17 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,8 +1,5 @@ en: controllers: - concerns: - authentication: - unauthorized: "You need to sign in or sign up before continuing." password_resets: create: notice: "Check your email to reset your password." diff --git a/config/routes.rb b/config/routes.rb index 96a018c0..972ff602 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,5 +9,7 @@ resource :registration, only: [:new, :create] resource :session, only: [:new, :create, :destroy] resource :password, only: [:edit, :update] - resource :password_reset, only: [:new, :create, :edit, :update] + resource :password_reset, only: [:new, :create, :edit, :update] do + get :post_submit + end end diff --git a/config/tailwind.config.js b/config/tailwind.config.js index 7cba2be2..8f38f935 100644 --- a/config/tailwind.config.js +++ b/config/tailwind.config.js @@ -10,7 +10,19 @@ module.exports = { theme: { extend: { fontFamily: { - sans: ['Inter var', ...defaultTheme.fontFamily.sans] + sans: ['Roboto', ...defaultTheme.fontFamily.sans] + }, + maxWidth: { + 'screen-sm': '425px' + }, + colors: { + gray: '#C6C6C8', + 'purple-dark': '#432463', + 'purple-light': '#4E2A73', + red: '#CB0C1C', + blue: '#0A4E6B', + 'green-dark': '#62C554', + 'green-light': '#D8F1D4' } } }, diff --git a/spec/controllers/password_resets_controller_spec.rb b/spec/controllers/password_resets_controller_spec.rb index bd7dfe3a..bf648050 100644 --- a/spec/controllers/password_resets_controller_spec.rb +++ b/spec/controllers/password_resets_controller_spec.rb @@ -25,7 +25,7 @@ expect { post :create, params: params }.to have_enqueued_mail(PasswordMailer, :password_reset) - expect(response).to redirect_to(new_session_path) + expect(response).to redirect_to(post_submit_password_reset_path) end end end diff --git a/spec/system/user_sign_in_spec.rb b/spec/system/user_sign_in_spec.rb index 62f87f69..e86233ec 100644 --- a/spec/system/user_sign_in_spec.rb +++ b/spec/system/user_sign_in_spec.rb @@ -6,7 +6,6 @@ it "redirects to the login page when trying to access another page" do visit edit_password_path expect(page).to have_current_path(new_session_path) - expect(page).to have_content("You need to sign in or sign up before continuing.") end context "when the user inputs invalid credentials" do