This commit is contained in:
Noah Spannbauer
2023-02-15 12:46:50 -06:00
parent c2d8bd1838
commit 0d5eb3e801
99 changed files with 20124 additions and 213 deletions

268
app/package-lock.json generated
View File

@@ -16,7 +16,9 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-grid-system": "^8.1.6",
"react-router-dom": "^6.6.1"
"react-router-dom": "^6.6.1",
"semantic-ui-css": "^2.5.0",
"semantic-ui-react": "^2.1.4"
},
"devDependencies": {
"@babel/core": "^7.20.12",
@@ -1809,7 +1811,6 @@
"version": "7.20.13",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz",
"integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==",
"dev": true,
"dependencies": {
"regenerator-runtime": "^0.13.11"
},
@@ -2259,6 +2260,31 @@
"react-dom": ">=16.8.0 <19.0.0"
}
},
"node_modules/@fluentui/react-component-event-listener": {
"version": "0.63.1",
"resolved": "https://registry.npmjs.org/@fluentui/react-component-event-listener/-/react-component-event-listener-0.63.1.tgz",
"integrity": "sha512-gSMdOh6tI3IJKZFqxfQwbTpskpME0CvxdxGM2tdglmf6ZPVDi0L4+KKIm+2dN8nzb8Ya1A8ZT+Ddq0KmZtwVQg==",
"dependencies": {
"@babel/runtime": "^7.10.4"
},
"peerDependencies": {
"react": "^16.8.0 || ^17 || ^18",
"react-dom": "^16.8.0 || ^17 || ^18"
}
},
"node_modules/@fluentui/react-component-ref": {
"version": "0.63.1",
"resolved": "https://registry.npmjs.org/@fluentui/react-component-ref/-/react-component-ref-0.63.1.tgz",
"integrity": "sha512-8MkXX4+R3i80msdbD4rFpEB4WWq2UDvGwG386g3ckIWbekdvN9z2kWAd9OXhRGqB7QeOsoAGWocp6gAMCivRlw==",
"dependencies": {
"@babel/runtime": "^7.10.4",
"react-is": "^16.6.3"
},
"peerDependencies": {
"react": "^16.8.0 || ^17 || ^18",
"react-dom": "^16.8.0 || ^17 || ^18"
}
},
"node_modules/@fluentui/react-focus": {
"version": "8.8.12",
"resolved": "https://registry.npmjs.org/@fluentui/react-focus/-/react-focus-8.8.12.tgz",
@@ -2631,6 +2657,15 @@
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.6",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@remix-run/router": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.3.0.tgz",
@@ -2639,6 +2674,19 @@
"node": ">=14"
}
},
"node_modules/@semantic-ui-react/event-stack": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/@semantic-ui-react/event-stack/-/event-stack-3.1.3.tgz",
"integrity": "sha512-FdTmJyWvJaYinHrKRsMLDrz4tTMGdFfds299Qory53hBugiDvGC0tEJf+cHsi5igDwWb/CLOgOiChInHwq8URQ==",
"dependencies": {
"exenv": "^1.2.2",
"prop-types": "^15.6.2"
},
"peerDependencies": {
"react": "^16.0.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/@sideway/address": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz",
@@ -5036,6 +5084,14 @@
"node": ">=6"
}
},
"node_modules/clsx": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
"engines": {
"node": ">=6"
}
},
"node_modules/coffeeify": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/coffeeify/-/coffeeify-3.0.1.tgz",
@@ -6870,6 +6926,11 @@
"node": ">=4"
}
},
"node_modules/exenv": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
"integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw=="
},
"node_modules/express": {
"version": "4.18.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
@@ -8811,6 +8872,11 @@
"@sideway/pinpoint": "^2.0.0"
}
},
"node_modules/jquery": {
"version": "3.6.3",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.3.tgz",
"integrity": "sha512-bZ5Sy3YzKo9Fyc8wH2iIQK4JImJ6R0GWI9kL1/k7Z91ZBNgkRXE6U0JfHIizZbort8ZunhSI3jw9I6253ahKfg=="
},
"node_modules/js-base64": {
"version": "2.6.4",
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz",
@@ -8975,6 +9041,11 @@
"verror": "1.10.0"
}
},
"node_modules/keyboard-key": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/keyboard-key/-/keyboard-key-1.1.0.tgz",
"integrity": "sha512-qkBzPTi3rlAKvX7k0/ub44sqOfXeLc/jcnGGmj5c7BJpU8eDrEVPyhCvNYAaoubbsLm9uGWwQJO1ytQK1a9/dQ=="
},
"node_modules/kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@@ -9423,8 +9494,12 @@
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"node_modules/lodash.clonedeep": {
"version": "4.5.0",
@@ -11774,6 +11849,11 @@
"react": "^18.2.0"
}
},
"node_modules/react-fast-compare": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
},
"node_modules/react-grid-system": {
"version": "8.1.8",
"resolved": "https://registry.npmjs.org/react-grid-system/-/react-grid-system-8.1.8.tgz",
@@ -11790,6 +11870,20 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/react-popper": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz",
"integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==",
"dependencies": {
"react-fast-compare": "^3.0.1",
"warning": "^4.0.2"
},
"peerDependencies": {
"@popperjs/core": "^2.0.0",
"react": "^16.8.0 || ^17 || ^18",
"react-dom": "^16.8.0 || ^17 || ^18"
}
},
"node_modules/react-router": {
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.7.0.tgz",
@@ -11994,8 +12088,7 @@
"node_modules/regenerator-runtime": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
"dev": true
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
},
"node_modules/regenerator-transform": {
"version": "0.15.1",
@@ -12506,6 +12599,38 @@
"node": ">=10"
}
},
"node_modules/semantic-ui-css": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/semantic-ui-css/-/semantic-ui-css-2.5.0.tgz",
"integrity": "sha512-jIWn3WXXE2uSaWCcB+gVJVRG3masIKtTMNEP2X8Aw909H2rHpXGneYOxzO3hT8TpyvB5/dEEo9mBFCitGwoj1A==",
"dependencies": {
"jquery": "x.*"
}
},
"node_modules/semantic-ui-react": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/semantic-ui-react/-/semantic-ui-react-2.1.4.tgz",
"integrity": "sha512-7CxjBoFUfH7fUvtn+SPkkIocthUD9kV3niF1mUMa9TbeyPAf2brtRCZBlT2OpHaXmkscFzGjEfhbJo9gKfotzQ==",
"dependencies": {
"@babel/runtime": "^7.10.5",
"@fluentui/react-component-event-listener": "~0.63.0",
"@fluentui/react-component-ref": "~0.63.0",
"@popperjs/core": "^2.6.0",
"@semantic-ui-react/event-stack": "^3.1.3",
"clsx": "^1.1.1",
"keyboard-key": "^1.1.0",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"prop-types": "^15.7.2",
"react-is": "^16.8.6 || ^17.0.0 || ^18.0.0",
"react-popper": "^2.3.0",
"shallowequal": "^1.1.0"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -12699,6 +12824,11 @@
"node": ">=8"
}
},
"node_modules/shallowequal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
},
"node_modules/shasum": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz",
@@ -14243,6 +14373,14 @@
"node": ">=12.0.0"
}
},
"node_modules/warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/watchify": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/watchify/-/watchify-4.0.0.tgz",
@@ -16164,7 +16302,6 @@
"version": "7.20.13",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz",
"integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==",
"dev": true,
"requires": {
"regenerator-runtime": "^0.13.11"
}
@@ -16529,6 +16666,23 @@
"tslib": "^2.1.0"
}
},
"@fluentui/react-component-event-listener": {
"version": "0.63.1",
"resolved": "https://registry.npmjs.org/@fluentui/react-component-event-listener/-/react-component-event-listener-0.63.1.tgz",
"integrity": "sha512-gSMdOh6tI3IJKZFqxfQwbTpskpME0CvxdxGM2tdglmf6ZPVDi0L4+KKIm+2dN8nzb8Ya1A8ZT+Ddq0KmZtwVQg==",
"requires": {
"@babel/runtime": "^7.10.4"
}
},
"@fluentui/react-component-ref": {
"version": "0.63.1",
"resolved": "https://registry.npmjs.org/@fluentui/react-component-ref/-/react-component-ref-0.63.1.tgz",
"integrity": "sha512-8MkXX4+R3i80msdbD4rFpEB4WWq2UDvGwG386g3ckIWbekdvN9z2kWAd9OXhRGqB7QeOsoAGWocp6gAMCivRlw==",
"requires": {
"@babel/runtime": "^7.10.4",
"react-is": "^16.6.3"
}
},
"@fluentui/react-focus": {
"version": "8.8.12",
"resolved": "https://registry.npmjs.org/@fluentui/react-focus/-/react-focus-8.8.12.tgz",
@@ -16826,11 +16980,25 @@
"rimraf": "^3.0.2"
}
},
"@popperjs/core": {
"version": "2.11.6",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw=="
},
"@remix-run/router": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.3.0.tgz",
"integrity": "sha512-nwQoYb3m4DDpHTeOwpJEuDt8lWVcujhYYSFGLluC+9es2PyLjm+jjq3IeRBQbwBtPLJE/lkuHuGHr8uQLgmJRA=="
},
"@semantic-ui-react/event-stack": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/@semantic-ui-react/event-stack/-/event-stack-3.1.3.tgz",
"integrity": "sha512-FdTmJyWvJaYinHrKRsMLDrz4tTMGdFfds299Qory53hBugiDvGC0tEJf+cHsi5igDwWb/CLOgOiChInHwq8URQ==",
"requires": {
"exenv": "^1.2.2",
"prop-types": "^15.6.2"
}
},
"@sideway/address": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz",
@@ -18740,6 +18908,11 @@
"shallow-clone": "^3.0.0"
}
},
"clsx": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg=="
},
"coffeeify": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/coffeeify/-/coffeeify-3.0.1.tgz",
@@ -20157,6 +20330,11 @@
"pify": "^2.2.0"
}
},
"exenv": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
"integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw=="
},
"express": {
"version": "4.18.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
@@ -21624,6 +21802,11 @@
"@sideway/pinpoint": "^2.0.0"
}
},
"jquery": {
"version": "3.6.3",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.3.tgz",
"integrity": "sha512-bZ5Sy3YzKo9Fyc8wH2iIQK4JImJ6R0GWI9kL1/k7Z91ZBNgkRXE6U0JfHIizZbort8ZunhSI3jw9I6253ahKfg=="
},
"js-base64": {
"version": "2.6.4",
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz",
@@ -21752,6 +21935,11 @@
"verror": "1.10.0"
}
},
"keyboard-key": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/keyboard-key/-/keyboard-key-1.1.0.tgz",
"integrity": "sha512-qkBzPTi3rlAKvX7k0/ub44sqOfXeLc/jcnGGmj5c7BJpU8eDrEVPyhCvNYAaoubbsLm9uGWwQJO1ytQK1a9/dQ=="
},
"kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@@ -22058,8 +22246,12 @@
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"lodash.clonedeep": {
"version": "4.5.0",
@@ -23869,6 +24061,11 @@
"scheduler": "^0.23.0"
}
},
"react-fast-compare": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
},
"react-grid-system": {
"version": "8.1.8",
"resolved": "https://registry.npmjs.org/react-grid-system/-/react-grid-system-8.1.8.tgz",
@@ -23882,6 +24079,15 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"react-popper": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz",
"integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==",
"requires": {
"react-fast-compare": "^3.0.1",
"warning": "^4.0.2"
}
},
"react-router": {
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.7.0.tgz",
@@ -24049,8 +24255,7 @@
"regenerator-runtime": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
"dev": true
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
},
"regenerator-transform": {
"version": "0.15.1",
@@ -24417,6 +24622,34 @@
"node-forge": "^1"
}
},
"semantic-ui-css": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/semantic-ui-css/-/semantic-ui-css-2.5.0.tgz",
"integrity": "sha512-jIWn3WXXE2uSaWCcB+gVJVRG3masIKtTMNEP2X8Aw909H2rHpXGneYOxzO3hT8TpyvB5/dEEo9mBFCitGwoj1A==",
"requires": {
"jquery": "x.*"
}
},
"semantic-ui-react": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/semantic-ui-react/-/semantic-ui-react-2.1.4.tgz",
"integrity": "sha512-7CxjBoFUfH7fUvtn+SPkkIocthUD9kV3niF1mUMa9TbeyPAf2brtRCZBlT2OpHaXmkscFzGjEfhbJo9gKfotzQ==",
"requires": {
"@babel/runtime": "^7.10.5",
"@fluentui/react-component-event-listener": "~0.63.0",
"@fluentui/react-component-ref": "~0.63.0",
"@popperjs/core": "^2.6.0",
"@semantic-ui-react/event-stack": "^3.1.3",
"clsx": "^1.1.1",
"keyboard-key": "^1.1.0",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"prop-types": "^15.7.2",
"react-is": "^16.8.6 || ^17.0.0 || ^18.0.0",
"react-popper": "^2.3.0",
"shallowequal": "^1.1.0"
}
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -24589,6 +24822,11 @@
"kind-of": "^6.0.2"
}
},
"shallowequal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
},
"shasum": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz",
@@ -25772,6 +26010,14 @@
"rxjs": "^7.8.0"
}
},
"warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"requires": {
"loose-envify": "^1.0.0"
}
},
"watchify": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/watchify/-/watchify-4.0.0.tgz",

