From 4ad0914b173f714aa082bd7cf2c0ad7b832aaae1 Mon Sep 17 00:00:00 2001 From: grimsi <9295182+grimsi@users.noreply.github.com> Date: Sat, 16 Mar 2024 14:48:06 +0100 Subject: [PATCH] Fix Multi-Step-Wizard Implement generic Wizard component for future use in Gameyfin --- .run/UI debug.run.xml | 2 +- frontend/components/Input.tsx | 19 +- frontend/components/wizard/Wizard.tsx | 87 +++++++++ frontend/components/wizard/WizardStep.tsx | 3 + frontend/views/SetupView.tsx | 224 +++++++++------------- gradlew | 0 6 files changed, 185 insertions(+), 150 deletions(-) create mode 100644 frontend/components/wizard/Wizard.tsx create mode 100644 frontend/components/wizard/WizardStep.tsx mode change 100644 => 100755 gradlew diff --git a/.run/UI debug.run.xml b/.run/UI debug.run.xml index b656b83..0a58cbb 100644 --- a/.run/UI debug.run.xml +++ b/.run/UI debug.run.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/frontend/components/Input.tsx b/frontend/components/Input.tsx index 13f0a79..148e5bb 100644 --- a/frontend/components/Input.tsx +++ b/frontend/components/Input.tsx @@ -30,21 +30,4 @@ const Input = ({label, ...props}) => { ); } -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 +export default Input; \ No newline at end of file diff --git a/frontend/components/wizard/Wizard.tsx b/frontend/components/wizard/Wizard.tsx new file mode 100644 index 0000000..d50e13b --- /dev/null +++ b/frontend/components/wizard/Wizard.tsx @@ -0,0 +1,87 @@ +import React, {useState} from "react"; +import {Form, Formik, FormikBag, FormikHelpers} from "formik"; +import {Button, Spinner, Step, Stepper} from "@material-tailwind/react"; +import {ArrowLeft, ArrowRight, Check} from "@phosphor-icons/react"; + +const Wizard = ({children, initialValues, onSubmit}: { children: any, initialValues: any, onSubmit: any }) => { + const [stepNumber, setStepNumber] = useState(0); + const steps = React.Children.toArray(children); + const [snapshot, setSnapshot] = useState(initialValues); + + const step = steps[stepNumber]; + const totalSteps = steps.length; + const isFirstStep = stepNumber === 0; + const isLastStep = stepNumber === totalSteps - 1; + + const next = (values: any) => { + setSnapshot(values); + setStepNumber(Math.min(stepNumber + 1, totalSteps - 1)); + }; + + const previous = (values: any) => { + setSnapshot(values); + setStepNumber(Math.max(stepNumber - 1, 0)); + }; + + const handleSubmit = async (values: any, bag: FormikBag | FormikHelpers) => { + /*// @ts-ignore*/ + if (step.props.onSubmit) { + /*// @ts-ignore*/ + await step.props.onSubmit(values, bag); + } + if (isLastStep) { + return onSubmit(values, bag); + } else { + await bag.setTouched({}); + next(values); + } + }; + + return ( + + {formik => ( +
+
+ + {steps.map((child, index) => ( + + {/*// @ts-ignore*/} + {child.props.icon} + + ))} + +
+
+ {step} +
+
+
+ + +
+
+
+ )} +
+ ); +}; + +export default Wizard; \ No newline at end of file diff --git a/frontend/components/wizard/WizardStep.tsx b/frontend/components/wizard/WizardStep.tsx new file mode 100644 index 0000000..c34c99d --- /dev/null +++ b/frontend/components/wizard/WizardStep.tsx @@ -0,0 +1,3 @@ +const WizardStep = ({children}: { children: any }) => children; + +export default WizardStep; \ No newline at end of file diff --git a/frontend/views/SetupView.tsx b/frontend/views/SetupView.tsx index 1c0784b..840c3a3 100644 --- a/frontend/views/SetupView.tsx +++ b/frontend/views/SetupView.tsx @@ -1,55 +1,89 @@ -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 React from 'react'; +import {useFormikContext} from 'formik'; import * as Yup from 'yup'; +import Wizard from "Frontend/components/wizard/Wizard"; +import WizardStep from "Frontend/components/wizard/WizardStep"; +import {Card, Typography} from "@material-tailwind/react"; import Input from "Frontend/components/Input"; +import {GearFine, HandWaving, User} from "@phosphor-icons/react"; -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 sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); - const steps = [, , ]; +function WelcomeStep() { + return ( +
+ Welcome to Gameyfin 👋 +

+ 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 + 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! +
+ ); +} - const handleNext = () => !isLastStep && setActiveStep((cur) => cur + 1); - const handlePrev = () => !isFirstStep && setActiveStep((cur) => cur - 1); - const finish = () => { - alert("Setup finished"); - } - - function WelcomeStep() { - return ( -
- Welcome to Gameyfin 👋 -

- 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 - 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! +function UserStep() { + const formik = useFormikContext(); + return ( +
+ Create your account + This will set up the initial admin user account. +
+ + +
- ); - } +
+ ); +} - function UserStep() { - return ( -
- Create your account - This will set up the initial admin user account. - + Settings + Configure your settings +
+ ); +} + +const SetupView = () => ( +
+
+ + + sleep(300).then(() => alert(JSON.stringify(values, null, 2))) + } + > + }> + + + { - setTimeout(() => { - alert(JSON.stringify(values, null, 2)); - setSubmitting(false); - }, 400); - }} + icon={} > - {formik => -
- - - - -
- } - -
- ); - } + + + } + > + + + + +
+); - function SettingsStep() { - return ( - <> - - ); - } - - return ( -
-
- -
- setIsLastStep(value)} - isFirstStep={(value) => setIsFirstStep(value)} - > - setActiveStep(0)}> - - - setActiveStep(1)}> - - - setActiveStep(2)}> - - - -
-
-
- {steps[activeStep]} -
-
-
-
- - -
-
-
-
- ); -} \ No newline at end of file +export default SetupView; \ No newline at end of file diff --git a/gradlew b/gradlew old mode 100644 new mode 100755