diff --git a/.gitignore b/.gitignore index e16dc71..c2bdef3 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,7 @@ # 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 a2cf1bd..ab43707 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" @@ -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 da3d837..35c713b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,231 +1,301 @@ 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) + 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) + 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) @@ -242,13 +312,129 @@ DEPENDENCIES selenium-webdriver sprockets-rails stimulus-rails + tailwindcss-rails (~> 4.4) turbo-rails tzinfo-data 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 + 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 + 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/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/stylesheets/application.css b/app/assets/stylesheets/application.css index 288b9ab..6bdf67f 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -1,15 +1,5 @@ /* - * 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. - * + * This is a manifest file - keep it minimal, Tailwind handles all styling *= require_tree . *= require_self */ diff --git a/app/assets/tailwind/application.css b/app/assets/tailwind/application.css new file mode 100644 index 0000000..f8d1c02 --- /dev/null +++ b/app/assets/tailwind/application.css @@ -0,0 +1,11 @@ +@import "tailwindcss"; + +/* Custom font */ +@theme { + --font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; +} + +/* Ensure buttons from forms display properly */ +form button, form input[type="submit"] { + cursor: pointer; +} 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..facb450 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -1,4 +1,11 @@ +# 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 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/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb index 9b486b8..613ca95 100644 --- a/app/views/devise/passwords/new.html.erb +++ b/app/views/devise/passwords/new.html.erb @@ -1,16 +1,36 @@ -

Forgot your password?

+
+
+ +
+
+ 🔑 +
+

Reset your password

+

We'll send you instructions to reset it

+
-<%= 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, class: "block text-sm font-medium text-slate-700 mb-2" %> + <%= f.email_field :email, autofocus: true, autocomplete: "email", placeholder: "you@example.com", class: "w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl text-slate-900 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all" %> +
-
- <%= f.submit "Send me reset password instructions" %> -
-<% end %> +
+ <%= f.submit "Send Reset Link", class: "w-full py-3.5 px-4 bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 text-white font-semibold rounded-xl shadow-lg shadow-blue-500/30 hover:shadow-xl hover:shadow-blue-500/40 transition-all cursor-pointer" %> +
+
+ <% end %> +
-<%= render "devise/shared/links" %> + +

+ Remember your password? + <%= link_to "Sign in", new_session_path(resource_name), class: "text-blue-600 hover:text-blue-700 font-semibold" %> +

+
+
diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index 38d95b8..f04a1a1 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -1,43 +1,86 @@ -

Edit <%= resource_name.to_s.humanize %>

+
+ +
+

Account Settings

+

Manage your account information and security

+
-<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> - <%= render "devise/shared/error_messages", resource: resource %> + +
+ +
+
+
+ 👤 +
+
+

<%= current_user.email.split('@').first.capitalize %>

+

<%= current_user.email %>

+
+
+
-
- <%= f.label :email %>
- <%= f.email_field :email, autofocus: true, autocomplete: "email" %> -
+ +
+ <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> + <%= render "devise/shared/error_messages", resource: resource %> - <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> -
Currently waiting confirmation for: <%= resource.unconfirmed_email %>
- <% end %> - -
- <%= 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 - <% end %> -
+
+
+

Email Address

+ <%= f.email_field :email, autofocus: true, autocomplete: "email", class: "w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl text-slate-900 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all" %> +
-
- <%= f.label :password_confirmation %>
- <%= f.password_field :password_confirmation, autocomplete: "new-password" %> -
+ <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> +
+

Waiting confirmation for: <%= resource.unconfirmed_email %>

+
+ <% end %> -
- <%= f.label :current_password %> (we need your current password to confirm your changes)
- <%= f.password_field :current_password, autocomplete: "current-password" %> -
+
-
- <%= f.submit "Update" %> -
-<% end %> +
+

Change Password

+

Leave blank if you don't want to change

+ +
+
+ <%= f.label :password, "New Password", class: "block text-sm font-medium text-slate-700 mb-2" %> + <%= f.password_field :password, autocomplete: "new-password", placeholder: "••••••••", class: "w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl text-slate-900 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all" %> +
+ +
+ <%= f.label :password_confirmation, "Confirm New Password", class: "block text-sm font-medium text-slate-700 mb-2" %> + <%= f.password_field :password_confirmation, autocomplete: "new-password", placeholder: "••••••••", class: "w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl text-slate-900 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all" %> +
+
+
-