View File

@@ -69,6 +69,8 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-grid-system": "^8.1.6",
"react-router-dom": "^6.6.1"
"react-router-dom": "^6.6.1",
"semantic-ui-css": "^2.5.0",
"semantic-ui-react": "^2.1.4"
}
}

View File

@@ -0,0 +1,3 @@
.content {
padding: 30px;
}

View File

@@ -1,38 +1,44 @@
import React from 'react';
import { Routes, Route, useLocation } from 'react-router-dom';
import { Container, Row, Col } from 'react-grid-system';
import styles from './App.module.scss'
import { Routes, Route } from 'react-router-dom';
import { initializeIcons } from '@fluentui/font-icons-mdl2';
import Menu from '../menu/Menu';
import { Grid, Sidebar } from 'semantic-ui-react';
import Header from '../header/Header';
import Footer from '../footer/Footer';
import Navigation from '../navigation/Navigation';
import Teams from '../teams/Teams';
import Venues from '../venues/Venues';
import { useSidebarContext } from '../../hooks/sidebarContext/UseSidebarContext';
initializeIcons();
const App: React.FC<unknown> = () => {
const location = useLocation();
const sidebarContext = useSidebarContext();
return (
<Container fluid={true} style={{ padding: '0' }}>
<Row>
<Col sm={6}>Goodbye!</Col>
<Col sm={6}>Hello!</Col>
</Row>
<Row>
<Col sm={3}>
<Menu
selectedKey={
location.pathname === '/'
? 'home'
: location.pathname.replace('/', '')
}
/>
</Col>
<Col>
<Routes>
<Route path='venues' element={<Venues />} />
</Routes>
</Col>
</Row>
</Container>
<Sidebar.Pushable>
<Sidebar.Pusher dimmed={sidebarContext.state.sidebar?.visible}>
<Header />
<Grid columns={16}>
<Grid.Row>
<Grid.Column width={3}>
<Navigation />
</Grid.Column>
<Grid.Column width={12}>
<div className={styles.content}>
<Routes>
<Route path='teams' element={<Teams />} />
</Routes>
<Routes>
<Route path='venues' element={<Venues />} />
</Routes>
</div>
</Grid.Column>
</Grid.Row>
</Grid>
<Footer />
</Sidebar.Pusher>
</Sidebar.Pushable>
);
};

