diff --git a/docs/02_architecture_constraints.adoc b/docs/02_architecture_constraints.adoc index bc865df..ac78f34 100644 --- a/docs/02_architecture_constraints.adoc +++ b/docs/02_architecture_constraints.adoc @@ -19,7 +19,7 @@ |=== | |Constraint|Motivation | OC1 | Time | The application will be developed between March 2022 and May 2022. -| OC2 | Team | Ignacio Gomez Gasch, Valentin Dumitru, Mario Garcia Prieto, Jorge Torano Herrera, Adrian Estrada Gonzalez +| OC2 | Team | Ignacio Gomez Gasch, Valentin Dumitru, Jorge Torano Herrera, Adrian Estrada Gonzalez | OC3 | Repository| The code and infomation of the whole project will be managed in GitHub in a private repository. |=== diff --git a/docs/06_runtime_view.adoc b/docs/06_runtime_view.adoc index b9c7778..144e28e 100644 --- a/docs/06_runtime_view.adoc +++ b/docs/06_runtime_view.adoc @@ -1,5 +1,6 @@ [[section-runtime-view]] == Runtime View +=== Add Product to Shopping Cart === Log In / Register @@ -18,17 +19,68 @@ The the runtime interactions inside the system to log or register are the follow === Purchase image:Diagram_ASW_Runtime_Purchase.png["Hierarchy of building blocks"] The the runtime interactions inside the system purchase any item in our store are the following: +[plantuml,"Diagrama Añadir producto",png] +---- +actor Client +participant Shopping Cart +Client -> Shopping Cart: Authentication request +Shopping Cart -> Client: Authentication answer +Client -> Shopping Cart: Add products +note across: Then, the product is stored +Client -> Shopping Cart: Click on shopping cart +Shopping Cart -> Client: View shopping cart +---- +=== Delete Product from Shopping Cart. - - First the client enters the webpage. - - Then searches the product they want by their name or searching by category. - - After that, the API is called and it fetches the products the user searched from the database. - - Afterwards the user will select the items he wants to buy. - - We look into our database to see if user exists, if exists brings back his data, if dont we store them, and after finishing, they will go to the shopping cart to conclude. - - The api will calculate the price, and if the user modifies the products, it will calculate it again. - - Then the user will press buy. - - For the order to be sent, the user is required to allow the app to collect data from the POD, in this case, his credit card, adress and other relevant data. After allowed, the API stores into the database the order. - - And finally the user is sent back to the home page. +[plantuml,"Diagrama Eliminar Producto",png] +---- +actor Client +participant Shopping Cart +Client -> Shopping Cart: Click on shopping cart +Shopping Cart -> Cliente: View shopping cart +Client -> Shopping Cart: Delete selected product +note across: Then, the product is deleted +Shopping Cart -> Client: Shopping cart is updated +---- + +=== Login + +[plantuml,"Diagrama Inicio de sesión",png] +---- +actor Client +participant Frontend +participant Backend +Client -> Frontend: Introduce email and password +Frontend -> Backend: Login request +alt User exists + Backend -> Frontend: Returns user + Frontend -> Cliente: Redirects home page with the user session +else User doesn't exists + Backend -> Frontend: Authentication error +end +---- + +=== Register + +[plantuml,"Diagrama Registro",png] +---- +actor Client +participant Frontend +participant Backend +Cliente -> Frontend: Introduce email, name, dni, password and confirm password +Frontend -> Backend: Authentication request +alt User exists + Backend -> Frontend: Sign up fails + Frontend -> Cliente: Notification to user (email in use) +else User doesn't exists + Backend -> Frontend: New user registered + Frontend -> Cliente: Redirects login page +end +---- + + +=== View User Orders === Filter Catalog image:Diagram_ASW_Runtime_FilterCatalog.png["Hierarchy of building blocks"] @@ -40,3 +92,13 @@ The the runtime interactions inside the system purchase any item in our store ar - The api processes the request and answers with the items. - The interface updates and shows the client their desired products. +[plantuml,"Ver pedidos",png] +---- +actor Client +participant User Interface +database "POD" +Client -> User Interface: View orders +User Interface -> "POD": Obtain user orders +"POD" -> User Interface: Return user orders +User Interface -> Show user orders +---- diff --git a/docs/07_deployment_view.adoc b/docs/07_deployment_view.adoc index 1088a09..cd258d2 100644 --- a/docs/07_deployment_view.adoc +++ b/docs/07_deployment_view.adoc @@ -3,84 +3,15 @@ == Deployment View -[role="arc42help"] -**** -.Content -The deployment view describes: - - 1. the technical infrastructure used to execute your system, with infrastructure elements like geographical locations, environments, computers, processors, channels and net topologies as well as other infrastructure elements and - -2. the mapping of (software) building blocks to that infrastructure elements. - -Often systems are executed in different environments, e.g. development environment, test environment, production environment. In such cases you should document all relevant environments. - -Especially document the deployment view when your software is executed as distributed system with more then one computer, processor, server or container or when you design and construct your own hardware processors and chips. - -From a software perspective it is sufficient to capture those elements of the infrastructure that are needed to show the deployment of your building blocks. Hardware architects can go beyond that and describe the infrastructure to any level of detail they need to capture. - -.Motivation -Software does not run without hardware. -This underlying infrastructure can and will influence your system and/or some -cross-cutting concepts. Therefore, you need to know the infrastructure. - -.Form - -Maybe the highest level deployment diagram is already contained in section 3.2. as -technical context with your own infrastructure as ONE black box. In this section you will -zoom into this black box using additional deployment diagrams: - -* UML offers deployment diagrams to express that view. Use it, probably with nested diagrams, -when your infrastructure is more complex. -* When your (hardware) stakeholders prefer other kinds of diagrams rather than the deployment diagram, let them use any kind that is able to show nodes and channels of the infrastructure. -**** - === Infrastructure Level 1 -[role="arc42help"] -**** -Describe (usually in a combination of diagrams, tables, and text): - -* the distribution of your system to multiple locations, environments, computers, processors, .. as well as the physical connections between them -* important justification or motivation for this deployment structure -* Quality and/or performance features of the infrastructure -* the mapping of software artifacts to elements of the infrastructure - -For multiple environments or alternative deployments please copy that section of arc42 for all relevant environments. -**** - -_****_ Motivation:: -__ +The motivation of this deployment structure is the correct understanding of how nodes and components of the project behave and are related in runtime. Quality and/or Performance Features:: -__ +The performance mainly depends on the network connection from the user and the servers on which the application runs. We cannot control those two things, but we can improve as much as possible the quality of the application by writing the cleanest possible code. Mapping of Building Blocks to Infrastructure:: -__ - - -=== Infrastructure Level 2 - -[role="arc42help"] -**** -Here you can include the internal structure of (some) infrastructure elements from level 1. - -Please copy the structure from level 1 for each selected element. -**** - -==== __ - -__ - -==== __ - -__ - -... - -==== __ - -__ diff --git a/docs/09_design_decisions.adoc b/docs/09_design_decisions.adoc index c00fde0..93f6558 100644 --- a/docs/09_design_decisions.adoc +++ b/docs/09_design_decisions.adoc @@ -4,10 +4,9 @@ [options="header",cols="1,2"] |=== |Decision|Reason -|TypeScript|It will be one of the languages ​​used in the application. One of its positive aspects is its ease of use with Solid -|Solid|This technology will be used to store client addresses through the use of pods. -|React|The use of this open source library is one of the requirements of the application that will be used to create the application interfaces. |MogoDB|This type of database is according to the requirements of the application. -|BootStrap|As it has been/will be used in other subjects, the use of this library has been chosen, since it is also in accordance with the requirements of the application. |Visual Studio Code|It will be the development enviroment used by all members of the group. One of its most favorable points is the possibility of adding a wide variety of extensions that will allow the project to be carried out in a simple way +|Cloudinary|In this platform the images of the application will be stored, making it not necessary to save them locally +|Node Geocoder|By using this library we get the coordinates from the user address stored in your POD +|Openstreetmap|This will be the provider that we will use in the Node Geoder api, to obtain the coordinates of the user's address |=== \ No newline at end of file diff --git a/docs/10_quality_scenarios.adoc b/docs/10_quality_scenarios.adoc index 385781d..d12e3c3 100644 --- a/docs/10_quality_scenarios.adoc +++ b/docs/10_quality_scenarios.adoc @@ -11,12 +11,12 @@ image::Quality_Tree.png[] === Quality Scenarios [options="header",cols="1,1,1,1"] |=== -Priority Position|Quality attribute|Scenario|Priority -| **1** | **Usability** | The application must be intuitive and easy to use bu most users | Very High -| **2** | **Privay** | The user will have the power to choose the (non-essential) information that the application shows or has | Very High -| **3** | **Security** | The application should offer a certain security and integrity against attacks | High -| **4** | **Modifiability** | The application code should be easily extensible to add new functionality easily | Medium -| **5** | **Efficiency** | The application must be optimized to minimize waiting times for services | Medium -| **6** | **Testability** | The application code should be easily testable, to facilitate testing to realiease a robust final product | Medium +ID|Quality attribute|Scenario|Priority User/Dev +| **U.1** | **Usability** | The application must be intuitive and easy to use bu most users | High/High +| **P.1** | **Privacity** | The user will have the power to choose the (non-essential) information that the application shows or has | High/High +| **S.1** | **Security** | The application should offer a certain security and integrity against attacks | High/Medium +| **M.1** | **Modifiability** | The application code should be easily extensible to add new functionality easily | Low/High +| **E.1** | **Efficiency** | The application must be optimized to minimize waiting times for services | High/Medium +| **T.1** | **Testability** | The application code should be easily testable, to facilitate testing to realiease a robust final product | Low/High |=== diff --git a/docs/11_technical_risks.adoc b/docs/11_technical_risks.adoc index c52fb74..aa7d981 100644 --- a/docs/11_technical_risks.adoc +++ b/docs/11_technical_risks.adoc @@ -1,17 +1,13 @@ [[section-technical-risks]] -== Risks and Technical Debts - -[role="arc42help"] -**** -.Contents -A list of identified technical risks or technical debts, ordered by priority - -.Motivation -“Risk management is project management for grown-ups” (Tim Lister, Atlantic Systems Guild.) - -This should be your motto for systematic detection and evaluation of risks and technical debts in the architecture, which will be needed by management stakeholders (e.g. project managers, product owners) as part of the overall risk analysis and measurement planning. - -.Form -List of risks and/or technical debts, probably including suggested measures to minimize, mitigate or avoid risks or reduce technical debts. -**** +=== Risks and Technical Debts +[options="header",cols="1,1"] +|=== +Risk|Trade off +| The interface is unfriendly to users | We will have to invest time to test and code the flows through the interfaces +| The payment data of the purchases can intervene | slower payment transactions +| An attacker can access and modify the data of our application | More time to choose a robust db for the application +| It is complicated to add new functionalities to the application | Refactor and choose application design patterns well to facilitate the addition of new functionalities +| Waiting times for application processes are very long | Increased work to design a code as efficient as possible +| It is complicated to test the functionalities of the application | Increased work to design tests that test all the functionalities of the application +|=== diff --git a/docs/12_glossary.adoc b/docs/12_glossary.adoc index fbf4b01..288156d 100644 --- a/docs/12_glossary.adoc +++ b/docs/12_glossary.adoc @@ -43,4 +43,12 @@ Potentially more columns in case you need translations. | BootStrap | Bootstrap is a free and open source front end development framework for the creation of websites and web apps | TypeScript | TypeScript is a programming language developed and maintained by Microsoft | Visual Studio Code | Visual Studio Code is a lightweight but powerful source code editor which runs on your desktop and is available for Windows, macOS and Linux +|Cloudinary |Cloudinary is an api that transform images and videos to load faster with no visual degradation, automatically generate image and video variants, and deliver high quality responsive experiences to increase conversions. +|OpenStreetMap |OpenStreetMap is a collaborative project to create free and editable maps. +| U.1 | Identificator for Usability +| P.1 | Identificator for Privacity +| S.1 | Identificator for Security +| M.1 | Identificator for Modifiability +| E.1 | Identificator for Efficiency +| T.1 | Identificator for Testability |=== diff --git a/webapp/package-lock.json b/webapp/package-lock.json index fb0063c..08ca1b0 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -34,6 +34,7 @@ "@types/express": "^4.17.13", "@types/jest": "^27.4.0", "@types/puppeteer": "^5.4.4", + "@types/styled-components": "^5.1.24", "expect-puppeteer": "^6.0.2", "jest-cucumber": "^3.0.1", "jest-puppeteer": "^6.0.3", @@ -1951,9 +1952,9 @@ "dev": true }, "node_modules/@csstools/postcss-color-function": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.0.3.tgz", - "integrity": "sha512-J26I69pT2B3MYiLY/uzCGKVJyMYVg9TCpXkWsRlt+Yfq+nELUEm72QXIMYXs4xA9cJA4Oqs2EylrfokKl3mJEQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.0.tgz", + "integrity": "sha512-5D5ND/mZWcQoSfYnSPsXtuiFxhzmhxt6pcjrFLJyldj+p0ZN2vvRpYNX+lahFTtMhAYOa2WmkdGINr0yP0CvGA==", "dev": true, "dependencies": { "@csstools/postcss-progressive-custom-properties": "^1.1.0", @@ -1962,6 +1963,10 @@ "engines": { "node": "^12 || ^14 || >=16" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, "peerDependencies": { "postcss": "^8.4" } @@ -2013,16 +2018,20 @@ } }, "node_modules/@csstools/postcss-is-pseudo-class": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.1.tgz", - "integrity": "sha512-Og5RrTzwFhrKoA79c3MLkfrIBYmwuf/X83s+JQtz/Dkk/MpsaKtqHV1OOzYkogQ+tj3oYp5Mq39XotBXNqVc3Q==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.2.tgz", + "integrity": "sha512-L9h1yxXMj7KpgNzlMrw3isvHJYkikZgZE4ASwssTnGEH8tm50L6QsM9QQT5wR4/eO5mU0rN5axH7UzNxEYg5CA==", "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.9" + "postcss-selector-parser": "^6.0.10" }, "engines": { "node": "^12 || ^14 || >=16" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, "peerDependencies": { "postcss": "^8.4" } @@ -2043,9 +2052,9 @@ } }, "node_modules/@csstools/postcss-oklab-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.0.2.tgz", - "integrity": "sha512-QwhWesEkMlp4narAwUi6pgc6kcooh8cC7zfxa9LSQNYXqzcdNUtNBzbGc5nuyAVreb7uf5Ox4qH1vYT3GA1wOg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.0.tgz", + "integrity": "sha512-e/Q5HopQzmnQgqimG9v3w2IG4VRABsBq3itOcn4bnm+j4enTgQZ0nWsaH/m9GV2otWGQ0nwccYL5vmLKyvP1ww==", "dev": true, "dependencies": { "@csstools/postcss-progressive-custom-properties": "^1.1.0", @@ -2054,6 +2063,10 @@ "engines": { "node": "^12 || ^14 || >=16" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, "peerDependencies": { "postcss": "^8.4" } @@ -3557,9 +3570,9 @@ } }, "node_modules/@pmmmwh/react-refresh-webpack-plugin": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.4.tgz", - "integrity": "sha512-zZbZeHQDnoTlt2AF+diQT0wsSXpvWiaIOZwBRdltNFhG1+I3ozyaw7U/nBiUwyJ0D+zwdXp0E3bWOl38Ag2BMw==", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.5.tgz", + "integrity": "sha512-RbG7h6TuP6nFFYKJwbcToA1rjC1FyPg25NR2noAZ0vKI+la01KTSRPkuVPE+U88jXv7javx2JHglUcL1MHcshQ==", "dev": true, "dependencies": { "ansi-html-community": "^0.0.8", @@ -4556,6 +4569,16 @@ "@types/node": "*" } }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dev": true, + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -4827,6 +4850,17 @@ "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", "dev": true }, + "node_modules/@types/styled-components": { + "version": "5.1.24", + "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.24.tgz", + "integrity": "sha512-mz0fzq2nez+Lq5IuYammYwWgyLUE6OMAJTQL9D8hFLP4Pkh7gVYJii/VQWxq8/TK34g/OrkehXaFNdcEKcItug==", + "dev": true, + "dependencies": { + "@types/hoist-non-react-statics": "*", + "@types/react": "*", + "csstype": "^3.0.2" + } + }, "node_modules/@types/testing-library__jest-dom": { "version": "5.14.3", "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.3.tgz", @@ -4881,14 +4915,14 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.17.0.tgz", - "integrity": "sha512-qVstvQilEd89HJk3qcbKt/zZrfBZ+9h2ynpAGlWjWiizA7m/MtLT9RoX6gjtpE500vfIg8jogAkDzdCxbsFASQ==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.18.0.tgz", + "integrity": "sha512-tzrmdGMJI/uii9/V6lurMo4/o+dMTKDH82LkNjhJ3adCW22YQydoRs5MwTiqxGF9CSYxPxQ7EYb4jLNlIs+E+A==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.17.0", - "@typescript-eslint/type-utils": "5.17.0", - "@typescript-eslint/utils": "5.17.0", + "@typescript-eslint/scope-manager": "5.18.0", + "@typescript-eslint/type-utils": "5.18.0", + "@typescript-eslint/utils": "5.18.0", "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", @@ -4929,12 +4963,12 @@ } }, "node_modules/@typescript-eslint/experimental-utils": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.17.0.tgz", - "integrity": "sha512-U4sM5z0/ymSYqQT6I7lz8l0ZZ9zrya5VIwrwAP5WOJVabVtVsIpTMxPQe+D3qLyePT+VlETUTO2nA1+PufPx9Q==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.18.0.tgz", + "integrity": "sha512-hypiw5N0aM2aH91/uMmG7RpyUH3PN/iOhilMwkMFZIbm/Bn/G3ZnbaYdSoAN4PG/XHQjdhBYLi0ZoRZsRYT4hA==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "5.17.0" + "@typescript-eslint/utils": "5.18.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -4948,14 +4982,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.17.0.tgz", - "integrity": "sha512-aRzW9Jg5Rlj2t2/crzhA2f23SIYFlF9mchGudyP0uiD6SenIxzKoLjwzHbafgHn39dNV/TV7xwQkLfFTZlJ4ig==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.18.0.tgz", + "integrity": "sha512-+08nYfurBzSSPndngnHvFw/fniWYJ5ymOrn/63oMIbgomVQOvIDhBoJmYZ9lwQOCnQV9xHGvf88ze3jFGUYooQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.17.0", - "@typescript-eslint/types": "5.17.0", - "@typescript-eslint/typescript-estree": "5.17.0", + "@typescript-eslint/scope-manager": "5.18.0", + "@typescript-eslint/types": "5.18.0", + "@typescript-eslint/typescript-estree": "5.18.0", "debug": "^4.3.2" }, "engines": { @@ -4975,13 +5009,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.17.0.tgz", - "integrity": "sha512-062iCYQF/doQ9T2WWfJohQKKN1zmmXVfAcS3xaiialiw8ZUGy05Em6QVNYJGO34/sU1a7a+90U3dUNfqUDHr3w==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.18.0.tgz", + "integrity": "sha512-C0CZML6NyRDj+ZbMqh9FnPscg2PrzSaVQg3IpTmpe0NURMVBXlghGZgMYqBw07YW73i0MCqSDqv2SbywnCS8jQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.17.0", - "@typescript-eslint/visitor-keys": "5.17.0" + "@typescript-eslint/types": "5.18.0", + "@typescript-eslint/visitor-keys": "5.18.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -4992,12 +5026,12 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.17.0.tgz", - "integrity": "sha512-3hU0RynUIlEuqMJA7dragb0/75gZmwNwFf/QJokWzPehTZousP/MNifVSgjxNcDCkM5HI2K22TjQWUmmHUINSg==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.18.0.tgz", + "integrity": "sha512-vcn9/6J5D6jtHxpEJrgK8FhaM8r6J1/ZiNu70ZUJN554Y3D9t3iovi6u7JF8l/e7FcBIxeuTEidZDR70UuCIfA==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "5.17.0", + "@typescript-eslint/utils": "5.18.0", "debug": "^4.3.2", "tsutils": "^3.21.0" }, @@ -5018,9 +5052,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.17.0.tgz", - "integrity": "sha512-AgQ4rWzmCxOZLioFEjlzOI3Ch8giDWx8aUDxyNw9iOeCvD3GEYAB7dxWGQy4T/rPVe8iPmu73jPHuaSqcjKvxw==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.18.0.tgz", + "integrity": "sha512-bhV1+XjM+9bHMTmXi46p1Led5NP6iqQcsOxgx7fvk6gGiV48c6IynY0apQb7693twJDsXiVzNXTflhplmaiJaw==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -5031,13 +5065,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.17.0.tgz", - "integrity": "sha512-X1gtjEcmM7Je+qJRhq7ZAAaNXYhTgqMkR10euC4Si6PIjb+kwEQHSxGazXUQXFyqfEXdkGf6JijUu5R0uceQzg==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.18.0.tgz", + "integrity": "sha512-wa+2VAhOPpZs1bVij9e5gyVu60ReMi/KuOx4LKjGx2Y3XTNUDJgQ+5f77D49pHtqef/klglf+mibuHs9TrPxdQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.17.0", - "@typescript-eslint/visitor-keys": "5.17.0", + "@typescript-eslint/types": "5.18.0", + "@typescript-eslint/visitor-keys": "5.18.0", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -5073,15 +5107,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.17.0.tgz", - "integrity": "sha512-DVvndq1QoxQH+hFv+MUQHrrWZ7gQ5KcJzyjhzcqB1Y2Xes1UQQkTRPUfRpqhS8mhTWsSb2+iyvDW1Lef5DD7vA==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.18.0.tgz", + "integrity": "sha512-+hFGWUMMri7OFY26TsOlGa+zgjEy1ssEipxpLjtl4wSll8zy85x0GrUSju/FHdKfVorZPYJLkF3I4XPtnCTewA==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.17.0", - "@typescript-eslint/types": "5.17.0", - "@typescript-eslint/typescript-estree": "5.17.0", + "@typescript-eslint/scope-manager": "5.18.0", + "@typescript-eslint/types": "5.18.0", + "@typescript-eslint/typescript-estree": "5.18.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, @@ -5119,12 +5153,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.17.0.tgz", - "integrity": "sha512-6K/zlc4OfCagUu7Am/BD5k8PSWQOgh34Nrv9Rxe2tBzlJ7uOeJ/h7ugCGDCeEZHT6k2CJBhbk9IsbkPI0uvUkA==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.18.0.tgz", + "integrity": "sha512-Hf+t+dJsjAKpKSkg3EHvbtEpFFb/1CiOHnvI8bjHgOD4/wAw3gKrA0i94LrbekypiZVanJu3McWJg7rWDMzRTg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.17.0", + "@typescript-eslint/types": "5.18.0", "eslint-visitor-keys": "^3.0.0" }, "engines": { @@ -6502,9 +6536,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001324", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001324.tgz", - "integrity": "sha512-/eYp1J6zYh1alySQB4uzYFkLmxxI8tk0kxldbNHXp8+v+rdMKdUBNjRLz7T7fz6Iox+1lIdYpc7rq6ZcXfTukg==", + "version": "1.0.30001325", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001325.tgz", + "integrity": "sha512-sB1bZHjseSjDtijV1Hb7PB2Zd58Kyx+n/9EotvZ4Qcz2K3d0lWB8dB4nb8wN/TsOGFq3UuAm0zQZNQ4SoR7TrQ==", "funding": [ { "type": "opencollective", @@ -8782,9 +8816,9 @@ } }, "node_modules/eslint-plugin-testing-library": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.2.0.tgz", - "integrity": "sha512-fYFH8lA1hbc1Epr9laNm/+YIR2d+R7WI8sFz9jIRAUfqCf21Nb5BzZwhNeZlu9wKXwDtuf+hUM5QJxG1PuDsTQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.2.1.tgz", + "integrity": "sha512-88qJv6uzYALtiYJDzhelP3ov0Px/GLgnu+UekjjDxL2nMyvgdTyboKqcDBsvFPmAeizlCoSWOjeBN4DxO0BxaA==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.13.0" @@ -10438,9 +10472,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, "node_modules/growly": { @@ -17252,9 +17286,9 @@ } }, "node_modules/postcss-lab-function": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.1.2.tgz", - "integrity": "sha512-isudf5ldhg4fk16M8viAwAbg6Gv14lVO35N3Z/49NhbwPQ2xbiEoHgrRgpgQojosF4vF7jY653ktB6dDrUOR8Q==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.0.tgz", + "integrity": "sha512-Zb1EO9DGYfa3CP8LhINHCcTTCTLI+R3t7AX2mKsDzdgVQ/GkCpHOTgOr6HBHslP7XDdVbqgHW5vvRPMdVANQ8w==", "dev": true, "dependencies": { "@csstools/postcss-progressive-custom-properties": "^1.1.0", @@ -17263,6 +17297,10 @@ "engines": { "node": "^12 || ^14 || >=16" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, "peerDependencies": { "postcss": "^8.4" } @@ -17550,16 +17588,20 @@ } }, "node_modules/postcss-nesting": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.1.3.tgz", - "integrity": "sha512-wUC+/YCik4wH3StsbC5fBG1s2Z3ZV74vjGqBFYtmYKlVxoio5TYGM06AiaKkQPPlkXWn72HKfS7Cw5PYxnoXSw==", + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.1.4.tgz", + "integrity": "sha512-2ixdQ59ik/Gt1+oPHiI1kHdwEI8lLKEmui9B1nl6163ANLC+GewQn7fXMxJF2JSb4i2MKL96GU8fIiQztK4TTA==", "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.9" + "postcss-selector-parser": "^6.0.10" }, "engines": { "node": "^12 || ^14 || >=16" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, "peerDependencies": { "postcss": "^8.4" } @@ -17845,16 +17887,20 @@ } }, "node_modules/postcss-pseudo-class-any-link": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.1.tgz", - "integrity": "sha512-JRoLFvPEX/1YTPxRxp1JO4WxBVXJYrSY7NHeak5LImwJ+VobFMwYDQHvfTXEpcn+7fYIeGkC29zYFhFWIZD8fg==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.2.tgz", + "integrity": "sha512-76XzEQv3g+Vgnz3tmqh3pqQyRojkcJ+pjaePsyhcyf164p9aZsu3t+NWxkZYbcHLK1ju5Qmalti2jPI5IWCe5w==", "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.9" + "postcss-selector-parser": "^6.0.10" }, "engines": { "node": "^12 || ^14 || >=16" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, "peerDependencies": { "postcss": "^8.4" } @@ -24498,9 +24544,9 @@ "dev": true }, "@csstools/postcss-color-function": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.0.3.tgz", - "integrity": "sha512-J26I69pT2B3MYiLY/uzCGKVJyMYVg9TCpXkWsRlt+Yfq+nELUEm72QXIMYXs4xA9cJA4Oqs2EylrfokKl3mJEQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.0.tgz", + "integrity": "sha512-5D5ND/mZWcQoSfYnSPsXtuiFxhzmhxt6pcjrFLJyldj+p0ZN2vvRpYNX+lahFTtMhAYOa2WmkdGINr0yP0CvGA==", "dev": true, "requires": { "@csstools/postcss-progressive-custom-properties": "^1.1.0", @@ -24536,12 +24582,12 @@ } }, "@csstools/postcss-is-pseudo-class": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.1.tgz", - "integrity": "sha512-Og5RrTzwFhrKoA79c3MLkfrIBYmwuf/X83s+JQtz/Dkk/MpsaKtqHV1OOzYkogQ+tj3oYp5Mq39XotBXNqVc3Q==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.2.tgz", + "integrity": "sha512-L9h1yxXMj7KpgNzlMrw3isvHJYkikZgZE4ASwssTnGEH8tm50L6QsM9QQT5wR4/eO5mU0rN5axH7UzNxEYg5CA==", "dev": true, "requires": { - "postcss-selector-parser": "^6.0.9" + "postcss-selector-parser": "^6.0.10" } }, "@csstools/postcss-normalize-display-values": { @@ -24554,9 +24600,9 @@ } }, "@csstools/postcss-oklab-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.0.2.tgz", - "integrity": "sha512-QwhWesEkMlp4narAwUi6pgc6kcooh8cC7zfxa9LSQNYXqzcdNUtNBzbGc5nuyAVreb7uf5Ox4qH1vYT3GA1wOg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.0.tgz", + "integrity": "sha512-e/Q5HopQzmnQgqimG9v3w2IG4VRABsBq3itOcn4bnm+j4enTgQZ0nWsaH/m9GV2otWGQ0nwccYL5vmLKyvP1ww==", "dev": true, "requires": { "@csstools/postcss-progressive-custom-properties": "^1.1.0", @@ -25636,9 +25682,9 @@ } }, "@pmmmwh/react-refresh-webpack-plugin": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.4.tgz", - "integrity": "sha512-zZbZeHQDnoTlt2AF+diQT0wsSXpvWiaIOZwBRdltNFhG1+I3ozyaw7U/nBiUwyJ0D+zwdXp0E3bWOl38Ag2BMw==", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.5.tgz", + "integrity": "sha512-RbG7h6TuP6nFFYKJwbcToA1rjC1FyPg25NR2noAZ0vKI+la01KTSRPkuVPE+U88jXv7javx2JHglUcL1MHcshQ==", "dev": true, "requires": { "ansi-html-community": "^0.0.8", @@ -26372,6 +26418,16 @@ "@types/node": "*" } }, + "@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dev": true, + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -26642,6 +26698,17 @@ "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", "dev": true }, + "@types/styled-components": { + "version": "5.1.24", + "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.24.tgz", + "integrity": "sha512-mz0fzq2nez+Lq5IuYammYwWgyLUE6OMAJTQL9D8hFLP4Pkh7gVYJii/VQWxq8/TK34g/OrkehXaFNdcEKcItug==", + "dev": true, + "requires": { + "@types/hoist-non-react-statics": "*", + "@types/react": "*", + "csstype": "^3.0.2" + } + }, "@types/testing-library__jest-dom": { "version": "5.14.3", "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.3.tgz", @@ -26696,14 +26763,14 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.17.0.tgz", - "integrity": "sha512-qVstvQilEd89HJk3qcbKt/zZrfBZ+9h2ynpAGlWjWiizA7m/MtLT9RoX6gjtpE500vfIg8jogAkDzdCxbsFASQ==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.18.0.tgz", + "integrity": "sha512-tzrmdGMJI/uii9/V6lurMo4/o+dMTKDH82LkNjhJ3adCW22YQydoRs5MwTiqxGF9CSYxPxQ7EYb4jLNlIs+E+A==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.17.0", - "@typescript-eslint/type-utils": "5.17.0", - "@typescript-eslint/utils": "5.17.0", + "@typescript-eslint/scope-manager": "5.18.0", + "@typescript-eslint/type-utils": "5.18.0", + "@typescript-eslint/utils": "5.18.0", "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", @@ -26724,61 +26791,61 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.17.0.tgz", - "integrity": "sha512-U4sM5z0/ymSYqQT6I7lz8l0ZZ9zrya5VIwrwAP5WOJVabVtVsIpTMxPQe+D3qLyePT+VlETUTO2nA1+PufPx9Q==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.18.0.tgz", + "integrity": "sha512-hypiw5N0aM2aH91/uMmG7RpyUH3PN/iOhilMwkMFZIbm/Bn/G3ZnbaYdSoAN4PG/XHQjdhBYLi0ZoRZsRYT4hA==", "dev": true, "requires": { - "@typescript-eslint/utils": "5.17.0" + "@typescript-eslint/utils": "5.18.0" } }, "@typescript-eslint/parser": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.17.0.tgz", - "integrity": "sha512-aRzW9Jg5Rlj2t2/crzhA2f23SIYFlF9mchGudyP0uiD6SenIxzKoLjwzHbafgHn39dNV/TV7xwQkLfFTZlJ4ig==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.18.0.tgz", + "integrity": "sha512-+08nYfurBzSSPndngnHvFw/fniWYJ5ymOrn/63oMIbgomVQOvIDhBoJmYZ9lwQOCnQV9xHGvf88ze3jFGUYooQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.17.0", - "@typescript-eslint/types": "5.17.0", - "@typescript-eslint/typescript-estree": "5.17.0", + "@typescript-eslint/scope-manager": "5.18.0", + "@typescript-eslint/types": "5.18.0", + "@typescript-eslint/typescript-estree": "5.18.0", "debug": "^4.3.2" } }, "@typescript-eslint/scope-manager": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.17.0.tgz", - "integrity": "sha512-062iCYQF/doQ9T2WWfJohQKKN1zmmXVfAcS3xaiialiw8ZUGy05Em6QVNYJGO34/sU1a7a+90U3dUNfqUDHr3w==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.18.0.tgz", + "integrity": "sha512-C0CZML6NyRDj+ZbMqh9FnPscg2PrzSaVQg3IpTmpe0NURMVBXlghGZgMYqBw07YW73i0MCqSDqv2SbywnCS8jQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.17.0", - "@typescript-eslint/visitor-keys": "5.17.0" + "@typescript-eslint/types": "5.18.0", + "@typescript-eslint/visitor-keys": "5.18.0" } }, "@typescript-eslint/type-utils": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.17.0.tgz", - "integrity": "sha512-3hU0RynUIlEuqMJA7dragb0/75gZmwNwFf/QJokWzPehTZousP/MNifVSgjxNcDCkM5HI2K22TjQWUmmHUINSg==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.18.0.tgz", + "integrity": "sha512-vcn9/6J5D6jtHxpEJrgK8FhaM8r6J1/ZiNu70ZUJN554Y3D9t3iovi6u7JF8l/e7FcBIxeuTEidZDR70UuCIfA==", "dev": true, "requires": { - "@typescript-eslint/utils": "5.17.0", + "@typescript-eslint/utils": "5.18.0", "debug": "^4.3.2", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.17.0.tgz", - "integrity": "sha512-AgQ4rWzmCxOZLioFEjlzOI3Ch8giDWx8aUDxyNw9iOeCvD3GEYAB7dxWGQy4T/rPVe8iPmu73jPHuaSqcjKvxw==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.18.0.tgz", + "integrity": "sha512-bhV1+XjM+9bHMTmXi46p1Led5NP6iqQcsOxgx7fvk6gGiV48c6IynY0apQb7693twJDsXiVzNXTflhplmaiJaw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.17.0.tgz", - "integrity": "sha512-X1gtjEcmM7Je+qJRhq7ZAAaNXYhTgqMkR10euC4Si6PIjb+kwEQHSxGazXUQXFyqfEXdkGf6JijUu5R0uceQzg==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.18.0.tgz", + "integrity": "sha512-wa+2VAhOPpZs1bVij9e5gyVu60ReMi/KuOx4LKjGx2Y3XTNUDJgQ+5f77D49pHtqef/klglf+mibuHs9TrPxdQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.17.0", - "@typescript-eslint/visitor-keys": "5.17.0", + "@typescript-eslint/types": "5.18.0", + "@typescript-eslint/visitor-keys": "5.18.0", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -26798,15 +26865,15 @@ } }, "@typescript-eslint/utils": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.17.0.tgz", - "integrity": "sha512-DVvndq1QoxQH+hFv+MUQHrrWZ7gQ5KcJzyjhzcqB1Y2Xes1UQQkTRPUfRpqhS8mhTWsSb2+iyvDW1Lef5DD7vA==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.18.0.tgz", + "integrity": "sha512-+hFGWUMMri7OFY26TsOlGa+zgjEy1ssEipxpLjtl4wSll8zy85x0GrUSju/FHdKfVorZPYJLkF3I4XPtnCTewA==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.17.0", - "@typescript-eslint/types": "5.17.0", - "@typescript-eslint/typescript-estree": "5.17.0", + "@typescript-eslint/scope-manager": "5.18.0", + "@typescript-eslint/types": "5.18.0", + "@typescript-eslint/typescript-estree": "5.18.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, @@ -26830,12 +26897,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.17.0.tgz", - "integrity": "sha512-6K/zlc4OfCagUu7Am/BD5k8PSWQOgh34Nrv9Rxe2tBzlJ7uOeJ/h7ugCGDCeEZHT6k2CJBhbk9IsbkPI0uvUkA==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.18.0.tgz", + "integrity": "sha512-Hf+t+dJsjAKpKSkg3EHvbtEpFFb/1CiOHnvI8bjHgOD4/wAw3gKrA0i94LrbekypiZVanJu3McWJg7rWDMzRTg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.17.0", + "@typescript-eslint/types": "5.18.0", "eslint-visitor-keys": "^3.0.0" } }, @@ -27913,9 +27980,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001324", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001324.tgz", - "integrity": "sha512-/eYp1J6zYh1alySQB4uzYFkLmxxI8tk0kxldbNHXp8+v+rdMKdUBNjRLz7T7fz6Iox+1lIdYpc7rq6ZcXfTukg==" + "version": "1.0.30001325", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001325.tgz", + "integrity": "sha512-sB1bZHjseSjDtijV1Hb7PB2Zd58Kyx+n/9EotvZ4Qcz2K3d0lWB8dB4nb8wN/TsOGFq3UuAm0zQZNQ4SoR7TrQ==" }, "canonicalize": { "version": "1.0.8", @@ -29784,9 +29851,9 @@ "requires": {} }, "eslint-plugin-testing-library": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.2.0.tgz", - "integrity": "sha512-fYFH8lA1hbc1Epr9laNm/+YIR2d+R7WI8sFz9jIRAUfqCf21Nb5BzZwhNeZlu9wKXwDtuf+hUM5QJxG1PuDsTQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.2.1.tgz", + "integrity": "sha512-88qJv6uzYALtiYJDzhelP3ov0Px/GLgnu+UekjjDxL2nMyvgdTyboKqcDBsvFPmAeizlCoSWOjeBN4DxO0BxaA==", "dev": true, "requires": { "@typescript-eslint/utils": "^5.13.0" @@ -30888,9 +30955,9 @@ } }, "graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, "growly": { @@ -36006,9 +36073,9 @@ } }, "postcss-lab-function": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.1.2.tgz", - "integrity": "sha512-isudf5ldhg4fk16M8viAwAbg6Gv14lVO35N3Z/49NhbwPQ2xbiEoHgrRgpgQojosF4vF7jY653ktB6dDrUOR8Q==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.0.tgz", + "integrity": "sha512-Zb1EO9DGYfa3CP8LhINHCcTTCTLI+R3t7AX2mKsDzdgVQ/GkCpHOTgOr6HBHslP7XDdVbqgHW5vvRPMdVANQ8w==", "dev": true, "requires": { "@csstools/postcss-progressive-custom-properties": "^1.1.0", @@ -36182,12 +36249,12 @@ } }, "postcss-nesting": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.1.3.tgz", - "integrity": "sha512-wUC+/YCik4wH3StsbC5fBG1s2Z3ZV74vjGqBFYtmYKlVxoio5TYGM06AiaKkQPPlkXWn72HKfS7Cw5PYxnoXSw==", + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.1.4.tgz", + "integrity": "sha512-2ixdQ59ik/Gt1+oPHiI1kHdwEI8lLKEmui9B1nl6163ANLC+GewQn7fXMxJF2JSb4i2MKL96GU8fIiQztK4TTA==", "dev": true, "requires": { - "postcss-selector-parser": "^6.0.9" + "postcss-selector-parser": "^6.0.10" } }, "postcss-normalize": { @@ -36373,12 +36440,12 @@ } }, "postcss-pseudo-class-any-link": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.1.tgz", - "integrity": "sha512-JRoLFvPEX/1YTPxRxp1JO4WxBVXJYrSY7NHeak5LImwJ+VobFMwYDQHvfTXEpcn+7fYIeGkC29zYFhFWIZD8fg==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.2.tgz", + "integrity": "sha512-76XzEQv3g+Vgnz3tmqh3pqQyRojkcJ+pjaePsyhcyf164p9aZsu3t+NWxkZYbcHLK1ju5Qmalti2jPI5IWCe5w==", "dev": true, "requires": { - "postcss-selector-parser": "^6.0.9" + "postcss-selector-parser": "^6.0.10" } }, "postcss-reduce-initial": { diff --git a/webapp/package.json b/webapp/package.json index b78867a..3b68c14 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -55,6 +55,7 @@ "@types/express": "^4.17.13", "@types/jest": "^27.4.0", "@types/puppeteer": "^5.4.4", + "@types/styled-components": "^5.1.24", "expect-puppeteer": "^6.0.2", "jest-cucumber": "^3.0.1", "jest-puppeteer": "^6.0.3", diff --git a/webapp/src/App.tsx b/webapp/src/App.tsx index e214403..746ce02 100644 --- a/webapp/src/App.tsx +++ b/webapp/src/App.tsx @@ -1,3 +1,14 @@ + +import { useQuery } from 'react-query'; +import Box from '@mui/material/Box'; +//import Link from '@mui/material/Link'; +import Grid from '@mui/material/Grid'; + +import logo from './images/interfaz/logoRock.png'; +import Title from './components/titleUtil'; + + +import { createTheme, Drawer, List } from '@mui/material'; import { useState, useEffect } from 'react'; import Welcome from './components/Welcome'; import {getRocas} from './api/api'; @@ -16,6 +27,14 @@ import { Container } from '@mui/material'; //import {createData} from "./code/insertExampleData" +import ShoppingCart from './components/ShoppingCart'; +import PaymentPage from './components/PaymentPage'; +import { ContentCopy } from '@mui/icons-material'; + +type Props = { + openCart: () => void; +}; + function App(): JSX.Element { const [rocks,setRocks] = useState([]); @@ -23,25 +42,103 @@ function App(): JSX.Element { setRocks(await getRocas()); } + // Shopping cart + const [isNewCart, setNewCart] = useState(false); + const [isCartOpen, setCartOpen] = useState(false); + const [cartContent,setCartContent] = useState([]); + + useEffect(() => { + if(isNewCart) { + resetCart(); + setNewCart(false); + return; + } + const memoryCart = localStorage.getItem("cart"); + if (memoryCart) { + let cart: Rock[] = JSON.parse(memoryCart); + setCartContent(cart); + } else { + localStorage.setItem("cart", JSON.stringify([])); + } + }, [isNewCart]); + + const resetCart = () => { + setCartContent([]); + localStorage.setItem("cart", JSON.stringify([])); + setCartContent([]); + }; + + const handleAddToCart = (selectedItem: Rock) => { + localStorage.setItem("cart", JSON.stringify(cartContent)); + setCartContent(cart => { + if (cart.find(rocaInCart => rocaInCart.name === selectedItem.name)) { + // return cart.map(Rock => ( + // Rock.name === selectedItem.name ? + // { ...Rock, quantityCart: Rock.quantityCart + 1 } : + // Rock + // )); + var tempCart= cart.map(Rock=>( + Rock.name === selectedItem.name ? + { ...Rock, quantityCart: Rock.quantityCart + 1 } : + Rock + )); + return tempCart; + } + // return [...cart, {...selectedItem, quantityCart: 1}]; + var tempCart= [...cart, {...selectedItem, quantityCart:1}]; + return tempCart; + }); + }; + + const handleRemoveFromCart = (name: string) => { + localStorage.setItem("cart", JSON.stringify(cartContent)); + setCartContent(cart => ( + cart.reduce((sum, p) => { + if (p.name === name) { + if (p.quantityCart === 1) { + return sum; + } + // return [...sum, {...p, quantityCart: p.quantityCart - 1}]; + var tempCart= [...sum, {...p, quantityCart:p.quantityCart - 1}] + return tempCart; + } else { + // return [...sum, p]; + var tempCart= [...sum, p]; + return tempCart; + } + }, [] as Rock[]) + )); + }; + + useEffect(()=>{ refreshRockList(); },[]); return ( - + setCartOpen(true)}/> - } /> + } /> } /> - }/> + }/> + }/> }/> }/> + setCartOpen(false)}> + + + ); diff --git a/webapp/src/components/CartItem.tsx b/webapp/src/components/CartItem.tsx new file mode 100644 index 0000000..ff86dfc --- /dev/null +++ b/webapp/src/components/CartItem.tsx @@ -0,0 +1,58 @@ +import { Typography } from '@material-ui/core'; +import Button from '@material-ui/core/Button'; +import { Card, CardContent, CardMedia } from '@mui/material'; +import { Rock } from '../shared/shareddtypes'; +import '../css/CartItem.css'; + +type Props = { + item: Rock; + handleAddToCart: (selectedItem: Rock) => void; + handleRemoveFromCart: (id: string) => void; +} + + +const CartItem: React.FC = ({item, handleAddToCart, handleRemoveFromCart}) => { + + return ( + + + + {item.name} + +
+ + + {item.quantityCart + " uds " } + + +
+ + {(item.price * item.quantityCart).toFixed(2) + " €"} + +
+ +
+ + + ) +}; + + +export default CartItem; + diff --git a/webapp/src/components/Catalog.tsx b/webapp/src/components/Catalog.tsx index 48bef96..13313b7 100644 --- a/webapp/src/components/Catalog.tsx +++ b/webapp/src/components/Catalog.tsx @@ -1,8 +1,10 @@ import {Rock} from '../shared/shareddtypes'; import List from '@mui/material/List'; import Product from './Product'; + type RockListProps = { rocks: Rock[]; + handleAddToCart(rock:Rock): void; }; //a function Catalogo(rocks: RockListProps): JSX.Element { @@ -10,7 +12,7 @@ function Catalogo(rocks: RockListProps): JSX.Element { <> {rocks.rocks.map((rock,index)=>{ - return + return })} diff --git a/webapp/src/components/NavigationBar.tsx b/webapp/src/components/NavigationBar.tsx index 24b88b6..beb2f42 100644 --- a/webapp/src/components/NavigationBar.tsx +++ b/webapp/src/components/NavigationBar.tsx @@ -3,8 +3,13 @@ import Toolbar from '@mui/material/Toolbar'; import IconButton from '@mui/material/IconButton'; import Typography from '@mui/material/Typography'; import Button from '@mui/material/Button'; +import { Avatar, Tooltip } from '@mui/material'; -const NavBar=() =>{ +type Props = { + openCart: () => void; + }; + +const NavBar:React.FC=({openCart}) =>{ return( @@ -21,7 +26,11 @@ const NavBar=() =>{ - + + + + + ); diff --git a/webapp/src/components/PaymentPage.tsx b/webapp/src/components/PaymentPage.tsx new file mode 100644 index 0000000..53e7f96 --- /dev/null +++ b/webapp/src/components/PaymentPage.tsx @@ -0,0 +1,94 @@ + +import List from '@mui/material/List'; +import ListItemText from '@mui/material/ListItemText'; +import Grid from '@mui/material/Grid'; + +import Button from '@mui/material/Button'; +import '../css/PaymentPage.css' +import { CardContent, Typography } from '@mui/material'; +import { North } from '@mui/icons-material'; +import { useState } from 'react'; +import { Rock } from '../shared/shareddtypes'; + + +type Props = { + cartContent: Rock[]; + setNewCart: (isNewCart: boolean) => void; +}; + +const PaymentPage: React.FC = ({cartContent, setNewCart}) => { + + const [isPaid, setPaid] = useState(false); + const getTotalPrice = () => cartContent.reduce((sum: number, item) => sum + item.quantityCart * item.price, 0); + + const handlePay = () => { + if(!isPaid) + return; + + setNewCart(true); + setPaid(false); + } + + return ( +
+

