diff --git a/.gitattributes b/.gitattributes index 516857104..ea2a81515 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8,3 +8,6 @@ yarn.lock linguist-generated # Mark any vendored files as having been vendored. vendor/* linguist-vendored + +Gemfile merge=ours +Gemfile.lock merge=ours \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8ac3419f0..755774a6a 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,14 @@ .tool-versions # Ignore ENV variable file -.env \ No newline at end of file +.env + +# Ignore Gemfiles +Gemfile +Gemfile.lock + +# ignore emacs backup files +*~ +\#*\# +.idea + diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..82cf78194 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.exclude": { + "**/.git": false + } +} \ No newline at end of file diff --git a/Gemfile b/Gemfile index 5efe339e6..3bc8c20a0 100644 --- a/Gemfile +++ b/Gemfile @@ -34,10 +34,10 @@ gem "jbuilder" gem "redis", "~> 4.0" # Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis] -# gem "kredis" +gem "kredis" # Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword] -# gem "bcrypt", "~> 3.1.7" +gem "bcrypt", "~> 3.1.7" # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ] @@ -45,8 +45,11 @@ gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ] # Reduces boot times through caching; required in config/boot.rb gem "bootsnap", require: false +# Boostrap +gem 'bootstrap', '~> 4.1.1' + # Use Sass to process CSS -# gem "sassc-rails" +gem "sass-rails", '~> 5.0' # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] # gem "image_processing", "~> 1.2" @@ -83,3 +86,7 @@ gem 'dotenv-rails' # gem 'paperclip # gem 'uniquify' # gem 'will_paginate' + +gem "nio4r", "~> 2.5" + +gem 'geocoder', '~> 1.3', '>= 1.3.7' diff --git a/Gemfile.lock b/Gemfile.lock index c3e104938..6513414b0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,241 +1,293 @@ GEM remote: https://rubygems.org/ specs: - actioncable (7.0.3.1) - actionpack (= 7.0.3.1) - activesupport (= 7.0.3.1) + actioncable (7.0.8.6) + actionpack (= 7.0.8.6) + activesupport (= 7.0.8.6) 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.8.6) + actionpack (= 7.0.8.6) + activejob (= 7.0.8.6) + activerecord (= 7.0.8.6) + activestorage (= 7.0.8.6) + activesupport (= 7.0.8.6) 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.8.6) + actionpack (= 7.0.8.6) + actionview (= 7.0.8.6) + activejob (= 7.0.8.6) + activesupport (= 7.0.8.6) 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.8.6) + actionview (= 7.0.8.6) + activesupport (= 7.0.8.6) + 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.8.6) + actionpack (= 7.0.8.6) + activerecord (= 7.0.8.6) + activestorage (= 7.0.8.6) + activesupport (= 7.0.8.6) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.0.3.1) - activesupport (= 7.0.3.1) + actionview (7.0.8.6) + activesupport (= 7.0.8.6) 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.8.6) + activesupport (= 7.0.8.6) 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.8.6) + activesupport (= 7.0.8.6) + activerecord (7.0.8.6) + activemodel (= 7.0.8.6) + activesupport (= 7.0.8.6) + activestorage (7.0.8.6) + actionpack (= 7.0.8.6) + activejob (= 7.0.8.6) + activerecord (= 7.0.8.6) + activesupport (= 7.0.8.6) marcel (~> 1.0) mini_mime (>= 1.1.0) - activesupport (7.0.3.1) + activesupport (7.0.8.6) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) - addressable (2.8.1) - public_suffix (>= 2.0.2, < 6.0) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) + autoprefixer-rails (10.4.19.0) + execjs (~> 2) + base64 (0.2.0) + bcrypt (3.1.20) bindex (0.8.1) - bootsnap (1.13.0) + bootsnap (1.18.4) msgpack (~> 1.2) - builder (3.2.4) - capybara (3.37.1) + bootstrap (4.1.3) + autoprefixer-rails (>= 6.0.3) + popper_js (>= 1.12.9, < 2) + sass (>= 3.5.2) + 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.4) crass (1.0.6) - debug (1.6.2) - irb (>= 1.3.6) - reline (>= 0.3.1) - digest (3.1.0) - dotenv (2.8.1) - dotenv-rails (2.8.1) - dotenv (= 2.8.1) - railties (>= 3.2) - erubi (1.11.0) - globalid (1.0.0) - activesupport (>= 5.0) - i18n (1.12.0) + csv (3.3.0) + date (3.4.0) + debug (1.9.2) + irb (~> 1.10) + reline (>= 0.3.8) + dotenv (3.1.4) + dotenv-rails (3.1.4) + dotenv (= 3.1.4) + railties (>= 6.1) + erubi (1.13.0) + execjs (2.10.0) + ffi (1.17.0) + ffi (1.17.0-arm64-darwin) + ffi (1.17.0-x86_64-darwin) + geocoder (1.8.3) + base64 (>= 0.1.0) + csv (>= 3.0.0) + globalid (1.2.1) + activesupport (>= 6.1) + i18n (1.14.6) concurrent-ruby (~> 1.0) - importmap-rails (1.1.5) + importmap-rails (2.0.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) + io-console (0.7.2) + irb (1.14.1) + rdoc (>= 4.0.0) + reline (>= 0.4.2) + jbuilder (2.13.0) actionview (>= 5.0.0) activesupport (>= 5.0.0) - loofah (2.18.0) + kredis (1.7.0) + activemodel (>= 6.0.0) + activesupport (>= 6.0.0) + redis (>= 4.2, < 6) + loofah (2.23.1) crass (~> 1.0.2) - nokogiri (>= 1.5.9) - mail (2.7.1) + nokogiri (>= 1.12.0) + mail (2.8.1) mini_mime (>= 0.1.1) - marcel (1.0.2) + net-imap + net-pop + net-smtp + marcel (1.0.4) matrix (0.4.2) - method_source (1.0.0) - mini_mime (1.1.2) - minitest (5.16.3) - msgpack (1.5.6) - mysql2 (0.5.4) - net-imap (0.2.3) - digest + method_source (1.1.0) + mini_mime (1.1.5) + minitest (5.25.1) + msgpack (1.7.3) + mysql2 (0.5.6) + net-imap (0.5.0) + 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.0) net-protocol - timeout - nio4r (2.5.8) - nokogiri (1.13.8-arm64-darwin) + nio4r (2.7.4) + nokogiri (1.16.7-arm64-darwin) + racc (~> 1.4) + nokogiri (1.16.7-x86_64-darwin) racc (~> 1.4) - nokogiri (1.13.8-x86_64-linux) + nokogiri (1.16.7-x86_64-linux) racc (~> 1.4) - public_suffix (5.0.0) - puma (5.6.5) + popper_js (1.16.1) + psych (5.1.2) + stringio + public_suffix (6.0.1) + 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.10) + rack-test (2.1.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.8.6) + actioncable (= 7.0.8.6) + actionmailbox (= 7.0.8.6) + actionmailer (= 7.0.8.6) + actionpack (= 7.0.8.6) + actiontext (= 7.0.8.6) + actionview (= 7.0.8.6) + activejob (= 7.0.8.6) + activemodel (= 7.0.8.6) + activerecord (= 7.0.8.6) + activestorage (= 7.0.8.6) + activesupport (= 7.0.8.6) bundler (>= 1.15.0) - railties (= 7.0.3.1) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) + railties (= 7.0.8.6) + rails-dom-testing (2.2.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.0) + loofah (~> 2.21) + nokogiri (~> 1.14) + railties (7.0.8.6) + actionpack (= 7.0.8.6) + activesupport (= 7.0.8.6) method_source rake (>= 12.2) thor (~> 1.0) zeitwerk (~> 2.5) - rake (13.0.6) - redis (4.8.0) - regexp_parser (2.5.0) - reline (0.3.1) + rake (13.2.1) + rb-fsevent (0.11.2) + rb-inotify (0.11.1) + ffi (~> 1.0) + rdoc (6.7.0) + psych (>= 4.0.0) + redis (4.8.1) + regexp_parser (2.9.2) + reline (0.5.10) io-console (~> 0.5) - rexml (3.2.5) + rexml (3.3.9) rubyzip (2.3.2) - selenium-webdriver (4.4.0) - childprocess (>= 0.5, < 5.0) + sass (3.7.4) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sass-rails (5.1.0) + railties (>= 5.2.0) + sass (~> 3.1) + sprockets (>= 2.8, < 4.0) + sprockets-rails (>= 2.0, < 4.0) + tilt (>= 1.1, < 3) + selenium-webdriver (4.10.0) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) - sprockets (4.1.1) + sprockets (3.7.5) + base64 concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.4.2) - actionpack (>= 5.2) - activesupport (>= 5.2) + sprockets-rails (3.5.2) + actionpack (>= 6.1) + activesupport (>= 6.1) sprockets (>= 3.0.0) - stimulus-rails (1.1.0) - railties (>= 6.0.0) - strscan (3.0.4) - tailwindcss-rails (2.0.12-arm64-darwin) - railties (>= 6.0.0) - tailwindcss-rails (2.0.12-x86_64-linux) + stimulus-rails (1.3.4) railties (>= 6.0.0) - thor (1.2.1) - timeout (0.3.0) - turbo-rails (1.1.1) + stringio (3.1.1) + tailwindcss-rails (3.0.0) + railties (>= 7.0.0) + tailwindcss-ruby + tailwindcss-ruby (3.4.14-arm64-darwin) + tailwindcss-ruby (3.4.14-x86_64-darwin) + tailwindcss-ruby (3.4.14-x86_64-linux) + thor (1.3.2) + tilt (2.4.0) + timeout (0.4.1) + turbo-rails (2.0.11) actionpack (>= 6.0.0) - activejob (>= 6.0.0) railties (>= 6.0.0) - tzinfo (2.0.5) + tzinfo (2.0.6) concurrent-ruby (~> 1.0) - 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 (1.2.11) + websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.0) + zeitwerk (2.6.18) PLATFORMS - arm64-darwin-20 + arm64-darwin + arm64-darwin-23 + x86_64-darwin x86_64-linux DEPENDENCIES + bcrypt (~> 3.1.7) bootsnap + bootstrap (~> 4.1.1) capybara debug dotenv-rails + geocoder (~> 1.3, >= 1.3.7) importmap-rails jbuilder + kredis mysql2 (~> 0.5) + nio4r (~> 2.5) puma (~> 5.0) rails (~> 7.0.3, >= 7.0.3.1) redis (~> 4.0) + sass-rails (~> 5.0) selenium-webdriver sprockets-rails stimulus-rails @@ -249,4 +301,4 @@ RUBY VERSION ruby 3.1.2p20 BUNDLED WITH - 2.3.18 + 2.5.18 diff --git a/README.md b/README.md index 85f6c86ae..8ac3209fb 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ Smith College CSC223: Software Engineering\ Starter App for ValetBike project +#katie was here :3 + ## Environment Configuration As you configure your environment you should **keep a log** where you **write down all the steps you take** including **each command you type**. You will inevitably run into errors setting up your development environment and maintaining a meticulous log will allow others to help you troubleshoot. Ignore this recommendation at your own peril, but don't say you haven't been warned :] diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js index b06fc42ac..a2d906a5b 100644 --- a/app/assets/config/manifest.js +++ b/app/assets/config/manifest.js @@ -1,5 +1,6 @@ //= link_tree ../images -//= link_directory ../stylesheets .css +//= link application.css +//= link_directory ../stylesheets .scss //= link_tree ../../javascript .js //= link_tree ../../../vendor/javascript .js //= link_tree ../builds diff --git a/app/assets/images/MHBike.png b/app/assets/images/MHBike.png new file mode 100644 index 000000000..27e6e0eca Binary files /dev/null and b/app/assets/images/MHBike.png differ diff --git a/app/assets/images/MHmoney.jpg b/app/assets/images/MHmoney.jpg new file mode 100644 index 000000000..1fc457e69 Binary files /dev/null and b/app/assets/images/MHmoney.jpg differ diff --git a/app/assets/images/MHvehicle.webp b/app/assets/images/MHvehicle.webp new file mode 100644 index 000000000..bf632d45a Binary files /dev/null and b/app/assets/images/MHvehicle.webp differ diff --git a/app/assets/images/favicon.ico b/app/assets/images/favicon.ico new file mode 100644 index 000000000..ffb2aed28 Binary files /dev/null and b/app/assets/images/favicon.ico differ diff --git a/app/assets/images/ghoulia.jpg b/app/assets/images/ghoulia.jpg new file mode 100644 index 000000000..f165cad2c Binary files /dev/null and b/app/assets/images/ghoulia.jpg differ diff --git a/app/assets/images/logo.png b/app/assets/images/logo.png new file mode 100644 index 000000000..db6865363 Binary files /dev/null and b/app/assets/images/logo.png differ diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 288b9ab71..7c35026b8 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -12,4 +12,5 @@ * *= require_tree . *= require_self - */ + + */ \ No newline at end of file diff --git a/app/assets/stylesheets/form.css b/app/assets/stylesheets/form.css new file mode 100644 index 000000000..0728af263 --- /dev/null +++ b/app/assets/stylesheets/form.css @@ -0,0 +1,55 @@ +.form-container { + background-color: var(--white-color); + margin-top: 5rem; + padding: 2rem; + border-radius: var(--widget-radius); +} + +.form-wrapper { + margin-top: 2rem; +} + +.form-wrapper input[type=submit], .form-wrapper button { + display: block; + margin: auto; + width: 100%; +} + +.form-title { + font-family: var(--title-font); + font-weight: 500; + font-size: 1.5em; + text-align: center; +} + +.form-field label { + font-size: 0.8em; +} + +.form-field .form-control { + border-radius: var(--btn-radius); + border: var(--btn-thickness) solid var(--gray-color); +} + +.error-message { + font-size: 0.8em; + margin-bottom: 0; +} + +.error-message li { + list-style-type: circle; +} + +.form-logo img { + width: 180px; + margin: 0 auto; +} + +.form-links { + margin-top: 1em; + text-align: center; +} + +.form-links p a { + color: var(--theme-color); +} \ No newline at end of file diff --git a/app/assets/stylesheets/global.css b/app/assets/stylesheets/global.css index ff48f1abe..7e0f04c30 100644 --- a/app/assets/stylesheets/global.css +++ b/app/assets/stylesheets/global.css @@ -22,6 +22,22 @@ body { -ms-text-size-adjust:100%; } +caption{ + font-size:15pt; + -webkit-text-size-adjust:100%; + -moz-text-size-adjust:100%; + -ms-text-size-adjust:100%; + text-align: center; +} + +sub-caption{ + font-size:12pt; + -webkit-text-size-adjust:100%; + -moz-text-size-adjust:100%; + -ms-text-size-adjust:100%; + text-align: center; +} + #site-container{ position: relative; width: 100%; @@ -33,3 +49,57 @@ body { color: var(--black-color); background: var(--white-color); } + +.bg-fill { + background-color: var(--theme-color); + position: absolute; + width: 100%; + height: auto; + min-height: 100%; + padding-bottom: 3rem; +} + +.custom-btn { + padding: 0.5rem 1.5rem; + border-radius: var(--btn-radius); + transition: 0.1s ease; +} + +.btn-fill { + background: var(--theme-color); + color: var(--white-color); + border: var(--btn-thickness) solid var(--theme-color); +} + +.btn-fill:hover { + background: var(--white-color); + color: var(--black-color); +} + +img{ + height: 40%; + width: 40%; + margin-top: .5em; + border-radius: 15%; + border: 3px solid whitesmoke; + image-orientation: center; +} +.btn-outline { + background: var(--white-color); + border: var(--btn-thickness) solid var(--theme-color); +} + +.btn-outline:hover { + background: var(--theme-color); + color: var(--white-color); +} + +.btn-danger { + background: var(--danger-color); + color: var(--white-color); +} + +.btn-invalid { + background: var(--invalid-color); + color: var(--white-color); +} diff --git a/app/assets/stylesheets/header.css b/app/assets/stylesheets/header.css new file mode 100644 index 000000000..84b184bb1 --- /dev/null +++ b/app/assets/stylesheets/header.css @@ -0,0 +1,6 @@ +.app-header { + margin-bottom: 3em; + padding: 1.5em 0; + background: rgba(53, 144, 202, 0.95); + position: relative; +} \ No newline at end of file diff --git a/app/assets/stylesheets/variables.css b/app/assets/stylesheets/variables.css index 915c14dd3..68d2c8b17 100644 --- a/app/assets/stylesheets/variables.css +++ b/app/assets/stylesheets/variables.css @@ -9,5 +9,11 @@ --dark-white-color: #F3F2F3; --medium-white-color: #FDFCFD; --white-color: #FFFFFF; + --invalid-color: #B1B1B1; + --theme-color: #905ADB; + --btn-radius: 0.3rem; + --widget-radius: 0.5rem; + --btn-thickness: 2px; + --danger-color: #8B0000; } \ No newline at end of file diff --git a/app/controllers/access_controller.rb b/app/controllers/access_controller.rb new file mode 100644 index 000000000..6d98e1537 --- /dev/null +++ b/app/controllers/access_controller.rb @@ -0,0 +1,18 @@ +class AccessController < ApplicationController + def create + # Process log in information + @user = User.find_by(email: params[:email]) + if !!@user && @user&.authenticate(params[:password]) + session[:user_id] = @user[:id] + redirect_to root_path + else + flash[:notice] = "Something went wrong. Please check your email and password." + redirect_to log_in_path + end + end + + def destroy + session[:user_id] = nil + redirect_to root_path + end +end diff --git a/app/controllers/account_controller.rb b/app/controllers/account_controller.rb new file mode 100644 index 000000000..dec7e5782 --- /dev/null +++ b/app/controllers/account_controller.rb @@ -0,0 +1,28 @@ +class AccountController < ApplicationController + before_action :get_user_info_from_session + def index + if !logged_in? || !@user + redirect_to log_in_path + end + end + + def destroy + if !!@user + session[:user_id] = nil + @user.destroy + redirect_to root_path + end + end + + private +=begin + def get_user_info_from_session + @user = User.find_by(id: session[:user_id]) + end + + def logged_in? + # Check user's log in status + session[:user_id].present? + end +=end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 09705d12a..84808f420 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,2 +1,13 @@ class ApplicationController < ActionController::Base + + helper_method :get_user_info_from_session + helper_method :logged_in? + + def get_user_info_from_session + @user = User.find_by(id: session[:user_id]) + end + def logged_in? + # Check user's log in status + session[:user_id].present? + end end diff --git a/app/controllers/bikes_controller.rb b/app/controllers/bikes_controller.rb new file mode 100644 index 000000000..036a4f038 --- /dev/null +++ b/app/controllers/bikes_controller.rb @@ -0,0 +1,12 @@ +class BikesController < ApplicationController + def _row + @bikes = Bike.all.order(identifier: :asc) + end + + def index + end + def show + @bike = Bike.find(params[:id]) + end + +end diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb new file mode 100644 index 000000000..4e0b3c61c --- /dev/null +++ b/app/controllers/main_controller.rb @@ -0,0 +1,10 @@ +class MainController < ApplicationController + def index + end + + def pricing + end + + def contact + end +end diff --git a/app/controllers/password_resets_controller.rb b/app/controllers/password_resets_controller.rb new file mode 100644 index 000000000..5e9c354a1 --- /dev/null +++ b/app/controllers/password_resets_controller.rb @@ -0,0 +1,50 @@ +class PasswordResetsController < ApplicationController + def create + # Process email and send reset link + @user = User.find_by(email: params[:email]) + + if !!@user + # Send email in the background + PasswordMailer.with(user: @user).reset.deliver_later + flash[:notice] = "An email will be sent with a link to reset your password." + else + flash[:notice] = "An error occured. Please try again." + end + + redirect_to password_reset_url + end + + def edit + # Find the user with the given token + if params[:token] + @user = User.find_signed(params[:token], purpose: "password_reset") + else + redirect_to log_in_path + end + rescue ActiveSupport::MessageVerifier::InvalidSignature + redirect_to password_reset_url, notice: "Your token has expired. Please try again" + end + + def update + # Actually updates the password + @user = User.find_signed(params[:token], purpose: "password_reset") + + if @user.update(password_params) + flash[:notice] = "Your password was reset successfully. Please sign in." + redirect_to log_in_path + else + render :edit, status: 422 # have to set status. otherwise, the errors won't render + end + + rescue ActiveSupport::MessageVerifier::InvalidSignature + redirect_to password_reset_url, notice: "Your token has expired. Please try again" + end + + private + + def password_params + params.require(:user).permit(:password, :password_confirmation) + end + + +end diff --git a/app/controllers/stations_controller.rb b/app/controllers/stations_controller.rb index 88090af16..b8136fa54 100644 --- a/app/controllers/stations_controller.rb +++ b/app/controllers/stations_controller.rb @@ -2,6 +2,21 @@ class StationsController < ApplicationController def index @stations = Station.all.order(identifier: :asc) + @lats = Array.new # array of latitudes + @longs = Array.new # array of longitudes + @stations.each do |s| + puts s.latitude + @lats.append(s.latitude) + @longs.append(s.longitude) + end + end + + def show + @user = get_user_info_from_session + @station = Station.find(params[:id]) + unless @user.current_trip_id.nil? + @trip = Trip.find(@user.current_trip_id) + end end end diff --git a/app/controllers/trips_controller.rb b/app/controllers/trips_controller.rb new file mode 100644 index 000000000..b14035061 --- /dev/null +++ b/app/controllers/trips_controller.rb @@ -0,0 +1,49 @@ +class TripsController < ApplicationController + def new + @trip = Trip.new + @bike = Bike.find(params[:bike_id]) + @station = Station.find(params[:station_id]) + @user = User.find(params[:user_id]) + end + + def create + @trip = Trip.new(trip_params) + if @trip.save + @bike = Bike.find(@trip.bike_id) + @station = Station.find(@trip.start_station_is) + @user = User.find(@trip.user_id) + @user.update(current_trip_id: @trip.id) + @bike.update(is_available: false, current_station_id: nil) + redirect_to confirm_path(trip_id: @trip.id) + else + render :new + end + end + def show + @trip = Trip.find(params[:trip_id]) + end + + def confirmation + @trip = Trip.find(params[:trip_id]) + end + + def end_confirmation + @trip = Trip.find(params[:trip_id]) + @user = User.find(@trip.user_id) + @bike = Bike.find(@trip.bike_id) + @user.update(current_trip_id: nil) + @bike.update(is_available: true, current_station_id: params[:end_station_id]) + end + + def update + end + + def edit + end + + def trip_params + params.require(:trip).permit(:bike_id, :user_id, :start_station_is, :start_time) + end + + +end diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb new file mode 100644 index 000000000..09dfb94bc --- /dev/null +++ b/app/controllers/user_controller.rb @@ -0,0 +1,25 @@ +class UserController < ApplicationController + def new + # Display the sign up form + @user = User.new + end + + def create + # Process sign up information + @user = User.new(user_params) + if @user.save + redirect_to log_in_path # make them log in + else + render :new, status: 422 + end + end + + private + + def user_params + # Return params that includes only the given fields + # and sets the permitted attribute for the object to true. + # (useful for limiting which attributes should be allowed for updating) + params.require(:user).permit(:email, :password, :password_confirmation) + end +end diff --git a/app/helpers/access_helper.rb b/app/helpers/access_helper.rb new file mode 100644 index 000000000..342c6ff9f --- /dev/null +++ b/app/helpers/access_helper.rb @@ -0,0 +1,2 @@ +module AccessHelper +end diff --git a/app/helpers/account_helper.rb b/app/helpers/account_helper.rb new file mode 100644 index 000000000..6d3694a49 --- /dev/null +++ b/app/helpers/account_helper.rb @@ -0,0 +1,2 @@ +module AccountHelper +end diff --git a/app/helpers/bikes_helper.rb b/app/helpers/bikes_helper.rb new file mode 100644 index 000000000..a2645e4e1 --- /dev/null +++ b/app/helpers/bikes_helper.rb @@ -0,0 +1,2 @@ +module BikesHelper +end diff --git a/app/helpers/main_helper.rb b/app/helpers/main_helper.rb new file mode 100644 index 000000000..826effed9 --- /dev/null +++ b/app/helpers/main_helper.rb @@ -0,0 +1,2 @@ +module MainHelper +end diff --git a/app/helpers/password_resets_helper.rb b/app/helpers/password_resets_helper.rb new file mode 100644 index 000000000..0c9d96ecf --- /dev/null +++ b/app/helpers/password_resets_helper.rb @@ -0,0 +1,2 @@ +module PasswordResetsHelper +end diff --git a/app/helpers/trips_helper.rb b/app/helpers/trips_helper.rb new file mode 100644 index 000000000..04f333d46 --- /dev/null +++ b/app/helpers/trips_helper.rb @@ -0,0 +1,2 @@ +module TripsHelper +end diff --git a/app/helpers/user_helper.rb b/app/helpers/user_helper.rb new file mode 100644 index 000000000..0147c3fe6 --- /dev/null +++ b/app/helpers/user_helper.rb @@ -0,0 +1,2 @@ +module UserHelper +end diff --git a/app/javascript/application.js b/app/javascript/application.js index 0d7b49404..346cc81ed 100644 --- a/app/javascript/application.js +++ b/app/javascript/application.js @@ -1,3 +1,6 @@ +//= require bootstrap-sprockets // Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails import "@hotwired/turbo-rails" import "controllers" + +import "bootstrap" \ No newline at end of file diff --git a/app/javascript/osm_map.js b/app/javascript/osm_map.js new file mode 100644 index 000000000..59f13322d --- /dev/null +++ b/app/javascript/osm_map.js @@ -0,0 +1,46 @@ +/* +Base for this code pulled from https://stackoverflow.com/questions/925164/openstreetmap-embedding-map-in-webpage-like-google-maps +Answer by user totymedli +*/ + +const northamptonLat = '42.328674'; // what it says on the tag +const northamptonLng = '-72.646'; // rough center of northampton +const center = L.latLng(northamptonLat, northamptonLng); + +/* +initializes the map for future use +TODO + - figure out the tiling thing and how to get an actual image rendered +*/ +function mapInit(element){ + + // Create Leaflet map on map element. + var map = L.map(element); + + // Add OSM tile layer to the Leaflet map. + L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { + attribution: '© OpenStreetMap contributors' + }).addTo(map); + + // Set map's center to target with zoom 14. + map.setView(center, 14); // consider changing zoom + + return map +} + +/* +adds a marker to the leaflet +TODO + - hoping that the map var is getting set correctly + - add a popup to the marker to link to the station page +*/ +function addMarker(map, lat, lng) { + // Target's GPS coordinates. + var target = L.latLng(lat, lng); + + // Place a marker on the location. + L.marker(target).addTo(map); + + // Set map's center to target with zoom 14. + map.setView(center, 14); // consider changing zoom +} \ No newline at end of file diff --git a/app/mailers/password_mailer.rb b/app/mailers/password_mailer.rb new file mode 100644 index 000000000..aafdc4eb2 --- /dev/null +++ b/app/mailers/password_mailer.rb @@ -0,0 +1,15 @@ +class PasswordMailer < ApplicationMailer + + # Subject can be set in your I18n file at config/locales/en.yml + # with the following lookup: + # + # en.password_mailer.reset.subject + # + def reset + @user = params[:user] + + @token = @user.signed_id(expires_in: 15.minutes, purpose: 'password_reset') + + mail to: @user.email + end +end diff --git a/app/models/bike.rb b/app/models/bike.rb index f3648e343..eeb6d33a7 100644 --- a/app/models/bike.rb +++ b/app/models/bike.rb @@ -4,4 +4,13 @@ class Bike < ApplicationRecord belongs_to :current_station, class_name: :Station, foreign_key: :current_station_id, optional: true + + def available? + is_available + end + + def get_station + Station.find(current_station_id) + end + end diff --git a/app/models/station.rb b/app/models/station.rb index 64b9eaada..1a9430776 100644 --- a/app/models/station.rb +++ b/app/models/station.rb @@ -1,9 +1,14 @@ -class Station < ApplicationRecord +class Station < ApplicationRecord validates_presence_of :identifier, :name, :address validates_uniqueness_of :identifier has_many :docked_bikes, class_name: :Bike, foreign_key: :current_station_id - + + attribute :latitude, type: Float + attribute :longitude, type: Float + + geocoded_by :address + after_validation :geocode end diff --git a/app/models/trip.rb b/app/models/trip.rb new file mode 100644 index 000000000..d265a2ccc --- /dev/null +++ b/app/models/trip.rb @@ -0,0 +1,3 @@ +class Trip < ApplicationRecord + belongs_to :user +end diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 000000000..d4562c976 --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,16 @@ +class User < ApplicationRecord + has_secure_password + + EMAIL_REGEX = /\A[\w\-\.]+@([\w\-]+\.)+[\w\-]{2,4}\z/ + validates :email, presence: true, + uniqueness: {case_sensitive: false}, + format: {with: EMAIL_REGEX} + has_many :trips, dependent: :destroy + + def has_trip? + unless current_trip_id.nil? + current_trip_id + end + end + +end diff --git a/app/views/access/login.html.erb b/app/views/access/login.html.erb new file mode 100644 index 000000000..84ac41334 --- /dev/null +++ b/app/views/access/login.html.erb @@ -0,0 +1,37 @@ +
+
+
+
+ +
+ Log into your account +
+
+ <% if flash[:notice].present? %> +
+

