diff --git a/Gemfile b/Gemfile index 5efe339e6..35de3cbf2 100644 --- a/Gemfile +++ b/Gemfile @@ -76,10 +76,13 @@ end # Developer Added Gems gem 'dotenv-rails' +gem 'mapbox-gl-rails' # Suggested Potentially Useful Gems -# gem 'devise' +gem 'devise' # gem 'httparty' # gem 'paperclip # gem 'uniquify' # gem 'will_paginate' + +gem "geocoder", "~> 1.8" diff --git a/Gemfile.lock b/Gemfile.lock index c3e104938..ad6dec17d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -66,13 +66,14 @@ GEM i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) - addressable (2.8.1) + addressable (2.8.5) public_suffix (>= 2.0.2, < 6.0) + bcrypt (3.1.19) bindex (0.8.1) - bootsnap (1.13.0) + bootsnap (1.17.0) msgpack (~> 1.2) builder (3.2.4) - capybara (3.37.1) + capybara (3.39.2) addressable matrix mini_mime (>= 0.1.3) @@ -81,68 +82,79 @@ GEM 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.2.2) crass (1.0.6) - debug (1.6.2) - irb (>= 1.3.6) + date (3.3.4) + debug (1.8.0) + irb (>= 1.5.0) reline (>= 0.3.1) - digest (3.1.0) + devise (4.9.3) + bcrypt (~> 3.0) + orm_adapter (~> 0.1) + railties (>= 4.1.0) + responders + warden (~> 1.2.3) dotenv (2.8.1) dotenv-rails (2.8.1) dotenv (= 2.8.1) railties (>= 3.2) erubi (1.11.0) + geocoder (1.8.2) globalid (1.0.0) activesupport (>= 5.0) i18n (1.12.0) concurrent-ruby (~> 1.0) - importmap-rails (1.1.5) + importmap-rails (1.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) + io-console (0.6.0) + irb (1.8.3) + rdoc + reline (>= 0.3.8) jbuilder (2.11.5) actionview (>= 5.0.0) activesupport (>= 5.0.0) - loofah (2.18.0) + loofah (2.21.4) 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) + net-imap + net-pop + net-smtp + mapbox-gl-rails (2.9.0) + railties (>= 3.2) marcel (1.0.2) 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 + mini_mime (1.1.5) + minitest (5.20.0) + msgpack (1.7.2) + mysql2 (0.5.5) + net-imap (0.4.4) + date net-protocol - strscan - net-pop (0.1.1) - digest + net-pop (0.1.2) net-protocol + net-protocol (0.2.1) timeout - net-protocol (0.1.3) - timeout - net-smtp (0.3.1) - digest + net-smtp (0.4.0) net-protocol - timeout - nio4r (2.5.8) - nokogiri (1.13.8-arm64-darwin) + nio4r (2.5.9) + nokogiri (1.15.4-x86_64-darwin) racc (~> 1.4) - nokogiri (1.13.8-x86_64-linux) + nokogiri (1.15.4-x86_64-linux) racc (~> 1.4) - public_suffix (5.0.0) - puma (5.6.5) + orm_adapter (0.5.0) + psych (5.1.1.1) + stringio + public_suffix (5.0.3) + puma (5.6.7) nio4r (~> 2.0) - racc (1.6.0) - rack (2.2.4) - rack-test (2.0.2) + racc (1.7.3) + rack (2.2.8) + rack-test (2.1.0) rack (>= 1.3) rails (7.0.3.1) actioncable (= 7.0.3.1) @@ -158,11 +170,13 @@ GEM activesupport (= 7.0.3.1) bundler (>= 1.15.0) railties (= 7.0.3.1) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) + rails-dom-testing (2.2.0) + activesupport (>= 5.0.0) + minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.4.3) - loofah (~> 2.3) + rails-html-sanitizer (1.6.0) + loofah (~> 2.21) + nokogiri (~> 1.14) railties (7.0.3.1) actionpack (= 7.0.3.1) activesupport (= 7.0.3.1) @@ -170,41 +184,47 @@ GEM 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.1.0) + rdoc (6.6.0) + psych (>= 4.0.0) + redis (4.8.1) + regexp_parser (2.8.2) + reline (0.3.9) io-console (~> 0.5) - rexml (3.2.5) + responders (3.1.1) + actionpack (>= 5.2) + railties (>= 5.2) + rexml (3.2.6) rubyzip (2.3.2) - selenium-webdriver (4.4.0) - childprocess (>= 0.5, < 5.0) + 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 (4.2.1) concurrent-ruby (~> 1.0) - rack (> 1, < 3) + rack (>= 2.2.4, < 4) sprockets-rails (3.4.2) actionpack (>= 5.2) activesupport (>= 5.2) sprockets (>= 3.0.0) - stimulus-rails (1.1.0) + stimulus-rails (1.3.0) railties (>= 6.0.0) - strscan (3.0.4) - tailwindcss-rails (2.0.12-arm64-darwin) + stringio (3.0.8) + tailwindcss-rails (2.0.32-x86_64-darwin) railties (>= 6.0.0) - tailwindcss-rails (2.0.12-x86_64-linux) + tailwindcss-rails (2.0.32-x86_64-linux) railties (>= 6.0.0) - thor (1.2.1) - timeout (0.3.0) - turbo-rails (1.1.1) + thor (1.3.0) + timeout (0.4.1) + turbo-rails (1.5.0) 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) + warden (1.2.9) + rack (>= 2.0.9) + web-console (4.2.1) actionview (>= 6.0.0) activemodel (>= 6.0.0) bindex (>= 0.4.0) @@ -213,25 +233,29 @@ GEM nokogiri (~> 1.6) rubyzip (>= 1.3.0) selenium-webdriver (~> 4.0) - websocket (1.2.9) + websocket (1.2.10) websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.0) + zeitwerk (2.6.12) PLATFORMS - arm64-darwin-20 + x86_64-darwin-19 + x86_64-darwin-22 x86_64-linux DEPENDENCIES bootsnap capybara debug + devise dotenv-rails + geocoder (~> 1.8) importmap-rails jbuilder + mapbox-gl-rails mysql2 (~> 0.5) puma (~> 5.0) rails (~> 7.0.3, >= 7.0.3.1) @@ -249,4 +273,4 @@ RUBY VERSION ruby 3.1.2p20 BUNDLED WITH - 2.3.18 + 2.4.19 diff --git a/README.md b/README.md index 85f6c86ae..755ee7388 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,14 @@ Smith College CSC223: Software Engineering\ Starter App for ValetBike project + +**Team member names:** +Elena Wang, +Ying Loo, +Maya Gilliom, +Lesly Gonzalez, +Chris Dong + ## 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..4a1d0a009 100644 --- a/app/assets/config/manifest.js +++ b/app/assets/config/manifest.js @@ -3,3 +3,4 @@ //= link_tree ../../javascript .js //= link_tree ../../../vendor/javascript .js //= link_tree ../builds + diff --git a/app/assets/images/Carol.png b/app/assets/images/Carol.png new file mode 100644 index 000000000..d5732a2f7 Binary files /dev/null and b/app/assets/images/Carol.png differ diff --git a/app/assets/images/Carol.png:Zone.Identifier b/app/assets/images/Carol.png:Zone.Identifier new file mode 100644 index 000000000..0fb5dfe81 --- /dev/null +++ b/app/assets/images/Carol.png:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +HostUrl=https://gencraft.com/ diff --git a/app/assets/images/Clemenbykes stock photo.png b/app/assets/images/Clemenbykes stock photo.png new file mode 100644 index 000000000..ecb839f4f Binary files /dev/null and b/app/assets/images/Clemenbykes stock photo.png differ diff --git a/app/assets/images/backg_2.png b/app/assets/images/backg_2.png new file mode 100644 index 000000000..1fe322f72 Binary files /dev/null and b/app/assets/images/backg_2.png differ diff --git a/app/assets/images/backg_2.png:Zone.Identifier b/app/assets/images/backg_2.png:Zone.Identifier new file mode 100644 index 000000000..c82c53922 --- /dev/null +++ b/app/assets/images/backg_2.png:Zone.Identifier @@ -0,0 +1,4 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=https://mail.google.com/ +HostUrl=https://mail-attachment.googleusercontent.com/attachment/u/0/?ui=2&ik=d39b9f91f6&attid=0.1&permmsgid=msg-a:r5439327989664005209&th=18c55bb2a9e644d5&view=att&disp=safe&realattid=18c55baf97ab65b46191&saddbat=ANGjdJ-cgRMWY4B8abKo7NHnC1L7VFiTqD0BeAdp9jObaT_SYcukMCO8uZpF6QKkofKQpQ1B_SdZQLgZgl6F3WMNOU2wgMps3TSGWt3o1PVVLmXinkt5FXBaQHvlVxqjCv60g_gNNUyyZBVgR10HK_prxbxnVy-NZJ-sCLm7Jfdt1e7mJIGK7MIXZpOFGnqwbmPdz501e9_fjC-lyMYWraQsBzD0EyXVzwQ4dg_qRL7lo5pBuE7g5dpfIR6v0_L85o9KIQGm8H5xQ3oZ6yx4KwMQkbVonmT5dW4oGOUXCe5I7yWCDSTu63B0udOE0kGJaVyyv3S7LmT5bDvf6dF4u7UhNB_vJ-k8GTsae4G97lkQNdzDPHHr3m4YZxpfq_bMlqS6KO2GakgFNURYqpQs7EVtXoNlxuZQaeUHyKymAzDD7olgFSn4v7EG7rp0XIvIBRE3wN1ciQueXbUr7yQdaVvwftkXI6ESlkkhsD6-3mEVqMoWRQeiH3QAtCxeZ98-zW3nJC015wrWrsckGJ6dHndNY9lFcTpnupHwtNhqYdIR37SbfsZbSRngRgAtPuvPXZxvS7Ln2skwJ5sZ_D_0_yMp6aNCmfR-7GaaLQ74tKh7S0QHE8XMoeUw7omqr2NecJ0Awe1lLLb6N64HNMmv1kEOHUsDswatTxSCVkiOTGHd-9ACCQe1b4kLGxAEftUZhiAxqcq1OSTsq3vBtsFkTMnj40mtbWUB0qkBeK1GcPZlZisTlMVBcSwaYLD_njzgGQULZLtmU7Qdg76FH8R3GMSbh1KhvK9R6RejMBcdDMEFW-D--4qy4nlplBmzBTWx-WJ7G75F-2kiQiOUrn5lgb1Q5XX9R_Q6BRR7ClE2RQ_Afwo2DfoiPyiFR-x9foXkliy7Ll6rXH5LLhe19T2sKR6__EbAaJbzmZtQ62cs5fB0xsrBfLnp9QITnorzsy48srJyJNoVUvj3JWCQXKPmv3PG18PGnlgtGsV7ojtqtVZraeHq02zYS90OoBDxka8 diff --git a/app/assets/images/background.jpeg:Zone.Identifier b/app/assets/images/background.jpeg:Zone.Identifier new file mode 100644 index 000000000..b3099f837 --- /dev/null +++ b/app/assets/images/background.jpeg:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +HostUrl=https://web.whatsapp.com/ diff --git a/app/assets/images/background.png b/app/assets/images/background.png new file mode 100644 index 000000000..dc2a6b163 Binary files /dev/null and b/app/assets/images/background.png differ diff --git a/app/assets/images/background.png:Zone.Identifier b/app/assets/images/background.png:Zone.Identifier new file mode 100644 index 000000000..16c0f684e --- /dev/null +++ b/app/assets/images/background.png:Zone.Identifier @@ -0,0 +1,4 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=https://mail.google.com/ +HostUrl=https://mail-attachment.googleusercontent.com/attachment/u/0/?ui=2&ik=d39b9f91f6&attid=0.1&permmsgid=msg-a:r5826301768616074415&th=18c55b6cb3590bd6&view=att&disp=safe&realattid=18c55b698eeb65b46191&saddbat=ANGjdJ8V0IHfCSbrF_XHXfNUntI7IFhYJVZulrMHZVauPf9G8TuVJt5V-DSBBNcbL8PkT7i1IOdVYzW5HtREj8jwIoTpRQGlhT4wpmtGhHI5C9MqBCSCfOHrm22yAg4D-1iWrMpyDb4-SPk9khlG9vXls43zFOY8-hsjUhBiKXkqirbOogrO8m24EXLiN2q5PAGU5SW3K2AIYKbqB2_KXG9975-PdTfrsCLXDv2mjheSSNFpuuNfIzT7-SwWZ6k7D5ZtdHG_d3UaVfegfJ6sJfXVK0m-Ch0mcufDqKqp6S6sHZLu_Bmcj9tW8EZ934fBhxDZnSLVfcMvjvOjr7Z2GqO4_GpBpzx5AwTUZOqc5z0TSrBj1y9nTcJpRGLA7y2SgZFIXcM9hvP0-frHjwxOjFybc8AOrJ7GBq_7DJk7cAZJ1dYJnfIqIcp0P3fPQFs0boLwfpzuRbtUGpcZK89I31B4iia5-Gybu-VBA77UoMZToN4fdg8obfPZ__r1oBYp5hKpapHToD_PUum8jx2IaNGFxdwUZvk1_HcPUj6ccHrH5cyUeHDXakWYiMFqOJasRPfRrIE3w75YRkPPqtmUUPl_emeQJHpLgKuZlq38rIeEhLb2ERUlo_o_ziiXacIVwJGtIxk9VZVqn9AswUEicDw9IPMSTGexGVIpeVd-XU4bKahcVvM0X6X1tEEfH3XR-ps_jQfoaaNQ3NJ4QxiJ7EXhqQHyQc0sXJhdzo_ZPoSMO7WnYW7uVhNsq5alnmf0hEc2lt_aS0XSXNrsrNVcEZ8ULaU_MJXdBS38Vdxdc-qePpqmOv1HlKNw-12BIH247jp91AJdc0SUS8kiBeiWzyCUCGa2IzJlXszbGdfpRl5LVqn5s8fGioeS7xZ_6Z97FP65vgl68L42VJJPzPHjAyOdwzIgUogxnt229ZTJr3lcIWAnBrIQOcHNIbPgatDlRbQo9KoZcpwXMI-8mlOuMoCoLAK41j2RVjS-EN7AV4WOt2LKhcc67F5Ti1xVVd8 diff --git a/app/assets/images/banner.jpg b/app/assets/images/banner.jpg new file mode 100644 index 000000000..94fc9850a Binary files /dev/null and b/app/assets/images/banner.jpg differ diff --git a/app/assets/images/banner.jpg:Zone.Identifier b/app/assets/images/banner.jpg:Zone.Identifier new file mode 100644 index 000000000..68e244b96 --- /dev/null +++ b/app/assets/images/banner.jpg:Zone.Identifier @@ -0,0 +1,4 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=https://www.google.com/ +HostUrl=https://st4.depositphotos.com/1145675/27091/i/450/depositphotos_270917458-stock-photo-background-banner-flowers-natural-green.jpg diff --git a/app/assets/images/bicicleta.gif b/app/assets/images/bicicleta.gif new file mode 100644 index 000000000..d66d47c93 Binary files /dev/null and b/app/assets/images/bicicleta.gif differ diff --git a/app/assets/images/bicicleta.gif:Zone.Identifier b/app/assets/images/bicicleta.gif:Zone.Identifier new file mode 100644 index 000000000..c05bf530e --- /dev/null +++ b/app/assets/images/bicicleta.gif:Zone.Identifier @@ -0,0 +1,4 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=https://mail.google.com/ +HostUrl=https://mail-attachment.googleusercontent.com/attachment/u/0/?ui=2&ik=d39b9f91f6&attid=0.1&permmsgid=msg-a:r8931870788843572318&th=18c5b49082627208&view=att&disp=safe&realattid=18c5b48f69245622f0a1&saddbat=ANGjdJ_vDA34piJ6UZcBouSVqIypSmYVht4mmjUU3hJJdVupAohoXPWePH1L37yHhzwV7OAYb0Cl7b8abu2_Uss0nQBiASIdTI_l_Me83qIRL5bBYPS2lKLFbLpl3ec2bjdGO7vjCqSlLLxPa3vxPLT6Gqk8fu6LX2ubouc5C2DVos9dYmASQz3WqDDbCY7bMzT_2YTKJuotPm6P6U8Mompq7MYMg6tgwQEZs4ZZOZ0wvzNWk-K02SqQIlWJpMzD5_cr_AQiUSXq3bjmFeOdw3XaD3u3MncQQEBx3hFI-S_pn0C3ngYKUPlu6xiey5CLuZio_nbsfDDyMF1lGeQChj8YA7epdwGrIl_UYRbBZgFsZToKgxNog1bJRy5hJJOPeOg6WmZc9QZrZ8tUVTMeemUXCgLW_uffntx76YUNMBOlvR9IACG3IuNNSc_jzc4ugq-k6chOGP_ZaSQFgmFvMFXvjEIudTsIn84tf1wtvmTtFywEGaoN8Qj42x5VWnEv3dDl2LKB7eFF86Vvs7QQPpxRKjFje2suRVfSRP5w7Z60AIFbC9GTEuj6eBorqKEiTOs5WG1g0OTCc11WA6U7FW3b2ObqPdlO0UBmxrfUMCG7RmC_zhVcyZ5bODRoZ9fNEr9cSyt_jDw99nAbbBmQpiHTsraEXKDhS_d9KlvCer1DtiBTVDmwKRtVlCMRceEWQxivBM2xKGXoJxhot-MkGZKOrclMDLvXBd_h_Av5w__wjtt2FU1lwSnZg2gBvVwY_IAXTaIw-fb-XT2KUmhakJusuR_n0PKU7fLAW7mL9VSaZA2t4XNYluMRrTaFo8Wm3Pm2XixJH57KcKyU3LCx_XaSwcGugPAxd_ok3XgxHr8RKtEjFIJ9fBOpZo5Er2jg2BQ0ic4V2mXeiFEWMXn8DiZkrmyp05OZtuKkqFwfCZCmGKRfH2YglPcbUPsBEHzBtbnwWD7qdAZJR-M7nZW-sSNskjSiZfodjE04r2Z9DkCBVuoSU_YITAeD97-5KLE diff --git a/app/assets/images/bicicleta_2.gif b/app/assets/images/bicicleta_2.gif new file mode 100644 index 000000000..b0727c061 Binary files /dev/null and b/app/assets/images/bicicleta_2.gif differ diff --git a/app/assets/images/bicicleta_2.gif:Zone.Identifier b/app/assets/images/bicicleta_2.gif:Zone.Identifier new file mode 100644 index 000000000..869f159eb --- /dev/null +++ b/app/assets/images/bicicleta_2.gif:Zone.Identifier @@ -0,0 +1,4 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=https://mail.google.com/ +HostUrl=https://mail-attachment.googleusercontent.com/attachment/u/0/?ui=2&ik=d39b9f91f6&attid=0.1&permmsgid=msg-a:r4202205693239303764&th=18c5b4c260894382&view=att&disp=safe&realattid=18c5b4c191245622f0a1&saddbat=ANGjdJ897QA7IYls4z7KVJRl6J7ysOk5lRWGsGA8BMsSd5JDTMN3Cz1YMRMRVCdnq-YFjtp9WXbGUiXXh0PIwqt-jTBil6WZRIBe9tydnDK6d0oOXrhpNY4QEDIxL6wQwAyBNHeoYGxkmk3Aq4k9KHs_k2l-DdSVPXV4aVPFAdmdu4B3lfrGK0SYUZHHXt8RvsFbm2NHSC480I_XzbWHQfrc53mu1onUwuv8LOG_r5TgG_rjB7fqf82HrjClbEmtbCSosThSpkRHYvfMQ7px3kWjsWLLnGAO45zUuUn50EUoJJd3MQ8M3B1N-To5LEzcfpIFPlasClyL_MtdTZltzZBK6akP5OdbvfScpr7yAezjnbPAyRK6J_vdBk0CiLpq4JTrnADTsJ81osolibIqkDeOmGF3AOMGBE9nqgFDSHB7BnFlRPmK-Hm1FjdQae7RabqtmfEJwUWAC2Ql_-FEOL3RwinRv4ZhoxN-gscfEFMXN-uHWO6aiywFcHtJbK_ByKv7FdHjoTfPyaubU_PbCb5qvd-mNme89OE83r9f1mpbBEIbt2-C0URSp_PAgKf3J8Sjwn9sZXfBP5NxlBCj38kMzENGNkfmoyfEe8ROqb1RMQKufxoWYdL4nC-Q4fYgjNfsJNqn5oh-3HhGtEXvFs4x_ry-Pzbgu34AB4SZYEhY_UZpq5YuxE6jPgsF6uW5GloOkqRiiaqnboxzfn8BA9Jv1V9XZKIXmLvvOiXQC6K8885MwIYfGMrC-Xo5tCf2JL-xXAIqoiNs8jf6gnc1hRLEUp_15k_uy1PZiAKBgEEt9AQE53UV1pFw_GA1LmCO5R4FlUrUutfhCLoaxw1aesSNDlZTxBi8Y2ZiySnRtB-VljLYOCyfa2FRAhXmgvBb6UkPez7iJRsS7ME7NLbZr6lsXO5NBwBVP8-IPRQ1nZw7UIBpggBpsaBLOzMgZxPOw3JQ8e3huxIL2Cx41aB0pEEJ3yyh5mqBA6rF1I4geIWlw7k_NuHbQXaKeFdj-Kc diff --git a/app/assets/images/clemenbykes_bike_light.png b/app/assets/images/clemenbykes_bike_light.png new file mode 100644 index 000000000..acfda4ca1 Binary files /dev/null and b/app/assets/images/clemenbykes_bike_light.png differ diff --git a/app/assets/images/clemenbykes_logo.png b/app/assets/images/clemenbykes_logo.png new file mode 100644 index 000000000..f4ce783cf Binary files /dev/null and b/app/assets/images/clemenbykes_logo.png differ diff --git a/app/assets/images/clemenbykes_logo_light.png b/app/assets/images/clemenbykes_logo_light.png new file mode 100644 index 000000000..d497e3719 Binary files /dev/null and b/app/assets/images/clemenbykes_logo_light.png differ diff --git a/app/assets/images/clementeam.png b/app/assets/images/clementeam.png new file mode 100644 index 000000000..5359c9979 Binary files /dev/null and b/app/assets/images/clementeam.png differ diff --git a/app/assets/images/clementeam.png:Zone.Identifier b/app/assets/images/clementeam.png:Zone.Identifier new file mode 100644 index 000000000..60f0f9780 --- /dev/null +++ b/app/assets/images/clementeam.png:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +LastWriterPackageFamilyName=Microsoft.Windows.Photos_8wekyb3d8bbwe +ZoneId=3 diff --git a/app/assets/images/get code.png b/app/assets/images/get code.png new file mode 100644 index 000000000..fcb2b555f Binary files /dev/null and b/app/assets/images/get code.png differ diff --git a/app/assets/images/kiosk unlock.png b/app/assets/images/kiosk unlock.png new file mode 100644 index 000000000..721c20c8e Binary files /dev/null and b/app/assets/images/kiosk unlock.png differ diff --git a/app/assets/images/naranja.gif b/app/assets/images/naranja.gif new file mode 100644 index 000000000..96270617d Binary files /dev/null and b/app/assets/images/naranja.gif differ diff --git a/app/assets/images/naranjita (2) - Shortcut.lnk b/app/assets/images/naranjita (2) - Shortcut.lnk new file mode 100644 index 000000000..407d097b4 Binary files /dev/null and b/app/assets/images/naranjita (2) - Shortcut.lnk differ diff --git a/app/assets/images/naranjita (2).gif:Zone.Identifier b/app/assets/images/naranjita (2).gif:Zone.Identifier new file mode 100644 index 000000000..82264d337 --- /dev/null +++ b/app/assets/images/naranjita (2).gif:Zone.Identifier @@ -0,0 +1,4 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=https://convertio.co/ +HostUrl=https://s140.convertio.me/p/oTRHi2FHBxP5YlP9vf2H4A/ad3d5f88526c42f7e26f46b4c14cd9ba/WhatsApp-Video-2023-12-04-at-4.17.49-PM.gif diff --git a/app/assets/images/orange eigth.png b/app/assets/images/orange eigth.png new file mode 100644 index 000000000..f6cbee659 Binary files /dev/null and b/app/assets/images/orange eigth.png differ diff --git a/app/assets/images/orange full.png b/app/assets/images/orange full.png new file mode 100644 index 000000000..eba87f32e Binary files /dev/null and b/app/assets/images/orange full.png differ diff --git a/app/assets/images/orange half.png b/app/assets/images/orange half.png new file mode 100644 index 000000000..631bcc281 Binary files /dev/null and b/app/assets/images/orange half.png differ diff --git a/app/assets/images/orange_back.png b/app/assets/images/orange_back.png new file mode 100644 index 000000000..5bc63d14c Binary files /dev/null and b/app/assets/images/orange_back.png differ diff --git a/app/assets/images/orange_back.png:Zone.Identifier b/app/assets/images/orange_back.png:Zone.Identifier new file mode 100644 index 000000000..0fb5dfe81 --- /dev/null +++ b/app/assets/images/orange_back.png:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +HostUrl=https://gencraft.com/ diff --git a/app/assets/images/portada.png b/app/assets/images/portada.png new file mode 100644 index 000000000..c262e8f09 Binary files /dev/null and b/app/assets/images/portada.png differ diff --git a/app/assets/images/portada.png:Zone.Identifier b/app/assets/images/portada.png:Zone.Identifier new file mode 100644 index 000000000..0fb5dfe81 --- /dev/null +++ b/app/assets/images/portada.png:Zone.Identifier @@ -0,0 +1,3 @@ +[ZoneTransfer] +ZoneId=3 +HostUrl=https://gencraft.com/ diff --git a/app/assets/images/return bike.png b/app/assets/images/return bike.png new file mode 100644 index 000000000..79bdd4dd6 Binary files /dev/null and b/app/assets/images/return bike.png differ diff --git a/app/assets/images/ride bike.png b/app/assets/images/ride bike.png new file mode 100644 index 000000000..36c013159 Binary files /dev/null and b/app/assets/images/ride bike.png differ diff --git a/app/assets/images/team.png b/app/assets/images/team.png new file mode 100644 index 000000000..ea84c8a81 Binary files /dev/null and b/app/assets/images/team.png differ diff --git a/app/assets/images/team.png:Zone.Identifier b/app/assets/images/team.png:Zone.Identifier new file mode 100644 index 000000000..581251317 --- /dev/null +++ b/app/assets/images/team.png:Zone.Identifier @@ -0,0 +1,4 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=https://mail.google.com/ +HostUrl=https://mail-attachment.googleusercontent.com/attachment/u/0/?ui=2&ik=d39b9f91f6&attid=0.1&permmsgid=msg-a:r1247229375699654371&th=18c55eda8d5331c3&view=att&disp=safe&realattid=18c55ed9a67b65b46191&saddbat=ANGjdJ_osgNH6Uo_8IrZ--AmNbXzl2mMNAjN3ZfwQLThore23M84ovOlzGhPV30uJaw6PUd0UrLgcYjc4pzJBECesScaFUx_Lfzct06XIhYWpfNWU2VYhuzEgIMakicd2vK_4fp8deAq110Ht75ouWX0CSPp6jISGlNuW7w-jCPa5hH_emN3lKrNXuDFzIuuW4QyLsrybXJWiXQgxPfPnjHn10SS6bsLT5tNLkTByDuYXR9WeLEzg45H2_n0K_3JZ7Whf3PEXpYuCOR7OTuzU-0tps6mtFNhiVx_USdK5x-t-byx2SuJw3mK3vfy4q9O0D2TI0R8w0Hh9Y0cwRNPopkgTD59Qfca9zTwbL8WcI2CjVSaSkz7LWNAmCKhElWT9fOsLnuj-Oq1b5u6l0MYwpk8azSoLfXtARM3sYDYlG_4SV-iDU2nMpvtI01gX5csAHnCk0aRlj_9g0V6pi-S35tP2wmCAJK1hcGg6kbLSBSlxOAK6gYxUYUx_HRBg9gsACISkEklVmd2qhPv4m7hUazaeIU7M1DMMjgXrfdxVXXku_xgAOpSRzfnwjuBg0_OITX5jk61iY1EC7IO8qIripyvXUNCsPNySpPPXg5ba_y8xxfoGdwaL6WrLVNH2077qUbk-cNTAM6gLqQs-8Gltq3hta6xrE-gtH8XqtijHkga-UbY48T_3yvlWp_-Z8C_MgXopG6_QmLidMwUV4Ra2ls_BkD5tI6kM06mFe7JkZJpMvEYrvECY6RtcGUhnkmnPyOankgMySRac7Rc-BzmD6bJ801Wgk41VI_IiFRu8yMiLhMyijbaJQyDWkU356Ioi7OCbLBjv2jv4kuqB47x-ShSwvZwA_06lf-_lr8OHswAmKABKufAQ62l1xY63sIqDO3BPFg0W7RGpuOJoZSVIctyUAxp-Ch18DeHV0U3VMaurasEOuEptlFaKjyP9KtUE7h9181tYzH29mpHnqFYl-PQijYlYJAnufG3Peb3e4Xw-kBuRqtqxXmHByla358 diff --git a/app/assets/images/team_1.png b/app/assets/images/team_1.png new file mode 100644 index 000000000..f3f974a1e Binary files /dev/null and b/app/assets/images/team_1.png differ diff --git a/app/assets/images/team_1.png:Zone.Identifier b/app/assets/images/team_1.png:Zone.Identifier new file mode 100644 index 000000000..6ec4d6c0b --- /dev/null +++ b/app/assets/images/team_1.png:Zone.Identifier @@ -0,0 +1,5 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=https://mail.google.com/ +HostUrl=https://mail-attachment.googleusercontent.com/attachment/u/0/?ui=2&ik=d39b9f91f6&attid=0.1&permmsgid=msg-a:r-4944343429027153900&th=18c56baed664a1f6&view=att&disp=safe&realattid=18c56bad8b0b65b46191&saddbat=ANGjdJ9D7hACPRRukQrxtpHZ7JLbXnb6mOgZD89Z2mXCm4McJin3fa-pU-qilZF2hpblAFp_Ry3lpNI37jnluNKxA_3FM6MeevKNsP581wc6Bq4YXPzH-vFaWOpOyuGcHAnI8n3AgGzwNPqNtSjnWJ1pwiw4gojSYysPR4_3AASVn2XQJMBUJNNmWsgyMVwNyrYwey96q6Iv1I7eWxczVrA_OQGsskmWLBKBVXn3v02wdKuQGhvggBQDfiHCOesku1zWgawrwxrfatBDQI5i85CpAnSgLkfvunK0m43JaAH75IxCBqS65IBjf36qyxKwizelAhxhRJ6_9vgJkFsmIi4KBth4OXPCy8-WSkoR4i-US_NoN4wAqrBSlrEHV6FU2cc4aFLoSj2eehzfpavDeSlXJujpG2inj51aNzY9pP-WY_r1xN-IBXKZEgsMeMUEkREgsrBWykFR2FF_k1GjvIMGO0oCUxVSXwtNsJkKW0pfBSMlPqGq1_p_pVBdCwKLLMoB1cA2TI5OSegv9-RBnhuFVRetEf_FIZsSjwWlmv-J19S1hUkRCnzzLnatRqGffz_3qiU8W1TeoJ7oKVrgeWiih1pHWcNgd6IukYC7sTvSnpOkECGYakQG_DPxm_c7HqQhuyY5FHAqSjc1FcRQX7X6vAC9f7QTD2eThoDoYOnBzveS5A4nY-PYoEtzkX2YbL-fZ_3P3UtMqtDFMuc9uoa-Nxr1CmQZaFWABDnJSdL1G-SMpoO3Lzx4chov66m77CHzdgnSNd5bpFugqOL3P_m2mWgvC8QPG8gcldO7-XBBXXsORAEkh7OlRTVCZA6LQ4oMb-CUSnLZrCYSMRzTv1lLzVLCIaDBYEPcCW84lPQGm3Fm481MNhZfaL0G250UnSks7cRyMBZ9I-hM5nX8Za6Bts-Faw-dx3IHFUMksn4xLGEhX06ay4cnH10mdUHh8BrkKXH_j374zaK5Ac4f5sWP9hHvYkMA7xCL-OCKBlDhTw_u6DcFT06op0gOnaA +LastWriterPackageFamilyName=Microsoft.Windows.Photos_8wekyb3d8bbwe diff --git a/app/assets/images/unlock bike 2.png b/app/assets/images/unlock bike 2.png new file mode 100644 index 000000000..ab2bf29fd Binary files /dev/null and b/app/assets/images/unlock bike 2.png differ diff --git a/app/assets/images/user_profile.png b/app/assets/images/user_profile.png new file mode 100644 index 000000000..25a47ec9e Binary files /dev/null and b/app/assets/images/user_profile.png differ diff --git a/app/assets/images/user_profile.png:Zone.Identifier b/app/assets/images/user_profile.png:Zone.Identifier new file mode 100644 index 000000000..09cf58781 --- /dev/null +++ b/app/assets/images/user_profile.png:Zone.Identifier @@ -0,0 +1,4 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=https://www.google.com/ +HostUrl=https://cdn3.iconfinder.com/data/icons/vector-icons-6/96/256-512.png diff --git a/app/assets/stylesheets/dropdown.css b/app/assets/stylesheets/dropdown.css new file mode 100644 index 000000000..dc2e0f61c --- /dev/null +++ b/app/assets/stylesheets/dropdown.css @@ -0,0 +1,64 @@ +.sidebar{ + height: 100%; + width: 300px; + position: absolute; + z-index: 1; + top: 0; + left: 0; + background-color: #60843f; + overflow-x: hidden; + padding-top: 20px; +} + +.sidebar a { + border-radius: 120px; + text-decoration: none; + font-size: 1em; + color: #ffffff; + display: block; + transition: 0.3s; + } + +.sidebar a:hover{ + border-radius: 120px; + border-style: solid; + border-width: thin medium thin; + border-color: white; + background-color: #e09213; +} + +.sidebar .closebtn { + position: absolute; + top: 0; + right: 25px; + font-size: 36px; + margin-left: 50px; + } + + .openbtn { + position: absolute; + border-radius: 5px; + font-size: 20px; + cursor: pointer; + background-color: #60843f; + padding: 10px 15px; + color: white; + border: none; + margin-left: -640px; + } + + .openbtn:hover { + background-color: #59882d; + } + + /* Style page content - use this if you want to push the page content to the right when you open the side navigation */ + #stationview { + transition: margin-left .5s; /* If you want a transition effect */ + padding: 20px; + } + + /* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */ + @media screen and (max-height: 450px) { + .sidebar {padding-top: 15px;} + .sidebar a {font-size: 18px;} + } \ No newline at end of file diff --git a/app/assets/stylesheets/global.css b/app/assets/stylesheets/global.css index ff48f1abe..5d726ed8d 100644 --- a/app/assets/stylesheets/global.css +++ b/app/assets/stylesheets/global.css @@ -31,5 +31,5 @@ body { font-family: var(--body-font); font-weight: 400; color: var(--black-color); - background: var(--white-color); + background: color(#fafdeb) } diff --git a/app/assets/stylesheets/map.css b/app/assets/stylesheets/map.css new file mode 100644 index 000000000..7f6036a12 --- /dev/null +++ b/app/assets/stylesheets/map.css @@ -0,0 +1,15 @@ + #map{ + background-color: #ffffff; + grid-area: map; + } + + .mapboxgl-popup { + max-width: 200px; + } + + .mapboxgl-popup-content { + text-align: center; + font-family: 'Open Sans', + sans-serif; + } + \ No newline at end of file diff --git a/app/assets/stylesheets/navigation.css b/app/assets/stylesheets/navigation.css new file mode 100644 index 000000000..d0366437f --- /dev/null +++ b/app/assets/stylesheets/navigation.css @@ -0,0 +1,173 @@ +.button{ + border-radius: 25px; + display: block; + color: white; + background-color: #557735; + text-align: center; + padding: 8px; +} + +.button:hover { + background-color: #2a3f17; + transition: background-color 0.3s; +} + +.rent-button{ + display: block; + color: white; + border-radius: 10%; + background-color: #78a350; + text-align: center; + padding: 8px; + margin-top: 10px; + margin-left: 15px; + margin-bottom: 10px; + width: 70%; +} + +.rent-button:hover { + background-color: #d39510; + border-radius: 10%; + transition: background-color 0.3s; +} + +.profile-button{ + display: block; + color: white; + border-radius: 10%; + background-color: #78a350; + text-align: center; + padding: 8px; + margin-top: 10px; + width: 100%; +} + +.profile-button:hover { + background-color: #426521; + border-radius: 10%; + transition: background-color 0.3s; +} + +.back-button{ + display: block; + color: white; + border-radius: 5%; + background-color: #476d24; + text-align: center; + padding: 8px; + margin-top: 10px; + width: 100%; +} + +.back-button:hover { + border-radius: 20%; + transition: background-color 0.3s; +} + +.pricing-button{ + display: block; + color: white; + border-radius: 10%; + background-color: #baad3c; + text-align: center; + padding: 8px; + margin-top: 10px; + width: 100%; +} + +.pricing-button:hover { + background-color: #655a21; + border-radius: 10%; + transition: background-color 0.3s; +} + + + +nav{ + float:right +} + +nav ul { + list-style-type: none; + margin: 0; + padding: 0; + overflow: hidden; + background-color: #ff873c; +} + +nav ul li { + float: left; + margin: 0; +} + +nav ul li a { + display: block; + color: white; + float: right; + text-align: center; + padding: 40px 45px; + text-decoration: none; +} + + +nav ul li a:push{ + margin-left: auto; +} + +nav ul li a:hover { + background-color: #f67f25; +} + +nav ul li form { + display: block; + color: white; + float: right; + text-align: center; + padding: 40px 45px; + text-decoration: none; +} + +nav ul form:hover { + background-color: #f67f25; +} + + +input[type=text], select { + width: 100%; + padding: 12px 20px; + margin: 0; + display: inline-block; + border: 1px solid #ccc; + border-radius: 4px; + box-sizing: border-box; + } + + +input[type=text], select { + width: 100%; + padding: 12px 20px; + margin: 0; + display: inline-block; + border: 1px solid #ccc; + border-radius: 4px; + box-sizing: border-box; + } + + input[type=submit] { + width: 100%; + background-color: #557735; + color: white; + padding: 14px 20px; + margin: 8px 0; + border: none; + border-radius: 4px; + cursor: pointer; + } + + input[type=submit]:hover { + background-color: #557735; + } + + .form-label { + font-size: 13px; + } \ No newline at end of file diff --git a/app/assets/stylesheets/pages.css b/app/assets/stylesheets/pages.css index 16bd64b55..9a77ebfd5 100644 --- a/app/assets/stylesheets/pages.css +++ b/app/assets/stylesheets/pages.css @@ -2,10 +2,211 @@ /* Universal Page Style */ /************************************/ +header { + background: #ff873c; + grid-row: 1; +} + +header::after { + content: ''; + display: table; + clear: both; +} + +.home-container{ + display: grid; + min-height: 100vh; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-rows: .2fr .5fr .2fr 1fr; + grid-template-areas: + "welcome welcome bikeimg bikeimg" + "howto howto howto howto" + "desc desc desc desc" + "map map map map" + +} + +.map-container{ + display: grid; + height: 100vh; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-rows: .5fr .5fr; + grid-template-areas: + "mapSidebar desc desc desc" + "mapSidebar map map map" + +} + +.reglog-container{ + display: grid; + height: 100vh; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-areas: + "reglog reglog reglog reglog" +} + +.gen-container{ + display: grid; + height: 100vh; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-areas: + "gen gen gen gen" +} + +.about-container { + display: grid; + min-height: 100vh; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-rows: .3fr .5fr .2fr 1fr; + grid-template-areas: + "text text img img" + "faq faq faq faq" +} + +.pay-container{ + display: grid; + height: 100vh; + grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr; + grid-template-rows: 1fr 1fr 1fr 1fr 1fr 1fr; + grid-template-areas: + "first first first last last last" + "mon mon year year cvv cvv" + "num num num num num num" +} + +.check-container{ + display: grid; + min-height: 100vh; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-areas: + "bikeimg bikeimg desc desc" + "rdesc rdesc rdesc rdesc" +} +.profile-container { + display: grid; + min-height: 90vh; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-rows: .3fr .5fr .2fr 1fr; + grid-template-areas: + "photo photo" + "name name" + "background-photo background-photo background-photo background-photo" +} + +footer { + grid-row: 3; + bottom: 0; + width: 100%; + padding: 3em; + background: #ff873c; +} + +footer ul{ + float: right; + color: white; +} + +.container{ + margin: 0 auto; + justify-content: space-between; +} + +.row { + display: flex; + text-align: center; +} + +.column{ + border-radius: 25px; + background-color: #ffffff; + color: #2a5c25; + flex: 1; +} + + +.profile-column{ + z-index: 2; + border-radius: 25px; + border-color: #cfad47; + border-width: thick; + background-color: #ffffff; + color: #69b962; + padding: 3em 1em 3em 1em; + width: 25%; + margin-left: 870px; +} + +.profile-row { + display: block; + position: static; + margin-bottom: 170px; +} + +.register-container { + display: grid; + min-height: 160vh; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-rows: .3fr .5fr .2fr 1fr; + grid-template-areas: + "reg reg reg reg" +} + + +.register-column{ + border-radius: 25px; + background-color: #ffffff; + color: #2a5c25; + flex: 1; +} + +.register-row { + display: flex; + text-align: center; +} + +.payment-container { + display: grid; + min-height: 120vh; + max-height: 130vh; + min-width: 120vh; + grid-template-columns: 2fr 2fr 2fr 2fr; + grid-template-rows: .3fr .5fr .2fr 1fr; + grid-template-areas: + "pay pay pay pay" +} + +.payment-column{ + border-radius: 25px; + background-color: #ffffff; + margin-left: 7px; + color: #2a5c25; + flex: 1; +} + +.code-container { + display: grid; + min-height: 90vh; + max-width: 120vh; + background-color: white; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-rows: .3fr .5fr .2fr 1fr; + grid-template-areas: + "code code code code" +} + +.column h1{ + text-align: center; + font-size: 2em; +} + +.logo{ + float: left; + padding: 1em; +} + .page-section { - max-width: 80em; + max-width: 100em; width: 100%; - margin-top: 4em; } .page-section .section-inner { @@ -18,6 +219,7 @@ font-weight: 500; font-size: 2.5em; margin-bottom: 1em; + justify-content: center; } .record-row { @@ -35,6 +237,7 @@ } + /***********************************/ /* Responsiveness */ /***********************************/ @@ -49,4 +252,4 @@ margin-bottom: .6em; } -} +} \ No newline at end of file diff --git a/app/assets/stylesheets/sections.css b/app/assets/stylesheets/sections.css new file mode 100644 index 000000000..53374b303 --- /dev/null +++ b/app/assets/stylesheets/sections.css @@ -0,0 +1,157 @@ +#welcome { + background-color: #ffffff; + color: #2a5c25; + left: 0; + grid-area: welcome; + } + +#bikeimg { + right: 0; + background-color: #ffffff; + grid-area: bikeimg; +} + +#howto { + background-color: #ffcd91; + color: #2a5c25; + grid-area: howto; +} + +#desc{ + color: #2a5c25; + grid-area: desc; +} + +#rdesc{ + color: #2a5c25; + grid-area: rdesc; +} + + +#text { + background-color: #5c803c; + color: #ffffff; + top: 15%; + grid-area: text; +} + +#img { + background-color: #5c803c; + top: 50%; + grid-area: img; +} + +#faq { + grid-area: faq; + position:absolute ; + top: 38%; + left: 6%; +} + +#stationview{ + grid-area: stationview; +} + +#newrental{ + color: #2a5c25; +} + +#reglog{ + background-color: #b1e695; + color: #2a5c25; + grid-area: reglog; +} + +#general{ + color: #2a5c25; + grid-area: gen; +} + +#photo { + position: relative; + z-index: 2; +} + +#background-photo { + position: absolute; + z-index: 1; +} + +#name { + display: flex; + align-items: left; + justify-content: left; + text-align: left; + font-size: 24px; /* Adjust the font size as needed */ + font-family: sans-serif; /* Replace 'YourFont' with the desired font-family */ + color: #075c11; /* Set your desired text color */ + left: 50px; + padding-top: 0px; +} + +.profile-picture img { + display: flex; + align-items: right; + justify-content: right; + border-radius: 50%; + width: 90px; + height: 90px; + border: 4px solid #fff; + z-index: 2; + left: 50px; +} + +.back-picture img { + align-items: center; + justify-content: center; + width: 230vh; + height: 100vh; + z-index: 1; +} + +.profile-info h2 { + margin: 0; +} + +.centered { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + text-align: center; +} + +.profile-centered { + position: absolute; + top: 65%; + left: 15%; + transform: translate(-50%, -50%); + text-align: center; +} + +.centered img{ + max-width: 750px; + max-height: 500px; + position: static; + margin: auto; +} + +.bold-brown{ + font-weight: bold; + color: #134213; +} + +#reg{ + color: #2a5c25; + grid-area: reg; +} + +#pay{ + color: #2a5c25; + grid-area: pay; +} + +#code{ + color: #2a5c25; + grid-area: gen; +} \ No newline at end of file diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 09705d12a..084d01ecd 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,2 +1,12 @@ class ApplicationController < ActionController::Base + before_action :configure_permitted_parameters, if: :devise_controller? + + protected + + def configure_permitted_parameters + devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name, :birthday, :phone_number]) + devise_parameter_sanitizer.permit(:account_update, keys: [:first_name, :last_name, :phone_number]) + end + + end diff --git a/app/controllers/bikes_controller.rb b/app/controllers/bikes_controller.rb new file mode 100644 index 000000000..b304b5861 --- /dev/null +++ b/app/controllers/bikes_controller.rb @@ -0,0 +1,10 @@ +class BikesController < ApplicationController + + def index + # if params[:reverse].blank? || params[:reverse] == "0" + # @bikes = Bike.all.order(identifier: :asc) + # else + # @bikes = Bike.all.order(identifier: :desc) + end + +end diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb new file mode 100644 index 000000000..63da74ee1 --- /dev/null +++ b/app/controllers/home_controller.rb @@ -0,0 +1,44 @@ +class HomeController < ApplicationController + before_action :authenticate_user!, only: [:profile] + + before_action :set_active_rental, only: [:map, :profile] # defines a user's currently active rental if they have one + + def index + if params[:station].present? + @stations = Station.near(params[:station]) + else + @stations = Station.all.order(identifier: :asc) + end + end + + def map + if params[:station].present? + @stations = Station.near(params[:station]) + else + @stations = Station.all.order(identifier: :asc) + end + end + + def pricing + end + + def help + end + + def explore + end + + def profile + end + + private + + # defines a user's currently active rental if they have one + def set_active_rental + if user_signed_in? && !current_user.rentals.where(return: nil).empty? + @active_rental = current_user.rentals.where(return: nil).first + end + end + + +end diff --git a/app/controllers/payments_controller.rb b/app/controllers/payments_controller.rb new file mode 100644 index 000000000..0227e562d --- /dev/null +++ b/app/controllers/payments_controller.rb @@ -0,0 +1,86 @@ +class PaymentsController < ApplicationController + before_action :authenticate_user! + before_action :check_user, only: [:new, :create, :edit, :update] + before_action :check_existing_payment, only: [:new, :create] + before_action :check_payment_id, only: [:edit, :update] + + def index + @user = current_user + @payment = Payment.new + render :new + #temporary workaround to keep users on the new form in case they reload the page + end + + def show + @user = current_user + @payment = Payment.find_by(user_id: current_user.id) + render :edit + #temporary workaround to keep users on the edit form in case they reload the page + end + + def new + @user = current_user + @payment = Payment.new + end + + def create + @user = current_user + @payment = Payment.new(payment_params) + @payment.user = @user + if @payment.save + flash.notice = "Payment information saved" + redirect_to profile_home_index_path + else + render(action: :new) + end + end + + def edit + @user = current_user + @payment = Payment.find_by(user_id: current_user.id) + end + + def update + @user = current_user + @payment = Payment.find_by(user_id: current_user.id) + if @payment.update(payment_params) && @payment.valid? + flash.notice = "Payment information updated" + redirect_to profile_home_index_path + else + render :edit + end + end + + def check_user + if current_user.id != params[:user_id].to_i + flash.alert = "Unable to access requested resource. Check for proper URL." + redirect_to profile_home_index_path + end + end + + + def check_payment_id + @user = current_user + if @user.payment.id != params[:id].to_i + flash.alert = "Unable to access requested resource. Check for proper URL." + redirect_to profile_home_index_path + end + end + + + + def check_existing_payment + @user = current_user + @payment = Payment.find_by(user_id: @user) + if @payment.present? + redirect_to edit_user_payment_path(user_id: @user, id: @payment) and return true + end + end + + private + + def payment_params + params.require(:payment).permit(:first_name, :last_name, :card_number, :cvv, :exp_month, :exp_year) + end + +end diff --git a/app/controllers/rentals_controller.rb b/app/controllers/rentals_controller.rb new file mode 100644 index 000000000..a2d01fe9a --- /dev/null +++ b/app/controllers/rentals_controller.rb @@ -0,0 +1,122 @@ +class RentalsController < ApplicationController + before_action :authenticate_user! # forces user to log in before renting a bike + before_action :set_rental, only: [:show, :edit, :update] + before_action :set_station, only: [:new, :create, :edit] + before_action :ask_for_payment, :prevent_multi_rentals, :station_has_bikes, only: [:new, :create] + before_action :user_access, only: [:edit, :update, :show, :prevent_return_old_rental] + before_action :prevent_return_old_rental, only: [:edit, :update] # prevent user from returning a rental that was already returned + before_action :current_time, only: [:create, :update] + + + def index + @rentals = current_user.rentals + + end + + def new + @rental = Rental.new() + @station + end + + def create + @rental = Rental.new( + number: "%07d" % rand(10000000), + borrower: current_user, + checkout_station: @station, + bike: Bike.where(current_station_id: @station.id).first, + checkout: @current_time) + + if @rental.save + redirect_to rental_path(@rental) + @bike = @rental.bike + @bike.update(current_station_id: nil) + else + render('new') + end + end + + def show + end + + def edit + @rental.update(return_station_id: @station.id) + end + + def update + if @rental.update(rental_params) + @rental.update(return: @current_time) + @rental.update(cost: @rental.duration*0.05) #one day rate should not be hard coded :) + bike = @rental.bike + bike.update(current_station_id: @rental.return_station_id) + redirect_to rental_path(@rental) + else + render('edit') + end + end + + private + + def rental_params + params.require(:rental).permit(:checkout, :station_id, :return_station_id, :return, :checkout_station, :return_station) + end + + def set_station + @station = Station.find(params[:station_id]) + end + + def set_rental + @rental = Rental.find(params[:id]) + end + + # checks if current user has no rentals that have not been returned yet + def prevent_multi_rentals + unless current_user.rentals.where(return: nil).empty? + # redirects if user has an active rental that has not been returned yet + flash[:notice] = 'Please return your current bike before renting another one.' + @active_rental = current_user.rentals.where(return: nil).first + redirect_to rental_path(@active_rental.id) # redirects to currently active rental + end + end + + # checks if the rental has already been returned + def prevent_return_old_rental + unless @rental.return.nil? + # redirects if the rental has already been returned + flash[:notice] = 'You have already returned this bike.' + redirect_to rentals_path + end + end + + # checks if the station has bikes + def station_has_bikes + unless @station.docked_bikes.count > 0 + # redirects if the station has no bikes + flash[:notice] = 'This station has no bikes. Please choose another station.' + redirect_to map_home_index_path # flash message is hard to read bc map loads on top of it; TODO: may need to change this + end + end + + # checks if the user has provided their payment info + def ask_for_payment + @payment = Payment.find_by(user_id: current_user.id) + if @payment.nil? + # redirects if current user has no payment info + flash[:notice] = 'Please input your payment information.' + redirect_to new_user_payment_path(current_user.id) + end + end + + def current_time + @current_time = Time.now + end + + def user_access + @rental = Rental.find(params[:id]) + if @rental.borrower != current_user + flash[:notice] = "Cannot access rentals made by other users" + redirect_to rentals_path + end + end + + +end \ No newline at end of file diff --git a/app/controllers/stations_controller.rb b/app/controllers/stations_controller.rb index 88090af16..581a92844 100644 --- a/app/controllers/stations_controller.rb +++ b/app/controllers/stations_controller.rb @@ -5,3 +5,4 @@ def index end 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/home_helper.rb b/app/helpers/home_helper.rb new file mode 100644 index 000000000..23de56ac6 --- /dev/null +++ b/app/helpers/home_helper.rb @@ -0,0 +1,2 @@ +module HomeHelper +end diff --git a/app/helpers/map_helper.rb b/app/helpers/map_helper.rb new file mode 100644 index 000000000..65a956169 --- /dev/null +++ b/app/helpers/map_helper.rb @@ -0,0 +1,2 @@ +module MapHelper +end diff --git a/app/helpers/payments_helper.rb b/app/helpers/payments_helper.rb new file mode 100644 index 000000000..18d3f4ae6 --- /dev/null +++ b/app/helpers/payments_helper.rb @@ -0,0 +1,12 @@ +module PaymentsHelper + def display_alerts + html = <<-HTML +
+
+ #{flash[:alert]} +
+
+ HTML + html.html_safe if flash[:alert] + end +end diff --git a/app/helpers/rental_helper.rb b/app/helpers/rental_helper.rb new file mode 100644 index 000000000..cfdb52c5a --- /dev/null +++ b/app/helpers/rental_helper.rb @@ -0,0 +1,2 @@ +module RentalHelper +end diff --git a/app/models/bike.rb b/app/models/bike.rb index f3648e343..aa7341e4e 100644 --- a/app/models/bike.rb +++ b/app/models/bike.rb @@ -3,5 +3,7 @@ class Bike < ApplicationRecord validates_uniqueness_of :identifier belongs_to :current_station, class_name: :Station, foreign_key: :current_station_id, optional: true + + has_many :rentals, foreign_key: :bike_id end diff --git a/app/models/payment.rb b/app/models/payment.rb new file mode 100644 index 000000000..ac3b5db39 --- /dev/null +++ b/app/models/payment.rb @@ -0,0 +1,28 @@ +class Payment < ApplicationRecord + + validates :first_name, presence: true + validates :last_name, presence: true + validates :card_number, length: {minimum: 15, maximum: 16, message: "Invalid card number"}, numericality: {only_integer: true, message: "Invalid card number"} + validates :cvv, length: {is: 3, message: "Invalid CVV"}, numericality: {only_integer: true, message: "Invalid CVV"} + validates :exp_month, length: {minimum: 1, maximum: 2}, numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 12} + validates :exp_year, length: {is: 4}, numericality: { only_integer: true, greater_than_or_equal_to: Time.current.year} + validate :valid_expiry? + belongs_to :user, optional: true + + private + def valid_expiry? + if exp_year.nil? or exp_month.nil? + false + elsif exp_year == Time.current.year && exp_month.to_i >= Time.current.month + true + elsif exp_year > Time.current.year + true + else + errors.add(:base, "Invalid expiry date") + false + end + end + + + +end diff --git a/app/models/rental.rb b/app/models/rental.rb new file mode 100644 index 000000000..673c6288e --- /dev/null +++ b/app/models/rental.rb @@ -0,0 +1,16 @@ +class Rental < ApplicationRecord + + validates_uniqueness_of :return, scope: :borrower_id # prevents user from making multiple rentals at once + + belongs_to :borrower, class_name: :User, foreign_key: :borrower_id + belongs_to :bike, class_name: :Bike, foreign_key: :bike_id + belongs_to :checkout_station, class_name: :Station, foreign_key: :station_id + belongs_to :return_station, class_name: :Station, foreign_key: :return_station_id, optional: true + + def duration + unless self.return.blank? + (self.return - self.checkout).div(60) # Returns duration in minutes + end + end + +end diff --git a/app/models/station.rb b/app/models/station.rb index 64b9eaada..34e24d1ff 100644 --- a/app/models/station.rb +++ b/app/models/station.rb @@ -1,7 +1,11 @@ class Station < ApplicationRecord + geocoded_by :address + validates_presence_of :identifier, :name, :address + :latitude + :longitude validates_uniqueness_of :identifier has_many :docked_bikes, class_name: :Bike, foreign_key: :current_station_id diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 000000000..5a3617184 --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,14 @@ +class User < ApplicationRecord + + # Include default devise modules. Others available are: + # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable + devise :database_authenticatable, :registerable, + :recoverable, :rememberable, :validatable + + validates :phone_number, length: {is: 10}, numericality: {only_integer: true, message: "is not a number"} + + has_many :rentals, foreign_key: :borrower_id + + has_one :payment, dependent: :destroy + +end diff --git a/app/views/bikes/_row.html.erb b/app/views/bikes/_row.html.erb new file mode 100644 index 000000000..feff0c166 --- /dev/null +++ b/app/views/bikes/_row.html.erb @@ -0,0 +1,4 @@ +
flexbox horizontal justify-space-between"> +
<%= bike.identifier %>
+
<% bike.current_station.blank? ? "In Use" : "Docked (# {bike.current_station.address})" %>
+
diff --git a/app/views/devise/confirmations/new.html.erb b/app/views/devise/confirmations/new.html.erb new file mode 100644 index 000000000..b12dd0cbe --- /dev/null +++ b/app/views/devise/confirmations/new.html.erb @@ -0,0 +1,16 @@ +

