From be9e0609a4eb541d5afcab458ee90048fa25f4c0 Mon Sep 17 00:00:00 2001 From: Alfred Date: Mon, 19 Jan 2026 22:41:56 +0200 Subject: [PATCH 01/13] Add home page controller, user model, user controller with authentication - Update User model with email and password validations - Add authentication requirement to HomeController (before_action :authenticate_user!) - Create welcome index page with user greeting and sign out link - Implement full CRUD actions in UsersController - Configure Devise permitted parameters in ApplicationController - Add user resource routes --- app/controllers/application_controller.rb | 10 +++++ app/controllers/home_controller.rb | 3 ++ app/controllers/users_controller.rb | 46 +++++++++++++++++++++++ app/models/user.rb | 4 +- app/views/home/index.erb | 14 ++++++- app/views/home/index.html.erb | 13 +++++++ config/routes.rb | 4 ++ 7 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 app/views/home/index.html.erb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 09705d1..36b576c 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,2 +1,12 @@ class ApplicationController < ActionController::Base + protect_from_forgery with: :exception + + before_action :configure_permitted_parameters, if: :devise_controller? + + protected + + def configure_permitted_parameters + devise_parameter_sanitizer.permit(:sign_up, keys: [:email, :password, :password_confirmation]) + devise_parameter_sanitizer.permit(:account_update, keys: [:email, :password, :password_confirmation, :current_password]) + end end diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 9ec3adc..8517563 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -1,4 +1,7 @@ class HomeController < ApplicationController + before_action :authenticate_user! + def index + @user = current_user end end \ No newline at end of file diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 3004a55..3bee7f5 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,4 +1,50 @@ class UsersController < ApplicationController + before_action :authenticate_user! + before_action :set_user, only: [:show, :edit, :update, :destroy] + def index + @users = User.all + end + + def show + end + + def new + @user = User.new + end + + def create + @user = User.new(user_params) + if @user.save + redirect_to @user, notice: 'User was successfully created.' + else + render :new, status: :unprocessable_entity + end + end + + def edit + end + + def update + if @user.update(user_params) + redirect_to @user, notice: 'User was successfully updated.' + else + render :edit, status: :unprocessable_entity + end + end + + def destroy + @user.destroy + redirect_to users_url, notice: 'User was successfully deleted.' + end + + private + + def set_user + @user = User.find(params[:id]) + end + + def user_params + params.require(:user).permit(:email, :password, :password_confirmation) end end diff --git a/app/models/user.rb b/app/models/user.rb index a4defd2..85b7d42 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -3,5 +3,7 @@ class User < ApplicationRecord # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable - validates_uniqueness_of :email + + validates :email, presence: true, uniqueness: true + validates :password, presence: true, length: { minimum: 6 }, on: :create end diff --git a/app/views/home/index.erb b/app/views/home/index.erb index f47aba5..1508e4f 100644 --- a/app/views/home/index.erb +++ b/app/views/home/index.erb @@ -1 +1,13 @@ -

Welcome

\ No newline at end of file +
+

Welcome to Hospital Management System

+ + <% if user_signed_in? %> +

Hello, <%= current_user.email %>!

+

You are successfully logged in.

+ + + <% end %> +
\ No newline at end of file diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb new file mode 100644 index 0000000..1508e4f --- /dev/null +++ b/app/views/home/index.html.erb @@ -0,0 +1,13 @@ +
+

Welcome to Hospital Management System

+ + <% if user_signed_in? %> +

Hello, <%= current_user.email %>!

+

You are successfully logged in.

