diff --git a/frontend/components/Input.tsx b/frontend/components/Input.tsx new file mode 100644 index 0000000..13f0a79 --- /dev/null +++ b/frontend/components/Input.tsx @@ -0,0 +1,50 @@ +import {useField} from "formik"; +import {Input as MaterialInput, Typography} from "@material-tailwind/react"; +import {XCircle} from "@phosphor-icons/react"; + +// @ts-ignore +const Input = ({label, ...props}) => { + // @ts-ignore + const [field, meta] = useField(props); + + return ( + <> + + {(meta.touched && !!meta.error) ? + + {meta.error} + : <> + } + + ); +} + +export default Input; +/* + { + setUsername(event.target.value); + }} + id="username" + type="text" + autoComplete="username" + placeholder="" + size="lg" + className=" !border-t-blue-gray-200 focus:!border-t-gray-900" + labelProps={{ + className: "before:content-none after:content-none", + }} + crossOrigin="" //TODO: see https://github.com/creativetimofficial/material-tailwind/issues/427 + /> +*/ \ No newline at end of file diff --git a/frontend/routes.tsx b/frontend/routes.tsx index 87250a9..b3f6453 100644 --- a/frontend/routes.tsx +++ b/frontend/routes.tsx @@ -8,18 +8,16 @@ import SetupView from "Frontend/views/SetupView"; export const routes = protectRoutes([ { element: , - handle: {title: 'Main', requiresLogin: true}, + handle: {requiresLogin: true}, children: [ - {path: '/', element: , handle: {title: 'Gameyfin', requiresLogin: true}}, + {path: '/', element: , handle: {title: 'Gameyfin - Test'}}, ], }, { - path: '/login', - element: + path: '/login', element: , handle: {requiresLogin: false} }, { - path: '/setup', - element: + path: '/setup', element: , handle: {requiresLogin: false} } ]) as RouteObject[]; diff --git a/frontend/views/MainLayout.tsx b/frontend/views/MainLayout.tsx index 8a9c710..652b766 100644 --- a/frontend/views/MainLayout.tsx +++ b/frontend/views/MainLayout.tsx @@ -1,22 +1,15 @@ -import {useAuth} from 'Frontend/util/auth.js'; import {useRouteMetadata} from 'Frontend/util/routing.js'; import {useEffect} from 'react'; import {Navbar} from "@material-tailwind/react"; import ProfileMenu from "Frontend/components/ProfileMenu"; import {Outlet} from "react-router-dom"; -const navLinkClasses = ({isActive}: any) => { - return `block rounded-m p-s ${isActive ? 'bg-primary-10 text-primary' : 'text-body'}`; -}; - export default function MainLayout() { - const currentTitle = useRouteMetadata()?.title ?? 'My App'; + const currentTitle = `Gameyfin - ${useRouteMetadata()?.title}` ?? 'Gameyfin'; useEffect(() => { document.title = currentTitle; }, [currentTitle]); - const {state, logout} = useAuth(); - return ( <> diff --git a/frontend/views/SetupView.tsx b/frontend/views/SetupView.tsx index fa15976..1c0784b 100644 --- a/frontend/views/SetupView.tsx +++ b/frontend/views/SetupView.tsx @@ -1,12 +1,16 @@ import {Button, Card, Spinner, Step, Stepper, Typography} from "@material-tailwind/react"; import {useState} from "react"; import {ArrowLeft, ArrowRight, Check, GearFine, HandWaving, User} from "@phosphor-icons/react"; +import {Form, Formik} from "formik"; +import * as Yup from 'yup'; +import Input from "Frontend/components/Input"; export default function SetupView() { const [activeStep, setActiveStep] = useState(0); const [isLastStep, setIsLastStep] = useState(false); const [isFirstStep, setIsFirstStep] = useState(false); const [isLoading, setLoading] = useState(false); + const [isNextDisabled, setIsNextDisabled] = useState(false); const steps = [, , ]; @@ -18,19 +22,21 @@ export default function SetupView() { function WelcomeStep() { return ( -
+
Welcome to Gameyfin 👋 - - Gameyfin is a cutting-edge software tailored for gamers seeking efficient management of their video +

+ Gameyfin is a cutting-edge software tailored for gamers seeking efficient management of their + video game collections.

With its intuitive interface and comprehensive features, Gameyfin - simplifies the organization of game libraries. Users can effortlessly add games through manual input + simplifies the organization of game libraries. Users can effortlessly add games through manual + input or automated recognition, categorize them based on various criteria like genre or platform, track in-game progress, and share achievements with friends.

Notably, Gameyfin stands out for its user-friendly design and adaptability, offering ample customization options to meet diverse user preferences. - +

