diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index f0927c2a6..7f4e34c72 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -797,6 +797,7 @@ importers: eslint-plugin-react-hooks: ~4.6.0 eslint-plugin-unused-imports: ~2.0.0 formik: ^2.1.5 + jsdom: ~22.1.0 luxon: ^2.0.5 postcss: ~8.4.13 react: ^16.13.1 @@ -849,6 +850,7 @@ importers: eslint-plugin-react-hooks: 4.6.0_eslint@8.41.0 eslint-plugin-unused-imports: 2.0.0_2906aacee5c155bfb25e5c02bfd525c7 formik: 2.2.9_react@16.14.0 + jsdom: 22.1.0 postcss: 8.4.23 react: 16.14.0 react-dom: 16.14.0_react@16.14.0 @@ -858,7 +860,7 @@ importers: typescript: 5.0.4 uuid: 8.3.2 vite: 4.3.9 - vitest: 0.31.4_@vitest+ui@0.31.4 + vitest: 0.31.4_@vitest+ui@0.31.4+jsdom@22.1.0 packages: @@ -5480,7 +5482,6 @@ packages: /@tootallnate/once/2.0.0: resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} - optional: true /@tsconfig/node10/1.0.9: resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} @@ -6263,7 +6264,7 @@ packages: pathe: 1.1.0 picocolors: 1.0.0 sirv: 2.0.3 - vitest: 0.31.4_@vitest+ui@0.31.4 + vitest: 0.31.4_@vitest+ui@0.31.4+jsdom@22.1.0 /@vitest/utils/0.31.4: resolution: {integrity: sha512-DobZbHacWznoGUfYU8XDPY78UubJxXfMNY1+SUdOp1NsI34eopSA6aZMeaGu10waSOeYwE8lxrd/pLfT0RMxjQ==} @@ -8086,6 +8087,13 @@ packages: cssom: 0.3.8 dev: true + /cssstyle/3.0.0: + resolution: {integrity: sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==} + engines: {node: '>=14'} + dependencies: + rrweb-cssom: 0.6.0 + dev: true + /csstype/3.1.2: resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} @@ -8190,6 +8198,15 @@ packages: whatwg-url: 8.7.0 dev: true + /data-urls/4.0.0: + resolution: {integrity: sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==} + engines: {node: '>=14'} + dependencies: + abab: 2.0.6 + whatwg-mimetype: 3.0.0 + whatwg-url: 12.0.1 + dev: true + /date-fns/1.30.1: resolution: {integrity: sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==} dev: true @@ -8597,6 +8614,13 @@ packages: webidl-conversions: 5.0.0 dev: true + /domexception/4.0.0: + resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} + engines: {node: '>=12'} + dependencies: + webidl-conversions: 7.0.0 + dev: true + /domhandler/5.0.3: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} @@ -10869,6 +10893,13 @@ packages: whatwg-encoding: 1.0.5 dev: true + /html-encoding-sniffer/3.0.0: + resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} + engines: {node: '>=12'} + dependencies: + whatwg-encoding: 2.0.0 + dev: true + /html-escaper/2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -10939,7 +10970,6 @@ packages: debug: 4.3.4 transitivePeerDependencies: - supports-color - optional: true /http-signature/1.2.0: resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} @@ -12322,6 +12352,44 @@ packages: - utf-8-validate dev: true + /jsdom/22.1.0: + resolution: {integrity: sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==} + engines: {node: '>=16'} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + dependencies: + abab: 2.0.6 + cssstyle: 3.0.0 + data-urls: 4.0.0 + decimal.js: 10.4.3 + domexception: 4.0.0 + form-data: 4.0.0 + html-encoding-sniffer: 3.0.0 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.4 + parse5: 7.1.2 + rrweb-cssom: 0.6.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.2 + w3c-xmlserializer: 4.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 2.0.0 + whatwg-mimetype: 3.0.0 + whatwg-url: 12.0.1 + ws: 8.13.0 + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + /jsesc/0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true @@ -14455,6 +14523,12 @@ packages: resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} dev: true + /parse5/7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.5.0 + dev: true + /parseley/0.11.0: resolution: {integrity: sha512-VfcwXlBWgTF+unPcr7yu3HSSA6QUdDaDnrHcytVfj5Z8azAyKBDrYnSIfeSxlrEayndNcLmrXzg+Vxbo6DWRXQ==} dependencies: @@ -15721,6 +15795,10 @@ packages: setprototypeof: 1.2.0 utils-merge: 1.0.1 + /rrweb-cssom/0.6.0: + resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} + dev: true + /run-applescript/5.0.0: resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==} engines: {node: '>=12'} @@ -15802,6 +15880,13 @@ packages: xmlchars: 2.2.0 dev: true + /saxes/6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + dependencies: + xmlchars: 2.2.0 + dev: true + /scheduler/0.19.1: resolution: {integrity: sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==} dependencies: @@ -16892,6 +16977,13 @@ packages: punycode: 2.3.0 dev: true + /tr46/4.1.1: + resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==} + engines: {node: '>=14'} + dependencies: + punycode: 2.3.0 + dev: true + /tree-kill/1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -17684,6 +17776,73 @@ packages: - terser dev: true + /vitest/0.31.4_@vitest+ui@0.31.4+jsdom@22.1.0: + resolution: {integrity: sha512-GoV0VQPmWrUFOZSg3RpQAPN+LPmHg2/gxlMNJlyxJihkz6qReHDV6b0pPDcqFLNEPya4tWJ1pgwUNP9MLmUfvQ==} + engines: {node: '>=v14.18.0'} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@vitest/browser': '*' + '@vitest/ui': '*' + happy-dom: '*' + jsdom: '*' + playwright: '*' + safaridriver: '*' + webdriverio: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + playwright: + optional: true + safaridriver: + optional: true + webdriverio: + optional: true + dependencies: + '@types/chai': 4.3.5 + '@types/chai-subset': 1.3.3 + '@types/node': 18.16.15 + '@vitest/expect': 0.31.4 + '@vitest/runner': 0.31.4 + '@vitest/snapshot': 0.31.4 + '@vitest/spy': 0.31.4 + '@vitest/ui': 0.31.4_vitest@0.31.4 + '@vitest/utils': 0.31.4 + acorn: 8.8.2 + acorn-walk: 8.2.0 + cac: 6.7.14 + chai: 4.3.7 + concordance: 5.0.4 + debug: 4.3.4 + jsdom: 22.1.0 + local-pkg: 0.4.3 + magic-string: 0.30.0 + pathe: 1.1.0 + picocolors: 1.0.0 + std-env: 3.3.3 + strip-literal: 1.0.1 + tinybench: 2.5.0 + tinypool: 0.5.0 + vite: 4.3.9_@types+node@18.16.15 + vite-node: 0.31.4_@types+node@18.16.15 + why-is-node-running: 2.2.2 + transitivePeerDependencies: + - less + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + /vm2/3.9.19: resolution: {integrity: sha512-J637XF0DHDMV57R6JyVsTak7nIL8gy5KH4r1HiwWLf/4GBbb5MKL5y7LpmF4A8E2nR6XmzpmMFQ7V7ppPTmUQg==} engines: {node: '>=6.0'} @@ -17711,6 +17870,13 @@ packages: xml-name-validator: 3.0.0 dev: true + /w3c-xmlserializer/4.0.0: + resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} + engines: {node: '>=14'} + dependencies: + xml-name-validator: 4.0.0 + dev: true + /walker/1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} dependencies: @@ -17743,6 +17909,11 @@ packages: engines: {node: '>=10.4'} dev: true + /webidl-conversions/7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + dev: true + /webpack-sources/3.2.3: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} @@ -17814,6 +17985,13 @@ packages: iconv-lite: 0.4.24 dev: true + /whatwg-encoding/2.0.0: + resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} + engines: {node: '>=12'} + dependencies: + iconv-lite: 0.6.3 + dev: true + /whatwg-fetch/3.6.2: resolution: {integrity: sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==} @@ -17821,6 +17999,19 @@ packages: resolution: {integrity: sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==} dev: true + /whatwg-mimetype/3.0.0: + resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} + engines: {node: '>=12'} + dev: true + + /whatwg-url/12.0.1: + resolution: {integrity: sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==} + engines: {node: '>=14'} + dependencies: + tr46: 4.1.1 + webidl-conversions: 7.0.0 + dev: true + /whatwg-url/5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} dependencies: @@ -18050,6 +18241,11 @@ packages: resolution: {integrity: sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==} dev: true + /xml-name-validator/4.0.0: + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} + engines: {node: '>=12'} + dev: true + /xml/1.0.1: resolution: {integrity: sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==} dev: true diff --git a/common/config/rush/repo-state.json b/common/config/rush/repo-state.json index da85531e0..d04160148 100644 --- a/common/config/rush/repo-state.json +++ b/common/config/rush/repo-state.json @@ -1,5 +1,5 @@ // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. { - "pnpmShrinkwrapHash": "cc17ab6655bc3d4f47bc885c0d816820c0d2a09a", + "pnpmShrinkwrapHash": "9be2627e80b4a097f61c386c05b488c48c47c0ff", "preferredVersionsHash": "bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f" } diff --git a/packages/client/src/controllers/Layout.tsx b/packages/client/src/controllers/Layout.tsx index 9bafc0626..756ed8d02 100644 --- a/packages/client/src/controllers/Layout.tsx +++ b/packages/client/src/controllers/Layout.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { useSelector } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import { LinkItem, Layout, UserAvatarProps } from "@eisbuk/ui"; import { PrivateRoutes } from "@eisbuk/shared/ui"; @@ -10,6 +10,8 @@ import BirthdayMenu from "@/controllers/BirthdayMenu"; import AthletesApproval from "@/controllers/AthletesApproval"; import { NotificationsContainer } from "@/features/notifications/components/index"; +import { signOut } from "@/store/actions/authOperations"; + import { getIsAdmin } from "@/store/selectors/auth"; import { getOrgDisplayName } from "@/store/selectors/orgInfo"; @@ -20,6 +22,8 @@ interface Props { } const LayoutController: React.FC = (params) => { + const dispatch = useDispatch(); + const isAdmin = useSelector(getIsAdmin); const displayName = useSelector(getOrgDisplayName); @@ -44,6 +48,7 @@ const LayoutController: React.FC = (params) => { adminLinks={adminLinks} Notifications={NotificationsContainer} additionalAdminContent={additionalAdminContent} + onLogout={() => dispatch(signOut())} /> ); }; diff --git a/packages/client/src/pages/customers/index.tsx b/packages/client/src/pages/customers/index.tsx index ea270ba6d..5b5679a29 100644 --- a/packages/client/src/pages/customers/index.tsx +++ b/packages/client/src/pages/customers/index.tsx @@ -35,20 +35,23 @@ const AthletesPage: React.FC = () => { const { t } = useTranslation(); const history = useHistory(); + useTitle(t(NavigationLabel.Athletes)); + useFirestoreSubscribe(getOrganization(), [ { collection: OrgSubCollection.Customers }, ]); - const [toggled, setToggle] = useState(true); + // Approvals only display logic + const [approvalsOnly, setApprovalsOnly] = useState(true); useEffect(() => { - setToggle( - history.location.search !== "" && - history.location.search === "?approvals=true" - ); + setApprovalsOnly(history.location.search === "?approvals=true"); }, [history.location.search]); - useTitle(t(NavigationLabel.Athletes)); + const toggleApprovals = () => + history.location.search === "?approvals=true" + ? history.push(`${PrivateRoutes.Athletes}`) + : history.push(`${PrivateRoutes.Athletes}/?approvals=true`); const customers = useSelector(getCustomersList(true)); @@ -59,14 +62,6 @@ const AthletesPage: React.FC = () => { history.push(`${PrivateRoutes.Athletes}/${id}`); }; - const toggleApprovals = () => { - const toggled = - history.location.search && history.location.search === "?approvals=true"; - toggled - ? history.push(`${PrivateRoutes.Athletes}`) - : history.push(`${PrivateRoutes.Athletes}/?approvals=true`); - }; - /** @TODO update below when we create `isEmpty` and `isLoaded` helpers */ return ( @@ -82,10 +77,10 @@ const AthletesPage: React.FC = () => { ); diff --git a/packages/ui/src/Layout/Layout.tsx b/packages/ui/src/Layout/Layout.tsx index 45e66abec..e1d08e0dc 100644 --- a/packages/ui/src/Layout/Layout.tsx +++ b/packages/ui/src/Layout/Layout.tsx @@ -14,6 +14,7 @@ interface LayoutProps { children?: React.ReactNode[] | React.ReactNode; isAdmin?: boolean; adminLinks?: LinkItem[]; + onLogout?: () => void; } export interface LinkItem { Icon: SVGComponent; @@ -30,6 +31,7 @@ const Layout: React.FC = ({ isAdmin = false, children, adminLinks, + onLogout = () => {}, }) => { return (
@@ -40,6 +42,7 @@ const Layout: React.FC = ({ className={getHeaderRowClasses("top")} adminLinks={adminLinks} additionalContent={additionalAdminContent} + onLogout={onLogout} /> )} diff --git a/packages/ui/src/Layout/MobileHamburgerMenu.tsx b/packages/ui/src/Layout/MobileHamburgerMenu.tsx index acd866f4e..177ea7c3b 100644 --- a/packages/ui/src/Layout/MobileHamburgerMenu.tsx +++ b/packages/ui/src/Layout/MobileHamburgerMenu.tsx @@ -1,7 +1,9 @@ import React, { useState } from "react"; import { Link } from "react-router-dom"; -import { SVGComponent } from "@eisbuk/svg"; +import { ActionButton, useTranslation } from "@eisbuk/translations"; + +import { PowerCircle, SVGComponent } from "@eisbuk/svg"; interface Item { Icon: SVGComponent; @@ -10,13 +12,17 @@ interface Item { } interface MobileHamburgerMenuProps { adminLinks: Item[]; + onLogout?: () => void; } const MobileHamburgerMenu: React.FC = ({ adminLinks, + onLogout = () => {}, }) => { const [isNavOpen, setIsNavOpen] = useState(false); + const { t } = useTranslation(); + return (