+ + + <% end %> +
\ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index f3cc3ca..f0324d9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,9 @@ Rails.application.routes.draw do devise_for :users + + # User management routes + resources :users + # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html # Defines the root path route ("/") From 6bbe8bcb08e1335727e9f0bffd7783c96e09d196 Mon Sep 17 00:00:00 2001 From: Alfred Date: Mon, 19 Jan 2026 23:07:16 +0200 Subject: [PATCH 02/13] Fix configuration and routing issues for authentication - Update Ruby version in Gemfile from 3.0.1 to 3.2.3 for compatibility - Add host: localhost to database.yml for PostgreSQL password auth - Change users resource path to /manage_users to avoid conflict with Devise routes - Fix Sign Out button using button_to for proper DELETE method in Rails 7 - Update Gemfile.lock with new gem versions --- Gemfile | 2 +- Gemfile.lock | 449 +++++++++++++++++++++++----------- app/views/home/index.html.erb | 2 +- config/database.yml | 1 + config/routes.rb | 4 +- 5 files changed, 313 insertions(+), 145 deletions(-) diff --git a/Gemfile b/Gemfile index a2cf1bd..9275df2 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ source "https://rubygems.org" git_source(:github) { |repo| "https://github.com/#{repo}.git" } -ruby "3.0.1" +ruby "3.2.3" # Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main" gem "rails", "~> 7.0.3", ">= 7.0.3.1" diff --git a/Gemfile.lock b/Gemfile.lock index da3d837..b2222ed 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,231 +1,291 @@ GEM remote: https://rubygems.org/ specs: - actioncable (7.0.3.1) - actionpack (= 7.0.3.1) - activesupport (= 7.0.3.1) + actioncable (7.0.10) + actionpack (= 7.0.10) + activesupport (= 7.0.10) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (7.0.3.1) - actionpack (= 7.0.3.1) - activejob (= 7.0.3.1) - activerecord (= 7.0.3.1) - activestorage (= 7.0.3.1) - activesupport (= 7.0.3.1) + actionmailbox (7.0.10) + actionpack (= 7.0.10) + activejob (= 7.0.10) + activerecord (= 7.0.10) + activestorage (= 7.0.10) + activesupport (= 7.0.10) mail (>= 2.7.1) net-imap net-pop net-smtp - actionmailer (7.0.3.1) - actionpack (= 7.0.3.1) - actionview (= 7.0.3.1) - activejob (= 7.0.3.1) - activesupport (= 7.0.3.1) + actionmailer (7.0.10) + actionpack (= 7.0.10) + actionview (= 7.0.10) + activejob (= 7.0.10) + activesupport (= 7.0.10) mail (~> 2.5, >= 2.5.4) net-imap net-pop net-smtp rails-dom-testing (~> 2.0) - actionpack (7.0.3.1) - actionview (= 7.0.3.1) - activesupport (= 7.0.3.1) - rack (~> 2.0, >= 2.2.0) + actionpack (7.0.10) + actionview (= 7.0.10) + activesupport (= 7.0.10) + racc + rack (~> 2.0, >= 2.2.4) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (7.0.3.1) - actionpack (= 7.0.3.1) - activerecord (= 7.0.3.1) - activestorage (= 7.0.3.1) - activesupport (= 7.0.3.1) + actiontext (7.0.10) + actionpack (= 7.0.10) + activerecord (= 7.0.10) + activestorage (= 7.0.10) + activesupport (= 7.0.10) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.0.3.1) - activesupport (= 7.0.3.1) + actionview (7.0.10) + activesupport (= 7.0.10) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (7.0.3.1) - activesupport (= 7.0.3.1) + activejob (7.0.10) + activesupport (= 7.0.10) globalid (>= 0.3.6) - activemodel (7.0.3.1) - activesupport (= 7.0.3.1) - activerecord (7.0.3.1) - activemodel (= 7.0.3.1) - activesupport (= 7.0.3.1) - activestorage (7.0.3.1) - actionpack (= 7.0.3.1) - activejob (= 7.0.3.1) - activerecord (= 7.0.3.1) - activesupport (= 7.0.3.1) + activemodel (7.0.10) + activesupport (= 7.0.10) + activerecord (7.0.10) + activemodel (= 7.0.10) + activesupport (= 7.0.10) + activestorage (7.0.10) + actionpack (= 7.0.10) + activejob (= 7.0.10) + activerecord (= 7.0.10) + activesupport (= 7.0.10) marcel (~> 1.0) mini_mime (>= 1.1.0) - activesupport (7.0.3.1) + activesupport (7.0.10) + base64 + benchmark (>= 0.3) + bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) + drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) + mutex_m + securerandom (>= 0.3) tzinfo (~> 2.0) - addressable (2.8.0) - public_suffix (>= 2.0.2, < 5.0) - bcrypt (3.1.18) + addressable (2.8.8) + public_suffix (>= 2.0.2, < 8.0) + base64 (0.3.0) + bcrypt (3.1.21) + benchmark (0.5.0) + bigdecimal (4.0.1) bindex (0.8.1) - bootsnap (1.13.0) + bootsnap (1.21.1) msgpack (~> 1.2) - builder (3.2.4) - capybara (3.37.1) + builder (3.3.0) + capybara (3.40.0) addressable matrix mini_mime (>= 0.1.3) - nokogiri (~> 1.8) + nokogiri (~> 1.11) rack (>= 1.6.0) rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) childprocess (4.1.0) - concurrent-ruby (1.1.10) + concurrent-ruby (1.3.6) crass (1.0.6) - debug (1.6.2) - irb (>= 1.3.6) - reline (>= 0.3.1) - devise (4.8.1) + date (3.5.1) + debug (1.11.1) + irb (~> 1.10) + reline (>= 0.3.8) + devise (4.9.4) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) responders warden (~> 1.2.3) - digest (3.1.0) - erubi (1.11.0) - globalid (1.0.0) - activesupport (>= 5.0) - i18n (1.12.0) + drb (2.2.3) + erb (6.0.1) + erubi (1.13.1) + globalid (1.3.0) + activesupport (>= 6.1) + i18n (1.14.8) concurrent-ruby (~> 1.0) - importmap-rails (1.1.5) + importmap-rails (2.2.3) actionpack (>= 6.0.0) + activesupport (>= 6.0.0) railties (>= 6.0.0) - io-console (0.5.11) - irb (1.4.1) - reline (>= 0.3.0) - jbuilder (2.11.5) - actionview (>= 5.0.0) - activesupport (>= 5.0.0) - loofah (2.18.0) + io-console (0.8.2) + irb (1.16.0) + pp (>= 0.6.0) + rdoc (>= 4.0.0) + reline (>= 0.4.2) + jbuilder (2.14.1) + actionview (>= 7.0.0) + activesupport (>= 7.0.0) + logger (1.7.0) + loofah (2.25.0) crass (~> 1.0.2) - nokogiri (>= 1.5.9) - mail (2.7.1) + nokogiri (>= 1.12.0) + mail (2.9.0) + logger mini_mime (>= 0.1.1) - marcel (1.0.2) - matrix (0.4.2) - method_source (1.0.0) - mini_mime (1.1.2) - minitest (5.16.2) - msgpack (1.5.4) - net-imap (0.2.3) - digest + net-imap + net-pop + net-smtp + marcel (1.1.0) + matrix (0.4.3) + method_source (1.1.0) + mini_mime (1.1.5) + minitest (6.0.1) + prism (~> 1.5) + msgpack (1.8.0) + mutex_m (0.3.0) + net-imap (0.6.2) + date net-protocol - strscan - net-pop (0.1.1) - digest + net-pop (0.1.2) net-protocol + net-protocol (0.2.2) timeout - net-protocol (0.1.3) - timeout - net-smtp (0.3.1) - digest + net-smtp (0.5.1) net-protocol - timeout - nio4r (2.5.8) - nokogiri (1.13.8-x86_64-linux) + nio4r (2.7.5) + nokogiri (1.19.0-aarch64-linux-gnu) + racc (~> 1.4) + nokogiri (1.19.0-aarch64-linux-musl) + racc (~> 1.4) + nokogiri (1.19.0-arm-linux-gnu) + racc (~> 1.4) + nokogiri (1.19.0-arm-linux-musl) + racc (~> 1.4) + nokogiri (1.19.0-arm64-darwin) + racc (~> 1.4) + nokogiri (1.19.0-x86_64-darwin) + racc (~> 1.4) + nokogiri (1.19.0-x86_64-linux-gnu) + racc (~> 1.4) + nokogiri (1.19.0-x86_64-linux-musl) racc (~> 1.4) orm_adapter (0.5.0) - pg (1.4.3) - public_suffix (4.0.7) - puma (5.6.4) + pg (1.6.3) + pg (1.6.3-aarch64-linux) + pg (1.6.3-aarch64-linux-musl) + pg (1.6.3-arm64-darwin) + pg (1.6.3-x86_64-darwin) + pg (1.6.3-x86_64-linux) + pg (1.6.3-x86_64-linux-musl) + pp (0.6.3) + prettyprint + prettyprint (0.2.0) + prism (1.8.0) + psych (5.3.1) + date + stringio + public_suffix (7.0.2) + puma (5.6.9) nio4r (~> 2.0) - racc (1.6.0) - rack (2.2.4) - rack-test (2.0.2) + racc (1.8.1) + rack (2.2.21) + rack-test (2.2.0) rack (>= 1.3) - rails (7.0.3.1) - actioncable (= 7.0.3.1) - actionmailbox (= 7.0.3.1) - actionmailer (= 7.0.3.1) - actionpack (= 7.0.3.1) - actiontext (= 7.0.3.1) - actionview (= 7.0.3.1) - activejob (= 7.0.3.1) - activemodel (= 7.0.3.1) - activerecord (= 7.0.3.1) - activestorage (= 7.0.3.1) - activesupport (= 7.0.3.1) + rails (7.0.10) + actioncable (= 7.0.10) + actionmailbox (= 7.0.10) + actionmailer (= 7.0.10) + actionpack (= 7.0.10) + actiontext (= 7.0.10) + actionview (= 7.0.10) + activejob (= 7.0.10) + activemodel (= 7.0.10) + activerecord (= 7.0.10) + activestorage (= 7.0.10) + activesupport (= 7.0.10) bundler (>= 1.15.0) - railties (= 7.0.3.1) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) + railties (= 7.0.10) + rails-dom-testing (2.3.0) + activesupport (>= 5.0.0) + minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.4.3) - loofah (~> 2.3) - railties (7.0.3.1) - actionpack (= 7.0.3.1) - activesupport (= 7.0.3.1) + rails-html-sanitizer (1.6.2) + loofah (~> 2.21) + nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) + railties (7.0.10) + actionpack (= 7.0.10) + activesupport (= 7.0.10) method_source rake (>= 12.2) thor (~> 1.0) zeitwerk (~> 2.5) - rake (13.0.6) - redis (4.7.1) - regexp_parser (2.5.0) - reline (0.3.1) + rake (13.3.1) + rdoc (7.1.0) + erb + psych (>= 4.0.0) + tsort + redis (4.8.1) + regexp_parser (2.11.3) + reline (0.6.3) io-console (~> 0.5) - responders (3.0.1) - actionpack (>= 5.0) - railties (>= 5.0) - rexml (3.2.5) - rubyzip (2.3.2) - selenium-webdriver (4.4.0) + responders (3.2.0) + actionpack (>= 7.0) + railties (>= 7.0) + rexml (3.4.4) + rubyzip (3.2.2) + securerandom (0.4.1) + selenium-webdriver (4.1.0) childprocess (>= 0.5, < 5.0) rexml (~> 3.2, >= 3.2.5) - rubyzip (>= 1.2.2, < 3.0) - websocket (~> 1.0) - sprockets (4.1.1) + rubyzip (>= 1.2.2) + sprockets (4.2.2) concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.4.2) - actionpack (>= 5.2) - activesupport (>= 5.2) + logger + rack (>= 2.2.4, < 4) + sprockets-rails (3.5.2) + actionpack (>= 6.1) + activesupport (>= 6.1) sprockets (>= 3.0.0) - stimulus-rails (1.1.0) + stimulus-rails (1.3.4) railties (>= 6.0.0) - strscan (3.0.4) - thor (1.2.1) - timeout (0.3.0) - turbo-rails (1.1.1) + stringio (3.2.0) + thor (1.5.0) + timeout (0.6.0) + tsort (0.2.0) + turbo-rails (2.0.12) actionpack (>= 6.0.0) - activejob (>= 6.0.0) railties (>= 6.0.0) - tzinfo (2.0.5) + tzinfo (2.0.6) concurrent-ruby (~> 1.0) warden (1.2.9) rack (>= 2.0.9) - web-console (4.2.0) + web-console (4.2.1) actionview (>= 6.0.0) activemodel (>= 6.0.0) bindex (>= 0.4.0) railties (>= 6.0.0) - webdrivers (5.0.0) + webdrivers (5.3.1) nokogiri (~> 1.6) rubyzip (>= 1.3.0) - selenium-webdriver (~> 4.0) - websocket (1.2.9) - websocket-driver (0.7.5) + selenium-webdriver (~> 4.0, < 4.11) + websocket-driver (0.8.0) + base64 websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.0) + zeitwerk (2.7.4) PLATFORMS + aarch64-linux + aarch64-linux-gnu + aarch64-linux-musl + arm-linux-gnu + arm-linux-musl + arm64-darwin + x86_64-darwin x86_64-linux + x86_64-linux-musl DEPENDENCIES bcrypt (~> 3.1.7) @@ -247,8 +307,115 @@ DEPENDENCIES web-console webdrivers +CHECKSUMS + actioncable (7.0.10) sha256=7aa02ea26d6cc21c33e604bb28a0759c5212653311bc42105f96f709e507afab + actionmailbox (7.0.10) sha256=1236f472d86db056f97b3602391becab69c84d9f79d963b9c9b50056e213c1e6 + actionmailer (7.0.10) sha256=53bc7aac1659ef97a216c43002ea8286931d7b97f252b27152ac15de1b2585ef + actionpack (7.0.10) sha256=4c524b3b401cc828efb3fcd6f3de56ac1ec0180843b74f54357f58b0256f9509 + actiontext (7.0.10) sha256=ffadcbb9b21c09e9bfe946a79739d92abc92a9097eb1db7675e52484804c1c8c + actionview (7.0.10) sha256=e5a9475ccfcde80dddf7ced701f44aedc4f8262286051db84ae2c48322ec000e + activejob (7.0.10) sha256=f31b974206569a362e8c6c07aa00f3099fcc0f365880929c23e79c739d90fceb + activemodel (7.0.10) sha256=e2e1e0a4664b69606363e9f6f59afadeab6fa8843c5fb73cd037bb72a40fa498 + activerecord (7.0.10) sha256=63bc193d4c6944d85f53255362b67269d246a51bd664e09b1aa2cecfe5288c9a + activestorage (7.0.10) sha256=41906d59536170abcb480d05b2368ee06305307edcafc5e4891ffb7b0970eaa2 + activesupport (7.0.10) sha256=01487b0774045918b36893af4f012986db8375f6c5850c0ffc75b940ede72305 + addressable (2.8.8) sha256=7c13b8f9536cf6364c03b9d417c19986019e28f7c00ac8132da4eb0fe393b057 + base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b + bcrypt (3.1.21) sha256=5964613d750a42c7ee5dc61f7b9336fb6caca429ba4ac9f2011609946e4a2dcf + benchmark (0.5.0) sha256=465df122341aedcb81a2a24b4d3bd19b6c67c1530713fd533f3ff034e419236c + bigdecimal (4.0.1) sha256=8b07d3d065a9f921c80ceaea7c9d4ae596697295b584c296fe599dd0ad01c4a7 + bindex (0.8.1) sha256=7b1ecc9dc539ed8bccfc8cb4d2732046227b09d6f37582ff12e50a5047ceb17e + bootsnap (1.21.1) sha256=9373acfe732da35846623c337d3481af8ce77c7b3a927fb50e9aa92b46dbc4c4 + builder (3.3.0) sha256=497918d2f9dca528fdca4b88d84e4ef4387256d984b8154e9d5d3fe5a9c8835f + capybara (3.40.0) sha256=42dba720578ea1ca65fd7a41d163dd368502c191804558f6e0f71b391054aeef + childprocess (4.1.0) sha256=3616ce99ccb242361ce7f2b19bf9ff3e6bc1d98b927c7edc29af8ca617ba6cd3 + concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab + crass (1.0.6) sha256=dc516022a56e7b3b156099abc81b6d2b08ea1ed12676ac7a5657617f012bd45d + date (3.5.1) sha256=750d06384d7b9c15d562c76291407d89e368dda4d4fff957eb94962d325a0dc0 + debug (1.11.1) sha256=2e0b0ac6119f2207a6f8ac7d4a73ca8eb4e440f64da0a3136c30343146e952b6 + devise (4.9.4) sha256=920042fe5e704c548aa4eb65ebdd65980b83ffae67feb32c697206bfd975a7f8 + drb (2.2.3) sha256=0b00d6fdb50995fe4a45dea13663493c841112e4068656854646f418fda13373 + erb (6.0.1) sha256=28ecdd99c5472aebd5674d6061e3c6b0a45c049578b071e5a52c2a7f13c197e5 + erubi (1.13.1) sha256=a082103b0885dbc5ecf1172fede897f9ebdb745a4b97a5e8dc63953db1ee4ad9 + globalid (1.3.0) sha256=05c639ad6eb4594522a0b07983022f04aa7254626ab69445a0e493aa3786ff11 + i18n (1.14.8) sha256=285778639134865c5e0f6269e0b818256017e8cde89993fdfcbfb64d088824a5 + importmap-rails (2.2.3) sha256=7101be2a4dc97cf1558fb8f573a718404c5f6bcfe94f304bf1f39e444feeb16a + io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc + irb (1.16.0) sha256=2abe56c9ac947cdcb2f150572904ba798c1e93c890c256f8429981a7675b0806 + jbuilder (2.14.1) sha256=4eb26376ff60ef100cb4fd6fd7533cd271f9998327e86adf20fd8c0e69fabb42 + logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203 + loofah (2.25.0) sha256=df5ed7ac3bac6a4ec802df3877ee5cc86d027299f8952e6243b3dac446b060e6 + mail (2.9.0) sha256=6fa6673ecd71c60c2d996260f9ee3dd387d4673b8169b502134659ece6d34941 + marcel (1.1.0) sha256=fdcfcfa33cc52e93c4308d40e4090a5d4ea279e160a7f6af988260fa970e0bee + matrix (0.4.3) sha256=a0d5ab7ddcc1973ff690ab361b67f359acbb16958d1dc072b8b956a286564c5b + method_source (1.1.0) sha256=181301c9c45b731b4769bc81e8860e72f9161ad7d66dd99103c9ab84f560f5c5 + mini_mime (1.1.5) sha256=8681b7e2e4215f2a159f9400b5816d85e9d8c6c6b491e96a12797e798f8bccef + minitest (6.0.1) sha256=7854c74f48e2e975969062833adc4013f249a4b212f5e7b9d5c040bf838d54bb + msgpack (1.8.0) sha256=e64ce0212000d016809f5048b48eb3a65ffb169db22238fb4b72472fecb2d732 + mutex_m (0.3.0) sha256=cfcb04ac16b69c4813777022fdceda24e9f798e48092a2b817eb4c0a782b0751 + net-imap (0.6.2) sha256=08caacad486853c61676cca0c0c47df93db02abc4a8239a8b67eb0981428acc6 + net-pop (0.1.2) sha256=848b4e982013c15b2f0382792268763b748cce91c9e91e36b0f27ed26420dff3 + net-protocol (0.2.2) sha256=aa73e0cba6a125369de9837b8d8ef82a61849360eba0521900e2c3713aa162a8 + net-smtp (0.5.1) sha256=ed96a0af63c524fceb4b29b0d352195c30d82dd916a42f03c62a3a70e5b70736 + nio4r (2.7.5) sha256=6c90168e48fb5f8e768419c93abb94ba2b892a1d0602cb06eef16d8b7df1dca1 + nokogiri (1.19.0-aarch64-linux-gnu) sha256=11a97ecc3c0e7e5edcf395720b10860ef493b768f6aa80c539573530bc933767 + nokogiri (1.19.0-aarch64-linux-musl) sha256=eb70507f5e01bc23dad9b8dbec2b36ad0e61d227b42d292835020ff754fb7ba9 + nokogiri (1.19.0-arm-linux-gnu) sha256=572a259026b2c8b7c161fdb6469fa2d0edd2b61cd599db4bbda93289abefbfe5 + nokogiri (1.19.0-arm-linux-musl) sha256=23ed90922f1a38aed555d3de4d058e90850c731c5b756d191b3dc8055948e73c + nokogiri (1.19.0-arm64-darwin) sha256=0811dfd936d5f6dd3f6d32ef790568bf29b2b7bead9ba68866847b33c9cf5810 + nokogiri (1.19.0-x86_64-darwin) sha256=1dad56220b603a8edb9750cd95798bffa2b8dd9dd9aa47f664009ee5b43e3067 + nokogiri (1.19.0-x86_64-linux-gnu) sha256=f482b95c713d60031d48c44ce14562f8d2ce31e3a9e8dd0ccb131e9e5a68b58c + nokogiri (1.19.0-x86_64-linux-musl) sha256=1c4ca6b381622420073ce6043443af1d321e8ed93cc18b08e2666e5bd02ffae4 + orm_adapter (0.5.0) sha256=aa5d0be5d540cbb46d3a93e88061f4ece6a25f6e97d6a47122beb84fe595e9b9 + pg (1.6.3) sha256=1388d0563e13d2758c1089e35e973a3249e955c659592d10e5b77c468f628a99 + pg (1.6.3-aarch64-linux) sha256=0698ad563e02383c27510b76bf7d4cd2de19cd1d16a5013f375dd473e4be72ea + pg (1.6.3-aarch64-linux-musl) sha256=06a75f4ea04b05140146f2a10550b8e0d9f006a79cdaf8b5b130cde40e3ecc2c + pg (1.6.3-arm64-darwin) sha256=7240330b572e6355d7c75a7de535edb5dfcbd6295d9c7777df4d9dddfb8c0e5f + pg (1.6.3-x86_64-darwin) sha256=ee2e04a17c0627225054ffeb43e31a95be9d7e93abda2737ea3ce4a62f2729d6 + pg (1.6.3-x86_64-linux) sha256=5d9e188c8f7a0295d162b7b88a768d8452a899977d44f3274d1946d67920ae8d + pg (1.6.3-x86_64-linux-musl) sha256=9c9c90d98c72f78eb04c0f55e9618fe55d1512128e411035fe229ff427864009 + pp (0.6.3) sha256=2951d514450b93ccfeb1df7d021cae0da16e0a7f95ee1e2273719669d0ab9df6 + prettyprint (0.2.0) sha256=2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193 + prism (1.8.0) sha256=84453a16ef5530ea62c5f03ec16b52a459575ad4e7b9c2b360fd8ce2c39c1254 + psych (5.3.1) sha256=eb7a57cef10c9d70173ff74e739d843ac3b2c019a003de48447b2963d81b1974 + public_suffix (7.0.2) sha256=9114090c8e4e7135c1fd0e7acfea33afaab38101884320c65aaa0ffb8e26a857 + puma (5.6.9) sha256=20701b2451080ec8d6d78d2e4b5a2913e6d0b865a51d704a4d60db8fd39a4228 + racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f + rack (2.2.21) sha256=14e2f72f0765455fe424ff601588ac5ce84e95784f59e99251ffe1527152f739 + rack-test (2.2.0) sha256=005a36692c306ac0b4a9350355ee080fd09ddef1148a5f8b2ac636c720f5c463 + rails (7.0.10) sha256=866eb2c53d3184543fdb770d7ea308e4ee518063226a9e176229f3c7a9537c25 + rails-dom-testing (2.3.0) sha256=8acc7953a7b911ca44588bf08737bc16719f431a1cc3091a292bca7317925c1d + rails-html-sanitizer (1.6.2) sha256=35fce2ca8242da8775c83b6ba9c1bcaad6751d9eb73c1abaa8403475ab89a560 + railties (7.0.10) sha256=d52a8b7a61ad941121a15a6596b2150e05c70b199c3afc9e9b73e63b3b1a57a7 + rake (13.3.1) sha256=8c9e89d09f66a26a01264e7e3480ec0607f0c497a861ef16063604b1b08eb19c + rdoc (7.1.0) sha256=494899df0706c178596ca6e1d50f1b7eb285a9b2aae715be5abd742734f17363 + redis (4.8.1) sha256=387ee086694fffc9632aaeb1efe4a7b1627ca783bf373320346a8a20cd93333a + regexp_parser (2.11.3) sha256=ca13f381a173b7a93450e53459075c9b76a10433caadcb2f1180f2c741fc55a4 + reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835 + responders (3.2.0) sha256=89c2d6ac0ae16f6458a11524cae4a8efdceba1a3baea164d28ee9046bd3df55a + rexml (3.4.4) sha256=19e0a2c3425dfbf2d4fc1189747bdb2f849b6c5e74180401b15734bc97b5d142 + rubyzip (3.2.2) sha256=c0ed99385f0625415c8f05bcae33fe649ed2952894a95ff8b08f26ca57ea5b3c + securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1 + selenium-webdriver (4.1.0) sha256=076f13aa6317fb77a27409754b58c26387d5160b9d713311c147324054a7119e + sprockets (4.2.2) sha256=761e5a49f1c288704763f73139763564c845a8f856d52fba013458f8af1b59b1 + sprockets-rails (3.5.2) sha256=a9e88e6ce9f8c912d349aa5401509165ec42326baf9e942a85de4b76dbc4119e + stimulus-rails (1.3.4) sha256=765676ffa1f33af64ce026d26b48e8ffb2e0b94e0f50e9119e11d6107d67cb06 + stringio (3.2.0) sha256=c37cb2e58b4ffbd33fe5cd948c05934af997b36e0b6ca6fdf43afa234cf222e1 + thor (1.5.0) sha256=e3a9e55fe857e44859ce104a84675ab6e8cd59c650a49106a05f55f136425e73 + timeout (0.6.0) sha256=6d722ad619f96ee383a0c557ec6eb8c4ecb08af3af62098a0be5057bf00de1af + tsort (0.2.0) sha256=9650a793f6859a43b6641671278f79cfead60ac714148aabe4e3f0060480089f + turbo-rails (2.0.12) sha256=1a8cd55a92aef6bf49e63bacdb9a8873a326991bfe0e59c0b74039fe1389e431 + tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b + warden (1.2.9) sha256=46684f885d35a69dbb883deabf85a222c8e427a957804719e143005df7a1efd0 + web-console (4.2.1) sha256=e7bcf37a10ea2b4ec4281649d1cee461b32232d0a447e82c786e6841fd22fe20 + webdrivers (5.3.1) sha256=d7d5531fbc3c44b6a2a7710e3e6c5edc54f35c68af20017309e3eccf15ec4aa5 + websocket-driver (0.8.0) sha256=ed0dba4b943c22f17f9a734817e808bc84cdce6a7e22045f5315aa57676d4962 + websocket-extensions (0.1.5) sha256=1c6ba63092cda343eb53fc657110c71c754c56484aad42578495227d717a8241 + xpath (3.2.0) sha256=6dfda79d91bb3b949b947ecc5919f042ef2f399b904013eb3ef6d20dd3a4082e + zeitwerk (2.7.4) sha256=2bef90f356bdafe9a6c2bd32bcd804f83a4f9b8bc27f3600fff051eb3edcec8b + RUBY VERSION - ruby 3.0.1p64 + ruby 3.2.3 BUNDLED WITH - 2.3.17 + 4.0.4 diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb index 1508e4f..beab0cf 100644 --- a/app/views/home/index.html.erb +++ b/app/views/home/index.html.erb @@ -7,7 +7,7 @@ <% end %> \ No newline at end of file diff --git a/config/database.yml b/config/database.yml index aa8f77b..2bc7706 100644 --- a/config/database.yml +++ b/config/database.yml @@ -17,6 +17,7 @@ default: &default adapter: postgresql encoding: unicode + host: localhost username: postgres password: alfred # For details on connection pooling, see Rails configuration guide diff --git a/config/routes.rb b/config/routes.rb index f0324d9..d8e1a9a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,8 +1,8 @@ Rails.application.routes.draw do devise_for :users - # User management routes - resources :users + # User management routes (using different path to avoid conflict with Devise) + resources :users, path: 'manage_users' # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html From 86b56f518452779639c8c00730ca0844665fc46b Mon Sep 17 00:00:00 2001 From: Alfred Date: Mon, 19 Jan 2026 23:10:29 +0200 Subject: [PATCH 03/13] Add vendor/bundle to .gitignore - Exclude bundler gems directory from version control --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e16dc71..9115433 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,4 @@ # Ignore master key for decrypting credentials and more. /config/master.key +vendor/bundle/ From 1e40b3d10309cda0339d091088b6a9a925624f4f Mon Sep 17 00:00:00 2001 From: Alfred Date: Mon, 19 Jan 2026 23:10:56 +0200 Subject: [PATCH 04/13] Add styles for welcome page and buttons - Add welcome-container styling with centered layout - Add button styles with hover effects - Add danger button variant for sign out --- app/assets/stylesheets/application.css | 51 ++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 288b9ab..0e7d2fe 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -13,3 +13,54 @@ *= require_tree . *= require_self */ + +/* Welcome Page Styles */ +.welcome-container { + max-width: 800px; + margin: 50px auto; + padding: 40px; + text-align: center; + background: #f8f9fa; + border-radius: 10px; + box-shadow: 0 2px 10px rgba(0,0,0,0.1); +} + +.welcome-container h1 { + color: #2c3e50; + margin-bottom: 20px; +} + +.welcome-container p { + color: #555; + font-size: 1.1em; +} + +.user-actions { + margin-top: 30px; +} + +/* Button Styles */ +.btn { + display: inline-block; + padding: 10px 20px; + margin: 5px; + border: none; + border-radius: 5px; + cursor: pointer; + text-decoration: none; + font-size: 1em; + background-color: #3498db; + color: white; +} + +.btn:hover { + background-color: #2980b9; +} + +.btn-danger { + background-color: #e74c3c; +} + +.btn-danger:hover { + background-color: #c0392b; +} From c9816628113078aca6ad4120a0b68547da0ee885 Mon Sep 17 00:00:00 2001 From: Alfred Date: Mon, 19 Jan 2026 23:11:16 +0200 Subject: [PATCH 05/13] Add flash messages partial - Create reusable flash message component - Display notice and alert messages to users --- app/views/shared/_flash.html.erb | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 app/views/shared/_flash.html.erb diff --git a/app/views/shared/_flash.html.erb b/app/views/shared/_flash.html.erb new file mode 100644 index 0000000..17b4bfa --- /dev/null +++ b/app/views/shared/_flash.html.erb @@ -0,0 +1,6 @@ +<% flash.each do |type, message| %> +
+ <%= message %> +
+<% end %> + From 56f6aa5af89c1332adea5f99f664de5a2f87c02d Mon Sep 17 00:00:00 2001 From: Alfred Date: Mon, 19 Jan 2026 23:11:32 +0200 Subject: [PATCH 06/13] Update application layout with flash partial - Replace inline notice/alert with shared flash partial - Add main container wrapper for content --- app/views/layouts/application.html.erb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index cbec636..15a4cf8 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -11,8 +11,9 @@ -

