Remove toast components and added register form

The toast related components (toast.tsx, toaster.tsx, use-toast.ts) were removed from the code base. On the other hand, the register-form.tsx file was updated with a form for users to create an account. A new file toast-box.tsx was also added to display a custom message box.
This commit is contained in:
Mathis H (Avnyr) 2024-05-16 16:31:18 +02:00
parent 43f9d8204c
commit db6d838796
Signed by: Mathis
GPG Key ID: DD9E0666A747D126
13 changed files with 1295 additions and 1728 deletions

View File

@ -0,0 +1,72 @@
Index: .idea/workspace.xml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP
<+><?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"AutoImportSettings\">\n <option name=\"autoReloadType\" value=\"SELECTIVE\" />\n </component>\n <component name=\"ChangeListManager\">\n <list default=\"true\" id=\"42d2b9e8-8d19-46be-8636-69ddba4519e4\" name=\"Changes\" comment=\"\">\n <change beforePath=\"$PROJECT_DIR$/package.json\" beforeDir=\"false\" afterPath=\"$PROJECT_DIR$/package.json\" afterDir=\"false\" />\n <change beforePath=\"$PROJECT_DIR$/pnpm-lock.yaml\" beforeDir=\"false\" afterPath=\"$PROJECT_DIR$/pnpm-lock.yaml\" afterDir=\"false\" />\n <change beforePath=\"$PROJECT_DIR$/src/app/globals.css\" beforeDir=\"false\" afterPath=\"$PROJECT_DIR$/src/app/globals.css\" afterDir=\"false\" />\n <change beforePath=\"$PROJECT_DIR$/src/app/layout.tsx\" beforeDir=\"false\" afterPath=\"$PROJECT_DIR$/src/app/layout.tsx\" afterDir=\"false\" />\n <change beforePath=\"$PROJECT_DIR$/src/app/page.tsx\" beforeDir=\"false\" afterPath=\"$PROJECT_DIR$/src/app/page.tsx\" afterDir=\"false\" />\n <change beforePath=\"$PROJECT_DIR$/tailwind.config.ts\" beforeDir=\"false\" afterPath=\"$PROJECT_DIR$/tailwind.config.ts\" afterDir=\"false\" />\n </list>\n <option name=\"SHOW_DIALOG\" value=\"false\" />\n <option name=\"HIGHLIGHT_CONFLICTS\" value=\"true\" />\n <option name=\"HIGHLIGHT_NON_ACTIVE_CHANGELIST\" value=\"false\" />\n <option name=\"LAST_RESOLUTION\" value=\"IGNORE\" />\n </component>\n <component name=\"FileTemplateManagerImpl\">\n <option name=\"RECENT_TEMPLATES\">\n <list>\n <option value=\"TypeScript File\" />\n <option value=\"TypeScript JSX File\" />\n </list>\n </option>\n </component>\n <component name=\"Git.Settings\">\n <option name=\"RECENT_GIT_ROOT_PATH\" value=\"$PROJECT_DIR$\" />\n </component>\n <component name=\"ProjectColorInfo\">{\n &quot;associatedIndex&quot;: 2\n}</component>\n <component name=\"ProjectId\" id=\"2gVILtfjAaVovgsNiYlLfUmWgWX\" />\n <component name=\"ProjectViewState\">\n <option name=\"hideEmptyMiddlePackages\" value=\"true\" />\n <option name=\"showLibraryContents\" value=\"true\" />\n </component>\n <component name=\"PropertiesComponent\">{\n &quot;keyToString&quot;: {\n &quot;ASKED_ADD_EXTERNAL_FILES&quot;: &quot;true&quot;,\n &quot;ASKED_SHARE_PROJECT_CONFIGURATION_FILES&quot;: &quot;true&quot;,\n &quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,\n &quot;last_opened_file_path&quot;: &quot;/home/avnyr/workspace/Simplon/brief-06-front&quot;,\n &quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,\n &quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,\n &quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,\n &quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,\n &quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,\n &quot;npm.dev.executor&quot;: &quot;Run&quot;,\n &quot;settings.editor.selected.configurable&quot;: &quot;preferences.pluginManager&quot;,\n &quot;ts.external.directory.path&quot;: &quot;/home/avnyr/workspace/Simplon/brief-06-front/node_modules/typescript/lib&quot;,\n &quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;\n }\n}</component>\n <component name=\"RunManager\">\n <configuration name=\"dev\" type=\"js.build_tools.npm\" nameIsGenerated=\"true\">\n <package-json value=\"$PROJECT_DIR$/package.json\" />\n <command value=\"run\" />\n <scripts>\n <script value=\"dev\" />\n </scripts>\n <node-interpreter value=\"project\" />\n <package-manager value=\"/usr/bin/yarn\" />\n <envs />\n <method v=\"2\" />\n </configuration>\n </component>\n <component name=\"SharedIndexes\">\n <attachedChunks>\n <set>\n <option value=\"bundled-js-predefined-1d06a55b98c1-91d5c284f522-JavaScript-WS-241.15989.105\" />\n </set>\n </attachedChunks>\n </component>\n <component name=\"SpellCheckerSettings\" RuntimeDictionaries=\"0\" Folders=\"0\" CustomDictionaries=\"0\" DefaultDictionary=\"application-level\" UseSingleDictionary=\"true\" transferred=\"true\" />\n <component name=\"TaskManager\">\n <task active=\"true\" id=\"Default\" summary=\"Default task\">\n <changelist id=\"42d2b9e8-8d19-46be-8636-69ddba4519e4\" name=\"Changes\" comment=\"\" />\n <created>1715776265663</created>\n <option name=\"number\" value=\"Default\" />\n <option name=\"presentableId\" value=\"Default\" />\n <updated>1715776265663</updated>\n <workItem from=\"1715776267209\" duration=\"3260000\" />\n <workItem from=\"1715781823049\" duration=\"3317000\" />\n </task>\n <servers />\n </component>\n <component name=\"TypeScriptGeneratedFilesManager\">\n <option name=\"version\" value=\"3\" />\n </component>\n</project>
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
--- a/.idea/workspace.xml (revision 4559bc14311daecfe13fb72735751f1ad213dca3)
+++ b/.idea/workspace.xml (date 1715842583417)
@@ -4,14 +4,7 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
- <list default="true" id="42d2b9e8-8d19-46be-8636-69ddba4519e4" name="Changes" comment="">
- <change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
- <change beforePath="$PROJECT_DIR$/pnpm-lock.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/pnpm-lock.yaml" afterDir="false" />
- <change beforePath="$PROJECT_DIR$/src/app/globals.css" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/globals.css" afterDir="false" />
- <change beforePath="$PROJECT_DIR$/src/app/layout.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/layout.tsx" afterDir="false" />
- <change beforePath="$PROJECT_DIR$/src/app/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/page.tsx" afterDir="false" />
- <change beforePath="$PROJECT_DIR$/tailwind.config.ts" beforeDir="false" afterPath="$PROJECT_DIR$/tailwind.config.ts" afterDir="false" />
- </list>
+ <list default="true" id="42d2b9e8-8d19-46be-8636-69ddba4519e4" name="Changes" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
@@ -27,6 +20,10 @@
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
+ <option name="UPDATE_TYPE" value="REBASE" />
+ </component>
+ <component name="PackageJsonUpdateNotifier">
+ <dismissed value="$PROJECT_DIR$/package.json" />
</component>
<component name="ProjectColorInfo">{
&quot;associatedIndex&quot;: 2
@@ -83,10 +80,33 @@
<updated>1715776265663</updated>
<workItem from="1715776267209" duration="3260000" />
<workItem from="1715781823049" duration="3317000" />
+ <workItem from="1715785249624" duration="857000" />
</task>
+ <task id="LOCAL-00001" summary="Add generated system configs, theme and page elements&#10;&#10;This commit adds the necessary configuration files for the system, including components for the Tailwind CSS and version control. It also includes code for creating a basic user interface with theme and page elements. Additionally, the commit includes new SVG resources for design elements.">
+ <option name="closed" value="true" />
+ <created>1715785408587</created>
+ <option name="number" value="00001" />
+ <option name="presentableId" value="LOCAL-00001" />
+ <option name="project" value="LOCAL" />
+ <updated>1715785408587</updated>
+ </task>
+ <task id="LOCAL-00002" summary="Extended README with project details and instructions&#10;&#10;An elaborate explanation of the project, development setup, and deployment instructions has been added to the README. This includes details of the technologies utilized, step-by-step instructions for running the development server, and links to useful resources for further readme.">
+ <option name="closed" value="true" />
+ <created>1715785443613</created>
+ <option name="number" value="00002" />
+ <option name="presentableId" value="LOCAL-00002" />
+ <option name="project" value="LOCAL" />
+ <updated>1715785443613</updated>
+ </task>
+ <option name="localTasksCounter" value="3" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
+ <component name="VcsManagerConfiguration">
+ <MESSAGE value="Add generated system configs, theme and page elements&#10;&#10;This commit adds the necessary configuration files for the system, including components for the Tailwind CSS and version control. It also includes code for creating a basic user interface with theme and page elements. Additionally, the commit includes new SVG resources for design elements." />
+ <MESSAGE value="Extended README with project details and instructions&#10;&#10;An elaborate explanation of the project, development setup, and deployment instructions has been added to the README. This includes details of the technologies utilized, step-by-step instructions for running the development server, and links to useful resources for further readme." />
+ <option name="LAST_COMMIT_MESSAGE" value="Extended README with project details and instructions&#10;&#10;An elaborate explanation of the project, development setup, and deployment instructions has been added to the README. This includes details of the technologies utilized, step-by-step instructions for running the development server, and links to useful resources for further readme." />
+ </component>
</project>
\ No newline at end of file

View File

@ -0,0 +1,4 @@
<changelist name="Uncommitted_changes_before_Update_at_5_16_24,_8_59_AM_[Changes]" date="1715842838887" recycled="true" deleted="true">
<option name="PATH" value="$PROJECT_DIR$/.idea/shelf/Uncommitted_changes_before_Update_at_5_16_24,_8_59_AM_[Changes]/shelved.patch" />
<option name="DESCRIPTION" value="Uncommitted changes before Update at 5/16/24, 8:59 AM [Changes]" />
</changelist>

19
.idea/workspace.xml generated
View File

@ -5,17 +5,16 @@
</component>
<component name="ChangeListManager">
<list default="true" id="42d2b9e8-8d19-46be-8636-69ddba4519e4" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/src/app/account/login/page.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/app/account/register/page.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/components/login-form.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/components/register-form.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/app/threads/page.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/components/legals.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pnpm-lock.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/pnpm-lock.yaml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/layout.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/layout.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/page.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/components/header.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/header.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/components/theme-selector.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/theme-selector.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/components/login-form.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/login-form.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/components/register-form.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/register-form.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/components/ui/toast.tsx" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/components/ui/toaster.tsx" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/components/ui/use-toast.ts" beforeDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -25,8 +24,8 @@
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="TypeScript File" />
<option value="TypeScript JSX File" />
<option value="TypeScript File" />
</list>
</option>
</component>
@ -57,7 +56,7 @@
"nodejs_package_manager_path": "npm",
"npm.dev.executor": "Run",
"settings.editor.selected.configurable": "preferences.pluginManager",
"ts.external.directory.path": "/home/avnyr/monoliths/Simplon/brief-06-front/node_modules/typescript/lib",
"ts.external.directory.path": "/home/avnyr/workspace/Simplon/brief-06-front/node_modules/typescript/lib",
"vue.rearranger.settings.migration": "true"
}
}]]></component>

