From 9f35ceed04aef142f2bd8425cb4cd108396fee4a Mon Sep 17 00:00:00 2001 From: wil Date: Wed, 28 Aug 2024 23:16:41 -0400 Subject: [PATCH] api manager works, persist login works --- .env | 10 +- src/Classes/ApiManager/ApiManager.ts | 4 - src/app/index.tsx | 26 +++- src/components/ui/Input.tsx | 80 +++++++++++ src/components/ui/{spinner.tsx => Spinne.tsx} | 2 +- src/components/ui/index.ts | 3 +- src/pages/login.tsx | 136 +++++++++++++++++- vite.config.ts | 4 + 8 files changed, 247 insertions(+), 18 deletions(-) create mode 100644 src/components/ui/Input.tsx rename src/components/ui/{spinner.tsx => Spinne.tsx} (100%) diff --git a/.env b/.env index fc151be5f..2406a9e3e 100644 --- a/.env +++ b/.env @@ -1,6 +1,6 @@ -BASE_API="https://api.storyteller.ai" -GOOGLE_API="https://storage.googleapis.com" -FUNNEL_API="https://style.storyteller.ai" -CDN_API="https://cdn.storyteller.ai" -GRAVATAR_API="https://www.gravatar.com" +VITE_BASE_API="https://api.storyteller.ai" +VITE_GOOGLE_API="https://storage.googleapis.com" +VITE_FUNNEL_API="https://style.storyteller.ai" +VITE_CDN_API="https://cdn.storyteller.ai" +VITE_GRAVATAR_API="https://www.gravatar.com" diff --git a/src/Classes/ApiManager/ApiManager.ts b/src/Classes/ApiManager/ApiManager.ts index 489378fe1..927d491fd 100644 --- a/src/Classes/ApiManager/ApiManager.ts +++ b/src/Classes/ApiManager/ApiManager.ts @@ -154,10 +154,6 @@ export class ApiManager { return this.fetchMultipartFormData(endpoint, { method: "POST", - headers: { - Accept: "application/json", - }, - credentials: "include", body: formData, }); } diff --git a/src/app/index.tsx b/src/app/index.tsx index b5b892132..4904f08fb 100644 --- a/src/app/index.tsx +++ b/src/app/index.tsx @@ -1,16 +1,30 @@ -import { StrictMode } from "react"; +import { StrictMode, useRef } from "react"; import { createRoot } from "react-dom/client"; -import { useEffect } from "react"; -import EnvironmentVariables from "~/Classes/EnvironmentVariables"; + +import environmentVariables from "~/Classes/EnvironmentVariables"; import { RouterProvider } from "react-router-dom"; import { router } from "./router"; import "./global.css"; const App = () => { - useEffect(() => { - EnvironmentVariables.initialize(import.meta.env); - }, []); + const AppRerenderCount = useRef(0); + AppRerenderCount.current++; + if (AppRerenderCount.current === 1) { + console.log(`App rerendered ${AppRerenderCount.current} times`); + } else { + console.warn(`App rerendered ${AppRerenderCount.current} times`); + } + + if (Object.keys(environmentVariables.values).length === 0) { + environmentVariables.initialize({ + BASE_API: import.meta.env.VITE_BASE_API, + GOOGLE_API: import.meta.env.VITE_GOOGLE_API, + FUNNEL_API: import.meta.env.VITE_FUNNEL_API, + CDN_API: import.meta.env.VITE_CDN_API, + GRAVATAR_API: import.meta.env.VITE_GRAVATAR_API, + }); + } return ; }; diff --git a/src/components/ui/Input.tsx b/src/components/ui/Input.tsx new file mode 100644 index 000000000..153d03563 --- /dev/null +++ b/src/components/ui/Input.tsx @@ -0,0 +1,80 @@ +import React from "react"; +import { twMerge } from "tailwind-merge"; +import { IconDefinition } from "@fortawesome/pro-thin-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +const kebabCase = (str: string) => + str + .replace(/([a-z])([A-Z])/g, "$1-$2") + .replace(/[\s_]+/g, "-") + .toLowerCase(); + +interface InputProps extends React.InputHTMLAttributes { + inputClassName?: string; + iconClassName?: string; + label?: string; + icon?: IconDefinition; + isError?: boolean; + errorMessage?: string; +} + +export const Input = React.forwardRef( + ( + { + label, + icon, + inputClassName, + iconClassName, + className, + id, + isError, + onBlur, + onFocus, + errorMessage, + ...rest + }: InputProps, + ref: React.ForwardedRef, + ) => { + return ( +
+ {label && } + +
+ {icon && ( + + )} + ) => { + if (onFocus) { + onFocus(e); + } + }} + onBlur={(e: React.FocusEvent) => { + if (onBlur) { + onBlur(e); + } + }} + {...rest} + /> + {errorMessage && ( +
{errorMessage}
+ )} +
+
+ ); + }, +); + +Input.displayName = "Input"; diff --git a/src/components/ui/spinner.tsx b/src/components/ui/Spinne.tsx similarity index 100% rename from src/components/ui/spinner.tsx rename to src/components/ui/Spinne.tsx index 8874f60e6..1a443cce8 100644 --- a/src/components/ui/spinner.tsx +++ b/src/components/ui/Spinne.tsx @@ -1,5 +1,5 @@ -import { faSpinnerThird } from "@fortawesome/pro-thin-svg-icons"; import { twMerge } from "tailwind-merge"; +import { faSpinnerThird } from "@fortawesome/pro-thin-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; export const Spinner = ({ className }: { className?: string }) => { diff --git a/src/components/ui/index.ts b/src/components/ui/index.ts index eff29707a..95edc0271 100644 --- a/src/components/ui/index.ts +++ b/src/components/ui/index.ts @@ -1 +1,2 @@ -export * from "./spinner"; +export * from "./Spinne"; +export * from "./Input"; diff --git a/src/pages/login.tsx b/src/pages/login.tsx index 89bfb6298..c414c6f31 100644 --- a/src/pages/login.tsx +++ b/src/pages/login.tsx @@ -1,3 +1,137 @@ +import { useRef } from "react"; +import { useNavigate, useSearchParams, Link } from "react-router-dom"; +import { useSignalEffect } from "@preact/signals-react/runtime"; + +import { faKey, faUser } from "@fortawesome/pro-thin-svg-icons"; + +import { AUTH_STATUS } from "~/enums"; +import { authentication, login, logout } from "~/signals"; + +import { + Input, + // Spinner, +} from "~/components/ui"; + export const Login = () => { - return
Login
; + const navigate = useNavigate(); + const [searchParams] = useSearchParams(); + + const formRef = useRef(null); + const { status: authStatus } = authentication; + // const authLoaderMessage = getAuthLoaderMessage(); + // const shouldShowLoader = checkShouldShowLoader(); + + // const showNoAccessModal = authStatus.value === AUTH_STATUS.NO_ACCESS; + + const handleOnSumbit = (ev: React.FormEvent) => { + ev.preventDefault(); + if (formRef.current) { + const form = new FormData(formRef.current); + const usernameOrEmail = form.get("usernameOrEmail")?.toString(); + const password = form.get("password")?.toString(); + if (usernameOrEmail && password && login) { + login({ + usernameOrEmail, + password, + }); + } + } + }; // end handleOnSubmit + + useSignalEffect(() => { + const redirectPath = searchParams.get("redirect"); + if (authStatus.value === AUTH_STATUS.LOGGED_IN) { + navigate(redirectPath ? redirectPath : "/"); + } + }); + + return ( +
+
+