Resend confirmation instructions

+ +<%= form_for(resource, as: resource_name, url: confirmation_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", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %> +
+ +
+ <%= f.submit "Resend confirmation instructions" %> +
+<% end %> + +<%= render "devise/shared/links" %> diff --git a/app/views/devise/mailer/confirmation_instructions.html.erb b/app/views/devise/mailer/confirmation_instructions.html.erb new file mode 100644 index 000000000..dc55f64f6 --- /dev/null +++ b/app/views/devise/mailer/confirmation_instructions.html.erb @@ -0,0 +1,5 @@ +

Welcome <%= @email %>!

+ +

You can confirm your account email through the link below:

+ +

<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>

diff --git a/app/views/devise/mailer/email_changed.html.erb b/app/views/devise/mailer/email_changed.html.erb new file mode 100644 index 000000000..32f4ba803 --- /dev/null +++ b/app/views/devise/mailer/email_changed.html.erb @@ -0,0 +1,7 @@ +

Hello <%= @email %>!

+ +<% if @resource.try(:unconfirmed_email?) %> +

We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.

+<% else %> +

We're contacting you to notify you that your email has been changed to <%= @resource.email %>.

+<% end %> diff --git a/app/views/devise/mailer/password_change.html.erb b/app/views/devise/mailer/password_change.html.erb new file mode 100644 index 000000000..b41daf476 --- /dev/null +++ b/app/views/devise/mailer/password_change.html.erb @@ -0,0 +1,3 @@ +

Hello <%= @resource.email %>!

+ +

We're contacting you to notify you that your password has been changed.

diff --git a/app/views/devise/mailer/reset_password_instructions.html.erb b/app/views/devise/mailer/reset_password_instructions.html.erb new file mode 100644 index 000000000..f667dc12f --- /dev/null +++ b/app/views/devise/mailer/reset_password_instructions.html.erb @@ -0,0 +1,8 @@ +

Hello <%= @resource.email %>!

+ +

Someone has requested a link to change your password. You can do this through the link below.

+ +

<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>

+ +

If you didn't request this, please ignore this email.

+

Your password won't change until you access the link above and create a new one.

diff --git a/app/views/devise/mailer/unlock_instructions.html.erb b/app/views/devise/mailer/unlock_instructions.html.erb new file mode 100644 index 000000000..41e148bf2 --- /dev/null +++ b/app/views/devise/mailer/unlock_instructions.html.erb @@ -0,0 +1,7 @@ +

Hello <%= @resource.email %>!

+ +

Your account has been locked due to an excessive number of unsuccessful sign in attempts.

+ +

Click the link below to unlock your account:

+ +

<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>

diff --git a/app/views/devise/passwords/edit.html.erb b/app/views/devise/passwords/edit.html.erb new file mode 100644 index 000000000..5fbb9ff0a --- /dev/null +++ b/app/views/devise/passwords/edit.html.erb @@ -0,0 +1,25 @@ +

Change your password

+ +<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %> + <%= render "devise/shared/error_messages", resource: resource %> + <%= f.hidden_field :reset_password_token %> + +
+ <%= f.label :password, "New password" %>
+ <% if @minimum_password_length %> + (<%= @minimum_password_length %> characters minimum)
+ <% end %> + <%= f.password_field :password, autofocus: true, autocomplete: "new-password" %> +
+ +
+ <%= f.label :password_confirmation, "Confirm new password" %>
+ <%= f.password_field :password_confirmation, autocomplete: "new-password" %> +
+ +
+ <%= f.submit "Change my password" %> +
+<% end %> + +<%= render "devise/shared/links" %> diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb new file mode 100644 index 000000000..9b486b81b --- /dev/null +++ b/app/views/devise/passwords/new.html.erb @@ -0,0 +1,16 @@ +

Forgot your password?

+ +<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %> + <%= render "devise/shared/error_messages", resource: resource %> + +
+ <%= f.label :email %>
+ <%= f.email_field :email, autofocus: true, autocomplete: "email" %> +
+ +
+ <%= f.submit "Send me reset password instructions" %> +
+<% end %> + +<%= render "devise/shared/links" %> diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb new file mode 100644 index 000000000..339bf0943 --- /dev/null +++ b/app/views/devise/registrations/edit.html.erb @@ -0,0 +1,84 @@ +
+
+ <%= image_tag('backg_2.png') %> +
+
+ + + + +
+
+
+
+
+
+
+
+
+

Edit <%= resource_name.to_s.humanize %> Profile

+
+ <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> + <%= render "devise/shared/error_messages", resource: resource %> + +
+ <%= f.label :first_name, class: "form-label" %>
+ <%= f.text_field :first_name %> +
+ +
+ <%= f.label :last_name, class: "form-label" %>
+ <%= f.text_field :last_name %> +
+ +
+ <%= f.label :phone_number, class: "form-label" %>
+ <%= f.telephone_field :phone_number %> +
+ +
+ <%= f.label :email, class: "form-label" %>
+ <%= f.email_field :email, autofocus: true, autocomplete: "email" %> +
+ + <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> +
Currently waiting confirmation for: <%= resource.unconfirmed_email %>
+ <% end %> + +
+ <%= f.label :current_password, class: "form-label" %>
+ <%= f.password_field :current_password, autocomplete: "current-password" %> +
+ +
+ <% if @minimum_password_length %> + <%= f.label :new_password, class: "form-label" %> (<%= @minimum_password_length %> characters minimum) + <% end %> +
+ <%= f.password_field :password, autocomplete: "new-password" %> +
+ +
+ <%= f.label :password_confirmation, class: "form-label" %>
+ <%= f.password_field :password_confirmation, autocomplete: "new-password" %> +
+ + +
+ <%= f.submit "Update", class: 'back-button'%> + <% end %> + +
+ <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete, class: 'back-button'%> +
+ + <%= link_to "Back", :back , class: 'back-button'%> + +
+ +
+
+
+ + + diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb new file mode 100644 index 000000000..a35315cf3 --- /dev/null +++ b/app/views/devise/registrations/new.html.erb @@ -0,0 +1,76 @@ + +
+
+ <%= image_tag('backg_2.png') %> +
+
+ + +
+
+
+
+
+
+
+
+
+

Register

+
+ <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> + + <%= render "devise/shared/error_messages", resource: resource %> +
+ <%= f.label :first_name, class: "form-label" %>
+ <%= f.text_field :first_name, placeholder: "Enter your first name" %> +
+ +
+ <%= f.label :last_name, class: "form-label" %>
+ <%= f.text_field :last_name, placeholder: "Enter your last name" %> +
+ +
+ <%= f.label :email, class: "form-label" %>
+ <%= f.email_field :email, autofocus: true, autocomplete: "email", placeholder: "Enter your email" %> +
+ +
+ <%= f.label :birthday, class: "form-label" %>
+ <%= f.date_field :birthday %> + +
+ +
+ <%= f.label :phone_number, class: "form-label" %>
+ <%= f.telephone_field :phone_number, placeholder: "Enter your phone number" %> +
+ +
+ <%= f.label :password, class: "form-label" %> + <% if @minimum_password_length %> + (<%= @minimum_password_length %> characters minimum) + <% end %>
+ <%= f.password_field :password, autocomplete: "new-password", placeholder: "Enter your password" %> +
+ +
+ <%= f.label :password_confirmation, class: "form-label" %>
+ <%= f.password_field :password_confirmation, autocomplete: "new-password", placeholder: "Confirm your password" %> +
+ +
+ <%= f.submit "Register" %> +
+ + <% end %> + <%= render "devise/shared/links" %> +
+
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb new file mode 100644 index 000000000..7578d5bfa --- /dev/null +++ b/app/views/devise/sessions/new.html.erb @@ -0,0 +1,39 @@ + +
+
+ <%= image_tag('backg_2.png') %> +
+
+ +
+
+
+
+
+
+
+
+

Sign in

+
+ <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> +
+ <%= f.label :email %>
+ <%= f.email_field :email, autofocus: true, autocomplete: "email", placeholder: "Enter your email" %> +
+
+ <%= f.label :password %>
+ <%= f.password_field :password, autocomplete: "current-password", placeholder: "Enter your password" %> +
+
+ <%= f.submit "Sign in" %> +
+ <% end %> + + <%= render "devise/shared/links" %> +
+
+
+
+
+
+
diff --git a/app/views/devise/shared/_error_messages.html.erb b/app/views/devise/shared/_error_messages.html.erb new file mode 100644 index 000000000..cabfe307e --- /dev/null +++ b/app/views/devise/shared/_error_messages.html.erb @@ -0,0 +1,15 @@ +<% 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 %> +
+
+<% end %> diff --git a/app/views/devise/shared/_links.html.erb b/app/views/devise/shared/_links.html.erb new file mode 100644 index 000000000..114488219 --- /dev/null +++ b/app/views/devise/shared/_links.html.erb @@ -0,0 +1,24 @@ + +<%- if controller_name != 'sessions' %> + + <%= link_to "Sign in", new_session_path(resource_name) %>
+
+<% end %> + +<%- if devise_mapping.registerable? && controller_name != 'registrations' %> + <%= link_to "Register", new_registration_path(resource_name) %>
+<% end %> + +<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> + <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>
+<% end %> + +<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %> + <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %>
+<% end %> + +<%- if devise_mapping.omniauthable? %> + <%- resource_class.omniauth_providers.each do |provider| %> + <%= button_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), data: { turbo: false } %>
+ <% end %> +<% end %> diff --git a/app/views/devise/unlocks/new.html.erb b/app/views/devise/unlocks/new.html.erb new file mode 100644 index 000000000..ffc34de8d --- /dev/null +++ b/app/views/devise/unlocks/new.html.erb @@ -0,0 +1,16 @@ +

