Compare commits
No commits in common. "bug/refine-remix-vite" and "master" have entirely different histories.
bug/refine
...
master
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2024 Hammer Technologies LLC
|
||||
Copyright (c) 2024 LumeWeb
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
|
|
@ -64,36 +64,34 @@ export const FieldCheckbox = ({
|
|||
const id = inputProps.id ?? fallbackId
|
||||
const errorId = errors?.length ? `${id}-error` : undefined
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={cn("space-x-2 flex items-center text-primary-2", className)}
|
||||
>
|
||||
<Checkbox
|
||||
{...checkboxProps}
|
||||
id={id}
|
||||
aria-invalid={errorId ? true : undefined}
|
||||
aria-describedby={errorId}
|
||||
checked={input.value === checkedValue}
|
||||
onCheckedChange={(state) => {
|
||||
input.change(state.valueOf() ? checkedValue : "")
|
||||
inputProps.onCheckedChange?.(state)
|
||||
}}
|
||||
onFocus={(event) => {
|
||||
input.focus()
|
||||
inputProps.onFocus?.(event)
|
||||
}}
|
||||
onBlur={(event) => {
|
||||
input.blur()
|
||||
inputProps.onBlur?.(event)
|
||||
}}
|
||||
type="button"
|
||||
/>
|
||||
<Label {...labelProps} htmlFor={id} />
|
||||
</div>
|
||||
<div
|
||||
className={cn("space-x-2 flex items-center text-primary-2", className)}
|
||||
>
|
||||
<Checkbox
|
||||
{...checkboxProps}
|
||||
id={id}
|
||||
aria-invalid={errorId ? true : undefined}
|
||||
aria-describedby={errorId}
|
||||
checked={input.value === checkedValue}
|
||||
onCheckedChange={(state) => {
|
||||
input.change(state.valueOf() ? checkedValue : "")
|
||||
inputProps.onCheckedChange?.(state)
|
||||
}}
|
||||
onFocus={(event) => {
|
||||
input.focus()
|
||||
inputProps.onFocus?.(event)
|
||||
}}
|
||||
onBlur={(event) => {
|
||||
input.blur()
|
||||
inputProps.onBlur?.(event)
|
||||
}}
|
||||
type="button"
|
||||
/>
|
||||
<Label {...labelProps} htmlFor={id} />
|
||||
<div className="min-h-[32px] px-4 pb-3 pt-1">
|
||||
{errorId ? <ErrorList id={errorId} errors={errors} /> : null}
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -110,7 +108,7 @@ export function ErrorList({
|
|||
return (
|
||||
<ul id={id} className="flex flex-col gap-1">
|
||||
{errorsToRender.map((e) => (
|
||||
<li key={e} className="text-[12px] text-destructive-foreground">
|
||||
<li key={e} className="text-[10px] text-foreground-destructive">
|
||||
{e}
|
||||
</li>
|
||||
))}
|
||||
|
|
|
@ -7,7 +7,7 @@ import { cn } from "~/utils"
|
|||
const Checkbox = React.forwardRef<
|
||||
React.ElementRef<typeof CheckboxPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> & {
|
||||
className?: string
|
||||
className: string
|
||||
}
|
||||
>(({ className, ...props }, ref) => (
|
||||
<CheckboxPrimitive.Root
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
import { AuthProvider } from "@refinedev/core"
|
||||
import type {
|
||||
AuthActionResponse,
|
||||
CheckResponse,
|
||||
OnErrorResponse
|
||||
} from "@refinedev/core/dist/interfaces"
|
||||
|
||||
export const authProvider: AuthProvider = {
|
||||
login: async (params: any) => {
|
||||
return { success: true } satisfies AuthActionResponse
|
||||
},
|
||||
logout: async (params: any) => {
|
||||
return { success: true } satisfies AuthActionResponse
|
||||
},
|
||||
check: async (params?: any) => {
|
||||
return { authenticated: true } satisfies CheckResponse
|
||||
},
|
||||
onError: async (error: any) => {
|
||||
return { logout: true } satisfies OnErrorResponse
|
||||
},
|
||||
register: async (params: any) => {
|
||||
return { success: true } satisfies AuthActionResponse
|
||||
},
|
||||
forgotPassword: async (params: any) => {
|
||||
return { success: true } satisfies AuthActionResponse
|
||||
},
|
||||
updatePassword: async (params: any) => {
|
||||
return { success: true } satisfies AuthActionResponse
|
||||
},
|
||||
getPermissions: async (params: any) => {
|
||||
return { success: true } satisfies AuthActionResponse
|
||||
},
|
||||
getIdentity: async (params: any) => {
|
||||
return { id: "1", fullName: "John Doe", avatar: "https://via.placeholder.com/150" }
|
||||
}
|
||||
}
|
Binary file not shown.
30
app/root.tsx
30
app/root.tsx
|
@ -3,22 +3,19 @@ import {
|
|||
Meta,
|
||||
Outlet,
|
||||
Scripts,
|
||||
ScrollRestoration
|
||||
} from "@remix-run/react"
|
||||
ScrollRestoration,
|
||||
} from "@remix-run/react";
|
||||
|
||||
import stylesheet from "./tailwind.css?url"
|
||||
import { LinksFunction } from "@remix-run/node"
|
||||
import stylesheet from "./tailwind.css?url";
|
||||
import { LinksFunction } from "@remix-run/node";
|
||||
|
||||
// Supports weights 200-800
|
||||
import "@fontsource-variable/manrope"
|
||||
import { Refine } from "@refinedev/core"
|
||||
import routerProvider from "@refinedev/remix-router";
|
||||
import { authProvider } from "./data/auth-provider"
|
||||
import '@fontsource-variable/manrope';
|
||||
|
||||
export const links: LinksFunction = () => [
|
||||
{ rel: "stylesheet", href: stylesheet }
|
||||
{ rel: "stylesheet", href: stylesheet },
|
||||
// { rel: "stylesheet", href: manropeStylesheet },
|
||||
]
|
||||
];
|
||||
|
||||
export function Layout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
|
@ -30,23 +27,18 @@ export function Layout({ children }: { children: React.ReactNode }) {
|
|||
<Links />
|
||||
</head>
|
||||
<body>
|
||||
<Refine
|
||||
authProvider={authProvider}
|
||||
routerProvider={routerProvider}
|
||||
>
|
||||
{children}
|
||||
</Refine>
|
||||
{children}
|
||||
<ScrollRestoration />
|
||||
<Scripts />
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
return <Outlet />
|
||||
return <Outlet />;
|
||||
}
|
||||
|
||||
export function HydrateFallback() {
|
||||
return <p>Loading...</p>
|
||||
return <p>Loading...</p>;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,80 @@
|
|||
import Login from "./login"
|
||||
import type { MetaFunction } from "@remix-run/node"
|
||||
import { Link } from "@remix-run/react"
|
||||
import { Button } from "~/components/ui/button"
|
||||
import logoPng from "~/images/lume-logo.png?url"
|
||||
import lumeColorLogoPng from "~/images/lume-color-logo.png?url"
|
||||
import discordLogoPng from "~/images/discord-logo.png?url"
|
||||
import lumeBgPng from "~/images/lume-bg-image.png?url"
|
||||
import { Field, FieldCheckbox } from "~/components/forms"
|
||||
|
||||
export const meta: MetaFunction = () => {
|
||||
return [
|
||||
{ title: "New Remix SPA" },
|
||||
{ name: "description", content: "Welcome to Remix (SPA Mode)!" }
|
||||
]
|
||||
}
|
||||
|
||||
export default function Index() {
|
||||
const isLogged = false
|
||||
|
||||
if (isLogged) {
|
||||
window.location.href = "/dashboard"
|
||||
} else {
|
||||
window.location.href = "/login"
|
||||
}
|
||||
|
||||
return isLogged ? <div>Dashboard</div> : <Login />
|
||||
return (
|
||||
<div className="p-10 h-screen relative overflow-clip">
|
||||
<header>
|
||||
<img src={logoPng} alt="Lume logo" className="h-10"></img>
|
||||
</header>
|
||||
<form className="w-full p-2 max-w-md space-y-4 mt-12 bg-background">
|
||||
<h2 className="text-3xl font-bold !mb-12">Welcome back! 🎉</h2>
|
||||
<Field
|
||||
inputProps={{ name: "email" }}
|
||||
labelProps={{ children: "Email" }}
|
||||
/>
|
||||
<Field
|
||||
inputProps={{ name: "password", type: "password" }}
|
||||
labelProps={{ children: "Password" }}
|
||||
/>
|
||||
<FieldCheckbox
|
||||
inputProps={{ name: "rememberMe" }}
|
||||
labelProps={{ children: "Remember Me" }}
|
||||
/>
|
||||
<Button className="w-full h-14">Login</Button>
|
||||
<p className="text-input-placeholder">
|
||||
Forgot your password?{" "}
|
||||
<Link
|
||||
to="/sign-up"
|
||||
className="text-primary-1 text-md hover:underline hover:underline-offset-4"
|
||||
>
|
||||
Reset Password
|
||||
</Link>
|
||||
</p>
|
||||
<Button className="w-full h-14" variant={"outline"}>
|
||||
Create an Account
|
||||
</Button>
|
||||
</form>
|
||||
<img src={lumeBgPng} alt="Lume background" className="absolute top-0 right-0 md:w-2/3 object-cover z-[-1]"></img>
|
||||
<footer className="absolute bottom-5">
|
||||
<ul className="flex flex-row">
|
||||
<li>
|
||||
<Link to="https://discord.lumeweb.com">
|
||||
<Button
|
||||
variant={"link"}
|
||||
className="flex flex-row gap-x-2 text-input-placeholder"
|
||||
>
|
||||
<img className="h-5" src={discordLogoPng} alt="Discord Logo" />
|
||||
Connect with us
|
||||
</Button>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="https://lumeweb.com">
|
||||
<Button
|
||||
variant={"link"}
|
||||
className="flex flex-row gap-x-2 text-input-placeholder"
|
||||
>
|
||||
<img className="h-5" src={lumeColorLogoPng} alt="Lume Logo" />
|
||||
Connect with us
|
||||
</Button>
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</footer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,179 +0,0 @@
|
|||
import type { MetaFunction } from "@remix-run/node"
|
||||
import { Link, useLocation } from "@remix-run/react"
|
||||
import { z } from "zod"
|
||||
import { Button } from "~/components/ui/button"
|
||||
import logoPng from "~/images/lume-logo.png?url"
|
||||
import lumeColorLogoPng from "~/images/lume-color-logo.png?url"
|
||||
import discordLogoPng from "~/images/discord-logo.png?url"
|
||||
import lumeBgPng from "~/images/lume-bg-image.png?url"
|
||||
import { Field, FieldCheckbox } from "~/components/forms"
|
||||
import { getFormProps, useForm } from "@conform-to/react"
|
||||
import { getZodConstraint, parseWithZod } from "@conform-to/zod"
|
||||
|
||||
export const meta: MetaFunction = () => {
|
||||
return [
|
||||
{ title: "Login" },
|
||||
{ name: "description", content: "Welcome to Lume!" }
|
||||
]
|
||||
}
|
||||
|
||||
export default function Login() {
|
||||
const location = useLocation()
|
||||
const hash = location.hash
|
||||
|
||||
return (
|
||||
<div className="p-10 h-screen relative overflow-clip">
|
||||
<header>
|
||||
<img src={logoPng} alt="Lume logo" className="h-10" />
|
||||
</header>
|
||||
<div className="fixed inset-0 -z-10 overflow-clip">
|
||||
<img
|
||||
src={lumeBgPng}
|
||||
alt="Lume background"
|
||||
className="absolute top-0 right-0 md:w-2/3 object-cover z-[-1]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{hash === "" && <LoginForm />}
|
||||
{hash === "#otp" && <OtpForm />}
|
||||
|
||||
<footer className="my-5">
|
||||
<ul className="flex flex-row">
|
||||
<li>
|
||||
<Link to="https://discord.lumeweb.com">
|
||||
<Button
|
||||
variant={"link"}
|
||||
className="flex flex-row gap-x-2 text-input-placeholder"
|
||||
>
|
||||
<img className="h-5" src={discordLogoPng} alt="Discord Logo" />
|
||||
Connect with us
|
||||
</Button>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="https://lumeweb.com">
|
||||
<Button
|
||||
variant={"link"}
|
||||
className="flex flex-row gap-x-2 text-input-placeholder"
|
||||
>
|
||||
<img className="h-5" src={lumeColorLogoPng} alt="Lume Logo" />
|
||||
Connect with us
|
||||
</Button>
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</footer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const LoginSchema = z.object({
|
||||
email: z.string().email(),
|
||||
password: z.string(),
|
||||
rememberMe: z.boolean()
|
||||
})
|
||||
|
||||
const LoginForm = () => {
|
||||
const [form, fields] = useForm({
|
||||
id: "login",
|
||||
constraint: getZodConstraint(LoginSchema),
|
||||
onValidate({ formData }) {
|
||||
return parseWithZod(formData, { schema: LoginSchema })
|
||||
},
|
||||
shouldValidate: "onSubmit"
|
||||
})
|
||||
|
||||
return (
|
||||
<form
|
||||
className="w-full p-2 max-w-md space-y-3 mt-12 bg-background"
|
||||
{...getFormProps(form)}
|
||||
>
|
||||
<h2 className="text-3xl font-bold !mb-12">Welcome back! 🎉</h2>
|
||||
<Field
|
||||
inputProps={{ name: fields.email.name }}
|
||||
labelProps={{ children: "Email" }}
|
||||
errors={fields.email.errors}
|
||||
/>
|
||||
<Field
|
||||
inputProps={{ name: fields.password.name, type: "password" }}
|
||||
labelProps={{ children: "Password" }}
|
||||
errors={fields.password.errors}
|
||||
/>
|
||||
<FieldCheckbox
|
||||
inputProps={{ name: fields.rememberMe.name, form: form.id }}
|
||||
labelProps={{ children: "Remember Me" }}
|
||||
errors={fields.rememberMe.errors}
|
||||
/>
|
||||
<Button className="w-full h-14">Login</Button>
|
||||
<p className="inline-block text-input-placeholder">
|
||||
Forgot your password?{" "}
|
||||
<Link
|
||||
to="/reset-password"
|
||||
className="text-primary-1 text-md hover:underline hover:underline-offset-4"
|
||||
>
|
||||
Reset Password
|
||||
</Link>
|
||||
</p>
|
||||
<Link to="/sign-up" className="block">
|
||||
<Button type="button" className="w-full h-14" variant={"outline"}>
|
||||
Create an Account
|
||||
</Button>
|
||||
</Link>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
const OtpSchema = z.object({
|
||||
otp: z.string().length(6, { message: "OTP must be 6 characters" })
|
||||
})
|
||||
|
||||
const OtpForm = () => {
|
||||
// TODO: Add support for resending the OTP
|
||||
const [form, fields] = useForm({
|
||||
id: "otp",
|
||||
constraint: getZodConstraint(OtpSchema),
|
||||
onValidate({ formData }) {
|
||||
return parseWithZod(formData, { schema: OtpSchema })
|
||||
},
|
||||
shouldValidate: "onSubmit"
|
||||
})
|
||||
const valid = false // TODO: some sort of logic to verify user is on OTP state validly
|
||||
|
||||
if (!valid) {
|
||||
location.hash = ""
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<form
|
||||
className="w-full p-2 max-w-md mt-12 bg-background"
|
||||
{...getFormProps(form)}
|
||||
>
|
||||
<span className="block !mb-8 space-y-2">
|
||||
<h2 className="text-3xl font-bold">Check your inbox</h2>
|
||||
<p className="text-input-placeholder">
|
||||
We will need the six digit confirmation code you received in your
|
||||
email in order to verify your account and get started. Didn’t receive
|
||||
a code?{" "}
|
||||
<Button type="button" variant={"link"} className="text-md h-0">
|
||||
Resend now →
|
||||
</Button>
|
||||
</p>
|
||||
</span>
|
||||
<Field
|
||||
inputProps={{ name: fields.otp.name }}
|
||||
labelProps={{ children: "Confirmation Code" }}
|
||||
errors={fields.otp.errors}
|
||||
/>
|
||||
<Button className="w-full h-14">Verify</Button>
|
||||
<p className="text-input-placeholder w-full text-left">
|
||||
<Link
|
||||
to="/login"
|
||||
className="text-primary-1 text-md hover:underline hover:underline-offset-4"
|
||||
>
|
||||
← Back to Login
|
||||
</Link>
|
||||
</p>
|
||||
</form>
|
||||
)
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
import type { MetaFunction } from "@remix-run/node"
|
||||
import { Link } from "@remix-run/react"
|
||||
import { Button } from "~/components/ui/button"
|
||||
import logoPng from "~/images/lume-logo.png?url"
|
||||
import lumeColorLogoPng from "~/images/lume-color-logo.png?url"
|
||||
import discordLogoPng from "~/images/discord-logo.png?url"
|
||||
import lumeBgPng from "~/images/lume-bg-image.png?url"
|
||||
import { Field } from "~/components/forms"
|
||||
import { getFormProps, useForm } from "@conform-to/react"
|
||||
import { z } from "zod"
|
||||
import { getZodConstraint, parseWithZod } from "@conform-to/zod"
|
||||
|
||||
export const meta: MetaFunction = () => {
|
||||
return [{ title: "Sign Up" }]
|
||||
}
|
||||
|
||||
const RecoverPasswordSchema = z
|
||||
.object({
|
||||
email: z.string().email(),
|
||||
})
|
||||
export default function RecoverPassword() {
|
||||
const [form, fields] = useForm({
|
||||
id: "sign-up",
|
||||
constraint: getZodConstraint(RecoverPasswordSchema),
|
||||
onValidate({ formData }) {
|
||||
return parseWithZod(formData, { schema: RecoverPasswordSchema })
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="p-10 h-screen relative">
|
||||
<header>
|
||||
<img src={logoPng} alt="Lume logo" className="h-10" />
|
||||
</header>
|
||||
<form
|
||||
className="w-full p-2 max-w-md space-y-4 mt-12 bg-background"
|
||||
{...getFormProps(form)}
|
||||
>
|
||||
<span className="!mb-12 space-y-2">
|
||||
<h2 className="text-3xl font-bold">Reset your password</h2>
|
||||
</span>
|
||||
<Field
|
||||
inputProps={{ name: fields.email.name }}
|
||||
labelProps={{ children: "Email Address" }}
|
||||
errors={fields.email.errors}
|
||||
/>
|
||||
<Button className="w-full h-14">Create Account</Button>
|
||||
<p className="text-input-placeholder w-full text-left">
|
||||
<Link
|
||||
to="/login"
|
||||
className="text-primary-1 text-md hover:underline hover:underline-offset-4"
|
||||
>
|
||||
← Back to Login
|
||||
</Link>
|
||||
</p>
|
||||
</form>
|
||||
<div className="fixed inset-0 -z-10 overflow-clip">
|
||||
<img
|
||||
src={lumeBgPng}
|
||||
alt="Lume background"
|
||||
className="absolute top-0 right-0 md:w-2/3 object-cover z-[-1]"
|
||||
/>
|
||||
</div>
|
||||
<footer className="my-5">
|
||||
<ul className="flex flex-row">
|
||||
<li>
|
||||
<Link to="https://discord.lumeweb.com">
|
||||
<Button
|
||||
variant={"link"}
|
||||
className="flex flex-row gap-x-2 text-input-placeholder"
|
||||
>
|
||||
<img className="h-5" src={discordLogoPng} alt="Discord Logo" />
|
||||
Connect with us
|
||||
</Button>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="https://lumeweb.com">
|
||||
<Button
|
||||
variant={"link"}
|
||||
className="flex flex-row gap-x-2 text-input-placeholder"
|
||||
>
|
||||
<img className="h-5" src={lumeColorLogoPng} alt="Lume Logo" />
|
||||
Connect with us
|
||||
</Button>
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</footer>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,157 +0,0 @@
|
|||
import type { MetaFunction } from "@remix-run/node"
|
||||
import { Link } from "@remix-run/react"
|
||||
import { Button } from "~/components/ui/button"
|
||||
import logoPng from "~/images/lume-logo.png?url"
|
||||
import lumeColorLogoPng from "~/images/lume-color-logo.png?url"
|
||||
import discordLogoPng from "~/images/discord-logo.png?url"
|
||||
import lumeBgPng from "~/images/lume-bg-image.png?url"
|
||||
import { Field, FieldCheckbox } from "~/components/forms"
|
||||
import { getFormProps, useForm } from "@conform-to/react"
|
||||
import { z } from "zod"
|
||||
import { getZodConstraint, parseWithZod } from "@conform-to/zod"
|
||||
|
||||
export const meta: MetaFunction = () => {
|
||||
return [{ title: "Sign Up" }]
|
||||
}
|
||||
|
||||
const SignUpSchema = z
|
||||
.object({
|
||||
email: z.string().email(),
|
||||
password: z
|
||||
.string()
|
||||
.min(8, { message: "Password must be at least 8 characters" }),
|
||||
confirmPassword: z
|
||||
.string()
|
||||
.min(8, { message: "Password must be at least 8 characters" }),
|
||||
termsOfService: z.boolean({
|
||||
required_error: "You must agree to the terms of service"
|
||||
})
|
||||
})
|
||||
.superRefine((data, ctx) => {
|
||||
if (data.password !== data.confirmPassword) {
|
||||
return ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["confirmPassword"],
|
||||
message: "Passwords do not match"
|
||||
})
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
export default function SignUp() {
|
||||
const [form, fields] = useForm({
|
||||
id: "sign-up",
|
||||
constraint: getZodConstraint(SignUpSchema),
|
||||
onValidate({ formData }) {
|
||||
return parseWithZod(formData, { schema: SignUpSchema })
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="p-10 h-screen relative">
|
||||
<header>
|
||||
<img src={logoPng} alt="Lume logo" className="h-10" />
|
||||
</header>
|
||||
<form
|
||||
className="w-full p-2 max-w-md space-y-4 mt-12 bg-background"
|
||||
{...getFormProps(form)}
|
||||
>
|
||||
<span className="!mb-12 space-y-2">
|
||||
<h2 className="text-3xl font-bold">All roads lead to Lume</h2>
|
||||
<p className="text-input-placeholder">
|
||||
🤘 Get 50 GB free storage and download for free,{" "}
|
||||
<b
|
||||
className="text-primar
|
||||
y-2"
|
||||
>
|
||||
forever
|
||||
</b>
|
||||
.{" "}
|
||||
</p>
|
||||
</span>
|
||||
<Field
|
||||
inputProps={{ name: fields.email.name }}
|
||||
labelProps={{ children: "Email" }}
|
||||
errors={fields.email.errors}
|
||||
/>
|
||||
<Field
|
||||
inputProps={{ name: fields.password.name, type: "password" }}
|
||||
labelProps={{ children: "Password" }}
|
||||
errors={fields.password.errors}
|
||||
/>
|
||||
<Field
|
||||
inputProps={{ name: fields.confirmPassword.name, type: "password" }}
|
||||
labelProps={{ children: "Confirm Password" }}
|
||||
errors={fields.confirmPassword.errors}
|
||||
/>
|
||||
<FieldCheckbox
|
||||
inputProps={{ name: fields.termsOfService.name, form: form.id }}
|
||||
labelProps={{
|
||||
children: (
|
||||
<span>
|
||||
I agree to the
|
||||
<Link
|
||||
to="/terms-of-service"
|
||||
className="text-primary-1 text-md hover:underline hover:underline-offset-4 mx-1"
|
||||
>
|
||||
Terms of Service
|
||||
</Link>
|
||||
and
|
||||
<Link
|
||||
to="/privacy-policy"
|
||||
className="text-primary-1 text-md hover:underline hover:underline-offset-4 mx-1"
|
||||
>
|
||||
Privacy Policy
|
||||
</Link>
|
||||
</span>
|
||||
)
|
||||
}}
|
||||
errors={fields.termsOfService.errors}
|
||||
/>
|
||||
<Button className="w-full h-14">Create Account</Button>
|
||||
<p className="text-input-placeholder w-full text-right">
|
||||
Already have an account?{" "}
|
||||
<Link
|
||||
to="/login"
|
||||
className="text-primary-1 text-md hover:underline hover:underline-offset-4"
|
||||
>
|
||||
Login here instead →
|
||||
</Link>
|
||||
</p>
|
||||
</form>
|
||||
<div className="fixed inset-0 -z-10 overflow-clip">
|
||||
<img
|
||||
src={lumeBgPng}
|
||||
alt="Lume background"
|
||||
className="absolute top-0 right-0 md:w-2/3 object-cover z-[-1]"
|
||||
/>
|
||||
</div>
|
||||
<footer className="my-5">
|
||||
<ul className="flex flex-row">
|
||||
<li>
|
||||
<Link to="https://discord.lumeweb.com">
|
||||
<Button
|
||||
variant={"link"}
|
||||
className="flex flex-row gap-x-2 text-input-placeholder"
|
||||
>
|
||||
<img className="h-5" src={discordLogoPng} alt="Discord Logo" />
|
||||
Connect with us
|
||||
</Button>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="https://lumeweb.com">
|
||||
<Button
|
||||
variant={"link"}
|
||||
className="flex flex-row gap-x-2 text-input-placeholder"
|
||||
>
|
||||
<img className="h-5" src={lumeColorLogoPng} alt="Lume Logo" />
|
||||
Connect with us
|
||||
</Button>
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</footer>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -29,12 +29,12 @@
|
|||
--accent-foreground: 0 0% 9%;
|
||||
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 0 72% 51%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
|
||||
--border: 240 50% 17%;
|
||||
--input: 240 50% 17%;
|
||||
--input-placeholder: 241 21% 42%;
|
||||
--ring: 241 90% 82%;
|
||||
--ring: 0 0% 3.9%;
|
||||
|
||||
--radius: 5px;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "lume-portal-dashboard",
|
||||
"name": "",
|
||||
"private": true,
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
|
@ -14,14 +14,10 @@
|
|||
"@conform-to/react": "^1.0.2",
|
||||
"@conform-to/zod": "^1.0.2",
|
||||
"@fontsource-variable/manrope": "^5.0.19",
|
||||
"@lumeweb/portal-sdk": "^0.0.0-20240306231947",
|
||||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
"@radix-ui/react-icons": "^1.3.0",
|
||||
"@radix-ui/react-label": "^2.0.2",
|
||||
"@radix-ui/react-slot": "^1.0.2",
|
||||
"@refinedev/cli": "^2.16.1",
|
||||
"@refinedev/core": "^4.47.2",
|
||||
"@refinedev/remix-router": "^3.0.0",
|
||||
"@remix-run/node": "^2.8.0",
|
||||
"@remix-run/react": "^2.8.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
|
@ -29,8 +25,7 @@
|
|||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"tailwind-merge": "^2.2.1",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"zod": "^3.22.4"
|
||||
"tailwindcss-animate": "^1.0.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@remix-run/dev": "^2.8.0",
|
||||
|
|
|
@ -7,6 +7,7 @@ export default defineConfig({
|
|||
remix({
|
||||
ssr: false,
|
||||
ignoredRouteFiles: ["**/*.css"],
|
||||
|
||||
}),
|
||||
tsconfigPaths(),
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue