From e2d23d578f95f5b60561bc8d264a721e27ed7847 Mon Sep 17 00:00:00 2001 From: Rainnny7 Date: Wed, 18 Sep 2024 00:06:10 -0400 Subject: [PATCH] onboarding frontend --- bun.lockb | Bin 169332 -> 170092 bytes package.json | 2 + src/app/(pages)/dashboard/onboarding/page.tsx | 26 +++ src/app/(pages)/dashboard/page.tsx | 2 +- src/app/provider/user-provider.tsx | 22 ++- src/app/store/user-store-props.ts | 4 +- src/app/styles/globals.css | 2 +- src/app/types/onboarding-stage.ts | 19 ++ src/app/types/{ => user}/session.ts | 0 src/app/types/user/user-flag.ts | 8 + src/app/types/{ => user}/user.ts | 0 src/components/auth/auth-form.tsx | 2 +- src/components/auth/footer.tsx | 2 +- .../onboarding/completed-onboarding.tsx | 23 +++ .../dashboard/onboarding/onboarding-form.tsx | 181 ++++++++++++++++++ src/lib/api.ts | 12 +- src/lib/user.ts | 12 ++ 17 files changed, 301 insertions(+), 16 deletions(-) create mode 100644 src/app/(pages)/dashboard/onboarding/page.tsx create mode 100644 src/app/types/onboarding-stage.ts rename src/app/types/{ => user}/session.ts (100%) create mode 100644 src/app/types/user/user-flag.ts rename src/app/types/{ => user}/user.ts (100%) create mode 100644 src/components/dashboard/onboarding/completed-onboarding.tsx create mode 100644 src/components/dashboard/onboarding/onboarding-form.tsx create mode 100644 src/lib/user.ts diff --git a/bun.lockb b/bun.lockb index 5a9245375e5b5aaca9dfc82910cae2444875de6c..4d22c2f4ffccef9814d1a137acc9c29e08200cf6 100644 GIT binary patch delta 29634 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 delta 29585 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À)Qtm4{hjm&@ZvU%&Y2|L0)a~8_Q zH?hOV%F7M@EiNxU-uLD9 z7OmV|Y#g|WqgPb|!{GvJ>8#T+c=4z1qm@jv&DGBGvyTS`RBegLYB%zowsYZ@^PR zVSlr?YqEmS{q)siWT1!c>u>*451|W!8(d1P$-|F2Thy2RgdVP|Q+ruEFImZ}jMgYSjY(``@6r+vnw8KOSuTt;&JvDsa^JK5~z<=hH(M z3OkYl?0)^&O0?O2_rkcU3W1XCR_$I|#a)KbV|6z&>*XGX}&_ZlA-C#Z|#7OQ( zXzCfy$TB5y60V6^$fMTCS2qREN!hXkntVn8Yb=+VC(9}b!x8v>Ewxh%UW;$b|iuw)=0!VaPa%%bS&n)KRTEvphutgtP_y(K?nP+ zEi+2$)$l(i%_@lvz?>mfJP^_jxt#**Hp}1sr#Zah6Y@V0v)?tnU_Ph_m*q-9ueEGY zO79r(h-Zd4K@aFAUn!+G!^=Lr`t_0Dm(l~(qaFW8-$yl;A)ctbjT~88_mllSVQ8$J z=&3i-+fJ6tJ@wcC``;MZFz1;Qk1ZZITMZ<_V%ubS*Aor?(REz4vD5p?$xc-E@H~6} zvri#d*CwNg@`Y$2JA3JWcjuX$FQ54V_)cADia{iS?4y|muYa{;R0jgjfTfMwwL zZnj^Adj{V7>(o)3)TxYtZ*P1daO8z#>@uUiE+Ul{N3pgS=Wct(fu)c*JBt z#C9JkpZ3NoX8#jC-c@crd2QxNK8NBehTZ57zZdYg{{hC|w?!50PU|{Q>0!**%46P` zHD@ZyTi$;i`Ugil-c0{#YkIKRaP=|A`~MOh9rS}!W;AEvWXhK?AAe~7EiQwQr_X|$?dvg}=64-&~T2PAk3 zj_v%#$B`Zr-|n@thTkmkd>N8owMW@|m75=5C=1H#?s`}8CV}Fq(Gg#X@n!GcQVkuQ pYc+`fyCm9GBTVjJhdcG?3i=M&zn$*8KB}U=Dr)`2_IhE*{|AL}*VO<3 diff --git a/package.json b/package.json index feb33aa..0bb922d 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,8 @@ "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-slot": "^1.1.0", + "@types/canvas-confetti": "^1.6.4", + "canvas-confetti": "^1.9.3", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "framer-motion": "^11.5.4", diff --git a/src/app/(pages)/dashboard/onboarding/page.tsx b/src/app/(pages)/dashboard/onboarding/page.tsx new file mode 100644 index 0000000..b0dcdbf --- /dev/null +++ b/src/app/(pages)/dashboard/onboarding/page.tsx @@ -0,0 +1,26 @@ +"use client"; + +import { ReactElement } from "react"; +import OnboardingForm from "@/components/dashboard/onboarding/onboarding-form"; +import { useUserContext } from "@/app/provider/user-provider"; +import { UserState } from "@/app/store/user-store-props"; +import { User } from "@/app/types/user/user"; +import { hasFlag } from "@/lib/user"; +import { UserFlag } from "@/app/types/user/user-flag"; +import CompletedOnboarding from "@/components/dashboard/onboarding/completed-onboarding"; + +const OnboardingPage = (): ReactElement => { + const user: User | undefined = useUserContext( + (state: UserState) => state.user + ); + return ( +
+ {hasFlag(user as User, UserFlag.COMPLETED_ONBOARDING) ? ( + + ) : ( + + )} +
+ ); +}; +export default OnboardingPage; diff --git a/src/app/(pages)/dashboard/page.tsx b/src/app/(pages)/dashboard/page.tsx index ea3e3bc..4f203f6 100644 --- a/src/app/(pages)/dashboard/page.tsx +++ b/src/app/(pages)/dashboard/page.tsx @@ -2,7 +2,7 @@ import { ReactElement } from "react"; import { UserState } from "@/app/store/user-store-props"; -import { User } from "@/app/types/user"; +import { User } from "@/app/types/user/user"; import { useUserContext } from "@/app/provider/user-provider"; const DashboardPage = (): ReactElement => { diff --git a/src/app/provider/user-provider.tsx b/src/app/provider/user-provider.tsx index 28ad680..c16df69 100644 --- a/src/app/provider/user-provider.tsx +++ b/src/app/provider/user-provider.tsx @@ -13,14 +13,16 @@ import createUserStore, { UserState, UserStore, } from "@/app/store/user-store-props"; -import { User } from "@/app/types/user"; +import { User } from "@/app/types/user/user"; import { Cookies, useCookies } from "next-client-cookies"; -import { Session } from "@/app/types/session"; +import { Session } from "@/app/types/user/session"; import { apiRequest } from "@/lib/api"; import { StoreApi, useStore } from "zustand"; -import { useRouter } from "next/navigation"; +import { usePathname, useRouter } from "next/navigation"; import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime"; import DashboardLoader from "@/components/dashboard/loader"; +import { hasFlag } from "@/lib/user"; +import { UserFlag } from "@/app/types/user/user-flag"; /** * The provider that will provide user context to children. @@ -33,6 +35,7 @@ const UserProvider = ({ children }: { children: ReactNode }) => { const [authorized, setAuthorized] = useState(false); const cookies: Cookies = useCookies(); const router: AppRouterInstance = useRouter(); + const path: string = usePathname(); if (!storeRef.current) { storeRef.current = createUserStore(); } @@ -59,9 +62,20 @@ const UserProvider = ({ children }: { children: ReactNode }) => { router.push("/auth"); return; } - storeRef.current?.getState().authorize(session, data as User); + // User successfully authenticated + const user: User = data as User; + storeRef.current?.getState().authorize(session, user); setAuthorized(true); + + // User has not yet completed onboarding + if ( + !hasFlag(user, UserFlag.COMPLETED_ONBOARDING) && + !path.startsWith("/dashboard/onboarding") + ) { + router.push("/dashboard/onboarding"); + } }, [cookies, router]); + useEffect(() => { fetchUser(); }, [fetchUser]); diff --git a/src/app/store/user-store-props.ts b/src/app/store/user-store-props.ts index 3e831fd..08d284f 100644 --- a/src/app/store/user-store-props.ts +++ b/src/app/store/user-store-props.ts @@ -1,7 +1,7 @@ import { createStore } from "zustand"; -import { User } from "@/app/types/user"; +import { User } from "@/app/types/user/user"; import { createContext } from "react"; -import { Session } from "@/app/types/session"; +import { Session } from "@/app/types/user/session"; export const UserContext = createContext(null); diff --git a/src/app/styles/globals.css b/src/app/styles/globals.css index b3bf7d7..fe695a0 100644 --- a/src/app/styles/globals.css +++ b/src/app/styles/globals.css @@ -50,7 +50,7 @@ body { --card-foreground: 0 0% 98%; --popover: 240 10% 3.9%; --popover-foreground: 0 0% 98%; - --primary: 0 84% 60%; + --primary: 0 0% 98%; --primary-foreground: 240 5.9% 10%; --secondary: 240 3.7% 15.9%; --secondary-foreground: 0 0% 98%; diff --git a/src/app/types/onboarding-stage.ts b/src/app/types/onboarding-stage.ts new file mode 100644 index 0000000..f914661 --- /dev/null +++ b/src/app/types/onboarding-stage.ts @@ -0,0 +1,19 @@ +/** + * An onboarding stage. + */ +type OnboardingStage = { + /** + * The name of this stage. + */ + name: string; + + /** + * The description of this stage. + */ + description: string; + + /** + * The form schema for this stage. + */ + schema: any; +}; diff --git a/src/app/types/session.ts b/src/app/types/user/session.ts similarity index 100% rename from src/app/types/session.ts rename to src/app/types/user/session.ts diff --git a/src/app/types/user/user-flag.ts b/src/app/types/user/user-flag.ts new file mode 100644 index 0000000..7efe8f7 --- /dev/null +++ b/src/app/types/user/user-flag.ts @@ -0,0 +1,8 @@ +/** + * Flags for a {@link User}. + */ +export enum UserFlag { + DISABLED = 0, + COMPLETED_ONBOARDING = 1, + ADMINISTRATOR = 2, +} diff --git a/src/app/types/user.ts b/src/app/types/user/user.ts similarity index 100% rename from src/app/types/user.ts rename to src/app/types/user/user.ts diff --git a/src/components/auth/auth-form.tsx b/src/components/auth/auth-form.tsx index 1d458fc..44cb410 100644 --- a/src/components/auth/auth-form.tsx +++ b/src/components/auth/auth-form.tsx @@ -14,7 +14,7 @@ import { LockClosedIcon, } from "@heroicons/react/24/outline"; import { apiRequest } from "@/lib/api"; -import { Session } from "@/app/types/session"; +import { Session } from "@/app/types/user/session"; import { Cookies, useCookies } from "next-client-cookies"; import { useRouter } from "next/navigation"; import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime"; diff --git a/src/components/auth/footer.tsx b/src/components/auth/footer.tsx index 2b97daf..be4aa51 100644 --- a/src/components/auth/footer.tsx +++ b/src/components/auth/footer.tsx @@ -8,7 +8,7 @@ import Link from "next/link"; */ const Footer = (): ReactElement => (