<%= notice %>

-

<%= alert %>

- <%= yield %> +
+ <%= render 'shared/flash' %> + <%= yield %> +
From d3f05a931b4a008d028ca87e6f9a2f69dca28507 Mon Sep 17 00:00:00 2001 From: Alfred Date: Mon, 19 Jan 2026 23:11:46 +0200 Subject: [PATCH 07/13] Add flash message and container styles - Add notice and alert flash message styling - Add container padding for main content area --- app/assets/stylesheets/application.css | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 0e7d2fe..c7719ad 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -64,3 +64,29 @@ .btn-danger:hover { background-color: #c0392b; } + +/* Flash Message Styles */ +.flash { + padding: 15px 20px; + margin: 10px auto; + max-width: 800px; + border-radius: 5px; + text-align: center; +} + +.flash-notice { + background-color: #d4edda; + color: #155724; + border: 1px solid #c3e6cb; +} + +.flash-alert { + background-color: #f8d7da; + color: #721c24; + border: 1px solid #f5c6cb; +} + +/* Container */ +.container { + padding: 20px; +} From 0f300a8ff40d50f8e53bb1e307e5e0db736312ed Mon Sep 17 00:00:00 2001 From: Alfred Date: Mon, 19 Jan 2026 23:12:07 +0200 Subject: [PATCH 08/13] Add documentation comments to HomeController - Document controller purpose and authentication requirement - Add method-level documentation for index action --- app/controllers/home_controller.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 8517563..facb450 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -1,6 +1,10 @@ +# HomeController handles the main landing page of the application. +# All actions require user authentication via Devise. class HomeController < ApplicationController before_action :authenticate_user! + # GET / + # Displays the welcome page with current user information def index @user = current_user end From 34bd26df5539bf9b8fba8acb889e0360f82da660 Mon Sep 17 00:00:00 2001 From: Alfred Date: Mon, 19 Jan 2026 23:30:05 +0200 Subject: [PATCH 09/13] Redesign UI with professional styling and modern layout - Add responsive navigation bar with branding and user menu - Implement modern CSS with CSS variables for theming - Style Devise authentication pages (sign in, sign up, edit profile, forgot password) - Add Inter font from Google Fonts for professional typography - Create reusable navbar partial with conditional user links - Add footer with copyright notice - Implement flash message animations - Add responsive design for mobile devices - Apply gradient styling and box shadows for depth - Update welcome page with professional layout --- app/assets/stylesheets/application.css | 421 +++++++++++++++--- app/views/devise/passwords/new.html.erb | 32 +- app/views/devise/registrations/edit.html.erb | 75 ++-- app/views/devise/registrations/new.html.erb | 50 ++- app/views/devise/sessions/new.html.erb | 43 +- .../devise/shared/_error_messages.html.erb | 9 +- app/views/home/index.html.erb | 11 +- app/views/layouts/application.html.erb | 19 +- app/views/shared/_navbar.html.erb | 18 + 9 files changed, 524 insertions(+), 154 deletions(-) create mode 100644 app/views/shared/_navbar.html.erb diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index c7719ad..d2b9862 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -1,92 +1,411 @@ /* - * This is a manifest file that'll be compiled into application.css, which will include all the files - * listed below. - * - * Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's - * vendor/assets/stylesheets directory can be referenced here using a relative path. - * - * You're free to add application-wide styles to this file and they'll appear at the bottom of the - * compiled file so the styles you add here take precedence over styles defined in any other CSS - * files in this directory. Styles in this file should be added after the last require_* statement. - * It is generally better to create a new file per style scope. - * + * Hospital Management System - Professional Styles *= require_tree . *= require_self */ -/* Welcome Page Styles */ +/* ========== CSS Variables ========== */ +:root { + --primary-color: #0d6efd; + --primary-dark: #0b5ed7; + --secondary-color: #6c757d; + --success-color: #198754; + --danger-color: #dc3545; + --warning-color: #ffc107; + --info-color: #0dcaf0; + --light-color: #f8f9fa; + --dark-color: #212529; + --white: #ffffff; + --gray-100: #f8f9fa; + --gray-200: #e9ecef; + --gray-300: #dee2e6; + --gray-400: #ced4da; + --gray-500: #adb5bd; + --gray-600: #6c757d; + --font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + --border-radius: 8px; + --box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --box-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); +} + +/* ========== Reset & Base ========== */ +*, *::before, *::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +html { + font-size: 16px; + scroll-behavior: smooth; +} + +body { + font-family: var(--font-family); + font-size: 1rem; + line-height: 1.6; + color: var(--dark-color); + background-color: var(--gray-100); + min-height: 100vh; + display: flex; + flex-direction: column; +} + +/* ========== Navbar ========== */ +.navbar { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem 2rem; + background: linear-gradient(135deg, #1e3a5f 0%, #2c5282 100%); + box-shadow: var(--box-shadow); + position: sticky; + top: 0; + z-index: 1000; +} + +.navbar-brand { + display: flex; + align-items: center; +} + +.navbar-logo { + font-size: 1.5rem; + font-weight: 700; + color: var(--white); + text-decoration: none; + letter-spacing: -0.5px; +} + +.navbar-logo:hover { + color: var(--gray-200); +} + +.navbar-menu { + display: flex; + align-items: center; + gap: 1rem; +} + +.navbar-user { + color: var(--gray-300); + font-size: 0.9rem; + margin-right: 1rem; +} + +.navbar-link { + color: var(--white); + text-decoration: none; + padding: 0.5rem 1rem; + border-radius: var(--border-radius); + transition: background-color 0.2s ease; +} + +.navbar-link:hover { + background-color: rgba(255, 255, 255, 0.1); +} + +.navbar-btn { + padding: 0.5rem 1.25rem; + border: none; + border-radius: var(--border-radius); + font-size: 0.9rem; + font-weight: 500; + cursor: pointer; + text-decoration: none; + transition: all 0.2s ease; +} + +.navbar-btn-primary { + background-color: var(--white); + color: var(--primary-color); +} + +.navbar-btn-primary:hover { + background-color: var(--gray-200); +} + +.navbar-btn-danger { + background-color: var(--danger-color); + color: var(--white); +} + +.navbar-btn-danger:hover { + background-color: #bb2d3b; +} + +/* ========== Main Content ========== */ +.main-content { + flex: 1; + padding: 2rem; + max-width: 1200px; + margin: 0 auto; + width: 100%; +} + +/* ========== Flash Messages ========== */ +.flash { + padding: 1rem 1.5rem; + margin-bottom: 1.5rem; + border-radius: var(--border-radius); + font-weight: 500; + display: flex; + align-items: center; + animation: slideIn 0.3s ease; +} + +@keyframes slideIn { + from { + opacity: 0; + transform: translateY(-10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.flash-notice, .flash-success { + background-color: #d1e7dd; + color: #0f5132; + border: 1px solid #badbcc; +} + +.flash-alert, .flash-error { + background-color: #f8d7da; + color: #842029; + border: 1px solid #f5c2c7; +} + +/* ========== Welcome Page ========== */ .welcome-container { - max-width: 800px; - margin: 50px auto; - padding: 40px; + background: var(--white); + border-radius: 16px; + padding: 3rem; + box-shadow: var(--box-shadow-lg); text-align: center; - background: #f8f9fa; - border-radius: 10px; - box-shadow: 0 2px 10px rgba(0,0,0,0.1); + max-width: 700px; + margin: 2rem auto; } .welcome-container h1 { - color: #2c3e50; - margin-bottom: 20px; + font-size: 2.5rem; + font-weight: 700; + color: var(--dark-color); + margin-bottom: 1rem; + background: linear-gradient(135deg, #1e3a5f 0%, #2c5282 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; } .welcome-container p { - color: #555; - font-size: 1.1em; + color: var(--gray-600); + font-size: 1.1rem; + margin-bottom: 0.5rem; +} + +.welcome-container strong { + color: var(--primary-color); } .user-actions { - margin-top: 30px; + margin-top: 2rem; + display: flex; + justify-content: center; + gap: 1rem; + flex-wrap: wrap; } -/* Button Styles */ +/* ========== Buttons ========== */ .btn { - display: inline-block; - padding: 10px 20px; - margin: 5px; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0.75rem 1.5rem; + font-size: 1rem; + font-weight: 500; + border-radius: var(--border-radius); border: none; - border-radius: 5px; cursor: pointer; text-decoration: none; - font-size: 1em; - background-color: #3498db; - color: white; + transition: all 0.2s ease; } -.btn:hover { - background-color: #2980b9; +.btn-primary { + background-color: var(--primary-color); + color: var(--white); +} + +.btn-primary:hover { + background-color: var(--primary-dark); + transform: translateY(-1px); } .btn-danger { - background-color: #e74c3c; + background-color: var(--danger-color); + color: var(--white); } .btn-danger:hover { - background-color: #c0392b; + background-color: #bb2d3b; + transform: translateY(-1px); } -/* Flash Message Styles */ -.flash { - padding: 15px 20px; - margin: 10px auto; - max-width: 800px; - border-radius: 5px; +.btn-secondary { + background-color: var(--secondary-color); + color: var(--white); +} + +.btn-secondary:hover { + background-color: #5c636a; +} + +/* ========== Forms (Devise) ========== */ +.auth-container { + max-width: 450px; + margin: 2rem auto; + padding: 2.5rem; + background: var(--white); + border-radius: 16px; + box-shadow: var(--box-shadow-lg); +} + +.auth-container h2 { + font-size: 1.75rem; + font-weight: 700; + color: var(--dark-color); + text-align: center; + margin-bottom: 2rem; +} + +.form-group { + margin-bottom: 1.25rem; +} + +.form-group label { + display: block; + font-weight: 500; + color: var(--dark-color); + margin-bottom: 0.5rem; +} + +.form-group input[type="email"], +.form-group input[type="password"], +.form-group input[type="text"] { + width: 100%; + padding: 0.75rem 1rem; + font-size: 1rem; + border: 2px solid var(--gray-300); + border-radius: var(--border-radius); + transition: border-color 0.2s ease, box-shadow 0.2s ease; +} + +.form-group input:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(13, 110, 253, 0.15); +} + +.form-group input[type="checkbox"] { + margin-right: 0.5rem; +} + +.form-hint { + font-size: 0.85rem; + color: var(--gray-500); + margin-top: 0.25rem; +} + +.form-actions { + margin-top: 1.5rem; +} + +.form-actions .btn { + width: 100%; + padding: 0.875rem; +} + +.auth-links { + margin-top: 1.5rem; text-align: center; + padding-top: 1.5rem; + border-top: 1px solid var(--gray-200); } -.flash-notice { - background-color: #d4edda; - color: #155724; - border: 1px solid #c3e6cb; +.auth-links a { + color: var(--primary-color); + text-decoration: none; + font-size: 0.9rem; + display: block; + margin: 0.5rem 0; } -.flash-alert { +.auth-links a:hover { + text-decoration: underline; +} + +/* ========== Footer ========== */ +.footer { + background-color: var(--dark-color); + color: var(--gray-400); + text-align: center; + padding: 1.5rem; + margin-top: auto; +} + +.footer p { + font-size: 0.9rem; +} + +/* ========== Error Messages ========== */ +.error-messages { background-color: #f8d7da; - color: #721c24; - border: 1px solid #f5c6cb; + border: 1px solid #f5c2c7; + border-radius: var(--border-radius); + padding: 1rem; + margin-bottom: 1.5rem; +} + +.error-messages h3 { + color: #842029; + font-size: 1rem; + margin-bottom: 0.5rem; +} + +.error-messages ul { + color: #842029; + margin-left: 1.25rem; + font-size: 0.9rem; } -/* Container */ -.container { - padding: 20px; +/* ========== Responsive ========== */ +@media (max-width: 768px) { + .navbar { + flex-direction: column; + padding: 1rem; + gap: 1rem; + } + + .navbar-menu { + flex-wrap: wrap; + justify-content: center; + } + + .main-content { + padding: 1rem; + } + + .welcome-container { + padding: 2rem 1.5rem; + } + + .welcome-container h1 { + font-size: 1.75rem; + } + + .auth-container { + margin: 1rem; + padding: 1.5rem; + } } diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb index 9b486b8..9209432 100644 --- a/app/views/devise/passwords/new.html.erb +++ b/app/views/devise/passwords/new.html.erb @@ -1,16 +1,24 @@ -

Forgot your password?

+
+

Forgot Password?

+

+ Enter your email and we'll send you instructions to reset your password. +

-<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %> - <%= render "devise/shared/error_messages", resource: resource %> + <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %> + <%= render "devise/shared/error_messages", resource: resource %> -
- <%= f.label :email %>
- <%= f.email_field :email, autofocus: true, autocomplete: "email" %> -
+
+ <%= f.label :email %> + <%= f.email_field :email, autofocus: true, autocomplete: "email", placeholder: "Enter your email" %> +
-
- <%= f.submit "Send me reset password instructions" %> -
-<% end %> +
+ <%= f.submit "Send Reset Instructions", class: "btn btn-primary" %> +
+ <% end %> -<%= render "devise/shared/links" %> + +
diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index 38d95b8..07993ba 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -1,43 +1,46 @@ -

Edit <%= resource_name.to_s.humanize %>

+
+

Edit Profile

-<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> - <%= render "devise/shared/error_messages", resource: resource %> + <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> + <%= render "devise/shared/error_messages", resource: resource %> -
- <%= f.label :email %>
- <%= f.email_field :email, autofocus: true, autocomplete: "email" %> -
- - <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> -
Currently waiting confirmation for: <%= resource.unconfirmed_email %>
- <% end %> +
+ <%= f.label :email %> + <%= f.email_field :email, autofocus: true, autocomplete: "email" %> +
-
- <%= f.label :password %> (leave blank if you don't want to change it)
- <%= f.password_field :password, autocomplete: "new-password" %> - <% if @minimum_password_length %> -
- <%= @minimum_password_length %> characters minimum + <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> +
+ Currently waiting confirmation for: <%= resource.unconfirmed_email %> +
<% end %> -
- -
- <%= f.label :password_confirmation %>
- <%= f.password_field :password_confirmation, autocomplete: "new-password" %> -
-
- <%= f.label :current_password %> (we need your current password to confirm your changes)
- <%= f.password_field :current_password, autocomplete: "current-password" %> -
+
+ <%= f.label :password %> + (leave blank if you don't want to change it) + <%= f.password_field :password, autocomplete: "new-password", placeholder: "New password" %> +
+ +
+ <%= f.label :password_confirmation %> + <%= f.password_field :password_confirmation, autocomplete: "new-password", placeholder: "Confirm new password" %> +
+ +
+ <%= f.label :current_password %> + (required to confirm changes) + <%= f.password_field :current_password, autocomplete: "current-password", placeholder: "Your current password" %> +
+ +
+ <%= f.submit "Update Profile", class: "btn btn-primary" %> +
+ <% end %> -
- <%= f.submit "Update" %> + -<% end %> - -

Cancel my account

- -

Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>

- -<%= link_to "Back", :back %> +
diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb index d655b66..7839bd3 100644 --- a/app/views/devise/registrations/new.html.erb +++ b/app/views/devise/registrations/new.html.erb @@ -1,29 +1,33 @@ -

Sign up

+
+

Create Account

-<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> - <%= render "devise/shared/error_messages", resource: resource %> + <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> + <%= render "devise/shared/error_messages", resource: resource %> -
- <%= f.label :email %>
- <%= f.email_field :email, autofocus: true, autocomplete: "email" %> -
+
+ <%= f.label :email %> + <%= f.email_field :email, autofocus: true, autocomplete: "email", placeholder: "Enter your email" %> +
-
- <%= f.label :password %> - <% if @minimum_password_length %> - (<%= @minimum_password_length %> characters minimum) - <% end %>
- <%= f.password_field :password, autocomplete: "new-password" %> -
+
+ <%= f.label :password %> + <% if @minimum_password_length %> + (<%= @minimum_password_length %> characters minimum) + <% end %> + <%= f.password_field :password, autocomplete: "new-password", placeholder: "Create a password" %> +
-
- <%= f.label :password_confirmation %>
- <%= f.password_field :password_confirmation, autocomplete: "new-password" %> -
+
+ <%= f.label :password_confirmation %> + <%= f.password_field :password_confirmation, autocomplete: "new-password", placeholder: "Confirm your password" %> +
-
- <%= f.submit "Sign up" %> -
-<% end %> +
+ <%= f.submit "Create Account", class: "btn btn-primary" %> +
+ <% end %> -<%= render "devise/shared/links" %> + +
diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb index 5ede964..2185c95 100644 --- a/app/views/devise/sessions/new.html.erb +++ b/app/views/devise/sessions/new.html.erb @@ -1,26 +1,31 @@ -

Log in

+
+

Welcome Back

-<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> -
- <%= f.label :email %>
- <%= f.email_field :email, autofocus: true, autocomplete: "email" %> -
+ <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> +
+ <%= f.label :email %> + <%= f.email_field :email, autofocus: true, autocomplete: "email", placeholder: "Enter your email" %> +
-
- <%= f.label :password %>
- <%= f.password_field :password, autocomplete: "current-password" %> -
+
+ <%= f.label :password %> + <%= f.password_field :password, autocomplete: "current-password", placeholder: "Enter your password" %> +
+ + <% if devise_mapping.rememberable? %> +
+ <%= f.check_box :remember_me %> + <%= f.label :remember_me, "Remember me" %> +
+ <% end %> - <% if devise_mapping.rememberable? %> -
- <%= f.check_box :remember_me %> - <%= f.label :remember_me %> +
+ <%= f.submit "Sign In", class: "btn btn-primary" %>
<% end %> -
- <%= f.submit "Log in" %> + -<% end %> - -<%= render "devise/shared/links" %> +
diff --git a/app/views/devise/shared/_error_messages.html.erb b/app/views/devise/shared/_error_messages.html.erb index ba7ab88..e853ec0 100644 --- a/app/views/devise/shared/_error_messages.html.erb +++ b/app/views/devise/shared/_error_messages.html.erb @@ -1,11 +1,10 @@ <% if resource.errors.any? %> -
-

+
+

<%= I18n.t("errors.messages.not_saved", count: resource.errors.count, - resource: resource.class.model_name.human.downcase) - %> -

+ resource: resource.class.model_name.human.downcase) %> +

    <% resource.errors.full_messages.each do |message| %>
  • <%= message %>
  • diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb index beab0cf..005e751 100644 --- a/app/views/home/index.html.erb +++ b/app/views/home/index.html.erb @@ -1,13 +1,16 @@
    -

    Welcome to Hospital Management System

    +

    🏥 Hospital Management System

    <% if user_signed_in? %>

    Hello, <%= current_user.email %>!

    -

    You are successfully logged in.

    +

    You are successfully logged in to the Hospital Management System.

    +

    + Manage patients, doctors, appointments, and more from your dashboard. +

    <% end %> -
    \ No newline at end of file +
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 15a4cf8..656b887 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,19 +1,30 @@ - + - HospitalManagementSystem + Hospital Management System + <%= csrf_meta_tags %> <%= csp_meta_tag %> - + + + + + <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> <%= javascript_importmap_tags %> -
+ <%= render 'shared/navbar' %> + +
<%= render 'shared/flash' %> <%= yield %>
+ +
+

© <%= Date.current.year %> Hospital Management System. All rights reserved.

+
diff --git a/app/views/shared/_navbar.html.erb b/app/views/shared/_navbar.html.erb new file mode 100644 index 0000000..efedbd8 --- /dev/null +++ b/app/views/shared/_navbar.html.erb @@ -0,0 +1,18 @@ + + From 01179e94a1b51415477941e26850cc22af7d4db4 Mon Sep 17 00:00:00 2001 From: Alfred Date: Tue, 20 Jan 2026 00:01:05 +0200 Subject: [PATCH 10/13] Add Tailwind CSS with modern UI design - Install tailwindcss-rails gem - Update all views with Tailwind utility classes - Redesign navbar with responsive layout - Style authentication pages (sign in, sign up, edit, forgot password) - Add gradient backgrounds and shadows - Implement mobile-responsive design --- .gitignore | 3 + Gemfile | 2 + Gemfile.lock | 19 +++++ Procfile.dev | 2 + app/assets/builds/.keep | 0 app/assets/config/manifest.js | 1 + app/assets/tailwind/application.css | 1 + app/views/devise/passwords/new.html.erb | 38 +++++----- app/views/devise/registrations/edit.html.erb | 71 ++++++++++--------- app/views/devise/registrations/new.html.erb | 52 +++++++------- app/views/devise/sessions/new.html.erb | 46 ++++++------ .../devise/shared/_error_messages.html.erb | 6 +- app/views/home/index.html.erb | 34 +++++---- app/views/layouts/application.html.erb | 9 +-- app/views/shared/_flash.html.erb | 6 +- app/views/shared/_navbar.html.erb | 41 ++++++----- bin/dev | 16 +++++ 17 files changed, 207 insertions(+), 140 deletions(-) create mode 100644 Procfile.dev create mode 100644 app/assets/builds/.keep create mode 100644 app/assets/tailwind/application.css create mode 100755 bin/dev diff --git a/.gitignore b/.gitignore index 9115433..c2bdef3 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,6 @@ # Ignore master key for decrypting credentials and more. /config/master.key vendor/bundle/ + +/app/assets/builds/* +!/app/assets/builds/.keep diff --git a/Gemfile b/Gemfile index 9275df2..ab43707 100644 --- a/Gemfile +++ b/Gemfile @@ -72,3 +72,5 @@ group :test do gem "selenium-webdriver" gem "webdrivers" end + +gem "tailwindcss-rails", "~> 4.4" diff --git a/Gemfile.lock b/Gemfile.lock index b2222ed..35c713b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -249,6 +249,16 @@ GEM stimulus-rails (1.3.4) railties (>= 6.0.0) stringio (3.2.0) + tailwindcss-rails (4.4.0) + railties (>= 7.0.0) + tailwindcss-ruby (~> 4.0) + tailwindcss-ruby (4.1.18) + tailwindcss-ruby (4.1.18-aarch64-linux-gnu) + tailwindcss-ruby (4.1.18-aarch64-linux-musl) + tailwindcss-ruby (4.1.18-arm64-darwin) + tailwindcss-ruby (4.1.18-x86_64-darwin) + tailwindcss-ruby (4.1.18-x86_64-linux-gnu) + tailwindcss-ruby (4.1.18-x86_64-linux-musl) thor (1.5.0) timeout (0.6.0) tsort (0.2.0) @@ -302,6 +312,7 @@ DEPENDENCIES selenium-webdriver sprockets-rails stimulus-rails + tailwindcss-rails (~> 4.4) turbo-rails tzinfo-data web-console @@ -401,6 +412,14 @@ CHECKSUMS sprockets-rails (3.5.2) sha256=a9e88e6ce9f8c912d349aa5401509165ec42326baf9e942a85de4b76dbc4119e stimulus-rails (1.3.4) sha256=765676ffa1f33af64ce026d26b48e8ffb2e0b94e0f50e9119e11d6107d67cb06 stringio (3.2.0) sha256=c37cb2e58b4ffbd33fe5cd948c05934af997b36e0b6ca6fdf43afa234cf222e1 + tailwindcss-rails (4.4.0) sha256=efa2961351a52acebe616e645a81a30bb4f27fde46cc06ce7688d1cd1131e916 + tailwindcss-ruby (4.1.18) sha256=b62fad5b00494e92987ee319dfb5c5ad272f0ed93649963d62f08d2ba0f03fa7 + tailwindcss-ruby (4.1.18-aarch64-linux-gnu) sha256=e10f9560bccddbb4955fd535b3bcc8c7071a7df07404dd473a23fa791ec4e46b + tailwindcss-ruby (4.1.18-aarch64-linux-musl) sha256=3c8426674718a2c98a0649c825ac0b3286ff52acd0b4052d7d19126cd74904f3 + tailwindcss-ruby (4.1.18-arm64-darwin) sha256=f940531d5a030c566d3d616004235bcd4c361abdd328f7d6c7e3a953a32e0155 + tailwindcss-ruby (4.1.18-x86_64-darwin) sha256=6a82115b606a6f748c600c666a19c16ee28f5736217af8d0c20cee5abe1ce2f7 + tailwindcss-ruby (4.1.18-x86_64-linux-gnu) sha256=e0a2220163246fe0126c5c5bafb95bc6206e7d21fce2a2878fd9c9a359137534 + tailwindcss-ruby (4.1.18-x86_64-linux-musl) sha256=d957cf545b09d2db7eb6267450cc1fc589e126524066537a0c4d5b99d701f4b2 thor (1.5.0) sha256=e3a9e55fe857e44859ce104a84675ab6e8cd59c650a49106a05f55f136425e73 timeout (0.6.0) sha256=6d722ad619f96ee383a0c557ec6eb8c4ecb08af3af62098a0be5057bf00de1af tsort (0.2.0) sha256=9650a793f6859a43b6641671278f79cfead60ac714148aabe4e3f0060480089f diff --git a/Procfile.dev b/Procfile.dev new file mode 100644 index 0000000..da151fe --- /dev/null +++ b/Procfile.dev @@ -0,0 +1,2 @@ +web: bin/rails server +css: bin/rails tailwindcss:watch diff --git a/app/assets/builds/.keep b/app/assets/builds/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js index ddd546a..b06fc42 100644 --- a/app/assets/config/manifest.js +++ b/app/assets/config/manifest.js @@ -2,3 +2,4 @@ //= link_directory ../stylesheets .css //= link_tree ../../javascript .js //= link_tree ../../../vendor/javascript .js +//= link_tree ../builds diff --git a/app/assets/tailwind/application.css b/app/assets/tailwind/application.css new file mode 100644 index 0000000..f1d8c73 --- /dev/null +++ b/app/assets/tailwind/application.css @@ -0,0 +1 @@ +@import "tailwindcss"; diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb index 9209432..dc481de 100644 --- a/app/views/devise/passwords/new.html.erb +++ b/app/views/devise/passwords/new.html.erb @@ -1,24 +1,26 @@ -
-

Forgot Password?

-

- Enter your email and we'll send you instructions to reset your password. -

+
+
+

Forgot Password?

+

+ Enter your email and we'll send you instructions to reset your password. +

- <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %> - <%= render "devise/shared/error_messages", resource: resource %> + <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post, class: "space-y-6" }) do |f| %> + <%= render "devise/shared/error_messages", resource: resource %> -
- <%= f.label :email %> - <%= f.email_field :email, autofocus: true, autocomplete: "email", placeholder: "Enter your email" %> -
+
+ <%= f.label :email, class: "block text-sm font-medium text-gray-700 mb-1" %> + <%= f.email_field :email, autofocus: true, autocomplete: "email", placeholder: "Enter your email", class: "w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition" %> +
-
- <%= f.submit "Send Reset Instructions", class: "btn btn-primary" %> -
- <% end %> +
+ <%= f.submit "Send Reset Instructions", class: "w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-3 px-4 rounded-lg transition shadow-md hover:shadow-lg cursor-pointer" %> +
+ <% end %> -
diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index 07993ba..50357a8 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -1,46 +1,47 @@ -
-