View File

@@ -0,0 +1,4 @@
.siteFooter {
background-color: #e0e1e2;
height: 150px;
}

View File

@@ -0,0 +1,22 @@
import React from 'react';
import styles from './Footer.module.scss';
import { Grid } from 'semantic-ui-react';
const Footer: React.FC<unknown> = () => {
return (
<div className={styles.siteFooter}>
<Grid columns={16}>
<Grid.Row>
<Grid.Column width={8}>
Hello!
</Grid.Column>
<Grid.Column width={8} textAlign='right'>
Goodbye!
</Grid.Column>
</Grid.Row>
</Grid>
</div>
)
}
export default Footer;

View File

@@ -0,0 +1,4 @@
.siteHeader {
background-color: #e0e1e2;
height: 100px;
}

View File

@@ -0,0 +1,22 @@
import React from 'react';
import styles from './Header.module.scss';
import { Grid, Icon } from 'semantic-ui-react';
const Header: React.FC<unknown> = () => {
return (
<div className={styles.siteHeader}>
<Grid columns={16}>
<Grid.Row>
<Grid.Column width={8}>
<Icon name='baseball ball' size='huge' />
</Grid.Column>
<Grid.Column width={8} textAlign='right'>
Goodbye!
</Grid.Column>
</Grid.Row>
</Grid>
</div>
)
}
export default Header;

