diff --git a/frontend/pronunciationAppFront/README.md b/frontend/pronunciationAppFront/README.md index f768e33fc..70ac016cc 100644 --- a/frontend/pronunciationAppFront/README.md +++ b/frontend/pronunciationAppFront/README.md @@ -1,8 +1,88 @@ -# React + Vite +# Descripción del Cambio -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. +Este PR incluye la implementación de las tareas definidas en la práctica, abarcando: -Currently, two official plugins are available: +- Configuración de un servidor mock en Postman. +- Diseño de funciones desacopladas con Axios. +- Creación de estructuras de datos JSON para usuarios y palabras. +- Desarrollo de componentes React que renderizan los datos con características avanzadas. + +--- + +## ¿Cómo ejecutar el proyecto? +- Frontend: Ejecuta el comando `npm run dev` +- Api: Ejecuta el comando `npm run start:api` + +## Cambios Realizados + +### Configuración del servidor mock en Postman + +- Se creó un servidor mock con un endpoint personalizado: [Mock Server](https://1f196337-d694-4b64-9b0e-ef471d8cd805.mock.pstmn.io) +- Las respuestas mock fueron diseñadas para: + - **Estructura de usuarios**, incluyendo: + - Nombre, edad, correo electrónico, fecha de registro, dirección postal y preferencias de usuario. + - **Estructura de palabras**, incluyendo: + - ID, pronunciación, niveles de dificultad y sinónimos. + +### Implementación de la función Axios para obtención de datos + +- Se creó un archivo separado `data-api.js` con la función Axios. +- La función realiza solicitudes `GET` al servidor mock de Postman. +- Maneja errores y retorna los datos obtenidos. +- **Nota:** Se implementó un servidor personalizado con `json-server` debido a la limitación de peticiones en el servidor mock. + +### Estructura JSON para usuarios + +Se diseñó una estructura JSON con los siguientes campos: + +```json +{ + "id": "1", + "name": "Jane Doe", + "age": 28, + "isActive": true, + "joinDate": "2024-12-10", + "email": "jane.doe@example.com", + "phone": "+1234567890", + "address": { + "street": "123 Main St", + "city": "Springfield", + "zipcode": "12345" + }, + "preferences": { + "newsletter": true, + "notifications": false + }, + "profile": { + "avatar": {"imageId": "abc123", "imageName": "Jane_Doe"}, + "bio": "Avid traveler and coffee enthusiast." + } +} +``` + +- Esta estructura incluye tipos de datos variados como `string`, `boolean`, `int` y `date`. +- Los datos fueron añadidos al servidor mock. + +### Componente de usuario con avatar + +- Se desarrolló un componente `User.jsx` que muestra los datos del usuario, incluyendo un avatar. +- Los datos del usuario son obtenidos del servidor mock y renderizados dinámicamente. + +### Ampliación de la estructura de palabras + +- Se añadió un campo de dificultad con 3 niveles posibles: `rookie`, `pro` y `legend`. +- Se implementó una función de filtrado que permite mostrar solo las palabras dependiendo del nivel. + +### Renderizado de sinónimos para palabras + +- Se añadió un campo `synonyms` como un array en la estructura de palabras. +- El componente `WordSynonyms.jsx` renderiza los sinónimos y maneja adecuadamente las palabras que no tienen sinónimos. + +### Personalización avanzada + +- Se aplicaron mejoras visuales con CSS, incluyendo: + - Un fondo con gradiente para las cards. + - Efecto transitorio al hacer `hover` sobre las tarjetas. + - Animaciones con `Motion` para mejorar la interacción. + - Se incluyó una tarjeta mejorada con controles de reproducción utilizando `Material-UI`. -- [@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/frontend/pronunciationAppFront/db.json b/frontend/pronunciationAppFront/db.json new file mode 100644 index 000000000..7833f959d --- /dev/null +++ b/frontend/pronunciationAppFront/db.json @@ -0,0 +1,123 @@ +{ + "words": { + "words": [ + { + "id": "8b9248a4e0b64bbccf82e7723a3734279bf9bbc4", + "word": "benevolent", + "pronunciation": "/bɪˈnɛvələnt/", + "level": 3 + }, + { + "id": "3a7bd3e2a07e8c7e9b6e0d2c1f4a5b8d9c0e3f2", + "word": "serendipity", + "pronunciation": "/ˌserənˈdɪpɪti/", + "level": 1 + }, + { + "id": "5c9d7f3e1a2b4d6e8g0h9i7j6k5l4m3n2o1p", + "word": "ephemeral", + "pronunciation": "/ɪˈfɛmərəl/", + "level": 3, + "synonyms": ["transient", "fleeting", "momentary"] + }, + { + "id": "2f4e6d8c0b2a4d6e8f0a2c4e6g8i0k2m4o6q", + "word": "ubiquitous", + "pronunciation": "/juːˈbɪkwɪtəs/", + "level": 3, + "synonyms": ["omnipresent", "universal", "pervasive"] + }, + { + "id": "7h9j1l3n5p7r9t1v3x5z7b9d1f3h5j7l9n", + "word": "mellifluous", + "pronunciation": "/məˈlɪfluəs/", + "level": 3, + "synonyms": ["harmonious", "melodious", "euphonic"] + }, + { + "id": "1a3c5e7g9i1k3m5o7q9s1u3w5y7a9c1e3", + "word": "eloquent", + "pronunciation": "/ˈɛləkwənt/", + "level": 1, + "synonyms": ["articulate", "expressive", "persuasive"] + }, + { + "id": "4b6d8f0h2j4l6n8p0r2t4v6x8z0b2d4f6", + "word": "quintessential", + "pronunciation": "/ˌkwɪntɪˈsenʃəl/", + "level": 2, + "synonyms": ["typical", "ideal", "archetypal"] + }, + { + "id": "9k1m3o5q7s9u1w3y5a7c9e1g3i5k7m9o", + "word": "ethereal", + "pronunciation": "/ɪˈθɪəriəl/", + "level": 2, + "synonyms": ["delicate", "heavenly", "airy"] + }, + { + "id": "2p4r6t8v0x2z4b6d8f0h2j4l6n8p0r2t", + "word": "surreptitious", + "pronunciation": "/ˌsʌrəpˈtɪʃəs/", + "level": 2, + "synonyms": ["secretive", "clandestine", "stealthy"] + }, + { + "id": "5u7w9y1a3c5e7g9i1k3m5o7q9s1u3w5", + "word": "labyrinthine", + "pronunciation": "/ˌlæbəˈrɪnθaɪn/", + "level": 1, + "synonyms": ["complex", "intricate", "convoluted"] + }, + { + "id": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6", + "word": "ambivalent", + "pronunciation": "/æmˈbɪvələnt/", + "level": 2 + }, + { + "id": "z1x2c3v4b5n6m7q8w9e0r1t2y3u4i5o6", + "word": "capricious", + "pronunciation": "/kəˈprɪʃəs/", + "level": 3, + "synonyms": ["unpredictable", "impulsive", "fickle"] + }, + { + "id": "q1w2e3r4t5y6u7i8o9p0a1s2d3f4g5h6", + "word": "idiosyncratic", + "pronunciation": "/ˌɪdiəsɪŋˈkrætɪk/", + "level": 1, + "synonyms": ["distinctive", "peculiar", "individual"] + }, + { + "id": "m1n2b3v4c5x6z7a8s9d0f1g2h3j4k5l6", + "word": "resilient", + "pronunciation": "/rɪˈzɪliənt/", + "level": 2, + "synonyms": ["strong", "hardy", "adaptable"] + } + ] + }, + "user": { + "id": "1", + "name": "Jane Doe", + "age": 28, + "isActive": true, + "joinDate": "2024-12-10", + "email": "jane.doe@example.com", + "phone": "+1234567890", + "address": { + "street": "123 Main St", + "city": "Springfield", + "zipcode": "12345" + }, + "preferences": { + "newsletter": true, + "notifications": false + }, + "profile": { + "avatar": { "imageId": "abc123", "imageName": "Jane_Doe" }, + "bio": "Avid traveler and coffee enthusiast." + } + } +} diff --git a/frontend/pronunciationAppFront/package-lock.json b/frontend/pronunciationAppFront/package-lock.json index 96c25f82d..20af73c35 100644 --- a/frontend/pronunciationAppFront/package-lock.json +++ b/frontend/pronunciationAppFront/package-lock.json @@ -8,6 +8,14 @@ "name": "pronunciationappfront", "version": "0.0.0", "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.0", + "@fontsource/roboto": "^5.1.1", + "@mui/icons-material": "^6.4.0", + "@mui/material": "^6.4.0", + "axios": "^1.7.9", + "json-server": "^1.0.0-beta.3", + "motion": "^12.0.5", "react": "^18.3.1", "react-dom": "^18.3.1" }, @@ -24,6 +32,270 @@ "vite": "^6.0.5" } }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", + "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", + "dependencies": { + "@babel/parser": "^7.26.5", + "@babel/types": "^7.26.5", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.5.tgz", + "integrity": "sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==", + "dependencies": { + "@babel/types": "^7.26.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", + "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.5.tgz", + "integrity": "sha512-rkOSPOw+AXbgtwUga3U4u8RpoK9FEFWBNAlTpcnkLFjL5CT+oyHNuUUC/xx6XefEJ16r38r8Bc/lfp6rYuHeJQ==", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.5", + "@babel/parser": "^7.26.5", + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.5", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/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==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.5.tgz", + "integrity": "sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz", + "integrity": "sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==", + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" + }, + "node_modules/@emotion/react": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", + "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==" + }, + "node_modules/@emotion/styled": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz", + "integrity": "sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==" + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.24.2", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", @@ -554,6 +826,11 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@fontsource/roboto": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.1.1.tgz", + "integrity": "sha512-XwVVXtERDQIM7HPUIbyDe0FP4SRovpjF7zMI8M7pbqFp3ahLJsJTd18h+E6pkar6UbV3btbwkKjYARr5M+SQow==" + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -615,6 +892,296 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mui/core-downloads-tracker": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.4.0.tgz", + "integrity": "sha512-6u74wi+9zeNlukrCtYYET8Ed/n9AS27DiaXCZKAD3TRGFaqiyYSsQgN2disW83pI/cM1Q2lJY1JX4YfwvNtlNw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/icons-material": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-6.4.0.tgz", + "integrity": "sha512-zF0Vqt8a+Zp2Oz8P+WvJflba6lLe3PhxIz1NNqn+n4A+wKLPbkeqY8ShmKjPyiCTg0RMbPrp993oUDl9xGsDlQ==", + "dependencies": { + "@babel/runtime": "^7.26.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^6.4.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.4.0.tgz", + "integrity": "sha512-hNIgwdM9U3DNmowZ8mU59oFmWoDKjc92FqQnQva3Pxh6xRKWtD2Ej7POUHMX8Dwr1OpcSUlT2+tEMeLb7WYsIg==", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@mui/core-downloads-tracker": "^6.4.0", + "@mui/system": "^6.4.0", + "@mui/types": "^7.2.21", + "@mui/utils": "^6.4.0", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.12", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^19.0.0", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material-pigment-css": "^6.4.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material/node_modules/react-is": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz", + "integrity": "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==" + }, + "node_modules/@mui/private-theming": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.4.0.tgz", + "integrity": "sha512-rNHci8MP6NOdEWAfZ/RBMO5Rhtp1T6fUDMSmingg9F1T6wiUeodIQ+NuTHh2/pMoUSeP9GdHdgMhMmfsXxOMuw==", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@mui/utils": "^6.4.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.4.0.tgz", + "integrity": "sha512-ek/ZrDujrger12P6o4luQIfRd2IziH7jQod2WMbLqGE03Iy0zUwYmckRTVhRQTLPNccpD8KXGcALJF+uaUQlbg==", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@emotion/cache": "^11.13.5", + "@emotion/serialize": "^1.3.3", + "@emotion/sheet": "^1.4.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.4.0.tgz", + "integrity": "sha512-wTDyfRlaZCo2sW2IuOsrjeE5dl0Usrs6J7DxE3GwNCVFqS5wMplM2YeNiV3DO7s53RfCqbho+gJY6xaB9KThUA==", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@mui/private-theming": "^6.4.0", + "@mui/styled-engine": "^6.4.0", + "@mui/types": "^7.2.21", + "@mui/utils": "^6.4.0", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.2.21", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.21.tgz", + "integrity": "sha512-6HstngiUxNqLU+/DPqlUJDIPbzUBxIVHb1MmXP0eTWDIROiCR2viugXpEif0PPe2mLqqakPzzRClWAnK+8UJww==", + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.4.0.tgz", + "integrity": "sha512-woOTATWNsTNR3YBh2Ixkj3l5RaxSiGoC9G8gOpYoFw1mZM77LWJeuMHFax7iIW4ahK0Cr35TF9DKtrafJmOmNQ==", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@mui/types": "^7.2.21", + "@types/prop-types": "^15.7.14", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.0.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils/node_modules/react-is": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz", + "integrity": "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==" + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.28", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", + "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", + "license": "MIT" + }, + "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/@rollup/rollup-android-arm-eabi": { "version": "4.30.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.30.1.tgz", @@ -1075,6 +1642,244 @@ "@swc/counter": "^0.1.3" } }, + "node_modules/@tinyhttp/accepts": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@tinyhttp/accepts/-/accepts-2.2.3.tgz", + "integrity": "sha512-9pQN6pJAJOU3McmdJWTcyq7LLFW8Lj5q+DadyKcvp+sxMkEpktKX5sbfJgJuOvjk6+1xWl7pe0YL1US1vaO/1w==", + "license": "MIT", + "dependencies": { + "mime": "4.0.4", + "negotiator": "^0.6.3" + }, + "engines": { + "node": ">=12.20.0" + }, + "funding": { + "type": "individual", + "url": "https://github.com/tinyhttp/tinyhttp?sponsor=1" + } + }, + "node_modules/@tinyhttp/app": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@tinyhttp/app/-/app-2.5.0.tgz", + "integrity": "sha512-mwVY6RhTqF/s49tqNqpkRWbXAC7OmfpxR6YI6atp9xDauUOv3n1hv38AKy89Ga8HC8G2p1KR9vPD66VmF6VMnw==", + "license": "MIT", + "dependencies": { + "@tinyhttp/cookie": "2.1.1", + "@tinyhttp/proxy-addr": "2.2.0", + "@tinyhttp/req": "2.2.4", + "@tinyhttp/res": "2.2.4", + "@tinyhttp/router": "2.2.3", + "header-range-parser": "1.1.3", + "regexparam": "^2.0.2" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "individual", + "url": "https://github.com/tinyhttp/tinyhttp?sponsor=1" + } + }, + "node_modules/@tinyhttp/content-disposition": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@tinyhttp/content-disposition/-/content-disposition-2.2.2.tgz", + "integrity": "sha512-crXw1txzrS36huQOyQGYFvhTeLeG0Si1xu+/l6kXUVYpE0TjFjEZRqTbuadQLfKGZ0jaI+jJoRyqaWwxOSHW2g==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "funding": { + "type": "individual", + "url": "https://github.com/tinyhttp/tinyhttp?sponsor=1" + } + }, + "node_modules/@tinyhttp/content-type": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@tinyhttp/content-type/-/content-type-0.1.4.tgz", + "integrity": "sha512-dl6f3SHIJPYbhsW1oXdrqOmLSQF/Ctlv3JnNfXAE22kIP7FosqJHxkz/qj2gv465prG8ODKH5KEyhBkvwrueKQ==", + "license": "MIT", + "engines": { + "node": ">=12.4" + } + }, + "node_modules/@tinyhttp/cookie": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/cookie/-/cookie-2.1.1.tgz", + "integrity": "sha512-h/kL9jY0e0Dvad+/QU3efKZww0aTvZJslaHj3JTPmIPC9Oan9+kYqmh3M6L5JUQRuTJYFK2nzgL2iJtH2S+6dA==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "funding": { + "type": "individual", + "url": "https://github.com/tinyhttp/tinyhttp?sponsor=1" + } + }, + "node_modules/@tinyhttp/cookie-signature": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/cookie-signature/-/cookie-signature-2.1.1.tgz", + "integrity": "sha512-VDsSMY5OJfQJIAtUgeQYhqMPSZptehFSfvEEtxr+4nldPA8IImlp3QVcOVuK985g4AFR4Hl1sCbWCXoqBnVWnw==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/cors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/cors/-/cors-2.0.1.tgz", + "integrity": "sha512-qrmo6WJuaiCzKWagv2yA/kw6hIISfF/hOqPWwmI6w0o8apeTMmRN3DoCFvQ/wNVuWVdU5J4KU7OX8aaSOEq51A==", + "license": "MIT", + "dependencies": { + "@tinyhttp/vary": "^0.1.3" + }, + "engines": { + "node": ">=12.20 || 14.x || >=16" + } + }, + "node_modules/@tinyhttp/encode-url": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/encode-url/-/encode-url-2.1.1.tgz", + "integrity": "sha512-AhY+JqdZ56qV77tzrBm0qThXORbsVjs/IOPgGCS7x/wWnsa/Bx30zDUU/jPAUcSzNOzt860x9fhdGpzdqbUeUw==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/etag": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@tinyhttp/etag/-/etag-2.1.2.tgz", + "integrity": "sha512-j80fPKimGqdmMh6962y+BtQsnYPVCzZfJw0HXjyH70VaJBHLKGF+iYhcKqzI3yef6QBNa8DKIPsbEYpuwApXTw==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/forwarded": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/forwarded/-/forwarded-2.1.1.tgz", + "integrity": "sha512-nO3kq0R1LRl2+CAMlnggm22zE6sT8gfvGbNvSitV6F9eaUSurHP0A8YZFMihSkugHxK+uIegh1TKrqgD8+lyGQ==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/logger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tinyhttp/logger/-/logger-2.0.0.tgz", + "integrity": "sha512-8DfLQjGDIaIJeivYamVrrpmwmsGwS8wt2DGvzlcY5HEBagdiI4QJy/veAFcUHuaJqufn4wLwmn4q5VUkW8BCpQ==", + "license": "MIT", + "dependencies": { + "colorette": "^2.0.20", + "dayjs": "^1.11.10", + "http-status-emojis": "^2.2.0" + }, + "engines": { + "node": ">=14.18 || >=16.20" + } + }, + "node_modules/@tinyhttp/proxy-addr": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@tinyhttp/proxy-addr/-/proxy-addr-2.2.0.tgz", + "integrity": "sha512-WM/PPL9xNvrs7/8Om5nhKbke5FHrP3EfjOOR+wBnjgESfibqn0K7wdUTnzSLp1lBmemr88os1XvzwymSgaibyA==", + "license": "MIT", + "dependencies": { + "@tinyhttp/forwarded": "2.1.1", + "ipaddr.js": "^2.2.0" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/req": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@tinyhttp/req/-/req-2.2.4.tgz", + "integrity": "sha512-lQAZIAo0NOeghxFOZS57tQzxpHSPPLs9T68Krq2BncEBImKwqaDKUt7M9Y5Kb+rvC/GwIL3LeErhkg7f5iG4IQ==", + "license": "MIT", + "dependencies": { + "@tinyhttp/accepts": "2.2.3", + "@tinyhttp/type-is": "2.2.4", + "@tinyhttp/url": "2.1.1", + "header-range-parser": "^1.1.3" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/res": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@tinyhttp/res/-/res-2.2.4.tgz", + "integrity": "sha512-ETBRShnO19oJyIg2XQHQoofXPWeTXPAuwnIVYkU8WaftvXd/Vz4y5+WFQDHUzKlmdGOw5fAFnrEU7pIVMeFeVA==", + "license": "MIT", + "dependencies": { + "@tinyhttp/content-disposition": "2.2.2", + "@tinyhttp/cookie": "2.1.1", + "@tinyhttp/cookie-signature": "2.1.1", + "@tinyhttp/encode-url": "2.1.1", + "@tinyhttp/req": "2.2.4", + "@tinyhttp/send": "2.2.3", + "@tinyhttp/vary": "^0.1.3", + "es-escape-html": "^0.1.1", + "mime": "4.0.4" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/router": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@tinyhttp/router/-/router-2.2.3.tgz", + "integrity": "sha512-O0MQqWV3Vpg/uXsMYg19XsIgOhwjyhTYWh51Qng7bxqXixxx2PEvZWnFjP7c84K7kU/nUX41KpkEBTLnznk9/Q==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/send": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@tinyhttp/send/-/send-2.2.3.tgz", + "integrity": "sha512-o4cVHHGQ8WjVBS8UT0EE/2WnjoybrfXikHwsRoNlG1pfrC/Sd01u1N4Te8cOd/9aNGLr4mGxWb5qTm2RRtEi7g==", + "license": "MIT", + "dependencies": { + "@tinyhttp/content-type": "^0.1.4", + "@tinyhttp/etag": "2.1.2", + "mime": "4.0.4" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/type-is": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@tinyhttp/type-is/-/type-is-2.2.4.tgz", + "integrity": "sha512-7F328NheridwjIfefBB2j1PEcKKABpADgv7aCJaE8x8EON77ZFrAkI3Rir7pGjopV7V9MBmW88xUQigBEX2rmQ==", + "license": "MIT", + "dependencies": { + "@tinyhttp/content-type": "^0.1.4", + "mime": "4.0.4" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/url": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/url/-/url-2.1.1.tgz", + "integrity": "sha512-POJeq2GQ5jI7Zrdmj22JqOijB5/GeX+LEX7DUdml1hUnGbJOTWDx7zf2b5cCERj7RoXL67zTgyzVblBJC+NJWg==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@tinyhttp/vary": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@tinyhttp/vary/-/vary-0.1.3.tgz", + "integrity": "sha512-SoL83sQXAGiHN1jm2VwLUWQSQeDAAl1ywOm6T0b0Cg1CZhVsjoiZadmjhxF6FHCCY7OHHVaLnTgSMxTPIDLxMg==", + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -1087,17 +1892,20 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, "node_modules/@types/prop-types": { "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", - "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", - "dev": true + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==" }, "node_modules/@types/react": { "version": "18.3.18", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", - "dev": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -1112,6 +1920,14 @@ "@types/react": "^18.0.0" } }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "peerDependencies": { + "@types/react": "*" + } + }, "node_modules/@vitejs/plugin-react-swc": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.7.2.tgz", @@ -1311,6 +2127,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -1326,6 +2147,49 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-macros/node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1393,7 +2257,6 @@ "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" } @@ -1414,6 +2277,29 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1432,12 +2318,57 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "license": "MIT" + }, + "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/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": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1455,8 +2386,7 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/data-view-buffer": { "version": "1.0.2", @@ -1509,11 +2439,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, "dependencies": { "ms": "^2.1.3" }, @@ -1566,6 +2501,14 @@ "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/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -1578,6 +2521,30 @@ "node": ">=0.10.0" } }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/dot-prop": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-9.0.0.tgz", + "integrity": "sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^4.18.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -1592,6 +2559,14 @@ "node": ">= 0.4" } }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-abstract": { "version": "1.23.9", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", @@ -1675,6 +2650,15 @@ "node": ">= 0.4" } }, + "node_modules/es-escape-html": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/es-escape-html/-/es-escape-html-0.1.1.tgz", + "integrity": "sha512-yUx1o+8RsG7UlszmYPtks+dm6Lho2m8lgHMOsLJQsFI0R8XwUJwiMhM1M4E/S8QLeGyf6MkDV/pWgjQ0tdTSyQ==", + "license": "MIT", + "engines": { + "node": ">=12.x" + } + }, "node_modules/es-iterator-helpers": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", @@ -1799,7 +2783,6 @@ "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" }, @@ -2006,6 +2989,18 @@ "node": ">=0.10.0" } }, + "node_modules/eta": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/eta/-/eta-3.5.0.tgz", + "integrity": "sha512-e3x3FBvGzeCIHhF+zhK8FZA2vC5uFn6b4HJjegUbIWrDb4mJ7JjTGMJY9VGIbRVpmSwHopNiaJibhjIr+HfLug==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "url": "https://github.com/eta-dev/eta?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", @@ -2036,6 +3031,11 @@ "node": ">=16.0.0" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -2071,6 +3071,25 @@ "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "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", @@ -2080,6 +3099,46 @@ "is-callable": "^1.1.3" } }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/framer-motion": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.0.5.tgz", + "integrity": "sha512-OgfUHfL+u80uCf6VzkV7j3+H2W9zPMdV+40bug4ftB0C2+0FpfNca2rbH2Fouq2R7//bjw6tJhOwXsrsM4+LKw==", + "license": "MIT", + "dependencies": { + "motion-dom": "^12.0.0", + "motion-utils": "^12.0.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2098,7 +3157,6 @@ "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" } @@ -2317,7 +3375,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -2325,6 +3382,29 @@ "node": ">= 0.4" } }, + "node_modules/header-range-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/header-range-parser/-/header-range-parser-1.1.3.tgz", + "integrity": "sha512-B9zCFt3jH8g09LR1vHL4pcAn8yMEtlSlOUdQemzHMRKMImNIhhszdeosYFfNW0WXKQtXIlWB+O4owHJKvEJYaA==", + "license": "MIT", + "engines": { + "node": ">=12.22.0" + } + }, + "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/http-status-emojis": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/http-status-emojis/-/http-status-emojis-2.2.0.tgz", + "integrity": "sha512-ompKtgwpx8ff0hsbpIB7oE4ax1LXoHmftsHHStMELX56ivG3GhofTX8ZHWlUaFKfGjcGjw6G3rPk7dJRXMmbbg==", + "license": "MIT" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -2338,7 +3418,6 @@ "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" @@ -2359,6 +3438,15 @@ "node": ">=0.8.19" } }, + "node_modules/inflection": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-3.0.2.tgz", + "integrity": "sha512-+Bg3+kg+J6JUWn8J6bzFmOWkTQ6L/NHfDRSYU+EVvuKHDxUDHAXgqixHfVlzuBQaPOTac8hn43aPhMNk6rMe3g==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -2373,6 +3461,15 @@ "node": ">= 0.4" } }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -2390,6 +3487,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, "node_modules/is-async-function": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.0.tgz", @@ -2455,7 +3557,6 @@ "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, "dependencies": { "hasown": "^2.0.2" }, @@ -2763,24 +3864,91 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "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-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, "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-server": { + "version": "1.0.0-beta.3", + "resolved": "https://registry.npmjs.org/json-server/-/json-server-1.0.0-beta.3.tgz", + "integrity": "sha512-DwE69Ep5ccwIJZBUIWEENC30Yj8bwr4Ax9W9VoIWAYnB8Sj4ReptscO8/DRHv/nXwVlmb3Bk73Ls86+VZdYkkA==", + "license": "SEE LICENSE IN ./LICENSE", + "dependencies": { + "@tinyhttp/app": "^2.4.0", + "@tinyhttp/cors": "^2.0.1", + "@tinyhttp/logger": "^2.0.0", + "chalk": "^5.3.0", + "chokidar": "^4.0.1", + "dot-prop": "^9.0.0", + "eta": "^3.5.0", + "inflection": "^3.0.0", + "json5": "^2.2.3", + "lowdb": "^7.0.1", + "milliparsec": "^4.0.0", + "sirv": "^2.0.4", + "sort-on": "^6.1.0" + }, + "bin": { + "json-server": "lib/bin.js" + }, + "engines": { + "node": ">=18.3" + } + }, + "node_modules/json-server/node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "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==", + "license": "MIT", + "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", @@ -2818,6 +3986,11 @@ "node": ">= 0.8.0" } }, + "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==" + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -2850,6 +4023,21 @@ "loose-envify": "cli.js" } }, + "node_modules/lowdb": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-7.0.1.tgz", + "integrity": "sha512-neJAj8GwF0e8EpycYIDFqEPcx9Qz4GUho20jWFR7YiFeXzF1YMLdxB36PypcTSPMA+4+LvgyMacYhlr18Zlymw==", + "license": "MIT", + "dependencies": { + "steno": "^4.0.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -2859,6 +4047,49 @@ "node": ">= 0.4" } }, + "node_modules/milliparsec": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/milliparsec/-/milliparsec-4.0.0.tgz", + "integrity": "sha512-/wk9d4Z6/9ZvoEH/6BI4TrTCgmkpZPuSRN/6fI9aUHOfXdNTuj/VhLS7d+NqG26bi6L9YmGXutVYvWC8zQ0qtA==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/mime": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.4.tgz", + "integrity": "sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==", + "funding": [ + "https://github.com/sponsors/broofa" + ], + "license": "MIT", + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "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", @@ -2871,11 +4102,60 @@ "node": "*" } }, + "node_modules/motion": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/motion/-/motion-12.0.5.tgz", + "integrity": "sha512-AFCMJWX7xtd2V4PEuL+FnVscw++SaMZuFXrm3kjN1sIqrNDJdJrFbZ2B+pfq6CKlcTor/vVJcmrc2pJqF3EByw==", + "license": "MIT", + "dependencies": { + "framer-motion": "^12.0.5", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/motion-dom": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.0.0.tgz", + "integrity": "sha512-CvYd15OeIR6kHgMdonCc1ihsaUG4MYh/wrkz8gZ3hBX/uamyZCXN9S9qJoYF03GqfTt7thTV/dxnHYX4+55vDg==", + "license": "MIT", + "dependencies": { + "motion-utils": "^12.0.0" + } + }, + "node_modules/motion-utils": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.0.0.tgz", + "integrity": "sha512-MNFiBKbbqnmvOjkPyOKgHUp3Q6oiokLkI1bEwm5QA28cxMZrv0CbbBGDNmhF6DIXsi1pCQBSs0dX8xjeER1tmA==", + "license": "MIT" + }, + "node_modules/mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "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==", - "dev": true + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/nanoid": { "version": "3.3.8", @@ -2901,11 +4181,19 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "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" } @@ -3069,7 +4357,6 @@ "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" }, @@ -3077,6 +4364,23 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3098,14 +4402,20 @@ "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 + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/possible-typed-array-names": { "version": "1.0.0", @@ -3157,13 +4467,17 @@ "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.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -3199,8 +4513,35 @@ "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==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/readdirp": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.1.tgz", + "integrity": "sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==", + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", @@ -3224,6 +4565,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", @@ -3244,6 +4590,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regexparam": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/regexparam/-/regexparam-2.0.2.tgz", + "integrity": "sha512-A1PeDEYMrkLrfyOwv2jwihXbo9qxdGD3atBYQA9JJgreAx8/7rC6IUkWOw2NQlOxLp2wL0ifQbh1HuidDfYA6w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/resolve": { "version": "2.0.0-next.5", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", @@ -3265,7 +4620,6 @@ "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" } @@ -3516,6 +4870,43 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sort-on": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/sort-on/-/sort-on-6.1.0.tgz", + "integrity": "sha512-WTECP0nYNWO1n2g5bpsV0yZN9cBmZsF8ThHFbOqVN0HBFRoaQZLLEMvMmJlKHNPYQeVngeI5+jJzIfFqOIo1OA==", + "license": "MIT", + "dependencies": { + "dot-prop": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -3525,6 +4916,18 @@ "node": ">=0.10.0" } }, + "node_modules/steno": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/steno/-/steno-4.0.2.tgz", + "integrity": "sha512-yhPIQXjrlt1xv7dyPQg2P17URmXbuM5pdGkpiMB3RenprfiBlvK415Lctfe0eshk90oA7/tNq7WEiMK8RSP39A==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/string.prototype.matchall": { "version": "4.0.12", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", @@ -3630,6 +5033,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -3646,7 +5054,6 @@ "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" }, @@ -3654,6 +5061,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -3666,6 +5088,18 @@ "node": ">= 0.8.0" } }, + "node_modules/type-fest": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.33.0.tgz", + "integrity": "sha512-s6zVrxuyKbbAsSAD5ZPTB77q4YIdRctkTbJ2/Dqlinwz+8ooH2gd+YA7VA6Pa93KML9GockVvoxjZ2vHP+mu8g==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -3946,6 +5380,20 @@ "node": ">=0.10.0" } }, + "node_modules/yaml": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", + "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", + "dev": true, + "optional": true, + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/frontend/pronunciationAppFront/package.json b/frontend/pronunciationAppFront/package.json index 19d0c456f..5460d1390 100644 --- a/frontend/pronunciationAppFront/package.json +++ b/frontend/pronunciationAppFront/package.json @@ -5,11 +5,20 @@ "type": "module", "scripts": { "dev": "vite", + "start:api": "json-server db.json", "build": "vite build", "lint": "eslint .", "preview": "vite preview" }, "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.0", + "@fontsource/roboto": "^5.1.1", + "@mui/icons-material": "^6.4.0", + "@mui/material": "^6.4.0", + "axios": "^1.7.9", + "json-server": "^1.0.0-beta.3", + "motion": "^12.0.5", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/frontend/pronunciationAppFront/src/AnimatedCard.jsx b/frontend/pronunciationAppFront/src/AnimatedCard.jsx new file mode 100644 index 000000000..7b5bbc594 --- /dev/null +++ b/frontend/pronunciationAppFront/src/AnimatedCard.jsx @@ -0,0 +1,8 @@ +import { motion } from "motion/react"; + +// eslint-disable-next-line react/prop-types +export function AnimatedCard({ children }) { + return + {children} + ; +} diff --git a/frontend/pronunciationAppFront/src/App.css b/frontend/pronunciationAppFront/src/App.css index b9d355df2..d7882d451 100644 --- a/frontend/pronunciationAppFront/src/App.css +++ b/frontend/pronunciationAppFront/src/App.css @@ -5,38 +5,7 @@ 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; -} +ul { + list-style-type: none; +} \ No newline at end of file diff --git a/frontend/pronunciationAppFront/src/App.jsx b/frontend/pronunciationAppFront/src/App.jsx index f67355ae0..43980e0e7 100644 --- a/frontend/pronunciationAppFront/src/App.jsx +++ b/frontend/pronunciationAppFront/src/App.jsx @@ -1,35 +1,22 @@ -import { useState } from 'react' -import reactLogo from './assets/react.svg' -import viteLogo from '/vite.svg' import './App.css' +import Cards from "./Cards.jsx" +import Header from "./Hero.jsx"; +import User from "./User.jsx" 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 -