Resend unlock instructions

+ +<%= form_for(resource, as: resource_name, url: unlock_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.submit "Resend unlock instructions" %> +
+<% end %> + +<%= render "devise/shared/links" %> diff --git a/app/views/home/_row.html.erb b/app/views/home/_row.html.erb new file mode 100644 index 000000000..77a69471a --- /dev/null +++ b/app/views/home/_row.html.erb @@ -0,0 +1,34 @@ +
flexbox vertical stretch"> +
    +
    + <%= station.name %>
    + Address: <%= station.address %> +
    + + <% if user_signed_in? && !current_user.rentals.where(return: nil).empty? %> +
  • +
    + <%= pluralize(station.docked_bikes.count, 'bike') %> +
    +
    + <%= link_to("Return a bike to this station", edit_rental_path(id: @active_rental, station_id: station), class: 'action edit', class: 'rent-button') %> +
    +
  • + <% elsif station.docked_bikes.count == 0 %> +
      + There are currently 0 bikes at this station. Check back later! +
    + <% else %> +
  • +
    + <%= pluralize(station.docked_bikes.count, 'bike') %> available +
    +
    + <%= link_to("Rent a bike at this station", new_station_rental_path(station), class: 'rent-button') %> +
    +
  • + <% end %> +
+ + +
diff --git a/app/views/home/explore.html.erb b/app/views/home/explore.html.erb new file mode 100644 index 000000000..77653a911 --- /dev/null +++ b/app/views/home/explore.html.erb @@ -0,0 +1,18 @@ +
+ +
+ <%= image_tag('Carol.png', width: '300px') %> +
+ +
+
+

yarnlover123

+
+

Wow this bike system is amazing for an old soul like me. Everything is so accessible and affordable! 10/10 would reccommend!

+
+ +
+

The explore feature was supposed to be a place where users could view and post posts about their favorite trails. Posts could include images, and users could search for different trails based on length, area of the valley, and more. Users could rate trails too, and ideally there would be some sort of filter or mod feature to make sure content was appropriate. We didn't get to coding this feature, but we thought we'd share anyway :)!

