Fix poster selection and cart
This commit is contained in:
221
package-lock.json
generated
221
package-lock.json
generated
@@ -8,13 +8,13 @@
|
|||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.13.3",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.13.0",
|
"@emotion/styled": "^11.14.0",
|
||||||
"@material-ui/core": "^4.12.4",
|
"@material-ui/core": "^4.12.4",
|
||||||
"@material-ui/icons": "^4.11.3",
|
"@material-ui/icons": "^4.11.3",
|
||||||
"@mui/icons-material": "^6.0.1",
|
"@mui/icons-material": "^6.0.1",
|
||||||
"@mui/lab": "^6.0.0-beta.9",
|
"@mui/lab": "^6.0.0-beta.9",
|
||||||
"@mui/material": "^6.0.1",
|
"@mui/material": "^6.2.0",
|
||||||
"@testing-library/jest-dom": "^5.17.0",
|
"@testing-library/jest-dom": "^5.17.0",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"redux": "^5.0.1",
|
"redux": "^5.0.1",
|
||||||
"redux-persist": "^6.0.0",
|
"redux-persist": "^6.0.0",
|
||||||
|
"reselect": "^5.1.1",
|
||||||
"sass": "^1.80.3",
|
"sass": "^1.80.3",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
@@ -2127,10 +2128,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@babel/runtime": {
|
"node_modules/@babel/runtime": {
|
||||||
"version": "7.25.6",
|
"version": "7.26.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz",
|
||||||
"integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==",
|
"integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"regenerator-runtime": "^0.14.0"
|
"regenerator-runtime": "^0.14.0"
|
||||||
},
|
},
|
||||||
@@ -2477,16 +2477,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@emotion/babel-plugin": {
|
"node_modules/@emotion/babel-plugin": {
|
||||||
"version": "11.12.0",
|
"version": "11.13.5",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz",
|
||||||
"integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==",
|
"integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-module-imports": "^7.16.7",
|
"@babel/helper-module-imports": "^7.16.7",
|
||||||
"@babel/runtime": "^7.18.3",
|
"@babel/runtime": "^7.18.3",
|
||||||
"@emotion/hash": "^0.9.2",
|
"@emotion/hash": "^0.9.2",
|
||||||
"@emotion/memoize": "^0.9.0",
|
"@emotion/memoize": "^0.9.0",
|
||||||
"@emotion/serialize": "^1.2.0",
|
"@emotion/serialize": "^1.3.3",
|
||||||
"babel-plugin-macros": "^3.1.0",
|
"babel-plugin-macros": "^3.1.0",
|
||||||
"convert-source-map": "^1.5.0",
|
"convert-source-map": "^1.5.0",
|
||||||
"escape-string-regexp": "^4.0.0",
|
"escape-string-regexp": "^4.0.0",
|
||||||
@@ -2498,20 +2497,17 @@
|
|||||||
"node_modules/@emotion/babel-plugin/node_modules/@emotion/hash": {
|
"node_modules/@emotion/babel-plugin/node_modules/@emotion/hash": {
|
||||||
"version": "0.9.2",
|
"version": "0.9.2",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz",
|
||||||
"integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==",
|
"integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g=="
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/@emotion/babel-plugin/node_modules/convert-source-map": {
|
"node_modules/@emotion/babel-plugin/node_modules/convert-source-map": {
|
||||||
"version": "1.9.0",
|
"version": "1.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
|
||||||
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
|
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": {
|
"node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||||
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
},
|
},
|
||||||
@@ -2523,20 +2519,18 @@
|
|||||||
"version": "0.5.7",
|
"version": "0.5.7",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||||
"integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
|
"integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
|
||||||
"license": "BSD-3-Clause",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@emotion/cache": {
|
"node_modules/@emotion/cache": {
|
||||||
"version": "11.13.1",
|
"version": "11.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz",
|
||||||
"integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==",
|
"integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/memoize": "^0.9.0",
|
"@emotion/memoize": "^0.9.0",
|
||||||
"@emotion/sheet": "^1.4.0",
|
"@emotion/sheet": "^1.4.0",
|
||||||
"@emotion/utils": "^1.4.0",
|
"@emotion/utils": "^1.4.2",
|
||||||
"@emotion/weak-memoize": "^0.4.0",
|
"@emotion/weak-memoize": "^0.4.0",
|
||||||
"stylis": "4.2.0"
|
"stylis": "4.2.0"
|
||||||
}
|
}
|
||||||
@@ -2563,17 +2557,16 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@emotion/react": {
|
"node_modules/@emotion/react": {
|
||||||
"version": "11.13.3",
|
"version": "11.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.3.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
|
||||||
"integrity": "sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==",
|
"integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.18.3",
|
"@babel/runtime": "^7.18.3",
|
||||||
"@emotion/babel-plugin": "^11.12.0",
|
"@emotion/babel-plugin": "^11.13.5",
|
||||||
"@emotion/cache": "^11.13.0",
|
"@emotion/cache": "^11.14.0",
|
||||||
"@emotion/serialize": "^1.3.1",
|
"@emotion/serialize": "^1.3.3",
|
||||||
"@emotion/use-insertion-effect-with-fallbacks": "^1.1.0",
|
"@emotion/use-insertion-effect-with-fallbacks": "^1.2.0",
|
||||||
"@emotion/utils": "^1.4.0",
|
"@emotion/utils": "^1.4.2",
|
||||||
"@emotion/weak-memoize": "^0.4.0",
|
"@emotion/weak-memoize": "^0.4.0",
|
||||||
"hoist-non-react-statics": "^3.3.1"
|
"hoist-non-react-statics": "^3.3.1"
|
||||||
},
|
},
|
||||||
@@ -2587,23 +2580,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@emotion/serialize": {
|
"node_modules/@emotion/serialize": {
|
||||||
"version": "1.3.1",
|
"version": "1.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz",
|
||||||
"integrity": "sha512-dEPNKzBPU+vFPGa+z3axPRn8XVDetYORmDC0wAiej+TNcOZE70ZMJa0X7JdeoM6q/nWTMZeLpN/fTnD9o8MQBA==",
|
"integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/hash": "^0.9.2",
|
"@emotion/hash": "^0.9.2",
|
||||||
"@emotion/memoize": "^0.9.0",
|
"@emotion/memoize": "^0.9.0",
|
||||||
"@emotion/unitless": "^0.10.0",
|
"@emotion/unitless": "^0.10.0",
|
||||||
"@emotion/utils": "^1.4.0",
|
"@emotion/utils": "^1.4.2",
|
||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@emotion/serialize/node_modules/@emotion/hash": {
|
"node_modules/@emotion/serialize/node_modules/@emotion/hash": {
|
||||||
"version": "0.9.2",
|
"version": "0.9.2",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz",
|
||||||
"integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==",
|
"integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g=="
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/@emotion/sheet": {
|
"node_modules/@emotion/sheet": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
@@ -2612,17 +2603,16 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@emotion/styled": {
|
"node_modules/@emotion/styled": {
|
||||||
"version": "11.13.0",
|
"version": "11.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz",
|
||||||
"integrity": "sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==",
|
"integrity": "sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.18.3",
|
"@babel/runtime": "^7.18.3",
|
||||||
"@emotion/babel-plugin": "^11.12.0",
|
"@emotion/babel-plugin": "^11.13.5",
|
||||||
"@emotion/is-prop-valid": "^1.3.0",
|
"@emotion/is-prop-valid": "^1.3.0",
|
||||||
"@emotion/serialize": "^1.3.0",
|
"@emotion/serialize": "^1.3.3",
|
||||||
"@emotion/use-insertion-effect-with-fallbacks": "^1.1.0",
|
"@emotion/use-insertion-effect-with-fallbacks": "^1.2.0",
|
||||||
"@emotion/utils": "^1.4.0"
|
"@emotion/utils": "^1.4.2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@emotion/react": "^11.0.0-rc.0",
|
"@emotion/react": "^11.0.0-rc.0",
|
||||||
@@ -2637,23 +2627,20 @@
|
|||||||
"node_modules/@emotion/unitless": {
|
"node_modules/@emotion/unitless": {
|
||||||
"version": "0.10.0",
|
"version": "0.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz",
|
||||||
"integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==",
|
"integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg=="
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/@emotion/use-insertion-effect-with-fallbacks": {
|
"node_modules/@emotion/use-insertion-effect-with-fallbacks": {
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz",
|
||||||
"integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==",
|
"integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==",
|
||||||
"license": "MIT",
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": ">=16.8.0"
|
"react": ">=16.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@emotion/utils": {
|
"node_modules/@emotion/utils": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz",
|
||||||
"integrity": "sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==",
|
"integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA=="
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/@emotion/weak-memoize": {
|
"node_modules/@emotion/weak-memoize": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
@@ -3933,10 +3920,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@mui/core-downloads-tracker": {
|
"node_modules/@mui/core-downloads-tracker": {
|
||||||
"version": "6.0.1",
|
"version": "6.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.2.0.tgz",
|
||||||
"integrity": "sha512-TmKkCTwgtwvlFTF1tZzG4lYbi7v6NGweEJwFBZoIWZrkF1OLa0xu4umifmIyd+bVIScsEj//E2AD6bOJbPMOOQ==",
|
"integrity": "sha512-Nn5PSkUqbDrvezpiiiYZiAbX4SFEiy3CbikUL6pWOXEUsq+L1j50OOyyUIHpaX2Hr+5V5UxTh+fPeC4nsGNhdw==",
|
||||||
"license": "MIT",
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
"url": "https://opencollective.com/mui-org"
|
"url": "https://opencollective.com/mui-org"
|
||||||
@@ -4023,22 +4009,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/material": {
|
"node_modules/@mui/material": {
|
||||||
"version": "6.0.1",
|
"version": "6.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/material/-/material-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/material/-/material-6.2.0.tgz",
|
||||||
"integrity": "sha512-gOJS0RKYs9lRACaTluXPNopxFpIBhWVmhf09lHpqpPlR6bujXhuiTE2Q8puensdz3Qm2JGzl1VjccYHieV1g8A==",
|
"integrity": "sha512-7FXXUPIyYzP02a7GvqwJ7ocmdP+FkvLvmy/uxG1TDmTlsr8nEClQp75uxiVznJqAY/jJy4d+Rj/fNWNxwidrYQ==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.25.0",
|
"@babel/runtime": "^7.26.0",
|
||||||
"@mui/core-downloads-tracker": "^6.0.1",
|
"@mui/core-downloads-tracker": "^6.2.0",
|
||||||
"@mui/system": "^6.0.1",
|
"@mui/system": "^6.2.0",
|
||||||
"@mui/types": "^7.2.16",
|
"@mui/types": "^7.2.19",
|
||||||
"@mui/utils": "^6.0.1",
|
"@mui/utils": "^6.2.0",
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"@types/react-transition-group": "^4.4.11",
|
"@types/react-transition-group": "^4.4.11",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"csstype": "^3.1.3",
|
"csstype": "^3.1.3",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"react-is": "^18.3.1",
|
"react-is": "^19.0.0",
|
||||||
"react-transition-group": "^4.4.5"
|
"react-transition-group": "^4.4.5"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -4051,7 +4036,7 @@
|
|||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@emotion/react": "^11.5.0",
|
"@emotion/react": "^11.5.0",
|
||||||
"@emotion/styled": "^11.3.0",
|
"@emotion/styled": "^11.3.0",
|
||||||
"@mui/material-pigment-css": "^6.0.1",
|
"@mui/material-pigment-css": "^6.2.0",
|
||||||
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||||
"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"
|
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
@@ -4081,19 +4066,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/material/node_modules/react-is": {
|
"node_modules/@mui/material/node_modules/react-is": {
|
||||||
"version": "18.3.1",
|
"version": "19.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz",
|
||||||
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
|
"integrity": "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g=="
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/@mui/private-theming": {
|
"node_modules/@mui/private-theming": {
|
||||||
"version": "6.0.2",
|
"version": "6.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.2.0.tgz",
|
||||||
"integrity": "sha512-emddFcRhA0hPGVIwIbW5g0V8vtCgw2g/H/A7jTdGe7dpCWEPpp6jPIXRRKcEUWgmg91R6rBNfV+LFHxBxmZXOQ==",
|
"integrity": "sha512-lYd2MrVddhentF1d/cMXKnwlDjr/shbO3A2eGq22PCYUoZaqtAGZMc0U86KnJ/Sh5YzNYePqTOaaowAN8Qea8A==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.25.0",
|
"@babel/runtime": "^7.26.0",
|
||||||
"@mui/utils": "^6.0.2",
|
"@mui/utils": "^6.2.0",
|
||||||
"prop-types": "^15.8.1"
|
"prop-types": "^15.8.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -4114,13 +4097,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/styled-engine": {
|
"node_modules/@mui/styled-engine": {
|
||||||
"version": "6.0.2",
|
"version": "6.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.2.0.tgz",
|
||||||
"integrity": "sha512-qd3Vlhted0SYVGotnCfVNcxff7vW2WN0fclbAexff60NeNS1qs/H/CImHEHUBiUGeNWMPRochbN6VF1arQ7/jA==",
|
"integrity": "sha512-rV4YCu6kcCjMnHFXU/tQcL6XfYVfFVR8n3ZVNGnk2rpXnt/ctOPJsF+eUQuhkHciueLVKpI06+umr1FxWWhVmQ==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.25.0",
|
"@babel/runtime": "^7.26.0",
|
||||||
"@emotion/cache": "^11.13.1",
|
"@emotion/cache": "^11.13.5",
|
||||||
|
"@emotion/serialize": "^1.3.3",
|
||||||
|
"@emotion/sheet": "^1.4.0",
|
||||||
"csstype": "^3.1.3",
|
"csstype": "^3.1.3",
|
||||||
"prop-types": "^15.8.1"
|
"prop-types": "^15.8.1"
|
||||||
},
|
},
|
||||||
@@ -4146,16 +4130,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/system": {
|
"node_modules/@mui/system": {
|
||||||
"version": "6.0.2",
|
"version": "6.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/system/-/system-6.2.0.tgz",
|
||||||
"integrity": "sha512-AZv1/C4PuHgWFTA8YraIzl3FTVLdRz0RIMRwEADWZBdIhnuTHS/4+r8qE9+3CcpTHg1WsEu8btaO3AhQahSM9A==",
|
"integrity": "sha512-DCeqev9Cd4f4pm3O1lqSGW/DIHHBG6ZpqMX9iIAvN4asYv+pPWv2/lKov9kWk5XThhxFnGSv93SRNE1kNRRg5Q==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.25.0",
|
"@babel/runtime": "^7.26.0",
|
||||||
"@mui/private-theming": "^6.0.2",
|
"@mui/private-theming": "^6.2.0",
|
||||||
"@mui/styled-engine": "^6.0.2",
|
"@mui/styled-engine": "^6.2.0",
|
||||||
"@mui/types": "^7.2.16",
|
"@mui/types": "^7.2.19",
|
||||||
"@mui/utils": "^6.0.2",
|
"@mui/utils": "^6.2.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"csstype": "^3.1.3",
|
"csstype": "^3.1.3",
|
||||||
"prop-types": "^15.8.1"
|
"prop-types": "^15.8.1"
|
||||||
@@ -4195,10 +4178,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/types": {
|
"node_modules/@mui/types": {
|
||||||
"version": "7.2.16",
|
"version": "7.2.19",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.16.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.19.tgz",
|
||||||
"integrity": "sha512-qI8TV3M7ShITEEc8Ih15A2vLzZGLhD+/UPNwck/hcls2gwg7dyRjNGXcQYHKLB5Q7PuTRfrTkAoPa2VV1s67Ag==",
|
"integrity": "sha512-6XpZEM/Q3epK9RN8ENoXuygnqUQxE+siN/6rGRi2iwJPgBUR25mphYQ9ZI87plGh58YoZ5pp40bFvKYOCDJ3tA==",
|
||||||
"license": "MIT",
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
},
|
},
|
||||||
@@ -4209,17 +4191,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/utils": {
|
"node_modules/@mui/utils": {
|
||||||
"version": "6.0.2",
|
"version": "6.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.2.0.tgz",
|
||||||
"integrity": "sha512-TeFrYsxcmeoDSlkoPhX+LjIuuqC5Pyj+xz2kRceKCkUpwMNTEeVOfowXDPe+mboZwmpJ5ZxP4eiAgQMdeEasjg==",
|
"integrity": "sha512-77CaFJi+OIi2SjbPwCis8z5DXvE0dfx9hBz5FguZHt1VYFlWEPCWTHcMsQCahSErnfik5ebLsYK8+D+nsjGVfw==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.25.0",
|
"@babel/runtime": "^7.26.0",
|
||||||
"@mui/types": "^7.2.16",
|
"@mui/types": "^7.2.19",
|
||||||
"@types/prop-types": "^15.7.12",
|
"@types/prop-types": "^15.7.14",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"react-is": "^18.3.1"
|
"react-is": "^19.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
@@ -4248,10 +4229,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/utils/node_modules/react-is": {
|
"node_modules/@mui/utils/node_modules/react-is": {
|
||||||
"version": "18.3.1",
|
"version": "19.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz",
|
||||||
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
|
"integrity": "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g=="
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
|
"node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
|
||||||
"version": "5.1.1-v1",
|
"version": "5.1.1-v1",
|
||||||
@@ -5726,10 +5706,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/prop-types": {
|
"node_modules/@types/prop-types": {
|
||||||
"version": "15.7.12",
|
"version": "15.7.14",
|
||||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
|
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz",
|
||||||
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==",
|
"integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ=="
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/@types/q": {
|
"node_modules/@types/q": {
|
||||||
"version": "1.5.8",
|
"version": "1.5.8",
|
||||||
@@ -10311,8 +10290,7 @@
|
|||||||
"node_modules/find-root": {
|
"node_modules/find-root": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
|
||||||
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
|
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/find-up": {
|
"node_modules/find-up": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
@@ -18016,6 +17994,11 @@
|
|||||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
|
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/reselect": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w=="
|
||||||
|
},
|
||||||
"node_modules/resolve": {
|
"node_modules/resolve": {
|
||||||
"version": "1.22.8",
|
"version": "1.22.8",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"homepage": "https://hugyouu.github.io/Letterboxd-Diary-Posters-Picker",
|
"homepage": "https://hugyouu.github.io/Letterboxd-Diary-Posters-Picker",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.13.3",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.13.0",
|
"@emotion/styled": "^11.14.0",
|
||||||
"@material-ui/core": "^4.12.4",
|
"@material-ui/core": "^4.12.4",
|
||||||
"@material-ui/icons": "^4.11.3",
|
"@material-ui/icons": "^4.11.3",
|
||||||
"@mui/icons-material": "^6.0.1",
|
"@mui/icons-material": "^6.0.1",
|
||||||
"@mui/lab": "^6.0.0-beta.9",
|
"@mui/lab": "^6.0.0-beta.9",
|
||||||
"@mui/material": "^6.0.1",
|
"@mui/material": "^6.2.0",
|
||||||
"@testing-library/jest-dom": "^5.17.0",
|
"@testing-library/jest-dom": "^5.17.0",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"redux": "^5.0.1",
|
"redux": "^5.0.1",
|
||||||
"redux-persist": "^6.0.0",
|
"redux-persist": "^6.0.0",
|
||||||
|
"reselect": "^5.1.1",
|
||||||
"sass": "^1.80.3",
|
"sass": "^1.80.3",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useSelector, useDispatch } from "react-redux";
|
import { useSelector, useDispatch } from "react-redux";
|
||||||
import { removePoster } from "../services/action";
|
import {removeAllPosters, removePoster} from "../services/action";
|
||||||
import DeleteIcon from "@material-ui/icons/Delete";
|
import DeleteIcon from "@material-ui/icons/Delete";
|
||||||
import { Camera } from "lucide-react";
|
|
||||||
|
|
||||||
const apiUrl = process.env.REACT_APP_API_URL;
|
const apiUrl = process.env.REACT_APP_API_URL;
|
||||||
|
|
||||||
@@ -11,16 +10,24 @@ const Cart = () => {
|
|||||||
const selectedPosters = useSelector((state) => {
|
const selectedPosters = useSelector((state) => {
|
||||||
const selections = state.posterSelections;
|
const selections = state.posterSelections;
|
||||||
return Object.entries(selections).flatMap(([movieId, posters]) =>
|
return Object.entries(selections).flatMap(([movieId, posters]) =>
|
||||||
posters.map((posterId) => ({ movieId, posterId }))
|
posters.map((poster) => ({
|
||||||
|
movieId,
|
||||||
|
posterId: typeof poster === "string" ? poster : poster.posterId,
|
||||||
|
}))
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const [downloadFormat, setDownloadFormat] = useState("zip");
|
const [downloadFormat, setDownloadFormat] = useState("zip");
|
||||||
|
|
||||||
const handleRemovePoster = (movieId, posterId) => {
|
const handleRemovePoster = (movieId, posterId) => {
|
||||||
dispatch(removePoster(movieId, posterId));
|
if (movieId && posterId) dispatch(removePoster(movieId, posterId));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleRemoveAllPosters = () => {
|
||||||
|
dispatch(removeAllPosters());
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const handleDownload = async () => {
|
const handleDownload = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${apiUrl}/api/download-posters`, {
|
const response = await fetch(`${apiUrl}/api/download-posters`, {
|
||||||
@@ -55,72 +62,62 @@ const Cart = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const totalSlots = 4;
|
|
||||||
const posterSlots = [...Array(totalSlots)].map((_, index) => {
|
|
||||||
if (index < selectedPosters.length) {
|
|
||||||
return selectedPosters[index];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="cart-container">
|
<div className="cart-container">
|
||||||
<div className="poster-grid">
|
<div className="poster-grid">
|
||||||
{posterSlots.map((poster, index) => (
|
{selectedPosters.length === 0 ? (
|
||||||
<div
|
<p>No posters selected</p>
|
||||||
key={
|
) : (
|
||||||
poster ? `${poster.movieId}-${poster.posterId}` : `empty-${index}`
|
selectedPosters.map((poster) => (
|
||||||
}
|
<div
|
||||||
className="poster-card"
|
key={`${poster.movieId}-${poster.posterId}`}
|
||||||
>
|
className="poster-card"
|
||||||
{poster ? (
|
|
||||||
<>
|
|
||||||
<img
|
|
||||||
src={`https://image.tmdb.org/t/p/w500${poster.posterId}`}
|
|
||||||
alt="Movie poster"
|
|
||||||
className="poster-image"
|
|
||||||
/>
|
|
||||||
<div className="delete-overlay">
|
|
||||||
<button
|
|
||||||
className="delete-button"
|
|
||||||
onClick={() =>
|
|
||||||
handleRemovePoster(poster.movieId, poster.posterId)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<DeleteIcon />
|
<img
|
||||||
</button>
|
src={`https://image.tmdb.org/t/p/original${poster.posterId}`}
|
||||||
</div>
|
alt="Movie poster"
|
||||||
</>
|
className="poster-image"
|
||||||
) : (
|
/>
|
||||||
<div className="empty-poster">
|
<div className="delete-overlay">
|
||||||
<Camera size={48} />
|
<button
|
||||||
<p>Emplacement disponible</p>
|
className="delete-button"
|
||||||
</div>
|
onClick={() => handleRemovePoster(poster.movieId, poster.posterId)}
|
||||||
)}
|
>
|
||||||
</div>
|
<DeleteIcon/>
|
||||||
))}
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="action-panel">
|
<div className="action-panel">
|
||||||
<h2>Download Options</h2>
|
<h2>Download Options</h2>
|
||||||
<select
|
<select
|
||||||
value={downloadFormat}
|
value={downloadFormat}
|
||||||
onChange={(e) => setDownloadFormat(e.target.value)}
|
onChange={(e) => setDownloadFormat(e.target.value)}
|
||||||
className="format-select"
|
className="format-select"
|
||||||
>
|
>
|
||||||
<option value="zip">ZIP</option>
|
<option value="zip">ZIP</option>
|
||||||
<option value="tar">TAR</option>
|
<option value="tar">TAR</option>
|
||||||
<option value="7z">7Z</option>
|
<option value="7z">7Z</option>
|
||||||
</select>
|
</select>
|
||||||
<button
|
<button
|
||||||
className="download-button"
|
className="download-button"
|
||||||
onClick={handleDownload}
|
onClick={handleDownload}
|
||||||
disabled={selectedPosters.length === 0}
|
disabled={selectedPosters.length === 0}
|
||||||
>
|
>
|
||||||
Download Selected
|
Download Selected
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
className="clear-button"
|
||||||
|
onClick={handleRemoveAllPosters}
|
||||||
|
disabled={selectedPosters.length === 0}
|
||||||
|
>
|
||||||
|
Clear All Posters
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
import React from "react";
|
import React, { useMemo } from "react";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { AppBar, Toolbar, IconButton, Badge, Button } from '@material-ui/core';
|
import { AppBar, Toolbar, IconButton, Badge, Button } from '@material-ui/core';
|
||||||
import ShoppingCartIcon from '@material-ui/icons/ShoppingCart';
|
import ShoppingCartIcon from '@material-ui/icons/ShoppingCart';
|
||||||
import ArrowBackIcon from '@material-ui/icons/ArrowBack';
|
import ArrowBackIcon from '@material-ui/icons/ArrowBack';
|
||||||
import { useNavigate, useLocation } from 'react-router-dom';
|
import { useNavigate, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
const selectPosterSelections = (state) => state.posterSelections;
|
||||||
|
|
||||||
const NavBar = ({ onRefreshFiles }) => {
|
const NavBar = ({ onRefreshFiles }) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const selectedPosters = useSelector((state) => {
|
|
||||||
const selections = state.posterSelections;
|
const posterSelections = useSelector(selectPosterSelections);
|
||||||
return Object.values(selections).flat();
|
const selectedPosters = useMemo(() => {
|
||||||
});
|
return Object.values(posterSelections).flat();
|
||||||
|
}, [posterSelections]);
|
||||||
|
|
||||||
const totalSelected = selectedPosters.length;
|
const totalSelected = selectedPosters.length;
|
||||||
|
|
||||||
@@ -29,20 +32,39 @@ const NavBar = ({ onRefreshFiles }) => {
|
|||||||
<AppBar position="fixed" className="navbar">
|
<AppBar position="fixed" className="navbar">
|
||||||
<Toolbar className="toolbar">
|
<Toolbar className="toolbar">
|
||||||
{isPosterSelectorPage ? (
|
{isPosterSelectorPage ? (
|
||||||
<IconButton edge="start" className="back-button" onClick={handleBack}>
|
<IconButton
|
||||||
|
edge="start"
|
||||||
|
className="back-button"
|
||||||
|
onClick={handleBack}
|
||||||
|
>
|
||||||
<ArrowBackIcon />
|
<ArrowBackIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
) : (
|
) : (
|
||||||
<IconButton edge="start" className="back-button" disabled>
|
<IconButton
|
||||||
{/* Un IconButton vide et désactivé */}
|
edge="start"
|
||||||
|
className="back-button"
|
||||||
|
disabled
|
||||||
|
>
|
||||||
|
{/* Disabled IconButton */}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
<div>
|
<div>
|
||||||
<Button className="refresh-button" onClick={onRefreshFiles}>
|
<Button
|
||||||
|
className="refresh-button"
|
||||||
|
onClick={onRefreshFiles}
|
||||||
|
>
|
||||||
Refresh Files
|
Refresh Files
|
||||||
</Button>
|
</Button>
|
||||||
<IconButton edge="end" className="cart-button" onClick={handleCart}>
|
<IconButton
|
||||||
<Badge badgeContent={totalSelected} color="secondary">
|
edge="end"
|
||||||
|
className="cart-button"
|
||||||
|
onClick={handleCart}
|
||||||
|
>
|
||||||
|
<Badge
|
||||||
|
badgeContent={totalSelected}
|
||||||
|
color="secondary"
|
||||||
|
overlap="rectangular"
|
||||||
|
>
|
||||||
<ShoppingCartIcon />
|
<ShoppingCartIcon />
|
||||||
</Badge>
|
</Badge>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|||||||
@@ -11,18 +11,24 @@ import {
|
|||||||
CardMedia,
|
CardMedia,
|
||||||
CircularProgress,
|
CircularProgress,
|
||||||
Box,
|
Box,
|
||||||
Paper,
|
Paper, DialogContent, DialogTitle, DialogActions, Button,
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
import CheckIcon from "@material-ui/icons/Check";
|
import CheckIcon from "@material-ui/icons/Check";
|
||||||
import NavBar from "./NavBar";
|
import NavBar from "./NavBar";
|
||||||
|
import {Dialog} from "@mui/material";
|
||||||
|
|
||||||
const apiUrl = process.env.REACT_APP_API_URL;
|
const apiUrl = process.env.REACT_APP_API_URL;
|
||||||
|
|
||||||
const PosterGallery = ({ movieId }) => {
|
const PosterGallery = () => {
|
||||||
|
const { movieName, movieYear } = useParams();
|
||||||
const [posters, setPosters] = useState([]);
|
const [posters, setPosters] = useState([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const { movieName, movieYear } = useParams();
|
const [error, setError] = useState(null);
|
||||||
|
const [dialogOpen, setDialogOpen] = useState(false);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const movieId = `${movieName}-${movieYear}`;
|
||||||
|
|
||||||
const selectedPosters = useSelector(
|
const selectedPosters = useSelector(
|
||||||
(state) => state.posterSelections[movieId] || []
|
(state) => state.posterSelections[movieId] || []
|
||||||
);
|
);
|
||||||
@@ -31,10 +37,20 @@ const PosterGallery = ({ movieId }) => {
|
|||||||
const fetchPosters = async () => {
|
const fetchPosters = async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
setError(null);
|
||||||
|
|
||||||
|
const encodedName = encodeURIComponent(movieName);
|
||||||
|
const encodedYear = encodeURIComponent(movieYear);
|
||||||
|
|
||||||
const response = await axios.get(
|
const response = await axios.get(
|
||||||
`${apiUrl}/api/posters/${movieName}/${movieYear}`
|
`${apiUrl}/api/posters/${encodedName}/${encodedYear}`
|
||||||
);
|
);
|
||||||
setPosters(response.data.posters);
|
|
||||||
|
if (response.data && response.data.posters) {
|
||||||
|
setPosters(response.data.posters);
|
||||||
|
} else {
|
||||||
|
throw new Error("No posters data in response");
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching posters:", error);
|
console.error("Error fetching posters:", error);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -42,17 +58,46 @@ const PosterGallery = ({ movieId }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchPosters();
|
if (movieName && movieYear) {
|
||||||
|
fetchPosters();
|
||||||
|
}
|
||||||
}, [movieName, movieYear]);
|
}, [movieName, movieYear]);
|
||||||
|
|
||||||
const handlePosterSelect = (posterId) => {
|
const handlePosterSelect = (posterId) => {
|
||||||
if (selectedPosters.includes(posterId)) {
|
const postersForCurrentMovie = selectedPosters.filter(
|
||||||
dispatch(deselectPoster(movieId, posterId));
|
(poster) => poster.movieId !== movieId
|
||||||
|
);
|
||||||
|
|
||||||
|
const isPosterSelected = postersForCurrentMovie.some((poster) => poster.posterId === posterId)
|
||||||
|
|
||||||
|
if (postersForCurrentMovie.length > 0 && !isPosterSelected) {
|
||||||
|
setDialogOpen(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isPosterSelected) {
|
||||||
|
dispatch(deselectPoster(movieName, movieYear, posterId));
|
||||||
} else {
|
} else {
|
||||||
dispatch(selectPoster(movieId, posterId));
|
dispatch(selectPoster(movieName, movieYear, posterId));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDialogClose = () => {
|
||||||
|
setDialogOpen(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Paper elevation={3} className="content-paper">
|
||||||
|
<Typography color="error" align="center">
|
||||||
|
{error}
|
||||||
|
</Typography>
|
||||||
|
</Paper>
|
||||||
|
<NavBar />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Container className="poster-gallery">
|
<Container className="poster-gallery">
|
||||||
@@ -64,7 +109,7 @@ const PosterGallery = ({ movieId }) => {
|
|||||||
<Box className="loading-container">
|
<Box className="loading-container">
|
||||||
<CircularProgress />
|
<CircularProgress />
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : posters.length > 0 ? (
|
||||||
<Grid container spacing={3}>
|
<Grid container spacing={3}>
|
||||||
{posters.map((poster, index) => (
|
{posters.map((poster, index) => (
|
||||||
<Grid item xs={12} sm={6} md={4} lg={3} key={index}>
|
<Grid item xs={12} sm={6} md={4} lg={3} key={index}>
|
||||||
@@ -78,7 +123,7 @@ const PosterGallery = ({ movieId }) => {
|
|||||||
>
|
>
|
||||||
<CardMedia
|
<CardMedia
|
||||||
className="poster-image"
|
className="poster-image"
|
||||||
image={`https://image.tmdb.org/t/p/w500${poster.file_path}`}
|
image={`https://image.tmdb.org/t/p/original${poster.file_path}`}
|
||||||
title={`${movieName} poster ${index + 1}`}
|
title={`${movieName} poster ${index + 1}`}
|
||||||
/>
|
/>
|
||||||
{selectedPosters.includes(poster.file_path) && (
|
{selectedPosters.includes(poster.file_path) && (
|
||||||
@@ -88,10 +133,27 @@ const PosterGallery = ({ movieId }) => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
) : (
|
||||||
|
<Typography align="center">
|
||||||
|
No posters found for this movie.
|
||||||
|
</Typography>
|
||||||
)}
|
)}
|
||||||
</Paper>
|
</Paper>
|
||||||
</Container>
|
</Container>
|
||||||
<NavBar />
|
<NavBar />
|
||||||
|
<Dialog open={dialogOpen} onClose={handleDialogClose}>
|
||||||
|
<DialogTitle>Poster already selected</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<Typography>
|
||||||
|
You can only select one poster per movie. Please deselect the current poster first.
|
||||||
|
</Typography>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={handleDialogClose} color="primary">
|
||||||
|
OK
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -109,9 +109,7 @@ const PosterSelector = () => {
|
|||||||
|
|
||||||
const handleMovieClick = (movieName, movieYear) => {
|
const handleMovieClick = (movieName, movieYear) => {
|
||||||
navigate(
|
navigate(
|
||||||
`/posters/${encodeURIComponent(movieName)}/${encodeURIComponent(
|
`/posters/${encodeURIComponent(movieName)}/${encodeURIComponent(movieYear)}`
|
||||||
movieYear
|
|
||||||
)}`
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,32 @@
|
|||||||
export const selectPoster = (movieId, posterId) => ({
|
export const SELECT_POSTER = "SELECT_POSTER";
|
||||||
type: "SELECT_POSTER",
|
export const DESELECT_POSTER = "DESELECT_POSTER";
|
||||||
movieId,
|
export const REMOVE_POSTER = "REMOVE_POSTER";
|
||||||
posterId,
|
|
||||||
});
|
export const REMOVE_ALL_POSTERS = "REMOVE_ALL_POSTERS";
|
||||||
|
|
||||||
|
export const selectPoster = (movieName, movieYear, posterId) => {
|
||||||
|
const movieId = `${movieName}-${movieYear}`;
|
||||||
|
return {
|
||||||
|
type: SELECT_POSTER,
|
||||||
|
payload: { movieId, posterId },
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deselectPoster = (movieName, movieYear, posterId) => {
|
||||||
|
const movieId = `${movieName}-${movieYear}`;
|
||||||
|
return {
|
||||||
|
type: DESELECT_POSTER,
|
||||||
|
payload: { movieId, posterId },
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const deselectPoster = (movieId, posterId) => ({
|
|
||||||
type: "DESELECT_POSTER",
|
|
||||||
movieId,
|
|
||||||
posterId,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const removePoster = (movieId, posterId) => ({
|
export const removePoster = (movieId, posterId) => ({
|
||||||
type: "REMOVE_POSTER",
|
type: "REMOVE_POSTER",
|
||||||
movieId,
|
movieId,
|
||||||
posterId,
|
posterId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const removeAllPosters = () => ({
|
||||||
|
type: REMOVE_ALL_POSTERS,
|
||||||
|
});
|
||||||
@@ -1,30 +1,40 @@
|
|||||||
import { legacy_createStore as createStore, combineReducers } from "redux";
|
import { legacy_createStore as createStore, combineReducers } from "redux";
|
||||||
import { persistStore, persistReducer } from "redux-persist";
|
import { persistStore, persistReducer } from "redux-persist";
|
||||||
import storage from "redux-persist/lib/storage";
|
import storage from "redux-persist/lib/storage";
|
||||||
|
import {DESELECT_POSTER, REMOVE_ALL_POSTERS, REMOVE_POSTER, SELECT_POSTER} from "./action";
|
||||||
|
|
||||||
const posterSelectionReducer = (state = {}, action) => {
|
const posterSelectionReducer = (state = {}, action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case "SELECT_POSTER":
|
case SELECT_POSTER: {
|
||||||
return {
|
const { movieId, posterId } = action.payload;
|
||||||
...state,
|
return {
|
||||||
[action.movieId]: [...(state[action.movieId] || []), action.posterId],
|
...state,
|
||||||
};
|
[movieId]: [...(state[movieId] || []), posterId],
|
||||||
case "DESELECT_POSTER":
|
};
|
||||||
return {
|
}
|
||||||
...state,
|
case DESELECT_POSTER: {
|
||||||
[action.movieId]: state[action.movieId].filter(
|
const { movieId, posterId } = action.payload;
|
||||||
(id) => id !== action.posterId
|
return {
|
||||||
),
|
...state,
|
||||||
};
|
[movieId]: state[movieId]?.filter(
|
||||||
case "REMOVE_POSTER":
|
(id) => id !== posterId
|
||||||
return {
|
),
|
||||||
...state,
|
};
|
||||||
[action.movieId]: state[action.movieId].filter(
|
}
|
||||||
(id) => id !== action.posterId
|
case REMOVE_POSTER: {
|
||||||
),
|
const { movieId, posterId } = action;
|
||||||
};
|
return {
|
||||||
default:
|
...state,
|
||||||
return state;
|
[movieId]: state[movieId]?.filter(
|
||||||
|
(id) => id !== posterId
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case REMOVE_ALL_POSTERS: {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,14 +10,11 @@
|
|||||||
grid-template-columns: repeat(4, 1fr);
|
grid-template-columns: repeat(4, 1fr);
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
max-height: calc(100vh - 4rem);
|
max-height: calc(100vh - 4rem);
|
||||||
overflow-y: auto;
|
|
||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
|
|
||||||
.poster-card {
|
.poster-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
aspect-ratio: 2/3;
|
aspect-ratio: 2/3;
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
&:hover .delete-overlay {
|
&:hover .delete-overlay {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
@@ -26,7 +23,6 @@
|
|||||||
.poster-image {
|
.poster-image {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.delete-overlay {
|
.delete-overlay {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ $hover-color: rgba(102, 119, 136, 0.2);
|
|||||||
}
|
}
|
||||||
|
|
||||||
.movie-item {
|
.movie-item {
|
||||||
|
padding: 0 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
transition: background-color 0.3s ease;
|
transition: background-color 0.3s ease;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Reference in New Issue
Block a user