Let's get started!
); @@ -38,8 +44,59 @@ export default function SetupView() { function UserStep() { return ( - <> - +
+ Create your account + This will set up the initial admin user account. + { + setTimeout(() => { + alert(JSON.stringify(values, null, 2)); + setSubmitting(false); + }, 400); + }} + > + {formik => +
+ + + + +
+ } +
+
); } @@ -53,7 +110,7 @@ export default function SetupView() { return (
- +
- {steps[activeStep]} +
+ {steps[activeStep]} +
-
diff --git a/package-lock.json b/package-lock.json index e211cd6..2b2ef09 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,10 +31,12 @@ "@vaadin/router": "1.7.5", "classnames": "^2.3.2", "construct-style-sheets-polyfill": "3.1.0", + "formik": "^2.4.5", "lit": "3.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-router-dom": "^6.4.2" + "react-router-dom": "^6.4.2", + "yup": "^1.4.0" }, "devDependencies": { "@lit-labs/react": "^1.1.0", @@ -3458,6 +3460,15 @@ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", + "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", @@ -3486,14 +3497,12 @@ "node_modules/@types/prop-types": { "version": "15.7.11", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", - "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==", - "devOptional": true + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" }, "node_modules/@types/react": { "version": "18.2.42", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.42.tgz", "integrity": "sha512-c1zEr96MjakLYus/wPnuWDo1/zErfdU9rNsIGmE+NV71nx88FG9Ttgo5dqorXTu/LImX2f63WBP986gJkMPNbA==", - "devOptional": true, "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -3521,8 +3530,7 @@ "node_modules/@types/scheduler": { "version": "0.16.8", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", - "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", - "devOptional": true + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" }, "node_modules/@types/trusted-types": { "version": "2.0.7", @@ -5705,8 +5713,7 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "devOptional": true + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/dash-ast": { "version": "1.0.0", @@ -6247,6 +6254,38 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/formik": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.5.tgz", + "integrity": "sha512-Gxlht0TD3vVdzMDHwkiNZqJ7Mvg77xQNfmBRrNtvzcHZs72TJppSTDKHpImCMJZwcWPBJ8jSQQ95GJzXFf1nAQ==", + "funding": [ + { + "type": "individual", + "url": "https://opencollective.com/formik" + } + ], + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.1", + "deepmerge": "^2.1.1", + "hoist-non-react-statics": "^3.3.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "react-fast-compare": "^2.0.1", + "tiny-warning": "^1.0.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/formik/node_modules/deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -6651,6 +6690,14 @@ "resolved": "https://registry.npmjs.org/highcharts/-/highcharts-9.2.2.tgz", "integrity": "sha512-OMEdFCaG626ES1JEcKAvJTpxAOMuchy0XuAplmnOs0Yu7NMd2RMfTLFQ2fCJOxo3ubSdm/RVQwKAWC+5HYThnw==" }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/hosted-git-info": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", @@ -7481,8 +7528,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.debounce": { "version": "4.0.8", @@ -8485,6 +8536,11 @@ "react-is": "^16.13.1" } }, + "node_modules/property-expr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", + "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==" + }, "node_modules/protocol-buffers-schema": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", @@ -8594,6 +8650,11 @@ "react": "^18.2.0" } }, + "node_modules/react-fast-compare": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", + "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==" + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -9788,12 +9849,22 @@ "real-require": "^0.2.0" } }, + "node_modules/tiny-case": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", + "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==" + }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", "dev": true }, + "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/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -9815,6 +9886,11 @@ "node": ">=8.0" } }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" + }, "node_modules/tr46": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", @@ -11258,6 +11334,28 @@ "node": ">=12" } }, + "node_modules/yup": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.4.0.tgz", + "integrity": "sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==", + "dependencies": { + "property-expr": "^2.0.5", + "tiny-case": "^1.0.3", + "toposort": "^2.0.2", + "type-fest": "^2.19.0" + } + }, + "node_modules/yup/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/zstddec": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/zstddec/-/zstddec-0.1.0.tgz", diff --git a/package.json b/package.json index 42468d2..027d058 100644 --- a/package.json +++ b/package.json @@ -26,10 +26,12 @@ "@vaadin/router": "1.7.5", "classnames": "^2.3.2", "construct-style-sheets-polyfill": "3.1.0", + "formik": "^2.4.5", "lit": "3.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-router-dom": "^6.4.2" + "react-router-dom": "^6.4.2", + "yup": "^1.4.0" }, "devDependencies": { "@lit-labs/react": "^1.1.0", @@ -82,7 +84,9 @@ "@hilla/generator-typescript-plugin-backbone": "$@hilla/generator-typescript-plugin-backbone", "@hilla/generator-typescript-cli": "$@hilla/generator-typescript-cli", "@material-tailwind/react": "$@material-tailwind/react", - "@phosphor-icons/react": "$@phosphor-icons/react" + "@phosphor-icons/react": "$@phosphor-icons/react", + "formik": "$formik", + "yup": "$yup" }, "vaadin": { "dependencies": { @@ -126,6 +130,6 @@ "workbox-core": "7.0.0", "workbox-precaching": "7.0.0" }, - "hash": "866532fc7368b3b6387e2dee804a0a2f82b8b5c94f00c0a5fa056b2bd6af0220" + "hash": "4a15d7e79e5a115970b30fcf67cfdd2edab987a6419ed93f8f80f6969d884b1d" } }