Cancel my account

+
-

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

+
+

Confirm Changes

+ <%= f.label :current_password, class: "block text-sm font-medium text-slate-700 mb-2" %> +

Enter your current password to save changes

+ <%= f.password_field :current_password, autocomplete: "current-password", placeholder: "••••••••", class: "w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl text-slate-900 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all" %> +
-<%= link_to "Back", :back %> +
+ <%= f.submit "Save Changes", class: "w-full py-3.5 px-4 bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 text-white font-semibold rounded-xl shadow-lg shadow-blue-500/30 hover:shadow-xl hover:shadow-blue-500/40 transition-all cursor-pointer" %> +
+
+ <% end %> +
+
+ + +
+
+

⚠️ Danger Zone

+
+
+

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

+ <%= button_to "Delete Account", registration_path(resource_name), data: { confirm: "Are you sure? This cannot be undone." }, method: :delete, class: "px-6 py-3 bg-red-600 hover:bg-red-700 text-white font-medium rounded-xl transition-colors cursor-pointer" %> +
+
+
diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb index d655b66..642a267 100644 --- a/app/views/devise/registrations/new.html.erb +++ b/app/views/devise/registrations/new.html.erb @@ -1,29 +1,49 @@ -

Sign up

+
+
+ +
+
+ 🏥 +
+

Create your account

+

Start managing your hospital today

+
-<%= 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, class: "block text-sm font-medium text-slate-700 mb-2" %> + <%= f.email_field :email, autofocus: true, autocomplete: "email", placeholder: "you@example.com", class: "w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl text-slate-900 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all" %> +
-
- <%= f.label :password %> - <% if @minimum_password_length %> - (<%= @minimum_password_length %> characters minimum) - <% end %>
- <%= f.password_field :password, autocomplete: "new-password" %> -
+
+ <%= f.label :password, class: "block text-sm font-medium text-slate-700 mb-2" %> + <% if @minimum_password_length %> + (min. <%= @minimum_password_length %> characters) + <% end %> + <%= f.password_field :password, autocomplete: "new-password", placeholder: "••••••••", class: "w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl text-slate-900 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all" %> +
-
- <%= f.label :password_confirmation %>
- <%= f.password_field :password_confirmation, autocomplete: "new-password" %> -
+
+ <%= f.label :password_confirmation, "Confirm Password", class: "block text-sm font-medium text-slate-700 mb-2" %> + <%= f.password_field :password_confirmation, autocomplete: "new-password", placeholder: "••••••••", class: "w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl text-slate-900 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all" %> +
-
- <%= f.submit "Sign up" %> -
-<% end %> +
+ <%= f.submit "Create Account", class: "w-full py-3.5 px-4 bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 text-white font-semibold rounded-xl shadow-lg shadow-blue-500/30 hover:shadow-xl hover:shadow-blue-500/40 transition-all cursor-pointer" %> +
+
+ <% end %> +
-<%= render "devise/shared/links" %> + +

+ Already have an account? + <%= link_to "Sign in", new_session_path(resource_name), class: "text-blue-600 hover:text-blue-700 font-semibold" %> +

+
+
diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb index 5ede964..d21361a 100644 --- a/app/views/devise/sessions/new.html.erb +++ b/app/views/devise/sessions/new.html.erb @@ -1,26 +1,49 @@ -

Log in

+
+
+ +
+
+ 🏥 +
+

Welcome back

+

Sign in to your account to continue

+
-<%= 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, class: "block text-sm font-medium text-slate-700 mb-2" %> + <%= f.email_field :email, autofocus: true, autocomplete: "email", placeholder: "you@example.com", class: "w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl text-slate-900 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all" %> +
-
- <%= f.label :password %>
- <%= f.password_field :password, autocomplete: "current-password" %> -
+
+ <%= f.label :password, class: "block text-sm font-medium text-slate-700 mb-2" %> + <%= f.password_field :password, autocomplete: "current-password", placeholder: "••••••••", class: "w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl text-slate-900 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all" %> +
- <% if devise_mapping.rememberable? %> -
- <%= f.check_box :remember_me %> - <%= f.label :remember_me %> + <% if devise_mapping.rememberable? %> +
+ + <%= link_to "Forgot password?", new_password_path(resource_name), class: "text-sm text-blue-600 hover:text-blue-700 font-medium" %> +
+ <% end %> + +
+ <%= f.submit "Sign In", class: "w-full py-3.5 px-4 bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 text-white font-semibold rounded-xl shadow-lg shadow-blue-500/30 hover:shadow-xl hover:shadow-blue-500/40 transition-all cursor-pointer" %> +
+
+ <% end %>
- <% end %> -
- <%= f.submit "Log in" %> + +