+
+ +
\ No newline at end of file diff --git a/app/views/home/help.html.erb b/app/views/home/help.html.erb new file mode 100644 index 000000000..e001e86cc --- /dev/null +++ b/app/views/home/help.html.erb @@ -0,0 +1,194 @@ + + + + + + + + + + + + +
+
+
+
+
+

Meet the ClemenTeam

+
+

Five dedicated computer science students, class of 2025, passionate about contributing to the progress and well-being of our city's population. Through hard work and innovation, we have created a bike renting website that provides an affordable and convenient solution for people in the valley to get around. Our commitment to sustainable transportation aims to make a positive impact on both the community and the environment.

+
+
+
+ +
+
+ <%= image_tag('team_1.png') %> +
+
+ +
+ +
+ + + + + + + diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb new file mode 100644 index 000000000..72d8aca20 --- /dev/null +++ b/app/views/home/index.html.erb @@ -0,0 +1,101 @@ + +
+ +
+
+
+
+

CiTrust us to get to your destination!

+
+

With stations across Amherst, Northampton, Hampshire, and Springfield, perform errands with ease or have fun exploring scenic bike routes!

+ <%= link_to('Start Now', map_home_index_path, class: 'button') %> +
+
+
+ +
+ <%= image_tag('Clemenbykes stock photo.png') %> +
+ +
+
+
+
+