<%= flash[:notice] %>

+
+ <% end %> + <%= form_with model: @user, url: log_in_path do |f| %> +
+ <%= f.label :email, "Email" %> + <%= f.text_field :email, placeholder: "Enter your email", class: "form-control" %> +
+
+ <%= f.label :password, "Password" %> + <%= f.password_field :password, placeholder: "Enter your password", class: "form-control" %> +
+ <%= f.submit "Log in", class: "mt-3 custom-btn btn-fill" %> + <% end %> + <%= button_to('Cancel', root_path, class: "mt-3 custom-btn btn-outline", method: :get) %> +
+ +
+
+
+
\ No newline at end of file diff --git a/app/views/account/index.html.erb b/app/views/account/index.html.erb new file mode 100644 index 000000000..e07be6fd0 --- /dev/null +++ b/app/views/account/index.html.erb @@ -0,0 +1,19 @@ +
+
+
+ My account +
+ + <% if @user %> + <%= @user[:email] %> + + <%= button_to('Delete account', account_path(@user[:id]), class: "mt-3 custom-btn btn-danger", method: :delete) %> + <%= button_to('Log out', log_out_path, class: "mt-3 custom-btn btn-outline", method: :post) %> + <% else %> +
+ No account found. +
+ <% end %> + +
+
diff --git a/app/views/bikes/_row.html.erb b/app/views/bikes/_row.html.erb new file mode 100644 index 000000000..0a2bb2424 --- /dev/null +++ b/app/views/bikes/_row.html.erb @@ -0,0 +1,27 @@ +
+
+ <% user = get_user_info_from_session %> + <% station = bike.get_station%> + Bike <%= bike.identifier %> + <% if !logged_in? || !user %> + <%= button_to('Reserve Bike', {}, class: "mt-3 custom-btn btn-invalid", method: :get) %> + Please log in to reserve bike + <% else if user.has_trip?%> + <%= button_to('Reserve Bike', {}, class: "mt-3 custom-btn btn-invalid", method: :get) %> + Please return your current bike to reserve a new one + <% else if !bike.available? %> + <%= button_to('Reserve Bike', {}, class: "mt-3 custom-btn btn-invalid", method: :get) %> + Bike is currently Unavailable + <% else %> + <%= link_to 'Reserve Bike', new_trip_path(bike_id: bike.id, station_id: station.id, user_id: user.id), class: 'action new' "mt-3 custom-btn btn-outline" "", method: :get %> + <% end %> + <% end %> + <% end %> + + +
+
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 7ace1393e..6e7ee1b24 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -8,14 +8,24 @@ <%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %> <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> <%= javascript_importmap_tags %> + + - + <%= favicon_link_tag asset_path('favicon.ico') %> + <%= yield :head %> ValetBike
- <%= yield %> +
+ <%= link_to('Home Page', {controller: 'main' , action: 'index'}) %> | + <%= link_to('Bikes/Stations', {controller: 'stations' , action: 'index'}) %> | + <%= link_to('Pricing', {controller: 'main' , action: 'pricing'}) %> | + <%= link_to('Contact', {controller: 'main' , action: 'contact'}) %> | + <%= link_to('Account', {controller: 'account' , action: 'index'}) %> +
+ <%= content_for(:content) ? yield(:content) : yield %>
diff --git a/app/views/main/contact.html.erb b/app/views/main/contact.html.erb new file mode 100644 index 000000000..cb2f91bec --- /dev/null +++ b/app/views/main/contact.html.erb @@ -0,0 +1,15 @@ +
+
+
+ Contact Page +
+
+ + We are ValetBike! We are NOT a group of gay kids taking CSC223 and making a website at all nooooo... + You can reachout to our contact: DivaDevs@valetbike.com with any questions or concerns. + + <%= image_tag('ghoulia.jpg') %> +
+
+
+ \ No newline at end of file diff --git a/app/views/main/index.html.erb b/app/views/main/index.html.erb new file mode 100644 index 000000000..8a0ce9cfa --- /dev/null +++ b/app/views/main/index.html.erb @@ -0,0 +1,20 @@ +<% content_for :head do %> +<% end %> + +<% content_for :content do %> +
+
+
+ ValetBike Home Page +
+
+
+ This could be you!: + + <%= image_tag('MHBike.png') %> +
+ + +
+<% end %> \ No newline at end of file diff --git a/app/views/main/pricing.html.erb b/app/views/main/pricing.html.erb new file mode 100644 index 000000000..faf927c0f --- /dev/null +++ b/app/views/main/pricing.html.erb @@ -0,0 +1,27 @@ +
+
+
+ Pricing Page +
+ +
+ We at ValetBike offer many different options that range various levels. + + + + Our Student Plan offers free 30 minutes of ride time a day at the charge + of $5.99 a month. + + +
+ +
+ Must have vaild studentID from a University or College you are currently attending + +
+ + <%= image_tag('MHmoney.jpg') %> +
+
diff --git a/app/views/password_mailer/reset.html.erb b/app/views/password_mailer/reset.html.erb new file mode 100644 index 000000000..52e1c618e --- /dev/null +++ b/app/views/password_mailer/reset.html.erb @@ -0,0 +1,11 @@ +
+ <%= image_tag('logo.png', alt: 'valetbike-logo') %> + +
+