Your BUY

+
+ +
+
+

Articles

+
+ { cartContent.map(Rock => ( +
+

{Rock.name}

+

x{Rock.quantityCart}

+

{Rock.quantityCart*Rock.price}€

+
+ )) + } +
+
+ +
+

Payment summary

+

Cost (no iva): { (getTotalPrice() - (getTotalPrice()*0.21)).toFixed(2) }€

+

Cost: {getTotalPrice().toFixed(2)}€

+ +

Cost (shipping costs): {(getTotalPrice()+ 12).toFixed(2)}€

+ {/* Aqui cogemos la dir de los pods y sacamos los costes envio */} +
+
+ + {isPaid ?

Purchase made

: null} + +
+ + +
+
+
+ ) +}; + +export default PaymentPage; diff --git a/webapp/src/components/Product.tsx b/webapp/src/components/Product.tsx index 4948571..88683ae 100644 --- a/webapp/src/components/Product.tsx +++ b/webapp/src/components/Product.tsx @@ -5,6 +5,7 @@ import Button from '@mui/material/Button'; type ProductProps = { product: Rock |null; buyable:boolean; + handleAddToCart(r:Rock): void; }; //a function Product(product: ProductProps): JSX.Element { @@ -33,7 +34,13 @@ function Product(product: ProductProps): JSX.Element { } - + ); } diff --git a/webapp/src/components/ShoppingCart.tsx b/webapp/src/components/ShoppingCart.tsx new file mode 100644 index 0000000..aad36a5 --- /dev/null +++ b/webapp/src/components/ShoppingCart.tsx @@ -0,0 +1,54 @@ +import { Button, Grid } from '@mui/material'; +import e from 'express'; +import { useEffect, useState } from 'react'; +import { Rock } from '../shared/shareddtypes'; +import CartItem from './CartItem'; +import '../css/ShoppingCart.css'; +import ProfileViewer from './solid-pods/ProfileViewer'; +import { useSession } from '@inrupt/solid-ui-react'; +import LoginPod from './solid-pods/LoginPod'; + + + +type Props = { + cartContent: Rock[]; + handleAddToCart: (selectedItem: Rock) => void; + handleRemoveFromCart: (id: string) => void; +}; + +const Cart: React.FC = ({ cartContent, handleAddToCart, handleRemoveFromCart }) => { + + const getTotalPrice = () => cartContent.reduce((sum: number, item) => sum + item.quantityCart * item.price, 0); + + const check2 = (cartContent: Rock[]) => { + let a = ""; + cartContent.forEach((v, k) => ( a += (v.name + " " + v.quantityCart + "\n") )); + console.log(a); + + } + + return ( + +

