diff --git a/bbssite/urls.py b/bbssite/urls.py index 37effd7..d32f5a5 100755 --- a/bbssite/urls.py +++ b/bbssite/urls.py @@ -22,5 +22,5 @@ urlpatterns = [ path("graphql/", GraphQLView.as_view(schema=schema)), ] -urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) +urlpatterns += static('/media', document_root=settings.MEDIA_ROOT) urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e86be56..c456c8b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -12,7 +12,8 @@ "date-fns": "^2.25.0", "graphql": "^15.7.2", "react": "^17.0.2", - "react-dom": "^17.0.2" + "react-dom": "^17.0.2", + "react-router-dom": "^5.3.0" }, "devDependencies": { "@graphql-codegen/cli": "^2.2.2", @@ -20,6 +21,7 @@ "@graphql-codegen/typescript-react-apollo": "^3.2.0", "@types/react": "^17.0.33", "@types/react-dom": "^17.0.10", + "@types/react-router-dom": "^5.3.2", "@typescript-eslint/eslint-plugin": "^5.2.0", "@typescript-eslint/parser": "^5.2.0", "@vitejs/plugin-react": "^1.0.7", @@ -1323,7 +1325,6 @@ "version": "7.16.0", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.0.tgz", "integrity": "sha512-Nht8L0O8YCktmsDV6FqFue7vQLRx3Hb0B37lS5y0jDRqRxlBG4wIJHnf9/bgSE2UyipKFA01YtS+npRdTWBUyw==", - "dev": true, "dependencies": { "regenerator-runtime": "^0.13.4" }, @@ -2551,6 +2552,12 @@ "@types/node": "*" } }, + "node_modules/@types/history": { + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.9.tgz", + "integrity": "sha512-MUc6zSmU3tEVnkQ78q0peeEjKWPUADMlC/t++2bI8WnAG2tvYRPIgHG8lWkXwqc8MsUF6Z2MOf+Mh5sazOmhiQ==", + "dev": true + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", @@ -2664,6 +2671,27 @@ "@types/react": "*" } }, + "node_modules/@types/react-router": { + "version": "5.1.17", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.17.tgz", + "integrity": "sha512-RNSXOyb3VyRs/EOGmjBhhGKTbnN6fHWvy5FNLzWfOWOGjgVUKqJZXfpKzLmgoU8h6Hj8mpALj/mbXQASOb92wQ==", + "dev": true, + "dependencies": { + "@types/history": "*", + "@types/react": "*" + } + }, + "node_modules/@types/react-router-dom": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.2.tgz", + "integrity": "sha512-ELEYRUie2czuJzaZ5+ziIp9Hhw+juEw8b7C11YNA4QdLCVbQ3qLi2l4aq8XnlqM7V31LZX8dxUuFUCrzHm6sqQ==", + "dev": true, + "dependencies": { + "@types/history": "*", + "@types/react": "*", + "@types/react-router": "*" + } + }, "node_modules/@types/scheduler": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", @@ -6162,6 +6190,19 @@ "tslib": "^2.0.3" } }, + "node_modules/history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "dependencies": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, "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", @@ -6827,6 +6868,11 @@ "node": ">=0.10.0" } }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -8606,6 +8652,19 @@ "node": ">=4" } }, + "node_modules/mini-create-react-context": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", + "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", + "dependencies": { + "@babel/runtime": "^7.12.1", + "tiny-warning": "^1.0.3" + }, + "peerDependencies": { + "prop-types": "^15.0.0", + "react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, "node_modules/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -9174,6 +9233,14 @@ "node": ">=0.10.0" } }, + "node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dependencies": { + "isarray": "0.0.1" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -9550,6 +9617,48 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz", + "integrity": "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/react-router-dom": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz", + "integrity": "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.2.1", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/react-router/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -9664,8 +9773,7 @@ "node_modules/regenerator-runtime": { "version": "0.13.9", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, "node_modules/regexp.prototype.flags": { "version": "1.3.1", @@ -9915,6 +10023,11 @@ "node": ">=8" } }, + "node_modules/resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, "node_modules/resolve.exports": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", @@ -10784,6 +10897,16 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, + "node_modules/tiny-invariant": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", + "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, "node_modules/title-case": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/title-case/-/title-case-3.0.3.tgz", @@ -11199,6 +11322,11 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, "node_modules/value-or-promise": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.11.tgz", @@ -12454,7 +12582,6 @@ "version": "7.16.0", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.0.tgz", "integrity": "sha512-Nht8L0O8YCktmsDV6FqFue7vQLRx3Hb0B37lS5y0jDRqRxlBG4wIJHnf9/bgSE2UyipKFA01YtS+npRdTWBUyw==", - "dev": true, "requires": { "regenerator-runtime": "^0.13.4" } @@ -13430,6 +13557,12 @@ "@types/node": "*" } }, + "@types/history": { + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.9.tgz", + "integrity": "sha512-MUc6zSmU3tEVnkQ78q0peeEjKWPUADMlC/t++2bI8WnAG2tvYRPIgHG8lWkXwqc8MsUF6Z2MOf+Mh5sazOmhiQ==", + "dev": true + }, "@types/istanbul-lib-coverage": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", @@ -13543,6 +13676,27 @@ "@types/react": "*" } }, + "@types/react-router": { + "version": "5.1.17", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.17.tgz", + "integrity": "sha512-RNSXOyb3VyRs/EOGmjBhhGKTbnN6fHWvy5FNLzWfOWOGjgVUKqJZXfpKzLmgoU8h6Hj8mpALj/mbXQASOb92wQ==", + "dev": true, + "requires": { + "@types/history": "*", + "@types/react": "*" + } + }, + "@types/react-router-dom": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.2.tgz", + "integrity": "sha512-ELEYRUie2czuJzaZ5+ziIp9Hhw+juEw8b7C11YNA4QdLCVbQ3qLi2l4aq8XnlqM7V31LZX8dxUuFUCrzHm6sqQ==", + "dev": true, + "requires": { + "@types/history": "*", + "@types/react": "*", + "@types/react-router": "*" + } + }, "@types/scheduler": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", @@ -16139,6 +16293,19 @@ "tslib": "^2.0.3" } }, + "history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "requires": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, "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", @@ -16617,6 +16784,11 @@ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -18011,6 +18183,15 @@ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true }, + "mini-create-react-context": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", + "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", + "requires": { + "@babel/runtime": "^7.12.1", + "tiny-warning": "^1.0.3" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -18443,6 +18624,14 @@ "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", "dev": true }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } + }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -18719,6 +18908,44 @@ "integrity": "sha512-PgidR3wST3dDYKr6b4pJoqQFpPGNKDSCDx4cZoshjXipw3LzO7mG1My2pwEzz2JVkF+inx3xRpDeQLFQGH/hsQ==", "dev": true }, + "react-router": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz", + "integrity": "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==", + "requires": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "dependencies": { + "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==" + } + } + }, + "react-router-dom": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz", + "integrity": "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==", + "requires": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.2.1", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, "read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -18812,8 +19039,7 @@ "regenerator-runtime": { "version": "0.13.9", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, "regexp.prototype.flags": { "version": "1.3.1", @@ -19011,6 +19237,11 @@ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, + "resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, "resolve.exports": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", @@ -19699,6 +19930,16 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, + "tiny-invariant": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", + "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" + }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, "title-case": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/title-case/-/title-case-3.0.3.tgz", @@ -20018,6 +20259,11 @@ "spdx-expression-parse": "^3.0.0" } }, + "value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, "value-or-promise": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.11.tgz", diff --git a/frontend/package.json b/frontend/package.json index b446c35..e4d8b07 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -19,7 +19,8 @@ "date-fns": "^2.25.0", "graphql": "^15.7.2", "react": "^17.0.2", - "react-dom": "^17.0.2" + "react-dom": "^17.0.2", + "react-router-dom": "^5.3.0" }, "devDependencies": { "@graphql-codegen/cli": "^2.2.2", @@ -27,6 +28,7 @@ "@graphql-codegen/typescript-react-apollo": "^3.2.0", "@types/react": "^17.0.33", "@types/react-dom": "^17.0.10", + "@types/react-router-dom": "^5.3.2", "@typescript-eslint/eslint-plugin": "^5.2.0", "@typescript-eslint/parser": "^5.2.0", "@vitejs/plugin-react": "^1.0.7", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index d44e983..14479d3 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,17 +1,22 @@ import { ApolloProvider } from "@apollo/client"; import React from "react"; +import { BrowserRouter as Router } from "react-router-dom"; import styles from "./App.module.css"; +import { Routes } from "./Routes"; import logo from "./assets/brick.svg"; import client from "./client"; -import { Register } from "./features/Register"; +import { Header } from "./components/Header"; const App: React.FC = () => ( -
- logo - -
+ +
+
+ logo + +
+ ); diff --git a/frontend/src/Routes.tsx b/frontend/src/Routes.tsx new file mode 100644 index 0000000..3c05f2a --- /dev/null +++ b/frontend/src/Routes.tsx @@ -0,0 +1,12 @@ +import React from "react"; +import { Route, Switch } from "react-router-dom"; + +import { Deposit } from "./features/deposit/Deposit"; +import { Register } from "./features/register/Register"; + +export const Routes: React.FC = () => ( + + + + +); diff --git a/frontend/src/components/Header.tsx b/frontend/src/components/Header.tsx new file mode 100644 index 0000000..f437768 --- /dev/null +++ b/frontend/src/components/Header.tsx @@ -0,0 +1,14 @@ +import React from "react"; +import { Link } from "react-router-dom"; + +export const Header: React.FC = () => { + return ( +
+
Biceps Bar System - BBS
+ +
+ ); +}; diff --git a/frontend/src/features/Register.tsx b/frontend/src/features/Register.tsx deleted file mode 100644 index c1d6ae6..0000000 --- a/frontend/src/features/Register.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from "react"; - -import { Product, User } from "../types"; -import { useRegister } from "./useRegister"; - -export const Register: React.FC = () => { - const { users, products, loading, showAll, setShowAll } = useRegister(); - if (loading) { - return
...
; - } - return ( -
-
- {users.map((user: User) => { - return
{user.firstName}
; - })} -
-
- {products.map((product: Product) => { - return
{product.name}
; - })} -
-
- ); -}; diff --git a/frontend/src/features/deposit/Deposit.tsx b/frontend/src/features/deposit/Deposit.tsx new file mode 100644 index 0000000..ea78e6c --- /dev/null +++ b/frontend/src/features/deposit/Deposit.tsx @@ -0,0 +1,5 @@ +import React from "react"; + +export const Deposit: React.FC = () => { + return
Hi from deposit
; +}; diff --git a/frontend/src/features/register/Register.module.css b/frontend/src/features/register/Register.module.css new file mode 100644 index 0000000..ef4cc1c --- /dev/null +++ b/frontend/src/features/register/Register.module.css @@ -0,0 +1,19 @@ +.productList { + display: grid; + grid-template-columns: repeat(6, 1fr); + gap: 16px; +} +.product { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} +.productText { + padding-top: 8px; +} +.productImage { + width: 100px; + height: 100px; + object-fit: contain; +} \ No newline at end of file diff --git a/frontend/src/features/register/Register.tsx b/frontend/src/features/register/Register.tsx new file mode 100644 index 0000000..4bbc6d0 --- /dev/null +++ b/frontend/src/features/register/Register.tsx @@ -0,0 +1,48 @@ +import React from "react"; + +import { Product, User } from "../../types"; +import styles from "./Register.module.css"; +import { useRegister } from "./useRegister"; + +export const Register: React.FC = () => { + const { users, products, loading, showAll, setShowAll } = useRegister(); + if (loading) { + return
Loading...
; + } + return ( +
+
+

Hvem kjøper?

+
Ekstern
+ {users.map((user: User) => { + return
{user.firstName}
; + })} + +
+
+

Kjøper hva?

+
+ {products.map((product: Product) => { + return ( +
+ {product.imageUrl && {product.name}} + {product.name} +
+ ); + })} +
+
+
+ Totalt: 0 + + +
+
+ ); +}; diff --git a/frontend/src/features/allProducts.graphql b/frontend/src/features/register/allProducts.graphql similarity index 91% rename from frontend/src/features/allProducts.graphql rename to frontend/src/features/register/allProducts.graphql index 1f83088..533bab7 100644 --- a/frontend/src/features/allProducts.graphql +++ b/frontend/src/features/register/allProducts.graphql @@ -2,6 +2,7 @@ query allProducts($active: Boolean!) { allProducts(filters: {active: $active}) { id name + imageUrl salePriceExt salePriceInt } diff --git a/frontend/src/features/allUsers.graphql b/frontend/src/features/register/allUsers.graphql similarity index 100% rename from frontend/src/features/allUsers.graphql rename to frontend/src/features/register/allUsers.graphql diff --git a/frontend/src/features/useRegister.ts b/frontend/src/features/register/useRegister.ts similarity index 73% rename from frontend/src/features/useRegister.ts rename to frontend/src/features/register/useRegister.ts index cb9dcd0..efcbb4b 100644 --- a/frontend/src/features/useRegister.ts +++ b/frontend/src/features/register/useRegister.ts @@ -1,11 +1,19 @@ import { parseISO, subDays } from "date-fns"; import { useState } from "react"; -import { useAllProductsQuery, useAllUsersQuery, User } from "../types"; +import { useAllProductsQuery, useAllUsersQuery, User, Product } from "../../types"; const activeLimitDays = 365 / 2; -export const useRegister = () => { +type useRegisterType = { + users: User[]; + products: Product[]; + loading: boolean; + showAll: boolean; + setShowAll: CallableFunction; +}; + +export const useRegister = (): useRegisterType => { const [showAll, setShowAll] = useState(false); const { data, loading } = useAllProductsQuery({ variables: { active: true } }); const { data: usersData, loading: usersLoading } = useAllUsersQuery(); diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 0f91c39..45fdcaa 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -19,6 +19,7 @@ export type Scalars = { export type Product = { __typename?: 'Product'; id: Scalars['ID']; + imageUrl: Scalars['String']; name: Scalars['String']; salePriceExt: Scalars['Float']; salePriceInt: Scalars['Float']; @@ -61,7 +62,7 @@ export type AllProductsQueryVariables = Exact<{ }>; -export type AllProductsQuery = { __typename?: 'Query', allProducts: Array<{ __typename?: 'Product', id: string, name: string, salePriceExt: number, salePriceInt: number }> }; +export type AllProductsQuery = { __typename?: 'Query', allProducts: Array<{ __typename?: 'Product', id: string, name: string, imageUrl: string, salePriceExt: number, salePriceInt: number }> }; export type AllUsersQueryVariables = Exact<{ [key: string]: never; }>; @@ -74,6 +75,7 @@ export const AllProductsDocument = gql` allProducts(filters: {active: $active}) { id name + imageUrl salePriceExt salePriceInt } diff --git a/main/api/types.py b/main/api/types.py index ed5ae86..7f41636 100644 --- a/main/api/types.py +++ b/main/api/types.py @@ -20,6 +20,7 @@ class ProductFilter: class Product: id: auto name: auto + image_url: str sale_price_int: auto sale_price_ext: auto diff --git a/main/models.py b/main/models.py index 5ea39a4..e139bb7 100755 --- a/main/models.py +++ b/main/models.py @@ -2,6 +2,7 @@ from datetime import datetime from django.conf import settings from django.db import models +from django.templatetags.static import static from django.utils.translation import ugettext_lazy as _ @@ -43,6 +44,10 @@ class Product(models.Model): def wholesale_value(self): return self.wholesale_unit_price * self.inventory_amount + @property + def image_url(self): + return self.image.url if self.image else "" + def __str__(self): return self.name