View File

@@ -1,3 +0,0 @@
export interface IMenuProps {
selectedKey: string;
}

View File

@@ -1,29 +0,0 @@
import React from 'react';
import { IMenuProps } from './IMenuProps';
import {
Nav,
INavLinkGroup
} from '@fluentui/react/lib/Nav';
const Menu: React.FC<IMenuProps> = (props: IMenuProps) => {
const navLinkGroups: INavLinkGroup[] = [
{
links: [
{
name: 'Home',
url: 'http://localhost:3000',
key: 'home'
},
{
name: 'Venues',
url: 'http://localhost:3000/venues',
key: 'venues'
}
]
}
];
return <Nav groups={navLinkGroups} selectedKey={props.selectedKey} />;
};
export default Menu;

View File

@@ -0,0 +1,3 @@
export interface INavigationState {
activeLink: string;
}

View File

@@ -0,0 +1,75 @@
import React, { Component, useEffect, useReducer } from 'react';
// import { IMenuProps } from './IMenuProps';
// import {
// Nav,
// INavLinkGroup
// } from '@fluentui/react/lib/Nav';
import { Menu } from 'semantic-ui-react';
import { initialState, reducer } from './reducer';
import { useLocation, useNavigate } from 'react-router-dom';
// const Menu: React.FC<IMenuProps> = (props: IMenuProps) => {
// const navLinkGroups: INavLinkGroup[] = [
// {
// links: [
// {
// name: 'Home',
// url: 'http://localhost:3000',
// key: 'home'
// },
// {
// name: 'Venues',
// url: 'http://localhost:3000/venues',
// key: 'venues'
// }
// ]
// }
// ];
// return <Nav groups={navLinkGroups} selectedKey={props.selectedKey} />;
// };
// export default Menu;
const Navigation: React.FC<unknown> = (props) => {
const [state, dispatch] = useReducer(reducer, initialState);
const location = useLocation();
const navigate = useNavigate();
const menuItems: string[] = [
'gameday',
'teams',
'venues'
];
const onMenuItemClicked = (event: any, { name }: any) => {
navigate(name);
dispatch({ type: 'SET_ACTIVE_MENU_ITEM', payload: name });
}
useEffect(() => {
const activeLink: string = location.pathname === '/' ? 'home' : location.pathname.replace('/', '')
dispatch({ type: 'SET_ACTIVE_MENU_ITEM', payload: activeLink });
}, [])
return (
<Menu
pointing
secondary
vertical
>
{menuItems.map((menuItem: string) => {
return (
<Menu.Item
key={menuItem}
name={menuItem}
active={state.activeLink === menuItem}
onClick={onMenuItemClicked}
/>
)
})}
</Menu>
)
}
export default Navigation;

View File

@@ -0,0 +1,19 @@
import { INavigationState } from "./INavigationState"
export type Action =
| { type: 'SET_ACTIVE_MENU_ITEM', payload: string }
export const initialState: INavigationState = {
activeLink: ''
}
export const reducer = (state: INavigationState, action: Action): INavigationState => {
switch (action.type) {
case 'SET_ACTIVE_MENU_ITEM': {
return {
...state,
activeLink: action.payload
}
}
}
}

View File

@@ -0,0 +1,13 @@
import { ICommandBarItemProps } from "@fluentui/react/lib/CommandBar";
import { ITeam } from '../../models/ITeam';
export interface ITeamsState {
items: ITeam[];
totalItemCount: number | null;
totalPageCount: number | null;
currentPageNumber: number;
pageSize: number;
selectedItems: ITeam[];
commandBarItems: ICommandBarItemProps[];
isPanelOpen: boolean;
}

View File

