From dccb71599d8f7f95f9ebef62e85d32e05b42ea7d Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 20 Oct 2023 20:06:43 -0400 Subject: [PATCH 001/130] Update README.md add user stories and features --- README.md | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0e1211217..376edc7d7 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,94 @@ -# [your app name here] +# StayVue CodePath WEB103 Final Project -Designed and developed by: [your names here] +Designed and developed by: Saoirse Siobhan Ebert and Hafeefa Sulttan πŸ”— Link to deployed app: ## About +### User Stories: + +`As a traveler, I want to find accommodations in my desired location, so I can plan my trip.` + +Feature: Accommodation Search + +- Users can search for accommodations based on location, dates, and preferences. + + +`As a traveler, I want to see detailed information and photos of accommodations, so I can make an informed decision.` + +Feature: Detailed Accommodation Listings + +- Users can view detailed property listings with descriptions, photos, amenities, and reviews. + +`As a traveler, I want to book accommodations with ease, so I can secure my stay.` + +Feature: Booking Process + +- Users can easily book accommodations with a streamlined booking process. + +`As a traveler, I want to leave reviews and ratings for accommodations after my stay, so I can share my experiences.` + +Feature: Review Submission + +- Users can submit reviews and star ratings for accommodations they've stayed in. + +`As a traveler, I want to earn points for leaving reviews, so I can be rewarded for my feedback.` + +Feature: Review Points System + +- Users earn points for submitting reviews and ratings. + +`As a traveler, I want to see my accumulated points and rewards in one place for easy access.` + +Feature: Points and Rewards Dashboard + +- Users have access to a dashboard displaying their earned points and redeemed rewards. + +`As a traveler, I want to receive personalized recommendations for accommodations based on my previous bookings and preferences.` + +Feature: Personalized Accommodation Recommendations + +- The app provides users with tailored accommodation recommendations based on their history and preferences. + +`As a traveler, I want to see real-time reviews and ratings from other travelers while exploring accommodations.` + +Feature: Real-Time Reviews + +- Users can view real-time reviews and ratings from other travelers while browsing accommodation listings. + +`As a traveler, I want to redeem my earned points for discounts on future bookings, so I can save on my travels.` + +Feature: Redeem Points for Discounts + +- Users can use their earned points to receive discounts on future bookings. + +`As a host, I want to create and manage property listings, so I can attract guests.` + +Feature: Property Management + +- Hosts can create and manage property listings with descriptions, photos, and pricing. + +`As a host, I want to communicate with guests through in-app messaging, so I can provide assistance and answer questions.` + +Feature: In-App Messaging + +- Hosts and guests can communicate through in-app messaging. + +`As a host, I want to manage property availability through an integrated calendar, so I can keep my listings up to date.` + +Feature: Calendar Availability + +- Hosts can manage and display property availability calendars. + +`As a host, I want to define clear cancellation policies for my properties, so guests understand the terms.` + +Feature: Cancellation Policy + +- Hosts can set cancellation policies for their properties. + ### Description and Purpose [text goes here] @@ -47,3 +128,9 @@ Backend: ## Installation Instructions [instructions go here] + +### [ADDITIONAL FEATURES GO HERE - ADD ALL FEATURES HERE IN THE FORMAT ABOVE; you will check these off and add gifs as you complete them] + +## Installation Instructions + +[instructions go here] From 30fef451d7586b1a62b970a5eaaad697e3ab3683 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 20 Oct 2023 20:11:57 -0400 Subject: [PATCH 002/130] Update README.md --- README.md | 81 ------------------------------------------------------- 1 file changed, 81 deletions(-) diff --git a/README.md b/README.md index 376edc7d7..bc412cde0 100644 --- a/README.md +++ b/README.md @@ -8,87 +8,6 @@ Designed and developed by: Saoirse Siobhan Ebert and Hafeefa Sulttan ## About -### User Stories: - -`As a traveler, I want to find accommodations in my desired location, so I can plan my trip.` - -Feature: Accommodation Search - -- Users can search for accommodations based on location, dates, and preferences. - - -`As a traveler, I want to see detailed information and photos of accommodations, so I can make an informed decision.` - -Feature: Detailed Accommodation Listings - -- Users can view detailed property listings with descriptions, photos, amenities, and reviews. - -`As a traveler, I want to book accommodations with ease, so I can secure my stay.` - -Feature: Booking Process - -- Users can easily book accommodations with a streamlined booking process. - -`As a traveler, I want to leave reviews and ratings for accommodations after my stay, so I can share my experiences.` - -Feature: Review Submission - -- Users can submit reviews and star ratings for accommodations they've stayed in. - -`As a traveler, I want to earn points for leaving reviews, so I can be rewarded for my feedback.` - -Feature: Review Points System - -- Users earn points for submitting reviews and ratings. - -`As a traveler, I want to see my accumulated points and rewards in one place for easy access.` - -Feature: Points and Rewards Dashboard - -- Users have access to a dashboard displaying their earned points and redeemed rewards. - -`As a traveler, I want to receive personalized recommendations for accommodations based on my previous bookings and preferences.` - -Feature: Personalized Accommodation Recommendations - -- The app provides users with tailored accommodation recommendations based on their history and preferences. - -`As a traveler, I want to see real-time reviews and ratings from other travelers while exploring accommodations.` - -Feature: Real-Time Reviews - -- Users can view real-time reviews and ratings from other travelers while browsing accommodation listings. - -`As a traveler, I want to redeem my earned points for discounts on future bookings, so I can save on my travels.` - -Feature: Redeem Points for Discounts - -- Users can use their earned points to receive discounts on future bookings. - -`As a host, I want to create and manage property listings, so I can attract guests.` - -Feature: Property Management - -- Hosts can create and manage property listings with descriptions, photos, and pricing. - -`As a host, I want to communicate with guests through in-app messaging, so I can provide assistance and answer questions.` - -Feature: In-App Messaging - -- Hosts and guests can communicate through in-app messaging. - -`As a host, I want to manage property availability through an integrated calendar, so I can keep my listings up to date.` - -Feature: Calendar Availability - -- Hosts can manage and display property availability calendars. - -`As a host, I want to define clear cancellation policies for my properties, so guests understand the terms.` - -Feature: Cancellation Policy - -- Hosts can set cancellation policies for their properties. - ### Description and Purpose [text goes here] From a16b91125c40db4dc45a520674520982396fe615 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 20 Oct 2023 20:16:11 -0400 Subject: [PATCH 003/130] Update user_stories.md add user stories --- planning/user_stories.md | 66 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/planning/user_stories.md b/planning/user_stories.md index 1e55ecbcd..8fc870194 100644 --- a/planning/user_stories.md +++ b/planning/user_stories.md @@ -1,13 +1,69 @@ # User Stories -Reference the Writing User Stories final project guide in the course portal for more information about how to complete each of the sections below. - ## Outline User Roles -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ Include at least at least 1, but no more than 3, user roles.] +- Host Role: + +Description: + +`A host is a user who lists their property or accommodation on the platform for travelers to book. Hosts play a pivotal role in providing lodging and experiences to travelers, sharing their spaces and local insights.` + +- Traveler Role: +- +Description: + +`A traveler is a user who seeks accommodations or experiences on the platform for their trips. Travelers use the platform to discover and book a variety of lodging options, from vacation rentals to hotels, based on their preferences and travel plans.` ## Draft User Stories -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ Include at least at least 10 user stories in this format:] +1. `As a traveler, I want to find accommodations in my desired location, so I can plan my trip.` + +- Users can search for accommodations based on location, dates, and preferences. + +2. `As a traveler, I want to see detailed information and photos of accommodations, so I can make an informed decision.` + +- Users can view detailed property listings with descriptions, photos, amenities, and reviews. + +3. `As a traveler, I want to book accommodations with ease, so I can secure my stay.` + +- Users can easily book accommodations with a streamlined booking process. + +4. `As a traveler, I want to leave reviews and ratings for accommodations after my stay, so I can share my experiences.` + +- Users can submit reviews and star ratings for accommodations they've stayed in. + +5. `As a traveler, I want to earn points for leaving reviews, so I can be rewarded for my feedback.` + +- Users earn points for submitting reviews and ratings. + +6. `As a traveler, I want to see my accumulated points and rewards in one place for easy access.` + +- Users have access to a dashboard displaying their earned points and redeemed rewards. + +7. `As a traveler, I want to receive personalized recommendations for accommodations based on my previous bookings and preferences.` + +- The app provides users with tailored accommodation recommendations based on their history and preferences. + +8. `As a traveler, I want to see real-time reviews and ratings from other travelers while exploring accommodations.` + +- Users can view real-time reviews and ratings from other travelers while browsing accommodation listings. + +9. `As a traveler, I want to redeem my earned points for discounts on future bookings, so I can save on my travels.` + +- Users can use their earned points to receive discounts on future bookings. + +10. `As a host, I want to create and manage property listings, so I can attract guests.` + +- Hosts can create and manage property listings with descriptions, photos, and pricing. + +11. `As a host, I want to communicate with guests through in-app messaging, so I can provide assistance and answer questions.` + +- Hosts and guests can communicate through in-app messaging. + +12. `As a host, I want to manage property availability through an integrated calendar, so I can keep my listings up to date.` + +- Hosts can manage and display property availability calendars. + +13. `As a host, I want to define clear cancellation policies for my properties, so guests understand the terms.` -1. As a [user role], I want to [what], so that [why]. +- Hosts can set cancellation policies for their properties. From bdbd425fdc0fa6f638324a91c76b00449f94fe76 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 20 Oct 2023 20:18:01 -0400 Subject: [PATCH 004/130] Update milestone1.md --- milestones/milestone1.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/milestones/milestone1.md b/milestones/milestone1.md index a8f086378..9732d25a0 100644 --- a/milestones/milestone1.md +++ b/milestones/milestone1.md @@ -6,15 +6,15 @@ This document should be completed and submitted during **Unit 5** of this course This unit, be sure to complete all tasks listed below. To complete a task, place an `x` between the brackets. -- [ ] Read and understand all required features - - [ ] Understand you **must** implement **all** baseline features and **two** custom features -- [ ] In `readme.md`: update app name -- [ ] In `readme.md`: add all group members' names -- [ ] In `readme.md`: complete the **Description and Purpose** section -- [ ] In `readme.md`: complete the **Inspiration** section -- [ ] In `readme.md`: list all features you intend to include in your app (in future units, you will check off features as you complete them and add GIFs demonstrating the features) -- [ ] In `planning/user_stories.md`: add all user stories -- [ ] In this document, complete the **Reflection** section below +- [x] Read and understand all required features + - [x] Understand you **must** implement **all** baseline features and **two** custom features +- [x] In `readme.md`: update app name +- [x] In `readme.md`: add all group members' names +- [x] In `readme.md`: complete the **Description and Purpose** section +- [x] In `readme.md`: complete the **Inspiration** section +- [x] In `readme.md`: list all features you intend to include in your app (in future units, you will check off features as you complete them and add GIFs demonstrating the features) +- [x] In `planning/user_stories.md`: add all user stories +- [x] In this document, complete the **Reflection** section below ## Reflection From 7d4d7c8190b95c84c4b46e0eda95396bb90a5bc0 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 20 Oct 2023 20:53:30 -0400 Subject: [PATCH 005/130] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bc412cde0..d631b9aa2 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,11 @@ Designed and developed by: Saoirse Siobhan Ebert and Hafeefa Sulttan ### Description and Purpose -[text goes here] +StayVue is your ultimate travel companion, seamlessly merging the world of accommodations with an exclusive rewards program, connecting you to local businesses for a personalized and unforgettable travel experience. Whether you're a wanderlust-filled traveler or an enthusiastic host, StayVue is combination of exceptional stays and rewards that make travel memories even more rewarding. Travelers can experience unique accommodation experiences, write reviews and share their own experiences and earn points in return. The more you travel, the more you earn. Collect points on each stay, each review, and through a referral program. A user can redeem their earned points for discounts on future bookings, exclusive deals, and gift cards for local businesses. Additionally, users will get personalized recommendation and stay connected to local businesses, which means that the app's mission extends to not only providing awesome travel arrangements but supporting the businesses in which the accomodation is near. Users can communicate with hosts for a seamless booking process and personalized travel guidance, the hosts can show their trust value with verified identities and properties. ### Inspiration -[text goes here] +StayVue's mission goes beyond just booking accommodations; it's about enriching travel experience by connecting you to the heart and soul of your destinationβ€”its local businesses. StayVue is a gateway to immersive travel, rewards, and connections with local communities. Airbnb and other accomodations apps are a huge inspiration for this capstone, but extending the mission in this way is a huge factor into creating a culture of giving back to those communities and the folks who live there. ## Tech Stack From e475b3b5643b1b1db513ffba648d3eaf8650d73c Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 20 Oct 2023 20:59:01 -0400 Subject: [PATCH 006/130] Update README.md --- README.md | 52 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d631b9aa2..671a76ee5 100644 --- a/README.md +++ b/README.md @@ -24,25 +24,63 @@ Backend: ## Features -### [Name of Feature 1] +### Accommodation Search -[short description goes here] +Users can search for accommodations based on location, dates, and preferences. [gif goes here] -### [Name of Feature 2] +### Detailed Accommodation Listings -[short description goes here] +sers can view detailed property listings with descriptions, photos, amenities, and reviews. [gif goes here] -### [Name of Feature 3] +### Booking Process -[short description goes here] +Users can easily book accommodations with a streamlined booking process. [gif goes here] -### [ADDITIONAL FEATURES GO HERE - ADD ALL FEATURES HERE IN THE FORMAT ABOVE; you will check these off and add gifs as you complete them] +### Review Submission + +Users can submit and edit, and delete reviews and star ratings for accommodations they've stayed in. + +### Review Points System + +Users earn points for submitting reviews and ratings. + +### Points and Rewards Dashboard + +Users have access to a dashboard displaying their earned points and redeemed rewards. + +### Real-Time Reviews + +Users can view real-time reviews and ratings from other travelers while browsing accommodation listings. + +### Redeem Points for Discounts and Perks + +Users can use their earned points to receive discounts on future bookings and experiences within the local community that the booking is at + +### Property Management + +Hosts can create and manage property listings with descriptions, photos, and pricing. + +### In-App Messaging + +Hosts and guests can communicate through in-app messaging. + +### Host Verification + +Hosts can verify their identity and properties to build trust with users. + +### Calendar Availability + +Hosts can manage and display property availability calendars. + +### Cancellation Policy + +Hosts can set cancellation policies for their properties. ## Installation Instructions From ea2be549ef9c526f33f10bf769bb442c6f3fd1f8 Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sat, 21 Oct 2023 00:49:40 -0400 Subject: [PATCH 007/130] completed readme reflection for milestone1 --- milestones/milestone1.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/milestones/milestone1.md b/milestones/milestone1.md index 9732d25a0..06a0e2b71 100644 --- a/milestones/milestone1.md +++ b/milestones/milestone1.md @@ -20,12 +20,13 @@ This unit, be sure to complete all tasks listed below. To complete a task, place ### 1. What went well during this unit? -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ your answer here] + +[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ What went well during this unit was how quickly and swiftly we acted as a team as soon as we found out we were teammates. We developed a clear and innovative concept for our app. We then went on to make user stories, where we successfully created comprehensive user stories that detailed the user's perspective with our app, which made us realize on a deeper level about what a user would want from our application.] ### 2. What were some challenges your group faced in this unit? -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ your answer here] +[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ As a team of just two people, we had a bit of confusion because I had a hackathon commitment. But we talked it out and adjusted our project schedule. We also both had college to deal with, so we made a shared calendar and split our tasks better. Despite the challenges, we learned to manage our time and communicate effectively, and we still got our project done.] ### 3. What additional support will you need in upcoming units as you continue to work on your final project? -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ your answer here] +[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ As we continue with our final project, we could use extra help in a few areas. It'd be great to get feedback from instructors and mentors to ensure we're on the right track. Also, technical support, access to necessary tools, and help with any technical issues would be beneficial.] From e0d3186433e7509c1e06d04d1baaecf9ae4398b8 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 28 Oct 2023 01:56:11 -0400 Subject: [PATCH 008/130] Update milestone2.md --- milestones/milestone2.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/milestones/milestone2.md b/milestones/milestone2.md index 7d7687f1e..0acc14bed 100644 --- a/milestones/milestone2.md +++ b/milestones/milestone2.md @@ -6,11 +6,11 @@ This document should be completed and submitted during **Unit 6** of this course This unit, be sure to complete all tasks listed below. To complete a task, place an `x` between the brackets. -- [ ] In `planning/wireframes.md`: add wireframes for at least three pages in your web app -- [ ] In `planning/entity_relationship_diagram.md`: add the entity relationship diagram you developed for your database -- [ ] Prepare your three-minute pitch presentation, to be presented during Unit 7 (the next unit) - - [ ] You do **not** need to submit any materials in advance of your pitch -- [ ] In this document, complete the **Reflection** section below +- [x] In `planning/wireframes.md`: add wireframes for at least three pages in your web app +- [x] In `planning/entity_relationship_diagram.md`: add the entity relationship diagram you developed for your database +- [x] Prepare your three-minute pitch presentation, to be presented during Unit 7 (the next unit) + - [x] You do **not** need to submit any materials in advance of your pitch +- [x] In this document, complete the **Reflection** section below ## Reflection From 9d9731a025138f3b30df0c5f0df816f920855f0a Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 28 Oct 2023 02:03:33 -0400 Subject: [PATCH 009/130] Update entity_relationship_diagram.md --- planning/entity_relationship_diagram.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/planning/entity_relationship_diagram.md b/planning/entity_relationship_diagram.md index 12c25f62c..db2dcfb27 100644 --- a/planning/entity_relationship_diagram.md +++ b/planning/entity_relationship_diagram.md @@ -4,14 +4,17 @@ Reference the Creating an Entity Relationship Diagram final project guide in the ## Create the List of Tables -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ List each table in your diagram] +Tables: +- Traveler +- Host +- Property +- Booking +- Invoice +- Listing +- Business +- Perk +- TravelerBookingPerk ## Add the Entity Relationship Diagram -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ Include an image or images of the diagram below. You may also wish to use the following markdown syntax to outline each table, as per your preference.] - -| Column Name | Type | Description | -|-------------|------|-------------| -| id | integer | primary key | -| name | text | name of the shoe model | -| ... | ... | ... | +![StayVue ERD (1)](https://github.com/itsgivingchaotica/stayvue/assets/91578619/75ce01ca-e0d8-4e2d-960c-59555e1d07bf) From 38974cefde5cb3c3cddc61f1976a736846e29d9c Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 28 Oct 2023 02:27:03 -0400 Subject: [PATCH 010/130] Update wireframes.md --- planning/wireframes.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/planning/wireframes.md b/planning/wireframes.md index fbcd15a0c..8a4cf49c9 100644 --- a/planning/wireframes.md +++ b/planning/wireframes.md @@ -4,18 +4,24 @@ Reference the Creating an Entity Relationship Diagram final project guide in the ## List of Pages -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ List the pages you expect to have in your app, with a ⭐ next to pages you have wireframed] +- Listings Page +- View Listing Page +- Host Profile Page +- Traveler Profile Page +- Your Perks Page +- Edit Profile Page +- Add Property Page -## Wireframe 1: [page title] +## Wireframe 1: Listings Page [πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ include wireframe 1] -## Wireframe 2: [page title] +## Wireframe 2: View Listing Page [πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ include wireframe 2] -## Wireframe 3: [page title] +## Wireframe 3: Your Perks Page + + -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ include wireframe 3] -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ include more wireframes as desired] From 4b23b672a1cbfc80e7cc0050798cfec018203fcf Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 28 Oct 2023 02:27:35 -0400 Subject: [PATCH 011/130] Update entity_relationship_diagram.md --- planning/entity_relationship_diagram.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/planning/entity_relationship_diagram.md b/planning/entity_relationship_diagram.md index db2dcfb27..ed1cc35db 100644 --- a/planning/entity_relationship_diagram.md +++ b/planning/entity_relationship_diagram.md @@ -2,7 +2,7 @@ Reference the Creating an Entity Relationship Diagram final project guide in the course portal for more information about how to complete this deliverable. -## Create the List of Tables +## List of Tables Tables: - Traveler @@ -15,6 +15,6 @@ Tables: - Perk - TravelerBookingPerk -## Add the Entity Relationship Diagram +## Entity Relationship Diagram -![StayVue ERD (1)](https://github.com/itsgivingchaotica/stayvue/assets/91578619/75ce01ca-e0d8-4e2d-960c-59555e1d07bf) +![StayVue ERD (2)](https://github.com/itsgivingchaotica/stayvue/assets/91578619/c6eebc9a-392c-4f13-8566-234e86bf0831) From 6c812c4e680fefc7b385022b297213319ae66ab2 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 28 Oct 2023 02:32:59 -0400 Subject: [PATCH 012/130] Update entity_relationship_diagram.md --- planning/entity_relationship_diagram.md | 1 + 1 file changed, 1 insertion(+) diff --git a/planning/entity_relationship_diagram.md b/planning/entity_relationship_diagram.md index ed1cc35db..c26699857 100644 --- a/planning/entity_relationship_diagram.md +++ b/planning/entity_relationship_diagram.md @@ -14,6 +14,7 @@ Tables: - Business - Perk - TravelerBookingPerk +- Amenities ## Entity Relationship Diagram From c30d4ddbde17fe408ca9f916cdec4cb81433ce1a Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sat, 28 Oct 2023 02:42:43 -0400 Subject: [PATCH 013/130] added milestone2 relflection --- milestones/milestone2.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/milestones/milestone2.md b/milestones/milestone2.md index 0acc14bed..2bf559655 100644 --- a/milestones/milestone2.md +++ b/milestones/milestone2.md @@ -16,12 +16,12 @@ This unit, be sure to complete all tasks listed below. To complete a task, place ### 1. What went well during this unit? -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ your answer here] +[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ Working on time with each other went really well. We were able to complete the basic wireframes on Monday and worked together until completion. We met again on Friday in order to discuss how to complete how the 3 pages will be visualized, and we were able to finish that quickly and swiftly. We also divided the rest of the tasks equally between us throughout the week to ensure none of us were overwelmed with too much work. ] ### 2. What were some challenges your group faced in this unit? -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ your answer here] +[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎThe visualization of the pages became a bit of a challenge for us. We tried to encorporate what other similar sites were like and how we would like to make the site appear. We came up with a color scheme along with this but were not able to implement it into our figma right away, as the color did seem a bit off. We hope to fix this issue as soon as possible while designing the site and have clean, simple UI in the actual website] ### 3. What additional support will you need in upcoming units as you continue to work on your final project? -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ your answer here] +[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ In the future, it would just be great if our mentor can visit us more often for helping us out with the visualization and the coloring of the webpage. Furthermore, it would be great to discuss the ideas we have come up with her so we can reach a conclusion about what we should finalize in our website] From 8f97ffa3efaa3ca913ae94eda0b23414916341bb Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 28 Oct 2023 02:54:39 -0400 Subject: [PATCH 014/130] Update wireframes.md --- planning/wireframes.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/planning/wireframes.md b/planning/wireframes.md index 8a4cf49c9..fb3dab27e 100644 --- a/planning/wireframes.md +++ b/planning/wireframes.md @@ -14,14 +14,18 @@ Reference the Creating an Entity Relationship Diagram final project guide in the ## Wireframe 1: Listings Page -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ include wireframe 1] +![Listings Page](https://github.com/itsgivingchaotica/stayvue/assets/91578619/3ec5f0dc-493f-4cba-8ba8-4390bc430cf1) + +![Listings Page Filtering](https://github.com/itsgivingchaotica/stayvue/assets/91578619/554d60e2-93ff-481d-8861-e0e08d2256e0) + ## Wireframe 2: View Listing Page -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ include wireframe 2] +![Single Listing Page](https://github.com/itsgivingchaotica/stayvue/assets/91578619/f9f902e2-ce5f-4550-a982-fa6f6918eed9) ## Wireframe 3: Your Perks Page +![Your Perks](https://github.com/itsgivingchaotica/stayvue/assets/91578619/7831807b-db41-452d-93d6-de531ed310a4) From b6186e28b1448d0a331eb20a9daac7f1a8e2faa1 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 29 Oct 2023 14:23:59 -0400 Subject: [PATCH 015/130] react redux tailwind init --- client/.eslintrc.cjs | 20 + client/.gitignore | 26 + client/README.md | 8 + client/index.html | 14 + client/package-lock.json | 4679 +++++++++++++++++++++++++++++++++++ client/package.json | 34 + client/public/vite.svg | 1 + client/src/App.css | 42 + client/src/App.jsx | 35 + client/src/assets/react.svg | 1 + client/src/index.css | 73 + client/src/main.jsx | 10 + client/tailwind.config.js | 8 + client/vite.config.js | 7 + 14 files changed, 4958 insertions(+) create mode 100644 client/.eslintrc.cjs create mode 100644 client/.gitignore create mode 100644 client/README.md create mode 100644 client/index.html create mode 100644 client/package-lock.json create mode 100644 client/package.json create mode 100644 client/public/vite.svg create mode 100644 client/src/App.css create mode 100644 client/src/App.jsx create mode 100644 client/src/assets/react.svg create mode 100644 client/src/index.css create mode 100644 client/src/main.jsx create mode 100644 client/tailwind.config.js create mode 100644 client/vite.config.js diff --git a/client/.eslintrc.cjs b/client/.eslintrc.cjs new file mode 100644 index 000000000..4dcb43901 --- /dev/null +++ b/client/.eslintrc.cjs @@ -0,0 +1,20 @@ +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: [ + 'eslint:recommended', + 'plugin:react/recommended', + 'plugin:react/jsx-runtime', + 'plugin:react-hooks/recommended', + ], + ignorePatterns: ['dist', '.eslintrc.cjs'], + parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, + settings: { react: { version: '18.2' } }, + plugins: ['react-refresh'], + rules: { + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, +} diff --git a/client/.gitignore b/client/.gitignore new file mode 100644 index 000000000..bcdd101bd --- /dev/null +++ b/client/.gitignore @@ -0,0 +1,26 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules/ +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +.env \ No newline at end of file diff --git a/client/README.md b/client/README.md new file mode 100644 index 000000000..f768e33fc --- /dev/null +++ b/client/README.md @@ -0,0 +1,8 @@ +# React + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh diff --git a/client/index.html b/client/index.html new file mode 100644 index 000000000..5337b1764 --- /dev/null +++ b/client/index.html @@ -0,0 +1,14 @@ + + + + + + + + StayVue + + +
+ + + diff --git a/client/package-lock.json b/client/package-lock.json new file mode 100644 index 000000000..e7735b267 --- /dev/null +++ b/client/package-lock.json @@ -0,0 +1,4679 @@ +{ + "name": "client", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "client", + "version": "0.0.0", + "dependencies": { + "@reduxjs/toolkit": "^1.9.7", + "axios": "^1.6.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-redux": "^8.1.3", + "redux": "^4.2.1", + "redux-logger": "^3.0.6", + "redux-persist": "^6.0.0", + "redux-thunk": "^2.4.2" + }, + "devDependencies": { + "@types/react": "^18.2.15", + "@types/react-dom": "^18.2.7", + "@vitejs/plugin-react": "^4.0.3", + "eslint": "^8.45.0", + "eslint-plugin-react": "^7.32.2", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.3", + "tailwindcss": "^3.3.5", + "vite": "^4.4.5" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", + "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", + "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.2", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", + "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.22.5.tgz", + "integrity": "sha512-nTh2ogNUtxbiSbxaT4Ds6aXnXEipHweN9YRgOX/oNXdf0cCrGn/+2LozFa3lnPV5D90MkjhgckCPBrsoSc1a7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.22.5.tgz", + "integrity": "sha512-yIiRO6yobeEIaI0RTbIr8iAK9FcBHLtZq0S89ZPjDLQXBA4xvghaKqI0etp/tF3htTM0sazJKKLz9oEiGRtu7w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", + "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", + "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@reduxjs/toolkit": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.7.tgz", + "integrity": "sha512-t7v8ZPxhhKgOKtU+uyJT13lu4vL7az5aFi4IdoDs/eS548edn2M8Ik9h8fxgvMjGoAUVFSt6ZC1P5cWmQ014QQ==", + "dependencies": { + "immer": "^9.0.21", + "redux": "^4.2.1", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.8" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18", + "react-redux": "^7.2.1 || ^8.0.2" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.3.tgz", + "integrity": "sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.6", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.6.tgz", + "integrity": "sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.3.tgz", + "integrity": "sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.3.tgz", + "integrity": "sha512-Lsh766rGEFbaxMIDH7Qa+Yha8cMVI3qAK6CHt3OR0YfxOIn5Z54iHiyDRycHrBqeIiqGa20Kpsv1cavfBKkRSw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.4.tgz", + "integrity": "sha512-ZchYkbieA+7tnxwX/SCBySx9WwvWR8TaP5tb2jRAzwvLb/rWchGw3v0w3pqUbUvj0GCwW2Xz/AVPSk6kUGctXQ==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.9", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz", + "integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==" + }, + "node_modules/@types/react": { + "version": "18.2.33", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.33.tgz", + "integrity": "sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.2.14", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.14.tgz", + "integrity": "sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==", + "devOptional": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.5.tgz", + "integrity": "sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==" + }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", + "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.1.0.tgz", + "integrity": "sha512-rM0SqazU9iqPUraQ2JlIvReeaxOoRj6n+PzB1C0cBzIbd8qP336nC39/R9yPi3wVcah7E7j/kdU1uCUqMEU4OQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.22.20", + "@babel/plugin-transform-react-jsx-self": "^7.22.5", + "@babel/plugin-transform-react-jsx-source": "^7.22.5", + "@types/babel__core": "^7.20.2", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0" + } + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz", + "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asynciterator.prototype": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", + "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001557", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001557.tgz", + "integrity": "sha512-91oR7hLNUP3gG6MLU+n96em322a8Xzes8wWdBKhLgUoiJsAF5irZnxSUCbc+qUZXNnPCfUwLOi9ZCZpkvjQajw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-diff": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz", + "integrity": "sha512-yVn6RZmHiGnxRKR9sJb3iVV2XTF1Ghh2DiWRZ3dMnGc43yUdWWF/kX6lQyk3+P84iprfWKU/8zFTrlkvtFm1ug==" + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.569", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.569.tgz", + "integrity": "sha512-LsrJjZ0IbVy12ApW3gpYpcmHS3iRxH4bkKOW98y1/D+3cvDUWGcbzbsFinfUS8knpcZk/PG/2p/RnkMCYN7PVg==", + "dev": true + }, + "node_modules/es-abstract": { + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.5", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz", + "integrity": "sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==", + "dev": true, + "dependencies": { + "asynciterator.prototype": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.1", + "es-set-tostringtag": "^2.0.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.0.1" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", + "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.52.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.33.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", + "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "array.prototype.tosorted": "^1.1.1", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.12", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "object.hasown": "^1.1.2", + "object.values": "^1.1.6", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.4", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.8" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.4.tgz", + "integrity": "sha512-eD83+65e8YPVg6603Om2iCIwcQJf/y7++MWm4tACtEswFLYMwxwVWAfwN+e19f5Ad/FOyyNg9Dfi5lXhH3Y3rA==", + "dev": true, + "peerDependencies": { + "eslint": ">=7" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", + "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, + "node_modules/jiti": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.20.0.tgz", + "integrity": "sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", + "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.hasown": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz", + "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-import/node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", + "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", + "dev": true, + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^2.1.1" + }, + "engines": { + "node": ">= 14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", + "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.11" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-redux": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.3.tgz", + "integrity": "sha512-n0ZrutD7DaX/j9VscF+uTALI3oUPa/pO4Z3soOBIjuRn/FzVu6aehhysxZCLi6y7duMf52WNZGMl7CtuK5EnRw==", + "dependencies": { + "@babel/runtime": "^7.12.1", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/use-sync-external-store": "^0.0.3", + "hoist-non-react-statics": "^3.3.2", + "react-is": "^18.0.0", + "use-sync-external-store": "^1.0.0" + }, + "peerDependencies": { + "@types/react": "^16.8 || ^17.0 || ^18.0", + "@types/react-dom": "^16.8 || ^17.0 || ^18.0", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0", + "react-native": ">=0.59", + "redux": "^4 || ^5.0.0-beta.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "node_modules/react-redux/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/react-refresh": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", + "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, + "node_modules/redux-logger": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/redux-logger/-/redux-logger-3.0.6.tgz", + "integrity": "sha512-JoCIok7bg/XpqA1JqCqXFypuqBbQzGQySrhFzewB7ThcnysTO30l4VCst86AuB9T9tuT03MAA56Jw2PNhRSNCg==", + "dependencies": { + "deep-diff": "^0.3.5" + } + }, + "node_modules/redux-persist": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz", + "integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==", + "peerDependencies": { + "redux": ">4.0.0" + } + }, + "node_modules/redux-thunk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", + "peerDependencies": { + "redux": "^4" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", + "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" + }, + "node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", + "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "regexp.prototype.flags": "^1.5.0", + "set-function-name": "^2.0.0", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sucrase": { + "version": "3.34.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz", + "integrity": "sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "7.1.6", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.5.tgz", + "integrity": "sha512-5SEZU4J7pxZgSkv7FP1zY8i2TIAOooNZ1e/OGtxIEv6GltpoiXUqWvLy89+a10qYTB1N5Ifkuw9lqQkN9sscvA==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.19.1", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/vite": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", + "integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==", + "dev": true, + "dependencies": { + "esbuild": "^0.18.10", + "postcss": "^8.4.27", + "rollup": "^3.27.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.4", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yaml": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz", + "integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/client/package.json b/client/package.json new file mode 100644 index 000000000..97fc51ddb --- /dev/null +++ b/client/package.json @@ -0,0 +1,34 @@ +{ + "name": "client", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "@reduxjs/toolkit": "^1.9.7", + "axios": "^1.6.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-redux": "^8.1.3", + "redux": "^4.2.1", + "redux-logger": "^3.0.6", + "redux-persist": "^6.0.0", + "redux-thunk": "^2.4.2" + }, + "devDependencies": { + "@types/react": "^18.2.15", + "@types/react-dom": "^18.2.7", + "@vitejs/plugin-react": "^4.0.3", + "eslint": "^8.45.0", + "eslint-plugin-react": "^7.32.2", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.3", + "tailwindcss": "^3.3.5", + "vite": "^4.4.5" + } +} diff --git a/client/public/vite.svg b/client/public/vite.svg new file mode 100644 index 000000000..e7b8dfb1b --- /dev/null +++ b/client/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/src/App.css b/client/src/App.css new file mode 100644 index 000000000..b9d355df2 --- /dev/null +++ b/client/src/App.css @@ -0,0 +1,42 @@ +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} diff --git a/client/src/App.jsx b/client/src/App.jsx new file mode 100644 index 000000000..b8b8473a3 --- /dev/null +++ b/client/src/App.jsx @@ -0,0 +1,35 @@ +import { useState } from 'react' +import reactLogo from './assets/react.svg' +import viteLogo from '/vite.svg' +import './App.css' + +function App() { + const [count, setCount] = useState(0) + + return ( + <> +
+ + Vite logo + + + React logo + +
+

Vite + React

+
+ +

+ Edit src/App.jsx and save to test HMR +

+
+

+ Click on the Vite and React logos to learn more +

+ + ) +} + +export default App diff --git a/client/src/assets/react.svg b/client/src/assets/react.svg new file mode 100644 index 000000000..6c87de9bb --- /dev/null +++ b/client/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/src/index.css b/client/src/index.css new file mode 100644 index 000000000..ad94ef851 --- /dev/null +++ b/client/src/index.css @@ -0,0 +1,73 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/client/src/main.jsx b/client/src/main.jsx new file mode 100644 index 000000000..54b39dd1d --- /dev/null +++ b/client/src/main.jsx @@ -0,0 +1,10 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.jsx' +import './index.css' + +ReactDOM.createRoot(document.getElementById('root')).render( + + + , +) diff --git a/client/tailwind.config.js b/client/tailwind.config.js new file mode 100644 index 000000000..a37d3934f --- /dev/null +++ b/client/tailwind.config.js @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ["./src/**/*.{html,js,jsx}"], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/client/vite.config.js b/client/vite.config.js new file mode 100644 index 000000000..5a33944a9 --- /dev/null +++ b/client/vite.config.js @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}) From b19a681421013673f91a66237fe24335e199ff46 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 29 Oct 2023 14:24:14 -0400 Subject: [PATCH 016/130] node express init --- server/.gitignore | 133 +++++ server/package-lock.json | 1164 ++++++++++++++++++++++++++++++++++++++ server/package.json | 19 + 3 files changed, 1316 insertions(+) create mode 100644 server/.gitignore create mode 100644 server/package-lock.json create mode 100644 server/package.json diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 000000000..8fb58faa8 --- /dev/null +++ b/server/.gitignore @@ -0,0 +1,133 @@ +.env +node_modules/ + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* \ No newline at end of file diff --git a/server/package-lock.json b/server/package-lock.json new file mode 100644 index 000000000..f2dc0f0fc --- /dev/null +++ b/server/package-lock.json @@ -0,0 +1,1164 @@ +{ + "name": "server", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "server", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "dotenv": "^16.3.1", + "express": "^4.18.2", + "nodemon": "^3.0.1", + "pg": "^8.11.3" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dependencies": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "dependencies": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nodemon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.1.tgz", + "integrity": "sha512-g9AZ7HmkhQkqXkRc20w+ZfQ73cHLbE8hnPbtaFbFtCumZsjyMhKk9LajQ07U5Ux28lvFjZ5X7HvWR1xzU8jHVw==", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/pg": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", + "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", + "dependencies": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.6.2", + "pg-pool": "^3.6.1", + "pg-protocol": "^1.6.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", + "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": { + "split2": "^4.1.0" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/server/package.json b/server/package.json new file mode 100644 index 000000000..3bcf7c5f2 --- /dev/null +++ b/server/package.json @@ -0,0 +1,19 @@ +{ + "name": "server", + "version": "1.0.0", + "description": "", + "main": "server.js", + "type": "module", + "scripts": { + "start": "nodemon server.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "dotenv": "^16.3.1", + "express": "^4.18.2", + "nodemon": "^3.0.1", + "pg": "^8.11.3" + } +} From 69441dbea2558cb15c9c9730f9877ce33435a8e4 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 29 Oct 2023 18:20:39 -0400 Subject: [PATCH 017/130] Update entity_relationship_diagram.md --- planning/entity_relationship_diagram.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/planning/entity_relationship_diagram.md b/planning/entity_relationship_diagram.md index c26699857..d0974d246 100644 --- a/planning/entity_relationship_diagram.md +++ b/planning/entity_relationship_diagram.md @@ -5,17 +5,22 @@ Reference the Creating an Entity Relationship Diagram final project guide in the ## List of Tables Tables: +- User - Traveler - Host +- Admin - Property - Booking - Invoice - Listing +- ListingMessage - Business +- Image - Perk - TravelerBookingPerk -- Amenities +- AmenitityList ## Entity Relationship Diagram -![StayVue ERD (2)](https://github.com/itsgivingchaotica/stayvue/assets/91578619/c6eebc9a-392c-4f13-8566-234e86bf0831) +![StayVue ERD (3)](https://github.com/itsgivingchaotica/stayvue/assets/91578619/29ff9f22-bfba-4bae-98ba-358e476a0f48) + From c8a922108c8a3fc2000e6796e64470cca106d9d5 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 3 Nov 2023 21:37:36 -0400 Subject: [PATCH 018/130] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 671a76ee5..9e9cd2ef5 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,9 @@ StayVue's mission goes beyond just booking accommodations; it's about enriching ## Tech Stack -Frontend: +Frontend: React, Redux, TailwindCSS, Axios, Webix -Backend: +Backend: NodeJS, Express, PostgreSQL, Socket.io, Passport.js ## Features From c3577d2283c404bec7191729f8c87bdf006113e3 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 3 Nov 2023 21:38:24 -0400 Subject: [PATCH 019/130] Update milestone3.md --- milestones/milestone3.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/milestones/milestone3.md b/milestones/milestone3.md index 74f5aa99a..52617fb58 100644 --- a/milestones/milestone3.md +++ b/milestones/milestone3.md @@ -8,14 +8,14 @@ This unit, be sure to complete all tasks listed below. To complete a task, place You will need to reference the GitHub Project Management guide in the course portal for more information about how to complete each of these steps. -- [ ] Create a project board associated with this repo -- [ ] In this repo, create GitHub milestones for each of the remaining milestones in this unit -- [ ] In this repo, create issues for each feature on your feature list - - [ ] Make sure to add the issues to your project board and to the appropriate milestones -- [ ] Update the status of issues in your project board as you complete them -- [ ] In `readme.md`, check off the features you have completed in this unit by adding a βœ… emoji in front of their title - - [ ] Under each feature you have completed, **include a GIF** showing feature functionality -- [ ] In this document, complete the **Reflection** section below +- [x] Create a project board associated with this repo +- [x] In this repo, create GitHub milestones for each of the remaining milestones in this unit +- [x] In this repo, create issues for each feature on your feature list + - [x] Make sure to add the issues to your project board and to the appropriate milestones +- [x] Update the status of issues in your project board as you complete them +- [x] In `readme.md`, check off the features you have completed in this unit by adding a βœ… emoji in front of their title + - [x] Under each feature you have completed, **include a GIF** showing feature functionality +- [x] In this document, complete the **Reflection** section below ## Reflection From e16e607c90a7c4328d5e3c486f91130b8f62c4bb Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sat, 4 Nov 2023 01:38:50 -0400 Subject: [PATCH 020/130] completed reflection --- milestones/milestone3.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/milestones/milestone3.md b/milestones/milestone3.md index 74f5aa99a..0a603aae3 100644 --- a/milestones/milestone3.md +++ b/milestones/milestone3.md @@ -8,33 +8,33 @@ This unit, be sure to complete all tasks listed below. To complete a task, place You will need to reference the GitHub Project Management guide in the course portal for more information about how to complete each of these steps. -- [ ] Create a project board associated with this repo -- [ ] In this repo, create GitHub milestones for each of the remaining milestones in this unit -- [ ] In this repo, create issues for each feature on your feature list - - [ ] Make sure to add the issues to your project board and to the appropriate milestones -- [ ] Update the status of issues in your project board as you complete them -- [ ] In `readme.md`, check off the features you have completed in this unit by adding a βœ… emoji in front of their title - - [ ] Under each feature you have completed, **include a GIF** showing feature functionality -- [ ] In this document, complete the **Reflection** section below +- [x] Create a project board associated with this repo +- [x] In this repo, create GitHub milestones for each of the remaining milestones in this unit +- [x] In this repo, create issues for each feature on your feature list + - [x] Make sure to add the issues to your project board and to the appropriate milestones +- [x] Update the status of issues in your project board as you complete them +- [x] In `readme.md`, check off the features you have completed in this unit by adding a βœ… emoji in front of their title + - [x] Under each feature you have completed, **include a GIF** showing feature functionality +- [x] In this document, complete the **Reflection** section below ## Reflection ### 1. What went well during this unit? -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ your answer here] +[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ During this unit, our team divided tasks clearly and used efficient communication. We supported each other and quickly solved any challenges that arose. We managed our time well, and our positive team spirit made the work enjoyable. This allowed us to complete our tasks swiftly and without interruptions.] ### 2. What were some challenges your group faced in this unit? -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ your answer here] +[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ We faced a problem when the storyboard on GitHub disappeared. It turned out that one team member got accidentally removed from the project. To fix it, we worked together to figure out what went wrong and added the team member back to the project. We learned to be more careful with project settings in the future.] ### Did you finish all of your tasks in your sprint plan for this week? If you did not finish all of the planned tasks, how would you prioritize the remaining tasks on your list? -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ your answer here] +[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ Yes, we completed all our tasks in the sprint plan for this week. If we hadn't finished them, we would have prioritized the remaining tasks based on their importance and dependencies to ensure we meet our project goals.] ### Which features and user stories would you consider β€œat risk”? How will you change your plan if those items remain β€œat risk”? -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ your answer here] +[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ The login feature, which involves using Passport for OAuth, could be considered "at risk" due to potential complexities. If this remains a challenge, we'll allocate more time for troubleshooting and may seek external assistance or consider alternative authentication methods to ensure the login functionality is implemented effectively.] ### 5. What additional support will you need in upcoming units as you continue to work on your final project? -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ your answer here] +[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ We'd like a mentor to review our work and provide guidance to ensure everything is on track. Their input will help us make improvements and avoid potential issues. This support is crucial for our project's success.] From a7b3b80ab2cade11f40d59ef608f61f2b221f43d Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 4 Nov 2023 23:27:41 -0400 Subject: [PATCH 021/130] establish connection to stayvue database --- server/config/database.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 server/config/database.js diff --git a/server/config/database.js b/server/config/database.js new file mode 100644 index 000000000..573ca1479 --- /dev/null +++ b/server/config/database.js @@ -0,0 +1,12 @@ +import pg from "pg"; +import "./dotenv.js"; + +const config = { + user: process.env.PGUSER, + password: process.env.PGPASSWORD, + host: process.env.PGHOST, + port: process.env.PGPORT, + database: process.env.PGDATABASE, +}; + +export const pool = new pg.Pool(config); From 8a8085e6f44dd50b90d5b7da733f9125f773d188 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 4 Nov 2023 23:28:00 -0400 Subject: [PATCH 022/130] use env file --- server/config/dotenv.js | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 server/config/dotenv.js diff --git a/server/config/dotenv.js b/server/config/dotenv.js new file mode 100644 index 000000000..eff5c64ed --- /dev/null +++ b/server/config/dotenv.js @@ -0,0 +1,2 @@ +import dotenv from "dotenv"; +dotenv.config({ path: "../.env" }); From 4a53703f0332d20b557ffc341f1f5e63937d898f Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 4 Nov 2023 23:28:08 -0400 Subject: [PATCH 023/130] create reset file --- server/config/reset.js | 318 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 server/config/reset.js diff --git a/server/config/reset.js b/server/config/reset.js new file mode 100644 index 000000000..e43e4a18b --- /dev/null +++ b/server/config/reset.js @@ -0,0 +1,318 @@ +import { pool } from "./database.js"; +import "./dotenv.js"; +import { fileURLToPath } from "url"; +import path, { dirname } from "path"; +import fs from "fs"; + +const currentPath = fileURLToPath(import.meta.url); +const usersFile = fs.readFileSync( + path.join(dirname(currentPath), "../config/data/users.json") +); +const propertiesFile = fs.readFileSync( + path.join(dirname(currentPath), "../config/data/properties.json") +); +const listingsFile = fs.readFileSync( + path.join(dirname(currentPath), "../config/data/listings.json") +); +const listingAvailabilityFile = fs.readFileSync( + path.join(dirname(currentPath), "../config/data/listingAvailability.json") +); +const propertyAmenitiesFile = fs.readFileSync( + path.join(dirname(currentPath), "../config/data/propertyAmenities.json") +); + +const usersData = JSON.parse(usersFile); +const propertiesData = JSON.parse(propertiesFile); +const listingsData = JSON.parse(listingsFile); +const listingAvailabilityData = JSON.parse(listingAvailabilityFile); +const propertyAmenitiesData = JSON.parse(propertyAmenitiesFile); + +const createUsersTable = async () => { + const createUsersTableQuery = await pool.query( + `CREATE TABLE IF NOT EXISTS users ( + id SERIAL PRIMARY KEY, + first_name VARCHAR(50) NOT NULL, + last_name VARCHAR(50) NOT NULL, + address1 VARCHAR(255) NOT NULL, + address2 VARCHAR(255), + city VARCHAR(255) NOT NULL, + state VARCHAR(255) NOT NULL, + country VARCHAR(255) NOT NULL, + zipcode VARCHAR(255) NOT NULL, + phone VARCHAR(50) NOT NULL, + user_name VARCHAR(50) UNIQUE NOT NULL, + email VARCHAR(50) UNIQUE NOT NULL, + password VARCHAR(255) NOT NULL, + is_active BOOLEAN DEFAULT true + )` + ); + try { + const res = await pool.query(createUsersTableQuery); + console.log("πŸŽ‰ users table created successfully"); + } catch (err) { + console.log("⚠️ error creating users table", err); + } +}; + +const createPropertiesTable = async () => { + const createPropertiesTableQuery = await pool.query( + `CREATE TABLE IF NOT EXISTS properties ( + id SERIAL PRIMARY KEY, + host_id INTEGER REFERENCES users(id) NOT NULL, + address1 VARCHAR(255) NOT NULL, + address2 VARCHAR(255), + city VARCHAR(255) NOT NULL, + state VARCHAR(255) NOT NULL, + country VARCHAR(255) NOT NULL, + zipcode VARCHAR(255) NOT NULL, + rating FLOAT NOT NULL, + num_beds INTEGER NOT NULL, + num_baths INTEGER NOT NULL, + num_bedrooms INTEGER NOT NULL, + property_type VARCHAR(255) NOT NULL + )` + ); + try { + const res = await pool.query(createPropertiesTableQuery); + console.log("πŸŽ‰ properties table created successfully"); + } catch (err) { + console.log("⚠️ error creating properties table", err); + } +}; + +const createListingsTable = async () => { + const createListingsTableQuery = await pool.query( + `CREATE TABLE IF NOT EXISTS listings ( + id SERIAL PRIMARY KEY, + title VARCHAR(255) NOT NULL, + property_id INTEGER REFERENCES properties(id) NOT NULL, + price_per_night MONEY NOT NULL + )` + ); + try { + const res = await pool.query(createListingsTableQuery); + console.log("πŸŽ‰ listings table created successfully"); + } catch (err) { + console.log("⚠️ error creating listings table", err); + } +}; + +const createListingAvailabilityTable = async () => { + const createListingAvailabilityTableQuery = await pool.query( + `CREATE TABLE IF NOT EXISTS listingAvailability ( + id SERIAL PRIMARY KEY, + listing_id INTEGER REFERENCES listings(id) NOT NULL, + start_availability DATE NOT NULL, + end_availability DATE NOT NULL + )` + ); + try { + const res = await pool.query(createListingAvailabilityTableQuery); + console.log("πŸŽ‰ listingAvailability table created successfully"); + } catch (err) { + console.log("⚠️ error creating listingAvailability table", err); + } +}; + +const createPropertyAmenitiesTable = async () => { + const createPropertyAmenitiesTableQuery = await pool.query( + `CREATE TABLE IF NOT EXISTS propertyAmenities ( + id SERIAL PRIMARY KEY, + property_id INTEGER REFERENCES properties(id) NOT NULL, + wifi BOOLEAN NOT NULL, + dryer BOOLEAN NOT NULL, + washer BOOLEAN NOT NULL, + iron BOOLEAN NOT NULL, + air_conditioner BOOLEAN NOT NULL, + heater BOOLEAN NOT NULL, + pool BOOLEAN NOT NULL, + grill BOOLEAN NOT NULL, + hot_tub BOOLEAN NOT NULL, + free_parking BOOLEAN NOT NULL, + ev_charger BOOLEAN NOT NULL, + beach_front BOOLEAN NOT NULL, + water_front BOOLEAN NOT NULL, + mountain_view BOOLEAN NOT NULL, + city_view BOOLEAN NOT NULL, + gym BOOLEAN NOT NULL, + elevator BOOLEAN NOT NULL, + wheelchair_accessible BOOLEAN NOT NULL, + pet_friendly BOOLEAN NOT NULL, + smoking_allowed BOOLEAN NOT NULL + )` + ); + + try { + const res = await pool.query(createPropertyAmenitiesTableQuery); + console.log("πŸŽ‰ propertyAmenities table created successfully"); + } catch (err) { + console.log("⚠️ error creating propertyAmenities table", err); + } +}; + +const seedUsersTable = async () => { + await createUsersTable(); + + usersData.forEach((user) => { + const insertQuery = { + text: "INSERT INTO users (first_name, last_name, address1, address2, city, state, country, zipcode, phone, user_name, email, password, is_active) VALUES ($1, $2, $3, $4, $5, $6, $7, $8 ,$9, $10, $11, $12, $13)", + }; + + const values = [ + user.first_name, + user.last_name, + user.address1, + user.address2, + user.city, + user.state, + user.country, + user.zipcode, + user.phone, + user.user_name, + user.email, + user.password, + user.is_active, + ]; + try { + pool.query(insertQuery, values); + console.log(`βœ… ${user.user_name} added successfully`); + } catch (err) { + console.error("⚠️ error inserting user", err); + } + }); +}; + +const seedPropertiesTable = async () => { + await createPropertiesTable(); + + propertiesData.forEach((property) => { + const insertQuery = { + text: "INSERT INTO properties (host_id, address1, address2, city, state, country, zipcode, rating, num_beds, num_baths, num_bedrooms, property_type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8 ,$9, $10, $11, $12)", + }; + + const values = [ + property.host_id, + property.address1, + property.address2, + property.city, + property.state, + property.country, + property.zipcode, + property.rating, + property.num_beds, + property.num_baths, + property.num_bedrooms, + property.property_type, + ]; + try { + pool.query(insertQuery, values); + console.log(`βœ… ${property.host_id}'s property added successfully`); + } catch (err) { + console.error("⚠️ error inserting property", err); + } + }); +}; + +const seedListingsTable = async () => { + await createListingsTable(); + + listingsData.forEach((listing) => { + const insertQuery = { + text: "INSERT INTO listings (title, property_id, price_per_night) VALUES ($1, $2, $3)", + }; + + const values = [ + listing.title, + listing.property_id, + listing.price_per_night, + ]; + try { + pool.query(insertQuery, values); + console.log(`βœ… ${listing.title} added successfully`); + } catch (err) { + console.error("⚠️ error inserting property", err); + } + }); +}; + +const seedPropertyAmenitiesTable = async () => { + await createPropertyAmenitiesTable(); + + propertyAmenitiesData.forEach((amenityList) => { + const insertQuery = { + text: "INSERT INTO propertyAmenities (property_id, wifi, dryer, washer, iron, air_conditioner, heater, pool, grill, hot_tub, free_parking, ev_charger, beach_front, water_front, mountain_view, city_view, gym, elevator, wheelchair_accessible, pet_friendly, smoking_allowed) VALUES ($1, $2, $3, $4, $5, $6, $7, $8 ,$9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21)", + }; + + const values = [ + amenityList.property_id, + amenityList.wifi, + amenityList.dryer, + amenityList.washer, + amenityList.iron, + amenityList.air_conditioner, + amenityList.heater, + amenityList.pool, + amenityList.grill, + amenityList.hot_tub, + amenityList.free_parking, + amenityList.ev_charger, + amenityList.beach_front, + amenityList.water_front, + amenityList.mountain_view, + amenityList.city_view, + amenityList.gym, + amenityList.elevator, + amenityList.wheelchair_accessible, + amenityList.pet_friendly, + amenityList.smoking_allowed, + ]; + try { + pool.query(insertQuery, values); + console.log( + `βœ… ${amenityList.property_id}'s amentieis added successfully` + ); + } catch (err) { + console.error("⚠️ error inserting amenities", err); + } + }); +}; + +const seedListingAvailabilityTable = async () => { + await createListingAvailabilityTable(); + + listingAvailabilityData.forEach((listing) => { + const insertQuery = { + text: "INSERT INTO listingAvailability (listing_id, start_availability, end_availability) VALUES ($1, $2, $3)", + }; + + const values = [ + listing.listing_id, + listing.start_availability, + listing.end_availability, + ]; + try { + pool.query(insertQuery, values); + console.log(`βœ… ${listing.listing_id} availability added successfully`); + } catch (err) { + console.error("⚠️ error inserting property", err); + } + }); +}; + +const dropAllTables = async () => { + const dropTablesQuery = + "DROP TABLE IF EXISTS users, properties, listings, listingAvailability, propertyAmenities"; + + try { + await pool.query(dropTablesQuery); + console.log("πŸŽ‰ all tables dropped successfully"); + } catch (err) { + console.log("⚠️ error dropping tables", err); + } +}; +// dropAllTables(); +// seedUsersTable(); +// seedPropertiesTable(); +// seedListingsTable(); +// seedPropertyAmenitiesTable(); +seedListingAvailabilityTable(); From caa0d1fd563a0488dcb3ec481ddb02f195a5e940 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 4 Nov 2023 23:28:22 -0400 Subject: [PATCH 024/130] add all mock data --- server/config/data/listingAvailability.json | 37 ++++++ server/config/data/listings.json | 32 +++++ server/config/data/properties.json | 86 ++++++++++++ server/config/data/propertyAmenities.json | 140 ++++++++++++++++++++ server/config/data/users.json | 47 +++++++ 5 files changed, 342 insertions(+) create mode 100644 server/config/data/listingAvailability.json create mode 100644 server/config/data/listings.json create mode 100644 server/config/data/properties.json create mode 100644 server/config/data/propertyAmenities.json create mode 100644 server/config/data/users.json diff --git a/server/config/data/listingAvailability.json b/server/config/data/listingAvailability.json new file mode 100644 index 000000000..18eaba30a --- /dev/null +++ b/server/config/data/listingAvailability.json @@ -0,0 +1,37 @@ +[ + { + "listing_id": 1, + "start_availability": "2019-01-01", + "end_availability": "2019-01-31" + }, + { + "listing_id": 2, + "start_availability": "2019-02-01", + "end_availability": "2019-02-28" + }, + { + "listing_id": 3, + "start_availability": "2019-01-15", + "end_availability": "2019-01-23" + }, + { + "listing_id": 3, + "start_availability": "2019-01-28", + "end_availability": "2019-02-02" + }, + { + "listing_id": 4, + "start_availability": "2019-01-01", + "end_availability": "2019-01-31" + }, + { + "listing_id": 5, + "start_availability": "2019-01-12", + "end_availability": "2019-01-30" + }, + { + "listing_id": 6, + "start_availability": "2019-01-11", + "end_availability": "2019-01-21" + } +] diff --git a/server/config/data/listings.json b/server/config/data/listings.json new file mode 100644 index 000000000..2c081dbf6 --- /dev/null +++ b/server/config/data/listings.json @@ -0,0 +1,32 @@ +[ + { + "title": "Beautiful Ann Arbor Suburban Home", + "property_id": 2, + "price_per_night": "$230.00" + }, + { + "title": "Cabin Home in Ann Arbor Outskirts", + "property_id": 1, + "price_per_night": "$130.00" + }, + { + "title": "Apartment in Dallas Right Across from Major Transit Hub", + "property_id": 4, + "price_per_night": "$175.00" + }, + { + "title": "Apartment in Gated Community in Dallas", + "property_id": 3, + "price_per_night": "$130.00" + }, + { + "title": "Large Guest House in Peaceful Vermont Countryside", + "property_id": 5, + "price_per_night": "$125.00" + }, + { + "title": "The best Bed and Breakfast in Vermont", + "property_id": 6, + "price_per_night": "200.00" + } +] diff --git a/server/config/data/properties.json b/server/config/data/properties.json new file mode 100644 index 000000000..65fce85ce --- /dev/null +++ b/server/config/data/properties.json @@ -0,0 +1,86 @@ +[ + { + "host_id": 2, + "address1": "8089 Wishing Tree Lane", + "address2": "", + "city": "Ann Arbor", + "state": "MI", + "country": "US", + "zipcode": "48108", + "rating": 4.5, + "num_beds": 2, + "num_baths": 2, + "num_bedrooms": 2, + "property_type": "House" + }, + { + "host_id": 2, + "address1": "1518 Pontiac Trail", + "address2": "", + "city": "Ann Arbor", + "state": "MI", + "country": "US", + "zipcode": "48105", + "rating": 4.3, + "num_beds": 5, + "num_baths": 2, + "num_bedrooms": 3, + "property_type": "House" + }, + { + "host_id": 3, + "address1": "4171 Gladewater Rd", + "address2": "Apt 3", + "city": "Dallas", + "state": "TX", + "country": "US", + "zipcode": "75206", + "rating": 4.6, + "num_beds": 2, + "num_baths": 1, + "num_bedrooms": 2, + "property_type": "Apartment" + }, + { + "host_id": 3, + "address1": "3607 Cole Ave", + "address2": "Apt 2", + "city": "Dallas", + "state": "TX", + "country": "US", + "zipcode": "75204", + "rating": 4.1, + "num_beds": 2, + "num_baths": 1, + "num_bedrooms": 1, + "property_type": "Apartment" + }, + { + "host_id": 1, + "address1": "4410 Pikes Falls Rd", + "address2": "", + "city": "Jamaica", + "state": "VT", + "country": "US", + "zipcode": "05343", + "rating": 4.9, + "num_beds": 8, + "num_baths": 3, + "num_bedrooms": 6, + "property_type": "House" + }, + { + "host_id": 1, + "address1": "3849 VT-30", + "address2": "", + "city": "Jamaica", + "state": "VT", + "country": "US", + "zipcode": "05343", + "rating": 5.0, + "num_beds": 7, + "num_baths": 3, + "num_bedrooms": 3, + "property_type": "Bed and Breakfast" + } +] diff --git a/server/config/data/propertyAmenities.json b/server/config/data/propertyAmenities.json new file mode 100644 index 000000000..216e69cc5 --- /dev/null +++ b/server/config/data/propertyAmenities.json @@ -0,0 +1,140 @@ +[ + { + "property_id": 2, + "wifi": true, + "dryer": true, + "washer": true, + "iron": true, + "air_conditioner": false, + "heater": true, + "pool": false, + "grill": true, + "hot_tub": false, + "free_parking": true, + "ev_charger": true, + "beach_front": false, + "water_front": false, + "mountain_view": true, + "city_view": false, + "gym": false, + "elevator": false, + "wheelchair_accessible": true, + "pet_friendly": true, + "smoking_allowed": true + }, + { + "property_id": 1, + "wifi": true, + "dryer": true, + "washer": true, + "iron": true, + "air_conditioner": false, + "heater": true, + "pool": false, + "grill": true, + "hot_tub": false, + "free_parking": true, + "ev_charger": true, + "beach_front": false, + "water_front": true, + "mountain_view": false, + "city_view": false, + "gym": false, + "elevator": false, + "wheelchair_accessible": true, + "pet_friendly": true, + "smoking_allowed": false + }, + { + "property_id": 4, + "wifi": true, + "dryer": false, + "washer": true, + "iron": true, + "air_conditioner": true, + "heater": false, + "pool": false, + "grill": false, + "hot_tub": false, + "free_parking": false, + "ev_charger": false, + "beach_front": false, + "water_front": false, + "mountain_view": false, + "city_view": true, + "gym": false, + "elevator": false, + "wheelchair_accessible": true, + "pet_friendly": true, + "smoking_allowed": true + }, + { + "property_id": 5, + "wifi": true, + "dryer": true, + "washer": true, + "iron": true, + "air_conditioner": true, + "heater": true, + "pool": false, + "grill": true, + "hot_tub": false, + "free_parking": true, + "ev_charger": true, + "beach_front": false, + "water_front": false, + "mountain_view": false, + "city_view": true, + "gym": false, + "elevator": false, + "wheelchair_accessible": false, + "pet_friendly": false, + "smoking_allowed": false + }, + { + "property_id": 6, + "wifi": true, + "dryer": true, + "washer": true, + "iron": true, + "air_conditioner": true, + "heater": true, + "pool": true, + "grill": true, + "hot_tub": true, + "free_parking": true, + "ev_charger": true, + "beach_front": false, + "water_front": false, + "mountain_view": true, + "city_view": false, + "gym": false, + "elevator": false, + "wheelchair_accessible": true, + "pet_friendly": true, + "smoking_allowed": false + }, + { + "property_id": 3, + "wifi": true, + "dryer": true, + "washer": true, + "iron": true, + "air_conditioner": true, + "heater": true, + "pool": false, + "grill": false, + "hot_tub": true, + "free_parking": true, + "ev_charger": true, + "beach_front": true, + "water_front": false, + "mountain_view": false, + "city_view": false, + "gym": true, + "elevator": true, + "wheelchair_accessible": true, + "pet_friendly": false, + "smoking_allowed": false + } +] diff --git a/server/config/data/users.json b/server/config/data/users.json new file mode 100644 index 000000000..4961a4af7 --- /dev/null +++ b/server/config/data/users.json @@ -0,0 +1,47 @@ +[ + { + "first_name": "Mary", + "last_name": "Taylor", + "address1": "8089 Wishing Tree Lane", + "address2": "", + "city": "Ann Arbor", + "state": "MI", + "country": "US", + "zipcode": "48108", + "phone": "734-477-6920", + "user_name": "marytaylor123", + "email": "marytaylor123@gmail.com", + "password": "password123", + "is_active": true + }, + { + "first_name": "Tate", + "last_name": "Greene", + "address1": "4171 Gladewater Rd", + "address2": "Apt 3", + "city": "Dallas", + "state": "TX", + "country": "US", + "zipcode": "75206", + "phone": "345-240-3310", + "user_name": "tategreene456", + "email": "tategreene456@gmail.com", + "password": "password456", + "is_active": true + }, + { + "first_name": "Marilyn", + "last_name": "Whiteman", + "address1": "4410 Pikes Falls Rd", + "address2": "", + "city": "Jamaica", + "state": "VT", + "country": "US", + "zipcode": "05343", + "phone": "381-240-3310", + "user_name": "marilynwhiteman789", + "email": "marilynwhiteman789@gmail.com", + "password": "password789", + "is_active": true + } +] From 1c23a56c77a9d3eb8b8bf77391d4e22c649dcb6a Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 4 Nov 2023 23:28:37 -0400 Subject: [PATCH 025/130] create stayvue server --- server/server.js | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 server/server.js diff --git a/server/server.js b/server/server.js new file mode 100644 index 000000000..6ff51fad8 --- /dev/null +++ b/server/server.js @@ -0,0 +1,60 @@ +import express from "express"; +import cors from "cors"; +// import tripRoutes from "./routes/trips.js"; +// import activityRoutes from "./routes/activities.js"; +// import destinationRoutes from "./routes/destinations.js"; +// import tripDestinationRoutes from "./routes/trips_destinations.js"; +// import authRoutes from "./routes/auth.js"; +// import passport from "passport"; +// import session from "express-session"; +// import { GitHub } from "./config/auth.js"; +import "./config/dotenv.js"; + +const app = express(); + +// app.use( +// session({ +// secret: process.env.CLIENT_SECRET, //need random string in .env +// resave: false, +// saveUninitialized: true, +// }) +// ); + +app.use(express.json()); +app.use(cors()) +// app.use( +// cors({ +// origin: "http://localhost:3000", +// methods: "GET,HEAD,PUT,PATCH,POST,DELETE", +// credentials: true, +// }) +// ); + +// app.use(passport.initialize()); +// app.use(passport.session()); +// passport.use(GitHub); + +//to implement own strategy, can these functions in a custom way +// passport.serializeUser((user, done) => { +// done(null, user); +// }); + +// passport.deserializeUser((user, done) => { +// done(null, user); +// }); + +app.get("/", (req, res) => { + res.redirect("http://localhost:3000"); +}); + +// app.use("/auth", authRoutes); +// app.use("/api/trips", tripRoutes); +// app.use("/api/activities", activityRoutes); +// app.use("/api/destinations", destinationRoutes); +// app.use("/api/trips-destinations", tripDestinationRoutes); + +const PORT = process.env.PORT || 3001; + +app.listen(PORT, () => { + console.log(`πŸš€ Server running on http://localhost:${PORT}`); +}); From fce9170186b88f03cd670c87ee0d048b1341f85d Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 4 Nov 2023 23:28:53 -0400 Subject: [PATCH 026/130] add cors to depedencies --- server/package-lock.json | 21 +++++++++++++++++++++ server/package.json | 4 +++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/server/package-lock.json b/server/package-lock.json index f2dc0f0fc..1098a8e40 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", "nodemon": "^3.0.1", @@ -197,6 +198,18 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -696,6 +709,14 @@ "node": ">=0.10.0" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", diff --git a/server/package.json b/server/package.json index 3bcf7c5f2..8ce10c6df 100644 --- a/server/package.json +++ b/server/package.json @@ -5,12 +5,14 @@ "main": "server.js", "type": "module", "scripts": { - "start": "nodemon server.js" + "start": "npm run reset && nodemon --require dotenv/config server.js", + "reset": "cd config && node --require dotenv/config reset.js" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { + "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", "nodemon": "^3.0.1", From f8888ae6ac7df2d16d016cb496ca0ee943b3b574 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 5 Nov 2023 13:28:26 -0500 Subject: [PATCH 027/130] create and seed images table --- server/config/reset.js | 86 +++++++++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 22 deletions(-) diff --git a/server/config/reset.js b/server/config/reset.js index e43e4a18b..2a1da5f6e 100644 --- a/server/config/reset.js +++ b/server/config/reset.js @@ -5,6 +5,7 @@ import path, { dirname } from "path"; import fs from "fs"; const currentPath = fileURLToPath(import.meta.url); + const usersFile = fs.readFileSync( path.join(dirname(currentPath), "../config/data/users.json") ); @@ -21,15 +22,20 @@ const propertyAmenitiesFile = fs.readFileSync( path.join(dirname(currentPath), "../config/data/propertyAmenities.json") ); +const listingImagesFile = fs.readFileSync( + path.join(dirname(currentPath), "../config/data/listingImages.json") +); + const usersData = JSON.parse(usersFile); const propertiesData = JSON.parse(propertiesFile); const listingsData = JSON.parse(listingsFile); const listingAvailabilityData = JSON.parse(listingAvailabilityFile); const propertyAmenitiesData = JSON.parse(propertyAmenitiesFile); +const listingImagesData = JSON.parse(listingImagesFile); const createUsersTable = async () => { - const createUsersTableQuery = await pool.query( - `CREATE TABLE IF NOT EXISTS users ( + const createUsersTableQuery = { + text: `CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, first_name VARCHAR(50) NOT NULL, last_name VARCHAR(50) NOT NULL, @@ -44,8 +50,8 @@ const createUsersTable = async () => { email VARCHAR(50) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, is_active BOOLEAN DEFAULT true - )` - ); + )`, + }; try { const res = await pool.query(createUsersTableQuery); console.log("πŸŽ‰ users table created successfully"); @@ -55,8 +61,8 @@ const createUsersTable = async () => { }; const createPropertiesTable = async () => { - const createPropertiesTableQuery = await pool.query( - `CREATE TABLE IF NOT EXISTS properties ( + const createPropertiesTableQuery = { + text: `CREATE TABLE IF NOT EXISTS properties ( id SERIAL PRIMARY KEY, host_id INTEGER REFERENCES users(id) NOT NULL, address1 VARCHAR(255) NOT NULL, @@ -70,8 +76,8 @@ const createPropertiesTable = async () => { num_baths INTEGER NOT NULL, num_bedrooms INTEGER NOT NULL, property_type VARCHAR(255) NOT NULL - )` - ); + )`, + }; try { const res = await pool.query(createPropertiesTableQuery); console.log("πŸŽ‰ properties table created successfully"); @@ -81,14 +87,14 @@ const createPropertiesTable = async () => { }; const createListingsTable = async () => { - const createListingsTableQuery = await pool.query( - `CREATE TABLE IF NOT EXISTS listings ( + const createListingsTableQuery = { + text: `CREATE TABLE IF NOT EXISTS listings ( id SERIAL PRIMARY KEY, title VARCHAR(255) NOT NULL, property_id INTEGER REFERENCES properties(id) NOT NULL, price_per_night MONEY NOT NULL - )` - ); + )`, + }; try { const res = await pool.query(createListingsTableQuery); console.log("πŸŽ‰ listings table created successfully"); @@ -98,14 +104,14 @@ const createListingsTable = async () => { }; const createListingAvailabilityTable = async () => { - const createListingAvailabilityTableQuery = await pool.query( - `CREATE TABLE IF NOT EXISTS listingAvailability ( + const createListingAvailabilityTableQuery = { + text: `CREATE TABLE IF NOT EXISTS listingAvailability ( id SERIAL PRIMARY KEY, listing_id INTEGER REFERENCES listings(id) NOT NULL, start_availability DATE NOT NULL, end_availability DATE NOT NULL - )` - ); + )`, + }; try { const res = await pool.query(createListingAvailabilityTableQuery); console.log("πŸŽ‰ listingAvailability table created successfully"); @@ -115,8 +121,8 @@ const createListingAvailabilityTable = async () => { }; const createPropertyAmenitiesTable = async () => { - const createPropertyAmenitiesTableQuery = await pool.query( - `CREATE TABLE IF NOT EXISTS propertyAmenities ( + const createPropertyAmenitiesTableQuery = { + text: `CREATE TABLE IF NOT EXISTS propertyAmenities ( id SERIAL PRIMARY KEY, property_id INTEGER REFERENCES properties(id) NOT NULL, wifi BOOLEAN NOT NULL, @@ -139,8 +145,8 @@ const createPropertyAmenitiesTable = async () => { wheelchair_accessible BOOLEAN NOT NULL, pet_friendly BOOLEAN NOT NULL, smoking_allowed BOOLEAN NOT NULL - )` - ); + )`, + }; try { const res = await pool.query(createPropertyAmenitiesTableQuery); @@ -150,6 +156,23 @@ const createPropertyAmenitiesTable = async () => { } }; +const createListingImagesTable = async () => { + const createListingImagesTableQuery = { + text: `CREATE TABLE IF NOT EXISTS listingImages ( + id SERIAL PRIMARY KEY, + property_id INTEGER REFERENCES properties(id) NOT NULL, + image_url VARCHAR(255) NOT NULL + )`, + }; + + try { + const res = await pool.query(createListingImagesTableQuery); + console.log("πŸŽ‰ listingImages table created successfully"); + } catch (err) { + console.log("⚠️ error creating listingImages table", err); + } +}; + const seedUsersTable = async () => { await createUsersTable(); @@ -299,9 +322,27 @@ const seedListingAvailabilityTable = async () => { }); }; +const seedListingImagesTable = async () => { + await createListingImagesTable(); + + listingImagesData.forEach((listingImage) => { + const insertQuery = { + text: "INSERT INTO listingImages (property_id, image_url) VALUES ($1, $2)", + }; + + const values = [listingImage.property_id, listingImage.image_url]; + try { + pool.query(insertQuery, values); + console.log(`βœ… ${listingImage.image_url} added successfully`); + } catch (err) { + console.error("⚠️ error inserting listing image", err); + } + }); +}; + const dropAllTables = async () => { const dropTablesQuery = - "DROP TABLE IF EXISTS users, properties, listings, listingAvailability, propertyAmenities"; + "DROP TABLE IF EXISTS users, properties, listings, listingAvailability, propertyAmenities, listingImages"; try { await pool.query(dropTablesQuery); @@ -315,4 +356,5 @@ const dropAllTables = async () => { // seedPropertiesTable(); // seedListingsTable(); // seedPropertyAmenitiesTable(); -seedListingAvailabilityTable(); +// seedListingAvailabilityTable(); +// seedListingImagesTable(); From eb0c8cb3192bac6593ad9d3b31cf1e2f62ab8979 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 5 Nov 2023 13:28:39 -0500 Subject: [PATCH 028/130] add listings route as home --- server/server.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/server.js b/server/server.js index 6ff51fad8..cc887d426 100644 --- a/server/server.js +++ b/server/server.js @@ -1,5 +1,6 @@ import express from "express"; import cors from "cors"; +import listingsRoutes from "./routes/listings.js"; // import tripRoutes from "./routes/trips.js"; // import activityRoutes from "./routes/activities.js"; // import destinationRoutes from "./routes/destinations.js"; @@ -21,7 +22,7 @@ const app = express(); // ); app.use(express.json()); -app.use(cors()) +app.use(cors()); // app.use( // cors({ // origin: "http://localhost:3000", @@ -53,6 +54,7 @@ app.get("/", (req, res) => { // app.use("/api/destinations", destinationRoutes); // app.use("/api/trips-destinations", tripDestinationRoutes); +app.use("/api", listingsRoutes); const PORT = process.env.PORT || 3001; app.listen(PORT, () => { From c428c12144be59f5b3d335b92b5675761e9caab6 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 5 Nov 2023 13:28:57 -0500 Subject: [PATCH 029/130] generate listing images data for all properties --- server/config/data/listingImages.json | 74 +++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 server/config/data/listingImages.json diff --git a/server/config/data/listingImages.json b/server/config/data/listingImages.json new file mode 100644 index 000000000..154ac7037 --- /dev/null +++ b/server/config/data/listingImages.json @@ -0,0 +1,74 @@ +[ + { + "property_id": 1, + "image_url": "https://i.ibb.co/VDrRDZF/Screen-Shot-2023-11-05-at-1-01-54-PM.png" + }, + { + "property_id": 1, + "image_url": "https://i.ibb.co/7gQsrnp/Screen-Shot-2023-11-05-at-1-02-16-PM.png" + }, + { + "property_id": 1, + "image_url": "https://i.ibb.co/7bFzJy4/Screen-Shot-2023-11-05-at-1-02-24-PM.png" + }, + { + "property_id": 2, + "image_url": "https://i.ibb.co/bQPF56V/Screen-Shot-2023-11-05-at-1-05-58-PM.png" + }, + { + "property_id": 2, + "image_url": "https://i.ibb.co/GFG88cM/Screen-Shot-2023-11-05-at-1-05-13-PM.png" + }, + { + "property_id": 2, + "image_url": "https://i.ibb.co/b7JKrbn/Screen-Shot-2023-11-05-at-1-08-37-PM.png" + }, + { + "property_id": 3, + "image_url": "https://i.ibb.co/CQ8gGxd/Screen-Shot-2023-11-05-at-1-01-32-PM.png" + }, + { + "property_id": 3, + "image_url": "https://i.ibb.co/4gD1pfv/Screen-Shot-2023-11-05-at-1-05-28-PM.png" + }, + { + "property_id": 3, + "image_url": "https://i.ibb.co/K2HS6hF/Screen-Shot-2023-11-05-at-1-06-31-PM.png" + }, + { + "property_id": 4, + "image_url": "https://i.ibb.co/ZTxTgLM/Screen-Shot-2023-11-05-at-1-06-20-PM.png" + }, + { + "property_id": 4, + "image_url": "https://i.ibb.co/2M9Qcjv/Screen-Shot-2023-11-05-at-1-07-45-PM.png" + }, + { + "property_id": 4, + "image_url": "https://i.ibb.co/fGR4zZp/Screen-Shot-2023-11-05-at-1-06-54-PM.png" + }, + { + "property_id": 5, + "image_url": "https://i.ibb.co/znZJCRn/Screen-Shot-2023-11-05-at-1-09-10-PM.png" + }, + { + "property_id": 5, + "image_url": "https://i.ibb.co/3mdcdYw/Screen-Shot-2023-11-05-at-1-07-16-PM.png" + }, + { + "property_id": 5, + "image_url": "https://i.ibb.co/TPh5Mnz/Screen-Shot-2023-11-05-at-1-05-39-PM.png" + }, + { + "property_id": 6, + "image_url": "https://i.ibb.co/Thd2VR8/Screen-Shot-2023-11-05-at-1-07-04-PM.png" + }, + { + "property_id": 6, + "image_url": "https://i.ibb.co/483dmYd/Screen-Shot-2023-11-05-at-1-09-36-PM.png" + }, + { + "property_id": 6, + "image_url": "https://i.ibb.co/Zx84M7s/Screen-Shot-2023-11-05-at-1-17-10-PM.png" + } +] From 2677b1b7bad68a5618d14209b1727d21d84e4f23 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 5 Nov 2023 13:29:09 -0500 Subject: [PATCH 030/130] listings controller --- server/controllers/listings.js | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 server/controllers/listings.js diff --git a/server/controllers/listings.js b/server/controllers/listings.js new file mode 100644 index 000000000..96e8c2762 --- /dev/null +++ b/server/controllers/listings.js @@ -0,0 +1,32 @@ +import { pool } from "../config/database.js"; + +const getAllListings = async (request, response) => { + try { + const query = ` + SELECT + listings.*, + properties.*, + propertyAmenities.*, + ( + SELECT json_agg(listingAvailability.*) + FROM listingAvailability + WHERE listingAvailability.listing_id = listings.id + ) AS availability, + json_agg(DISTINCT listingImages.*) AS images + FROM listings + INNER JOIN properties ON properties.id = listings.property_id + INNER JOIN propertyAmenities ON properties.id = propertyAmenities.property_id + LEFT JOIN listingImages ON properties.id = listingImages.property_id + GROUP BY listings.id, properties.id, propertyAmenities.id + `; + + const results = await pool.query(query); + response.status(200).json(results.rows); + } catch (error) { + response.status(409).json({ error: error.message }); + } +}; + +export default { + getAllListings, +}; From d71f1104756dde1d027279215dfe3a21467b7796 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 5 Nov 2023 13:29:18 -0500 Subject: [PATCH 031/130] listings route --- server/routes/listings.js | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 server/routes/listings.js diff --git a/server/routes/listings.js b/server/routes/listings.js new file mode 100644 index 000000000..f13161cd9 --- /dev/null +++ b/server/routes/listings.js @@ -0,0 +1,9 @@ +import express from "express"; + +import ListingsController from "../controllers/listings.js"; + +const router = express.Router(); + +router.get("/", ListingsController.getAllListings); + +export default router; From 14d903f9888ed9d23b899afedb9db0421829a936 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 5 Nov 2023 13:29:32 -0500 Subject: [PATCH 032/130] edit start script --- server/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/package.json b/server/package.json index 8ce10c6df..4c53a9fba 100644 --- a/server/package.json +++ b/server/package.json @@ -5,7 +5,7 @@ "main": "server.js", "type": "module", "scripts": { - "start": "npm run reset && nodemon --require dotenv/config server.js", + "start": "nodemon --require dotenv/config server.js", "reset": "cd config && node --require dotenv/config reset.js" }, "keywords": [], From 7cc1a6918d350046868faa390b3119be5d01fc59 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 5 Nov 2023 20:21:42 -0500 Subject: [PATCH 033/130] add styling --- client/src/App.css | 94 +++++++++++++++++++++++++---------- client/src/index.css | 70 -------------------------- client/src/pages/listings.css | 5 ++ 3 files changed, 73 insertions(+), 96 deletions(-) create mode 100644 client/src/pages/listings.css diff --git a/client/src/App.css b/client/src/App.css index b9d355df2..4695c1c0a 100644 --- a/client/src/App.css +++ b/client/src/App.css @@ -1,42 +1,84 @@ #root { max-width: 1280px; margin: 0 auto; - padding: 2rem; - text-align: center; } -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; - transition: filter 300ms; +body { + margin: 0; + font-family: "Work Sans", sans-serif; + font-weight: 800; + box-sizing: border-box; + background-color: #fffffe; } -.logo:hover { - filter: drop-shadow(0 0 2em #646cffaa); + +.container { + position: fixed; + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 20px; + width: 100vw; + z-index: 1000; /* Ensure it's on top of other elements */ + background-color: white; + border-bottom: 1px solid black; } -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafbaa); + +header { + display: flex; +} + +header::after { + content: ""; + display: table; + clear: both; +} + +.stayvue-logo { + height: 5rem; +} + +nav { + float: right; } -@keyframes logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } +nav ul { + margin: 0; + padding: 0; + list-style: none; } -@media (prefers-reduced-motion: no-preference) { - a:nth-of-type(2) .logo { - animation: logo-spin infinite 20s linear; - } +nav li { + display: inline-block; + margin-left: 70px; + position: relative; } -.card { - padding: 2em; +nav a { + color: #444; + text-decoration: none; + text-transform: uppercase; + font-size: 14px; } -.read-the-docs { - color: #888; +nav a:hover { + color: #000; +} + +nav a::before { + content: ""; + display: block; + height: 5px; + background-color: #444; + + position: absolute; + top: 0; + width: 0%; +} + +nav a:hover::before { + width: 100%; +} + +.stayvue-logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); } diff --git a/client/src/index.css b/client/src/index.css index ad94ef851..b5c61c956 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -1,73 +1,3 @@ @tailwind base; @tailwind components; @tailwind utilities; - -:root { - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} -a:hover { - color: #535bf2; -} - -body { - margin: 0; - display: flex; - place-items: center; - min-width: 320px; - min-height: 100vh; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } -} diff --git a/client/src/pages/listings.css b/client/src/pages/listings.css new file mode 100644 index 000000000..728d7c0d7 --- /dev/null +++ b/client/src/pages/listings.css @@ -0,0 +1,5 @@ +.listings-container { + height: 100vh; + margin-top: 8em; + margin-left: 4em; +} From cd44e1cba93e3502bb8a0d2d88f94649ebdc556f Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 5 Nov 2023 20:21:52 -0500 Subject: [PATCH 034/130] create listings page --- client/src/pages/Listings.jsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 client/src/pages/Listings.jsx diff --git a/client/src/pages/Listings.jsx b/client/src/pages/Listings.jsx new file mode 100644 index 000000000..d36e74767 --- /dev/null +++ b/client/src/pages/Listings.jsx @@ -0,0 +1,13 @@ +import React from "react"; +import "./listings.css"; +import ListingsContainer from "../containers/ListingsContainer"; + +const Listings = ({ data }) => { + return ( +
+ +
+ ); +}; + +export default Listings; From 0a324aa9c6417bbafef6a2abb7576b0d0cc0b942 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 5 Nov 2023 20:22:14 -0500 Subject: [PATCH 035/130] show listings in container --- client/src/containers/ListingsContainer.jsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 client/src/containers/ListingsContainer.jsx diff --git a/client/src/containers/ListingsContainer.jsx b/client/src/containers/ListingsContainer.jsx new file mode 100644 index 000000000..4c80f8a6c --- /dev/null +++ b/client/src/containers/ListingsContainer.jsx @@ -0,0 +1,16 @@ +import React from "react"; +import ListingCard from "../components/ListingCard"; + +const ListingsContainer = ({ data }) => { + return ( +
+ {data.map((listing) => ( +
+ +
+ ))} +
+ ); +}; + +export default ListingsContainer; From 669634efc16e9f89782a7689603c945b24bfa22a Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 5 Nov 2023 20:22:32 -0500 Subject: [PATCH 036/130] create cards and carousels for each listing --- client/src/components/ListingCard.jsx | 54 ++++++++++++++++++ client/src/components/ListingCarousel.jsx | 69 +++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 client/src/components/ListingCard.jsx create mode 100644 client/src/components/ListingCarousel.jsx diff --git a/client/src/components/ListingCard.jsx b/client/src/components/ListingCard.jsx new file mode 100644 index 000000000..d0b955858 --- /dev/null +++ b/client/src/components/ListingCard.jsx @@ -0,0 +1,54 @@ +import React from "react"; +import ListingCarousel from "./ListingCarousel"; +import { BsFillStarFill } from "react-icons/bs"; +import { format, isSameMonth } from "date-fns"; + +const ListingCard = ({ listing }) => { + const formattedAvailability = listing.availability.map((item) => { + const startDate = new Date(item.start_availability); + const endDate = new Date(item.end_availability); + + const startMonth = format(startDate, "MMM"); // Format month as a 3-letter abbreviation + const endMonth = format(endDate, "MMM"); + + let formattedDate; + + if (isSameMonth(startDate, endDate)) { + formattedDate = `${startMonth} ${startDate.getDate()}-${endDate.getDate()}`; + } else { + formattedDate = `${startMonth} ${startDate.getDate()} - ${endMonth} ${endDate.getDate()}`; + } + + return formattedDate; + }); + + return ( +
+ + + +
+
+
+ {listing.city}, {listing.state} +
+
+ {listing.rating} +
+
+
+ + {formattedAvailability.join(", ")} + +
+
+ + {listing.price_per_night} per night + +
+
+
+ ); +}; + +export default ListingCard; diff --git a/client/src/components/ListingCarousel.jsx b/client/src/components/ListingCarousel.jsx new file mode 100644 index 000000000..15bf8fe24 --- /dev/null +++ b/client/src/components/ListingCarousel.jsx @@ -0,0 +1,69 @@ +import React, { useEffect, useState } from "react"; +import { TbChevronCompactLeft, TbChevronCompactRight } from "react-icons/tb"; +import { RxDotFilled } from "react-icons/rx"; + +const ListingCarousel = ({ images }) => { + const [currentIndex, setCurrentIndex] = useState(0); + + const prevSlide = () => { + const isFirstImage = currentIndex === 0; + const newIndex = isFirstImage ? images.length - 1 : currentIndex - 1; + setCurrentIndex(newIndex); + }; + + const nextSlide = () => { + const isLastImage = currentIndex === images.length - 1; + const newIndex = isLastImage ? 0 : currentIndex + 1; + setCurrentIndex(newIndex); + }; + + const goToImage = (imageIndex) => { + setCurrentIndex(imageIndex); + }; + + if (images) { + console.log(images[currentIndex].image_url); + } + + return ( +
+
+ {/* Left Arrow */} +
+ +
+ {/* Right Arrow */} +
+ +
+
+
+ {images.map((image, imageIndex) => ( +
goToImage(imageIndex)} + className="px-2 text-2xl cursor-pointer" + > + +
+ ))} +
+
+ ); +}; + +export default ListingCarousel; From 14b81ced66cd41df05168fe03924d02ac7bbe4b2 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 5 Nov 2023 20:22:57 -0500 Subject: [PATCH 037/130] add listing page route to app --- client/src/App.jsx | 86 ++++++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 29 deletions(-) diff --git a/client/src/App.jsx b/client/src/App.jsx index b8b8473a3..02a1343e0 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -1,35 +1,63 @@ -import { useState } from 'react' -import reactLogo from './assets/react.svg' -import viteLogo from '/vite.svg' -import './App.css' +import React, { useEffect, useState } from "react"; +import { useRoutes } from "react-router-dom"; +import stayvueLogo from "./assets/StayVue.png"; +import Listings from "./pages/Listings"; +import { Link } from "react-router-dom"; +import "./App.css"; function App() { - const [count, setCount] = useState(0) + const [listings, setListings] = useState([]); + const API_URL = "http://localhost:3001"; + + useEffect(() => { + const fetchListings = async () => { + const response = await fetch(`${API_URL}/api`); + const data = await response.json(); + setListings(data); + }; + fetchListings(); + }, []); + + // Sets up routes + let element = useRoutes([ + { + path: "/", + element: ( + // user && user.id ? ( + + ), + // ) : ( + // + // ), + }, + ]); return ( - <> - -

Vite + React

-
- -

- Edit src/App.jsx and save to test HMR -

-
-

- Click on the Vite and React logos to learn more -

- - ) +
+
+
+ StayVue + +
+
+ {element} +
+ ); } -export default App +export default App; From ec1d8d258e6c4619a643c3a9a5c0a8c9d90fd3d3 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 5 Nov 2023 20:23:22 -0500 Subject: [PATCH 038/130] logo assets --- client/public/StayVue-2.png | Bin 0 -> 23307 bytes client/src/assets/StayVue-3.png | Bin 0 -> 21253 bytes client/src/assets/StayVue.png | Bin 0 -> 10270 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 client/public/StayVue-2.png create mode 100644 client/src/assets/StayVue-3.png create mode 100644 client/src/assets/StayVue.png diff --git a/client/public/StayVue-2.png b/client/public/StayVue-2.png new file mode 100644 index 0000000000000000000000000000000000000000..b6d8463dd02147b13a7af75e4e1143ba87d197ea GIT binary patch literal 23307 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 literal 0 HcmV?d00001 diff --git a/client/src/assets/StayVue-3.png b/client/src/assets/StayVue-3.png new file mode 100644 index 0000000000000000000000000000000000000000..bd74d7fb0d93af38146ed363dcd9403108c3d405 GIT binary patch literal 21253 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 ZK&tj0{`Px=lyv|BNJ~u*Qmq1u{15v#S*8F0 literal 0 HcmV?d00001 From 0ea03eb176969a32255eabc91964a3995be1c962 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 5 Nov 2023 20:23:36 -0500 Subject: [PATCH 039/130] add react router dom --- client/src/main.jsx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/client/src/main.jsx b/client/src/main.jsx index 54b39dd1d..8a91f187d 100644 --- a/client/src/main.jsx +++ b/client/src/main.jsx @@ -1,10 +1,13 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' -import App from './App.jsx' -import './index.css' +import React from "react"; +import ReactDOM from "react-dom/client"; +import { BrowserRouter } from "react-router-dom"; +import App from "./App.jsx"; +import "./index.css"; -ReactDOM.createRoot(document.getElementById('root')).render( +ReactDOM.createRoot(document.getElementById("root")).render( - - , -) + + + + +); From f27d61eb0f2dda7c60d1eb0be132a6cb1e622f94 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 5 Nov 2023 20:23:52 -0500 Subject: [PATCH 040/130] install dependencies for date formatting and icons --- client/src/assets/react.svg | 1 - 1 file changed, 1 deletion(-) delete mode 100644 client/src/assets/react.svg diff --git a/client/src/assets/react.svg b/client/src/assets/react.svg deleted file mode 100644 index 6c87de9bb..000000000 --- a/client/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file From f65d1dc7f1f1c1fb6a4c749e649c106f416dd75e Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 5 Nov 2023 20:38:05 -0500 Subject: [PATCH 041/130] Update README.md complete listings feature --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9e9cd2ef5..5f3677ba0 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,14 @@ Backend: NodeJS, Express, PostgreSQL, Socket.io, Passport.js ## Features +### Listings + +- [x] Users can browse the many listings offered at StayVue through our hosts. + +
+Video Walkthrough +
+ ### Accommodation Search Users can search for accommodations based on location, dates, and preferences. @@ -32,7 +40,7 @@ Users can search for accommodations based on location, dates, and preferences. ### Detailed Accommodation Listings -sers can view detailed property listings with descriptions, photos, amenities, and reviews. +Users can view detailed property listings with descriptions, photos, amenities, and reviews. [gif goes here] @@ -86,6 +94,9 @@ Hosts can set cancellation policies for their properties. [instructions go here] + +GIFs created with
Gifcap + ### [ADDITIONAL FEATURES GO HERE - ADD ALL FEATURES HERE IN THE FORMAT ABOVE; you will check these off and add gifs as you complete them] ## Installation Instructions From 6ceca35c995986957ee235a09b1d0929c7504301 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:11:28 -0500 Subject: [PATCH 042/130] add search icon --- client/src/assets/search.png | Bin 0 -> 3075 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 client/src/assets/search.png diff --git a/client/src/assets/search.png b/client/src/assets/search.png new file mode 100644 index 0000000000000000000000000000000000000000..5ca418eb0cd4f6ba77f5330f0be2e4cafc7e8cbf GIT binary patch literal 3075 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 Date: Mon, 6 Nov 2023 21:11:45 -0500 Subject: [PATCH 043/130] create navbar --- client/src/components/Navbar.jsx | 74 ++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 client/src/components/Navbar.jsx diff --git a/client/src/components/Navbar.jsx b/client/src/components/Navbar.jsx new file mode 100644 index 000000000..d7de88726 --- /dev/null +++ b/client/src/components/Navbar.jsx @@ -0,0 +1,74 @@ +import React, { useState } from "react"; +import { Link } from "react-router-dom"; +import stayvueLogo from "../assets/StayVue.png"; +import search from "../assets/search.png"; +import LoginModal from "./LoginModal"; +import DropdownMenu from "./DropdownMenu"; + +const Navbar = ({ isModalOpen, setIsModalOpen }) => { + const [isDropdownOpen, setIsDropdownOpen] = useState(false); + + const handleButtonClick = (label) => { + // Add your logic here to handle button clicks + }; + + const toggleDropdown = () => { + if (!isModalOpen) { + setIsDropdownOpen(!isDropdownOpen); + } + }; + + const toggleLoginModal = () => { + setIsModalOpen(!isModalOpen); + console.log("MODAL open"); + }; + + return ( + + ); +}; + +export default Navbar; From 62e11acb0b237ed6f7f22a83d0e047f7377d5ed8 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:11:57 -0500 Subject: [PATCH 044/130] make login modal --- client/src/components/LoginModal.jsx | 321 +++++++++++++++++++++++++++ 1 file changed, 321 insertions(+) create mode 100644 client/src/components/LoginModal.jsx diff --git a/client/src/components/LoginModal.jsx b/client/src/components/LoginModal.jsx new file mode 100644 index 000000000..be58035f7 --- /dev/null +++ b/client/src/components/LoginModal.jsx @@ -0,0 +1,321 @@ +import React, { useEffect, useState } from "react"; + +const LoginModal = ({ toggleLoginModal }) => { + const [isRegistering, setIsRegistering] = useState(false); + return isRegistering ? ( + + ) : ( + + ); +}; + +export default LoginModal; From b4495e50ff45e622ff5e10da9ab4e72ec2a57a45 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:12:09 -0500 Subject: [PATCH 045/130] create dropdown menu --- client/src/components/DropdownMenu.jsx | 73 ++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 client/src/components/DropdownMenu.jsx diff --git a/client/src/components/DropdownMenu.jsx b/client/src/components/DropdownMenu.jsx new file mode 100644 index 000000000..765ced875 --- /dev/null +++ b/client/src/components/DropdownMenu.jsx @@ -0,0 +1,73 @@ +import React from "react"; +import { RxAvatar, RxDropdownMenu } from "react-icons/rx"; + +const DropdownMenu = ({ toggleDropdown, toggleLoginModal, isDropdownOpen }) => { + return ( +
+
+ + + {isDropdownOpen && ( +
+
+
Bonnie Green
+
name@flowbite.com
+
+
+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+
+ +
+
+ )} +
+
+ ); +}; + +export default DropdownMenu; From f4f9e8ce7455e5b68741a60397f43f8211d7cc7f Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:12:37 -0500 Subject: [PATCH 046/130] remove output because postcss :) --- client/index.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/index.html b/client/index.html index 5337b1764..e89cc4c66 100644 --- a/client/index.html +++ b/client/index.html @@ -2,9 +2,8 @@ - + - StayVue From bd0c2af37a893916f1d759296a3b918bafa14f0c Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:12:56 -0500 Subject: [PATCH 047/130] remove unneccessary css --- client/src/App.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/src/App.css b/client/src/App.css index 4695c1c0a..c5e0a7a43 100644 --- a/client/src/App.css +++ b/client/src/App.css @@ -11,6 +11,10 @@ body { background-color: #fffffe; } +.button { + background-color: #ff5470; +} + .container { position: fixed; display: flex; From 652d80f41e15710b2c86e920266bf178aefecb37 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:13:07 -0500 Subject: [PATCH 048/130] re-init tailwind: --- client/tailwind.config.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/client/tailwind.config.js b/client/tailwind.config.js index a37d3934f..fc7f340d2 100644 --- a/client/tailwind.config.js +++ b/client/tailwind.config.js @@ -1,8 +1,18 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ["./src/**/*.{html,js,jsx}"], + content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], theme: { - extend: {}, + extend: { + backgroundColor: { + "button-color": "#ff5470", + "login-color": "#fde24f", + }, + }, + }, + variants: { + extend: { + backgroundColor: ["hover"], + }, }, plugins: [], }; From 28a8597c09c61c463f388d2abdac945c4c8accfe Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:13:24 -0500 Subject: [PATCH 049/130] add navbar component --- client/src/pages/Listings.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/pages/Listings.jsx b/client/src/pages/Listings.jsx index d36e74767..162c9b24f 100644 --- a/client/src/pages/Listings.jsx +++ b/client/src/pages/Listings.jsx @@ -1,10 +1,9 @@ import React from "react"; -import "./listings.css"; import ListingsContainer from "../containers/ListingsContainer"; const Listings = ({ data }) => { return ( -
+
); From 8e607c2eaaf8a86efbdf8c4b1c2ac67c2a21c3a2 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:13:39 -0500 Subject: [PATCH 050/130] begin passport init --- server/server.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/server/server.js b/server/server.js index cc887d426..7bbd7d97f 100644 --- a/server/server.js +++ b/server/server.js @@ -5,8 +5,8 @@ import listingsRoutes from "./routes/listings.js"; // import activityRoutes from "./routes/activities.js"; // import destinationRoutes from "./routes/destinations.js"; // import tripDestinationRoutes from "./routes/trips_destinations.js"; -// import authRoutes from "./routes/auth.js"; -// import passport from "passport"; +import authRoutes from "./routes/auth.js"; +import passport from "passport"; // import session from "express-session"; // import { GitHub } from "./config/auth.js"; import "./config/dotenv.js"; @@ -47,8 +47,7 @@ app.use(cors()); app.get("/", (req, res) => { res.redirect("http://localhost:3000"); }); - -// app.use("/auth", authRoutes); +app.use("/auth", authRoutes); // app.use("/api/trips", tripRoutes); // app.use("/api/activities", activityRoutes); // app.use("/api/destinations", destinationRoutes); From f809ba25318a0498292ddac752f93bebc9989b3e Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:13:47 -0500 Subject: [PATCH 051/130] postcss --- client/postcss.config.js | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 client/postcss.config.js diff --git a/client/postcss.config.js b/client/postcss.config.js new file mode 100644 index 000000000..2e7af2b7f --- /dev/null +++ b/client/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} From ca229de965de22dde6c69c01e25170ef6fb56394 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:14:00 -0500 Subject: [PATCH 052/130] create login controller --- server/controllers/login.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 server/controllers/login.js diff --git a/server/controllers/login.js b/server/controllers/login.js new file mode 100644 index 000000000..21f466411 --- /dev/null +++ b/server/controllers/login.js @@ -0,0 +1,30 @@ +import { pool } from "../config/database.js"; + +import bcrypt from "bcrypt"; + +const emailExists = async (email) => { + const data = await pool.query("SELECT * FROM users WHERE email=$1", [email]); + + if (data.rowCount == 0) return false; + return data.rows[0]; +}; + +const createUser = async (email, password) => { + const salt = await bcrypt.genSalt(10); + const hash = await bcrypt.hash(password, salt); + + const data = await pool.query( + "INSERT INTO users(email, password) VALUES ($1, $2) RETURNING id, email, password", + [email, hash] + ); + + if (data.rowCount == 0) return false; + return data.rows[0]; +}; + +const matchPassword = async (password, hashPassword) => { + const match = await bcrypt.compare(password, hashPassword); + return match; +}; + +export default { emailExists, createUser, matchPassword }; From ac0fc9457430ca9af07eb7c16f9524699aab73b0 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:14:14 -0500 Subject: [PATCH 053/130] auth routes --- server/routes/auth.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 server/routes/auth.js diff --git a/server/routes/auth.js b/server/routes/auth.js new file mode 100644 index 000000000..d5fb9e5df --- /dev/null +++ b/server/routes/auth.js @@ -0,0 +1,24 @@ +import express from "express"; +import passport from "passport"; + +const router = express.Router(); + +router.post( + "/login", + passport.authenticate("local-login", { session: false }), + (req, res, next) => { + res.json({ user: req.user }); + } +); + +router.post( + "/signup", + passport.authenticate("local-signup", { session: false }), + (req, res, next) => { + res.json({ + user: req.user, + }); + } +); + +export default router; From d04f336ac7e83ec465aedbc03565eba139f53b58 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:14:30 -0500 Subject: [PATCH 054/130] make navbar a component --- client/src/App.jsx | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/client/src/App.jsx b/client/src/App.jsx index 02a1343e0..ad4a8ef62 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -4,9 +4,11 @@ import stayvueLogo from "./assets/StayVue.png"; import Listings from "./pages/Listings"; import { Link } from "react-router-dom"; import "./App.css"; +import Navbar from "./components/Navbar"; function App() { const [listings, setListings] = useState([]); + const [isModalOpen, setIsModalOpen] = useState(false); const API_URL = "http://localhost:3001"; useEffect(() => { @@ -22,40 +24,20 @@ function App() { let element = useRoutes([ { path: "/", - element: ( - // user && user.id ? ( - - ), - // ) : ( - // - // ), + element: , }, ]); return (
-
- StayVue - -
+
- {element} +
+ {element} +
); } From 97215669cf1cabc0fc72779da5261a7215c6e219 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:14:43 -0500 Subject: [PATCH 055/130] edit layout --- client/src/components/ListingCarousel.jsx | 31 +++++++++++++++-------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/client/src/components/ListingCarousel.jsx b/client/src/components/ListingCarousel.jsx index 15bf8fe24..8121cfc73 100644 --- a/client/src/components/ListingCarousel.jsx +++ b/client/src/components/ListingCarousel.jsx @@ -5,19 +5,22 @@ import { RxDotFilled } from "react-icons/rx"; const ListingCarousel = ({ images }) => { const [currentIndex, setCurrentIndex] = useState(0); - const prevSlide = () => { + const prevSlide = (e) => { + e.preventDefault(); const isFirstImage = currentIndex === 0; const newIndex = isFirstImage ? images.length - 1 : currentIndex - 1; setCurrentIndex(newIndex); }; - const nextSlide = () => { + const nextSlide = (e) => { + e.preventDefault(); const isLastImage = currentIndex === images.length - 1; const newIndex = isLastImage ? 0 : currentIndex + 1; setCurrentIndex(newIndex); }; - const goToImage = (imageIndex) => { + const goToImage = (e, imageIndex) => { + e.preventDefault(); setCurrentIndex(imageIndex); }; @@ -26,7 +29,7 @@ const ListingCarousel = ({ images }) => { } return ( -
+
{ alignItems: "center", // Center icons vertically position: "relative", // Ensure the div is positioned for z-index }} - className="w-full duration-500" + className="w-full duration-500 bg-slate-400" > {/* Left Arrow */} -
- +
+
{/* Right Arrow */} -
- +
+
{images.map((image, imageIndex) => (
goToImage(imageIndex)} - className="px-2 text-2xl cursor-pointer" + onClick={(e) => goToImage(e, imageIndex)} + className="text-2xl cursor-pointer" >
From 9c3b2ea9190b8ad84c7d1ead45f4251e36319f9e Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:14:56 -0500 Subject: [PATCH 056/130] install depednencies --- client/package-lock.json | 143 +++++++++++++++++++++++++++++++--- client/package.json | 5 ++ client/public/vite.svg | 1 - client/src/pages/listings.css | 5 -- server/package-lock.json | 49 ++++++++++++ server/package.json | 3 + 6 files changed, 191 insertions(+), 15 deletions(-) delete mode 100644 client/public/vite.svg delete mode 100644 client/src/pages/listings.css diff --git a/client/package-lock.json b/client/package-lock.json index e7735b267..19abf2fdf 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -10,9 +10,12 @@ "dependencies": { "@reduxjs/toolkit": "^1.9.7", "axios": "^1.6.0", + "date-fns": "^2.30.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-icons": "^4.11.0", "react-redux": "^8.1.3", + "react-router-dom": "^6.18.0", "redux": "^4.2.1", "redux-logger": "^3.0.6", "redux-persist": "^6.0.0", @@ -22,10 +25,12 @@ "@types/react": "^18.2.15", "@types/react-dom": "^18.2.7", "@vitejs/plugin-react": "^4.0.3", + "autoprefixer": "^10.4.16", "eslint": "^8.45.0", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.3", + "postcss": "^8.4.31", "tailwindcss": "^3.3.5", "vite": "^4.4.5" } @@ -964,6 +969,14 @@ } } }, + "node_modules/@remix-run/router": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.11.0.tgz", + "integrity": "sha512-BHdhcWgeiudl91HvVa2wxqZjSHbheSgIiDvxrF1VjFzBzpTtuDPkOdOi3Iqvc08kXtFkLjhbS+ML9aM8mJS+wQ==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@types/babel__core": { "version": "7.20.3", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.3.tgz", @@ -1278,6 +1291,43 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, + "node_modules/autoprefixer": { + "version": "10.4.16", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz", + "integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.21.10", + "caniuse-lite": "^1.0.30001538", + "fraction.js": "^4.3.6", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -1552,6 +1602,21 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -2128,9 +2193,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -2277,6 +2342,19 @@ "node": ">= 6" } }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2961,9 +3039,9 @@ } }, "node_modules/jiti": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.20.0.tgz", - "integrity": "sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", "dev": true, "bin": { "jiti": "bin/jiti.js" @@ -3230,6 +3308,15 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -3707,6 +3794,14 @@ "react": "^18.2.0" } }, + "node_modules/react-icons": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.11.0.tgz", + "integrity": "sha512-V+4khzYcE5EBk/BvcuYRq6V/osf11ODUM2J8hg2FDSswRrGvqiYUYPRy4OdrWaQOBj4NcpJfmHZLNaD+VH0TyA==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -3764,6 +3859,36 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.18.0.tgz", + "integrity": "sha512-vk2y7Dsy8wI02eRRaRmOs9g2o+aE72YCx5q9VasT1N9v+lrdB79tIqrjMfByHiY5+6aYkH2rUa5X839nwWGPDg==", + "dependencies": { + "@remix-run/router": "1.11.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.18.0.tgz", + "integrity": "sha512-Ubrue4+Ercc/BoDkFQfc6og5zRQ4A8YxSO3Knsne+eRbZ+IepAsK249XBH/XaFuOYOYr3L3r13CXTLvYt5JDjw==", + "dependencies": { + "@remix-run/router": "1.11.0", + "react-router": "6.18.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -4655,9 +4780,9 @@ "dev": true }, "node_modules/yaml": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz", - "integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "dev": true, "engines": { "node": ">= 14" diff --git a/client/package.json b/client/package.json index 97fc51ddb..362d80126 100644 --- a/client/package.json +++ b/client/package.json @@ -12,9 +12,12 @@ "dependencies": { "@reduxjs/toolkit": "^1.9.7", "axios": "^1.6.0", + "date-fns": "^2.30.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-icons": "^4.11.0", "react-redux": "^8.1.3", + "react-router-dom": "^6.18.0", "redux": "^4.2.1", "redux-logger": "^3.0.6", "redux-persist": "^6.0.0", @@ -24,10 +27,12 @@ "@types/react": "^18.2.15", "@types/react-dom": "^18.2.7", "@vitejs/plugin-react": "^4.0.3", + "autoprefixer": "^10.4.16", "eslint": "^8.45.0", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.3", + "postcss": "^8.4.31", "tailwindcss": "^3.3.5", "vite": "^4.4.5" } diff --git a/client/public/vite.svg b/client/public/vite.svg deleted file mode 100644 index e7b8dfb1b..000000000 --- a/client/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/client/src/pages/listings.css b/client/src/pages/listings.css deleted file mode 100644 index 728d7c0d7..000000000 --- a/client/src/pages/listings.css +++ /dev/null @@ -1,5 +0,0 @@ -.listings-container { - height: 100vh; - margin-top: 8em; - margin-left: 4em; -} diff --git a/server/package-lock.json b/server/package-lock.json index 1098a8e40..fe3640c0c 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -9,10 +9,13 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "bcryptjs": "^2.4.3", "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", "nodemon": "^3.0.1", + "passport": "^0.6.0", + "passport-local": "^1.0.0", "pg": "^8.11.3" } }, @@ -55,6 +58,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -749,11 +757,52 @@ "node": ">= 0.8" } }, + "node_modules/passport": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", + "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, "node_modules/pg": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", diff --git a/server/package.json b/server/package.json index 4c53a9fba..f87155710 100644 --- a/server/package.json +++ b/server/package.json @@ -12,10 +12,13 @@ "author": "", "license": "ISC", "dependencies": { + "bcryptjs": "^2.4.3", "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", "nodemon": "^3.0.1", + "passport": "^0.6.0", + "passport-local": "^1.0.0", "pg": "^8.11.3" } } From d702e8b54d9d80fe59629892ab069136daae5766 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 10 Nov 2023 22:46:53 -0500 Subject: [PATCH 057/130] posting new listingimages, listing availability, get listing by id --- server/controllers/listings.js | 117 +++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/server/controllers/listings.js b/server/controllers/listings.js index 96e8c2762..eb10912ba 100644 --- a/server/controllers/listings.js +++ b/server/controllers/listings.js @@ -1,6 +1,10 @@ import { pool } from "../config/database.js"; +//get all listings that are currently advertised const getAllListings = async (request, response) => { + response.cookie("visited", true, { + maxAge: 1000 * 60 * 60 * 24 * 7, + }); try { const query = ` SELECT @@ -27,6 +31,119 @@ const getAllListings = async (request, response) => { } }; +//get all listings that specific user currently has advertised +const getUserListings = async (request, response) => { + try { + const id = parseInt(request.params.id); + const results = await pool.query( + "SELECT listings.* FROM users JOIN listings ON users.id = listings.user_id WHERE users.id = $1", + [id] + ); + response.status(200).json(results.rows); + } catch (error) { + response.status(409).json({ error: error.message }); + } +}; + +//get single listing +const getListingById = async (request, response) => { + console.log(request.cookies); + try { + const id = parseInt(request.params.id); + const results = await pool.query("SELECT * FROM listings WHERE id = $1", [ + id, + ]); + response.status(200).json(results.rows); + } catch (error) { + response.status(409).json({ error: error.message }); + } +}; + +//create a new listing +const postNewListing = async (request, response) => { + try { + const propertyId = parseInt(request.params.id); + const { title, pricePerNight } = request.body; + // const propertyExists = await pool.query( + // "SELECT * FROM properties WHERE id = $1", + // [propertyId] + // ); + // if (propertyExists.rowCount === 0) { + // const newProperty = await pool.query(`INSERT INTO properties (host_id, address1, address2, city, state, country, zipcode, rating, num_beds, num_baths, num_bedrooms, property_type) VALUES ($1, $2, $3, $4, $5, $6) RETURNING *`, [propertyId, title, pricePerNight, images, amenities, availability]); + + // } + // else { + // } + const newListing = await pool.query( + `INSERT INTO listings (title, property_id, price_per_night) VALUES ($1, $2, $3) RETURNING *`, + [title, propertyId, pricePerNight] + ); + response.status(201).json(newListing.rows[0]); + } catch (error) { + response.status(409).json({ error: error.message }); + } +}; + +//add images to a listing +const postNewListingImages = async (request, response) => { + try { + const propertyId = parseInt(request.params.id); + const { images } = request.body; + + for (let image of images) { + try { + const newImage = await pool.query( + `INSERT INTO listingImages (property_id, image_url) VALUES ($1, $2) RETURNING *`, + [propertyId, image] + ); + response.status(201).json(newImage.rows[0]); + } catch (error) { + response.status(409).json({ error: error.message }); + } + } + } catch (error) { + response.status(409).json({ error: error.message }); + } +}; + +//add availability to a new listing +const postNewListingAvailability = async (request, response) => { + try { + const listingId = parseInt(request.params.id); + const { startAvailability, endAvailability } = request.body; + const newAvailability = await pool.query( + `INSERT INTO listingAvailability (listing_id, start_availability, end_availability) VALUES ($1, $2, $3) RETURNING *`, + [listingId, startAvailability, endAvailability] + ); + response.status(201).json(newAvailability.rows[0]); + } catch (error) { + response.status(409).json({ error: error.message }); + } +}; +// const propertyExists = await pool.query( +// "SELECT * FROM properties WHERE id = $1", +// [propertyId] +// ); +// if (propertyExists.rowCount === 0) { +// const newProperty = await pool.query(`INSERT INTO properties (host_id, address1, address2, city, state, country, zipcode, rating, num_beds, num_baths, num_bedrooms, property_type) VALUES ($1, $2, $3, $4, $5, $6) RETURNING *`, [propertyId, title, pricePerNight, images, amenities, availability]); + +// } +// else { +// } +// const newListing = await pool.query( +// `INSERT INTO listings (title, property_id, price_per_night) VALUES ($1, $2, $3) RETURNING *`, +// [title, propertyId, pricePerNight] +// ); +// response.status(201).json(newListing.rows[0]); +// } catch (error) { +// response.status(409).json({ error: error.message }); +// } +// }; export default { getAllListings, + getUserListings, + getListingById, + postNewListing, + postNewListingAvailability, + postNewListingImages, }; From cd8f9de0270dfcf4a88c3c108ef5944dca5d8ddb Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 10 Nov 2023 22:47:27 -0500 Subject: [PATCH 058/130] remove null restraints for registration user --- server/config/reset.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/config/reset.js b/server/config/reset.js index 2a1da5f6e..158372075 100644 --- a/server/config/reset.js +++ b/server/config/reset.js @@ -39,11 +39,11 @@ const createUsersTable = async () => { id SERIAL PRIMARY KEY, first_name VARCHAR(50) NOT NULL, last_name VARCHAR(50) NOT NULL, - address1 VARCHAR(255) NOT NULL, + address1 VARCHAR(255), address2 VARCHAR(255), - city VARCHAR(255) NOT NULL, - state VARCHAR(255) NOT NULL, - country VARCHAR(255) NOT NULL, + city VARCHAR(255), + state VARCHAR(255), + country VARCHAR(255), zipcode VARCHAR(255) NOT NULL, phone VARCHAR(50) NOT NULL, user_name VARCHAR(50) UNIQUE NOT NULL, From 9ff7c688b6fefbadb413cee39deb8928efba8292 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 10 Nov 2023 22:47:58 -0500 Subject: [PATCH 059/130] add routes for auth --- server/routes/auth.js | 94 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 15 deletions(-) diff --git a/server/routes/auth.js b/server/routes/auth.js index d5fb9e5df..452311618 100644 --- a/server/routes/auth.js +++ b/server/routes/auth.js @@ -1,24 +1,88 @@ import express from "express"; import passport from "passport"; +import { pool } from "../config/database.js"; +import { comparePassword, hashPassword } from "../utils/helpers.js"; const router = express.Router(); -router.post( - "/login", - passport.authenticate("local-login", { session: false }), - (req, res, next) => { - res.json({ user: req.user }); - } -); +// router.post("/login", async (request, response) => { +// const { email, password } = request.body; +// if (!email || !password) { +// return response.status(400).json({ message: "Missing credentials" }); +// } +// try { +// const result = await pool.query(`SELECT * FROM users WHERE email = $1`, [ +// email, +// ]); +// if (!result.rows || result.rows.length === 0) { +// return response.status(401).json({ message: "Invalid credentials" }); +// } +// const user = result.rows[0]; +// const isValid = comparePassword(password, user.password); +// if (isValid) { +// request.session.user = user; +// return response.status(200).json({ message: "Logged in successfully" }); +// } else { +// return response.status(401).json({ message: "Invalid credentials" }); +// } +// } catch (error) { +// return response.status(500).json({ error: error.message }); +// } +// }); + +router.post('/login', passport.authenticate('local'), (request, response, next) => { + response.status(200).json({ message: 'Logged in successfully' }); +}) -router.post( - "/signup", - passport.authenticate("local-signup", { session: false }), - (req, res, next) => { - res.json({ - user: req.user, - }); +router.post("/register", async (request, response) => { + try { + const { + first_name, + last_name, + zipcode, + phone, + user_name, + email, + password, + } = request.body; + const user = await pool.query(`SELECT * FROM users WHERE email = $1`, [ + email, + ]); + if (user.rows > 0) { + response.status(400).json({ message: "User already exists" }); + } else { + const hashedPassword = hashPassword(password); + try { + const newUser = await pool.query( + `INSERT INTO users (first_name, last_name, zipcode, phone, user_name, email, password) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING *`, + [ + first_name, + last_name, + zipcode, + phone, + user_name, + email, + hashedPassword, + ] + ); + response.status(201).json(newUser.rows[0]); + } catch (error) { + response.status(500).json({ error: error.message }); + } + } + } catch (error) { + response.status(500).json({ error: error.message }); } -); +}); + +// router.post( +// "/signup", +// passport.authenticate("local-signup", { session: false }), +// (req, res, next) => { +// res.json({ +// user: req.user, +// }); +// } +// ); export default router; From 39e1613f4fc74bcefdf68b26ab32d47e4bfea89f Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 10 Nov 2023 22:48:27 -0500 Subject: [PATCH 060/130] routes for listings --- server/routes/listings.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/server/routes/listings.js b/server/routes/listings.js index f13161cd9..13e39e1a5 100644 --- a/server/routes/listings.js +++ b/server/routes/listings.js @@ -5,5 +5,18 @@ import ListingsController from "../controllers/listings.js"; const router = express.Router(); router.get("/", ListingsController.getAllListings); +router.get("/:id", ListingsController.getListingById); + +router.get("/listings", (request, response) => {}); +router.post("/listings/:propertyId", ListingsController.postNewListing); +router.get("/listings/:userId/all", ListingsController.getUserListings); +router.post( + "/listings/images/:userId", + ListingsController.postNewListingImages +); +router.post( + "/listings/availability/:listingId", + ListingsController.postNewListingAvailability +); export default router; From 335ce4ad9fe1f6de4835a0187aa866071d513588 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 10 Nov 2023 22:48:44 -0500 Subject: [PATCH 061/130] passport and sessions --- server/server.js | 71 ++++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/server/server.js b/server/server.js index 7bbd7d97f..b6c82f83f 100644 --- a/server/server.js +++ b/server/server.js @@ -1,60 +1,67 @@ import express from "express"; import cors from "cors"; import listingsRoutes from "./routes/listings.js"; -// import tripRoutes from "./routes/trips.js"; -// import activityRoutes from "./routes/activities.js"; -// import destinationRoutes from "./routes/destinations.js"; -// import tripDestinationRoutes from "./routes/trips_destinations.js"; +import propertiesRoutes from "./routes/properties.js"; import authRoutes from "./routes/auth.js"; import passport from "passport"; -// import session from "express-session"; +import session from "express-session"; // import { GitHub } from "./config/auth.js"; import "./config/dotenv.js"; +import cookieParser from "cookie-parser"; +import "./strategies/local.js"; const app = express(); +const PORT = process.env.PORT || 3001; +const memoryStore = new session.MemoryStore(); +app.use(express.json()); +app.use(cookieParser()); -// app.use( -// session({ -// secret: process.env.CLIENT_SECRET, //need random string in .env -// resave: false, -// saveUninitialized: true, -// }) -// ); +app.use( + session({ + secret: process.env.CLIENT_SECRET, + resave: false, + saveUninitialized: false, + store: memoryStore, + }) +); +// app.use(cors()); +app.use( + cors({ + origin: "http://localhost:3000", + methods: "GET,HEAD,PUT,PATCH,POST,DELETE", + credentials: true, + }) +); -app.use(express.json()); -app.use(cors()); -// app.use( -// cors({ -// origin: "http://localhost:3000", -// methods: "GET,HEAD,PUT,PATCH,POST,DELETE", -// credentials: true, -// }) -// ); - -// app.use(passport.initialize()); -// app.use(passport.session()); +app.use(passport.initialize()); +app.use(passport.session()); // passport.use(GitHub); //to implement own strategy, can these functions in a custom way -// passport.serializeUser((user, done) => { -// done(null, user); -// }); +passport.serializeUser((user, done) => { + done(null, user); +}); -// passport.deserializeUser((user, done) => { -// done(null, user); -// }); +passport.deserializeUser((user, done) => { + done(null, user); +}); app.get("/", (req, res) => { res.redirect("http://localhost:3000"); }); -app.use("/auth", authRoutes); + +app.use((req, res, next) => { + console.log("Incoming Request Body:", req.body); + next(); +}); // app.use("/api/trips", tripRoutes); // app.use("/api/activities", activityRoutes); // app.use("/api/destinations", destinationRoutes); // app.use("/api/trips-destinations", tripDestinationRoutes); app.use("/api", listingsRoutes); -const PORT = process.env.PORT || 3001; +app.use("/api/auth", authRoutes); +app.use("/api/properties", propertiesRoutes); app.listen(PORT, () => { console.log(`πŸš€ Server running on http://localhost:${PORT}`); From 84dae7022bbe733c87df6bb37a6abcb41aed7b1d Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 10 Nov 2023 22:49:01 -0500 Subject: [PATCH 062/130] properties controller --- server/controllers/properties.js | 129 +++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 server/controllers/properties.js diff --git a/server/controllers/properties.js b/server/controllers/properties.js new file mode 100644 index 000000000..ebb8ddae3 --- /dev/null +++ b/server/controllers/properties.js @@ -0,0 +1,129 @@ +import { pool } from "../config/database.js"; + +const getUserProperties = async (request, response) => { + try { + const userId = parseInt(request.params.id); + const properties = await pool.query( + "SELECT listings.*, ARRAY_AGG(listingsImages.image_url) AS image_urls, propertyAmenities.* FROM listings LEFT JOIN listingsImages ON listings.property_id = listingsImages.property_id JOIN propertyAmenities ON listings.property_id = propertyAmenities.property_id WHERE listings.user_id = $1 GROUP BY listings.id, propertyAmenities.property_id;", + [userId] + ); + response.status(200).json(properties.rows); + } catch (error) { + response.status(409).json({ error: error.message }); + } +}; + +//post a new property with its images and amenities +const postNewProperty = async (request, response) => { + try { + const hostId = parseInt(request.params.id); + const { + address1, + address2, + city, + state, + zipcode, + rating, + numBeds, + numBaths, + numBedrooms, + propertyType, + imagesArray, + amenitiesArray, + } = request.body; + + //add property to properties table + const property = await pool.query( + "INSERT INTO properties (host_id, address1, address2, city, state, zipcode, rating, num_beds, num_baths, num_bedrooms, property_type,) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING id", + [ + hostId, + address1, + address2, + city, + state, + zipcode, + rating, + numBeds, + numBaths, + numBedrooms, + propertyType, + ] + ); + + const propertyId = property.rows[0].id; + + const { + wifi, + dryer, + washer, + iron, + airConditioner, + heater, + poolAvailable, + grill, + hotTub, + freeParking, + evCharger, + beachFront, + waterFront, + mountainView, + cityView, + gym, + elevator, + wheelchairAccessilbe, + petFriendly, + smokingAllowed, + } = amenitiesArray; + + //add all amenities to propertyAmenities table + const addedAmenities = await pool.query( + "INSERT INTO propertyAmenities (property_id, wifi, dryer, washer, iron, air_conditioner, heater, pool, grill, hot_tub, free_parking, ev_charger, beach_front, water_front, mountain_view, city_view, gym, elevator, wheelchair_accessilbe, pet_friendly, smoking_allowed) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22) RETURNING *", + [ + wifi, + dryer, + washer, + iron, + airConditioner, + heater, + poolAvailable, + grill, + hotTub, + freeParking, + evCharger, + beachFront, + waterFront, + mountainView, + cityView, + gym, + elevator, + wheelchairAccessilbe, + petFriendly, + smokingAllowed, + ] + ); + //each image is an array of urls + for (image of imagesArray) { + try { + const addedImages = await pool.query( + "INSERT INTO listingsImages (property_id, image_url) VALUES ($1, $2) RETURNING *", + [propertyId, image] + ); + response.json(addedImages.rows[0]); + } catch (error) { + response.status(409).json({ error: error.message }); + } + } + response.status(200).json({ + property: property.rows[0], + amenities: addedAmenities.rows[0], + images: addedImages.rows[0], + }); + } catch (error) { + response.status(409).json({ error: error.message }); + } +}; + +export default { + getUserProperties, + postNewProperty, +}; From af452b4dc78540102c0fd5c5306ad1015257d684 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 10 Nov 2023 22:49:12 -0500 Subject: [PATCH 063/130] properties routes --- server/routes/properties.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 server/routes/properties.js diff --git a/server/routes/properties.js b/server/routes/properties.js new file mode 100644 index 000000000..c50f6aff0 --- /dev/null +++ b/server/routes/properties.js @@ -0,0 +1,10 @@ +import express from "express"; + +import PropertiesController from "../controllers/properties.js"; + +const router = express.Router(); + +router.get("/properties/:userId", PropertiesController.getUserProperties); +router.post("/properties/new/:userId", PropertiesController.postNewProperty); + +export default router; From eb5eaaf81a6918719ea75c81a8e46f1a3a42106b Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 10 Nov 2023 22:49:29 -0500 Subject: [PATCH 064/130] hashing password --- server/utils/helpers.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 server/utils/helpers.js diff --git a/server/utils/helpers.js b/server/utils/helpers.js new file mode 100644 index 000000000..5115c379b --- /dev/null +++ b/server/utils/helpers.js @@ -0,0 +1,18 @@ +import bcrypt from "bcrypt"; + +const saltRounds = 10; + +const hashPassword = (password) => { + console.log("hasing password"); + console.log(password); + const salt = bcrypt.genSaltSync(saltRounds); + return bcrypt.hashSync(password, salt); +}; + +const comparePassword = (raw, hash) => { + console.log(raw); + console.log(hash); + return bcrypt.compareSync(raw, hash); +}; + +export { hashPassword, comparePassword }; From d46a82a93abfda89c7a375fecc46941c1a95d307 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 10 Nov 2023 22:49:46 -0500 Subject: [PATCH 065/130] passport local strategy --- server/strategies/local.js | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 server/strategies/local.js diff --git a/server/strategies/local.js b/server/strategies/local.js new file mode 100644 index 000000000..4cdaea425 --- /dev/null +++ b/server/strategies/local.js @@ -0,0 +1,40 @@ +import passport from "passport"; +import { Strategy } from "passport-local"; +import { pool } from "../config/database.js"; +import { comparePassword } from "../utils/helpers.js"; + +passport.use( + new Strategy( + { + usernameField: "email", + }, + async (email, password, done) => { + console.log(email); + console.log(password); + try { + if (!email || !password) { + return response.status(400).json({ message: "Missing credentials" }); + } + const result = await pool.query( + `SELECT * FROM users WHERE email = $1`, + [email] + ); + if (!result.rows || result.rows.length === 0) { + return response.status(401).json({ message: "Invalid credentials" }); + } + const user = result.rows[0]; + const isValid = comparePassword(password, user.password); + if (isValid) { + console.log("authenticated successfully"); + done(null, user); + } else { + console.log("invalid credentials"); + done(null, null); + } + } catch (error) { + console.log(error); + done(error, null); + } + } + ) +); From 015069234dcaf8e14afd6541f5936eee76b9fc59 Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Fri, 10 Nov 2023 22:52:09 -0500 Subject: [PATCH 066/130] built some profile page backend --- server/controllers/profile.js | 44 +++++++++++++++++++++++++++++++++++ server/routes/profile.js | 8 +++++++ 2 files changed, 52 insertions(+) create mode 100644 server/controllers/profile.js create mode 100644 server/routes/profile.js diff --git a/server/controllers/profile.js b/server/controllers/profile.js new file mode 100644 index 000000000..dead720bf --- /dev/null +++ b/server/controllers/profile.js @@ -0,0 +1,44 @@ +import { pool } from "../config/database.js"; + +const updateUserProfile = (async(req, res) => { + try { + //get user data from the request + const { user } = req; + + //check if the user is authenticated. if they are not, then return a 401 unauthorized error + if (!user){ + return res.status(401).json({ error: 'Unauthorized' }); + } + + //access the users ID from the user object if it's stored in session or token + const userId = user.id; + + //verify the user is updating their own profile by checking the user ID + if(userId != req.params.userId) { + return res.status(403).json({ error: "Forbiden. You can only update your own profile."}) + } + + //update the users email: + const { newEmail } = req.body; //assuming the new email is sent in the request body + + //update user's email in the database: + const updateQuery = "UPDATE users SET email = $1 WHERE id = $2" + const updateValues = [newEmail, userId]; + + const result = await pool.query(updateQuery, updateValues) + + if(result.rowCount > 0) { + res.json({ message: "Profile updated successfully. "}) + } else { + res.status(500).json({ error: 'Profile update failed.' }) + } + + // res.json({ message: "Profile updated successfully." }) + } catch (error) { + res.status(500).json({ error: 'Internal server error '}) + } +}) + +export default { + updateUserProfile +} \ No newline at end of file diff --git a/server/routes/profile.js b/server/routes/profile.js new file mode 100644 index 000000000..780a92f84 --- /dev/null +++ b/server/routes/profile.js @@ -0,0 +1,8 @@ +import express from 'express'; +import updateUserProfile from '../controllers/profile.js' + +const router = express.Router(); + +router.put('/profile', ProfileController.updateUserProfile) + +export default router; \ No newline at end of file From 8a2b8dcb587e68dd2c004be30d910dd414e680b5 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 10 Nov 2023 22:57:26 -0500 Subject: [PATCH 067/130] download depedencies --- server/package-lock.json | 579 ++++++++++++++++++++++++++++++++++++++- server/package.json | 4 +- 2 files changed, 577 insertions(+), 6 deletions(-) diff --git a/server/package-lock.json b/server/package-lock.json index fe3640c0c..c9632624c 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -9,16 +9,51 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "bcryptjs": "^2.4.3", + "bcrypt": "^5.1.1", + "cookie-parser": "^1.4.6", "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", + "express-session": "^1.17.3", "nodemon": "^3.0.1", "passport": "^0.6.0", "passport-local": "^1.0.0", "pg": "^8.11.3" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -36,6 +71,46 @@ "node": ">= 0.6" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -48,6 +123,23 @@ "node": ">= 8" } }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -58,10 +150,18 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "node_modules/bcryptjs": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } }, "node_modules/binary-extensions": { "version": "2.2.0", @@ -169,11 +269,32 @@ "fsevents": "~2.3.2" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -201,6 +322,26 @@ "node": ">= 0.6" } }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -239,6 +380,11 @@ "node": ">= 0.4" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -256,6 +402,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "engines": { + "node": ">=8" + } + }, "node_modules/dotenv": { "version": "16.3.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", @@ -272,6 +426,11 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -334,6 +493,32 @@ "node": ">= 0.10.0" } }, + "node_modules/express-session": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", + "dependencies": { + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -378,6 +563,33 @@ "node": ">= 0.6" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -399,6 +611,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/get-intrinsic": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", @@ -413,6 +644,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -476,6 +726,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "node_modules/hasown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", @@ -502,6 +757,39 @@ "node": ">= 0.8" } }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -518,6 +806,15 @@ "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -550,6 +847,14 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -580,6 +885,28 @@ "node": ">=10" } }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -642,6 +969,48 @@ "node": "*" } }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -655,6 +1024,30 @@ "node": ">= 0.6" } }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/nodemon": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.1.tgz", @@ -717,6 +1110,17 @@ "node": ">=0.10.0" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -744,6 +1148,22 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/packet-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", @@ -793,6 +1213,14 @@ "node": ">= 0.4.0" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -963,6 +1391,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -985,6 +1421,19 @@ "node": ">= 0.8" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -996,6 +1445,20 @@ "node": ">=8.10.0" } }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1076,6 +1539,11 @@ "node": ">= 0.8.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "node_modules/set-function-length": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", @@ -1108,6 +1576,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, "node_modules/simple-update-notifier": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", @@ -1135,6 +1608,38 @@ "node": ">= 0.8" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -1146,6 +1651,22 @@ "node": ">=4" } }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -1176,6 +1697,11 @@ "nodetouch": "bin/nodetouch.js" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -1188,6 +1714,17 @@ "node": ">= 0.6" } }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", @@ -1201,6 +1738,11 @@ "node": ">= 0.8" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -1217,6 +1759,33 @@ "node": ">= 0.8" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/server/package.json b/server/package.json index f87155710..3a5934bff 100644 --- a/server/package.json +++ b/server/package.json @@ -12,10 +12,12 @@ "author": "", "license": "ISC", "dependencies": { - "bcryptjs": "^2.4.3", + "bcrypt": "^5.1.1", + "cookie-parser": "^1.4.6", "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", + "express-session": "^1.17.3", "nodemon": "^3.0.1", "passport": "^0.6.0", "passport-local": "^1.0.0", From ee5c620e829cbb2350f0122dc26d064eb6dafd0d Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 10 Nov 2023 23:47:08 -0500 Subject: [PATCH 068/130] fix redirect and cors origin --- server/server.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/server.js b/server/server.js index b6c82f83f..a018bcda9 100644 --- a/server/server.js +++ b/server/server.js @@ -27,7 +27,7 @@ app.use( // app.use(cors()); app.use( cors({ - origin: "http://localhost:3000", + origin: "http://localhost:5173", methods: "GET,HEAD,PUT,PATCH,POST,DELETE", credentials: true, }) @@ -47,7 +47,7 @@ passport.deserializeUser((user, done) => { }); app.get("/", (req, res) => { - res.redirect("http://localhost:3000"); + res.redirect("http://localhost:3001"); }); app.use((req, res, next) => { From 379a2ad525a251bcb676d6c326a11e0bb35d703e Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Fri, 10 Nov 2023 23:50:30 -0500 Subject: [PATCH 069/130] debugging backend connection errors --- client/.eslintrc.cjs | 3 +++ client/package-lock.json | 2 +- client/package.json | 2 +- client/src/App.jsx | 7 +++++-- client/src/PropTypes/props.js | 6 ++++++ client/src/components/ListingCarousel.jsx | 3 ++- client/src/pages/Listings.jsx | 6 ++++-- client/src/pages/Profiles.jsx | 9 +++++++++ 8 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 client/src/PropTypes/props.js create mode 100644 client/src/pages/Profiles.jsx diff --git a/client/.eslintrc.cjs b/client/.eslintrc.cjs index 4dcb43901..a44070760 100644 --- a/client/.eslintrc.cjs +++ b/client/.eslintrc.cjs @@ -6,6 +6,7 @@ module.exports = { 'plugin:react/recommended', 'plugin:react/jsx-runtime', 'plugin:react-hooks/recommended', + 'plugin:react/recommended' ], ignorePatterns: ['dist', '.eslintrc.cjs'], parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, @@ -15,6 +16,8 @@ module.exports = { 'react-refresh/only-export-components': [ 'warn', { allowConstantExport: true }, + ], }, } + diff --git a/client/package-lock.json b/client/package-lock.json index 19abf2fdf..aade7d156 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -27,7 +27,7 @@ "@vitejs/plugin-react": "^4.0.3", "autoprefixer": "^10.4.16", "eslint": "^8.45.0", - "eslint-plugin-react": "^7.32.2", + "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.3", "postcss": "^8.4.31", diff --git a/client/package.json b/client/package.json index 362d80126..2f1447245 100644 --- a/client/package.json +++ b/client/package.json @@ -29,7 +29,7 @@ "@vitejs/plugin-react": "^4.0.3", "autoprefixer": "^10.4.16", "eslint": "^8.45.0", - "eslint-plugin-react": "^7.32.2", + "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.3", "postcss": "^8.4.31", diff --git a/client/src/App.jsx b/client/src/App.jsx index ad4a8ef62..e53ffac09 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -1,10 +1,10 @@ import React, { useEffect, useState } from "react"; import { useRoutes } from "react-router-dom"; -import stayvueLogo from "./assets/StayVue.png"; import Listings from "./pages/Listings"; -import { Link } from "react-router-dom"; +import { BrowserRouter as Router, Route, Routes } from 'react-router-dom' import "./App.css"; import Navbar from "./components/Navbar"; +import Profiles from "./pages/Profiles"; function App() { const [listings, setListings] = useState([]); @@ -38,6 +38,9 @@ function App() { > {element}
+ + }/> +
); } diff --git a/client/src/PropTypes/props.js b/client/src/PropTypes/props.js new file mode 100644 index 000000000..75dddfab6 --- /dev/null +++ b/client/src/PropTypes/props.js @@ -0,0 +1,6 @@ +// prop-types.js +import PropTypes from 'prop-types'; + +export const listingPropTypes = { + data: PropTypes.array.isRequired, +}; diff --git a/client/src/components/ListingCarousel.jsx b/client/src/components/ListingCarousel.jsx index 8121cfc73..47a00962c 100644 --- a/client/src/components/ListingCarousel.jsx +++ b/client/src/components/ListingCarousel.jsx @@ -1,7 +1,8 @@ -import React, { useEffect, useState } from "react"; +import React, { useState } from "react"; import { TbChevronCompactLeft, TbChevronCompactRight } from "react-icons/tb"; import { RxDotFilled } from "react-icons/rx"; + const ListingCarousel = ({ images }) => { const [currentIndex, setCurrentIndex] = useState(0); diff --git a/client/src/pages/Listings.jsx b/client/src/pages/Listings.jsx index 162c9b24f..817105444 100644 --- a/client/src/pages/Listings.jsx +++ b/client/src/pages/Listings.jsx @@ -1,5 +1,6 @@ -import React from "react"; -import ListingsContainer from "../containers/ListingsContainer"; +// Listings.js +import React from 'react'; +import ListingsContainer from '../containers/ListingsContainer'; const Listings = ({ data }) => { return ( @@ -9,4 +10,5 @@ const Listings = ({ data }) => { ); }; + export default Listings; diff --git a/client/src/pages/Profiles.jsx b/client/src/pages/Profiles.jsx new file mode 100644 index 000000000..2afdc3d91 --- /dev/null +++ b/client/src/pages/Profiles.jsx @@ -0,0 +1,9 @@ +import React from 'react' + +function Profiles() { + return ( +
Profiles
+ ) +} + +export default Profiles \ No newline at end of file From 566d50970b98c9faac42350af4097e50dfcf6159 Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sat, 11 Nov 2023 00:34:54 -0500 Subject: [PATCH 070/130] designed ui of user information --- client/src/pages/Profiles.jsx | 71 +++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 4 deletions(-) diff --git a/client/src/pages/Profiles.jsx b/client/src/pages/Profiles.jsx index 2afdc3d91..c50c3f6a9 100644 --- a/client/src/pages/Profiles.jsx +++ b/client/src/pages/Profiles.jsx @@ -1,9 +1,72 @@ -import React from 'react' +import React from 'react'; function Profiles() { return ( -
Profiles
- ) +
+

User Info

+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ + {/* Add a button for updating the profile */} + + +

Listings

+
+ ); } -export default Profiles \ No newline at end of file +export default Profiles; From d9476f937f32d0fa2e237bb65c6ec3189ffceadf Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sat, 11 Nov 2023 01:50:30 -0500 Subject: [PATCH 071/130] completed ui for userprofile page --- client/src/components/DropdownMenu.jsx | 4 + client/src/pages/Profiles.jsx | 239 ++++++++++++++++++------- 2 files changed, 181 insertions(+), 62 deletions(-) diff --git a/client/src/components/DropdownMenu.jsx b/client/src/components/DropdownMenu.jsx index 765ced875..3bc86a5a9 100644 --- a/client/src/components/DropdownMenu.jsx +++ b/client/src/components/DropdownMenu.jsx @@ -1,5 +1,6 @@ import React from "react"; import { RxAvatar, RxDropdownMenu } from "react-icons/rx"; +import { Link } from 'react-router-dom' const DropdownMenu = ({ toggleDropdown, toggleLoginModal, isDropdownOpen }) => { return ( @@ -28,12 +29,15 @@ const DropdownMenu = ({ toggleDropdown, toggleLoginModal, isDropdownOpen }) => {
  • + + +
  • + +
-
- - -
-
+ {activeTab === 'user' && ( +
+

User Profile

+
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
- {/* Add a button for updating the profile */} - +
+ + +
-

Listings

-
- ); +
+
+ + +
+ +
+ + +
+
+ + + +
+ )} + + {activeTab === 'listings' &&

Listings

} + + {/* {activeTab === 'listings' && } */} + {/*
*/} + + +
+ ); } export default Profiles; From c09095555df6a6644f2d35486b97900b04d917b8 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 11 Nov 2023 15:05:48 -0500 Subject: [PATCH 072/130] add click handlers to switch between login and logout modals --- client/src/components/LoginModal.jsx | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/client/src/components/LoginModal.jsx b/client/src/components/LoginModal.jsx index be58035f7..d3760bd70 100644 --- a/client/src/components/LoginModal.jsx +++ b/client/src/components/LoginModal.jsx @@ -2,6 +2,15 @@ import React, { useEffect, useState } from "react"; const LoginModal = ({ toggleLoginModal }) => { const [isRegistering, setIsRegistering] = useState(false); + + const handleRegisterClick = () => { + setIsRegistering(true); + }; + + const handleLoginClick = () => { + setIsRegistering(false); + }; + return isRegistering ? (
{
Already have an account?{" "} - Login - +
@@ -303,12 +312,13 @@ const LoginModal = ({ toggleLoginModal }) => {
Not registered?{" "} - Create account - +
From d5f6fce08c28baa19f651cc2b4a74fafb2bffbf6 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 11 Nov 2023 15:06:04 -0500 Subject: [PATCH 073/130] add connection string config --- server/config/database.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/config/database.js b/server/config/database.js index 573ca1479..f1cff1de9 100644 --- a/server/config/database.js +++ b/server/config/database.js @@ -9,4 +9,8 @@ const config = { database: process.env.PGDATABASE, }; +const conString = process.env.DATABASE_URL; + export const pool = new pg.Pool(config); + +export { conString }; From 6a7a3b47cf2e3bf0dfdbd8bd1971921b6cd69a1c Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 11 Nov 2023 15:06:27 -0500 Subject: [PATCH 074/130] create session table --- server/config/reset.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/server/config/reset.js b/server/config/reset.js index 158372075..024d3ba29 100644 --- a/server/config/reset.js +++ b/server/config/reset.js @@ -351,6 +351,26 @@ const dropAllTables = async () => { console.log("⚠️ error dropping tables", err); } }; + +const createSessionTable = async () => { + const createSessionTableQuery = { + text: `CREATE TABLE IF NOT EXISTS "session" ( + sid varchar NOT NULL COLLATE "default", + sess json NOT NULL, + expire timestamp(6) NOT NULL + ) + WITH (OIDS=FALSE); + ALTER TABLE "session" ADD CONSTRAINT "session_pkey" PRIMARY KEY ("sid") NOT DEFERRABLE INITIALLY IMMEDIATE;`, + }; + + try { + const res = await pool.query(createSessionTableQuery); + console.log("πŸŽ‰ session table created successfully"); + } catch (err) { + console.log("⚠️ error creating session table", err); + } +}; + // dropAllTables(); // seedUsersTable(); // seedPropertiesTable(); @@ -358,3 +378,4 @@ const dropAllTables = async () => { // seedPropertyAmenitiesTable(); // seedListingAvailabilityTable(); // seedListingImagesTable(); +// createSessionTable(); From 1a41b3179d9b3fd05dd201e2f9928ea4c78025c9 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 11 Nov 2023 15:06:45 -0500 Subject: [PATCH 075/130] user session --- server/routes/auth.js | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/server/routes/auth.js b/server/routes/auth.js index 452311618..acd6ee648 100644 --- a/server/routes/auth.js +++ b/server/routes/auth.js @@ -30,9 +30,31 @@ const router = express.Router(); // } // }); -router.post('/login', passport.authenticate('local'), (request, response, next) => { - response.status(200).json({ message: 'Logged in successfully' }); -}) +router.post( + "/login", + passport.authenticate("local"), + (request, response, next) => { + response.status(200).json({ message: "Logged in successfully" }); + } +); + +router.post("/logout", (req, res) => { + req.logout((err) => { + if (err) { + console.error("Error during logout:", err); + res.status(500).json({ error: "Internal Server Error" }); + } else { + req.session.destroy((err) => { + if (err) { + console.error("Error destroying session:", err); + res.status(500).json({ error: "Internal Server Error" }); + } else { + res.status(200).json({ message: "Logged out successfully" }); + } + }); + } + }); +}); router.post("/register", async (request, response) => { try { From e0c41f445dd420abe1fa6e5e3a6669f398a3b223 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 11 Nov 2023 15:07:10 -0500 Subject: [PATCH 076/130] connect pg session --- server/server.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/server/server.js b/server/server.js index a018bcda9..bc048bc7d 100644 --- a/server/server.js +++ b/server/server.js @@ -9,10 +9,16 @@ import session from "express-session"; import "./config/dotenv.js"; import cookieParser from "cookie-parser"; import "./strategies/local.js"; +import { conString } from "./config/database.js"; +import connectPgSimple from "connect-pg-simple"; const app = express(); const PORT = process.env.PORT || 3001; -const memoryStore = new session.MemoryStore(); +// const memoryStore = new session.MemoryStore(); +const PostgresqlStore = connectPgSimple(session); +const sessionStore = new PostgresqlStore({ + conString: conString, +}); app.use(express.json()); app.use(cookieParser()); @@ -21,7 +27,7 @@ app.use( secret: process.env.CLIENT_SECRET, resave: false, saveUninitialized: false, - store: memoryStore, + store: sessionStore, }) ); // app.use(cors()); From 02da0426698193d508e92aea67807312fd3416c8 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 11 Nov 2023 15:07:21 -0500 Subject: [PATCH 077/130] install pg connect simple --- client/src/redux/rootReducer.js | 0 client/src/redux/slices/listingsSlice.js | 0 client/src/redux/slices/messagesSlice.js | 0 client/src/redux/slices/propertiesSlice.js | 0 client/src/redux/slices/userSlice.js | 0 client/src/redux/store.js | 20 ++++++++++++++++++++ 6 files changed, 20 insertions(+) create mode 100644 client/src/redux/rootReducer.js create mode 100644 client/src/redux/slices/listingsSlice.js create mode 100644 client/src/redux/slices/messagesSlice.js create mode 100644 client/src/redux/slices/propertiesSlice.js create mode 100644 client/src/redux/slices/userSlice.js create mode 100644 client/src/redux/store.js diff --git a/client/src/redux/rootReducer.js b/client/src/redux/rootReducer.js new file mode 100644 index 000000000..e69de29bb diff --git a/client/src/redux/slices/listingsSlice.js b/client/src/redux/slices/listingsSlice.js new file mode 100644 index 000000000..e69de29bb diff --git a/client/src/redux/slices/messagesSlice.js b/client/src/redux/slices/messagesSlice.js new file mode 100644 index 000000000..e69de29bb diff --git a/client/src/redux/slices/propertiesSlice.js b/client/src/redux/slices/propertiesSlice.js new file mode 100644 index 000000000..e69de29bb diff --git a/client/src/redux/slices/userSlice.js b/client/src/redux/slices/userSlice.js new file mode 100644 index 000000000..e69de29bb diff --git a/client/src/redux/store.js b/client/src/redux/store.js new file mode 100644 index 000000000..5501b095f --- /dev/null +++ b/client/src/redux/store.js @@ -0,0 +1,20 @@ +import { configureStore } from "@reduxjs/toolkit"; +import storage from "redux-persist/lib/storage"; +import { persistReducer, persistStore } from "redux-persist"; +import logger from "redux-logger"; +import rootReducer from "./rootReducer"; + +const persistConfig = { + key: "root", + storage, +}; + +const persistedReducer = persistReducer(persistConfig, rootReducer); + +export const store = configureStore({ + reducer: persistedReducer, + devTools: process.env.NODE_ENV !== "production", + middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger), +}); + +export const persistor = persistStore(store); From 1cfc3f5ad1ee7d0a9c5fbe1833025e55b058363d Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 11 Nov 2023 15:08:12 -0500 Subject: [PATCH 078/130] install connect-pg-simple --- server/controllers/login.js | 30 ------------------------------ server/package-lock.json | 12 ++++++++++++ server/package.json | 1 + 3 files changed, 13 insertions(+), 30 deletions(-) delete mode 100644 server/controllers/login.js diff --git a/server/controllers/login.js b/server/controllers/login.js deleted file mode 100644 index 21f466411..000000000 --- a/server/controllers/login.js +++ /dev/null @@ -1,30 +0,0 @@ -import { pool } from "../config/database.js"; - -import bcrypt from "bcrypt"; - -const emailExists = async (email) => { - const data = await pool.query("SELECT * FROM users WHERE email=$1", [email]); - - if (data.rowCount == 0) return false; - return data.rows[0]; -}; - -const createUser = async (email, password) => { - const salt = await bcrypt.genSalt(10); - const hash = await bcrypt.hash(password, salt); - - const data = await pool.query( - "INSERT INTO users(email, password) VALUES ($1, $2) RETURNING id, email, password", - [email, hash] - ); - - if (data.rowCount == 0) return false; - return data.rows[0]; -}; - -const matchPassword = async (password, hashPassword) => { - const match = await bcrypt.compare(password, hashPassword); - return match; -}; - -export default { emailExists, createUser, matchPassword }; diff --git a/server/package-lock.json b/server/package-lock.json index c9632624c..5a14524f8 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "bcrypt": "^5.1.1", + "connect-pg-simple": "^9.0.1", "cookie-parser": "^1.4.6", "cors": "^2.8.5", "dotenv": "^16.3.1", @@ -290,6 +291,17 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/connect-pg-simple": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/connect-pg-simple/-/connect-pg-simple-9.0.1.tgz", + "integrity": "sha512-BuwWJH3K3aLpONkO9s12WhZ9ceMjIBxIJAh0JD9x4z1Y9nShmWqZvge5PG/+4j2cIOcguUoa2PSQ4HO/oTsrVg==", + "dependencies": { + "pg": "^8.8.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", diff --git a/server/package.json b/server/package.json index 3a5934bff..8d9b6cdd9 100644 --- a/server/package.json +++ b/server/package.json @@ -13,6 +13,7 @@ "license": "ISC", "dependencies": { "bcrypt": "^5.1.1", + "connect-pg-simple": "^9.0.1", "cookie-parser": "^1.4.6", "cors": "^2.8.5", "dotenv": "^16.3.1", From e68448e534d00a14013d2d08a437743b4ef88974 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 11 Nov 2023 20:13:23 -0500 Subject: [PATCH 079/130] login/logout based on redux user --- client/src/components/DropdownMenu.jsx | 82 ++++++++++++++++++-------- 1 file changed, 57 insertions(+), 25 deletions(-) diff --git a/client/src/components/DropdownMenu.jsx b/client/src/components/DropdownMenu.jsx index 3bc86a5a9..44804e733 100644 --- a/client/src/components/DropdownMenu.jsx +++ b/client/src/components/DropdownMenu.jsx @@ -1,8 +1,18 @@ import React from "react"; import { RxAvatar, RxDropdownMenu } from "react-icons/rx"; -import { Link } from 'react-router-dom' +import { Link } from "react-router-dom"; +import { useSelector, useDispatch } from "react-redux"; +import { authLogOut } from "../redux/slices/userSlice"; const DropdownMenu = ({ toggleDropdown, toggleLoginModal, isDropdownOpen }) => { + const user = useSelector((state) => state.user?.loggedInUser); + const dispatch = useDispatch(); + + const handleLogoutUser = async () => { + await dispatch(authLogOut()); + }; + + console.log(user); return (
@@ -11,32 +21,41 @@ const DropdownMenu = ({ toggleDropdown, toggleLoginModal, isDropdownOpen }) => { className="flex border-solid border-2 px-4 rounded-3xl w-28 h-14 items-center" type="button" > - -
+
+ +
+
{isDropdownOpen && ( -
+
-
Bonnie Green
-
name@flowbite.com
+ {user ? ( + <> +
+ {user.first_name} {user.last_name} +
+
{user.email}
+ + ) : ( +
Guest
+ )}
  • - - +
  • @@ -57,16 +76,29 @@ const DropdownMenu = ({ toggleDropdown, toggleLoginModal, isDropdownOpen }) => {
-
- -
+ {user ? ( +
+ +
+ ) : ( +
+ +
+ )}
)}
From f1e7ee53f2b1cabbcea795197ab4a74a276c126a Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 11 Nov 2023 20:13:52 -0500 Subject: [PATCH 080/130] form states to submit registration and login --- client/src/components/LoginModal.jsx | 148 ++++++++++++++++++--------- 1 file changed, 101 insertions(+), 47 deletions(-) diff --git a/client/src/components/LoginModal.jsx b/client/src/components/LoginModal.jsx index d3760bd70..66f7f615f 100644 --- a/client/src/components/LoginModal.jsx +++ b/client/src/components/LoginModal.jsx @@ -1,8 +1,18 @@ import React, { useEffect, useState } from "react"; +import { useDispatch } from "react-redux"; +import { authLogIn, authRegister } from "../redux/slices/userSlice"; +import { set } from "date-fns"; const LoginModal = ({ toggleLoginModal }) => { const [isRegistering, setIsRegistering] = useState(false); - + const [userEmail, setUserEmail] = useState(""); + const [userPassword, setUserPassword] = useState(""); + const [userFirstName, setUserFirstName] = useState(""); + const [userLastName, setUserLastName] = useState(""); + const [userMobileNumber, setUserMobileNumber] = useState(""); + const [userZipcode, setUserZipcode] = useState(""); + const [userUsername, setUserUsername] = useState(""); + const dispatch = useDispatch(); const handleRegisterClick = () => { setIsRegistering(true); }; @@ -11,6 +21,62 @@ const LoginModal = ({ toggleLoginModal }) => { setIsRegistering(false); }; + const handleLoginUser = async (e) => { + e.preventDefault(); + try { + await dispatch(authLogIn({ email: userEmail, password: userPassword })); + } catch (error) { + console.error("Error authenticating user:", error); + } + }; + + const handleRegisterUser = async (e) => { + e.preventDefault(); + try { + await dispatch( + authRegister({ + first_name: userFirstName, + last_name: userLastName, + zipcode: userZipcode, + phone: userMobileNumber, + user_name: userUsername, + email: userEmail, + password: userPassword, + }) + ); + } catch (error) { + console.error("Error registering user:", error); + } + }; + + const handleEnterPassword = (e) => { + setUserPassword(e.target.value); + }; + + const handleEnterEmail = (e) => { + setUserEmail(e.target.value); + }; + + const handleEnterFirstName = (e) => { + setUserFirstName(e.target.value); + }; + + const handleEnterLastName = (e) => { + setUserLastName(e.target.value); + }; + + const handleEnterMobileNumber = (e) => { + setUserMobileNumber(e.target.value); + }; + + const handleEnterZipcode = (e) => { + setUserZipcode(e.target.value); + }; + + const handleEnterUsername = (e) => { + setUserUsername(e.target.value); + }; + return isRegistering ? (
{ className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus-ring-blue-500 focus-border-blue-500 block w-full p-2.5 dark-bg-gray-600 dark-border-gray-500 dark-placeholder-gray-400 dark-text-white" placeholder="name@company.com" required + onChange={handleEnterEmail} />
@@ -99,98 +166,82 @@ const LoginModal = ({ toggleLoginModal }) => { placeholder="β€’β€’β€’β€’β€’β€’β€’β€’" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus-ring-blue-500 focus-border-blue-500 block w-full p-2.5 dark-bg-gray-600 dark-border-gray-500 dark-placeholder-gray-400 dark-text-white" required + onChange={handleEnterPassword} />
-
-
-
- -
- -
-
@@ -259,6 +310,7 @@ const LoginModal = ({ toggleLoginModal }) => { className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus-ring-blue-500 focus-border-blue-500 block w-full p-2.5 dark-bg-gray-600 dark-border-gray-500 dark-placeholder-gray-400 dark-text-white" placeholder="name@company.com" required + onChange={handleEnterEmail} />
@@ -275,9 +327,10 @@ const LoginModal = ({ toggleLoginModal }) => { placeholder="β€’β€’β€’β€’β€’β€’β€’β€’" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus-ring-blue-500 focus-border-blue-500 block w-full p-2.5 dark-bg-gray-600 dark-border-gray-500 dark-placeholder-gray-400 dark-text-white" required + onChange={handleEnterPassword} />
-
+ {/*
{ Lost Password?
-
+
*/} From 73374127d54684c06b73805879244cf0349cada5 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 11 Nov 2023 20:14:35 -0500 Subject: [PATCH 081/130] toggle modal based on login attempt --- client/src/components/Navbar.jsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/client/src/components/Navbar.jsx b/client/src/components/Navbar.jsx index d7de88726..5b5c2eb46 100644 --- a/client/src/components/Navbar.jsx +++ b/client/src/components/Navbar.jsx @@ -1,5 +1,6 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { Link } from "react-router-dom"; +import { useSelector } from "react-redux"; import stayvueLogo from "../assets/StayVue.png"; import search from "../assets/search.png"; import LoginModal from "./LoginModal"; @@ -7,6 +8,13 @@ import DropdownMenu from "./DropdownMenu"; const Navbar = ({ isModalOpen, setIsModalOpen }) => { const [isDropdownOpen, setIsDropdownOpen] = useState(false); + const user = useSelector((state) => state.user?.loggedInUser); + + useEffect(() => { + if (user) { + setIsModalOpen(false); + } + }, [user]); const handleButtonClick = (label) => { // Add your logic here to handle button clicks @@ -65,8 +73,7 @@ const Navbar = ({ isModalOpen, setIsModalOpen }) => { isDropdownOpen={isDropdownOpen} />
- {isModalOpen && - } + {isModalOpen && } ); }; From 93abe2db06a85c0ee2c9fae4f020a8c5ef13ea38 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 11 Nov 2023 20:14:56 -0500 Subject: [PATCH 082/130] implement redux persist store --- client/src/main.jsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/client/src/main.jsx b/client/src/main.jsx index 8a91f187d..ddbab978f 100644 --- a/client/src/main.jsx +++ b/client/src/main.jsx @@ -3,11 +3,18 @@ import ReactDOM from "react-dom/client"; import { BrowserRouter } from "react-router-dom"; import App from "./App.jsx"; import "./index.css"; +import { persistor, store } from "./redux/store"; +import { PersistGate } from "redux-persist/integration/react"; +import { Provider } from "react-redux"; ReactDOM.createRoot(document.getElementById("root")).render( - - - + + + + + + + ); From 1eea4eaf3d6486e348dcd623ff6094fb8e62d8a7 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 11 Nov 2023 20:15:08 -0500 Subject: [PATCH 083/130] redux root reducer init --- client/src/redux/rootReducer.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/client/src/redux/rootReducer.js b/client/src/redux/rootReducer.js index e69de29bb..c9fe7cb05 100644 --- a/client/src/redux/rootReducer.js +++ b/client/src/redux/rootReducer.js @@ -0,0 +1,8 @@ +import { combineReducers } from "@reduxjs/toolkit"; +import userReducer from "./slices/userSlice"; + +const rootReducer = combineReducers({ + user: userReducer, +}); + +export default rootReducer; From 171e26368e7c84ddce5c3c195e952b5d28ef5623 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 11 Nov 2023 20:15:17 -0500 Subject: [PATCH 084/130] user slice init --- client/src/redux/slices/userSlice.js | 144 +++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/client/src/redux/slices/userSlice.js b/client/src/redux/slices/userSlice.js index e69de29bb..049fc3c3d 100644 --- a/client/src/redux/slices/userSlice.js +++ b/client/src/redux/slices/userSlice.js @@ -0,0 +1,144 @@ +import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"; +import axios from "axios"; +import { set } from "date-fns"; + +export const authLogIn = createAsyncThunk( + "user/authLogIn", + async ({ email, password }, { dispatch }) => { + try { + const res = await axios.post( + `${import.meta.env.VITE_BACKEND_URL}/api/auth/login`, + { email, password }, + { withCredentials: true } + ); + dispatch(setLoggedInUser(res.data.user)); + dispatch(setEmail(res.data.user.email)); + dispatch(setAuthenticated(true)); + dispatch(toggleLoggedIn()); + // const userData = res.data; + // return userData; + } catch (error) { + console.error("Error authenticating user:", error); + throw error; // Re-throw the error to be caught in the rejected case + } + } +); + +export const authRegister = createAsyncThunk( + "user/authRegister", + async ( + { first_name, last_name, zipcode, phone, user_name, email, password }, + { dispatch } + ) => { + console.log("attempt to register"); + const apiUrl = `${import.meta.env.VITE_BACKEND_URL}/api/auth/register`; + console.log(apiUrl); + try { + const res = await axios.post( + `${import.meta.env.VITE_BACKEND_URL}/api/auth/register`, + { first_name, last_name, zipcode, phone, user_name, email, password }, + { withCredentials: true } + ); + + console.log(res.data.user); + dispatch(setLoggedInUser(res.data.user)); + dispatch(setEmail(res.data.user.email)); + dispatch(setAuthenticated(true)); + dispatch(toggleLoggedIn()); + // const userData = res.data; + // return userData; + } catch (error) { + console.error("Error authenticating user:", error); + throw error; // Re-throw the error to be caught in the rejected case + } + } +); + +export const authLogOut = createAsyncThunk( + "user/authLogOut", + async (_, { dispatch }) => { + try { + const res = await axios.post( + `${import.meta.env.VITE_BACKEND_URL}/api/auth/logout`, + { withCredentials: true } + ); + dispatch(toggleLoggedIn()); + } catch (error) { + console.error("Error logging out user:", error); + throw error; + } + } +); + +const initialState = { + email: null, + loggedInUser: [], + isLoggedIn: false, + isAuthenticated: false, + error: null, +}; + +const userSlice = createSlice({ + name: "user", + initialState, + reducers: { + setEmail: (state, action) => { + state.email = action.payload; + }, + setLoggedInUser: (state, action) => { + state.loggedInUser = action.payload; + }, + toggleLoggedIn: (state) => { + state.isLoggedIn = !state.isLoggedIn; + }, + setAuthenticated: (state, action) => { + state.isAuthenticated = action.payload; + }, + setError: (state, action) => { + state.error = action.payload; + }, + }, + extraReducers: (builder) => { + builder + .addCase(authLogIn.pending, (state) => { + state.status = "loading"; + state.error = null; + }) + .addCase(authLogIn.fulfilled, (state, action) => { + state.status = "succeeded"; + // state.loggedInUser = action.payload; + }) + .addCase(authLogIn.rejected, (state, action) => { + state.status = "failed"; + state.error = action.error.message; + }) + .addCase(authRegister.pending, (state) => { + state.error = null; + state.status = "loading"; + }) + .addCase(authRegister.fulfilled, (state, action) => { + state.status = "succeeded"; + state.loggedInUser = action.payload; + }) + .addCase(authRegister.rejected, (state, action) => { + state.status = "failed"; + state.error = action.error.message; + }) + .addCase(authLogOut.pending, (state) => { + state.error = null; + state.status = "loading"; + }) + .addCase(authLogOut.fulfilled, (state, action) => { + state.status = "succeeded"; + state.loggedInUser = null; + }) + .addCase(authLogOut.rejected, (state, action) => { + state.status = "failed"; + state.error = action.error.message; + }); + }, +}); + +export const { setEmail, toggleLoggedIn, setAuthenticated, setLoggedInUser } = + userSlice.actions; +export default userSlice.reducer; From 6da155e12d21ca72bfcc74341013ebaf45ed24f6 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 11 Nov 2023 20:15:36 -0500 Subject: [PATCH 085/130] add image to user table --- server/config/reset.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server/config/reset.js b/server/config/reset.js index 024d3ba29..27347b1d0 100644 --- a/server/config/reset.js +++ b/server/config/reset.js @@ -49,6 +49,7 @@ const createUsersTable = async () => { user_name VARCHAR(50) UNIQUE NOT NULL, email VARCHAR(50) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, + image_url VARCHAR(255), is_active BOOLEAN DEFAULT true )`, }; From 563062627d682f53f18ac1e567a3dc0546c77bd9 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 11 Nov 2023 20:16:08 -0500 Subject: [PATCH 086/130] implement additiona llogic to return user object to client side --- server/routes/auth.js | 50 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/server/routes/auth.js b/server/routes/auth.js index acd6ee648..5878a55e4 100644 --- a/server/routes/auth.js +++ b/server/routes/auth.js @@ -32,12 +32,46 @@ const router = express.Router(); router.post( "/login", - passport.authenticate("local"), - (request, response, next) => { - response.status(200).json({ message: "Logged in successfully" }); + passport.authenticate("local", { + failureRedirect: "/api/auth/login/failed", + }), + async (req, res) => { + try { + // Assuming you have a users table in your database + const result = await pool.query(`SELECT * FROM users WHERE id = $1`, [ + req.user.id, + ]); + + if (!result.rows || result.rows.length === 0) { + return res.status(401).json({ message: "User not found" }); + } + + const user = result.rows[0]; + + // Now you have the full user data from the database + res.status(200).json({ message: "Logged in successfully", user }); + } catch (error) { + console.error("Error fetching user data:", error); + res.status(500).json({ error: "Internal Server Error" }); + } } ); +router.get("/login/success", (req, res) => { + // This route will be reached when authentication is successful + if (req.user) { + res.status(200).json({ success: true, user: req.user }); + } else { + // Handle the case where the user object is not available + res.status(401).json({ success: false, message: "User not authenticated" }); + } +}); + +router.get("/login/failed", (req, res) => { + // This route will be reached when authentication fails + res.status(401).json({ success: false, message: "Authentication failed" }); +}); + router.post("/logout", (req, res) => { req.logout((err) => { if (err) { @@ -67,10 +101,12 @@ router.post("/register", async (request, response) => { email, password, } = request.body; + const user = await pool.query(`SELECT * FROM users WHERE email = $1`, [ email, ]); - if (user.rows > 0) { + + if (user.rows.length > 0) { response.status(400).json({ message: "User already exists" }); } else { const hashedPassword = hashPassword(password); @@ -87,7 +123,11 @@ router.post("/register", async (request, response) => { hashedPassword, ] ); - response.status(201).json(newUser.rows[0]); + + // Send the user data in the response + response + .status(201) + .json({ message: "Registered successfully", user: newUser.rows[0] }); } catch (error) { response.status(500).json({ error: error.message }); } From bfb5ee8f89e11e022cf20612a67da1956937269f Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sat, 11 Nov 2023 20:16:21 -0500 Subject: [PATCH 087/130] fix import for profile controller --- server/routes/profile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/routes/profile.js b/server/routes/profile.js index 780a92f84..bbb647e46 100644 --- a/server/routes/profile.js +++ b/server/routes/profile.js @@ -1,5 +1,5 @@ import express from 'express'; -import updateUserProfile from '../controllers/profile.js' +import ProfileController from '../controllers/profile.js' const router = express.Router(); From b65168010329957cf5c31e10d989cd0744546ff0 Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sat, 11 Nov 2023 20:46:26 -0500 Subject: [PATCH 088/130] adding form validation and adding listing component on profile page --- client/.eslintrc.cjs | 5 ++- client/src/components/ListingCard.jsx | 17 ++++++++- client/src/pages/Profiles.jsx | 50 ++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 5 deletions(-) diff --git a/client/.eslintrc.cjs b/client/.eslintrc.cjs index a44070760..cf8614eb9 100644 --- a/client/.eslintrc.cjs +++ b/client/.eslintrc.cjs @@ -16,8 +16,7 @@ module.exports = { 'react-refresh/only-export-components': [ 'warn', { allowConstantExport: true }, - ], + 'react/prop-types': 'off', // Separate rule from the array }, -} - +}; diff --git a/client/src/components/ListingCard.jsx b/client/src/components/ListingCard.jsx index d0b955858..6194244b9 100644 --- a/client/src/components/ListingCard.jsx +++ b/client/src/components/ListingCard.jsx @@ -4,11 +4,21 @@ import { BsFillStarFill } from "react-icons/bs"; import { format, isSameMonth } from "date-fns"; const ListingCard = ({ listing }) => { + if (!listing || !listing.availability) { + console.error('Invalid or missing listing data:', listing); + return null; // or handle it in another way + } + const formattedAvailability = listing.availability.map((item) => { const startDate = new Date(item.start_availability); const endDate = new Date(item.end_availability); - const startMonth = format(startDate, "MMM"); // Format month as a 3-letter abbreviation + if (!startDate || !endDate) { + console.error('Invalid date range:', item); + return null; // or handle it in another way + } + + const startMonth = format(startDate, "MMM"); const endMonth = format(endDate, "MMM"); let formattedDate; @@ -22,6 +32,11 @@ const ListingCard = ({ listing }) => { return formattedDate; }); + if (formattedAvailability.includes(null)) { + console.error('Invalid date range in availability:', listing.availability); + return null; // or handle it in another way + } + return (
diff --git a/client/src/pages/Profiles.jsx b/client/src/pages/Profiles.jsx index 81ec50ea1..1acab546b 100644 --- a/client/src/pages/Profiles.jsx +++ b/client/src/pages/Profiles.jsx @@ -1,4 +1,5 @@ import React, { useState } from 'react'; +import ListingCard from '../components/ListingCard'; function Profiles() { const [activeTab, setActiveTab] = useState('user'); // 'user' or 'listings' @@ -8,6 +9,17 @@ function Profiles() { email: '', password: '', }); + const [fieldErrors, setFieldErrors] = useState({ + firstName: false, + lastName: false, + address: false, + city: false, + state: false, + zipcode: false, + email: false, + password: false, + }); + const handleInputChange = (e) => { const { name, value } = e.target; @@ -15,8 +27,33 @@ function Profiles() { ...prevUserData, [name]: value, })); + // Clear the error when the user starts typing in the field + setFieldErrors((prevErrors) => ({ + ...prevErrors, + [name]: false, + })); }; + const handleUpdateProfile = () => { + // Check for empty fields and set errors + const errors = {}; + Object.entries(userData).forEach(([key, value]) => { + if (value.trim() === '') { + errors[key] = true; + } + }); + setFieldErrors(errors); + + // If no errors, proceed with updating the profile + if (Object.keys(errors).length === 0) { + // Add logic to update the profile + console.log('Profile updated successfully!'); + } + console.log('unsuccessful') + }; + + + return (
@@ -31,7 +68,9 @@ function Profiles() { className={`w-full py-2 rounded-md focus:outline-none ${activeTab === 'listings' ? 'bg-red-500 text-white' : 'bg-gray-300 text-gray-700' }`} onClick={() => setActiveTab('listings')} + > + r Listings
@@ -45,9 +84,11 @@ function Profiles() { First Name @@ -58,6 +99,7 @@ function Profiles() { Last Name Update Profile From a0c55092294f46ba59ea21e031d9bd40a020cbbb Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 12 Nov 2023 19:44:20 -0500 Subject: [PATCH 089/130] api url prod and dev --- client/src/App.jsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/client/src/App.jsx b/client/src/App.jsx index e53ffac09..e4b125b1c 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from "react"; import { useRoutes } from "react-router-dom"; import Listings from "./pages/Listings"; -import { BrowserRouter as Router, Route, Routes } from 'react-router-dom' +import { BrowserRouter as Router, Route, Routes } from "react-router-dom"; import "./App.css"; import Navbar from "./components/Navbar"; import Profiles from "./pages/Profiles"; @@ -9,7 +9,10 @@ import Profiles from "./pages/Profiles"; function App() { const [listings, setListings] = useState([]); const [isModalOpen, setIsModalOpen] = useState(false); - const API_URL = "http://localhost:3001"; + const API_URL = + process.env.NODE_ENV === "production" + ? import.meta.env.VITE_SERVER_URL + : VITE_BACKEND_URL; useEffect(() => { const fetchListings = async () => { @@ -38,9 +41,9 @@ function App() { > {element}
- - }/> - + + } /> +
); } From dc9314814dc7c5774737d8cb577bddfa8b398d10 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 12 Nov 2023 19:44:35 -0500 Subject: [PATCH 090/130] add api url --- client/src/redux/slices/userSlice.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/client/src/redux/slices/userSlice.js b/client/src/redux/slices/userSlice.js index 049fc3c3d..398bf2b49 100644 --- a/client/src/redux/slices/userSlice.js +++ b/client/src/redux/slices/userSlice.js @@ -2,12 +2,17 @@ import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"; import axios from "axios"; import { set } from "date-fns"; +const API_URL = + process.env.NODE_ENV === "production" + ? import.meta.env.VITE_SERVER_URL + : VITE_BACKEND_URL; + export const authLogIn = createAsyncThunk( "user/authLogIn", async ({ email, password }, { dispatch }) => { try { const res = await axios.post( - `${import.meta.env.VITE_BACKEND_URL}/api/auth/login`, + `${API_URL}/api/auth/login`, { email, password }, { withCredentials: true } ); @@ -31,7 +36,7 @@ export const authRegister = createAsyncThunk( { dispatch } ) => { console.log("attempt to register"); - const apiUrl = `${import.meta.env.VITE_BACKEND_URL}/api/auth/register`; + const apiUrl = `${API_URL}/api/auth/register`; console.log(apiUrl); try { const res = await axios.post( @@ -59,7 +64,7 @@ export const authLogOut = createAsyncThunk( async (_, { dispatch }) => { try { const res = await axios.post( - `${import.meta.env.VITE_BACKEND_URL}/api/auth/logout`, + `${API_URL}/api/auth/logout`, { withCredentials: true } ); dispatch(toggleLoggedIn()); From ad6616599519b2cf5dad2597d8260bb6546c100e Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 12 Nov 2023 19:44:44 -0500 Subject: [PATCH 091/130] client url for server --- server/server.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/server/server.js b/server/server.js index bc048bc7d..b456be17f 100644 --- a/server/server.js +++ b/server/server.js @@ -12,6 +12,16 @@ import "./strategies/local.js"; import { conString } from "./config/database.js"; import connectPgSimple from "connect-pg-simple"; +const CLIENT_URL = + process.env.NODE_ENV === "production" + ? process.env.PROD_CLIENT_URL + : process.env.DEV_CLIENT_URL; + +const API_URL = + process.env.NODE_ENV === "production" + ? process.env.PROD_SERVER_URL + : process.env.DEV_SERVER_URL; + const app = express(); const PORT = process.env.PORT || 3001; // const memoryStore = new session.MemoryStore(); @@ -33,7 +43,7 @@ app.use( // app.use(cors()); app.use( cors({ - origin: "http://localhost:5173", + origin: CLIENT_URL, methods: "GET,HEAD,PUT,PATCH,POST,DELETE", credentials: true, }) @@ -53,7 +63,7 @@ passport.deserializeUser((user, done) => { }); app.get("/", (req, res) => { - res.redirect("http://localhost:3001"); + res.redirect(CLIENT_URL); }); app.use((req, res, next) => { From 7363f071e2a1adadcffdc845e3ccc72fb4a560ab Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 12 Nov 2023 19:50:10 -0500 Subject: [PATCH 092/130] serve build script --- client/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/client/package.json b/client/package.json index 2f1447245..b03f37f11 100644 --- a/client/package.json +++ b/client/package.json @@ -4,6 +4,7 @@ "version": "0.0.0", "type": "module", "scripts": { + "start": "serve build -s -n -L -p $PORT", "dev": "vite", "build": "vite build", "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", From bb2715bd508b8357c35421a3569f5e0118e89b3e Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 12 Nov 2023 19:50:17 -0500 Subject: [PATCH 093/130] api proxy --- client/vite.config.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/client/vite.config.js b/client/vite.config.js index 5a33944a9..fa00a1e39 100644 --- a/client/vite.config.js +++ b/client/vite.config.js @@ -1,7 +1,14 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], -}) + server: { + proxy: { + "/api": { + target: "http://localhost:3001", + }, + }, + }, +}); From 7d26c845854766bd1ea7b47f5a134cdbb428ddfc Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 12 Nov 2023 19:52:50 -0500 Subject: [PATCH 094/130] redux fix api url import --- client/src/redux/slices/userSlice.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/client/src/redux/slices/userSlice.js b/client/src/redux/slices/userSlice.js index 398bf2b49..8b8132faf 100644 --- a/client/src/redux/slices/userSlice.js +++ b/client/src/redux/slices/userSlice.js @@ -5,7 +5,7 @@ import { set } from "date-fns"; const API_URL = process.env.NODE_ENV === "production" ? import.meta.env.VITE_SERVER_URL - : VITE_BACKEND_URL; + : import.meta.env.VITE_BACKEND_URL; export const authLogIn = createAsyncThunk( "user/authLogIn", @@ -63,10 +63,9 @@ export const authLogOut = createAsyncThunk( "user/authLogOut", async (_, { dispatch }) => { try { - const res = await axios.post( - `${API_URL}/api/auth/logout`, - { withCredentials: true } - ); + const res = await axios.post(`${API_URL}/api/auth/logout`, { + withCredentials: true, + }); dispatch(toggleLoggedIn()); } catch (error) { console.error("Error logging out user:", error); From f0474abb01f2e9c5d01c10a95786aeccfa69200f Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 12 Nov 2023 19:55:34 -0500 Subject: [PATCH 095/130] redux fix api url import --- client/src/App.jsx | 2 +- client/src/redux/slices/userSlice.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/App.jsx b/client/src/App.jsx index e4b125b1c..8b746b770 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -12,7 +12,7 @@ function App() { const API_URL = process.env.NODE_ENV === "production" ? import.meta.env.VITE_SERVER_URL - : VITE_BACKEND_URL; + : "http://localhost:3001"; useEffect(() => { const fetchListings = async () => { diff --git a/client/src/redux/slices/userSlice.js b/client/src/redux/slices/userSlice.js index 8b8132faf..ecd48ec63 100644 --- a/client/src/redux/slices/userSlice.js +++ b/client/src/redux/slices/userSlice.js @@ -5,7 +5,7 @@ import { set } from "date-fns"; const API_URL = process.env.NODE_ENV === "production" ? import.meta.env.VITE_SERVER_URL - : import.meta.env.VITE_BACKEND_URL; + : "http://localhost:3001"; export const authLogIn = createAsyncThunk( "user/authLogIn", From b54a53c142f2a2cb8fa5fbbd6d5ba418980a912b Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 12 Nov 2023 20:00:45 -0500 Subject: [PATCH 096/130] install serve --- client/package-lock.json | 800 +++++++++++++++++++++++++++++++++++++-- client/package.json | 3 +- 2 files changed, 780 insertions(+), 23 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index aade7d156..fd6250157 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -19,7 +19,8 @@ "redux": "^4.2.1", "redux-logger": "^3.0.6", "redux-persist": "^6.0.0", - "redux-thunk": "^2.4.2" + "redux-thunk": "^2.4.2", + "serve": "^14.2.1" }, "devDependencies": { "@types/react": "^18.2.15", @@ -1086,6 +1087,23 @@ "vite": "^4.2.0" } }, + "node_modules/@zeit/schemas": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.29.0.tgz", + "integrity": "sha512-g5QiLIfbg3pLuYUJPlisNKY+epQJTcMDsOnVNkscrDP1oi7vmJnzOANYJI/1pZcVJ6umUkBv3aFtlg1UvUHGzA==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.11.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", @@ -1123,11 +1141,36 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -1163,11 +1206,29 @@ "node": ">= 8" } }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" }, "node_modules/argparse": { "version": "2.0.1", @@ -1353,8 +1414,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/binary-extensions": { "version": "2.2.0", @@ -1365,11 +1425,53 @@ "node": ">=8" } }, + "node_modules/boxen": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.0.tgz", + "integrity": "sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^7.0.0", + "chalk": "^5.0.1", + "cli-boxes": "^3.0.0", + "string-width": "^5.1.2", + "type-fest": "^2.13.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.0.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/boxen/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1419,6 +1521,14 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/call-bind": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", @@ -1442,6 +1552,17 @@ "node": ">=6" } }, + "node_modules/camelcase": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -1485,6 +1606,84 @@ "node": ">=4" } }, + "node_modules/chalk-template": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", + "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "dependencies": { + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/chalk-template?sponsor=1" + } + }, + "node_modules/chalk-template/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/chalk-template/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk-template/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/chalk-template/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/chalk-template/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk-template/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -1524,6 +1723,33 @@ "node": ">= 6" } }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clipboardy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-3.0.0.tgz", + "integrity": "sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==", + "dependencies": { + "arch": "^2.2.0", + "execa": "^5.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -1559,11 +1785,59 @@ "node": ">= 6" } }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", + "engines": { + "node": ">= 0.6" + } }, "node_modules/convert-source-map": { "version": "2.0.0", @@ -1575,7 +1849,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1639,6 +1912,14 @@ "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz", "integrity": "sha512-yVn6RZmHiGnxRKR9sJb3iVV2XTF1Ghh2DiWRZ3dMnGc43yUdWWF/kX6lQyk3+P84iprfWKU/8zFTrlkvtFm1ug==" }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -1708,12 +1989,22 @@ "node": ">=6.0.0" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, "node_modules/electron-to-chromium": { "version": "1.4.569", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.569.tgz", "integrity": "sha512-LsrJjZ0IbVy12ApW3gpYpcmHS3iRxH4bkKOW98y1/D+3cvDUWGcbzbsFinfUS8knpcZk/PG/2p/RnkMCYN7PVg==", "dev": true }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, "node_modules/es-abstract": { "version": "1.22.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", @@ -2186,11 +2477,32 @@ "node": ">=0.10.0" } }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { "version": "3.3.2", @@ -2232,6 +2544,19 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", + "dependencies": { + "punycode": "^1.3.2" + } + }, + "node_modules/fast-url-parser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" + }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -2435,6 +2760,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", @@ -2614,6 +2950,14 @@ "react-is": "^16.7.0" } }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, "node_modules/ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", @@ -2673,6 +3017,11 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, "node_modules/internal-slot": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", @@ -2795,6 +3144,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2816,6 +3179,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-generator-function": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", @@ -2897,6 +3268,17 @@ "node": ">=8" } }, + "node_modules/is-port-reachable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-port-reachable/-/is-port-reachable-4.0.0.tgz", + "integrity": "sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -2934,6 +3316,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -3013,6 +3406,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -3022,8 +3426,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/iterator.prototype": { "version": "1.1.2", @@ -3199,6 +3602,11 @@ "yallist": "^3.0.2" } }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3240,11 +3648,18 @@ "node": ">= 0.6" } }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3252,6 +3667,14 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -3293,6 +3716,14 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/node-releases": { "version": "2.0.13", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", @@ -3317,6 +3748,17 @@ "node": ">=0.10.0" } }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -3432,6 +3874,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3441,6 +3891,20 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -3518,11 +3982,15 @@ "node": ">=0.10.0" } }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==" + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -3533,6 +4001,11 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -3746,7 +4219,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, "engines": { "node": ">=6" } @@ -3771,6 +4243,36 @@ } ] }, + "node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -3984,6 +4486,34 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dependencies": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==", + "dependencies": { + "rc": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/reselect": { "version": "4.1.8", "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", @@ -4097,6 +4627,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/safe-regex-test": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", @@ -4128,6 +4663,95 @@ "semver": "bin/semver.js" } }, + "node_modules/serve": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/serve/-/serve-14.2.1.tgz", + "integrity": "sha512-48er5fzHh7GCShLnNyPBRPEjs2I6QBozeGr02gaacROiyS/8ARADlj595j39iZXAqBbJHH/ivJJyPRWY9sQWZA==", + "dependencies": { + "@zeit/schemas": "2.29.0", + "ajv": "8.11.0", + "arg": "5.0.2", + "boxen": "7.0.0", + "chalk": "5.0.1", + "chalk-template": "0.4.0", + "clipboardy": "3.0.0", + "compression": "1.7.4", + "is-port-reachable": "4.0.0", + "serve-handler": "6.1.5", + "update-check": "1.5.4" + }, + "bin": { + "serve": "build/main.js" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/serve-handler": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", + "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", + "dependencies": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.1.2", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" + } + }, + "node_modules/serve-handler/node_modules/mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-handler/node_modules/mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dependencies": { + "mime-db": "~1.33.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/serve/node_modules/chalk": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", + "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/serve/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "node_modules/set-function-length": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", @@ -4161,7 +4785,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -4173,7 +4796,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -4192,6 +4814,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", @@ -4201,6 +4828,47 @@ "node": ">=0.10.0" } }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/string.prototype.matchall": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", @@ -4270,7 +4938,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -4278,6 +4945,14 @@ "node": ">=8" } }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -4598,11 +5273,19 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/update-check": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.4.tgz", + "integrity": "sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==", + "dependencies": { + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -4621,6 +5304,14 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/vite": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", @@ -4680,7 +5371,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -4767,6 +5457,72 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "dependencies": { + "string-width": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/client/package.json b/client/package.json index b03f37f11..170719cfc 100644 --- a/client/package.json +++ b/client/package.json @@ -22,7 +22,8 @@ "redux": "^4.2.1", "redux-logger": "^3.0.6", "redux-persist": "^6.0.0", - "redux-thunk": "^2.4.2" + "redux-thunk": "^2.4.2", + "serve": "^14.2.1" }, "devDependencies": { "@types/react": "^18.2.15", From 8271ed346fa609e80787106e4235615dbb130591 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Sun, 12 Nov 2023 20:30:47 -0500 Subject: [PATCH 097/130] edit start script for serve --- client/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/package.json b/client/package.json index 170719cfc..c76095f16 100644 --- a/client/package.json +++ b/client/package.json @@ -3,8 +3,9 @@ "private": true, "version": "0.0.0", "type": "module", + "proxy": "http://localhost:3001", "scripts": { - "start": "serve build -s -n -L -p $PORT", + "start": "serve dist -s -n -L -p $PORT", "dev": "vite", "build": "vite build", "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", From f21d4e0e56601fd0c5302584ec722de300df2c2a Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sun, 12 Nov 2023 21:08:20 -0500 Subject: [PATCH 098/130] added user icon --- client/src/pages/Profiles.jsx | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/client/src/pages/Profiles.jsx b/client/src/pages/Profiles.jsx index 1acab546b..80eb6b860 100644 --- a/client/src/pages/Profiles.jsx +++ b/client/src/pages/Profiles.jsx @@ -1,5 +1,7 @@ import React, { useState } from 'react'; import ListingCard from '../components/ListingCard'; +import ProfileListing from './ProfileListing'; +import UserIcon from '../jsons/UserIcon.json' function Profiles() { const [activeTab, setActiveTab] = useState('user'); // 'user' or 'listings' @@ -52,10 +54,10 @@ function Profiles() { console.log('unsuccessful') }; - + return ( -
+
@@ -78,7 +80,20 @@ function Profiles() { {activeTab === 'user' && (

User Profile

+
    + {UserIcon.map(icon => ( +
  • + {`avatar`} +

    {icon.name}

    +
  • + ))} +
+ +
+ + +
)} - {activeTab === 'listings' &&

Listings

} + {activeTab === 'listings' && ( +
+ +
+ )} - {/* {activeTab === 'listings' && } */} - {/*
*/}
From fcb6355f6acc3bef14bc05ce1b515d35b507c084 Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sun, 12 Nov 2023 21:08:39 -0500 Subject: [PATCH 099/130] made json for testing --- client/src/jsons/UserIcon.json | 7 +++++++ client/src/jsons/listings.json | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 client/src/jsons/UserIcon.json create mode 100644 client/src/jsons/listings.json diff --git a/client/src/jsons/UserIcon.json b/client/src/jsons/UserIcon.json new file mode 100644 index 000000000..d5108d6ab --- /dev/null +++ b/client/src/jsons/UserIcon.json @@ -0,0 +1,7 @@ +[ + { + + "avatar": "https://i.pinimg.com/originals/84/26/36/8426368e9df8aaca0aff5e6a61ca3adb.jpg" + } + ] + \ No newline at end of file diff --git a/client/src/jsons/listings.json b/client/src/jsons/listings.json new file mode 100644 index 000000000..53df74a8f --- /dev/null +++ b/client/src/jsons/listings.json @@ -0,0 +1,33 @@ +[ + { + "title": "Beautiful Ann Arbor Suburban Home", + "property_id": 2, + "price_per_night": "$230.00" + }, + { + "title": "Cabin Home in Ann Arbor Outskirts", + "property_id": 1, + "price_per_night": "$130.00" + }, + { + "title": "Apartment in Dallas Right Across from Major Transit Hub", + "property_id": 4, + "price_per_night": "$175.00" + }, + { + "title": "Apartment in Gated Community in Dallas", + "property_id": 3, + "price_per_night": "$130.00" + }, + { + "title": "Large Guest House in Peaceful Vermont Countryside", + "property_id": 5, + "price_per_night": "$125.00" + }, + { + "title": "The best Bed and Breakfast in Vermont", + "property_id": 6, + "price_per_night": "200.00" + } + ] + \ No newline at end of file From b756fe184405fe45e93cc289c960bd3f2839f183 Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sun, 12 Nov 2023 21:09:03 -0500 Subject: [PATCH 100/130] made listing page --- client/src/pages/ProfileListing.jsx | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 client/src/pages/ProfileListing.jsx diff --git a/client/src/pages/ProfileListing.jsx b/client/src/pages/ProfileListing.jsx new file mode 100644 index 000000000..46665fe79 --- /dev/null +++ b/client/src/pages/ProfileListing.jsx @@ -0,0 +1,21 @@ +import React from 'react'; +import listings from '../jsons/listings.json'; + +function ProfileListing() { + return ( +
+

Listings

+
    + {listings.map(listing => ( +
  • +

    {listing.title}

    +

    Property ID: {listing.property_id}

    +

    Price per night: {listing.price_per_night}

    +
  • + ))} +
+
+ ); +} + +export default ProfileListing; From 6e6f8b672b48c1d7b6193565df6050b6666cb783 Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sun, 12 Nov 2023 22:58:13 -0500 Subject: [PATCH 101/130] made form for adding a listing, make a delete and edit button, delete button fully functional --- client/src/pages/ProfileListing.jsx | 156 +++++++++++++++++++++++++++- 1 file changed, 152 insertions(+), 4 deletions(-) diff --git a/client/src/pages/ProfileListing.jsx b/client/src/pages/ProfileListing.jsx index 46665fe79..7639e5537 100644 --- a/client/src/pages/ProfileListing.jsx +++ b/client/src/pages/ProfileListing.jsx @@ -1,13 +1,161 @@ -import React from 'react'; +import React, { useState } from 'react'; import listings from '../jsons/listings.json'; function ProfileListing() { + const [showForm, setShowForm] = useState(false); + const [formData, setFormData] = useState({ + title: '', + id: '', + price: '', + img: '', + }); + const [userListings, setUserListings] = useState([]); + + const handleAddListingClick = () => { + setShowForm(!showForm); + }; + + const handleInputChange = (e) => { + const { name, value } = e.target; + setFormData((prevFormData) => ({ + ...prevFormData, + [name]: value, + })); + }; + + const handleEditListing = (index) => { + console.log(`Edit clicked for index: ${index}`); + }; + + const handleDeleteListing = (index) => { + const updatedListings = [...userListings]; + updatedListings.splice(index, 1); + setUserListings(updatedListings); + }; + + const handleFormSubmit = (e) => { + e.preventDefault(); + + // Add the form data to the list of user listings + setUserListings([...userListings, formData]); + + // Clear the form data + setFormData({ + title: '', + id: '', + price: '', + img: '', + }); + + // Hide the form + setShowForm(false); + + + + } + + return (

Listings

-
    - {listings.map(listing => ( -
  • + + + + {showForm && ( +
    +
    + {/* Form fields go here */} + + + + + + + + + + + + + +
    + +
    + )} + +
      + {userListings.map((userListing, index) => ( +
    • +

      {userListing.title}

      +

      ID: {userListing.id}

      +

      Price per night: {userListing.price}

      + {userListing.img && {`Image} +
      + + +
      +
    • + ))} + + {/* Render existing listings */} + {listings.map((listing, index) => ( +
    • {listing.title}

      Property ID: {listing.property_id}

      Price per night: {listing.price_per_night}

      From 064888c6aac0e07c873750b9b419931087949636 Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sun, 12 Nov 2023 22:58:48 -0500 Subject: [PATCH 102/130] Made button for properties tab --- client/src/pages/Profiles.jsx | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/client/src/pages/Profiles.jsx b/client/src/pages/Profiles.jsx index 80eb6b860..2eba54bec 100644 --- a/client/src/pages/Profiles.jsx +++ b/client/src/pages/Profiles.jsx @@ -1,5 +1,4 @@ import React, { useState } from 'react'; -import ListingCard from '../components/ListingCard'; import ProfileListing from './ProfileListing'; import UserIcon from '../jsons/UserIcon.json' @@ -66,6 +65,18 @@ function Profiles() { > User Profile + + + + + +
{activeTab === 'user' && ( @@ -243,10 +256,15 @@ function Profiles() {
)} + {activeTab === 'properties' && ( +
+ properties +
+ )} -
- ); +
+ ); } export default Profiles; From ed26f80de9c192307b7ed37a51e1ade1b9cb55e5 Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Mon, 13 Nov 2023 02:23:38 -0500 Subject: [PATCH 103/130] added images to json --- client/src/jsons/listings.json | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/client/src/jsons/listings.json b/client/src/jsons/listings.json index 53df74a8f..903e48153 100644 --- a/client/src/jsons/listings.json +++ b/client/src/jsons/listings.json @@ -2,32 +2,41 @@ { "title": "Beautiful Ann Arbor Suburban Home", "property_id": 2, - "price_per_night": "$230.00" + "price_per_night": "$230.00", + "image_url": "https://i.ibb.co/VDrRDZF/Screen-Shot-2023-11-05-at-1-01-54-PM.png" + }, { "title": "Cabin Home in Ann Arbor Outskirts", "property_id": 1, - "price_per_night": "$130.00" + "price_per_night": "$130.00", + "image_url": "https://i.ibb.co/7gQsrnp/Screen-Shot-2023-11-05-at-1-02-16-PM.png" + }, { "title": "Apartment in Dallas Right Across from Major Transit Hub", "property_id": 4, - "price_per_night": "$175.00" + "price_per_night": "$175.00", + "image_url": "https://i.ibb.co/7bFzJy4/Screen-Shot-2023-11-05-at-1-02-24-PM.png" }, { "title": "Apartment in Gated Community in Dallas", "property_id": 3, - "price_per_night": "$130.00" + "price_per_night": "$130.00", + "image_url": "https://i.ibb.co/bQPF56V/Screen-Shot-2023-11-05-at-1-05-58-PM.png" }, { "title": "Large Guest House in Peaceful Vermont Countryside", "property_id": 5, - "price_per_night": "$125.00" + "price_per_night": "$125.00", + "image_url": "https://i.ibb.co/GFG88cM/Screen-Shot-2023-11-05-at-1-05-13-PM.png" }, { "title": "The best Bed and Breakfast in Vermont", "property_id": 6, - "price_per_night": "200.00" + "price_per_night": "200.00", + "image_url": "https://i.ibb.co/b7JKrbn/Screen-Shot-2023-11-05-at-1-08-37-PM.png" + } ] \ No newline at end of file From 090df8d1ddb74de802e9dcc9c52907890dcd4dcd Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Mon, 13 Nov 2023 02:24:19 -0500 Subject: [PATCH 104/130] added images from json, adjusted size of cards, allowed for easier listing and deleting --- client/src/pages/ProfileListing.jsx | 86 ++++++++++++++++------------- 1 file changed, 48 insertions(+), 38 deletions(-) diff --git a/client/src/pages/ProfileListing.jsx b/client/src/pages/ProfileListing.jsx index 7639e5537..47cff0af0 100644 --- a/client/src/pages/ProfileListing.jsx +++ b/client/src/pages/ProfileListing.jsx @@ -48,15 +48,11 @@ function ProfileListing() { }); // Hide the form - setShowForm(false); - - - + setShowForm(false); } - return ( -
+

Listings

- -
- - ))} +
    + {userListings.map((userListing, index) => ( +
  • +

    {userListing.title}

    + {/*

    ID: {userListing.id}

    */} +

    Price per night: ${parseFloat(userListing.price).toFixed(2)}

    + {userListing.img && ( + {`Image + )} +
    + + +
    +
  • + ))} + {/* Render existing listings */} + {listings.map((listing, index) => ( -
  • -

    {listing.title}

    -

    Property ID: {listing.property_id}

    -

    Price per night: {listing.price_per_night}

    -
  • - ))} -
+
  • +

    {listing.title}

    + {/*

    Property ID: {listing.property_id}

    */} +

    Price per night: {listing.price_per_night}

    + {listing.image_url && ( + {`Image + )} +
  • +))} + + + +
    ); } From 6d196bc6fa2aec247849eee20c0c3925bf9a0984 Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Mon, 13 Nov 2023 02:36:40 -0500 Subject: [PATCH 105/130] completed milestone 4 reflection --- milestones/milestone4.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/milestones/milestone4.md b/milestones/milestone4.md index 8c781fd23..0aa48e8b0 100644 --- a/milestones/milestone4.md +++ b/milestones/milestone4.md @@ -6,29 +6,29 @@ This document should be completed and submitted during **Unit 8** of this course This unit, be sure to complete all tasks listed below. To complete a task, place an `x` between the brackets. -- [ ] Update the status of issues in your project board as you complete them -- [ ] In `readme.md`, check off the features you have completed in this unit by adding a βœ… emoji in front of their title - - [ ] Under each feature you have completed, **include a GIF** showing feature functionality -- [ ] In this document, complete the **Reflection** section below +- [x] Update the status of issues in your project board as you complete them +- [x] In `readme.md`, check off the features you have completed in this unit by adding a βœ… emoji in front of their title + - [x] Under each feature you have completed, **include a GIF** showing feature functionality +- [x] In this document, complete the **Reflection** section below ## Reflection ### 1. What went well during this unit? -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ your answer here] +[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ What went well during this project was the team work. We meet very often for standups, and keep in contact everyday to discuss what to do for our project.] ### 2. What were some challenges your group faced in this unit? -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ your answer here] +[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ The main errors that occured were merge conflicts. We are still in the midst of resolving them. ] ### Did you finish all of your tasks in your sprint plan for this week? If you did not finish all of the planned tasks, how would you prioritize the remaining tasks on your list? -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ your answer here] +[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ Siobhan was able to finish, while I was unable to. I plan to dedicate more time this week and make a schedule for myself. ] ### Which features and user stories would you consider β€œat risk”? How will you change your plan if those items remain β€œat risk”? -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ your answer here] +[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ The perks section seems to be at risk due to time constraints, but we will try our best to implement it before it is time for presentations. Our plan is still the same, however, for the rest of our pages.] ### 5. What additional support will you need in upcoming units as you continue to work on your final project? -[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ your answer here] +[πŸ‘‰πŸΎπŸ‘‰πŸΎπŸ‘‰πŸΎ We will just need the TF's to check over our work and help us anywhere we have errors.] From ecf2fa9242d239a69f5ac9dd686b9a6a39634c19 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 13 Nov 2023 16:56:04 -0500 Subject: [PATCH 106/130] add propertiesReducer to root --- client/src/redux/rootReducer.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/redux/rootReducer.js b/client/src/redux/rootReducer.js index c9fe7cb05..b0e6ff6cf 100644 --- a/client/src/redux/rootReducer.js +++ b/client/src/redux/rootReducer.js @@ -1,8 +1,10 @@ import { combineReducers } from "@reduxjs/toolkit"; import userReducer from "./slices/userSlice"; +import propertiesReducer from "./slices/propertiesSlice"; const rootReducer = combineReducers({ user: userReducer, + properties: propertiesReducer, }); export default rootReducer; From 824d3c65a8c2f43e55198e763bc34950f07accab Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 13 Nov 2023 16:56:22 -0500 Subject: [PATCH 107/130] revise properties routes --- server/routes/properties.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/routes/properties.js b/server/routes/properties.js index c50f6aff0..9f7a9e6d1 100644 --- a/server/routes/properties.js +++ b/server/routes/properties.js @@ -4,7 +4,8 @@ import PropertiesController from "../controllers/properties.js"; const router = express.Router(); -router.get("/properties/:userId", PropertiesController.getUserProperties); -router.post("/properties/new/:userId", PropertiesController.postNewProperty); +router.get("/:userId", PropertiesController.getUserProperties); +router.get("/view/:propertyId", PropertiesController.getPropertyById); +router.post("/new/:userId", PropertiesController.postNewProperty); export default router; From fc909fc24deffa89949280658c2c4a3f10176851 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 13 Nov 2023 16:56:33 -0500 Subject: [PATCH 108/130] create properties slice --- client/src/redux/slices/propertiesSlice.js | 163 +++++++++++++++++++++ 1 file changed, 163 insertions(+) diff --git a/client/src/redux/slices/propertiesSlice.js b/client/src/redux/slices/propertiesSlice.js index e69de29bb..787e9d556 100644 --- a/client/src/redux/slices/propertiesSlice.js +++ b/client/src/redux/slices/propertiesSlice.js @@ -0,0 +1,163 @@ +import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"; +import axios from "axios"; + +const API_URL = + process.env.NODE_ENV === "production" + ? import.meta.env.VITE_SERVER_URL + : "http://localhost:3001"; + +export const fetchUserProperties = createAsyncThunk( + "properties/fetcUserProperties", + async ({ userId }, { dispatch }) => { + try { + const res = await axios.get( + `${API_URL}/api/properties/${userId}`, + {}, + { withCredentials: true } + ); + dispatch(setUserProperties(res.data)); + // const userData = res.data; + // return userData; + } catch (error) { + console.error("Error fetching user properties:", error); + throw error; + } + } +); + +export const fetchUserPropertyById = createAsyncThunk( + "properties/fetchUserPropertyById", + async ({ propertyId }, { dispatch }) => { + try { + const res = await axios.get( + `${API_URL}/api/properties/view/${propertyId}`, + {}, + { withCredentials: true } + ); + dispatch(setCurrentProperty(res.data)); + } catch (error) { + console.error("Error fetching single property", error); + throw error; + } + } +); + +export const createNewUserProperty = createAsyncThunk( + "properties/createNewUserProperty", + async ( + { + address1, + address2, + city, + state, + zipcode, + rating, + numBeds, + numBaths, + numBedrooms, + propertyType, + imagesArray, + amenitiesArray, + }, + { dispatch } + ) => { + try { + const res = await axios.put( + `${API_URL}/api/properties/${hostId}`, + { + address1, + address2, + city, + state, + zipcode, + rating, + numBeds, + numBaths, + numBedrooms, + propertyType, + imagesArray, + amenitiesArray, + }, + { withCredentials: true } + ); + dispatch(addUserPropertyToList(res.data)); + } catch (error) { + console.error("Error creating new user property", error); + throw error; + } + } +); + +const initialState = { + userProperties: [], + currentProperty: [], + error: null, +}; + +const propertiesSlice = createSlice({ + name: "properties", + initialState, + reducers: { + setUserProperties: (state, action) => { + state.userProperties = action.payload; + }, + setCurrentProperty: (state, action) => { + state.currentProperty = action.payload; + }, + addUserPropertyToList(state) { + if (state.currentProperty) { + state.userProperties.push(state.currentProperty); + } + }, + setError: (state, action) => { + state.error = action.payload; + }, + }, + extraReducers: (builder) => { + builder + .addCase(fetchUserProperties.pending, (state) => { + state.status = "loading"; + state.error = null; + }) + .addCase(fetchUserProperties.fulfilled, (state, action) => { + state.status = "succeeded"; + // state.loggedInUser = action.payload; + }) + .addCase(fetchUserProperties.rejected, (state, action) => { + state.status = "failed"; + state.error = action.error.message; + }) + .addCase(fetchUserPropertyById.pending, (state) => { + state.status = "loading"; + state.error = null; + }) + .addCase(fetchUserPropertyById.fulfilled, (state, action) => { + state.status = "succeeded"; + // state.loggedInUser = action.payload; + }) + .addCase(fetchUserPropertyById.rejected, (state, action) => { + state.status = "failed"; + state.error = action.error.message; + }) + .addCase(createNewUserProperty.pending, (state) => { + state.status = "loading"; + state.error = null; + }) + .addCase(createNewUserProperty.fulfilled, (state, action) => { + state.status = "succeeded"; + // state.loggedInUser = action.payload; + }) + .addCase(createNewUserProperty.rejected, (state, action) => { + state.status = "failed"; + state.error = action.error.message; + }); + }, +}); + +export const { + setUserProperties, + setCurrentProperty, + addUserPropertyToList, + setError, +} = propertiesSlice.actions; +export default propertiesSlice.reducer; From 11df346183bfab067028563e8749fa5878520fee Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Mon, 13 Nov 2023 16:57:17 -0500 Subject: [PATCH 109/130] edit logic to get and post properties --- server/controllers/properties.js | 34 +++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/server/controllers/properties.js b/server/controllers/properties.js index ebb8ddae3..9e603600e 100644 --- a/server/controllers/properties.js +++ b/server/controllers/properties.js @@ -2,12 +2,35 @@ import { pool } from "../config/database.js"; const getUserProperties = async (request, response) => { try { - const userId = parseInt(request.params.id); + // Validate and parse userId as an integer + const parsedUserId = parseInt(request.params.userId); + if (isNaN(parsedUserId)) { + throw new Error("Invalid userId"); + } + + // Your SQL query with the parsed userId const properties = await pool.query( - "SELECT listings.*, ARRAY_AGG(listingsImages.image_url) AS image_urls, propertyAmenities.* FROM listings LEFT JOIN listingsImages ON listings.property_id = listingsImages.property_id JOIN propertyAmenities ON listings.property_id = propertyAmenities.property_id WHERE listings.user_id = $1 GROUP BY listings.id, propertyAmenities.property_id;", - [userId] + "SELECT properties.*, ARRAY_AGG(listingImages.image_url) AS image_urls, propertyAmenities.* FROM properties LEFT JOIN listings ON properties.id = listings.property_id LEFT JOIN listingImages ON properties.id = listingImages.property_id LEFT JOIN propertyAmenities ON properties.id = propertyAmenities.property_id WHERE properties.host_id = $1 GROUP BY properties.id, propertyAmenities.id", + [parsedUserId] + ); + + return response.status(200).json(properties.rows); + } catch (err) { + console.error("⚠️ error fetching user properties", err); + throw err; // Rethrow the error to handle it in the calling code + } +}; + +const getPropertyById = async (request, response) => { + console.log("hello"); + try { + const propertyId = parseInt(request.params.propertyId); + console.log("hello world"); + const singleProperty = await pool.query( + "SELECT * FROM properties WHERE id = $1", + [propertyId] ); - response.status(200).json(properties.rows); + response.status(200).json(singleProperty.rows[0]); } catch (error) { response.status(409).json({ error: error.message }); } @@ -105,7 +128,7 @@ const postNewProperty = async (request, response) => { for (image of imagesArray) { try { const addedImages = await pool.query( - "INSERT INTO listingsImages (property_id, image_url) VALUES ($1, $2) RETURNING *", + "INSERT INTO listingImages (property_id, image_url) VALUES ($1, $2) RETURNING *", [propertyId, image] ); response.json(addedImages.rows[0]); @@ -126,4 +149,5 @@ const postNewProperty = async (request, response) => { export default { getUserProperties, postNewProperty, + getPropertyById, }; From 798d2baee89c9e48d18f1fd43067f3b0044673cd Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 17 Nov 2023 22:04:20 -0500 Subject: [PATCH 110/130] route to get a single user information --- client/src/App.jsx | 4 +- client/src/components/DropdownMenu.jsx | 2 +- client/src/components/PropertyCard.jsx | 68 +++ client/src/containers/ListingsContainer.jsx | 2 +- client/src/containers/PropertiesContainer.jsx | 21 + client/src/pages/Profile.jsx | 415 ++++++++++++++++++ client/src/pages/Profiles.jsx | 270 ------------ client/src/redux/slices/userSlice.js | 2 +- server/routes/users.js | 9 + server/server.js | 2 +- 10 files changed, 519 insertions(+), 276 deletions(-) create mode 100644 client/src/components/PropertyCard.jsx create mode 100644 client/src/containers/PropertiesContainer.jsx create mode 100644 client/src/pages/Profile.jsx delete mode 100644 client/src/pages/Profiles.jsx create mode 100644 server/routes/users.js diff --git a/client/src/App.jsx b/client/src/App.jsx index 8b746b770..ef08fa804 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -4,7 +4,7 @@ import Listings from "./pages/Listings"; import { BrowserRouter as Router, Route, Routes } from "react-router-dom"; import "./App.css"; import Navbar from "./components/Navbar"; -import Profiles from "./pages/Profiles"; +import Profile from "./pages/Profile"; function App() { const [listings, setListings] = useState([]); @@ -42,7 +42,7 @@ function App() { {element}
    - } /> + } /> ); diff --git a/client/src/components/DropdownMenu.jsx b/client/src/components/DropdownMenu.jsx index 44804e733..6764de0db 100644 --- a/client/src/components/DropdownMenu.jsx +++ b/client/src/components/DropdownMenu.jsx @@ -76,7 +76,7 @@ const DropdownMenu = ({ toggleDropdown, toggleLoginModal, isDropdownOpen }) => { - {user ? ( + {user && user.length > 0 ? (
    + + + + +
    + + {activeTab === "user" && ( +
    +

    User Profile

    +
      + {UserIcon.map((icon) => ( +
    • + setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + /> + {user.image_url ? ( +
      {user.image_url}
      + ) : ( + + )} +

      {icon.name}

      +
    • + ))} +
    + {isUploadingPhoto ? ( +
    setIsPhotoIconHovered(false)} + > + setIsPhotoIconHovered(true)} + > + + + {isPhotoIconHovered && ( + + )} + + + + +
    + ) : ( + <> + )} + +
    +
    + + +
    + +
    + + +
    +
    + +
    +
    + + {user.address1 ? ( + + ) : ( + + )} +
    + +
    + + {user.address2 ? ( + + ) : ( + + )} +
    +
    + +
    +
    + + {user.city ? ( + + ) : ( + + )} +
    + +
    + + {user.state ? ( + + ) : ( + + )} +
    +
    + +
    +
    + + +
    + +
    + + +
    +
    + +
    + )} + + {/* {activeTab === "listings" && ( +
    + +
    + )} */} + + {activeTab === "properties" &&
    properties
    } + + ) : ( +
    loading...
    + ); +}; +export default Profile; diff --git a/client/src/pages/Profiles.jsx b/client/src/pages/Profiles.jsx deleted file mode 100644 index 2eba54bec..000000000 --- a/client/src/pages/Profiles.jsx +++ /dev/null @@ -1,270 +0,0 @@ -import React, { useState } from 'react'; -import ProfileListing from './ProfileListing'; -import UserIcon from '../jsons/UserIcon.json' - -function Profiles() { - const [activeTab, setActiveTab] = useState('user'); // 'user' or 'listings' - const [userData, setUserData] = useState({ - firstName: '', - lastName: '', - email: '', - password: '', - }); - const [fieldErrors, setFieldErrors] = useState({ - firstName: false, - lastName: false, - address: false, - city: false, - state: false, - zipcode: false, - email: false, - password: false, - }); - - - const handleInputChange = (e) => { - const { name, value } = e.target; - setUserData((prevUserData) => ({ - ...prevUserData, - [name]: value, - })); - // Clear the error when the user starts typing in the field - setFieldErrors((prevErrors) => ({ - ...prevErrors, - [name]: false, - })); - }; - - const handleUpdateProfile = () => { - // Check for empty fields and set errors - const errors = {}; - Object.entries(userData).forEach(([key, value]) => { - if (value.trim() === '') { - errors[key] = true; - } - }); - setFieldErrors(errors); - - // If no errors, proceed with updating the profile - if (Object.keys(errors).length === 0) { - // Add logic to update the profile - console.log('Profile updated successfully!'); - } - console.log('unsuccessful') - }; - - - - return ( -
    -
    - - - - - - - - -
    - - {activeTab === 'user' && ( -
    -

    User Profile

    -
      - {UserIcon.map(icon => ( -
    • - {`avatar`} -

      {icon.name}

      -
    • - ))} -
    - - -
    - - - -
    - - -
    - -
    - - -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    - -
    -
    - - -
    - -
    - - -
    -
    - -
    - - -
    - -
    -
    - - -
    - -
    - - -
    -
    - - - -
    - )} - - {activeTab === 'listings' && ( -
    - -
    - )} - - {activeTab === 'properties' && ( -
    - properties -
    - )} - - -
    - ); -} - -export default Profiles; diff --git a/client/src/redux/slices/userSlice.js b/client/src/redux/slices/userSlice.js index ecd48ec63..4ae26a525 100644 --- a/client/src/redux/slices/userSlice.js +++ b/client/src/redux/slices/userSlice.js @@ -134,7 +134,7 @@ const userSlice = createSlice({ }) .addCase(authLogOut.fulfilled, (state, action) => { state.status = "succeeded"; - state.loggedInUser = null; + state.loggedInUser = []; // Set to an empty array }) .addCase(authLogOut.rejected, (state, action) => { state.status = "failed"; diff --git a/server/routes/users.js b/server/routes/users.js new file mode 100644 index 000000000..c72f9ebf8 --- /dev/null +++ b/server/routes/users.js @@ -0,0 +1,9 @@ +import express from "express"; + +import UsersController from "../controllers/users.js"; + +const router = express.Router(); + +router.get("/:id", UsersController.getUserById); + +export default router; diff --git a/server/server.js b/server/server.js index b456be17f..776a87e72 100644 --- a/server/server.js +++ b/server/server.js @@ -15,7 +15,7 @@ import connectPgSimple from "connect-pg-simple"; const CLIENT_URL = process.env.NODE_ENV === "production" ? process.env.PROD_CLIENT_URL - : process.env.DEV_CLIENT_URL; + : "http://localhost:5173"; const API_URL = process.env.NODE_ENV === "production" From ef4da98532771f21cce499cded574b3f7f30e814 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 17 Nov 2023 22:04:40 -0500 Subject: [PATCH 111/130] controller to fetch user by id --- server/controllers/users.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 server/controllers/users.js diff --git a/server/controllers/users.js b/server/controllers/users.js new file mode 100644 index 000000000..f6e8b2455 --- /dev/null +++ b/server/controllers/users.js @@ -0,0 +1,13 @@ +import { pool } from "../config/database.js"; + +const getUserById = async (req, res) => { + try { + const id = parseInt(req.params.id); + const user = await pool.query("SELECT * FROM users WHERE id = $1", [id]); + res.json(user.rows[0]); + } catch (error) { + res.status(500).json({ error: "Internal server error " }); + } +}; + +export default { getUserById }; From 3378898747d454dfdfb83ee772feb9e921dbe6cb Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 17 Nov 2023 22:04:58 -0500 Subject: [PATCH 112/130] include profile and users routes --- server/server.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/server.js b/server/server.js index 776a87e72..2a1a2ccd3 100644 --- a/server/server.js +++ b/server/server.js @@ -3,6 +3,8 @@ import cors from "cors"; import listingsRoutes from "./routes/listings.js"; import propertiesRoutes from "./routes/properties.js"; import authRoutes from "./routes/auth.js"; +import profileRoutes from "./routes/profile.js"; +import userRoutes from "./routes/users.js"; import passport from "passport"; import session from "express-session"; // import { GitHub } from "./config/auth.js"; @@ -78,6 +80,8 @@ app.use((req, res, next) => { app.use("/api", listingsRoutes); app.use("/api/auth", authRoutes); app.use("/api/properties", propertiesRoutes); +app.use("/api/profile", profileRoutes); +app.use("/api/users", userRoutes); app.listen(PORT, () => { console.log(`πŸš€ Server running on http://localhost:${PORT}`); From 7e1b5480b0e80b79754c4e49fa00f6baddb55428 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 17 Nov 2023 22:05:12 -0500 Subject: [PATCH 113/130] routes for profile update photo --- server/routes/profile.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/server/routes/profile.js b/server/routes/profile.js index bbb647e46..e76870a8c 100644 --- a/server/routes/profile.js +++ b/server/routes/profile.js @@ -1,8 +1,9 @@ -import express from 'express'; -import ProfileController from '../controllers/profile.js' +import express from "express"; +import ProfileController from "../controllers/profile.js"; const router = express.Router(); -router.put('/profile', ProfileController.updateUserProfile) +router.put("/profile", ProfileController.updateUserProfile); +router.patch("/new-profile-photo", ProfileController.updateUserProfilePhoto); -export default router; \ No newline at end of file +export default router; From 46a54be8d16ab5a6f225273f1cf23b0e74197730 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 17 Nov 2023 22:05:24 -0500 Subject: [PATCH 114/130] update profile photo controller --- server/controllers/profile.js | 104 +++++++++++++++++++++------------- 1 file changed, 65 insertions(+), 39 deletions(-) diff --git a/server/controllers/profile.js b/server/controllers/profile.js index dead720bf..b76aa9897 100644 --- a/server/controllers/profile.js +++ b/server/controllers/profile.js @@ -1,44 +1,70 @@ import { pool } from "../config/database.js"; -const updateUserProfile = (async(req, res) => { - try { - //get user data from the request - const { user } = req; - - //check if the user is authenticated. if they are not, then return a 401 unauthorized error - if (!user){ - return res.status(401).json({ error: 'Unauthorized' }); - } - - //access the users ID from the user object if it's stored in session or token - const userId = user.id; - - //verify the user is updating their own profile by checking the user ID - if(userId != req.params.userId) { - return res.status(403).json({ error: "Forbiden. You can only update your own profile."}) - } - - //update the users email: - const { newEmail } = req.body; //assuming the new email is sent in the request body - - //update user's email in the database: - const updateQuery = "UPDATE users SET email = $1 WHERE id = $2" - const updateValues = [newEmail, userId]; - - const result = await pool.query(updateQuery, updateValues) - - if(result.rowCount > 0) { - res.json({ message: "Profile updated successfully. "}) - } else { - res.status(500).json({ error: 'Profile update failed.' }) - } - - // res.json({ message: "Profile updated successfully." }) - } catch (error) { - res.status(500).json({ error: 'Internal server error '}) +const updateUserProfile = async (req, res) => { + try { + //get user data from the request + const { user } = req; + + //check if the user is authenticated. if they are not, then return a 401 unauthorized error + if (!user) { + return res.status(401).json({ error: "Unauthorized" }); + } + + //access the users ID from the user object if it's stored in session or token + const userId = user.id; + + //verify the user is updating their own profile by checking the user ID + if (userId != req.params.userId) { + return res + .status(403) + .json({ error: "Forbiden. You can only update your own profile." }); + } + + //update the users email: + const { newEmail } = req.body; //assuming the new email is sent in the request body + + //update user's email in the database: + const updateQuery = "UPDATE users SET email = $1 WHERE id = $2"; + const updateValues = [newEmail, userId]; + + const result = await pool.query(updateQuery, updateValues); + + if (result.rowCount > 0) { + res.json(result); + } else { + res.status(500).json({ error: "Profile update failed." }); + } + + res.json({ message: "Profile updated successfully." }); + } catch (error) { + res.status(500).json({ error: "Internal server error " }); + } +}; + +const updateUserProfilePhoto = async (req, res) => { + try { + //update the users email: + const { id, newImageUrl } = req.body; //assuming the new email is sent in the request body + + //update user's email in the database: + const updateQuery = "UPDATE users SET image_url = $1 WHERE id = $2"; + const updateValues = [newImageUrl, id]; + + const result = await pool.query(updateQuery, updateValues); + + if (result.rowCount > 0) { + res.json({ message: "Profile updated successfully. " }); + } else { + res.status(500).json({ error: "Profile update failed." }); } -}) + + // res.json({ message: "Profile updated successfully." }) + } catch (error) { + res.status(500).json({ error: "Internal server error " }); + } +}; export default { - updateUserProfile -} \ No newline at end of file + updateUserProfile, + updateUserProfilePhoto, +}; From 4d590ed4fdc4dd3318cdcda0f2332484dc803d2c Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 17 Nov 2023 22:06:00 -0500 Subject: [PATCH 115/130] ttempt to update the profile photo --- client/src/redux/slices/userSlice.js | 69 ++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/client/src/redux/slices/userSlice.js b/client/src/redux/slices/userSlice.js index 4ae26a525..62bd28ba4 100644 --- a/client/src/redux/slices/userSlice.js +++ b/client/src/redux/slices/userSlice.js @@ -1,6 +1,7 @@ import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"; import axios from "axios"; import { set } from "date-fns"; +import cloneDeep from "lodash/cloneDeep"; const API_URL = process.env.NODE_ENV === "production" @@ -74,9 +75,47 @@ export const authLogOut = createAsyncThunk( } ); +export const fetchUpdatedUserInfo = createAsyncThunk( + "user/fetchUpdatedUserInfo", + async (userId, { dispatch }) => { + try { + // Make your API request to fetch updated user information + const res = await axios.get(`${API_URL}/api/users/${userId}`, { + withCredentials: true, + }); + + // Dispatch the action to update the user in the Redux store + dispatch(setLoggedInUser(res.data)); + } catch (error) { + console.error("Error fetching updated user information:", error); + throw error; + } + } +); + +export const postNewProfilePhoto = createAsyncThunk( + "user/postNewProfilePhoto", + async ({ userId, newImageUrl }, { dispatch }) => { + try { + // Make your API request + console.log(newImageUrl, "image url from redux"); + const res = await axios.patch( + `${API_URL}/api/profile/new-profile-photo`, + { id: userId, image_url: newImageUrl }, + { withCredentials: true } + ); + // Dispatch the fetchUpdatedUserInfo thunk to refetch the user details + dispatch(fetchUpdatedUserInfo(userId)); + } catch (error) { + console.error("Error posting new profile photo:", error); + throw error; + } + } +); + const initialState = { email: null, - loggedInUser: [], + loggedInUser: null, isLoggedIn: false, isAuthenticated: false, error: null, @@ -101,6 +140,9 @@ const userSlice = createSlice({ setError: (state, action) => { state.error = action.payload; }, + updateLoggedInUserImageUrl: (state, action) => { + state.loggedInUser.image_url = action.payload; + }, }, extraReducers: (builder) => { builder @@ -122,6 +164,7 @@ const userSlice = createSlice({ }) .addCase(authRegister.fulfilled, (state, action) => { state.status = "succeeded"; + console.log(action.payload, "action payload create"); state.loggedInUser = action.payload; }) .addCase(authRegister.rejected, (state, action) => { @@ -134,15 +177,33 @@ const userSlice = createSlice({ }) .addCase(authLogOut.fulfilled, (state, action) => { state.status = "succeeded"; - state.loggedInUser = []; // Set to an empty array + state.loggedInUser = null; // Set to an empty array }) .addCase(authLogOut.rejected, (state, action) => { state.status = "failed"; state.error = action.error.message; + }) + .addCase(fetchUpdatedUserInfo.pending, (state) => { + state.error = null; + state.status = "loading"; + }) + .addCase(postNewProfilePhoto.rejected, (state, action) => { + const actionWithoutCircularRefs = cloneDeep(action); + console.error( + "Error during postNewProfilePhoto:", + actionWithoutCircularRefs + ); + state.status = "failed"; + state.error = action.error.message; }); }, }); -export const { setEmail, toggleLoggedIn, setAuthenticated, setLoggedInUser } = - userSlice.actions; +export const { + setEmail, + toggleLoggedIn, + setAuthenticated, + setLoggedInUser, + updateLoggedInUserImageUrl, +} = userSlice.actions; export default userSlice.reducer; From 3149b06d5beb4b12064917557801a344277e5186 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 17 Nov 2023 22:06:17 -0500 Subject: [PATCH 116/130] form update --- client/src/pages/Profile.jsx | 90 +++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 37 deletions(-) diff --git a/client/src/pages/Profile.jsx b/client/src/pages/Profile.jsx index 38ba8facd..2ac8bfd95 100644 --- a/client/src/pages/Profile.jsx +++ b/client/src/pages/Profile.jsx @@ -6,11 +6,12 @@ import { useSelector, useDispatch } from "react-redux"; import { IoIosAddCircle } from "react-icons/io"; import { RxAvatar } from "react-icons/rx"; import { MdAddAPhoto } from "react-icons/md"; -// import { postNewProfilePhoto } from "../redux/slices/userSlice"; +import { postNewProfilePhoto } from "../redux/slices/userSlice"; const Profile = () => { const dispatch = useDispatch(); - const { userId } = useParams(); + const { id } = useParams(); + console.log(id, "user IDDDD"); const [activeTab, setActiveTab] = useState("user"); // 'user' or 'listings' const [userData, setUserData] = useState({ firstName: "", @@ -26,6 +27,7 @@ const Profile = () => { city: false, state: false, }); + const [imageUrl, setImageUrl] = useState(""); const [isUploadingPhoto, setIsUploadingPhoto] = useState(false); const [isHovered, setIsHovered] = useState(false); const [isPhotoIconHovered, setIsPhotoIconHovered] = useState(false); @@ -46,15 +48,21 @@ const Profile = () => { })); }; - const setProfilePhoto = async (image_url) => { - if (user && user.id) { - // Only proceed if user.id is present - console.log("hello i'm updating the photo"); - // await dispatch( - // postNewProfilePhoto({ userId: user.id, imageUrl: image_url }) - // ); + const setProfilePhoto = () => { + if (user && user.id && imageUrl) { + // Only proceed if user.id and imageUrl are present + console.log("Hello, I'm updating the photo"); + dispatch(postNewProfilePhoto({ userId: user?.id, newImageUrl: imageUrl })) + .then(() => { + // Additional logic after the photo is updated successfully + }) + .catch((error) => { + console.error("Error updating profile photo:", error); + }); } else { - console.error("User ID is not present. Cannot set profile photo."); + console.error( + "User ID or Image URL is missing. Cannot set profile photo." + ); } }; @@ -103,7 +111,7 @@ const Profile = () => { return user ? (
    -
    +
    {activeTab === "user" && ( -
    +

    User Profile

    -
      - {UserIcon.map((icon) => ( -
    • - setIsHovered(true)} - onMouseLeave={() => setIsHovered(false)} - /> - {user.image_url ? ( -
      {user.image_url}
      - ) : ( - - )} -

      {icon.name}

      -
    • - ))} -
    +
    +
    + setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + /> +
    +
    + {user.image_url ? ( +
    {user.image_url}
    + ) : ( + + )} +
    +
    {isUploadingPhoto ? (
    { setIsPhotoIconHovered(true)} + style={{ cursor: "pointer !important" }} > @@ -198,12 +207,19 @@ const Profile = () => { id="website-admin" className="rounded-none bg-gray-50 border text-gray-900 focus:ring-blue-500 focus:border-blue-500 block flex-1 min-w-0 w-full text-sm border-gray-300 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="Image Url" + onChange={(e) => setImageUrl(e.target.value)} /> - +
    ) : ( From cde72d8e9a517c661ea1f9627b533a91383a7c43 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 17 Nov 2023 22:06:31 -0500 Subject: [PATCH 117/130] update logic for dropdown login/logout --- client/src/components/DropdownMenu.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/components/DropdownMenu.jsx b/client/src/components/DropdownMenu.jsx index 6764de0db..1109c08ca 100644 --- a/client/src/components/DropdownMenu.jsx +++ b/client/src/components/DropdownMenu.jsx @@ -35,7 +35,7 @@ const DropdownMenu = ({ toggleDropdown, toggleLoginModal, isDropdownOpen }) => { {isDropdownOpen && (
    - {user ? ( + {user && user.id ? ( <>
    {user.first_name} {user.last_name} @@ -49,7 +49,7 @@ const DropdownMenu = ({ toggleDropdown, toggleLoginModal, isDropdownOpen }) => {
    • - +
    - {user && user.length > 0 ? ( + {user && user.id ? (
    - } /> + } />
    ); From 12aaf6053c8381073df3db47c491bce786fd8398 Mon Sep 17 00:00:00 2001 From: Saoirse Siobhan Ebert <91578619+itsgivingchaotica@users.noreply.github.com> Date: Fri, 17 Nov 2023 22:06:58 -0500 Subject: [PATCH 119/130] dependencies for testing --- client/package-lock.json | 6 ++++++ client/package.json | 1 + 2 files changed, 7 insertions(+) diff --git a/client/package-lock.json b/client/package-lock.json index fd6250157..a01a6f3d8 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -11,6 +11,7 @@ "@reduxjs/toolkit": "^1.9.7", "axios": "^1.6.0", "date-fns": "^2.30.0", + "lodash": "^4.17.21", "react": "^18.2.0", "react-dom": "^18.2.0", "react-icons": "^4.11.0", @@ -3576,6 +3577,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", diff --git a/client/package.json b/client/package.json index c76095f16..091ff8f77 100644 --- a/client/package.json +++ b/client/package.json @@ -15,6 +15,7 @@ "@reduxjs/toolkit": "^1.9.7", "axios": "^1.6.0", "date-fns": "^2.30.0", + "lodash": "^4.17.21", "react": "^18.2.0", "react-dom": "^18.2.0", "react-icons": "^4.11.0", From 99b04567532d0077a51c2eaafcb89459ce33d0ab Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Fri, 17 Nov 2023 23:38:43 -0500 Subject: [PATCH 120/130] designed listings page --- server/config/reset.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/config/reset.js b/server/config/reset.js index 27347b1d0..8fb330e59 100644 --- a/server/config/reset.js +++ b/server/config/reset.js @@ -379,4 +379,4 @@ const createSessionTable = async () => { // seedPropertyAmenitiesTable(); // seedListingAvailabilityTable(); // seedListingImagesTable(); -// createSessionTable(); +createSessionTable(); From 209696d9e052d6fca5533c120c8e4458058f54f8 Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Fri, 17 Nov 2023 23:41:14 -0500 Subject: [PATCH 121/130] fixed error where properties tab was not displaying --- client/src/pages/Profile.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/pages/Profile.jsx b/client/src/pages/Profile.jsx index 2ac8bfd95..dd1e206b0 100644 --- a/client/src/pages/Profile.jsx +++ b/client/src/pages/Profile.jsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from "react"; -// import ProfileListing from "./ProfileListing"; +import ProfileListing from "./ProfileListing"; import { useParams } from "react-router-dom"; // import UserIcon from "../jsons/UserIcon.json"; import { useSelector, useDispatch } from "react-redux"; @@ -416,11 +416,11 @@ const Profile = () => {
    )} - {/* {activeTab === "listings" && ( + {activeTab === "listings" && (
    - )} */} + )} {activeTab === "properties" &&
    properties
    }
    From 546c8f687edb6bdeecf78e1ce1ed64c18aaaa890 Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sat, 18 Nov 2023 01:56:04 -0500 Subject: [PATCH 122/130] added calendar components for check in and check out dates --- client/package-lock.json | 74 +++++++++++++++++++++++++++++++- client/package.json | 1 + client/src/components/Navbar.jsx | 48 ++++++++++++++++----- 3 files changed, 111 insertions(+), 12 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index a01a6f3d8..714118e95 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -13,6 +13,7 @@ "date-fns": "^2.30.0", "lodash": "^4.17.21", "react": "^18.2.0", + "react-datepicker": "^4.21.0", "react-dom": "^18.2.0", "react-icons": "^4.11.0", "react-redux": "^8.1.3", @@ -948,6 +949,15 @@ "node": ">= 8" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@reduxjs/toolkit": { "version": "1.9.7", "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.7.tgz", @@ -1724,6 +1734,11 @@ "node": ">= 6" } }, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "node_modules/cli-boxes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", @@ -3769,7 +3784,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -4209,7 +4223,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -4290,6 +4303,23 @@ "node": ">=0.10.0" } }, + "node_modules/react-datepicker": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.21.0.tgz", + "integrity": "sha512-z0DtuRrKMz9i7dcTusW29VacbM9pn08g1yw0cG+Y5GpodJDxSWv7zUMxl3IwKN9Ap/AMphiepvmT5P+iNCgEiA==", + "dependencies": { + "@popperjs/core": "^2.11.8", + "classnames": "^2.2.6", + "date-fns": "^2.30.0", + "prop-types": "^15.7.2", + "react-onclickoutside": "^6.13.0", + "react-popper": "^2.3.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17 || ^18", + "react-dom": "^16.9.0 || ^17 || ^18" + } + }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -4302,6 +4332,11 @@ "react": "^18.2.0" } }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + }, "node_modules/react-icons": { "version": "4.11.0", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.11.0.tgz", @@ -4315,6 +4350,33 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/react-onclickoutside": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz", + "integrity": "sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==", + "funding": { + "type": "individual", + "url": "https://github.com/Pomax/react-onclickoutside/blob/master/FUNDING.md" + }, + "peerDependencies": { + "react": "^15.5.x || ^16.x || ^17.x || ^18.x", + "react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x" + } + }, + "node_modules/react-popper": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", + "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==", + "dependencies": { + "react-fast-compare": "^3.0.1", + "warning": "^4.0.2" + }, + "peerDependencies": { + "@popperjs/core": "^2.0.0", + "react": "^16.8.0 || ^17 || ^18", + "react-dom": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/react-redux": { "version": "8.1.3", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.3.tgz", @@ -5373,6 +5435,14 @@ } } }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/client/package.json b/client/package.json index 091ff8f77..6cf7d5de6 100644 --- a/client/package.json +++ b/client/package.json @@ -17,6 +17,7 @@ "date-fns": "^2.30.0", "lodash": "^4.17.21", "react": "^18.2.0", + "react-datepicker": "^4.21.0", "react-dom": "^18.2.0", "react-icons": "^4.11.0", "react-redux": "^8.1.3", diff --git a/client/src/components/Navbar.jsx b/client/src/components/Navbar.jsx index 5b5c2eb46..42e59ccab 100644 --- a/client/src/components/Navbar.jsx +++ b/client/src/components/Navbar.jsx @@ -5,9 +5,13 @@ import stayvueLogo from "../assets/StayVue.png"; import search from "../assets/search.png"; import LoginModal from "./LoginModal"; import DropdownMenu from "./DropdownMenu"; +import DatePicker from "react-datepicker"; +import "react-datepicker/dist/react-datepicker.css"; const Navbar = ({ isModalOpen, setIsModalOpen }) => { const [isDropdownOpen, setIsDropdownOpen] = useState(false); + const [startDate, setStartDate] = useState(null); + const [endDate, setEndDate] = useState(null); const user = useSelector((state) => state.user?.loggedInUser); useEffect(() => { @@ -31,6 +35,14 @@ const Navbar = ({ isModalOpen, setIsModalOpen }) => { console.log("MODAL open"); }; + const handleDateChange = (date, type) => { + if (type === "start") { + setStartDate(date); + } else { + setEndDate(date); + } + }; + return (
    ); From 54b3a37364d2d41b836161d4f637925ce26f7307 Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sat, 18 Nov 2023 03:08:26 -0500 Subject: [PATCH 124/130] attached a link button for policies page --- client/src/components/DropdownMenu.jsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/client/src/components/DropdownMenu.jsx b/client/src/components/DropdownMenu.jsx index 1109c08ca..77e110688 100644 --- a/client/src/components/DropdownMenu.jsx +++ b/client/src/components/DropdownMenu.jsx @@ -3,6 +3,7 @@ import { RxAvatar, RxDropdownMenu } from "react-icons/rx"; import { Link } from "react-router-dom"; import { useSelector, useDispatch } from "react-redux"; import { authLogOut } from "../redux/slices/userSlice"; +import Policies from "../pages/Policies"; const DropdownMenu = ({ toggleDropdown, toggleLoginModal, isDropdownOpen }) => { const user = useSelector((state) => state.user?.loggedInUser); @@ -74,6 +75,16 @@ const DropdownMenu = ({ toggleDropdown, toggleLoginModal, isDropdownOpen }) => { Perks +
  • + + + +
  • {user && user.id ? ( From 6f38b5d04e43af389fcdbcd64eb47060db59273f Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sat, 18 Nov 2023 03:09:09 -0500 Subject: [PATCH 125/130] added general policies for users/buyers --- client/src/pages/Policies.jsx | 63 +++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 client/src/pages/Policies.jsx diff --git a/client/src/pages/Policies.jsx b/client/src/pages/Policies.jsx new file mode 100644 index 000000000..9a3c167fe --- /dev/null +++ b/client/src/pages/Policies.jsx @@ -0,0 +1,63 @@ +import React from 'react'; + +function Policies() { + return ( +
    +

    Policies

    + +

    +

    Booking and Reservation Policies:

    Welcome to our unique spaces! Each property may have different booking requirements, ranging from a minimum of one night to longer stays. Explore the listings for details on age restrictions and the distinctive charm each owner brings to their space. +

    + +

    +

    Check-in and Check-out:

    Check-in times vary depending on the property and its owner, starting at 3:00 PM. Check-out is generally by 11:00 AM, but please check your specific listing for details. Keys can be collected from the lockbox, providing a seamless arrival experience. +

    + +

    +

    Cancellation Policy:

    Cancellation policies are tailored to each owners preferences, ranging from fully refundable up to 7 days before the stay to more specific terms. Check your chosen propertys listing for cancellation details. +

    + +

    +

    House Rules:

    Embrace the diversity of our listings! While some spaces may allow smoking and pets, others maintain strict no-smoking policies or are pet-free. Be sure to review each propertys unique rules, such as noise levels and shared space usage. +

    + +

    +

    Security Deposit:

    The security deposit amount varies by property, with some owners requesting $100 and others more or less. Refer to your booking confirmation for details on the specific conditions for a refund. +

    + +

    +

    Cleaning and Maintenance:

    Cleaning fees vary based on the property, reflecting the owners commitment to maintaining a fresh and welcoming environment. Specific cleaning expectations are outlined in each listing, so guests are encouraged to review these details. +

    + +

    +

    Guest Responsibilities:

    Key handling guidelines are unique to each property. Some may require extra care due to high-security measures, so please check your specific listing for instructions. Familiarize yourself with community guidelines, as they may differ across properties. +

    + +

    +

    Communication:

    Owners may have different preferences for communication methods, ranging from Airbnb messaging to direct phone calls. Refer to your booking confirmation for the owners preferred contact details. +

    + +

    +

    Local Regulations and Laws:

    Discover the neighborhood responsibly by adhering to local laws and regulations. Waste disposal rules, local curfews, and other regulations may vary, so be sure to review property-specific guidelines. +

    + +

    +

    Liability and Insurance:

    While owners are committed to your safety, individual properties may have different insurance coverage. Guests are encouraged to consider travel insurance based on the specific propertys policies. +

    + +

    +

    Guest Identification:

    Some owners may request identification upon arrival for security purposes. Check your specific listing for details on guest identification requirements. +

    + +

    +

    Accessibility:

    Each owner strives to make their property accessible. If you have specific needs, please reach out to the individual owner to discuss accommodations tailored to your requirements. +

    + +

    +

    Feedback and Reviews:

    Share your unique experiences! Each property owner values your feedback, and your reviews contribute to the diverse community of Airbnb. Be open to different hosting styles and provide constructive feedback based on your individual experience. +

    +
    + ); +} + +export default Policies; From 70a9eb07423a96f26efe0dfa70c63aa9a0bd229a Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sat, 18 Nov 2023 03:10:08 -0500 Subject: [PATCH 126/130] made card links for individual listings pages --- client/src/pages/Profile.jsx | 2 +- client/src/pages/ProfileListing.jsx | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/client/src/pages/Profile.jsx b/client/src/pages/Profile.jsx index dd1e206b0..dde950350 100644 --- a/client/src/pages/Profile.jsx +++ b/client/src/pages/Profile.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useState } from "react"; import ProfileListing from "./ProfileListing"; import { useParams } from "react-router-dom"; // import UserIcon from "../jsons/UserIcon.json"; diff --git a/client/src/pages/ProfileListing.jsx b/client/src/pages/ProfileListing.jsx index 47cff0af0..d1cf1c1f0 100644 --- a/client/src/pages/ProfileListing.jsx +++ b/client/src/pages/ProfileListing.jsx @@ -1,5 +1,6 @@ import React, { useState } from 'react'; import listings from '../jsons/listings.json'; +import { Link } from 'react-router-dom' function ProfileListing() { const [showForm, setShowForm] = useState(false); @@ -128,7 +129,10 @@ function ProfileListing() {
      {userListings.map((userListing, index) => (
    • -

      {userListing.title}

      + +

      {userListing.title} + {userListing.title} +

      {/*

      ID: {userListing.id}

      */}

      Price per night: ${parseFloat(userListing.price).toFixed(2)}

      {userListing.img && ( From 85f7d783df2343a2a6fa9be68b2763592bbcdc40 Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sat, 18 Nov 2023 03:10:48 -0500 Subject: [PATCH 127/130] made individual listing page for calistings that are made --- client/src/pages/IndividualListings.jsx | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 client/src/pages/IndividualListings.jsx diff --git a/client/src/pages/IndividualListings.jsx b/client/src/pages/IndividualListings.jsx new file mode 100644 index 000000000..047bc8a8a --- /dev/null +++ b/client/src/pages/IndividualListings.jsx @@ -0,0 +1,28 @@ +import React from 'react'; + +const IndividualListings = ({ match, userListings }) => { + // Extract the listing ID from the URL parameter + console.log("hello world"); + console.log(userListings); + + const listingId = match.params.id; + + // Fetch the details of the listing based on the ID + // You may need to modify this part based on your data structure + const listingDetails = userListings.filter(listing => listing.id === listingId); + + if (!listingDetails) { + return
      Listing not found
      ; + } + + return ( +
      +

      {listingDetails.title}

      + {/* Render additional details here */} +

      Price per night: {listingDetails.price}

      +

      Image: {listingDetails.title}

      +
      + ); +}; + +export default IndividualListings; From 043d3943005c99efadb271b5b1acacba6d37cce7 Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sat, 18 Nov 2023 03:15:42 -0500 Subject: [PATCH 128/130] setting up pull request --- client/src/pages/IndividualListings.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/client/src/pages/IndividualListings.jsx b/client/src/pages/IndividualListings.jsx index 047bc8a8a..15a792845 100644 --- a/client/src/pages/IndividualListings.jsx +++ b/client/src/pages/IndividualListings.jsx @@ -2,7 +2,6 @@ import React from 'react'; const IndividualListings = ({ match, userListings }) => { // Extract the listing ID from the URL parameter - console.log("hello world"); console.log(userListings); const listingId = match.params.id; From 2c73b62e2845c5ff98e1e38c821a950a60d525bd Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sat, 18 Nov 2023 03:23:03 -0500 Subject: [PATCH 129/130] take out edit button due to time constraints --- client/src/pages/ProfileListing.jsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/src/pages/ProfileListing.jsx b/client/src/pages/ProfileListing.jsx index d1cf1c1f0..7e2086485 100644 --- a/client/src/pages/ProfileListing.jsx +++ b/client/src/pages/ProfileListing.jsx @@ -24,9 +24,9 @@ function ProfileListing() { })); }; - const handleEditListing = (index) => { - console.log(`Edit clicked for index: ${index}`); - }; + // const handleEditListing = (index) => { + // console.log(`Edit clicked for index: ${index}`); + // }; const handleDeleteListing = (index) => { const updatedListings = [...userListings]; @@ -143,15 +143,15 @@ function ProfileListing() { /> )}
      - + */} From e7e9ca19d647d7d32ab235ac91bdbb6d6eb6d2d0 Mon Sep 17 00:00:00 2001 From: Hafeefa Date: Sat, 18 Nov 2023 03:27:07 -0500 Subject: [PATCH 130/130] fix error where title appeared twice, took out individual listing due to time constraints --- client/src/pages/ProfileListing.jsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/src/pages/ProfileListing.jsx b/client/src/pages/ProfileListing.jsx index 7e2086485..4c21565f4 100644 --- a/client/src/pages/ProfileListing.jsx +++ b/client/src/pages/ProfileListing.jsx @@ -130,9 +130,11 @@ function ProfileListing() { {userListings.map((userListing, index) => (
    • -

      {userListing.title} - {userListing.title} -

      + + {/* */} +

      {userListing.title}

      + {/* */} + {/*

      ID: {userListing.id}

      */}

      Price per night: ${parseFloat(userListing.price).toFixed(2)}

      {userListing.img && (