Hi <%= @user.email %>,

+ +

If it was you who requested a password reset, please click on the link below to reset your password. The link will expire in 15 minutes.

+ + <%= link_to "Reset Password", password_reset_edit_url(token: @token) %> +
+
\ No newline at end of file diff --git a/app/views/password_mailer/reset.text.erb b/app/views/password_mailer/reset.text.erb new file mode 100644 index 000000000..c754b68db --- /dev/null +++ b/app/views/password_mailer/reset.text.erb @@ -0,0 +1,5 @@ +Hi <%= @user.email %>, + +If it was you who requested a password reset, please click on the link below to reset your password. The link will expire in 15 minutes. + +<%= password_reset_edit_url(token: @token) %> \ No newline at end of file diff --git a/app/views/password_resets/edit.html.erb b/app/views/password_resets/edit.html.erb new file mode 100644 index 000000000..0dc980130 --- /dev/null +++ b/app/views/password_resets/edit.html.erb @@ -0,0 +1,41 @@ +
+
+
+
+ +
+ Reset your password +
+
+ <%= form_with model: @user, url: password_reset_edit_path(token: params[:token]) do |f| %> + <% if f.object && f.object.errors.any? %> +
+
    + <% f.object.errors.full_messages.each do |message| %> +
  • <%= message %>
  • + <% end %> +