@@ -0,0 +1,135 @@
import React, { SyntheticEvent, useEffect, useReducer } from 'react';
import { useQuery } from '@apollo/client';
import { MessageBar, MessageBarType } from '@fluentui/react/lib/MessageBar';
import { initialState, reducer } from './reducer'
import { useAppContext } from '../../hooks/appContext/UseAppContext';
import { useSidebarContext } from '../../hooks/sidebarContext/UseSidebarContext';
import { GET_TEAMS } from '../../constants/graphQL';
import { INotification } from '../../models/INotification';
import { Button, Grid, Header, Icon, Loader, Pagination, Table } from 'semantic-ui-react'
const Teams: React.FC<unknown> = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const appContext = useAppContext();
const sidebarContext = useSidebarContext();
const currentPageNumber = state.currentPageNumber;
const pageSize = state.pageSize;
const { data, loading, error, refetch } = useQuery(GET_TEAMS, {
variables: {
pageNumber: currentPageNumber,
pageSize: pageSize
}
})
const columns: string[] = [
'Name',
''
]
const onPageChange = (event: SyntheticEvent, data: any) => {
const newCurrentPage: number = data.activePage;
dispatch({ type: 'SET_CURRENT_PAGE_NUMBER', payload: newCurrentPage });
}
useEffect(() => {
if (data) {
dispatch({
type: 'SET_ITEMS',
payload: {
items: data.teams.results,
totalItemCount: data.teams.totalItemCount,
totalPageCount: data.teams.totalPageCount
}
})
}
}, [data])
useEffect(() => {
refetch({
pageNumber: currentPageNumber,
pageSize: pageSize
})
}, [currentPageNumber])
return (
<Grid columns={1}>
<Grid.Row>
<Header as='h1'>
Teams
</Header>
</Grid.Row>
{appContext.state.notification?.isVisible && (
<Grid.Row>
<Grid.Column>
</Grid.Column>
</Grid.Row>
)}
<Grid.Row>
<Grid.Column>
{loading && (
<Loader size='massive' active={loading}>Loading...</Loader>
)}
{!loading &&
<Table selectable>
<Table.Header>
<Table.Row>
{columns.map((column: string) => {
return (
<Table.HeaderCell>
{column}
</Table.HeaderCell>
)
})}
</Table.Row>
</Table.Header>
<Table.Body>
{state.items.map((item) => {
return (
<Table.Row
key={item.id}
>
<Table.Cell>
{item.name}
</Table.Cell>
<Table.Cell textAlign='right'>
<Button
basic
icon
// onClick={() => onDetails(item.id)}
>
<Icon name='info circle' />
</Button>
</Table.Cell>
</Table.Row>
)
})}
</Table.Body>
<Table.Footer>
<Table.Row>
<Table.HeaderCell colSpan='2'>
<Grid columns={1}>
<Grid.Row>
<Grid.Column textAlign='right'>
<Pagination
totalPages={data.teams.totalPageCount}
activePage={state.currentPageNumber}
onPageChange={onPageChange}
size='mini'
/>
</Grid.Column>
</Grid.Row>
</Grid>
</Table.HeaderCell>
</Table.Row>
</Table.Footer>
</Table>
}
</Grid.Column>
</Grid.Row>
</Grid>
)
}
export default Teams;

View File

@@ -0,0 +1,73 @@
import { ITeamsState } from './ITeamsState';
import { ITeam } from '../../models/ITeam';
import { ICommandBarItemProps } from '@fluentui/react/lib/CommandBar';
import { IObjectWithKey } from '@fluentui/react';
export type Action =
| {
type: 'SET_ITEMS';
payload: {
items: ITeam[];
totalItemCount: number;
totalPageCount: number;
};
}
| { type: 'SET_CURRENT_PAGE_NUMBER'; payload: number }
| { type: 'SET_PAGE_SIZE'; payload: number }
| { type: 'SET_SELECTED_ITEM'; payload: IObjectWithKey[] }
| { type: 'SET_COMMAND_BAR_ITEMS'; payload: ICommandBarItemProps[] }
| { type: 'SET_IS_PANEL_OPEN'; payload: boolean };
export const initialState: ITeamsState = {
items: [],
totalItemCount: null,
totalPageCount: null,
currentPageNumber: 1,
pageSize: 10,
selectedItems: [],
commandBarItems: [],
isPanelOpen: false
}
export const reducer = (state: ITeamsState, action: Action): ITeamsState => {
switch (action.type) {
case 'SET_ITEMS': {
return {
...state,
items: action.payload.items,
totalItemCount: action.payload.totalItemCount,
totalPageCount: action.payload.totalPageCount
};
}
case 'SET_CURRENT_PAGE_NUMBER': {
return {
...state,
currentPageNumber: action.payload
};
}
case 'SET_PAGE_SIZE': {
return {
...state,
pageSize: action.payload
};
}
case 'SET_SELECTED_ITEM': {
return {
...state,
selectedItems: <ITeam[]>action.payload
};
}
case 'SET_COMMAND_BAR_ITEMS': {
return {
...state,
commandBarItems: action.payload
};
}
case 'SET_IS_PANEL_OPEN': {
return {
...state,
isPanelOpen: action.payload
};
}
}
}

View File

@@ -0,0 +1,3 @@
export interface IVenueDetailsProps {
venueId: number;
}

View File

@@ -0,0 +1,33 @@
import React, { useEffect } from 'react';
import { IVenueDetailsProps } from './IVenueDetailsProps';
import { Grid, Header } from 'semantic-ui-react';
import { useQuery } from '@apollo/client';
import { GET_VENUE_BY_ID } from '../../constants/graphQL';
const VenueDetails: React.FC<IVenueDetailsProps> = ({ venueId }: IVenueDetailsProps) => {
const { data, loading, error } = useQuery(GET_VENUE_BY_ID, {
variables: {
id: venueId
}
});
return (
<Grid>
<Grid.Row>
<Header as='h2'>
Venue
</Header>
</Grid.Row>
<Grid.Row>
{data &&
<ul>
<li>{data.venueById.results.name}</li>
<li>{data.venueById.results.id}</li>
</ul>
}
</Grid.Row>
</Grid>
)
}
export default VenueDetails;

View File

@@ -1,5 +1,5 @@
import React from 'react';
import AppContextProvider from '../../context/AppContextProvider';
import AppContextProvider from '../../context/app/AppContextProvider';
import Venues from './Venues';
import { MockedProvider } from '@apollo/client/testing';
import { GET_VENUES } from '../../constants/graphQL';

View File

