mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-05 09:48:44 +00:00
Modified the sign in and sign up buttons to use the new button link component
This commit is contained in:
1 parent
e9299ef97d
commit
757baf02f0
9 files changed
+439
-409
No files matched your search
@@ -14,6 +14,7 @@ import { EditModeRootComponent } from "~/EditModeRootComponent/EditModeRootCompo
|
||||
import { useRef } from "react";
|
||||
import { GenerationEngine } from "~/KonvaApp/GenerationEngine";
|
||||
import { GalleryRootComponent } from "~/GalleryRootComponent";
|
||||
|
||||
import { DemoModal } from "@storyteller/ui-demo-modal";
|
||||
|
||||
export const isTauri = (): boolean => {
|
||||
|
||||
@@ -4,9 +4,11 @@ import { Activity } from "~/components/ui/Activity/Activity";
|
||||
// import { paperWrapperStyles } from "~/components/styles";
|
||||
// import { faPlus, faQuestion } from "@fortawesome/pro-solid-svg-icons";
|
||||
// import { ToolbarButton } from "~/components/features/ToolbarButton";
|
||||
|
||||
import { Button } from "@storyteller/ui-button";
|
||||
import { SettingsModal } from "@storyteller/ui-settings-modal";
|
||||
import { useState } from "react";
|
||||
import { AuthButtons } from "~/components/shared_authentication/AuthButtons";
|
||||
|
||||
export const ToolbarTopRight = () => {
|
||||
const [isSettingsModalOpen, setIsSettingsModalOpen] = useState(false);
|
||||
@@ -21,8 +23,8 @@ export const ToolbarTopRight = () => {
|
||||
onClick={() => setIsSettingsModalOpen(true)}
|
||||
/>
|
||||
<Activity />
|
||||
<AuthButtons/>
|
||||
</div>
|
||||
|
||||
<SettingsModal
|
||||
isOpen={isSettingsModalOpen}
|
||||
onClose={() => setIsSettingsModalOpen(false)}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import { Link, LinkProps } from "@remix-run/react";
|
||||
import React from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
interface LinkButtonProps extends LinkProps {
|
||||
interface ButtonLinkProps {
|
||||
icon?: IconDefinition;
|
||||
variant?: "primary" | "secondary";
|
||||
className?: string;
|
||||
to: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const ButtonLink = ({
|
||||
@@ -13,9 +17,11 @@ export const ButtonLink = ({
|
||||
children,
|
||||
className: propsClassName,
|
||||
variant = "primary",
|
||||
to,
|
||||
...rest
|
||||
}: LinkButtonProps) => {
|
||||
//TODO: Duplicated from Button.tsx
|
||||
}: ButtonLinkProps) => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
function getVariantClassNames(variant: string) {
|
||||
switch (variant) {
|
||||
case "secondary": {
|
||||
@@ -31,14 +37,19 @@ export const ButtonLink = ({
|
||||
"text-sm font-medium whitespace-nowrap rounded-lg px-3 py-2 shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 transition-all duration-150";
|
||||
const variantClassNames = getVariantClassNames(variant);
|
||||
const className = twMerge(baseClassName, variantClassNames, propsClassName);
|
||||
// END TODO
|
||||
|
||||
const handleClick = () => {
|
||||
navigate(to);
|
||||
};
|
||||
|
||||
return (
|
||||
<Link {...rest}>
|
||||
<button className={className}>
|
||||
{icon && <FontAwesomeIcon className="mr-2" icon={icon} size="sm" />}
|
||||
{children}
|
||||
</button>
|
||||
</Link>
|
||||
<button
|
||||
className={className}
|
||||
onClick={handleClick}
|
||||
{...rest}
|
||||
>
|
||||
{icon && <FontAwesomeIcon className="mr-2" icon={icon} size="sm" />}
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
// import { AUTH_STATUS } from "~/signals/authentication/enums";
|
||||
// import { authentication } from "~/signals";
|
||||
import { ButtonLink } from "~/components/reusable/ButtonLink/ButtonLink";
|
||||
// import ProfileDropdown from "./ProfileDropdown";
|
||||
|
||||
// TODO MAKE THIS A SHARED COMPONENT ART CRAFT
|
||||
export const AuthButtons = () => {
|
||||
useSignals();
|
||||
//const { status } = authentication;
|
||||
if (false) {
|
||||
// status.value === AUTH_STATUS.LOGGED_IN
|
||||
return <ProfileDropdown />;
|
||||
} else {
|
||||
return (
|
||||
<div className="flex items-center gap-3.5">
|
||||
<span className="text-white/20">|</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<ButtonLink
|
||||
to="/login"
|
||||
variant="primary"
|
||||
className="bg-[#5F5F68]/60 backdrop-blur-lg hover:bg-[#5F5F68]/90" // TODO(bt,2025-04-19): Once we have in-page routing, get rid of this.
|
||||
>
|
||||
Login
|
||||
</ButtonLink>
|
||||
<ButtonLink
|
||||
to="/signup"
|
||||
variant="primary"
|
||||
className="bg-[#5F5F68]/60 backdrop-blur-lg hover:bg-[#5F5F68]/90" // TODO(bt,2025-04-19): Once we have in-page routing, get rid of this.
|
||||
>
|
||||
Sign Up
|
||||
</ButtonLink>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,41 +0,0 @@
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
|
||||
import { AUTH_STATUS } from "~/signals/authentication/enums";
|
||||
import { authentication } from "~/signals";
|
||||
|
||||
import { ButtonLink } from "~/components/ui/ButtonLink";
|
||||
import ProfileDropdown from "~/src/components/ProfileDropdown";
|
||||
|
||||
// TODO MAKE THIS A SHARED COMPONENT ART CRAFT
|
||||
export const AuthButtons = () => {
|
||||
useSignals();
|
||||
|
||||
const { status } = authentication;
|
||||
|
||||
if (status.value === AUTH_STATUS.LOGGED_IN) {
|
||||
return <ProfileDropdown />;
|
||||
} else {
|
||||
return (
|
||||
<div className="flex items-center gap-3.5">
|
||||
<span className="text-white/20">|</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<ButtonLink
|
||||
to="/login"
|
||||
variant="secondary"
|
||||
reloadDocument={true}
|
||||
className="h-[38px]" // TODO(bt,2025-04-19): Once we have in-page routing, get rid of this.
|
||||
>
|
||||
Login
|
||||
</ButtonLink>
|
||||
<ButtonLink
|
||||
to="/signup"
|
||||
reloadDocument={true}
|
||||
className="h-[38px]" // TODO(bt,2025-04-19): Once we have in-page routing, get rid of this.
|
||||
>
|
||||
Sign Up
|
||||
</ButtonLink>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,188 +1,191 @@
|
||||
import { faEnvelope, faKey, faUser } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { GlobalSettingsManager } from "./pages/PageEnigma/GlobalSettingsManager";
|
||||
import { Button, Input } from "~/shared/components";
|
||||
import { addToast, authentication, signUp } from "~/signals";
|
||||
import { FormEvent, useRef, useState, StrictMode } from "react";
|
||||
import { AUTH_STATUS, ToastTypes } from "~/enums";
|
||||
import { useSignalEffect, useSignals } from "@preact/signals-react/runtime";
|
||||
import { useNavigate, useSearchParams, BrowserRouter } from "react-router-dom";
|
||||
import { createRoot } from "react-dom/client";
|
||||
// import { faEnvelope, faKey, faUser } from "@fortawesome/pro-solid-svg-icons";
|
||||
// // import { GlobalSettingsManager } from "./pages/PageEnigma/GlobalSettingsManager";
|
||||
// import { Button } from "@storyteller/ui-button";
|
||||
// import { Input } from "@storyteller/ui-input";
|
||||
|
||||
import "./styles/normalize.css";
|
||||
import "./styles/tailwind.css";
|
||||
import "./styles/base.css";
|
||||
import "@fortawesome/fontawesome-svg-core/styles.css";
|
||||
// // import { addToast, authentication, signUp } from "~/signals";
|
||||
// import { FormEvent, useRef, useState, StrictMode } from "react";
|
||||
// // import { AUTH_STATUS, ToastTypes } from "~/enums";
|
||||
// import { useSignalEffect, useSignals } from "@preact/signals-react/runtime";
|
||||
// import { useNavigate, useSearchParams, BrowserRouter } from "react-router-dom";
|
||||
// import { createRoot } from "react-dom/client";
|
||||
|
||||
import { config } from "@fortawesome/fontawesome-svg-core";
|
||||
// // import "./styles/normalize.css";
|
||||
// // import "./styles/tailwind.css";
|
||||
// // import "./styles/base.css";
|
||||
|
||||
config.autoAddCss = false; /* eslint-disable import/first */
|
||||
// TODO MAKE THIS A SHARED COMPONENT ART CRAFT
|
||||
const regEx =
|
||||
/^(([^<>()[\].,;:\s@"]+(.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i;
|
||||
// import "@fortawesome/fontawesome-svg-core/styles.css";
|
||||
|
||||
// TODO(bt,2025-04-19): Make these configurable
|
||||
const ENV = {
|
||||
BASE_API: "https://api.storyteller.ai",
|
||||
GOOGLE_API: "https://studio.storyteller.ai",
|
||||
FUNNEL_API: "https://studio.storyteller.ai",
|
||||
CDN_API: "https://cdn-2.fakeyou.com",
|
||||
GRAVATAR_API: "https://studio.storyteller.ai",
|
||||
DEPLOY_PRIME_URL: "https://studio.storyteller.ai",
|
||||
};
|
||||
// import { config } from "@fortawesome/fontawesome-svg-core";
|
||||
|
||||
export default function SignUpScreen() {
|
||||
useSignals();
|
||||
const navigate = useNavigate();
|
||||
const formRef = useRef<HTMLFormElement | null>(null);
|
||||
const [usernameError, setUsernameError] = useState("");
|
||||
const [emailError, setEmailError] = useState("");
|
||||
const [passwordError, setPasswordError] = useState("");
|
||||
const [passwordConfirmationError, setPasswordConfirmationError] =
|
||||
useState("");
|
||||
const [searchParams] = useSearchParams();
|
||||
const { status: authStatus } = authentication;
|
||||
// config.autoAddCss = false; /* eslint-disable import/first */
|
||||
// // TODO MAKE THIS A SHARED COMPONENT ART CRAFT
|
||||
// const regEx =
|
||||
// /^(([^<>()[\].,;:\s@"]+(.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i;
|
||||
|
||||
const handleOnSubmit = (ev: FormEvent<HTMLFormElement>) => {
|
||||
ev.preventDefault();
|
||||
if (formRef.current) {
|
||||
const form = new FormData(formRef.current);
|
||||
const email = form.get("email")?.toString();
|
||||
const password = form.get("password")?.toString();
|
||||
const passwordConfirmation = form
|
||||
.get("password-confirmation")
|
||||
?.toString();
|
||||
const username = form.get("username")?.toString();
|
||||
setUsernameError("");
|
||||
if (!username || username.length < 6) {
|
||||
setUsernameError("Username must be at least 6 characters long");
|
||||
}
|
||||
setEmailError("");
|
||||
if (!email || !email.match(regEx)) {
|
||||
setEmailError("Email must be a valid email address");
|
||||
}
|
||||
setPasswordError("");
|
||||
if (!password || password.length < 8) {
|
||||
setPasswordError("Password must be at least 8 characters long");
|
||||
}
|
||||
setPasswordConfirmationError("");
|
||||
if (!passwordError && passwordConfirmation !== password) {
|
||||
setPasswordConfirmationError("Passwords do not match");
|
||||
}
|
||||
// // TODO(bt,2025-04-19): Make these configurable
|
||||
// const ENV = {
|
||||
// BASE_API: "https://api.storyteller.ai",
|
||||
// GOOGLE_API: "https://studio.storyteller.ai",
|
||||
// FUNNEL_API: "https://studio.storyteller.ai",
|
||||
// CDN_API: "https://cdn-2.fakeyou.com",
|
||||
// GRAVATAR_API: "https://studio.storyteller.ai",
|
||||
// DEPLOY_PRIME_URL: "https://studio.storyteller.ai",
|
||||
// };
|
||||
|
||||
if (
|
||||
!usernameError &&
|
||||
!passwordError &&
|
||||
!emailError &&
|
||||
!passwordConfirmationError &&
|
||||
signUp
|
||||
) {
|
||||
signUp({
|
||||
username: username!,
|
||||
email: email!,
|
||||
password: password!,
|
||||
passwordConfirmation: passwordConfirmation!,
|
||||
}).then((error) => {
|
||||
console.log("Error occured", error);
|
||||
if (error) {
|
||||
addToast(ToastTypes.ERROR, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}; // end handleOnSubmit
|
||||
// export default function SignUpScreen() {
|
||||
// useSignals();
|
||||
// const navigate = useNavigate();
|
||||
// const formRef = useRef<HTMLFormElement | null>(null);
|
||||
// const [usernameError, setUsernameError] = useState("");
|
||||
// const [emailError, setEmailError] = useState("");
|
||||
// const [passwordError, setPasswordError] = useState("");
|
||||
// const [passwordConfirmationError, setPasswordConfirmationError] =
|
||||
// useState("");
|
||||
// const [searchParams] = useSearchParams();
|
||||
// const { status: authStatus } = authentication;
|
||||
|
||||
useSignalEffect(() => {
|
||||
const redirectPath = searchParams.get("redirect");
|
||||
if (authStatus.value === AUTH_STATUS.LOGGED_IN) {
|
||||
navigate(redirectPath ? redirectPath : "/");
|
||||
return;
|
||||
}
|
||||
if (authStatus.value === AUTH_STATUS.NO_ACCESS) {
|
||||
window.open("https://storyteller.ai/", "_self");
|
||||
return;
|
||||
}
|
||||
});
|
||||
// const handleOnSubmit = (ev: FormEvent<HTMLFormElement>) => {
|
||||
// ev.preventDefault();
|
||||
// if (formRef.current) {
|
||||
// const form = new FormData(formRef.current);
|
||||
// const email = form.get("email")?.toString();
|
||||
// const password = form.get("password")?.toString();
|
||||
// const passwordConfirmation = form
|
||||
// .get("password-confirmation")
|
||||
// ?.toString();
|
||||
// const username = form.get("username")?.toString();
|
||||
// setUsernameError("");
|
||||
// if (!username || username.length < 6) {
|
||||
// setUsernameError("Username must be at least 6 characters long");
|
||||
// }
|
||||
// setEmailError("");
|
||||
// if (!email || !email.match(regEx)) {
|
||||
// setEmailError("Email must be a valid email address");
|
||||
// }
|
||||
// setPasswordError("");
|
||||
// if (!password || password.length < 8) {
|
||||
// setPasswordError("Password must be at least 8 characters long");
|
||||
// }
|
||||
// setPasswordConfirmationError("");
|
||||
// if (!passwordError && passwordConfirmation !== password) {
|
||||
// setPasswordConfirmationError("Passwords do not match");
|
||||
// }
|
||||
|
||||
return (
|
||||
<div className="fixed flex h-full w-full flex-col items-center justify-center overflow-auto bg-[#1b1b1f] bg-center bg-repeat">
|
||||
<div className="mb-7 flex w-10/12 max-w-2xl items-center justify-center gap-4">
|
||||
<img
|
||||
src="/resources/images/artcraft-logo-3.png"
|
||||
alt="ArtCraft Logo"
|
||||
className="h-9 select-none"
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full max-w-xl rounded-xl shadow-lg">
|
||||
<div className="glass glass-no-hover relative mx-auto w-full rounded-none rounded-t-xl p-6 shadow-none">
|
||||
<h1 className="mb-8 text-center text-2xl font-bold">Sign up</h1>
|
||||
<form
|
||||
ref={formRef}
|
||||
onSubmit={handleOnSubmit}
|
||||
className="flex flex-col gap-4"
|
||||
>
|
||||
<Input
|
||||
label="Username"
|
||||
icon={faUser}
|
||||
placeholder="Username"
|
||||
name="username"
|
||||
errorMessage={usernameError}
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
type="email"
|
||||
label="Email"
|
||||
icon={faEnvelope}
|
||||
placeholder="Email"
|
||||
name="email"
|
||||
errorMessage={emailError}
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
type="password"
|
||||
label="Password"
|
||||
icon={faKey}
|
||||
name="password"
|
||||
placeholder="Password"
|
||||
autoComplete="current-password"
|
||||
errorMessage={passwordError}
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
type="password"
|
||||
label="Password Confirmation"
|
||||
icon={faKey}
|
||||
placeholder="Password Confirmation"
|
||||
name="password-confirmation"
|
||||
errorMessage={passwordConfirmationError}
|
||||
required
|
||||
/>
|
||||
<Button className="mt-4 py-3">Sign up</Button>
|
||||
</form>
|
||||
</div>
|
||||
<div className="align-items flex w-full max-w-xl rounded-b-xl bg-ui-controls px-6 py-4">
|
||||
<div className="flex w-full justify-end gap-1 text-sm">
|
||||
<p className="opacity-75">Already have an account?</p>
|
||||
<a
|
||||
href="/login"
|
||||
className="text-brand-primary-400 hover:text-brand-primary-300 font-medium"
|
||||
>
|
||||
Log in
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// if (
|
||||
// !usernameError &&
|
||||
// !passwordError &&
|
||||
// !emailError &&
|
||||
// !passwordConfirmationError &&
|
||||
// signUp
|
||||
// ) {
|
||||
// signUp({
|
||||
// username: username!,
|
||||
// email: email!,
|
||||
// password: password!,
|
||||
// passwordConfirmation: passwordConfirmation!,
|
||||
// }).then((error) => {
|
||||
// console.log("Error occured", error);
|
||||
// if (error) {
|
||||
// addToast(ToastTypes.ERROR, error);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }; // end handleOnSubmit
|
||||
|
||||
// TODO: Replace environment variables from `root.tsx`
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<>
|
||||
<StrictMode>
|
||||
<BrowserRouter>
|
||||
<GlobalSettingsManager env={ENV} />
|
||||
<SignUpScreen />
|
||||
</BrowserRouter>
|
||||
</StrictMode>
|
||||
</>,
|
||||
);
|
||||
// useSignalEffect(() => {
|
||||
// const redirectPath = searchParams.get("redirect");
|
||||
// if (authStatus.value === AUTH_STATUS.LOGGED_IN) {
|
||||
// navigate(redirectPath ? redirectPath : "/");
|
||||
// return;
|
||||
// }
|
||||
// if (authStatus.value === AUTH_STATUS.NO_ACCESS) {
|
||||
// window.open("https://storyteller.ai/", "_self");
|
||||
// return;
|
||||
// }
|
||||
// });
|
||||
|
||||
// return (
|
||||
// <div className="fixed flex h-full w-full flex-col items-center justify-center overflow-auto bg-[#1b1b1f] bg-center bg-repeat">
|
||||
// <div className="mb-7 flex w-10/12 max-w-2xl items-center justify-center gap-4">
|
||||
// <img
|
||||
// src="/resources/images/artcraft-logo-3.png"
|
||||
// alt="ArtCraft Logo"
|
||||
// className="h-9 select-none"
|
||||
// />
|
||||
// </div>
|
||||
// <div className="w-full max-w-xl rounded-xl shadow-lg">
|
||||
// <div className="glass glass-no-hover relative mx-auto w-full rounded-none rounded-t-xl p-6 shadow-none">
|
||||
// <h1 className="mb-8 text-center text-2xl font-bold">Sign up</h1>
|
||||
// <form
|
||||
// ref={formRef}
|
||||
// onSubmit={handleOnSubmit}
|
||||
// className="flex flex-col gap-4"
|
||||
// >
|
||||
// <Input
|
||||
// label="Username"
|
||||
// icon={faUser}
|
||||
// placeholder="Username"
|
||||
// name="username"
|
||||
// errorMessage={usernameError}
|
||||
// required
|
||||
// />
|
||||
// <Input
|
||||
// type="email"
|
||||
// label="Email"
|
||||
// icon={faEnvelope}
|
||||
// placeholder="Email"
|
||||
// name="email"
|
||||
// errorMessage={emailError}
|
||||
// required
|
||||
// />
|
||||
// <Input
|
||||
// type="password"
|
||||
// label="Password"
|
||||
// icon={faKey}
|
||||
// name="password"
|
||||
// placeholder="Password"
|
||||
// autoComplete="current-password"
|
||||
// errorMessage={passwordError}
|
||||
// required
|
||||
// />
|
||||
// <Input
|
||||
// type="password"
|
||||
// label="Password Confirmation"
|
||||
// icon={faKey}
|
||||
// placeholder="Password Confirmation"
|
||||
// name="password-confirmation"
|
||||
// errorMessage={passwordConfirmationError}
|
||||
// required
|
||||
// />
|
||||
// <Button className="mt-4 py-3">Sign up</Button>
|
||||
// </form>
|
||||
// </div>
|
||||
// <div className="align-items flex w-full max-w-xl rounded-b-xl bg-ui-controls px-6 py-4">
|
||||
// <div className="flex w-full justify-end gap-1 text-sm">
|
||||
// <p className="opacity-75">Already have an account?</p>
|
||||
// <a
|
||||
// href="/login"
|
||||
// className="text-brand-primary-400 hover:text-brand-primary-300 font-medium"
|
||||
// >
|
||||
// Log in
|
||||
// </a>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
|
||||
// // TODO: Replace environment variables from `root.tsx`
|
||||
// createRoot(document.getElementById("root")!).render(
|
||||
// <>
|
||||
// <StrictMode>
|
||||
// <BrowserRouter>
|
||||
|
||||
// <SignUpScreen />
|
||||
// </BrowserRouter>
|
||||
// </StrictMode>
|
||||
// </>,
|
||||
// );
|
||||
@@ -1,188 +1,193 @@
|
||||
import { faEnvelope, faKey, faUser } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { GlobalSettingsManager } from "./pages/PageEnigma/GlobalSettingsManager";
|
||||
import { Button, Input } from "~/components";
|
||||
import { addToast, authentication, signUp } from "~/signals";
|
||||
import { FormEvent, useRef, useState, StrictMode } from "react";
|
||||
import { AUTH_STATUS, ToastTypes } from "~/enums";
|
||||
import { useSignalEffect, useSignals } from "@preact/signals-react/runtime";
|
||||
import { useNavigate, useSearchParams, BrowserRouter } from "react-router-dom";
|
||||
import { createRoot } from "react-dom/client";
|
||||
// import { faEnvelope, faKey, faUser } from "@fortawesome/pro-solid-svg-icons";
|
||||
// // import { GlobalSettingsManager } from "./pages/PageEnigma/GlobalSettingsManager";
|
||||
|
||||
import "./styles/normalize.css";
|
||||
import "./styles/tailwind.css";
|
||||
import "./styles/base.css";
|
||||
import "@fortawesome/fontawesome-svg-core/styles.css";
|
||||
// import { Button } from "@storyteller/ui-button";
|
||||
// import { Input } from "@storyteller/ui-input";
|
||||
// import { Toaster } from "@storyteller/ui-toaster";
|
||||
|
||||
import { config } from "@fortawesome/fontawesome-svg-core";
|
||||
// // import { authentication, signUp } from "~/signals";
|
||||
// import { FormEvent, useRef, useState, StrictMode } from "react";
|
||||
// // import { AUTH_STATUS, ToastTypes } from "~/enums";
|
||||
// import { useSignalEffect, useSignals } from "@preact/signals-react/runtime";
|
||||
// import { useNavigate, useSearchParams, BrowserRouter } from "react-router-dom";
|
||||
// import { createRoot } from "react-dom/client";
|
||||
|
||||
config.autoAddCss = false; /* eslint-disable import/first */
|
||||
// TODO MAKE THIS A SHARED COMPONENT ART CRAFT
|
||||
const regEx =
|
||||
/^(([^<>()[\].,;:\s@"]+(.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i;
|
||||
// // import "./styles/normalize.css";
|
||||
// // import "./styles/tailwind.css";
|
||||
// // import "./styles/base.css";
|
||||
|
||||
// TODO(bt,2025-04-19): Make these configurable
|
||||
const ENV = {
|
||||
BASE_API: "https://api.storyteller.ai",
|
||||
GOOGLE_API: "https://studio.storyteller.ai",
|
||||
FUNNEL_API: "https://studio.storyteller.ai",
|
||||
CDN_API: "https://cdn-2.fakeyou.com",
|
||||
GRAVATAR_API: "https://studio.storyteller.ai",
|
||||
DEPLOY_PRIME_URL: "https://studio.storyteller.ai",
|
||||
};
|
||||
// import "@fortawesome/fontawesome-svg-core/styles.css";
|
||||
|
||||
export default function SignUpScreen() {
|
||||
useSignals();
|
||||
const navigate = useNavigate();
|
||||
const formRef = useRef<HTMLFormElement | null>(null);
|
||||
const [usernameError, setUsernameError] = useState("");
|
||||
const [emailError, setEmailError] = useState("");
|
||||
const [passwordError, setPasswordError] = useState("");
|
||||
const [passwordConfirmationError, setPasswordConfirmationError] =
|
||||
useState("");
|
||||
const [searchParams] = useSearchParams();
|
||||
const { status: authStatus } = authentication;
|
||||
// import { config } from "@fortawesome/fontawesome-svg-core";
|
||||
|
||||
const handleOnSubmit = (ev: FormEvent<HTMLFormElement>) => {
|
||||
ev.preventDefault();
|
||||
if (formRef.current) {
|
||||
const form = new FormData(formRef.current);
|
||||
const email = form.get("email")?.toString();
|
||||
const password = form.get("password")?.toString();
|
||||
const passwordConfirmation = form
|
||||
.get("password-confirmation")
|
||||
?.toString();
|
||||
const username = form.get("username")?.toString();
|
||||
setUsernameError("");
|
||||
if (!username || username.length < 6) {
|
||||
setUsernameError("Username must be at least 6 characters long");
|
||||
}
|
||||
setEmailError("");
|
||||
if (!email || !email.match(regEx)) {
|
||||
setEmailError("Email must be a valid email address");
|
||||
}
|
||||
setPasswordError("");
|
||||
if (!password || password.length < 8) {
|
||||
setPasswordError("Password must be at least 8 characters long");
|
||||
}
|
||||
setPasswordConfirmationError("");
|
||||
if (!passwordError && passwordConfirmation !== password) {
|
||||
setPasswordConfirmationError("Passwords do not match");
|
||||
}
|
||||
// config.autoAddCss = false; /* eslint-disable import/first */
|
||||
// // TODO MAKE THIS A SHARED COMPONENT ART CRAFT
|
||||
// const regEx =
|
||||
// /^(([^<>()[\].,;:\s@"]+(.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i;
|
||||
|
||||
if (
|
||||
!usernameError &&
|
||||
!passwordError &&
|
||||
!emailError &&
|
||||
!passwordConfirmationError &&
|
||||
signUp
|
||||
) {
|
||||
signUp({
|
||||
username: username!,
|
||||
email: email!,
|
||||
password: password!,
|
||||
passwordConfirmation: passwordConfirmation!,
|
||||
}).then((error) => {
|
||||
console.log("Error occured", error);
|
||||
if (error) {
|
||||
addToast(ToastTypes.ERROR, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}; // end handleOnSubmit
|
||||
// // TODO(bt,2025-04-19): Make these configurable
|
||||
// const ENV = {
|
||||
// BASE_API: "https://api.storyteller.ai",
|
||||
// GOOGLE_API: "https://studio.storyteller.ai",
|
||||
// FUNNEL_API: "https://studio.storyteller.ai",
|
||||
// CDN_API: "https://cdn-2.fakeyou.com",
|
||||
// GRAVATAR_API: "https://studio.storyteller.ai",
|
||||
// DEPLOY_PRIME_URL: "https://studio.storyteller.ai",
|
||||
// };
|
||||
|
||||
useSignalEffect(() => {
|
||||
const redirectPath = searchParams.get("redirect");
|
||||
if (authStatus.value === AUTH_STATUS.LOGGED_IN) {
|
||||
navigate(redirectPath ? redirectPath : "/");
|
||||
return;
|
||||
}
|
||||
if (authStatus.value === AUTH_STATUS.NO_ACCESS) {
|
||||
window.open("https://storyteller.ai/", "_self");
|
||||
return;
|
||||
}
|
||||
});
|
||||
// export default function SignUpScreen() {
|
||||
// useSignals();
|
||||
// const navigate = useNavigate();
|
||||
// const formRef = useRef<HTMLFormElement | null>(null);
|
||||
// const [usernameError, setUsernameError] = useState("");
|
||||
// const [emailError, setEmailError] = useState("");
|
||||
// const [passwordError, setPasswordError] = useState("");
|
||||
// const [passwordConfirmationError, setPasswordConfirmationError] =
|
||||
// useState("");
|
||||
// const [searchParams] = useSearchParams();
|
||||
// // const { status: authStatus } = authentication;
|
||||
|
||||
return (
|
||||
<div className="fixed flex h-full w-full flex-col items-center justify-center overflow-auto bg-[#1b1b1f] bg-center bg-repeat">
|
||||
<div className="mb-7 flex w-10/12 max-w-2xl items-center justify-center gap-4">
|
||||
<img
|
||||
src="/resources/images/artcraft-logo-3.png"
|
||||
alt="ArtCraft Logo"
|
||||
className="h-9 select-none"
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full max-w-xl rounded-xl shadow-lg">
|
||||
<div className="glass glass-no-hover relative mx-auto w-full rounded-none rounded-t-xl p-6 shadow-none">
|
||||
<h1 className="mb-8 text-center text-2xl font-bold">Sign up</h1>
|
||||
<form
|
||||
ref={formRef}
|
||||
onSubmit={handleOnSubmit}
|
||||
className="flex flex-col gap-4"
|
||||
>
|
||||
<Input
|
||||
label="Username"
|
||||
icon={faUser}
|
||||
placeholder="Username"
|
||||
name="username"
|
||||
errorMessage={usernameError}
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
type="email"
|
||||
label="Email"
|
||||
icon={faEnvelope}
|
||||
placeholder="Email"
|
||||
name="email"
|
||||
errorMessage={emailError}
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
type="password"
|
||||
label="Password"
|
||||
icon={faKey}
|
||||
name="password"
|
||||
placeholder="Password"
|
||||
autoComplete="current-password"
|
||||
errorMessage={passwordError}
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
type="password"
|
||||
label="Password Confirmation"
|
||||
icon={faKey}
|
||||
placeholder="Password Confirmation"
|
||||
name="password-confirmation"
|
||||
errorMessage={passwordConfirmationError}
|
||||
required
|
||||
/>
|
||||
<Button className="mt-4 py-3">Sign up</Button>
|
||||
</form>
|
||||
</div>
|
||||
<div className="align-items flex w-full max-w-xl rounded-b-xl bg-ui-controls px-6 py-4">
|
||||
<div className="flex w-full justify-end gap-1 text-sm">
|
||||
<p className="opacity-75">Already have an account?</p>
|
||||
<a
|
||||
href="/login"
|
||||
className="text-brand-primary-400 hover:text-brand-primary-300 font-medium"
|
||||
>
|
||||
Log in
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// const handleOnSubmit = (ev: FormEvent<HTMLFormElement>) => {
|
||||
// ev.preventDefault();
|
||||
// if (formRef.current) {
|
||||
// const form = new FormData(formRef.current);
|
||||
// const email = form.get("email")?.toString();
|
||||
// const password = form.get("password")?.toString();
|
||||
// const passwordConfirmation = form
|
||||
// .get("password-confirmation")
|
||||
// ?.toString();
|
||||
// const username = form.get("username")?.toString();
|
||||
// setUsernameError("");
|
||||
// if (!username || username.length < 6) {
|
||||
// setUsernameError("Username must be at least 6 characters long");
|
||||
// }
|
||||
// setEmailError("");
|
||||
// if (!email || !email.match(regEx)) {
|
||||
// setEmailError("Email must be a valid email address");
|
||||
// }
|
||||
// setPasswordError("");
|
||||
// if (!password || password.length < 8) {
|
||||
// setPasswordError("Password must be at least 8 characters long");
|
||||
// }
|
||||
// setPasswordConfirmationError("");
|
||||
// if (!passwordError && passwordConfirmation !== password) {
|
||||
// setPasswordConfirmationError("Passwords do not match");
|
||||
// }
|
||||
|
||||
// TODO: Replace environment variables from `root.tsx`
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<>
|
||||
<StrictMode>
|
||||
<BrowserRouter>
|
||||
<GlobalSettingsManager env={ENV} />
|
||||
<SignUpScreen />
|
||||
</BrowserRouter>
|
||||
</StrictMode>
|
||||
</>,
|
||||
);
|
||||
// if (
|
||||
// !usernameError &&
|
||||
// !passwordError &&
|
||||
// !emailError &&
|
||||
// !passwordConfirmationError &&
|
||||
// signUp
|
||||
// ) {
|
||||
// signUp({
|
||||
// username: username!,
|
||||
// email: email!,
|
||||
// password: password!,
|
||||
// passwordConfirmation: passwordConfirmation!,
|
||||
// }).then((error) => {
|
||||
// console.log("Error occured", error);
|
||||
// if (error) {
|
||||
// Toaster.toast(ToastTypes.ERROR, error);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }; // end handleOnSubmit
|
||||
|
||||
// useSignalEffect(() => {
|
||||
// const redirectPath = searchParams.get("redirect");
|
||||
// if (authStatus.value === AUTH_STATUS.LOGGED_IN) {
|
||||
// navigate(redirectPath ? redirectPath : "/");
|
||||
// return;
|
||||
// }
|
||||
// if (authStatus.value === AUTH_STATUS.NO_ACCESS) {
|
||||
// window.open("https://storyteller.ai/", "_self");
|
||||
// return;
|
||||
// }
|
||||
// });
|
||||
|
||||
// return (
|
||||
// <div className="fixed flex h-full w-full flex-col items-center justify-center overflow-auto bg-[#1b1b1f] bg-center bg-repeat">
|
||||
// <div className="mb-7 flex w-10/12 max-w-2xl items-center justify-center gap-4">
|
||||
// <img
|
||||
// src="/resources/images/artcraft-logo-3.png"
|
||||
// alt="ArtCraft Logo"
|
||||
// className="h-9 select-none"
|
||||
// />
|
||||
// </div>
|
||||
// <div className="w-full max-w-xl rounded-xl shadow-lg">
|
||||
// <div className="glass glass-no-hover relative mx-auto w-full rounded-none rounded-t-xl p-6 shadow-none">
|
||||
// <h1 className="mb-8 text-center text-2xl font-bold">Sign up</h1>
|
||||
// <form
|
||||
// ref={formRef}
|
||||
// onSubmit={handleOnSubmit}
|
||||
// className="flex flex-col gap-4"
|
||||
// >
|
||||
// <Input
|
||||
// label="Username"
|
||||
// icon={faUser}
|
||||
// placeholder="Username"
|
||||
// name="username"
|
||||
// errorMessage={usernameError}
|
||||
// required
|
||||
// />
|
||||
// <Input
|
||||
// type="email"
|
||||
// label="Email"
|
||||
// icon={faEnvelope}
|
||||
// placeholder="Email"
|
||||
// name="email"
|
||||
// errorMessage={emailError}
|
||||
// required
|
||||
// />
|
||||
// <Input
|
||||
// type="password"
|
||||
// label="Password"
|
||||
// icon={faKey}
|
||||
// name="password"
|
||||
// placeholder="Password"
|
||||
// autoComplete="current-password"
|
||||
// errorMessage={passwordError}
|
||||
// required
|
||||
// />
|
||||
// <Input
|
||||
// type="password"
|
||||
// label="Password Confirmation"
|
||||
// icon={faKey}
|
||||
// placeholder="Password Confirmation"
|
||||
// name="password-confirmation"
|
||||
// errorMessage={passwordConfirmationError}
|
||||
// required
|
||||
// />
|
||||
// <Button className="mt-4 py-3">Sign up</Button>
|
||||
// </form>
|
||||
// </div>
|
||||
// <div className="align-items flex w-full max-w-xl rounded-b-xl bg-ui-controls px-6 py-4">
|
||||
// <div className="flex w-full justify-end gap-1 text-sm">
|
||||
// <p className="opacity-75">Already have an account?</p>
|
||||
// <a
|
||||
// href="/login"
|
||||
// className="text-brand-primary-400 hover:text-brand-primary-300 font-medium"
|
||||
// >
|
||||
// Log in
|
||||
// </a>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
|
||||
// // TODO: Replace environment variables from `root.tsx`
|
||||
// createRoot(document.getElementById("root")!).render(
|
||||
// <>
|
||||
// <StrictMode>
|
||||
// <BrowserRouter>
|
||||
// {/* <GlobalSettingsManager env={ENV} /> */}
|
||||
// <SignUpScreen />
|
||||
// </BrowserRouter>
|
||||
// </StrictMode>
|
||||
// </>,
|
||||
// );
|
||||
@@ -28,6 +28,12 @@
|
||||
"src"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../libs/components/toaster/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../../libs/components/input/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../../libs/components/settings-modal/tsconfig.lib.json"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../libs/components/toaster"
|
||||
},
|
||||
{
|
||||
"path": "../../libs/components/input"
|
||||
},
|
||||
{
|
||||
"path": "../../libs/components/settings-modal"
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user