+

Welcome to PronunciationApp

+ + + +
+ + - ) + ); } export default App diff --git a/frontend/pronunciationAppFront/src/Cards.jsx b/frontend/pronunciationAppFront/src/Cards.jsx new file mode 100644 index 000000000..d95abbd1f --- /dev/null +++ b/frontend/pronunciationAppFront/src/Cards.jsx @@ -0,0 +1,112 @@ +import { useState, useEffect } from "react"; +import { + Box, + Card, + CardContent, + Typography, + Container, + Grid, + FormControl, + Select, + MenuItem, +} from "@mui/material"; +import { fetchWords } from "./data-api"; +import { filterByLevel } from "./utils"; +import { AnimatedCard } from "./AnimatedCard"; +import { WordSynonyms } from "./WordSynonyms"; + + +export default function WordList() { + const [words, setWords] = useState([]); + const [level, setLevel] = useState(1); + + useEffect(() => { + const getWords = async () => { + try { + const data = await fetchWords(); + setWords(data); + } catch (error) { + console.error("Failed to fetch words:", error); + } + }; + + getWords(); + }, []); + + function handleLevel(event) { + setLevel(event.target.value); + } + + if (!words || words.length === 0) return

Loading...

; + + return ( + + + + Word List + + + Select a level: + + + + + {filterByLevel(words, level).map((word) => ( + + + + + + {word.word} + + + Pronunciation: {word.pronunciation} + + + level: {word.level} + + {word.synonyms ? ( + + ) : ( + + No synonyms to show + + )} + + + + + ))} + + + + ); +} diff --git a/frontend/pronunciationAppFront/src/Hero.jsx b/frontend/pronunciationAppFront/src/Hero.jsx new file mode 100644 index 000000000..1d889fc1c --- /dev/null +++ b/frontend/pronunciationAppFront/src/Hero.jsx @@ -0,0 +1,33 @@ +export default function HeroSection(){ + + +return ( + <> +

Learn English once and for all

+
+

Practice Real-World Conversations

+ Practice Real-World Conversations +
    +
  • + Speak: + practice your pronunciation +
  • +
  • + Drill: + repeat until perfection! +
  • +
  • + Listen: + get used to real english sounds +
  • +
+
+ +); + + +} \ No newline at end of file diff --git a/frontend/pronunciationAppFront/src/User.jsx b/frontend/pronunciationAppFront/src/User.jsx new file mode 100644 index 000000000..fa6e1dafb --- /dev/null +++ b/frontend/pronunciationAppFront/src/User.jsx @@ -0,0 +1,75 @@ +import { useEffect, useState } from "react"; +import { fetchUserData } from "./data-api"; +import Card from "@mui/material/Card"; +import Box from "@mui/material/Box"; +import Avatar from "@mui/material/Avatar"; +import CardContent from "@mui/material/CardContent"; +import Typography from "@mui/material/Typography"; +import { stringAvatar } from "./utils"; + +export default function User() { + const [user, setUser] = useState(null); + const [error, setError] = useState(null); + + useEffect(function () { + fetchUserData() + .then(function (data) { + setUser(data); + }) + .catch(function (error) { + setError("Error obteniendo usuario"); + console.error(error); + }); + }, []); + + if (!user && !error) { + return

Loading...

; + } + + return ( + <> + {error !== null ? ( +

{error}

+ ) : ( + + + + + + {user.name} + + + {user.email} + + + Age: {user.age} + + + Member since: {new Date(user.joinDate).toLocaleDateString()} + + + + + )} + + ); +} diff --git a/frontend/pronunciationAppFront/src/WordSynonyms.jsx b/frontend/pronunciationAppFront/src/WordSynonyms.jsx new file mode 100644 index 000000000..4bb395e42 --- /dev/null +++ b/frontend/pronunciationAppFront/src/WordSynonyms.jsx @@ -0,0 +1,50 @@ +/* eslint-disable react/prop-types */ +import { Box, IconButton, Typography } from "@mui/material"; +import SkipPreviousIcon from "@mui/icons-material/SkipPrevious"; +import SkipNextIcon from "@mui/icons-material/SkipNext"; +import { useState } from "react"; + +export function WordSynonyms({ synonyms }) { + const [index, setIndex] = useState(0); + + function handlePrevious() { + if (index > 0) { + setIndex(index - 1); + } + } + + function handleNext() { + if (index < synonyms.length - 1) { + setIndex(index + 1); + } + } + return ( + + + Synonyms + + + 0 ? 'visible' : 'hidden' }} onClick={handlePrevious} aria-label="previous"> + + + + {synonyms[index]} + + + + + + + ); +} diff --git a/frontend/pronunciationAppFront/src/assets/hero-image.png b/frontend/pronunciationAppFront/src/assets/hero-image.png new file mode 100644 index 000000000..142e2916b Binary files /dev/null and b/frontend/pronunciationAppFront/src/assets/hero-image.png differ diff --git a/frontend/pronunciationAppFront/src/assets/react.svg b/frontend/pronunciationAppFront/src/assets/react.svg deleted file mode 100644 index 6c87de9bb..000000000 --- a/frontend/pronunciationAppFront/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/pronunciationAppFront/src/data-api.js b/frontend/pronunciationAppFront/src/data-api.js new file mode 100644 index 000000000..14c2dce55 --- /dev/null +++ b/frontend/pronunciationAppFront/src/data-api.js @@ -0,0 +1,25 @@ +// api.js +import axios from "axios"; + +// const BASE_URL = "https://1f196337-d694-4b64-9b0e-ef471d8cd805.mock.pstmn.io"; +const BASE_URL = "http://localhost:3000" + +export const fetchWords = async () => { + try { + const response = await axios.get(`${BASE_URL}/words`); + return response.data.words; + } catch (error) { + console.error("Error fetching words:", error); + throw error; + } +}; + +export const fetchUserData = async () => { + try { + const response = await axios.get(`${BASE_URL}/user`); + return response.data; + } catch (error) { + console.error("Error fetching user:", error); + throw error; + } +}; \ No newline at end of file diff --git a/frontend/pronunciationAppFront/src/index.css b/frontend/pronunciationAppFront/src/index.css index 6119ad9a8..fbfbcdf4f 100644 --- a/frontend/pronunciationAppFront/src/index.css +++ b/frontend/pronunciationAppFront/src/index.css @@ -5,7 +5,6 @@ color-scheme: light dark; color: rgba(255, 255, 255, 0.87); - background-color: #242424; font-synthesis: none; text-rendering: optimizeLegibility; @@ -13,56 +12,18 @@ -moz-osx-font-smoothing: grayscale; } -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; + background: radial-gradient(ellipse at center, #4b6cb7, #182848); + color: #F0F4F8; /* Soft light gray text */ + line-height: 1.6; + letter-spacing: 0.5px; } + + 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/frontend/pronunciationAppFront/src/main.jsx b/frontend/pronunciationAppFront/src/main.jsx index b9a1a6dea..4ec53d92f 100644 --- a/frontend/pronunciationAppFront/src/main.jsx +++ b/frontend/pronunciationAppFront/src/main.jsx @@ -2,6 +2,10 @@ import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import './index.css' import App from './App.jsx' +import "@fontsource/roboto/300.css"; +import "@fontsource/roboto/400.css"; +import "@fontsource/roboto/500.css"; +import "@fontsource/roboto/700.css"; createRoot(document.getElementById('root')).render( diff --git a/frontend/pronunciationAppFront/src/utils.js b/frontend/pronunciationAppFront/src/utils.js new file mode 100644 index 000000000..b7e038a78 --- /dev/null +++ b/frontend/pronunciationAppFront/src/utils.js @@ -0,0 +1,30 @@ +function stringToColor(string) { + let hash = 0; + let i; + + for (i = 0; i < string.length; i += 1) { + hash = string.charCodeAt(i) + ((hash << 5) - hash); + } + + let color = "#"; + + for (i = 0; i < 3; i += 1) { + const value = (hash >> (i * 8)) & 0xff; + color += `00${value.toString(16)}`.slice(-2); + } + + return color; +} + +export function stringAvatar(name) { + return { + sx: { + bgcolor: stringToColor(name), + }, + children: `${name.split(" ")[0][0]}${name.split(" ")[1][0]}`, + }; +} + +export function filterByLevel(words, level) { + return words.filter(w => Number(w.level) === level) +} \ No newline at end of file diff --git a/frontend/resources/CreateReactviteProject.md b/frontend/resources/create-React-vite/createReactviteProject.md similarity index 100% rename from frontend/resources/CreateReactviteProject.md rename to frontend/resources/create-React-vite/createReactviteProject.md diff --git a/frontend/resources/pronunciationAppFront-v0.0-project-structure.png b/frontend/resources/create-React-vite/pronunciationAppFront-v0.0-project-structure.png similarity index 100% rename from frontend/resources/pronunciationAppFront-v0.0-project-structure.png rename to frontend/resources/create-React-vite/pronunciationAppFront-v0.0-project-structure.png diff --git a/frontend/resources/pronunciationAppFront-v0.0-run-dev.png b/frontend/resources/create-React-vite/pronunciationAppFront-v0.0-run-dev.png similarity index 100% rename from frontend/resources/pronunciationAppFront-v0.0-run-dev.png rename to frontend/resources/create-React-vite/pronunciationAppFront-v0.0-run-dev.png diff --git a/frontend/resources/create-React-vite/pronunciationAppFront-v0.0-web-1.png b/frontend/resources/create-React-vite/pronunciationAppFront-v0.0-web-1.png new file mode 100644 index 000000000..653a20fa5 Binary files /dev/null and b/frontend/resources/create-React-vite/pronunciationAppFront-v0.0-web-1.png differ diff --git a/frontend/resources/pronunciationAppFront-v0.0-web.png b/frontend/resources/create-React-vite/pronunciationAppFront-v0.0-web.png similarity index 100% rename from frontend/resources/pronunciationAppFront-v0.0-web.png rename to frontend/resources/create-React-vite/pronunciationAppFront-v0.0-web.png diff --git a/frontend/resources/css/css-cheesheat-1.png b/frontend/resources/css/css-cheesheat-1.png new file mode 100644 index 000000000..92aaa4546 Binary files /dev/null and b/frontend/resources/css/css-cheesheat-1.png differ diff --git a/frontend/resources/css/css-cheesheat-2.png b/frontend/resources/css/css-cheesheat-2.png new file mode 100644 index 000000000..e7562b5b3 Binary files /dev/null and b/frontend/resources/css/css-cheesheat-2.png differ diff --git a/frontend/resources/css/css-cheesheat-3.png b/frontend/resources/css/css-cheesheat-3.png new file mode 100644 index 000000000..8026011f9 Binary files /dev/null and b/frontend/resources/css/css-cheesheat-3.png differ diff --git a/frontend/resources/data-JSON/words.json b/frontend/resources/data-JSON/words.json new file mode 100644 index 000000000..863968d84 --- /dev/null +++ b/frontend/resources/data-JSON/words.json @@ -0,0 +1,54 @@ +{ + "words": [ + { + "id": "8b9248a4e0b64bbccf82e7723a3734279bf9bbc4", + "word": "benevolent", + "pronunciation": "/bɪˈnɛvələnt/" + }, + { + "id": "3a7bd3e2a07e8c7e9b6e0d2c1f4a5b8d9c0e3f2", + "word": "serendipity", + "pronunciation": "/ˌserənˈdɪpɪti/" + }, + { + "id": "5c9d7f3e1a2b4d6e8g0h9i7j6k5l4m3n2o1p", + "word": "ephemeral", + "pronunciation": "/ɪˈfɛmərəl/" + }, + { + "id": "2f4e6d8c0b2a4d6e8f0a2c4e6g8i0k2m4o6q", + "word": "ubiquitous", + "pronunciation": "/juːˈbɪkwɪtəs/" + }, + { + "id": "7h9j1l3n5p7r9t1v3x5z7b9d1f3h5j7l9n", + "word": "mellifluous", + "pronunciation": "/məˈlɪfluəs/" + }, + { + "id": "1a3c5e7g9i1k3m5o7q9s1u3w5y7a9c1e3", + "word": "eloquent", + "pronunciation": "/ˈɛləkwənt/" + }, + { + "id": "4b6d8f0h2j4l6n8p0r2t4v6x8z0b2d4f6", + "word": "quintessential", + "pronunciation": "/ˌkwɪntɪˈsenʃəl/" + }, + { + "id": "9k1m3o5q7s9u1w3y5a7c9e1g3i5k7m9o", + "word": "ethereal", + "pronunciation": "/ɪˈθɪəriəl/" + }, + { + "id": "2p4r6t8v0x2z4b6d8f0h2j4l6n8p0r2t", + "word": "surreptitious", + "pronunciation": "/ˌsʌrəpˈtɪʃəs/" + }, + { + "id": "5u7w9y1a3c5e7g9i1k3m5o7q9s1u3w5", + "word": "labyrinthine", + "pronunciation": "/ˌlæbəˈrɪnθaɪn/" + } + ] +} diff --git a/frontend/resources/material-ui/CSS-Box-Model.png b/frontend/resources/material-ui/CSS-Box-Model.png new file mode 100644 index 000000000..d55e46211 Binary files /dev/null and b/frontend/resources/material-ui/CSS-Box-Model.png differ diff --git a/frontend/resources/material-ui/boxing-containers.md b/frontend/resources/material-ui/boxing-containers.md new file mode 100644 index 000000000..39ae6f92e --- /dev/null +++ b/frontend/resources/material-ui/boxing-containers.md @@ -0,0 +1,159 @@ +# CSS basics: box and containers + +> `CSS (Cascading Style Sheets)` is a fundamental technology for web design, and understanding the `box model and containers` is key for layout and styling. + +## CSS Box Model + +The CSS box model is the foundation of layout in CSS. It treats every HTML element as a box with four components[1][4]: + +1. `Content`: The actual text, images, or other media within the element. +2. `Padding`: Transparent space around the content. +3. `Border`: A line surrounding the padding and content. +4. `Margin`: Transparent space outside the border. + +These components work together to determine the total size and spacing of elements on a webpage. For example: + +```css +div { + width: 350px; + height: 150px; + padding: 25px; + border: 5px solid black; + margin: 10px; +} +``` + +In this case, the total width of the element would be 410px (350px content + 50px padding + 10px border) and the height would be 210px (150px content + 50px padding + 10px border)[4]. + +## CSS Containers + +Containers in CSS are elements used to group and structure content within a webpage[9]. They help control the placement and styling of elements, creating organized and responsive layouts. Common container elements include: + +- `
`: A generic container for flow content. +- `
`: A thematic grouping of content. +- `
`: A self-contained composition. + +Containers are often styled using CSS classes: + +```css +.container { + max-width: 1200px; + margin: 0 auto; + padding: 20px; +} +``` + +This creates a centered container with a maximum width and some padding[9]. + +## Advanced Container Concepts + +1. Flexbox: A one-dimensional layout model for flexible container elements. +2. Grid: A two-dimensional layout system for more complex designs. +3. Container Queries: A newer feature allowing styles to be applied based on the container's size rather than the viewport[6]. + +Understanding these concepts allows developers to create responsive, well-structured layouts that adapt to various screen sizes and devices, enhancing the overall user experience of websites. + +Citations: +[1] https://www.w3schools.com/css/css_boxmodel.asp +[2] https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_box_model +[3] https://www.smashingmagazine.com/2021/05/complete-guide-css-container-queries/ +[4] https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Box_model +[5] https://www.youtube.com/watch?v=nSst4-WbEZk +[6] https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_containment/Container_queries +[7] https://www.programiz.com/css/box-model +[8] https://en.wikipedia.org/wiki/Internet_Explorer_box_model_bug +[9] https://www.javatpoint.com/css-container +[10] https://www.simplilearn.com/tutorials/css-tutorial/css-box-model +[11] https://www.geeksforgeeks.org/css-box-model/ + +## Example + +```js +import React, { useState, useEffect } from 'react'; +import axios from 'axios'; +import { + Box, + Card, + CardContent, + Typography, + Container, + Grid +} from '@mui/material'; + + +export default function WordList() { + + // business logic to fetch data: words + + return ( + + + + Word List + + + {words.map((word) => ( + + + + + {word.word} + + + Pronunciation: {word.pronunciation} + + + + + ))} + + + + ); +} +``` + +This table provides a balanced view of the advantages and potential drawbacks of using these Material-UI components in React applications.: explaining the pros and cons of using `Container`, `Box`, and `Grid` components in React with Material-UI: + +| Pros | Cons | +| --------------------------------------- | ------------------------------------------------------ | +| Responsive design out of the box | Learning curve for new developers | +| Consistent spacing and layout | Potential over-reliance on MUI components | +| Improved code organization | Extra abstraction layer | +| Better performance optimization | Increased bundle size | +| Adherence to Material Design principles | Less flexibility for highly custom designs | +| Enhanced accessibility | Potential performance impact with nested grids | +| Scalable structure | Possible verbosity in component structure | +| Cross-browser compatibility | Dependency on external library (MUI) | +| Easy theming and customization | Version compatibility issues during updates | +| Reduced development time | Potential for unnecessary complexity in simple layouts | + +### Box vs Container Comparison + +| Aspect | Box | Container | +| --------------------- | ------------------------------------- | ------------------------------------------ | +| Definition | Individual element rendering model | Structural element for grouping content | +| Primary Purpose | Define element dimensions and spacing | Organize and layout multiple elements | +| CSS Properties | `margin`, `padding`, `border` | `max-width`, `display`, `flex`, `grid` | +| Scope | Single HTML element | Multiple elements or child components | +| Responsiveness | Element-specific sizing | Layout-wide adaptability | +| Nesting Capability | Limited | High (can contain multiple boxes/elements) | +| Layout Behavior | Static individual element | Dynamic content arrangement | +| Typical HTML Elements | Every HTML tag | `
`, `
`, `
` | +| Flexibility | Fixed to element properties | Adaptable to different layout strategies | +| Performance Impact | Minimal | Can affect overall page rendering | + +## Key Takeaways + +- Boxes are about individual element rendering +- Containers are about structural organization + +### Links + +- [Container Component](https://mui.com/material-ui/react-container/) + +- [Box Component](https://mui.com/material-ui/react-box/) + +- [Container Component](https://mui.com/material-ui/react-container/) + +- [Grid version 2](https://mui.com/material-ui/react-grid2/) diff --git a/frontend/resources/material-ui/material-ui-install.md b/frontend/resources/material-ui/material-ui-install.md new file mode 100644 index 000000000..4d588e785 --- /dev/null +++ b/frontend/resources/material-ui/material-ui-install.md @@ -0,0 +1,61 @@ +# Material React UI + +To install Material-UI (now known as MUI) for React using npm, follow these steps: + +1. Open your terminal and navigate to your React project directory. + +2. Run the following command to install MUI and its peer dependencies: + +```bash +npm install @mui/material @emotion/react @emotion/styled +``` + +3. If you want to use icons, install the icons package: + +```bash +npm install @mui/icons-material +``` + +4. For optimal font loading, install Roboto font: + +```bash +npm install @fontsource/roboto +``` + +After installation, you can import and use MUI components in your React application. Here's a basic example of how to use a MUI component: + +```jsx +import React from 'react'; +import Button from '@mui/material/Button'; + +function App() { + return ( + + ); +} + +export default App; +``` + +Remember to import the Roboto font in your main `index.js` or `App.js` file: + +```jsx +import '@fontsource/roboto/300.css'; +import '@fontsource/roboto/400.css'; +import '@fontsource/roboto/500.css'; +import '@fontsource/roboto/700.css'; +``` + +This setup will allow you to use MUI components and styles in your React application[1][2][3]. + +Citations: +[1] https://v3.mui.com/getting-started/installation/ +[2] https://v5-0-6.mui.com/getting-started/installation/ +[3] https://mui.com/material-ui/getting-started/installation/ +[4] https://v4.mui.com/getting-started/installation/ +[5] https://www.educative.io/answers/how-to-install-material-ui-v5 +[6] https://www.npmjs.com/package/@mui/material +[7] https://v4.mui.com/es/getting-started/installation/ +[8] https://www.npmjs.com/package/@material-ui/core diff --git a/frontend/resources/pronunciationAppFront-v0.1-flow-data-1.png b/frontend/resources/pronunciationAppFront-v0.1-flow-data-1.png new file mode 100644 index 000000000..34e15a47d Binary files /dev/null and b/frontend/resources/pronunciationAppFront-v0.1-flow-data-1.png differ diff --git a/frontend/resources/pronunciationAppFront-v0.1-flow-data-2.png b/frontend/resources/pronunciationAppFront-v0.1-flow-data-2.png new file mode 100644 index 000000000..bbeee187a Binary files /dev/null and b/frontend/resources/pronunciationAppFront-v0.1-flow-data-2.png differ diff --git a/frontend/resources/pronunciationAppFront-v0.1-flow-data-3.png b/frontend/resources/pronunciationAppFront-v0.1-flow-data-3.png new file mode 100644 index 000000000..b39d8202e Binary files /dev/null and b/frontend/resources/pronunciationAppFront-v0.1-flow-data-3.png differ diff --git a/frontend/resources/pronunciationAppFront-v0.1-flow-data-4.png b/frontend/resources/pronunciationAppFront-v0.1-flow-data-4.png new file mode 100644 index 000000000..762e1c320 Binary files /dev/null and b/frontend/resources/pronunciationAppFront-v0.1-flow-data-4.png differ diff --git a/frontend/resources/pronunciationAppFront-v0.1-render-1-cards.png b/frontend/resources/pronunciationAppFront-v0.1-render-1-cards.png new file mode 100644 index 000000000..a9395cef5 Binary files /dev/null and b/frontend/resources/pronunciationAppFront-v0.1-render-1-cards.png differ diff --git a/frontend/resources/pronunciationAppFront-v0.1-render-2-cards.png b/frontend/resources/pronunciationAppFront-v0.1-render-2-cards.png new file mode 100644 index 000000000..4a0bf0ac0 Binary files /dev/null and b/frontend/resources/pronunciationAppFront-v0.1-render-2-cards.png differ diff --git a/frontend/resources/pronunciationAppFront-v0.1-render-3-cards.png b/frontend/resources/pronunciationAppFront-v0.1-render-3-cards.png new file mode 100644 index 000000000..15fe15340 Binary files /dev/null and b/frontend/resources/pronunciationAppFront-v0.1-render-3-cards.png differ diff --git a/frontend/resources/pronunciationAppFront-v0.1-render-4-data.png b/frontend/resources/pronunciationAppFront-v0.1-render-4-data.png new file mode 100644 index 000000000..729ae1ed4 Binary files /dev/null and b/frontend/resources/pronunciationAppFront-v0.1-render-4-data.png differ diff --git a/frontend/resources/pronunciationAppFront-v0.1-render-5-data-inline.png b/frontend/resources/pronunciationAppFront-v0.1-render-5-data-inline.png new file mode 100644 index 000000000..69f04de7f Binary files /dev/null and b/frontend/resources/pronunciationAppFront-v0.1-render-5-data-inline.png differ diff --git a/frontend/resources/pronunciatonApp-v0.1.md b/frontend/resources/pronunciatonApp-v0.1.md new file mode 100644 index 000000000..47dbc951a --- /dev/null +++ b/frontend/resources/pronunciatonApp-v0.1.md @@ -0,0 +1,283 @@ +# PronunciationApp Frontend v0.1 + +## Reference Lab + +- [Lab#RE06-1: healthyFood Restaurant – albertprofe wiki](https://albertprofe.dev/reactjs/rjslab6-1.html): with AWS workflow CD/CI deploy +- [Lab#RE01-1: API Rest Axios – albertprofe wiki](https://albertprofe.dev/reactjs/rjslab1.html): with Axios + +## Postman Mock Data Server + +> A **Postman mock server is a simulated API endpoint that mimics the behavior of a real server** without the need for a fully implemented backend. It allows developers to test and prototype APIs by returning predefined responses to requests. + +```js +const BASE_URL = 'https://a387bb02-2aa0-41a6-b8f7-9cc5247b9d5f.mock.pstmn.io'; +``` + +`Mock servers` are created from Postman collections, which contain saved examples of requests and responses. When a request is sent to the mock server, it matches the incoming request to the closest saved example and returns the corresponding response. + +- [Configure and use a Postman mock server | Postman Docs](https://learning.postman.com/docs/designing-and-developing-your-api/mocking-data/setting-up-mock/) + +These servers can be public or private, with private servers requiring an API key for access. They're useful for API development, testing, and simulating various scenarios without relying on a live backend. + +`Mock servers` can also simulate network delays and generate dynamic responses using variables and templates, enhancing the realism of API testing. They're particularly valuable in the early stages of API development, allowing frontend and backend teams to work concurrently without waiting for a fully functional API. + +### Fake data words + +```json +{ "words" : [ { "id": "8b9248a4e0b64bbccf82e7723a3734279bf9bbc4", "word": "benevolent", "pronunciation": "/bɪˈnɛvələnt/" }, { "id": "3a7bd3e2a07e8c7e9b6e0d2c1f4a5b8d9c0e3f2", "word": "serendipity", "pronunciation": "/ˌserənˈdɪpɪti/" }, { "id": "5c9d7f3e1a2b4d6e8g0h9i7j6k5l4m3n2o1p", "word": "ephemeral", "pronunciation": "/ɪˈfɛmərəl/" }, { "id": "2f4e6d8c0b2a4d6e8f0a2c4e6g8i0k2m4o6q", "word": "ubiquitous", "pronunciation": "/juːˈbɪkwɪtəs/" }, { "id": "7h9j1l3n5p7r9t1v3x5z7b9d1f3h5j7l9n", "word": "mellifluous", "pronunciation": "/məˈlɪfluəs/" }, { "id": "1a3c5e7g9i1k3m5o7q9s1u3w5y7a9c1e3", "word": "eloquent", "pronunciation": "/ˈɛləkwənt/" }, { "id": "4b6d8f0h2j4l6n8p0r2t4v6x8z0b2d4f6", "word": "quintessential", "pronunciation": "/ˌkwɪntɪˈsenʃəl/" }, { "id": "9k1m3o5q7s9u1w3y5a7c9e1g3i5k7m9o", "word": "ethereal", "pronunciation": "/ɪˈθɪəriəl/" }, { "id": "2p4r6t8v0x2z4b6d8f0h2j4l6n8p0r2t", "word": "surreptitious", "pronunciation": "/ˌsʌrəpˈtɪʃəs/" }, { "id": "5u7w9y1a3c5e7g9i1k3m5o7q9s1u3w5", "word": "labyrinthine", "pronunciation": "/ˌlæbəˈrɪnθaɪn/" } ]} +``` + +## Project + +### Tech stack + +Draft-sandbox coupled code using: + +- `Material UI`, + +- `Postam` Mock Data Server API endpoint, + +- `Axios` for data fetching, + +- `Hooks` for state management + +- and rendering the words + + - from the provided API endpoint using `map` js function + +This code combines the Material UI components with Axios for data fetching. It uses the `useState` and `useEffect` hooks to manage the state and side effects. The `fetchWords` function makes a GET request to the provided API endpoint to retrieve the word data. The component then renders the fetched words in a responsive grid of Material UI cards. + +Remember to install the necessary dependencies: + +```bash +npm install @mui/material @emotion/react @emotion/styled axios +``` + +This setup provides a clean, modern look with Material UI components and efficiently fetches data from the API using Axios. + +### Flow + +> This flow simulate API interactions without a real backend. + +The mock server returns predefined data, which Axios fetches in the useEffect hook. The fetched data is then stored in state using useState. Finally, the component maps over the state data, rendering each word as a card in the UI, creating a seamless development experience before the actual API is ready. + +The flow from a Postman mock server to rendering in React involves these steps: + +1. **Postman mock server**: Simulates an API endpoint, providing predefined responses to requests. + +2. **Axios**: Makes an HTTP GET request to the mock server URL. + +3. **useEffect**: Triggers the Axios request when the component mounts. + +4. **useState**: Stores the fetched data in the component's state. + +5. **words.map()**: Iterates over the array of words stored in state. + +6. **Render**: Displays each word as a Material UI Card component in the UI. + +### Code sandbox + +Coupled `fetchWords` and `WordList()` + +```js +import React, { useState, useEffect } from 'react'; +import axios from 'axios'; +import { + Box, + Card, + CardContent, + Typography, + Container, + Grid +} from '@mui/material'; + +const BASE_URL = 'https://a387bb02-2aa0-41a6-b8f7-9cc5247b9d5f.mock.pstmn.io'; + +const fetchWords = async () => { + try { + const response = await axios.get(`${BASE_URL}/words`); + return response.data.words; + } catch (error) { + console.error('Error fetching words:', error); + throw error; + } +}; + +export default function WordList() { + const [words, setWords] = useState([]); + + useEffect(() => { + const getWords = async () => { + try { + const data = await fetchWords(); + setWords(data); + } catch (error) { + console.error('Failed to fetch words:', error); + } + }; + + getWords(); + }, []); + + return ( + + + + Word List + + + {words.map((word) => ( + + + + + {word.word} + + + Pronunciation: {word.pronunciation} + + + + + ))} + + + + ); +} +``` + +### Code sandbox without MUI + +`./pronunciationAppFront/src/Cards.jsx` + +```jsx +import { useState, useEffect } from "react"; +import { fetchWords } from "./data-api"; + +export default function WordList() { + const [words, setWords] = useState([]); + + useEffect(() => { + const getWords = async () => { + try { + const data = await fetchWords(); + setWords(data); + } catch (error) { + console.error("Failed to fetch words:", error); + } + }; + + getWords(); + }, []); + + return ( + <> +

Words List

+ {words.map((word) => ( +

+ {word.id}: {word.word} {word.pronunciation} +

+ ))} + + ); +} +``` + +`./pronunciationAppFront/src/data-api.js` + +```js +// api.js +import axios from "axios"; + +const BASE_URL = "https://a387bb02-2aa0-41a6-b8f7-9cc5247b9d5f.mock.pstmn.io"; + +export const fetchWords = async () => { + try { + const response = await axios.get(`${BASE_URL}/words`); + return response.data.words; + } catch (error) { + console.error("Error fetching words:", error); + throw error; + } +}; +``` + +### Code typescript + +`./pronunciationAppFront/src/Cards.jsx` + +```typescript +import React, { useState, useEffect } from 'react'; +import axios from 'axios'; +import { + Box, + Card, + CardContent, + Typography, + Container, + Grid +} from '@mui/material'; + +const BASE_URL = 'https://a387bb02-2aa0-41a6-b8f7-9cc5247b9d5f.mock.pstmn.io'; + +interface Word { + id: string; + word: string; + pronunciation: string; +} + +const fetchWords = async (): Promise => { + try { + const response = +await axios.get<{ words: Word[] }>(`${BASE_URL}/words`); + return response.data.words; + } catch (error) { + console.error('Error fetching words:', error); + throw error; + } +}; + +export default function WordList(): JSX.Element { + const [words, setWords] = useState([]); + + useEffect(() => { + const getWords = async () => { + try { + const data = await fetchWords(); + setWords(data); + } catch (error) { + console.error('Failed to fetch words:', error); + } + }; + + getWords(); + }, []); + + return ( + + + + Word List + + + {words.map((word) => ( + + + + + {word.word} + + + Pronunciation: {word.pronunciation} + + + + + ))} + + + + ); +} +```