+ Don't have an account? + <%= link_to "Sign up for free", new_registration_path(resource_name), class: "text-blue-600 hover:text-blue-700 font-semibold" %> +

-<% 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..f7c98e3 100644 --- a/app/views/devise/shared/_error_messages.html.erb +++ b/app/views/devise/shared/_error_messages.html.erb @@ -1,15 +1,21 @@ <% 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 %> -
+
+
+
+ + + +
+
+

+ <%= 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 %> +
+
+
<% 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..c5e2de7 --- /dev/null +++ b/app/views/home/index.html.erb @@ -0,0 +1,75 @@ +<% if user_signed_in? %> + +
+

Welcome back! 👋

+

Here's what's happening with your hospital today.

+
+ + +
+
+
+
+

Total Patients

+

1,234

+
+
+ 👥 +
+
+
+ ↑ 12% + from last month +
+
+ +
+
+
+

Appointments

+

56

+
+
+ 📅 +
+
+
+ ↑ 8% + from last week +
+
+ +
+
+
+

Doctors

+

24

+
+
+ 👨‍⚕️ +
+
+
+ Active staff members +
+
+
+ + +
+
+
+ 👤 +
+
+

<%= current_user.email.split('@').first.capitalize %>

+

<%= current_user.email %>

+
+
+

You are logged in to the Hospital Management System. Manage patients, doctors, appointments, and more from your dashboard.

+
+ <%= link_to 'Edit Profile', edit_user_registration_path, class: "inline-flex items-center px-5 py-2.5 bg-white text-blue-600 font-medium rounded-xl hover:bg-blue-50 transition-colors" %> + <%= button_to 'Sign Out', destroy_user_session_path, method: :delete, class: "inline-flex items-center px-5 py-2.5 bg-white/20 backdrop-blur text-white font-medium rounded-xl hover:bg-white/30 transition-colors cursor-pointer" %> +
+
+<% end %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index cbec636..bd6fde8 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,18 +1,33 @@ - + - HospitalManagementSystem + Hospital Management System + <%= csrf_meta_tags %> <%= csp_meta_tag %> - + + + + + + <%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %> <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> <%= javascript_importmap_tags %> + + - -

<%= notice %>

-

<%= alert %>

- <%= yield %> + + <%= render 'shared/navbar' %> + +
+
+ <%= render 'shared/flash' %> + <%= yield %> +
+
diff --git a/app/views/shared/_flash.html.erb b/app/views/shared/_flash.html.erb new file mode 100644 index 0000000..9983eff --- /dev/null +++ b/app/views/shared/_flash.html.erb @@ -0,0 +1,21 @@ +<% flash.each do |type, message| %> + <% if type == 'notice' || type == 'success' %> +
+
+ + + +
+

<%= message %>

+
+ <% else %> +
+
+ + + +
+

<%= message %>

+
+ <% end %> +<% end %> diff --git a/app/views/shared/_navbar.html.erb b/app/views/shared/_navbar.html.erb new file mode 100644 index 0000000..a410e74 --- /dev/null +++ b/app/views/shared/_navbar.html.erb @@ -0,0 +1,30 @@ + diff --git a/bin/dev b/bin/dev new file mode 100755 index 0000000..ad72c7d --- /dev/null +++ b/bin/dev @@ -0,0 +1,16 @@ +#!/usr/bin/env sh + +if ! gem list foreman -i --silent; then + echo "Installing foreman..." + gem install foreman +fi + +# Default to port 3000 if not specified +export PORT="${PORT:-3000}" + +# Let the debug gem allow remote connections, +# but avoid loading until `debugger` is called +export RUBY_DEBUG_OPEN="true" +export RUBY_DEBUG_LAZY="true" + +exec foreman start -f Procfile.dev "$@" 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 f3cc3ca..d8e1a9a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,9 @@ Rails.application.routes.draw do devise_for :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 # Defines the root path route ("/")