@@ -1,28 +1,18 @@
import React, { useEffect, useReducer } from 'react';
import React, { SyntheticEvent, useEffect, useReducer } from 'react';
import { useQuery } from '@apollo/client';
import {
CommandBar,
ICommandBarItemProps
} from '@fluentui/react/lib/CommandBar';
import {
DetailsList,
IColumn,
Selection,
SelectionMode
} from '@fluentui/react/lib/DetailsList';
import { MessageBar, MessageBarType } from '@fluentui/react/lib/MessageBar';
import { Panel } from '@fluentui/react/lib/Panel';
import Paginator from '../paginator/Paginator';
import { Spinner, SpinnerSize } from '@fluentui/react/lib/Spinner';
import { initialState, reducer } from './reducer';
import { useAppContext } from '../../hooks/appContext/UseAppContext';
import { useSidebarContext } from '../../hooks/sidebarContext/UseSidebarContext';
import { GET_VENUES } from '../../constants/graphQL';
import { INotification } from '../../models/INotification';
import { IVenue } from '../../models/IVenue';
import { Button, Grid, Header, Icon, Loader, Pagination, Sidebar, Table } from 'semantic-ui-react';
import VenueDetails from '../venueDetails/VenueDetails';
const Venues: React.FC<unknown> = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const appContext = useAppContext();
const sidebarContext = useSidebarContext();
const currentPageNumber = state.currentPageNumber;
const pageSize = state.pageSize;
const { data, loading, error, refetch } = useQuery(GET_VENUES, {
@@ -31,24 +21,11 @@ const Venues: React.FC<unknown> = () => {
pageSize: pageSize
}
});
const columns: IColumn[] = [
{
key: 'name',
name: 'Name',
fieldName: 'name',
minWidth: 100,
isResizable: true
}
];
const selection: Selection = new Selection({
onSelectionChanged: () =>
dispatch({ type: 'SET_SELECTED_ITEM', payload: selection.getSelection() })
});
const onIsPanelOpen = () => {
dispatch({ type: 'SET_IS_PANEL_OPEN', payload: !state.isPanelOpen });
};
const columns: string[] = [
'Name',
''
]
const onDismissMessageBar = () => {
const notification: INotification = {
@@ -59,32 +36,21 @@ const Venues: React.FC<unknown> = () => {
appContext.dispatch({ type: 'SET_NOTIFICATION', payload: notification });
};
const onPageChange = (newCurrentPage: number) => {
console.log(newCurrentPage);
const onPageChange = (event: SyntheticEvent, data: any) => {
const newCurrentPage: number = data.activePage;
dispatch({ type: 'SET_CURRENT_PAGE_NUMBER', payload: newCurrentPage });
refetch({
pageNumber: newCurrentPage,
pageSize: pageSize
});
};
useEffect(() => {
dispatch({
type: 'SET_COMMAND_BAR_ITEMS',
payload: [
{
key: 'openItem',
text: 'Open',
iconProps: { iconName: 'OpenPane' },
onClick: onIsPanelOpen,
disabled: true
}
]
});
}, []);
const onDetails = (id: number) => {
sidebarContext.dispatch({ type: 'SET_SIDEBAR', payload: { sidebar: { visible: true, animation: 'overlay', width: 'very wide', direction: 'right' }, content: <VenueDetails venueId={id} />}})
}
useEffect(() => {
console.log(sidebarContext)
}, [sidebarContext])
useEffect(() => {
console.log(JSON.stringify(data));
if (data) {
dispatch({
type: 'SET_ITEMS',
@@ -98,6 +64,7 @@ const Venues: React.FC<unknown> = () => {
}, [data]);
useEffect(() => {
console.log(error);
const notification: INotification = {
messageBarType: MessageBarType.error,
message: error?.message,
@@ -109,68 +76,97 @@ const Venues: React.FC<unknown> = () => {
}, [error]);
useEffect(() => {
if (state.selectedItems.length > 0 && state.commandBarItems.length > 0) {
const newCommandBarItems = state.commandBarItems.map(
(commandBarItem: ICommandBarItemProps) => {
return {
...commandBarItem,
disabled: false
};
}
);
dispatch({ type: 'SET_COMMAND_BAR_ITEMS', payload: newCommandBarItems });
}
}, [state.selectedItems]);
refetch({
pageNumber: currentPageNumber,
pageSize: pageSize
});
}, [currentPageNumber])
return (
<div>
{loading && <Spinner size={SpinnerSize.large} />}
{!loading && (
<React.Fragment>
{appContext.state.notification?.isVisible && (
<MessageBar
messageBarType={appContext.state.notification?.messageBarType}
isMultiline={appContext.state.notification?.isMultiline}
onDismiss={onDismissMessageBar}
>
{appContext.state.notification?.message}
</MessageBar>
)}
<CommandBar items={state.commandBarItems} />
<DetailsList
columns={columns}
items={state.items}
selection={selection}
selectionMode={SelectionMode.single}
selectionPreservedOnEmptyClick={true}
/>
<Paginator
totalPageCount={data.venues.totalPageCount}
currentPage={state.currentPageNumber}
pageSize={state.pageSize}
onPageChange={onPageChange}
/>
<Panel
headerText='Venue'
isOpen={state.isPanelOpen}
onDismiss={onIsPanelOpen}
>
{state.selectedItems.length > 0 &&
state.selectedItems.map((item: IVenue) => {
return (
<React.Fragment>
<p>{item.name}</p>
<p>{item.id}</p>
<p>{item.link}</p>
<p>{item.active}</p>
</React.Fragment>
);
})}
</Panel>
</React.Fragment>
<Grid columns={1}>
<Grid.Row>
<Header as='h1'>
Venues
</Header>
</Grid.Row>
{appContext.state.notification?.isVisible && (
<Grid.Row>
<Grid.Column>
<MessageBar
messageBarType={appContext.state.notification?.messageBarType}
isMultiline={appContext.state.notification?.isMultiline}
onDismiss={onDismissMessageBar}
>
{appContext.state.notification?.message}
</MessageBar>
</Grid.Column>
</Grid.Row>
)}
</div>
<Grid.Row>
<Grid.Column>
{loading && (
<Loader size='massive' active={loading}>Loading...</Loader>
)}
{!loading &&
<Table selectable>
<Table.Header>
<Table.Row>
{columns.map((column: string) => {
return (
<Table.HeaderCell>
{column}
</Table.HeaderCell>
)
})}
</Table.Row>
</Table.Header>
<Table.Body>
{state.items.map((item) => {
return (
<Table.Row
key={item.id}
>
<Table.Cell>
{item.name}
</Table.Cell>
<Table.Cell textAlign='right'>
<Button
basic
icon
onClick={() => onDetails(item.id)}
>
<Icon name='info circle' />
</Button>
</Table.Cell>
</Table.Row>
)
})}
</Table.Body>
<Table.Footer>
<Table.Row>
<Table.HeaderCell colSpan='2'>
<Grid columns={1}>
<Grid.Row>
<Grid.Column
textAlign='right'
>
<Pagination
totalPages={data?.venues?.totalPageCount}
activePage={state.currentPageNumber}
onPageChange={onPageChange}
size='mini'
/>
</Grid.Column>
</Grid.Row>
</Grid>
</Table.HeaderCell>
</Table.Row>
</Table.Footer>
</Table>
}
</Grid.Column>
</Grid.Row>
</Grid>
);
};

View File

@@ -1,20 +1,72 @@
import { gql } from '@apollo/client';
export const GET_VENUES = gql`
query GetVenues($pageNumber: Int, $pageSize: Int) {
venues(pageNumber: $pageNumber, pageSize: $pageSize) {
currentPage
errors
message
export const GET_TEAMS = gql`
query GetTeams($pageNumber: Int!, $pageSize: Int!) {
teams(pageNumber: $pageNumber, pageSize: $pageSize) {
pageSize
succeeded
totalItemCount
message
errors
currentPage
totalPageCount
totalItemCount
succeeded
results {
active
id
link
name
link
id
active
}
}
}
`;
export const GET_TEAM = gql`
query GetTeam($id: Int!) {
teamById(id: $id) {
message
errors
succeeded
results {
name
link
id
active
}
}
}
`
export const GET_VENUES = gql`
query GetVenues($pageNumber: Int!, $pageSize: Int!) {
venues(pageNumber: $pageNumber, pageSize: $pageSize) {
pageSize
message
errors
currentPage
totalPageCount
totalItemCount
succeeded
results {
name
link
id
active
}
}
}
`;
export const GET_VENUE_BY_ID = gql`
query GetVenue($id: Int!) {
venueById(id: $id) {
message
errors
succeeded
results {
name
link
id
active
}
}
}

View File

@@ -1,5 +0,0 @@
import { INotification } from '../models/INotification';
export interface IAppContextState {
notification: INotification | undefined;
}

View File

@@ -0,0 +1,7 @@
import { ISidebar } from 'src/models/ISidebar';
import { INotification } from '../../models/INotification';
export interface IAppContextState {
notification: INotification | undefined;
isSidebarVisible: boolean;
}

View File

@@ -1,8 +1,10 @@
import { MessageBarType } from '@fluentui/react';
import { INotification } from '../models/INotification';
import { INotification } from '../../models/INotification';
import { IAppContextState } from './IAppContextState';
export type Action = { type: 'SET_NOTIFICATION'; payload: INotification };
export type Action =
| { type: 'SET_NOTIFICATION'; payload: INotification }
| { type: 'SET_IS_SIDEBAR_VISIBLE', payload: boolean };
export const initialState: IAppContextState = {
notification: {
@@ -10,7 +12,8 @@ export const initialState: IAppContextState = {
message: 'Blah blah blah',
isMultiline: false,
isVisible: true
}
},
isSidebarVisible: false
};
export const reducer = (
@@ -24,5 +27,14 @@ export const reducer = (
notification: action.payload
};
}
case 'SET_IS_SIDEBAR_VISIBLE': {
return {
...state,
isSidebarVisible: action.payload
}
}
default: {
return state;
}
}
};

View File

@@ -0,0 +1,8 @@
import React from 'react';
import { ISidebarContextState } from './ISidebarContextState';
import { Action } from './reducer';
export interface ISidebarContextProps {
state: ISidebarContextState;
dispatch: React.Dispatch<Action>;
}

View File

@@ -0,0 +1,5 @@
import React from "react";
export interface ISidebarContextProviderProps {
children: React.ReactNode;
}

View File

@@ -0,0 +1,8 @@
import React from 'react';
import { SidebarProps } from 'semantic-ui-react';
export interface ISidebarContextState {
content: React.ReactNode;
sidebar: SidebarProps;
title: string;
}

View File

@@ -0,0 +1,4 @@
.sidebar {
background-color: #FFFFFF;
padding: 30px;
}

View File

@@ -0,0 +1,4 @@
import { Context, createContext } from 'react';
import { ISidebarContextProps } from './ISidebarContextProps';
export const SidebarContext: Context<ISidebarContextProps> = createContext<ISidebarContextProps>({} as ISidebarContextProps);

View File

@@ -0,0 +1,53 @@
import React, { useEffect, useMemo, useReducer } from 'react';
import styles from './Sidebar.module.scss';
import { SidebarContext } from "./SidebarContext";
import { ISidebarContextProps } from './ISidebarContextProps';
import { ISidebarContextProviderProps } from './ISidebarContextProviderProps';
import { initialState, reducer } from './reducer';
import { Button, Grid, Icon, Sidebar } from 'semantic-ui-react';
const SidebarContextProvider: React.FC<ISidebarContextProviderProps> = (props: ISidebarContextProviderProps) => {
const [state, dispatch] = useReducer(reducer, initialState);
const contextValue: ISidebarContextProps = useMemo(() => {
return {
state,
dispatch
}
}, [state, dispatch]);
const onCloseSidebar = () => {
dispatch({ type: 'SET_SIDEBAR_VISIBLE', payload: !state.sidebar?.visible });
}
return (
<React.Fragment>
<Sidebar
className={styles.sidebar}
{...state.sidebar}
>
<Grid columns={1}>
<Grid.Row>
<Grid.Column
textAlign='right'
>
<Button>
<Icon name='close' size='large' onClick={onCloseSidebar} />
</Button>
</Grid.Column>
</Grid.Row>
<Grid.Row>
{state.content}
</Grid.Row>
<Grid.Row>
<Button onClick={onCloseSidebar}>Close</Button>
</Grid.Row>
</Grid>
</Sidebar>
<SidebarContext.Provider value={contextValue}>
{props.children}
</SidebarContext.Provider>
</React.Fragment>
)
}
export default SidebarContextProvider;

View File

@@ -0,0 +1,52 @@
import React from "react";
import { SidebarProps } from "semantic-ui-react";
import { ISidebarContextState } from "./ISidebarContextState";
export type Action =
| { type: 'SET_SIDEBAR', payload: { sidebar: SidebarProps, content: React.ReactNode }}
| { type: 'SET_SIDEBAR_PROPS', payload: SidebarProps}
| { type: 'SET_SIDEBAR_CONTENT', payload: React.ReactNode }
| { type: 'SET_SIDEBAR_VISIBLE', payload: boolean }
export const initialState: ISidebarContextState = {
sidebar: {
visible: false
},
content: undefined
}
export const reducer = (state: ISidebarContextState, action: Action): ISidebarContextState => {
switch (action.type) {
case 'SET_SIDEBAR': {
return {
...state,
sidebar: action.payload.sidebar,
content: action.payload.content
}
}
case 'SET_SIDEBAR_PROPS': {
return {
...state,
sidebar: action.payload
}
}
case 'SET_SIDEBAR_CONTENT': {
return {
...state,
content: action.payload
}
}
case 'SET_SIDEBAR_VISIBLE': {
return {
...state,
sidebar: {
...state.sidebar,
visible: action.payload
}
}
}
default: {
return state;
}
}
}

View File

@@ -1,5 +1,5 @@
import { useContext } from 'react';
import { AppContext } from '../../context/AppContext';
import { AppContext } from '../../context/app/AppContext';
export const useAppContext = () => {
const { state, dispatch } = useContext(AppContext);

View File

@@ -0,0 +1,11 @@
import { useContext } from 'react';
import { SidebarContext } from '../../context/sidebar/SidebarContext';
export const useSidebarContext = () => {
const { state, dispatch } = useContext(SidebarContext);
return {
state,
dispatch
}
}

View File

@@ -2,11 +2,13 @@ import React from 'react';
import { createRoot, Root } from 'react-dom/client';
import { BrowserRouter as Router } from 'react-router-dom';
import { ApolloClient, InMemoryCache, ApolloProvider, NormalizedCacheObject } from '@apollo/client';
import AppContextProvider from './context/AppContextProvider';
import AppContextProvider from './context/app/AppContextProvider';
import App from './components/app/App';
import 'semantic-ui-css/semantic.min.css';
import SidebarContextProvider from './context/sidebar/SidebarContextProvider';
const client: ApolloClient<NormalizedCacheObject> = new ApolloClient({
uri: 'http://localhost:8080/v1/graphql',
uri: 'http://localhost:8081/graphql',
cache: new InMemoryCache()
});
@@ -14,12 +16,14 @@ const container = document.getElementById('app-root') as HTMLElement;
const root: Root = createRoot(container);
root.render(
<React.StrictMode>
<AppContextProvider>
<ApolloProvider client={client}>
<Router>
<App />
</Router>
</ApolloProvider>
</AppContextProvider>
<ApolloProvider client={client}>
<AppContextProvider>
<SidebarContextProvider>
<Router>
<App />
</Router>
</SidebarContextProvider>
</AppContextProvider>
</ApolloProvider>
</React.StrictMode>
);

View File

@@ -0,0 +1,6 @@
import React from "react";
export interface ISidebar {
component: React.ReactNode | undefined;
isVisible: boolean;
}

23
app/src/models/ITeam.ts Normal file
View File

@@ -0,0 +1,23 @@
export interface ITeam {
id: number;
name: string;
abbreviation: string;
active: string;
allStarStatus: string;
clubName: string;
divisionId: number;
fileCode: string;
firstYearOfPlay: number;
franchiseName: string;
leagueId: number;
link: string;
locationName: string;
season: string;
shortName: string;
springLeagueId: number;
sprintVenueId: number;
sportId: number;
teamCode: string;
teamName: string;
venueId: number;
}

View File

@@ -20,10 +20,14 @@ module.exports = {
},
use: 'babel-loader',
},
{
test: /\.(css)$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
{
test: /\.(s(a|c)ss)$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
}
},
]
},
devServer: {