Edit Profile

+
+
+

Edit Profile

- <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> - <%= render "devise/shared/error_messages", resource: resource %> + <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, class: "space-y-6" }) do |f| %> + <%= render "devise/shared/error_messages", resource: resource %> -
- <%= f.label :email %> - <%= f.email_field :email, autofocus: true, autocomplete: "email" %> -
+
+ <%= f.label :email, class: "block text-sm font-medium text-gray-700 mb-1" %> + <%= f.email_field :email, autofocus: true, autocomplete: "email", class: "w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition" %> +
+ + <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> +
+ Currently waiting confirmation for: <%= resource.unconfirmed_email %> +
+ <% end %> - <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> -
- Currently waiting confirmation for: <%= resource.unconfirmed_email %> +
+ <%= f.label :password, class: "block text-sm font-medium text-gray-700 mb-1" %> + (leave blank if you don't want to change) + <%= f.password_field :password, autocomplete: "new-password", placeholder: "New password", class: "w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition mt-1" %>
- <% end %> -
- <%= f.label :password %> - (leave blank if you don't want to change it) - <%= f.password_field :password, autocomplete: "new-password", placeholder: "New password" %> -
+
+ <%= f.label :password_confirmation, class: "block text-sm font-medium text-gray-700 mb-1" %> + <%= f.password_field :password_confirmation, autocomplete: "new-password", placeholder: "Confirm new password", class: "w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition" %> +
-
- <%= f.label :password_confirmation %> - <%= f.password_field :password_confirmation, autocomplete: "new-password", placeholder: "Confirm new password" %> -
+
+ <%= f.label :current_password, class: "block text-sm font-medium text-gray-700 mb-1" %> + (required to confirm changes) + <%= f.password_field :current_password, autocomplete: "current-password", placeholder: "Your current password", class: "w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition mt-1" %> +
-
- <%= f.label :current_password %> - (required to confirm changes) - <%= f.password_field :current_password, autocomplete: "current-password", placeholder: "Your current password" %> -
+
+ <%= f.submit "Update Profile", class: "w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-3 px-4 rounded-lg transition shadow-md hover:shadow-lg cursor-pointer" %> +
+ <% end %> -
- <%= f.submit "Update Profile", class: "btn btn-primary" %> +
+

Danger Zone

+

Once you delete your account, there is no going back.

+ <%= button_to "Delete my account", registration_path(resource_name), data: { confirm: "Are you sure? This cannot be undone." }, method: :delete, class: "bg-red-600 hover:bg-red-700 text-white font-medium py-2 px-4 rounded-lg transition cursor-pointer" %>
- <% end %> - -
diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb index 7839bd3..148b4e9 100644 --- a/app/views/devise/registrations/new.html.erb +++ b/app/views/devise/registrations/new.html.erb @@ -1,33 +1,35 @@ -
-

Create Account

+
+
+

Create Account

- <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> - <%= render "devise/shared/error_messages", resource: resource %> + <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { class: "space-y-6" }) do |f| %> + <%= render "devise/shared/error_messages", resource: resource %> -
- <%= f.label :email %> - <%= f.email_field :email, autofocus: true, autocomplete: "email", placeholder: "Enter your email" %> -
+
+ <%= f.label :email, class: "block text-sm font-medium text-gray-700 mb-1" %> + <%= f.email_field :email, autofocus: true, autocomplete: "email", placeholder: "Enter your email", class: "w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition" %> +
-
- <%= f.label :password %> - <% if @minimum_password_length %> - (<%= @minimum_password_length %> characters minimum) - <% end %> - <%= f.password_field :password, autocomplete: "new-password", placeholder: "Create a password" %> -
+
+ <%= f.label :password, class: "block text-sm font-medium text-gray-700 mb-1" %> + <% if @minimum_password_length %> + (<%= @minimum_password_length %> characters minimum) + <% end %> + <%= f.password_field :password, autocomplete: "new-password", placeholder: "Create a password", class: "w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition mt-1" %> +
-
- <%= f.label :password_confirmation %> - <%= f.password_field :password_confirmation, autocomplete: "new-password", placeholder: "Confirm your password" %> -
+
+ <%= f.label :password_confirmation, class: "block text-sm font-medium text-gray-700 mb-1" %> + <%= f.password_field :password_confirmation, autocomplete: "new-password", placeholder: "Confirm your password", class: "w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition" %> +
-
- <%= f.submit "Create Account", class: "btn btn-primary" %> -
- <% end %> +
+ <%= f.submit "Create Account", class: "w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-3 px-4 rounded-lg transition shadow-md hover:shadow-lg cursor-pointer" %> +
+ <% end %> -
diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb index 2185c95..f4d3fea 100644 --- a/app/views/devise/sessions/new.html.erb +++ b/app/views/devise/sessions/new.html.erb @@ -1,31 +1,33 @@ -
-

Welcome Back

+
+
+

Welcome Back

- <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> -
- <%= f.label :email %> - <%= f.email_field :email, autofocus: true, autocomplete: "email", placeholder: "Enter your email" %> -
+ <%= form_for(resource, as: resource_name, url: session_path(resource_name), html: { class: "space-y-6" }) do |f| %> +
+ <%= f.label :email, class: "block text-sm font-medium text-gray-700 mb-1" %> + <%= f.email_field :email, autofocus: true, autocomplete: "email", placeholder: "Enter your email", class: "w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition" %> +
-
- <%= f.label :password %> - <%= f.password_field :password, autocomplete: "current-password", placeholder: "Enter your password" %> -
+
+ <%= f.label :password, class: "block text-sm font-medium text-gray-700 mb-1" %> + <%= f.password_field :password, autocomplete: "current-password", placeholder: "Enter your password", class: "w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition" %> +
+ + <% if devise_mapping.rememberable? %> +
+ <%= f.check_box :remember_me, class: "h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" %> + <%= f.label :remember_me, "Remember me", class: "ml-2 block text-sm text-gray-700" %> +
+ <% end %> - <% if devise_mapping.rememberable? %> -
- <%= f.check_box :remember_me %> - <%= f.label :remember_me, "Remember me" %> +
+ <%= f.submit "Sign In", class: "w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-3 px-4 rounded-lg transition shadow-md hover:shadow-lg cursor-pointer" %>
<% end %> -
- <%= f.submit "Sign In", class: "btn btn-primary" %> +
+ <%= link_to "Don't have an account? Sign up", new_registration_path(resource_name), class: "block text-blue-600 hover:text-blue-800 text-sm" %> + <%= link_to "Forgot your password?", new_password_path(resource_name), class: "block text-gray-500 hover:text-gray-700 text-sm" %>
- <% end %> - -
diff --git a/app/views/devise/shared/_error_messages.html.erb b/app/views/devise/shared/_error_messages.html.erb index e853ec0..de30bf5 100644 --- a/app/views/devise/shared/_error_messages.html.erb +++ b/app/views/devise/shared/_error_messages.html.erb @@ -1,11 +1,11 @@ <% if resource.errors.any? %> -
-

+
+

<%= I18n.t("errors.messages.not_saved", count: resource.errors.count, resource: resource.class.model_name.human.downcase) %>

-
    +
      <% resource.errors.full_messages.each do |message| %>
    • <%= message %>
    • <% end %> diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb index 005e751..b907d8d 100644 --- a/app/views/home/index.html.erb +++ b/app/views/home/index.html.erb @@ -1,16 +1,22 @@ -
      -

      🏥 Hospital Management System

      - - <% if user_signed_in? %> -

      Hello, <%= current_user.email %>!

      -

      You are successfully logged in to the Hospital Management System.

      -

      - Manage patients, doctors, appointments, and more from your dashboard. -

      +
      +
      +
      🏥
      +

      + Hospital Management System +

      - - <% end %> + <% if user_signed_in? %> +

      + Hello, <%= current_user.email %>! +

      +

      + You are successfully logged in. Manage patients, doctors, appointments, and more. +

      + +
      + <%= link_to 'Edit Profile', edit_user_registration_path, class: "inline-flex items-center justify-center px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition shadow-md hover:shadow-lg" %> + <%= button_to 'Sign Out', destroy_user_session_path, method: :delete, class: "inline-flex items-center justify-center px-6 py-3 bg-red-600 hover:bg-red-700 text-white font-medium rounded-lg transition shadow-md hover:shadow-lg" %> +
      + <% end %> +
      diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 656b887..2b8444b 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -11,20 +11,21 @@ + <%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %> <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> <%= javascript_importmap_tags %> - + <%= render 'shared/navbar' %> -
      +
      <%= render 'shared/flash' %> <%= yield %>
      -