+
+ <% end %> +
+ <%= f.label :password, "Password" %> + <%= f.password_field :password, placeholder: "Enter your password", class: "form-control" %> +
+
+ <%= f.label :password_confirmation, "Confirm your password" %> + <%= f.password_field :password_confirmation, placeholder: "Enter your password again", class: "form-control" %> +
+ <%= f.submit "Reset", class: "mt-3 custom-btn btn-fill" %> + <% end %> + <%= button_to('Cancel', root_path, class: "mt-3 custom-btn btn-outline", method: :get) %> +
+ +
+
+
+
\ No newline at end of file diff --git a/app/views/password_resets/new.html.erb b/app/views/password_resets/new.html.erb new file mode 100644 index 000000000..35cbfd6b4 --- /dev/null +++ b/app/views/password_resets/new.html.erb @@ -0,0 +1,34 @@ +
+
+
+
+ +
+ Reset password +
+
+ <% if flash[:notice].present? %> +
+

<%= flash[:notice] %>

+
+ <% end %> + + <%= form_with url: password_reset_path do |f| %> +
+ <%= f.label :email, "Email" %> + <%= f.text_field :email, placeholder: "Enter your email", class: "form-control" %> +
+ <%= f.submit "Reset password", class: "mt-3 custom-btn btn-fill" %> + <% end %> + <%= button_to('Cancel', root_path, class: "mt-3 custom-btn btn-outline", method: :get) %> +
+ +
+
+
+
\ No newline at end of file diff --git a/app/views/shared/_header.html.erb b/app/views/shared/_header.html.erb new file mode 100644 index 000000000..e69de29bb diff --git a/app/views/stations/_leaflet.html.erb b/app/views/stations/_leaflet.html.erb new file mode 100644 index 000000000..1e96c8401 --- /dev/null +++ b/app/views/stations/_leaflet.html.erb @@ -0,0 +1,24 @@ +
+ +<%= content_tag :div, '', id: 'lats', data: {source: lats} %> +<%= content_tag :div, '', id: 'longs', data: {source: longs} %> + + \ No newline at end of file diff --git a/app/views/stations/_row.html.erb b/app/views/stations/_row.html.erb index 68a74d983..be97aac79 100644 --- a/app/views/stations/_row.html.erb +++ b/app/views/stations/_row.html.erb @@ -1,3 +1,11 @@
flexbox vertical stretch"> - <%= station.identifier %>: <%= station.name %> (<%= station.address %>) -
\ No newline at end of file + Station <%= station.identifier %>: <%= station.name %> (<%= station.address %>) +
+ <%= Bike.where(current_station_id: station.id).length %> available bikes +
+
+ <%= button_to('More Details', station_path(station), class: "mt-3 custom-btn btn-outline", method: :get) %> + <%#= link_to('More Details', station_path(station), class: 'action :show') %> + <%#= render(partial: "bikes/row", collection: Bike.where(current_station_id: station.id), as: :bike )%> +
+ diff --git a/app/views/stations/index.html.erb b/app/views/stations/index.html.erb index d211dda42..429de90f7 100644 --- a/app/views/stations/index.html.erb +++ b/app/views/stations/index.html.erb @@ -1,16 +1,34 @@ -
-
-
- Welcome to ValetBike! -
-
- <% if @stations.present? %> - <%= render(partial: "stations/row", collection: @stations, as: :station) %> - <% else %> -
- No stations found. +<% content_for :head do %> + + + + <%= javascript_include_tag('https://unpkg.com/leaflet-geosearch@latest/dist/bundle.min.js') %> + <%= javascript_include_tag('osm_map.js') %> +<% end %> + +<% content_for :content do %> +
+
+
+ Bikes and Stations +
+ + <%= render partial: "stations/leaflet", locals: {lats: @lats, longs: @longs} %> + +
+ <% if @stations.present? %> + <%= render(partial: "stations/row", collection: @stations, as: :station) %> + <% else %> +
+ No stations found. +
+ <% end %>
- <% end %>
-
-
+
+<% end %> diff --git a/app/views/stations/show.html.erb b/app/views/stations/show.html.erb new file mode 100644 index 000000000..a823d806c --- /dev/null +++ b/app/views/stations/show.html.erb @@ -0,0 +1,11 @@ +<%= button_to('< Back to Stations', {controller: 'stations', action: 'index'}, class: "mt-3 custom-btn btn-outline", method: :get) %> +
+Info for Station: <%= @station.identifier %>: <%= @station.name %> (<%= @station.address %>) +<% unless @user.current_trip_id.nil? && @trip.nil?%> + <%= link_to 'Return Bike to This Station', end_confirm_path(trip_id: @trip.id, end_station_id: @station.id), + class: "mt-3 custom-btn btn-outline" %> +<% end %> +
+ <%= Bike.where(current_station_id: @station.id).length %> available bikes: + <%= render(partial: "bikes/row", collection: Bike.where(current_station_id: @station.id), as: :bike )%> +
\ No newline at end of file diff --git a/app/views/trips/_form.html.erb b/app/views/trips/_form.html.erb new file mode 100644 index 000000000..c8c3b9f83 --- /dev/null +++ b/app/views/trips/_form.html.erb @@ -0,0 +1,23 @@ + +