How It Works

+
+
+
+
+

Step 1

+ <%= image_tag('get code.png')%> +

Get Code

+

After choosing a station and time, simply click "Rent Now" and a unique code will be generated for you!

+
+
+

Step 2

+ <%= image_tag('kiosk unlock.png')%> +

Unlock

+

Enter your code at our kiosks located at each station and a bike will unlock!

+
+
+

Step 3

+ <%= image_tag('ride bike.png')%> +

Ride

+

Have a sweet time riding!

+
+
+

Step 4

+ <%= image_tag('return bike.png')%> +

Return

+

At the closest station near you, return the bike and you are all set!

+
+
+
+
+
+
+ + +
+
+
+
+

Checkout Our Stations Around the Pioneer Valley!

+
+
+
+
+ + + +
+ + + + + + + +
diff --git a/app/views/home/map.html.erb b/app/views/home/map.html.erb new file mode 100644 index 000000000..c37234ceb --- /dev/null +++ b/app/views/home/map.html.erb @@ -0,0 +1,69 @@ + + +
+
+
+
+
+

Check Out Our Stations Around the Pioneer Valley!

+
+ <% if user_signed_in? && !current_user.rentals.where(return: nil).empty? %> +

Done riding? Select a station from the sidebar to return your bike!

+ <% else %> +

Ready to ride? View the station locations in the map below, and select a station from the sidebar to rent a bike!

+ <% end %> + <% if user_signed_in? %> + <%= link_to "Past Rentals", rentals_path, class: 'button' %> + <% end %> +
+
+ +
+ + + + + +
+ + + + + +
+ + + + + + + diff --git a/app/views/home/pricing.html.erb b/app/views/home/pricing.html.erb new file mode 100644 index 000000000..99ed52d37 --- /dev/null +++ b/app/views/home/pricing.html.erb @@ -0,0 +1,40 @@ +
+
+ <%= image_tag('bicicleta_2.gif') %> +
+
+ +
+
+
+
+ +
+ Our Sweet Pricing Option! +
+ +
+
+
+

Unlike other expensive bike services we want our rides to be affordable. So, ride as long as you like, cause it will only cost you

+ +

$0.05/minute

+ +
+ <%= image_tag('naranja.gif') %> +
+ +
+ <%= image_tag('naranja.gif') %> +
+

Are you ready to ride? Click the button below to start!

+ <%= link_to('Start Now', map_home_index_path, class: 'button') %> +
+
+ +
+
+
+
+
+ diff --git a/app/views/home/profile.html.erb b/app/views/home/profile.html.erb new file mode 100644 index 000000000..2ae021802 --- /dev/null +++ b/app/views/home/profile.html.erb @@ -0,0 +1,37 @@ + +
+
+ <%= image_tag('backg_2.png') %> +
+
+ +
+
+
+
+
+
+
+
+
+ <%= image_tag('user_profile.png') %> +
+

<%= current_user.first_name%> <%= current_user.last_name%>

+
+
+
+ <% if user_signed_in? %> + <%= link_to "Edit My Info", edit_user_registration_path, class: 'profile-button' %> + <%= link_to "Edit Payment", new_user_payment_path(current_user), class: 'profile-button' %> + <%= link_to "My Rentals", rentals_path, class: 'profile-button' %> + <% unless current_user.rentals.where(return: nil).empty? %> + <%= link_to "Current rental", rental_path(@active_rental.id), class: 'profile-button' %> + <% end %> + <% end %> +
+
+
+
+
+
+
\ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 7ace1393e..317189699 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -10,13 +10,75 @@ <%= javascript_importmap_tags %> - ValetBike + + + + + + + + Clemenbykes - -
-
- <%= yield %> -
-
- + + + + +
+ <%= link_to(image_tag('clemenbykes_logo_light.png', alt: 'logo', class: 'logo', width: '225px'),home_index_path) %> + +
+ +
+
+
+ <% if notice %>