Login to Storyteller

+
+
+
+ + +
+ + Forgot your password? + +
+

Don't have an account?

+ Sign Up +
+
+ + +
+ {/* + { + handleClose(); + if (window) { + window.open("https://storyteller.ai/beta-key/redeem", "_blank"); + } + }} + />*/} +
+
+ ); }; + +// const handleClose = () => { +// if (authentication.status.value !== AUTH_STATUS.LOGGED_OUT) { +// logout(); +// } +// }; + +// const checkShouldShowLoader = () => { +// return ( +// authentication.status.value === AUTH_STATUS.LOGGING || +// authentication.status.value === AUTH_STATUS.LOGGED_IN +// ); +// }; +// const getAuthLoaderMessage = () => { +// if (authentication.status.value === AUTH_STATUS.LOGGED_IN) { +// return "Authenticated, Redirecting..."; +// } +// if (authentication.status.value === AUTH_STATUS.GET_USER_INFO) { +// return "Getting User Info..."; +// } +// return "Getting Session..."; +// }; diff --git a/vite.config.ts b/vite.config.ts index 956d908a5..ff5b3148f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -5,6 +5,10 @@ import tsconfigPaths from "vite-tsconfig-paths"; // https://vitejs.dev/config/ export default defineConfig({ + server: { + port: 5741, + }, + plugins: [ tsconfigPaths(), react({