New Trip

+ + + + + + + + + + + + + + + + + + + + +
Bike ID: <%= @bike.identifier %>
User ID:<%= @user.id %>
Station:<%= @station.identifier %>
Pickup Time<%= f.time_field(:start_time) %>
diff --git a/app/views/trips/confirmation.html.erb b/app/views/trips/confirmation.html.erb new file mode 100644 index 000000000..fd4ff1018 --- /dev/null +++ b/app/views/trips/confirmation.html.erb @@ -0,0 +1,33 @@ +
+
+
+ thanks for booking!! + Confirmation +
+ Trip is Confirmed! id: + <%= @trip.id %> + +
+
\ No newline at end of file diff --git a/app/views/trips/edit.html.erb b/app/views/trips/edit.html.erb new file mode 100644 index 000000000..e69de29bb diff --git a/app/views/trips/end_confirmation.html.erb b/app/views/trips/end_confirmation.html.erb new file mode 100644 index 000000000..00c16f526 --- /dev/null +++ b/app/views/trips/end_confirmation.html.erb @@ -0,0 +1,2 @@ +Trip ended! + diff --git a/app/views/trips/index.html.erb b/app/views/trips/index.html.erb new file mode 100644 index 000000000..e69de29bb diff --git a/app/views/trips/new.html.erb b/app/views/trips/new.html.erb new file mode 100644 index 000000000..0a84e0f21 --- /dev/null +++ b/app/views/trips/new.html.erb @@ -0,0 +1,38 @@ +
flexbox vertical stretch"> + <%= button_to("Back to Bikes", station_path(@station), class: "mt-3 custom-btn btn-outline", method: :get) %> + + <%= form_for(@trip) do |f| %> + +