<%= notice %>

<% end %> + <% if alert %>

<%= alert %>

<% end %> + <%= yield %> +
+
+
+ +
+
    +
  • Copyright © <%= Time.now.year %>
  • +
+
+ + diff --git a/app/views/payments/_form.html.erb b/app/views/payments/_form.html.erb new file mode 100644 index 000000000..361042654 --- /dev/null +++ b/app/views/payments/_form.html.erb @@ -0,0 +1,61 @@ + +
+
+
+
+
+
+
+
+ +
+

Payment Info

+
+ + <%= form_for [@user, @payment] do |form| %> +
+ <%= form.label :first_name %>
+ <%= form.text_field :first_name, placeholder: "Enter Your First Name" %> +
+
+ <%= form.label :last_name %>
+ <%= form.text_field :last_name, placeholder: "Enter Your Last Name"%> +
+
+ <%= form.label :cvv %>
+ <%= form.number_field :cvv , placeholder: "Enter Your 3 digit cvv" %> +
+
+ <%= form.label :card_number %>
+ <%= form.text_field :card_number, placeholder: "Enter your 16 digit card number" %> +
+ +
+ <%= form.label :exp_month%>
+ <%= form.number_field :exp_month , placeholder: "(MM)" %> +
+
+ <%= form.label :exp_year%>
+ <%= form.number_field :exp_year, placeholder: "(YYYY)" %> +
+ +
+ <% if @payment.errors.any? %> +
    + <% @payment.errors.full_messages.each do |msg| %> +
  • <%= msg%>
  • + <% end %> +
+ <% end %> +
+
+ <%= form.submit%> +
+
+ <% end %> + + +
+
+
+
diff --git a/app/views/payments/edit.html.erb b/app/views/payments/edit.html.erb new file mode 100644 index 000000000..77ce6177d --- /dev/null +++ b/app/views/payments/edit.html.erb @@ -0,0 +1,13 @@ +
+
+ <%= image_tag('backg_2.png') %> +
+
+ + +
+ + <%= render 'form' %> + +
+ \ No newline at end of file diff --git a/app/views/payments/index.html.erb b/app/views/payments/index.html.erb new file mode 100644 index 000000000..e69de29bb diff --git a/app/views/payments/new.html.erb b/app/views/payments/new.html.erb new file mode 100644 index 000000000..35092536c --- /dev/null +++ b/app/views/payments/new.html.erb @@ -0,0 +1,9 @@ +
+
+ <%= image_tag('backg_2.png') %> +
+
+ +
+ <%= render 'form' %> +
\ No newline at end of file diff --git a/app/views/payments/show.html.erb b/app/views/payments/show.html.erb new file mode 100644 index 000000000..fd6dbf142 --- /dev/null +++ b/app/views/payments/show.html.erb @@ -0,0 +1,9 @@ +
+

Payment#show

+

Find me in app/views/payments/show.html.erb. gorl jepls

+ +
+

<%= current_user.email %>

+ +
+
diff --git a/app/views/rentals/_row.html.erb b/app/views/rentals/_row.html.erb new file mode 100644 index 000000000..28a848fb7 --- /dev/null +++ b/app/views/rentals/_row.html.erb @@ -0,0 +1,41 @@ + +
+
+
Starting Station Name:
<%= @rental.checkout_station.name %> +
+ +
+ <%if @rental.return != nil %> +
Ending Station Name:
<%= @rental.return_station.name %> + <%end%> +
+ +
+
Bike id:
<%= @rental.bike_id %> +
+ +
+
Start Time:
<%= (@rental.checkout).strftime("%A %m/%d/%Y %I:%M %p")%> +
+ + <%if @rental.return != nil %> +
+
End time:
<%= (@rental.return).strftime("%A %m/%d/%Y %I:%M %p")%> +
+ +
+
Rental Duration:
<%= @rental.duration %> minutes +
+ +
+
Ride Cost:
$<%= number_with_precision(@rental.cost, precision: 2) %> +
+ + <% else %> + +
+ <%= link_to("Return Bike", edit_rental_path(id: @rental, station_id: @rental.checkout_station.id), class: 'action edit') %> +
+ + <%end%> +
\ No newline at end of file diff --git a/app/views/rentals/_table_header.html.erb b/app/views/rentals/_table_header.html.erb new file mode 100644 index 000000000..77adf49c7 --- /dev/null +++ b/app/views/rentals/_table_header.html.erb @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + +
Rented fromReturned toBike IDRental codeCheckout timeReturn timeCost of rental
\ No newline at end of file diff --git a/app/views/rentals/edit.html.erb b/app/views/rentals/edit.html.erb new file mode 100644 index 000000000..54eee39ae --- /dev/null +++ b/app/views/rentals/edit.html.erb @@ -0,0 +1,31 @@ +
+
+
+
+
+

Ready to Return?

+ +
+ +

Select the station you are returning the bike to.

+
+

Return bike to:

+ + <%= form_for @rental, method: :patch do |form| %> + + <%= form.select :return_station_id, Station.all.collect {|p| [ p.name, p.id ]}, include_blank: true %> + +
+ <%= form.submit "Return now" %> +
+ + <% end %> +
+
+
+
+ <%= image_tag('orange full.png') %> +
+
+
+
\ No newline at end of file diff --git a/app/views/rentals/index.html.erb b/app/views/rentals/index.html.erb new file mode 100644 index 000000000..e1c300fe9 --- /dev/null +++ b/app/views/rentals/index.html.erb @@ -0,0 +1,67 @@ + + + + + + + +
+
+
+
+
+

Your Rental History

+
+
+
+ + + + + + + + + + + + <% @rentals.each do |rental| %> + + + + <%if rental.return != nil %> + + + + + + + + <% end %> + + <% end %> +
Rented fromReturned toBike IDCheckout timeReturn timeDurationCost of rental
<%= rental.checkout_station.name %><%= rental.return_station.name %><%= rental.bike_id %><%= (rental.checkout).strftime("%A %m/%d/%Y %I:%M %p")%><%= (rental.return).strftime("%A %m/%d/%Y %I:%M %p")%><%= pluralize(rental.duration, 'minute')%>$<%= number_with_precision(rental.cost, precision: 2) %>
+
+
+
+ + \ No newline at end of file diff --git a/app/views/rentals/new.html.erb b/app/views/rentals/new.html.erb new file mode 100644 index 000000000..99d5f51cc --- /dev/null +++ b/app/views/rentals/new.html.erb @@ -0,0 +1,42 @@ +
+ +
+
+
+
+

Confirm Your Bike Rental

+
+

Selected Station: <%=@station.name%>

+

Station Address: <%=@station.address%>

+
+
+
+ + + + +
+ <%= image_tag('unlock bike 2.png') %> +
+ + +
+
+
+
+

Ready to Ride? Click the button below to get your code!

+
+ <%= form_for (@rental), url: {action: "create"}, html: {class: "nifty_form"} do |form| %> +
+ <%= form.submit "Rent now!" %> +
+ <% end %> +
+
+
+
+ +
+ + + diff --git a/app/views/rentals/show.html.erb b/app/views/rentals/show.html.erb new file mode 100644 index 000000000..9e797e915 --- /dev/null +++ b/app/views/rentals/show.html.erb @@ -0,0 +1,45 @@ +
+
+ <%= image_tag('backg_2.png') %> +
+
+ +
+
+
+
+ <% if @rental.return == nil %> +
+
+

It's Clementime to ride! This is your access Code:

+

<%= @rental.number %>

+
+
+
+
+

*Go to the station you requested a bike from and enter this code at the kiosk*

+
+
+
+
+

Below are the details of your rental, please click return bike when you have completed your ride!

+
+
+ <% else %> +
+

Hope you had a fruitful ride!
Here are the full details of your rental