2081
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -2,15 +2,20 @@ import type { Metadata } from "next";
import '@fontsource-variable/kode-mono';
import "./globals.css";
import {ThemeProvider} from "@/components/theme-provider";
import {ToastProvider} from "@/components/ui/toast";
import Header from "@/components/header";
import {BackgroundBeams} from "@/components/ui/background-beams";
import React from "react";
import Legals from "@/components/legals";
import {Toaster} from "react-hot-toast";
export const metadata: Metadata = {
title: "OnlyDevs",
description: "A social network for nerdy developers",
authors: {
name: "Yidhra Studio",
url: "https://yidhra.fr"
}
};
export default function RootLayout({
@ -20,7 +25,7 @@ export default function RootLayout({
}>) {
return (
<html lang="en">
<body className={"flex flex-col justify-center items-center relative"}>
<body className={"flex flex-col justify-between items-center relative w-screen min-h-screen"}>
<ThemeProvider
attribute="class"
defaultTheme="system"
@ -29,7 +34,8 @@ export default function RootLayout({
>
<Header/>
{children}
<ToastProvider/>
<Toaster/>
<Legals/>
</ThemeProvider>
<BackgroundBeams className={"-z-10 w-full h-full fixed"}/>
</body>

16
src/app/threads/page.tsx Normal file
View File

@ -0,0 +1,16 @@
import React from "react";
import {OctagonX} from "lucide-react";
export default function ThreadsPage() {
return (
<main className="flex flex-col justify-start items-center h-full w-full">
<div className={"flex flex-row items-center gap-2 scale-90 md:scale-100 p-2 rounded border bg-accent"}>
<OctagonX/>
<div className={"flex flex-col justify-center items-start"}>
<h3 className={"text-nowrap font-bold text-xl"}>Oups !</h3>
<p className={"text-wrap"}>Something went wrong...</p>
</div>
</div>
</main>
);
}

15
src/components/legals.tsx Normal file
View File

@ -0,0 +1,15 @@
import React from 'react'
import {Button} from "@/components/ui/button";
import {ThemeSelector} from "@/components/theme-selector";
import Link from "next/link";
export const Legals = () => {
return (
<footer className="flex flex-row justify-between items-center p-2 w-full self-end">
<div className="flex items-center justify-between">
Lorem ipsum dolor
</div>
</footer>
)
}
export default Legals;

View File

@ -4,6 +4,8 @@ import {Label} from "@/components/ui/label";
import {Input} from "@/components/ui/input";
import {cn} from "@/lib/utils";
import {User} from "lucide-react";
import Link from "next/link";
import {Button} from "@/components/ui/button";
export function LoginForm() {
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
@ -11,26 +13,12 @@ export function LoginForm() {
console.log("Form submitted");
};
return (
<div className="max-w-md w-full mx-auto rounded-none md:rounded-2xl p-4 md:p-8 shadow-input">
<div className="max-w-md w-full mx-auto rounded-none md:rounded-2xl p-4 md:p-8 shadow-input md:scale-125">
<h2 className="font-bold text-xl text-neutral-800 dark:text-neutral-200">
Welcome to OnlyDevs
Login to your account
</h2>
<p className="text-neutral-600 text-sm max-w-sm mt-2 dark:text-neutral-300">
Login to aceternity if you can because we don&apos;t have a login flow
yet
</p>
<form className="my-8" onSubmit={handleSubmit}>
<div className="flex flex-col md:flex-row space-y-2 md:space-y-0 md:space-x-2 mb-4">
<LabelInputContainer>
<Label htmlFor="firstname">First name</Label>
<Input id="firstname" placeholder="John" type="text" />
</LabelInputContainer>
<LabelInputContainer>
<Label htmlFor="lastname">Last name</Label>
<Input id="lastname" placeholder="Doe" type="text" />
</LabelInputContainer>
</div>
<LabelInputContainer className="mb-4">
<Label htmlFor="email">Email Address</Label>
<Input id="email" placeholder="projectmayhem@fc.com" type="email" />
@ -39,36 +27,32 @@ export function LoginForm() {
<Label htmlFor="password">Password</Label>
<Input id="password" placeholder="••••••••" type="password" />
</LabelInputContainer>
<LabelInputContainer className="mb-8">
<Label htmlFor="twitterpassword">Your twitter password</Label>
<Input
id="twitterpassword"
placeholder="••••••••"
type="twitterpassword"
/>
</LabelInputContainer>
<button
className="bg-gradient-to-br relative group/btn from-black dark:from-zinc-900 dark:to-zinc-900 to-neutral-600 block dark:bg-zinc-800 w-full text-white rounded-md h-10 font-medium shadow-[0px_1px_0px_0px_#ffffff40_inset,0px_-1px_0px_0px_#ffffff40_inset] dark:shadow-[0px_1px_0px_0px_var(--zinc-800)_inset,0px_-1px_0px_0px_var(--zinc-800)_inset]"
type="submit"
>
Sign up &rarr;
Login &rarr;
<BottomGradient />
</button>
<div className="bg-gradient-to-r from-transparent via-neutral-300 dark:via-neutral-700 to-transparent my-8 h-[1px] w-full" />
<div className="flex flex-col space-y-4">
<button
className=" relative group/btn flex space-x-2 items-center justify-start px-4 w-full text-black rounded-md h-10 font-medium shadow-input bg-gray-50 dark:bg-zinc-900 dark:shadow-[0px_0px_1px_1px_var(--neutral-800)]"
type="submit"
<Button
className=" relative group/btn flex space-x-2 items-center justify-center px-4 w-full text-black rounded-md h-10 font-medium shadow-input bg-gray-50 dark:bg-zinc-900 dark:shadow-[0px_0px_1px_1px_var(--neutral-800)]"
asChild
>
<Link
className={'flex flex-row justify-center items-center gap-2'}
href={"/account/register"}>
<User className="h-4 w-4 text-neutral-800 dark:text-neutral-300"/>
<span className="text-neutral-700 dark:text-neutral-300 text-sm">
OnlyFans
I don't have an account
</span>
<BottomGradient/>
</button>
</Link>
</Button>
</div>
</form>
</div>
@ -78,8 +62,8 @@ export function LoginForm() {
const BottomGradient = () => {
return (
<>
<span className="group-hover/btn:opacity-100 block transition duration-500 opacity-0 absolute h-px w-full -bottom-px inset-x-0 bg-gradient-to-r from-transparent via-cyan-500 to-transparent" />
<span className="group-hover/btn:opacity-100 blur-sm block transition duration-500 opacity-0 absolute h-px w-1/2 mx-auto -bottom-px inset-x-10 bg-gradient-to-r from-transparent via-indigo-500 to-transparent" />
<span className="group-hover/btn:opacity-100 block transition duration-500 opacity-0 absolute h-px w-full -bottom-px inset-x-0 bg-gradient-to-r from-transparent via-accent-foreground to-transparent" />
<span className="group-hover/btn:opacity-100 blur-sm block transition duration-500 opacity-0 absolute h-px w-1/2 mx-auto -bottom-px inset-x-10 bg-gradient-to-r from-transparent via-primary-foreground to-transparent" />
</>
);
};

View File

@ -3,15 +3,85 @@ import React from "react";
import {Label} from "@/components/ui/label";
import {Input} from "@/components/ui/input";
import {cn} from "@/lib/utils";
import {User} from "lucide-react";
import {OctagonX, User} from "lucide-react";
import Link from "next/link";
import {Button} from "@/components/ui/button";
import {Resolver, useForm} from "react-hook-form";
import toast, {ToastBar} from "react-hot-toast";
import {ToastBox, toastType} from "@/components/ui/toast-box";
interface UserInsert {
username: string,
displayName?: string,
email: string,
password: string,
rePassword: string
error?: Record<string, { type: string; message: string }>
}
export const resolver: Resolver<UserInsert> = async (values) => {
const errors: Record<string, { type: string; message: string }> = {}
if (!values.username) {
errors.name = {
type: 'required',
message: 'The username is required.',
}
}
if (!values.displayName) {
errors.description = {
type: 'required',
message: 'The displayname is required.',
}
}
if (!values.email) {
errors.start = {
type: 'required',
message: 'The email is required.',
}
}
if (!values.password) {
errors.promoId = {
type: 'required',
message: 'The password is required.',
}
}
if (!values.rePassword) {
errors.promoId = {
type: 'required',
message: 'You should retype the password.',
}
}
return {
values: Object.keys(errors).length === 0 ? values : {},
errors,
}
}
export function RegisterForm() {
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
const handleSubbmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
console.log("Form submitted");
};
const { register, handleSubmit, getValues } = useForm();
const onSubmit = (data: UserInsert) => {
console.log(data);
if (!data.error) {
toast.custom(<ToastBox
message={'Hello world !'}
type={toastType.success}
/>)
}
};
return (
<div className="max-w-md w-full mx-auto rounded-none md:rounded-2xl p-4 md:p-8 shadow-input">
<div className="max-w-md w-full mx-auto rounded-none md:rounded-2xl p-4 md:p-8 shadow-input md:scale-125">
<h2 className="font-bold text-xl text-neutral-800 dark:text-neutral-200">
Create an account
</h2>
@ -19,41 +89,54 @@ export function RegisterForm() {
By creating an account you can discuss on our platform.
</p>
<form className="my-8" onSubmit={handleSubmit}>
<form className="my-8" onSubmit={handleSubmit(onSubmit)}>
<div className="flex flex-col md:flex-row space-y-2 md:space-y-0 md:space-x-2 mb-4">
<LabelInputContainer>
<Label htmlFor="firstname">First name</Label>
<Input id="firstname" placeholder="John" type="text"/>
</LabelInputContainer>
<LabelInputContainer>
<Label htmlFor="lastname">Last name</Label>
<Input id="lastname" placeholder="Doe" type="text"/>
</LabelInputContainer>
</div>
<LabelInputContainer className="mb-4">
<Label htmlFor="email">Email Address</Label>
<Input id="email" placeholder="john.doe@foo.bar" type="email"/>
</LabelInputContainer>
<div
className="bg-gradient-to-r from-transparent via-neutral-300 dark:via-neutral-700 to-transparent my-8 h-[1px] w-full"/>
<LabelInputContainer className="mb-4">
<Label htmlFor="username">Username</Label>
<Input id="username" placeholder="john.doe68" type="text"/>
<Label htmlFor="username">Username<em className={"opacity-50"}>*</em></Label>
<Input
id="username"
placeholder="john.doe68"
type="text"
{...register("username", { required: true })}
/>
</LabelInputContainer>
<LabelInputContainer className="mb-4">
<Label htmlFor="displayName">Displayname</Label>
<Input id="displayName" placeholder="Johny" type="text"/>
<Input
id="displayName"
placeholder="Johny"
type="text"
{...register("displayName")}
/>
</LabelInputContainer>
</div>
<div
className="bg-gradient-to-r from-transparent via-neutral-300 dark:via-neutral-700 to-transparent my-4 h-[1px] w-full"/>
<LabelInputContainer className="mb-4">
<Label htmlFor="email">Email Address<em className={"opacity-50"}>*</em></Label>
<Input
id="email"
placeholder="john.doe@foo.bar"
type="email"
{...register("email", { required: true })}
/>
</LabelInputContainer>
<LabelInputContainer className="mb-4">
<Label htmlFor="password">Password</Label>
<Input id="password" placeholder="••••••••" type="password"/>
<Label htmlFor="password">Password<em className={"opacity-50"}>*</em></Label>
<Input
id="password"
placeholder="••••••••"
type="password"
{...register("password", { required: true })}
/>
</LabelInputContainer>
<LabelInputContainer className="mb-8">
<Label htmlFor="re-password">Re-type password</Label>
<Label htmlFor="re-password">Re-type password<em className={"opacity-50"}>*</em></Label>
<Input
id="re-password"
placeholder="••••••••"
type="password"
{...register("re-password", { validate: (value) => value === getValues('password') || "The passwords do not match" })}
/>
</LabelInputContainer>
@ -64,6 +147,25 @@ export function RegisterForm() {
Register &rarr;
<BottomGradient/>
</button>
<div
className="bg-gradient-to-r from-transparent via-neutral-300 dark:via-neutral-700 to-transparent my-8 h-[1px] w-full"/>
<div className="flex flex-col space-y-4">
<Button
className=" relative group/btn flex space-x-2 items-center justify-center px-4 w-full text-black rounded-md h-10 font-medium shadow-input bg-gray-50 dark:bg-zinc-900 dark:shadow-[0px_0px_1px_1px_var(--neutral-800)]"
asChild
>
<Link
className={'flex flex-row justify-center items-center gap-2'}
href={"/account/login"}>
<User className="h-4 w-4 text-neutral-800 dark:text-neutral-300"/>
<span className="text-neutral-700 dark:text-neutral-300 text-sm">
I already have an account
</span>
<BottomGradient/>
</Link>
</Button>
</div>
</form>
</div>
);
@ -72,9 +174,8 @@ export function RegisterForm() {
const BottomGradient = () => {
return (
<>
<span
className="group-hover/btn:opacity-100 block transition duration-500 opacity-0 absolute h-px w-full -bottom-px inset-x-0 bg-gradient-to-r from-transparent via-cyan-500 to-transparent" />
<span className="group-hover/btn:opacity-100 blur-sm block transition duration-500 opacity-0 absolute h-px w-1/2 mx-auto -bottom-px inset-x-10 bg-gradient-to-r from-transparent via-indigo-500 to-transparent" />
<span className="group-hover/btn:opacity-100 block transition duration-500 opacity-0 absolute h-px w-full -bottom-px inset-x-0 bg-gradient-to-r from-transparent via-accent-foreground to-transparent" />
<span className="group-hover/btn:opacity-100 blur-sm block transition duration-500 opacity-0 absolute h-px w-1/2 mx-auto -bottom-px inset-x-10 bg-gradient-to-r from-transparent via-primary-foreground to-transparent" />
</>
);
};

View File

@ -0,0 +1,63 @@
import {CircleCheckBig, MessageSquareText, OctagonX} from "lucide-react";
import React from "react";
export enum toastType {
info = "info",
warn = "warn",
error = "error",
refused= "refused",
success = "success",
add = "add",
del = "del",
message = "message"
}
export function ToastBox({title, message, type}: {title?: string, message: string, type: toastType}) {
let icon: any;
let bgColor: string;
switch (type) {
case toastType.message :
icon = <MessageSquareText />
bgColor = 'bg-accent'
break
case toastType.add:
icon = '<Plus />'
bgColor = 'bg-accent'
break
case toastType.del:
icon = '<Minus />'
bgColor = 'bg-accent'
break
case toastType.info:
icon = '<CircleHelp />'
bgColor = 'bg-accent'
break
case toastType.warn:
icon = '<CircleAlert />'
bgColor = 'bg-orange-500'
break
case toastType.error:
icon = '<Bug />'
bgColor = 'bg-red-500'
break
case toastType.success:
icon = <CircleCheckBig />
bgColor = 'bg-green-500'
break
case toastType.refused:
icon = '<OctagonX />'
bgColor = 'bg-red-700'
break
}
return (
<div className={`flex flex-row items-center gap-2 scale-90 md:scale-100 p-2 rounded border ${bgColor}`}>
{icon}
<div className={"flex flex-col justify-center items-start"}>
{title && <h3 className={"text-nowrap font-bold text-xl"}>{title}</h3>}
<p className={"text-wrap"}>{message}</p>
</div>
</div>
)
}

View File

@ -1,129 +0,0 @@
"use client"
import * as React from "react"
import * as ToastPrimitives from "@radix-ui/react-toast"
import { cva, type VariantProps } from "class-variance-authority"
import { X } from "lucide-react"
import { cn } from "@/lib/utils"
const ToastProvider = ToastPrimitives.Provider
const ToastViewport = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Viewport>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Viewport
ref={ref}
className={cn(
"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
className
)}
{...props}
/>
))
ToastViewport.displayName = ToastPrimitives.Viewport.displayName
const toastVariants = cva(
"group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
{
variants: {
variant: {
default: "border bg-background text-foreground",
destructive:
"destructive group border-destructive bg-destructive text-destructive-foreground",
},
},
defaultVariants: {
variant: "default",
},
}
)
const Toast = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
VariantProps<typeof toastVariants>
>(({ className, variant, ...props }, ref) => {
return (
<ToastPrimitives.Root
ref={ref}
className={cn(toastVariants({ variant }), className)}
{...props}
/>
)
})
Toast.displayName = ToastPrimitives.Root.displayName
const ToastAction = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Action>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Action
ref={ref}
className={cn(
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive",
className
)}
{...props}
/>
))
ToastAction.displayName = ToastPrimitives.Action.displayName
const ToastClose = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Close>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Close
ref={ref}
className={cn(
"absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
className
)}
toast-close=""
{...props}
>
<X className="h-4 w-4" />
</ToastPrimitives.Close>
))
ToastClose.displayName = ToastPrimitives.Close.displayName
const ToastTitle = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Title>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Title
ref={ref}
className={cn("text-sm font-semibold", className)}
{...props}
/>
))
ToastTitle.displayName = ToastPrimitives.Title.displayName
const ToastDescription = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Description>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Description
ref={ref}
className={cn("text-sm opacity-90", className)}
{...props}
/>
))
ToastDescription.displayName = ToastPrimitives.Description.displayName
type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>
type ToastActionElement = React.ReactElement<typeof ToastAction>
export {
type ToastProps,
type ToastActionElement,
ToastProvider,
ToastViewport,
Toast,
ToastTitle,
ToastDescription,
ToastClose,
ToastAction,
}

View File

@ -1,35 +0,0 @@
"use client"
import {
Toast,
ToastClose,
ToastDescription,
ToastProvider,
ToastTitle,
ToastViewport,
} from "@/components/ui/toast"
import { useToast } from "@/components/ui/use-toast"
export function Toaster() {
const { toasts } = useToast()
return (
<ToastProvider>
{toasts.map(function ({ id, title, description, action, ...props }) {
return (
<Toast key={id} {...props}>
<div className="grid gap-1">
{title && <ToastTitle>{title}</ToastTitle>}
{description && (
<ToastDescription>{description}</ToastDescription>
)}
</div>
{action}
<ToastClose />
</Toast>
)
})}
<ToastViewport />
</ToastProvider>
)
}

View File

@ -1,194 +0,0 @@
"use client"
// Inspired by react-hot-toast library
import * as React from "react"
import type {
ToastActionElement,
ToastProps,
} from "@/components/ui/toast"
const TOAST_LIMIT = 1
const TOAST_REMOVE_DELAY = 1000000
type ToasterToast = ToastProps & {
id: string
title?: React.ReactNode
description?: React.ReactNode
action?: ToastActionElement
}
const actionTypes = {
ADD_TOAST: "ADD_TOAST",
UPDATE_TOAST: "UPDATE_TOAST",
DISMISS_TOAST: "DISMISS_TOAST",
REMOVE_TOAST: "REMOVE_TOAST",
} as const
let count = 0
function genId() {
count = (count + 1) % Number.MAX_SAFE_INTEGER
return count.toString()
}
type ActionType = typeof actionTypes
type Action =
| {
type: ActionType["ADD_TOAST"]
toast: ToasterToast
}
| {
type: ActionType["UPDATE_TOAST"]
toast: Partial<ToasterToast>
}
| {
type: ActionType["DISMISS_TOAST"]
toastId?: ToasterToast["id"]
}
| {
type: ActionType["REMOVE_TOAST"]
toastId?: ToasterToast["id"]
}
interface State {
toasts: ToasterToast[]
}
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()
const addToRemoveQueue = (toastId: string) => {
if (toastTimeouts.has(toastId)) {
return
}
const timeout = setTimeout(() => {
toastTimeouts.delete(toastId)
dispatch({
type: "REMOVE_TOAST",
toastId: toastId,
})
}, TOAST_REMOVE_DELAY)
toastTimeouts.set(toastId, timeout)
}
export const reducer = (state: State, action: Action): State => {
switch (action.type) {
case "ADD_TOAST":
return {
...state,
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
}
case "UPDATE_TOAST":
return {
...state,
toasts: state.toasts.map((t) =>
t.id === action.toast.id ? { ...t, ...action.toast } : t
),
}
case "DISMISS_TOAST": {
const { toastId } = action
// ! Side effects ! - This could be extracted into a dismissToast() action,
// but I'll keep it here for simplicity
if (toastId) {
addToRemoveQueue(toastId)
} else {
state.toasts.forEach((toast) => {
addToRemoveQueue(toast.id)
})
}
return {
...state,
toasts: state.toasts.map((t) =>
t.id === toastId || toastId === undefined
? {
...t,
open: false,
}
: t
),
}
}
case "REMOVE_TOAST":
if (action.toastId === undefined) {
return {
...state,
toasts: [],
}
}
return {
...state,
toasts: state.toasts.filter((t) => t.id !== action.toastId),
}
}
}
const listeners: Array<(state: State) => void> = []
let memoryState: State = { toasts: [] }
function dispatch(action: Action) {
memoryState = reducer(memoryState, action)
listeners.forEach((listener) => {
listener(memoryState)
})
}
type Toast = Omit<ToasterToast, "id">
function toast({ ...props }: Toast) {
const id = genId()
const update = (props: ToasterToast) =>
dispatch({
type: "UPDATE_TOAST",
toast: { ...props, id },
})
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id })
dispatch({
type: "ADD_TOAST",
toast: {
...props,
id,
open: true,
onOpenChange: (open) => {
if (!open) dismiss()
},
},
})
return {
id: id,
dismiss,
update,
}
}
function useToast() {
const [state, setState] = React.useState<State>(memoryState)
React.useEffect(() => {
listeners.push(setState)
return () => {
const index = listeners.indexOf(setState)
if (index > -1) {
listeners.splice(index, 1)
}
}
}, [state])
return {
...state,
toast,
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
}
}
export { useToast, toast }