New Trip

+ + + + + + + + + + + + + + + + + <%= f.hidden_field :bike_id, value: @bike.id %> + <%= f.hidden_field :user_id, value: @user.id %> + <%= f.hidden_field :start_station_is, value: @station.id %> + + + + + +
Bike ID: <%= @bike.identifier %>
User ID:<%= @user.id %>
Station:<%= @station.identifier %>
Pickup Time<%= f.time_field(:start_time) %>
+ +
+ <%= f.submit("Create Trip") %> +
+ + <% end %> +
diff --git a/app/views/trips/show.html.erb b/app/views/trips/show.html.erb new file mode 100644 index 000000000..e69de29bb diff --git a/app/views/user/new.html.erb b/app/views/user/new.html.erb new file mode 100644 index 000000000..ce769696f --- /dev/null +++ b/app/views/user/new.html.erb @@ -0,0 +1,45 @@ +
+
+
+
+ +
+ Sign up an account +
+
+ <% if @user.errors.any? %> +
+
    + <% @user.errors.full_messages.each do |message| %> +
  • <%= message %>
  • + <% end %> +
+
+ <% end %> + + <%= form_with model: @user, url: sign_up_path do |f| %> +
+ <%= f.label :email, "Email" %> + <%= f.text_field :email, placeholder: "Enter your email", class: "form-control" %> +
+
+ <%= f.label :password, "Password" %> + <%= f.password_field :password, placeholder: "Enter your password", class: "form-control" %> +
+
+ <%= f.label :password_confirmation, "Confirm your password" %> + <%= f.password_field :password_confirmation, placeholder: "Enter your password again", class: "form-control" %> +
+ <%= f.submit "Create an account", class: "mt-3 custom-btn btn-fill" %> + <% end %> + <%= button_to('Cancel', root_path, class: "mt-3 custom-btn btn-outline", method: :get) %> +
+ +
+
+
+
\ No newline at end of file diff --git a/config/environments/development.rb b/config/environments/development.rb index 8500f459a..b242f5c70 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -67,4 +67,6 @@ # Uncomment if you wish to allow Action Cable access from any origin. # config.action_cable.disable_request_forgery_protection = true + + config.action_mailer.default_url_options = {host: 'localhost:3000'} end diff --git a/config/importmap.rb b/config/importmap.rb index 8dce42d40..60a344996 100644 --- a/config/importmap.rb +++ b/config/importmap.rb @@ -4,4 +4,5 @@ pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true +pin "bootstrap", to: 'bootstrap.min.js', preload: true pin_all_from "app/javascript/controllers", under: "controllers" diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 2eeef966f..c3ae110ab 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -9,4 +9,11 @@ # Precompile additional assets. # application.js, application.css, and all non-JS/CSS in the app/assets # folder are already added. -# Rails.application.config.assets.precompile += %w( admin.js admin.css ) +Rails.application.config.assets.precompile += %w( form.css ) + +# uhh so rails told me to add all these inexplicably but it works now so... +Rails.application.config.assets.precompile += %w( tailwind.css ) +Rails.application.config.assets.precompile += %w( bootstrap.min.js ) +Rails.application.config.assets.precompile += %w( controllers/hello_controller.js ) +Rails.application.config.assets.precompile += %w( controllers/index.js ) +Rails.application.config.assets.precompile += %w( osm_map.js ) diff --git a/config/initializers/geocoder.rb b/config/initializers/geocoder.rb new file mode 100644 index 000000000..c5edf0e9f --- /dev/null +++ b/config/initializers/geocoder.rb @@ -0,0 +1,27 @@ +Geocoder.configure( + # Geocoding options + # timeout: 3, # geocoding service timeout (secs) + lookup: :nominatim, # name of geocoding service (symbol) + # ip_lookup: :ipinfo_io, # name of IP address geocoding service (symbol) + language: :en, # ISO-639 language code + # use_https: false, # use HTTPS for lookup requests? (if supported) + # http_proxy: nil, # HTTP proxy server (user:pass@host:port) + # https_proxy: nil, # HTTPS proxy server (user:pass@host:port) + # api_key: nil, # API key for geocoding service + # cache: nil, # cache object (must respond to #[], #[]=, and #del) + + # Exceptions that should not be rescued by default + # (if you want to implement custom error handling); + # supports SocketError and Timeout::Error + # always_raise: [], + + # Calculation options + units: :mi, # :km for kilometers or :mi for miles + distances: :linear # :spherical or :linear + + # Cache configuration + # cache_options: { + # expiration: 2.days, + # prefix: 'geocoder:' + # } +) diff --git a/config/routes.rb b/config/routes.rb index f1eb0a0d8..1ffcdda4e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,37 @@ Rails.application.routes.draw do - root to: "stations#index" + get 'stations/index' + get 'stations/show' + get 'bikes/index' + get 'bikes/_row' + get 'main/pricing' + get 'main/contact' + + + get "confirm", to: "trips#confirmation" + get "end_confirm", to: "trips#end_confirmation" + + + # resources :bikes + # resources :stations + resources :stations, only: [:index, :show] do + resources :bikes, only: [:index, :show] + end + + resources :trips, except: [:destroy] + + get "sign-up", to: "user#new" + post "sign-up", to: "user#create" + + get "log-in", to: "access#login" + post "log-in", to: "access#create" + post "log-out", to: "access#destroy" + + get "password/reset", to: "password_resets#new" + post "password/reset", to: "password_resets#create" + get "password/reset/edit", to: "password_resets#edit" + patch "password/reset/edit", to: "password_resets#update" + + resources :account, only: [:index, :destroy] + + root to: "main#index" end \ No newline at end of file diff --git a/db/migrate/20241031151655_create_users.rb b/db/migrate/20241031151655_create_users.rb new file mode 100644 index 000000000..ca0284b32 --- /dev/null +++ b/db/migrate/20241031151655_create_users.rb @@ -0,0 +1,11 @@ +class CreateUsers < ActiveRecord::Migration[7.0] + def change + create_table :users do |t| + t.string :name + t.string :email, null: false + # t.string :password_digest + + t.timestamps + end + end +end diff --git a/db/migrate/20241031210449_add_password_digest_to_users.rb b/db/migrate/20241031210449_add_password_digest_to_users.rb new file mode 100644 index 000000000..5b478015b --- /dev/null +++ b/db/migrate/20241031210449_add_password_digest_to_users.rb @@ -0,0 +1,6 @@ +class AddPasswordDigestToUsers < ActiveRecord::Migration[7.0] + def change + add_column :users, :password_digest, :string + add_column :users, :string, :string + end +end diff --git a/db/migrate/20241101172048_add_phone_number_to_users.rb b/db/migrate/20241101172048_add_phone_number_to_users.rb new file mode 100644 index 000000000..85fbd3aa2 --- /dev/null +++ b/db/migrate/20241101172048_add_phone_number_to_users.rb @@ -0,0 +1,5 @@ +class AddPhoneNumberToUsers < ActiveRecord::Migration[7.0] + def change + add_column :users, :phone_number, :string + end +end diff --git a/db/migrate/20241110203104_add_availablility.rb b/db/migrate/20241110203104_add_availablility.rb new file mode 100644 index 000000000..3999bd2ea --- /dev/null +++ b/db/migrate/20241110203104_add_availablility.rb @@ -0,0 +1,5 @@ +class AddAvailablility < ActiveRecord::Migration[7.0] + def change + add_column :bikes, :is_available, :boolean, :default => true + end +end diff --git a/db/migrate/20241110210524_create_trips.rb b/db/migrate/20241110210524_create_trips.rb new file mode 100644 index 000000000..c63317ac2 --- /dev/null +++ b/db/migrate/20241110210524_create_trips.rb @@ -0,0 +1,13 @@ +class CreateTrips < ActiveRecord::Migration[7.0] + def change + create_table :trips do |t| + t.integer :bike_id # bike IDENTIFIER + t.integer :user_id + t.datetime :start_time + t.datetime :end_time + t.integer :end_station_id # station IDENTIFIER + + t.timestamps + end + end +end diff --git a/db/migrate/20241112212031_geocode_stations.rb b/db/migrate/20241112212031_geocode_stations.rb new file mode 100644 index 000000000..f5e8262ae --- /dev/null +++ b/db/migrate/20241112212031_geocode_stations.rb @@ -0,0 +1,6 @@ +class GeocodeStations < ActiveRecord::Migration[7.0] + def change + add_column :stations, :latitude, :double + add_column :stations, :longitude, :double + end +end diff --git a/db/migrate/20241114204842_add_start_station_to_trip.rb b/db/migrate/20241114204842_add_start_station_to_trip.rb new file mode 100644 index 000000000..931c4c15b --- /dev/null +++ b/db/migrate/20241114204842_add_start_station_to_trip.rb @@ -0,0 +1,5 @@ +class AddStartStationToTrip < ActiveRecord::Migration[7.0] + def change + add_column :trips, :start_station_is, :integer + end +end diff --git a/db/migrate/20241120010325_add_trip_to_users.rb b/db/migrate/20241120010325_add_trip_to_users.rb new file mode 100644 index 000000000..b940d9efc --- /dev/null +++ b/db/migrate/20241120010325_add_trip_to_users.rb @@ -0,0 +1,5 @@ +class AddTripToUsers < ActiveRecord::Migration[7.0] + def change + add_column :users, :current_trip_id, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index b98268f0e..2b2177047 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,12 +10,13 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2022_08_31_090719) do +ActiveRecord::Schema[7.0].define(version: 2024_11_20_184529) do create_table "bikes", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.integer "identifier" t.integer "current_station_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.boolean "is_available", default: true end create_table "stations", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| @@ -24,6 +25,30 @@ t.string "address" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.float "latitude", limit: 53 + t.float "longitude", limit: 53 + end + + create_table "trips", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "bike_id" + t.integer "user_id" + t.datetime "start_time" + t.datetime "end_time" + t.integer "end_station_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "start_station_is" + end + + create_table "users", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.string "name" + t.string "email", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "password_digest" + t.string "string" + t.string "phone_number" + t.integer "current_trip_id" end end diff --git a/lib/tasks/load_data.rake b/lib/tasks/load_data.rake new file mode 100644 index 000000000..626db11e7 --- /dev/null +++ b/lib/tasks/load_data.rake @@ -0,0 +1,25 @@ +namespace :load_data do + require 'csv' + + desc "Reads the station data in from the CSV." + task :station => :environment do + CSV.foreach('notes/station-data.csv', :headers => true) do |row| #stations + station = Station.create(identifier: row[0], + name: row[1], + address: row[6]) + end + end + + desc "Reads the bike data in from the CSV." + task :bike => :environment do + + CSV.foreach('notes/bike-data.csv', :headers => true) do |row| #bikes + station = Station.find_by(identifier: row[1]) + bike = Bike.create(identifier: row[0], current_station: station) + bike.current_station_id = station != nil ? station.id : nil + bike.save + + end + end + +end diff --git a/public/favicon.ico b/public/favicon.ico index e69de29bb..ffb2aed28 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/test/controllers/access_controller_test.rb b/test/controllers/access_controller_test.rb new file mode 100644 index 000000000..13ef117b0 --- /dev/null +++ b/test/controllers/access_controller_test.rb @@ -0,0 +1,8 @@ +require "test_helper" + +class AccessControllerTest < ActionDispatch::IntegrationTest + test "should get create" do + get access_create_url + assert_response :success + end +end diff --git a/test/controllers/account_controller_test.rb b/test/controllers/account_controller_test.rb new file mode 100644 index 000000000..032b870bd --- /dev/null +++ b/test/controllers/account_controller_test.rb @@ -0,0 +1,8 @@ +require "test_helper" + +class AccountControllerTest < ActionDispatch::IntegrationTest + test "should get index" do + get account_index_url + assert_response :success + end +end diff --git a/test/controllers/bikes_controller_test.rb b/test/controllers/bikes_controller_test.rb new file mode 100644 index 000000000..4f9b2d3f3 --- /dev/null +++ b/test/controllers/bikes_controller_test.rb @@ -0,0 +1,13 @@ +require "test_helper" + +class BikesControllerTest < ActionDispatch::IntegrationTest + test "should get index" do + get bikes_index_url + assert_response :success + end + + test "should get _row" do + get bikes__row_url + assert_response :success + end +end diff --git a/test/controllers/main_controller_test.rb b/test/controllers/main_controller_test.rb new file mode 100644 index 000000000..759df146c --- /dev/null +++ b/test/controllers/main_controller_test.rb @@ -0,0 +1,8 @@ +require "test_helper" + +class MainControllerTest < ActionDispatch::IntegrationTest + test "should get index" do + get main_index_url + assert_response :success + end +end diff --git a/test/controllers/password_resets_controller_test.rb b/test/controllers/password_resets_controller_test.rb new file mode 100644 index 000000000..abcca3e88 --- /dev/null +++ b/test/controllers/password_resets_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class PasswordResetsControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/test/controllers/trips_controller_test.rb b/test/controllers/trips_controller_test.rb new file mode 100644 index 000000000..c0efe9f75 --- /dev/null +++ b/test/controllers/trips_controller_test.rb @@ -0,0 +1,18 @@ +require "test_helper" + +class TripsControllerTest < ActionDispatch::IntegrationTest + test "should get index" do + get trips_index_url + assert_response :success + end + + test "should get new" do + get trips_new_url + assert_response :success + end + + test "should get edit" do + get trips_edit_url + assert_response :success + end +end diff --git a/test/controllers/user_controller_test.rb b/test/controllers/user_controller_test.rb new file mode 100644 index 000000000..f067a70e1 --- /dev/null +++ b/test/controllers/user_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class UserControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/test/fixtures/trips.yml b/test/fixtures/trips.yml new file mode 100644 index 000000000..45222f191 --- /dev/null +++ b/test/fixtures/trips.yml @@ -0,0 +1,15 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + bike_id: 1 + user_id: 1 + start_time: 2024-11-10 16:05:24 + end_time: 2024-11-10 16:05:24 + end_station_id: 1 + +two: + bike_id: 1 + user_id: 1 + start_time: 2024-11-10 16:05:24 + end_time: 2024-11-10 16:05:24 + end_station_id: 1 diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml new file mode 100644 index 000000000..cc9a815cd --- /dev/null +++ b/test/fixtures/users.yml @@ -0,0 +1,11 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name: MyString + email: MyString + password: MyString + +two: + name: MyString + email: MyString + password: MyString diff --git a/test/mailers/password_mailer_test.rb b/test/mailers/password_mailer_test.rb new file mode 100644 index 000000000..6f5cc7daf --- /dev/null +++ b/test/mailers/password_mailer_test.rb @@ -0,0 +1,12 @@ +require "test_helper" + +class PasswordMailerTest < ActionMailer::TestCase + test "reset" do + mail = PasswordMailer.reset + assert_equal "Reset", mail.subject + assert_equal ["to@example.org"], mail.to + assert_equal ["from@example.com"], mail.from + assert_match "Hi", mail.body.encoded + end + +end diff --git a/test/mailers/previews/password_mailer_preview.rb b/test/mailers/previews/password_mailer_preview.rb new file mode 100644 index 000000000..684b74290 --- /dev/null +++ b/test/mailers/previews/password_mailer_preview.rb @@ -0,0 +1,9 @@ +# Preview all emails at http://localhost:3000/rails/mailers/password_mailer +class PasswordMailerPreview < ActionMailer::Preview + + # Preview this email at http://localhost:3000/rails/mailers/password_mailer/reset + def reset + PasswordMailer.reset + end + +end diff --git a/test/models/trip_test.rb b/test/models/trip_test.rb new file mode 100644 index 000000000..c5ff46fcb --- /dev/null +++ b/test/models/trip_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class TripTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/user_test.rb b/test/models/user_test.rb new file mode 100644 index 000000000..5c07f4900 --- /dev/null +++ b/test/models/user_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class UserTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end