+ + <% end %> +
+ <%= render(partial: "rentals/row", object: @rental) %> +
+ <%= link_to("Show all rentals", rentals_path) %> +
+ +
+
+ + + +
+
\ No newline at end of file diff --git a/app/views/stations/_row.html.erb b/app/views/stations/_row.html.erb deleted file mode 100644 index 68a74d983..000000000 --- a/app/views/stations/_row.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -
flexbox vertical stretch"> - <%= station.identifier %>: <%= station.name %> (<%= station.address %>) -
\ No newline at end of file diff --git a/app/views/stations/index.html.erb b/app/views/stations/index.html.erb deleted file mode 100644 index d211dda42..000000000 --- a/app/views/stations/index.html.erb +++ /dev/null @@ -1,16 +0,0 @@ -
-
-
- Welcome to ValetBike! -
-
- <% if @stations.present? %> - <%= render(partial: "stations/row", collection: @stations, as: :station) %> - <% else %> -
- No stations found. -
- <% end %> -
-
-
diff --git a/config/application.rb b/config/application.rb index e2d9f859d..d7aece7ab 100644 --- a/config/application.rb +++ b/config/application.rb @@ -16,7 +16,8 @@ class Application < Rails::Application # These settings can be overridden in specific environments using the files # in config/environments, which are processed later. # - # config.time_zone = "Central Time (US & Canada)" + config.time_zone = "Eastern Time (US & Canada)" + # config.eager_load_paths << Rails.root.join("extras") end end diff --git a/config/database.yml b/config/database.yml index c000a031b..0720d67aa 100644 --- a/config/database.yml +++ b/config/database.yml @@ -15,7 +15,8 @@ default: &default pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: <%= ENV['MYSQL_USERNAME'] || 'root' %> password: <%= ENV['MYSQL_PASSWORD'] || '' %> - socket: <%= ENV['MYSQL_SOCKET'] || '/tmp/mysql.sock' %> + socket: <%= ENV['MYSQL_SOCKET'] || '/var/run/mysqld/mysqld.sock' %> + timezone: 'Eastern Time (US & Canada)' development: <<: *default diff --git a/config/environments/development.rb b/config/environments/development.rb index 8500f459a..369fc1fc9 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -59,6 +59,13 @@ # Suppress logger output for asset requests. config.assets.quiet = true + # For the Devise mailer: Required default URL options + config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } + + # TODO for the Devise mailer: Turn on when testing mail in development + # config.action_mailer.perform_deliveries = true + # config.action_mailer.delivery_method = :smtp + # Raises error for missing translations. # config.i18n.raise_on_missing_translations = true diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb new file mode 100644 index 000000000..686907112 --- /dev/null +++ b/config/initializers/devise.rb @@ -0,0 +1,313 @@ +# frozen_string_literal: true + +# Assuming you have not yet modified this file, each configuration option below +# is set to its default value. Note that some are commented out while others +# are not: uncommented lines are intended to protect your configuration from +# breaking changes in upgrades (i.e., in the event that future versions of +# Devise change the default values for those options). +# +# Use this hook to configure devise mailer, warden hooks and so forth. +# Many of these configuration options can be set straight in your model. +Devise.setup do |config| + # The secret key used by Devise. Devise uses this key to generate + # random tokens. Changing this key will render invalid all existing + # confirmation, reset password and unlock tokens in the database. + # Devise will use the `secret_key_base` as its `secret_key` + # by default. You can change it below and use your own secret key. + # config.secret_key = 'cf880084ae309cda3a7b034f438ca3cf7b1a0a4353ee6ea2a9387144c505c4f28983b3e1f4c90a8f681bc3e9464f03b5d1fefcab4e6c1daa43a124e390b09c4c' + + # ==> Controller configuration + # Configure the parent class to the devise controllers. + # config.parent_controller = 'DeviseController' + + # ==> Mailer Configuration + # Configure the e-mail address which will be shown in Devise::Mailer, + # note that it will be overwritten if you use your own mailer class + # with default "from" parameter. + config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com' + + # Configure the class responsible to send e-mails. + # config.mailer = 'Devise::Mailer' + + # Configure the parent class responsible to send e-mails. + # config.parent_mailer = 'ActionMailer::Base' + + # ==> ORM configuration + # Load and configure the ORM. Supports :active_record (default) and + # :mongoid (bson_ext recommended) by default. Other ORMs may be + # available as additional gems. + require 'devise/orm/active_record' + + # ==> Configuration for any authentication mechanism + # Configure which keys are used when authenticating a user. The default is + # just :email. You can configure it to use [:username, :subdomain], so for + # authenticating a user, both parameters are required. Remember that those + # parameters are used only when authenticating and not when retrieving from + # session. If you need permissions, you should implement that in a before filter. + # You can also supply a hash where the value is a boolean determining whether + # or not authentication should be aborted when the value is not present. + # config.authentication_keys = [:email] + + # Configure parameters from the request object used for authentication. Each entry + # given should be a request method and it will automatically be passed to the + # find_for_authentication method and considered in your model lookup. For instance, + # if you set :request_keys to [:subdomain], :subdomain will be used on authentication. + # The same considerations mentioned for authentication_keys also apply to request_keys. + # config.request_keys = [] + + # Configure which authentication keys should be case-insensitive. + # These keys will be downcased upon creating or modifying a user and when used + # to authenticate or find a user. Default is :email. + config.case_insensitive_keys = [:email] + + # Configure which authentication keys should have whitespace stripped. + # These keys will have whitespace before and after removed upon creating or + # modifying a user and when used to authenticate or find a user. Default is :email. + config.strip_whitespace_keys = [:email] + + # Tell if authentication through request.params is enabled. True by default. + # It can be set to an array that will enable params authentication only for the + # given strategies, for example, `config.params_authenticatable = [:database]` will + # enable it only for database (email + password) authentication. + # config.params_authenticatable = true + + # Tell if authentication through HTTP Auth is enabled. False by default. + # It can be set to an array that will enable http authentication only for the + # given strategies, for example, `config.http_authenticatable = [:database]` will + # enable it only for database authentication. + # For API-only applications to support authentication "out-of-the-box", you will likely want to + # enable this with :database unless you are using a custom strategy. + # The supported strategies are: + # :database = Support basic authentication with authentication key + password + # config.http_authenticatable = false + + # If 401 status code should be returned for AJAX requests. True by default. + # config.http_authenticatable_on_xhr = true + + # The realm used in Http Basic Authentication. 'Application' by default. + # config.http_authentication_realm = 'Application' + + # It will change confirmation, password recovery and other workflows + # to behave the same regardless if the e-mail provided was right or wrong. + # Does not affect registerable. + # config.paranoid = true + + # By default Devise will store the user in session. You can skip storage for + # particular strategies by setting this option. + # Notice that if you are skipping storage for all authentication paths, you + # may want to disable generating routes to Devise's sessions controller by + # passing skip: :sessions to `devise_for` in your config/routes.rb + config.skip_session_storage = [:http_auth] + + # By default, Devise cleans up the CSRF token on authentication to + # avoid CSRF token fixation attacks. This means that, when using AJAX + # requests for sign in and sign up, you need to get a new CSRF token + # from the server. You can disable this option at your own risk. + # config.clean_up_csrf_token_on_authentication = true + + # When false, Devise will not attempt to reload routes on eager load. + # This can reduce the time taken to boot the app but if your application + # requires the Devise mappings to be loaded during boot time the application + # won't boot properly. + # config.reload_routes = true + + # ==> Configuration for :database_authenticatable + # For bcrypt, this is the cost for hashing the password and defaults to 12. If + # using other algorithms, it sets how many times you want the password to be hashed. + # The number of stretches used for generating the hashed password are stored + # with the hashed password. This allows you to change the stretches without + # invalidating existing passwords. + # + # Limiting the stretches to just one in testing will increase the performance of + # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use + # a value less than 10 in other environments. Note that, for bcrypt (the default + # algorithm), the cost increases exponentially with the number of stretches (e.g. + # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation). + config.stretches = Rails.env.test? ? 1 : 12 + + # Set up a pepper to generate the hashed password. + # config.pepper = '09274642160706875afea5aa1c351b18094ef6abeb1caeee584d92ba7a1da84ba591a75a8409972566fd121c5c7d10340954384f12cb7ef642029e1a3729f41b' + + # Send a notification to the original email when the user's email is changed. + # config.send_email_changed_notification = false + + # Send a notification email when the user's password is changed. + # config.send_password_change_notification = false + + # ==> Configuration for :confirmable + # A period that the user is allowed to access the website even without + # confirming their account. For instance, if set to 2.days, the user will be + # able to access the website for two days without confirming their account, + # access will be blocked just in the third day. + # You can also set it to nil, which will allow the user to access the website + # without confirming their account. + # Default is 0.days, meaning the user cannot access the website without + # confirming their account. + # config.allow_unconfirmed_access_for = 2.days + + # A period that the user is allowed to confirm their account before their + # token becomes invalid. For example, if set to 3.days, the user can confirm + # their account within 3 days after the mail was sent, but on the fourth day + # their account can't be confirmed with the token any more. + # Default is nil, meaning there is no restriction on how long a user can take + # before confirming their account. + # config.confirm_within = 3.days + + # If true, requires any email changes to be confirmed (exactly the same way as + # initial account confirmation) to be applied. Requires additional unconfirmed_email + # db field (see migrations). Until confirmed, new email is stored in + # unconfirmed_email column, and copied to email column on successful confirmation. + config.reconfirmable = true + + # Defines which key will be used when confirming an account + # config.confirmation_keys = [:email] + + # ==> Configuration for :rememberable + # The time the user will be remembered without asking for credentials again. + # config.remember_for = 2.weeks + + # Invalidates all the remember me tokens when the user signs out. + config.expire_all_remember_me_on_sign_out = true + + # If true, extends the user's remember period when remembered via cookie. + # config.extend_remember_period = false + + # Options to be passed to the created cookie. For instance, you can set + # secure: true in order to force SSL only cookies. + # config.rememberable_options = {} + + # ==> Configuration for :validatable + # Range for password length. + config.password_length = 6..128 + + # Email regex used to validate email formats. It simply asserts that + # one (and only one) @ exists in the given string. This is mainly + # to give user feedback and not to assert the e-mail validity. + config.email_regexp = /\A[^@\s]+@[^@\s]+\z/ + + # ==> Configuration for :timeoutable + # The time you want to timeout the user session without activity. After this + # time the user will be asked for credentials again. Default is 30 minutes. + # config.timeout_in = 30.minutes + + # ==> Configuration for :lockable + # Defines which strategy will be used to lock an account. + # :failed_attempts = Locks an account after a number of failed attempts to sign in. + # :none = No lock strategy. You should handle locking by yourself. + # config.lock_strategy = :failed_attempts + + # Defines which key will be used when locking and unlocking an account + # config.unlock_keys = [:email] + + # Defines which strategy will be used to unlock an account. + # :email = Sends an unlock link to the user email + # :time = Re-enables login after a certain amount of time (see :unlock_in below) + # :both = Enables both strategies + # :none = No unlock strategy. You should handle unlocking by yourself. + # config.unlock_strategy = :both + + # Number of authentication tries before locking an account if lock_strategy + # is failed attempts. + # config.maximum_attempts = 20 + + # Time interval to unlock the account if :time is enabled as unlock_strategy. + # config.unlock_in = 1.hour + + # Warn on the last attempt before the account is locked. + # config.last_attempt_warning = true + + # ==> Configuration for :recoverable + # + # Defines which key will be used when recovering the password for an account + # config.reset_password_keys = [:email] + + # Time interval you can reset your password with a reset password key. + # Don't put a too small interval or your users won't have the time to + # change their passwords. + config.reset_password_within = 6.hours + + # When set to false, does not sign a user in automatically after their password is + # reset. Defaults to true, so a user is signed in automatically after a reset. + # config.sign_in_after_reset_password = true + + # ==> Configuration for :encryptable + # Allow you to use another hashing or encryption algorithm besides bcrypt (default). + # You can use :sha1, :sha512 or algorithms from others authentication tools as + # :clearance_sha1, :authlogic_sha512 (then you should set stretches above to 20 + # for default behavior) and :restful_authentication_sha1 (then you should set + # stretches to 10, and copy REST_AUTH_SITE_KEY to pepper). + # + # Require the `devise-encryptable` gem when using anything other than bcrypt + # config.encryptor = :sha512 + + # ==> Scopes configuration + # Turn scoped views on. Before rendering "sessions/new", it will first check for + # "users/sessions/new". It's turned off by default because it's slower if you + # are using only default views. + # config.scoped_views = false + + # Configure the default scope given to Warden. By default it's the first + # devise role declared in your routes (usually :user). + # config.default_scope = :user + + # Set this configuration to false if you want /users/sign_out to sign out + # only the current scope. By default, Devise signs out all scopes. + # config.sign_out_all_scopes = true + + # ==> Navigation configuration + # Lists the formats that should be treated as navigational. Formats like + # :html should redirect to the sign in page when the user does not have + # access, but formats like :xml or :json, should return 401. + # + # If you have any extra navigational formats, like :iphone or :mobile, you + # should add them to the navigational formats lists. + # + # The "*/*" below is required to match Internet Explorer requests. + config.navigational_formats = ['*/*', :html, :turbo_stream] + + # The default HTTP method used to sign out a resource. Default is :delete. + config.sign_out_via = :delete + + # ==> OmniAuth + # Add a new OmniAuth provider. Check the wiki for more information on setting + # up on your models and hooks. + # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo' + + # ==> Warden configuration + # If you want to use other strategies, that are not supported by Devise, or + # change the failure app, you can configure them inside the config.warden block. + # + # config.warden do |manager| + # manager.intercept_401 = false + # manager.default_strategies(scope: :user).unshift :some_external_strategy + # end + + # ==> Mountable engine configurations + # When using Devise inside an engine, let's call it `MyEngine`, and this engine + # is mountable, there are some extra configurations to be taken into account. + # The following options are available, assuming the engine is mounted as: + # + # mount MyEngine, at: '/my_engine' + # + # The router that invoked `devise_for`, in the example above, would be: + # config.router_name = :my_engine + # + # When using OmniAuth, Devise cannot automatically set OmniAuth path, + # so you need to do it manually. For the users scope, it would be: + # config.omniauth_path_prefix = '/my_engine/users/auth' + + # ==> Hotwire/Turbo configuration + # When using Devise with Hotwire/Turbo, the http status for error responses + # and some redirects must match the following. The default in Devise for existing + # apps is `200 OK` and `302 Found` respectively, but new apps are generated with + # these new defaults that match Hotwire/Turbo behavior. + # Note: These might become the new default in future versions of Devise. + config.responder.error_status = :unprocessable_entity + config.responder.redirect_status = :see_other + + # ==> Configuration for :registerable + + # When set to false, does not sign a user in automatically after their password is + # changed. Defaults to true, so a user is signed in automatically after changing a password. + # config.sign_in_after_change_password = true +end diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml new file mode 100644 index 000000000..260e1c4ba --- /dev/null +++ b/config/locales/devise.en.yml @@ -0,0 +1,65 @@ +# Additional translations at https://github.com/heartcombo/devise/wiki/I18n + +en: + devise: + confirmations: + confirmed: "Your email address has been successfully confirmed." + send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes." + send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes." + failure: + already_authenticated: "You are already signed in." + inactive: "Your account is not activated yet." + invalid: "Invalid %{authentication_keys} or password." + locked: "Your account is locked." + last_attempt: "You have one more attempt before your account is locked." + not_found_in_database: "Invalid %{authentication_keys} or password." + timeout: "Your session expired. Please sign in again to continue." + unauthenticated: "You need to sign in or sign up before continuing." + unconfirmed: "You have to confirm your email address before continuing." + mailer: + confirmation_instructions: + subject: "Confirmation instructions" + reset_password_instructions: + subject: "Reset password instructions" + unlock_instructions: + subject: "Unlock instructions" + email_changed: + subject: "Email Changed" + password_change: + subject: "Password Changed" + omniauth_callbacks: + failure: "Could not authenticate you from %{kind} because \"%{reason}\"." + success: "Successfully authenticated from %{kind} account." + passwords: + no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided." + send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes." + send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes." + updated: "Your password has been changed successfully. You are now signed in." + updated_not_active: "Your password has been changed successfully." + registrations: + destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon." + signed_up: "Welcome! You have signed up successfully." + signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated." + signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked." + signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account." + update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirmation link to confirm your new email address." + updated: "Your account has been updated successfully." + updated_but_not_signed_in: "Your account has been updated successfully, but since your password was changed, you need to sign in again." + sessions: + signed_in: "Signed in successfully." + signed_out: "Signed out successfully." + already_signed_out: "Signed out successfully." + unlocks: + send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes." + send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes." + unlocked: "Your account has been unlocked successfully. Please sign in to continue." + errors: + messages: + already_confirmed: "was already confirmed, please try signing in" + confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one" + expired: "has expired, please request a new one" + not_found: "not found" + not_locked: "was not locked" + not_saved: + one: "1 error prohibited this %{resource} from being saved:" + other: "%{count} errors prohibited this %{resource} from being saved:" diff --git a/config/routes.rb b/config/routes.rb index f1eb0a0d8..bd7534f68 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,44 @@ Rails.application.routes.draw do - root to: "stations#index" -end \ No newline at end of file + + resources :rentals + resources :stations do + resources :rentals, only: [:new, :create] + end + + resources :home do + collection do + get 'pricing' + get 'explore' + get 'map' + get 'help' + get 'profile' + end + end + + devise_for :users + + resources :users do + resources :payments + end + + root to: "home#index" + + + # match 'map', to: "home#map", via: :get + + # #Adding route for the pricing page + # match 'pricing', to: "home#pricing", via: :get + + # #Adding route for the help page + # match 'help', to: "home#help", via: :get + + # #Adding route for the explore page + # match 'explore', to: "home#explore", via: :get + + + # get 'home/index' + # get 'home/pricing' + # get 'home/explore' + # get 'home/map' + +end diff --git a/db/migrate/20231104193553_create_rentals.rb b/db/migrate/20231104193553_create_rentals.rb new file mode 100644 index 000000000..e253b17b1 --- /dev/null +++ b/db/migrate/20231104193553_create_rentals.rb @@ -0,0 +1,13 @@ +class CreateRentals < ActiveRecord::Migration[7.0] + def change + create_table :rentals do |t| + t.integer :borrower_id + t.integer :bike_id + t.integer :station_id + t.datetime :checkout + t.datetime :return + + t.timestamps + end + end +end diff --git a/db/migrate/20231105052828_add_lat_long_to_station.rb b/db/migrate/20231105052828_add_lat_long_to_station.rb new file mode 100644 index 000000000..9b2e4225b --- /dev/null +++ b/db/migrate/20231105052828_add_lat_long_to_station.rb @@ -0,0 +1,6 @@ +class AddLatLongToStation < ActiveRecord::Migration[7.0] + def change + add_column :stations, :latitude, :float + add_column :stations, :longitude, :float + end +end diff --git a/db/migrate/20231106014939_devise_create_users.rb b/db/migrate/20231106014939_devise_create_users.rb new file mode 100644 index 000000000..43927dbd1 --- /dev/null +++ b/db/migrate/20231106014939_devise_create_users.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +class DeviseCreateUsers < ActiveRecord::Migration[7.0] + def change + create_table :users do |t| + ## Database authenticatable + t.string :email, null: false, default: "" + t.string :encrypted_password, null: false, default: "" + + ## Recoverable + t.string :reset_password_token + t.datetime :reset_password_sent_at + + ## Rememberable + t.datetime :remember_created_at + + ## Trackable + # t.integer :sign_in_count, default: 0, null: false + # t.datetime :current_sign_in_at + # t.datetime :last_sign_in_at + # t.string :current_sign_in_ip + # t.string :last_sign_in_ip + + ## Confirmable + # t.string :confirmation_token + # t.datetime :confirmed_at + # t.datetime :confirmation_sent_at + # t.string :unconfirmed_email # Only if using reconfirmable + + ## Lockable + # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts + # t.string :unlock_token # Only if unlock strategy is :email or :both + # t.datetime :locked_at + + + t.timestamps null: false + end + + add_index :users, :email, unique: true + add_index :users, :reset_password_token, unique: true + # add_index :users, :confirmation_token, unique: true + # add_index :users, :unlock_token, unique: true + end +end diff --git a/db/migrate/20231113162708_add_number_to_rentals.rb b/db/migrate/20231113162708_add_number_to_rentals.rb new file mode 100644 index 000000000..893abebe1 --- /dev/null +++ b/db/migrate/20231113162708_add_number_to_rentals.rb @@ -0,0 +1,5 @@ +class AddNumberToRentals < ActiveRecord::Migration[7.0] + def change + add_column :rentals, :number, :string + end +end diff --git a/db/migrate/20231120055703_create_payments.rb b/db/migrate/20231120055703_create_payments.rb new file mode 100644 index 000000000..fd22aa3cb --- /dev/null +++ b/db/migrate/20231120055703_create_payments.rb @@ -0,0 +1,15 @@ +class CreatePayments < ActiveRecord::Migration[7.0] + def change + create_table :payments do |t| + t.string :first_name + t.string :last_name + t.string :card_number + t.integer :cvv + t.integer :exp_month + t.integer :exp_year + t.references :user, null: false, foreign_key: true, on_delete: :cascade + + t.timestamps + end + end +end diff --git a/db/migrate/20231205192829_add_data_to_users.rb b/db/migrate/20231205192829_add_data_to_users.rb new file mode 100644 index 000000000..01bef27ca --- /dev/null +++ b/db/migrate/20231205192829_add_data_to_users.rb @@ -0,0 +1,8 @@ +class AddDataToUsers < ActiveRecord::Migration[7.0] + def change + add_column :users, :first_name, :string + add_column :users, :last_name, :string + add_column :users, :birthday, :date + add_column :users, :phone_number, :bigint + end +end diff --git a/db/migrate/20231210215551_add_cost_to_rentals.rb b/db/migrate/20231210215551_add_cost_to_rentals.rb new file mode 100644 index 000000000..7d1748720 --- /dev/null +++ b/db/migrate/20231210215551_add_cost_to_rentals.rb @@ -0,0 +1,5 @@ +class AddCostToRentals < ActiveRecord::Migration[7.0] + def change + add_column :rentals, :cost, :float + end +end diff --git a/db/migrate/20231210230333_add_return_station_id_to_rentals.rb b/db/migrate/20231210230333_add_return_station_id_to_rentals.rb new file mode 100644 index 000000000..1ebd9e631 --- /dev/null +++ b/db/migrate/20231210230333_add_return_station_id_to_rentals.rb @@ -0,0 +1,5 @@ +class AddReturnStationIdToRentals < ActiveRecord::Migration[7.0] + def change + add_column :rentals, :return_station_id, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index b98268f0e..53e661ff3 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # 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: 2023_12_10_230333) do create_table "bikes", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.integer "identifier" t.integer "current_station_id" @@ -18,12 +18,57 @@ t.datetime "updated_at", null: false end + create_table "payments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.string "first_name" + t.string "last_name" + t.string "card_number" + t.integer "cvv" + t.integer "exp_month" + t.integer "exp_year" + t.bigint "user_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["user_id"], name: "index_payments_on_user_id" + end + + create_table "rentals", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.integer "borrower_id" + t.integer "bike_id" + t.integer "station_id" + t.datetime "checkout" + t.datetime "return" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "number" + t.float "cost" + t.integer "return_station_id" + end + create_table "stations", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.integer "identifier" t.string "name" t.string "address" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.float "latitude" + t.float "longitude" + end + + create_table "users", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.string "email", default: "", null: false + t.string "encrypted_password", default: "", null: false + t.string "reset_password_token" + t.datetime "reset_password_sent_at" + t.datetime "remember_created_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "first_name" + t.string "last_name" + t.date "birthday" + t.bigint "phone_number" + t.index ["email"], name: "index_users_on_email", unique: true + t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true end + add_foreign_key "payments", "users" end diff --git a/db/seeds.rb b/db/seeds.rb index bc25fce30..6b1a0c8cf 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -5,3 +5,19 @@ # # movies = Movie.create([{ name: "Star Wars" }, { name: "Lord of the Rings" }]) # Character.create(name: "Luke", movie: movies.first) + +#adds latitude and longitude attributes to station active records (will be helpful when constructing map) +Station.find_by(identifier: "21").update(latitude:42.326020, longitude:-72.633760) +Station.find_by(identifier: "24").update(latitude:42.335860, longitude:-72.673750) +Station.find_by(identifier: "30").update(latitude:42.334600, longitude:-72.645400) +Station.find_by(identifier: "25").update(latitude:42.330109, longitude:-72.652748) +Station.find_by(identifier: "29").update(latitude:42.335820, longitude:-72.667710) +Station.find_by(identifier: "33").update(latitude:42.323889, longitude:-72.652456) +Station.find_by(identifier: "20").update(latitude:42.312646, longitude:-72.647501) +Station.find_by(identifier: "26").update(latitude:42.318106, longitude:-72.634969) +Station.find_by(identifier: "23").update(latitude:42.316766, longitude:-72.635669) +Station.find_by(identifier: "27").update(latitude:42.317868, longitude:-72.632754) +Station.find_by(identifier: "31").update(latitude:42.319833, longitude:-72.631120) +Station.find_by(identifier: "28").update(latitude:42.318811, longitude:-72.626401) +Station.find_by(identifier: "32").update(latitude:42.323250, longitude:-72.626584) +Station.find_by(identifier: "22").update(latitude:42.327683, longitude:-72.650239) diff --git a/lib/tasks/import_bikes.rake b/lib/tasks/import_bikes.rake new file mode 100644 index 000000000..f18d6efd2 --- /dev/null +++ b/lib/tasks/import_bikes.rake @@ -0,0 +1,27 @@ +# to import bike data, run the following command in your terminal: +# rake db:import_bikes["notes/bike-data.csv"] +namespace :db do + desc "Import bike data from csv file" + task :import_bikes, [:filename] => :environment do |task,args| + require 'csv' + + puts "Importing bike data" + + CSV.parse(File.read(args[:filename]), headers: true).each do |row| + puts "Importing: Bike #{row.to_hash["identifier"]}\n" + + import_bike(row.to_hash) + end + end + + def import_bike(item) + bike = Bike.new(identifier: item["identifier"]) + bike.current_station = Station.find_by(identifier: item["current_station_identifier"]) + + if bike.save + puts "Successfully imported: Bike #{item["identifier"]}\n" + else + puts "Failed to import: Bike #{item["identifier"]}\n" + end + end +end diff --git a/lib/tasks/import_stations.rake b/lib/tasks/import_stations.rake new file mode 100644 index 000000000..520920fd8 --- /dev/null +++ b/lib/tasks/import_stations.rake @@ -0,0 +1,29 @@ +# task imports station data from a csv file +# use before importing bike data +# rake db:import_stations["notes/station-data.csv"] +# rails db:seed + +namespace :db do + desc "Import station data from csv file" + task :import_stations, [:filename] => :environment do |task, args| + require 'csv' + + puts "Importing station data" + + CSV.parse(File.read(args[:filename]), headers: true).each do |row| + puts "Importing: #{row.to_hash["identifier"]}\n" + + import_station(row.to_hash) + end + end + + def import_station(item) + station = Station.new({ identifier: item["identifier"], name: item["name"], address: item["address"] }) + + if station.save + puts "Successfully imported: #{item["name"]}\n" + else + puts "Failed to import: #{item["name"]}\n" + end + end +end \ No newline at end of file diff --git a/notes/bike-data.csv b/notes/bike-data.csv index fa1687fb9..9124cea92 100644 --- a/notes/bike-data.csv +++ b/notes/bike-data.csv @@ -3,26 +3,26 @@ identifier,current_station_identifier,station_id 3740,21,NULL 7946,29,NULL 6242,22,NULL -6928,NULL,NULL +6928,20,NULL 9543,30,NULL 2459,32,NULL 4949,25,NULL -2576,NULL,NULL +2576,21,NULL 4647,25,NULL -6868,NULL,NULL +6868,22,NULL 4684,31,NULL 3492,33,NULL 3594,30,NULL -4273,NULL,NULL +4273,23,NULL 6908,21,NULL 3176,29,NULL 7169,27,NULL 7938,26,NULL -5995,NULL,NULL -4499,NULL,NULL +5995,24,NULL +4499,25,NULL 6813,31,NULL 4329,27,NULL -9473,NULL,NULL +9473,26,NULL 5378,29,NULL 7872,31,NULL 2008,31,NULL @@ -30,72 +30,72 @@ identifier,current_station_identifier,station_id 4729,31,NULL 7165,21,NULL 1106,33,NULL -1372,NULL,NULL +1372,27,NULL 6730,26,NULL 2699,27,NULL 1366,31,NULL 2596,21,NULL -2663,NULL,NULL +2663,28,NULL 3780,27,NULL 5408,27,NULL -8564,NULL,NULL +8564,29,NULL 7022,22,NULL 4503,27,NULL 6884,22,NULL -4757,NULL,NULL +4757,30,NULL 8702,22,NULL -5697,NULL,NULL +5697,31,NULL 3434,25,NULL 3684,28,NULL 7522,20,NULL 9824,26,NULL -8918,NULL,NULL +8918,32,NULL 3924,27,NULL 5335,26,NULL 8089,25,NULL -1886,NULL,NULL +1886,33,NULL 2525,24,NULL 9192,27,NULL 5460,25,NULL 2253,30,NULL 5444,29,NULL -7788,NULL,NULL +7788,21,NULL 4047,26,NULL 3575,25,NULL 5741,32,NULL -9718,NULL,NULL +9718,22,NULL 7437,29,NULL 9348,28,NULL -4292,NULL,NULL +4292,23,NULL 2165,26,NULL 2612,21,NULL 5068,27,NULL 1028,22,NULL -9834,NULL,NULL +9834,24,NULL 2074,27,NULL 5111,21,NULL 7907,20,NULL 3994,23,NULL -5276,NULL,NULL +5276,25,NULL 7148,23,NULL 6862,31,NULL -7865,NULL,NULL +7865,26,NULL 1144,21,NULL -3998,NULL,NULL +3998,27,NULL 6669,26,NULL 9189,27,NULL 7420,33,NULL -5224,NULL,NULL +5224,28,NULL 3047,28,NULL 9494,21,NULL 7680,21,NULL 3422,27,NULL -2209,NULL,NULL +2209,29,NULL 3622,32,NULL 2887,33,NULL 3075,29,NULL -6541,NULL,NULL +6541,30,NULL 9557,30,NULL 1758,20,NULL -4033,NULL,NULL +4033,31,NULL 4683,31,NULL \ No newline at end of file diff --git a/notes/station-data.csv b/notes/station-data.csv index 6f147a8a8..e4e9a20ca 100644 --- a/notes/station-data.csv +++ b/notes/station-data.csv @@ -1,15 +1,15 @@ identifier,name,has_kiosk,needs_maintenance,dock_count,docked_bike_count,address -21,Florence Bank Station,0,0,7,4,19 Meadow Street Florence MA @ Lilly Library -24,Florence Center,0,0,10,2,31 Main Street Florence MA -30,Jackson Street,0,0,16,8,7A-7D Jackson Street Northampton MA -25,Cooley Dickinson Health Care,0,1,14,6,51 Locust Street Northampton MA -29,State St/Mass Central Rail Trail,0,0,10,4,State Street/Mass Central Rail Trail -33,Northampton High School,0,0,15,8,380 Elm Street Northampton MA -20,Village Hill/State Hospital,0,0,14,6,Village Hill/State Hospital -26,John M Greene Hall/Smith College,0,0,16,5,1 Chapin Way Northampton MA @ John M. Greene Hall -23,Forbes Library,0,0,13,6,20 West Street Northampton MA -27,Pulaski Park/Downtown,1,0,11,3,274 Main Street Northampton MA at Pulaski Park -31,Main Street/Court House,0,1,10,3,99 Main Street Northampton MA -28,Northampton Train Station,1,0,13,5,Northampton Train Station -32,Main Street/Bridge Street,0,0,15,8,1 Bridge Street Northampton MA -22,YMCA/Childs Park,0,0,17,8,YMCA/Childs Park \ No newline at end of file +21,Florence Bank Station,0,0,7,4,"19 Meadow St, Northampton, MA 01062, United States" +24,Florence Center,0,0,10,2,"31 Main Street, Florence, MA 01062, United States" +30,Jackson Street,0,0,16,8,"7A-7D Jackson Street, Northampton, MA 01060, United States" +25,Cooley Dickinson Health Care,0,1,14,6,"51 Locust Street,Northampton, MA 01060, United States" +29,State St/Mass Central Rail Trail,0,0,10,4,"1740 Hardwick Rd, New Braintree, MA 01531, United States" +33,Northampton High School,0,0,15,8,"380 Elm Street, Northampton, MA 01060, United States" +20,Village Hill/State Hospital,0,0,14,6,"51 Village Hill Rd, Northampton, MA 01060, United States" +26,John M Greene Hall/Smith College,0,0,16,5,"60 Elm St, Northampton, MA 01060, United States" +23,Forbes Library,0,0,13,6,"20 West Street, Northampton, MA 01060, United States" +27,Pulaski Park/Downtown,1,0,11,3,"240 Main St, Northampton, MA 01060, United States" +31,Main Street/Court House,0,1,10,3,"99 Main Street, Northampton, MA 01060, United States" +28,Northampton Train Station,1,0,13,5,"170 Pleasant St, Northampton, MA 01060, United States" +32,Main Street/Bridge Street,0,0,15,8,"1 Bridge St, Northampton, MA 01060, United States" +22,YMCA/Childs Park,0,0,17,8,"286 Prospect St, Northampton, MA 01060, United States" \ No newline at end of file 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/home_controller_test.rb b/test/controllers/home_controller_test.rb new file mode 100644 index 000000000..eac0e3360 --- /dev/null +++ b/test/controllers/home_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class HomeControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/test/controllers/map_controller_test.rb b/test/controllers/map_controller_test.rb new file mode 100644 index 000000000..02ff7dd87 --- /dev/null +++ b/test/controllers/map_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class MapControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/test/controllers/payments_controller_test.rb b/test/controllers/payments_controller_test.rb new file mode 100644 index 000000000..c5e86fa35 --- /dev/null +++ b/test/controllers/payments_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class PaymentsControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/test/controllers/rental_controller_test.rb b/test/controllers/rental_controller_test.rb new file mode 100644 index 000000000..a1fde8c56 --- /dev/null +++ b/test/controllers/rental_controller_test.rb @@ -0,0 +1,13 @@ +require "test_helper" + +class RentalControllerTest < ActionDispatch::IntegrationTest + test "should get new" do + get rental_new_url + assert_response :success + end + + test "should get edit" do + get rental_edit_url + assert_response :success + end +end diff --git a/test/fixtures/add_return_station_id_to_rentals.yml b/test/fixtures/add_return_station_id_to_rentals.yml new file mode 100644 index 000000000..c79ca2d31 --- /dev/null +++ b/test/fixtures/add_return_station_id_to_rentals.yml @@ -0,0 +1,7 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + return_station_id: 1 + +two: + return_station_id: 1 diff --git a/test/fixtures/payments.yml b/test/fixtures/payments.yml new file mode 100644 index 000000000..5e3922c56 --- /dev/null +++ b/test/fixtures/payments.yml @@ -0,0 +1,17 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + first_name: MyString + last_name: MyString + card_number: MyString + cvv: 1 + expiry: 2023-11-20 + user: one + +two: + first_name: MyString + last_name: MyString + card_number: MyString + cvv: 1 + expiry: 2023-11-20 + user: two diff --git a/test/fixtures/rentals.yml b/test/fixtures/rentals.yml new file mode 100644 index 000000000..7075131f9 --- /dev/null +++ b/test/fixtures/rentals.yml @@ -0,0 +1,13 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + borrower_id: 1 + bike_id: 1 + checkout: 2023-11-04 15:35:53 + return: 2023-11-04 15:35:53 + +two: + borrower_id: 1 + bike_id: 1 + checkout: 2023-11-04 15:35:53 + return: 2023-11-04 15:35:53 diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml new file mode 100644 index 000000000..b23047dc3 --- /dev/null +++ b/test/fixtures/users.yml @@ -0,0 +1,12 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +# This model initially had no columns defined. If you add columns to the +# model remove the "{}" from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value + diff --git a/test/models/add_return_station_id_to_rental_test.rb b/test/models/add_return_station_id_to_rental_test.rb new file mode 100644 index 000000000..3d055385c --- /dev/null +++ b/test/models/add_return_station_id_to_rental_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class AddReturnStationIdToRentalTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/payment_test.rb b/test/models/payment_test.rb new file mode 100644 index 000000000..f43bc797b --- /dev/null +++ b/test/models/payment_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class PaymentTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/rental_test.rb b/test/models/rental_test.rb new file mode 100644 index 000000000..c3d74bd40 --- /dev/null +++ b/test/models/rental_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class RentalTest < 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