Shopping Cart

+ {cartContent.length === 0 ?

No items in the cart

: null} + + +
+ {cartContent.map(item => ( + + ))} +

Total: {getTotalPrice().toFixed(2)} €

+
+ + + +
+ ) +}; + +export default Cart; \ No newline at end of file diff --git a/webapp/src/components/Showcase.tsx b/webapp/src/components/Showcase.tsx index cc7b2b9..421cd3e 100644 --- a/webapp/src/components/Showcase.tsx +++ b/webapp/src/components/Showcase.tsx @@ -5,14 +5,12 @@ import Product from './Product'; type RockListProps = { rocks: Rock[]; name:String; + handleAddToCart(r:Rock): void; }; //a function Showcase(prefilteredbox: RockListProps): JSX.Element { - - - return ( <>
@@ -23,7 +21,10 @@ function Showcase(prefilteredbox: RockListProps): JSX.Element { { prefilteredbox.rocks.map((_,product)=>{ if(prefilteredbox.rocks[product]!==undefined) - return ; + return ; }) } diff --git a/webapp/src/components/Showcases.tsx b/webapp/src/components/Showcases.tsx index 6848438..2699cc9 100644 --- a/webapp/src/components/Showcases.tsx +++ b/webapp/src/components/Showcases.tsx @@ -4,7 +4,11 @@ import { Rock } from "../shared/shareddtypes"; import Showcase from "./Showcase"; import prefilters from "../code/Prefilters" -function Showcases() { +type RockListProps = { + handleAddToCart(r:Rock): void; +}; + +function Showcases(prefilteredbox: RockListProps): JSX.Element { const [prefilteredRocks,setPrefilteredRocks] = useState([]); const [nameOfFilters,setNameOfFilters]=useState([]); @@ -22,7 +26,9 @@ function Showcases() { <> {prefilteredRocks.map((_, element) => { - return (); + + return (); + })} diff --git a/webapp/src/components/Welcome.tsx b/webapp/src/components/Welcome.tsx index 18ca905..103b640 100644 --- a/webapp/src/components/Welcome.tsx +++ b/webapp/src/components/Welcome.tsx @@ -1,10 +1,12 @@ - -import { Box, Container } from "@mui/material"; -import Grid from "@mui/material/Grid"; import logo from '../images/interfaz/logoRock.png'; import Showcases from "./Showcases"; +import { Rock } from "../shared/shareddtypes"; + +type RockListProps = { + handleAddToCart(r:Rock): void; +}; -function Welcome(): JSX.Element { +function Welcome(prefilteredbox: RockListProps): JSX.Element { return ( @@ -14,7 +16,7 @@ function Welcome(): JSX.Element {
- +
); diff --git a/webapp/src/components/solid-pods/LoginPod.tsx b/webapp/src/components/solid-pods/LoginPod.tsx index 6505fc5..0ebee27 100644 --- a/webapp/src/components/solid-pods/LoginPod.tsx +++ b/webapp/src/components/solid-pods/LoginPod.tsx @@ -2,16 +2,30 @@ import { useState, useEffect } from 'react'; import { SessionProvider, useSession } from "@inrupt/solid-ui-react"; import LoginForm from "./LoginForm" import ProfileViewer from "./ProfileViewer" +import React from 'react'; +import { Rock } from '../../shared/shareddtypes'; //import {createData} from "./code/insertExampleData" -function LoginPod(): JSX.Element { + +function LoginPod(): JSX.Element { //We use this state variable const [isLoggedIn, setIsLoggedIn] = useState(false); //With this we can control the login status for solid const { session } = useSession(); + +function getCartContent() { + const memoryCart = localStorage.getItem("cart"); + if (memoryCart) { + return JSON.parse(memoryCart); + } else { + return []; + } +} + + //We have logged in session.onLogin(()=>{ setIsLoggedIn(true) @@ -24,9 +38,12 @@ session.onLogout(()=>{ return ( - {(!isLoggedIn) ? : } + + {(!isLoggedIn) ? : } ) } export default LoginPod; + + diff --git a/webapp/src/components/solid-pods/ProfileViewer.tsx b/webapp/src/components/solid-pods/ProfileViewer.tsx index 29fd4bc..3731872 100644 --- a/webapp/src/components/solid-pods/ProfileViewer.tsx +++ b/webapp/src/components/solid-pods/ProfileViewer.tsx @@ -2,8 +2,13 @@ import { useSession, CombinedDataProvider, Image, LogoutButton, Text } from "@in import { Button, Card, CardActionArea, CardContent, Container, Typography } from "@material-ui/core"; import { FOAF, VCARD } from "@inrupt/lit-generated-vocab-common"; import GetPodAddress from './GetPodAddress'; +import { Rock } from "../../shared/shareddtypes"; -const ProfileViewer = () => { +type Props = { + cartContent: Rock[]; +}; + +const ProfileViewer: React.FC = ({cartContent}) => { const { session } = useSession(); return ( @@ -28,6 +33,15 @@ const ProfileViewer = () => { + ); diff --git a/webapp/src/css/CartItem.css b/webapp/src/css/CartItem.css new file mode 100644 index 0000000..ad1ccee --- /dev/null +++ b/webapp/src/css/CartItem.css @@ -0,0 +1,20 @@ +.cartItem-ci{ + display:grid; + grid-template-columns: repeat(3,auto); + grid-template-rows: repeat(1,1fr); +} + +.quantityController-ci { + grid-row-start: 1; + grid-row-end: 2; + + grid-column-start: 2; + grid-column-end: 3; + + + + display:grid; + grid-template-columns: repeat(3,auto); + grid-template-rows: repeat(1,auto); +} + diff --git a/webapp/src/css/PaymentPage.css b/webapp/src/css/PaymentPage.css new file mode 100644 index 0000000..5754374 --- /dev/null +++ b/webapp/src/css/PaymentPage.css @@ -0,0 +1,90 @@ +.paymentpage-payment{ + + padding: 5%; +} + +#title-payment{ + grid-row-start: 1; + grid-row-end: 2; + + grid-column-start: 1; + grid-column-end: 2; + + text-align:'left'; + + border-width: thin; + border-style: dotted; +} + +#info-payment{ + grid-row-start: 2; + grid-row-end: 3; + + grid-column-start: 1; + grid-column-end: 2; + + + display:grid; + grid-template-columns: repeat(1,1fr); + grid-template-rows: repeat(auto,1fr); + + text-align: center; + align-content: center; + + border-width: thin; + border-style: dotted; + +} + #articles-payment{ + grid-row-start: 1; + grid-row-end: 2; + + grid-column-start: 1; + grid-column-end: 2; + + text-align: left; + + padding-right: 50%; + } + #items-payment{ + display:grid; + grid-template-columns: repeat(3,1fr); + grid-template-rows: repeat(1,1fr); + + + text-align: left; + + } + + #bill-payment{ + grid-row-start: 1; + grid-row-end: 2; + + grid-column-start: 2; + grid-column-end: 3; + + text-align: left; + } + +#actionButtons-payment{ + grid-row-start: 3; + grid-row-end: 4; + + grid-column-start: 1; + grid-column-end: 2; + +} +#items-name-payment{ + text-align: left; + padding-right: 10%; + +} +#items-quantity-payment{ + text-align: center; + padding-right: 10%; + +} +#items-total-payment{ + text-align: right; + +} \ No newline at end of file diff --git a/webapp/src/css/ShoppingCart.css b/webapp/src/css/ShoppingCart.css new file mode 100644 index 0000000..0611de4 --- /dev/null +++ b/webapp/src/css/ShoppingCart.css @@ -0,0 +1,46 @@ + +shoppingCart{ + display:grid; + grid-template-columns: repeat(1,1fr); + grid-template-rows: repeat(4,1fr); + +} + +#title-cart{ + grid-row-start: 1; + grid-row-end: 2; + + grid-column-start: 1; + grid-column-end: 2; + + background-color: gold; +} + +#items-cart{ + grid-row-start: 2; + grid-row-end: 3; + + grid-column-start: 1; + grid-column-end: 2; +} + +#price-cart{ + grid-row-start: 3; + grid-row-end: 4; + + grid-column-start: 1; + grid-column-end: 2; + + background: gold; +} + +#pay-button{ + grid-row-start: 4; + grid-row-end: 5; + + grid-column-start: 1; + grid-column-end: 2; + + + background: cornflowerblue; +} \ No newline at end of file diff --git a/webapp/src/images/interfaz/carrito-de-compras.png b/webapp/src/images/interfaz/carrito-de-compras.png new file mode 100644 index 0000000..3f0f7f9 Binary files /dev/null and b/webapp/src/images/interfaz/carrito-de-compras.png differ diff --git a/webapp/src/shared/shareddtypes.ts b/webapp/src/shared/shareddtypes.ts index 3fcca88..4b5f808 100644 --- a/webapp/src/shared/shareddtypes.ts +++ b/webapp/src/shared/shareddtypes.ts @@ -8,10 +8,13 @@ export type User = { }; export type Rock = { id:React.Key; - name: String; + name: string; img: string; - price: Number; - mohsHardness:Number; - density:String; - type:String; + price: number; + mohsHardness:number; + density:string; + type:string; + + + quantityCart:number } \ No newline at end of file