refactor[signUpPage]: refactor sign up page to use radix ui form modal

This commit is contained in:
igorrCarvalho 2023-08-10 02:26:06 -03:00
commit 69ec2681bd
15 changed files with 461 additions and 396 deletions

View file

@ -46,8 +46,8 @@ export default function App() {
}>
>([]);
const isLoginPage = location.pathname.includes('login');
const isAdminPage = location.pathname.includes('admin');
const isLoginPage = location.pathname.includes("login");
const isAdminPage = location.pathname.includes("admin");
// Use effect hook to update alertsList when a new alert is added
useEffect(() => {
@ -124,7 +124,6 @@ export default function App() {
);
};
return (
//need parent component with width and height
<div className="flex h-full flex-col">
@ -137,10 +136,7 @@ export default function App() {
}}
FallbackComponent={CrashErrorComponent}
>
{
!isLoginPage
&&
<Header />}
{!isLoginPage && <Header />}
<Router />
</ErrorBoundary>
<div></div>

View file

@ -7,5 +7,11 @@ export default function IconComponent({
iconColor,
}: IconComponentProps): JSX.Element {
const TargetIcon = nodeIconsLucide[name] ?? nodeIconsLucide["unknown"];
return <TargetIcon strokeWidth={1.5} className={className} style={{ color: iconColor }} />;
return (
<TargetIcon
strokeWidth={1.5}
className={className}
style={{ color: iconColor }}
/>
);
}

View file

@ -10,6 +10,7 @@ export default function InputComponent({
password,
editNode = false,
placeholder = "Type something...",
className,
}: InputComponentType) {
const [pwdVisible, setPwdVisible] = useState(false);
@ -29,7 +30,8 @@ export default function InputComponent({
password && !pwdVisible && value !== "" ? " text-clip password " : "",
editNode ? " input-edit-node " : "",
password && editNode ? "pr-8" : "",
password && !editNode ? "pr-10" : ""
password && !editNode ? "pr-10" : "",
className
)}
placeholder={password && editNode ? "Key" : placeholder}
onChange={(e) => {

View file

@ -27,4 +27,4 @@ const PopoverContent = React.forwardRef<
));
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
export { Popover, PopoverTrigger, PopoverContent };
export { Popover, PopoverContent, PopoverTrigger };

View file

@ -1,15 +1,15 @@
"use client"
"use client";
import * as React from "react"
import * as SelectPrimitive from "@radix-ui/react-select"
import { Check, ChevronDown } from "lucide-react"
import { cn } from "../../utils/utils"
import * as SelectPrimitive from "@radix-ui/react-select";
import { Check, ChevronDown } from "lucide-react";
import * as React from "react";
import { cn } from "../../utils/utils";
const Select = SelectPrimitive.Root
const Select = SelectPrimitive.Root;
const SelectGroup = SelectPrimitive.Group
const SelectGroup = SelectPrimitive.Group;
const SelectValue = SelectPrimitive.Value
const SelectValue = SelectPrimitive.Value;
const SelectTrigger = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Trigger>,
@ -28,8 +28,8 @@ const SelectTrigger = React.forwardRef<
<ChevronDown className="h-4 w-4 opacity-50" />
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
))
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
));
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
const SelectContent = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Content>,
@ -58,8 +58,8 @@ const SelectContent = React.forwardRef<
</SelectPrimitive.Viewport>
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
))
SelectContent.displayName = SelectPrimitive.Content.displayName
));
SelectContent.displayName = SelectPrimitive.Content.displayName;
const SelectLabel = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Label>,
@ -70,8 +70,8 @@ const SelectLabel = React.forwardRef<
className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
{...props}
/>
))
SelectLabel.displayName = SelectPrimitive.Label.displayName
));
SelectLabel.displayName = SelectPrimitive.Label.displayName;
const SelectItem = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Item>,
@ -93,8 +93,8 @@ const SelectItem = React.forwardRef<
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
))
SelectItem.displayName = SelectPrimitive.Item.displayName
));
SelectItem.displayName = SelectPrimitive.Item.displayName;
const SelectSeparator = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Separator>,
@ -105,16 +105,16 @@ const SelectSeparator = React.forwardRef<
className={cn("-mx-1 my-1 h-px bg-muted", className)}
{...props}
/>
))
SelectSeparator.displayName = SelectPrimitive.Separator.displayName
));
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
export {
Select,
SelectGroup,
SelectValue,
SelectTrigger,
SelectContent,
SelectLabel,
SelectGroup,
SelectItem,
SelectLabel,
SelectSeparator,
}
SelectTrigger,
SelectValue,
};

View file

@ -510,7 +510,7 @@ export const URL_EXCLUDED_FROM_ERROR_RETRIES = [
];
export const CONTROL_INPUT_STATE = {
password: '',
cnfPassword: '',
username: '',
password: "",
cnfPassword: "",
username: "",
};

View file

@ -1,6 +1,5 @@
import axios, { AxiosError, AxiosInstance } from "axios";
import { useContext, useEffect, useRef } from "react";
import { URL_EXCLUDED_FROM_ERROR_RETRIES } from "../../constants/constants";
import { alertContext } from "../../contexts/alertContext";
// Create a new Axios instance
@ -20,7 +19,6 @@ function ApiInterceptor() {
// return Promise.reject(error);
// }
// let retryCount = 0;
// while (retryCount < 4) {
// await sleep(5000); // Sleep for 5 seconds
// retryCount++;

View file

@ -47,7 +47,15 @@ interface BaseModalProps {
open?: boolean;
setOpen?: (open: boolean) => void;
disable?: boolean;
size?: "x-small" | "smaller" | "small" | "medium" | "large" | "large-h-full" | "small-h-full" | "medium-h-full";
size?:
| "x-small"
| "smaller"
| "small"
| "medium"
| "large"
| "large-h-full"
| "small-h-full"
| "medium-h-full";
}
function BaseModal({
open,
@ -118,7 +126,7 @@ function BaseModal({
{triggerChild}
</DialogTrigger>
<DialogContent className={minWidth}>
<div className="word-break-break-word truncate-doubleline">
<div className="truncate-doubleline word-break-break-word">
{headerChild}
</div>
<div className={`mt-2 flex flex-col ${height} w-full `}>

View file

@ -1,11 +1,8 @@
import { FaApple, FaGithub } from "react-icons/fa";
import { useNavigate } from "react-router-dom";
import { Button } from "../../../components/ui/button";
import { Input } from "../../../components/ui/input";
import { GoogleIcon } from "../../../icons/Google";
import { useNavigate } from "react-router-dom";
export default function LoginAdminPage() {
const navigate = useNavigate();
function loginAdmin() {
@ -16,14 +13,16 @@ export default function LoginAdminPage() {
<div className="flex h-full w-full flex-col items-center justify-center bg-muted">
<div className="flex w-72 flex-col items-center justify-center gap-2">
<span className="mb-4 text-5xl">⛓️</span>
<span className="mb-6 text-2xl font-semibold text-primary">
Admin
</span>
<span className="mb-6 text-2xl font-semibold text-primary">Admin</span>
<Input className="bg-background" placeholder="Email address" />
<Input className="bg-background" placeholder="Password" />
<Button
onClick={() => {loginAdmin()}}
variant="default" className="w-full">
onClick={() => {
loginAdmin();
}}
variant="default"
className="w-full"
>
Login
</Button>
</div>

View file

@ -1,8 +1,9 @@
import _ from "lodash";
import { Pencil, Trash2, X } from "lucide-react";
import { X } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import PaginatorComponent from "../../components/PaginatorComponent";
import ShadTooltip from "../../components/ShadTooltipComponent";
import IconComponent from "../../components/genericIconComponent";
import { Button } from "../../components/ui/button";
import { Input } from "../../components/ui/input";
import {
@ -15,7 +16,6 @@ import {
} from "../../components/ui/table";
import ConfirmationModal from "../../modals/ConfirmationModal";
import UserManagementModal from "../../modals/UserManagementModal";
import IconComponent from "../../components/genericIconComponent";
export default function AdminPage() {
const [inputValue, setInputValue] = useState("");
@ -250,9 +250,9 @@ export default function AdminPage() {
return (
<>
<div className="main-page-panel">
<div className="h-full m-auto flex flex-row justify-center">
<div className="m-auto flex h-full flex-row justify-center">
<div className="basis-5/6">
<div className="m-auto h-full flex-col space-y-8 p-8 flex ">
<div className="m-auto flex h-full flex-col space-y-8 p-8 ">
<div className="flex items-center justify-between space-y-2">
<div>
<h2 className="text-2xl font-bold tracking-tight">
@ -347,7 +347,8 @@ export default function AdminPage() {
}}
>
<ShadTooltip content="Edit" side="top">
<IconComponent name="Pencil"
<IconComponent
name="Pencil"
className="h-4 w-4 cursor-pointer"
/>
</ShadTooltip>
@ -368,7 +369,8 @@ export default function AdminPage() {
}}
>
<ShadTooltip content="Delete" side="top">
<IconComponent name="Trash2"
<IconComponent
name="Trash2"
className="ml-2 h-4 w-4 cursor-pointer"
/>
</ShadTooltip>
@ -392,11 +394,8 @@ export default function AdminPage() {
)}
</div>
</div>
</div>
</div>
</>
);
}

View file

@ -1,49 +1,39 @@
import _ from "lodash";
import * as Form from "@radix-ui/react-form";
import { useState } from "react";
import { FaApple, FaGithub } from "react-icons/fa";
import InputComponent from "../../components/inputComponent";
import { Button } from "../../components/ui/button";
import { Input } from "../../components/ui/input";
import { GoogleIcon } from "../../icons/Google";
import { useContext, useState } from "react";
import { CONTROL_INPUT_STATE } from "../../constants/constants";
import { GoogleIcon } from "../../icons/Google";
import { inputHandlerEventType, inputStateType } from "../../types/components";
import { alertContext } from "../../contexts/alertContext";
import { Link } from "react-router-dom";
import InputComponent from "../../components/inputComponent";
import IconComponent from "../../components/genericIconComponent";
export default function SignUp(): JSX.Element {
const [inputState, setInputState] = useState<inputStateType>(CONTROL_INPUT_STATE);
const {
setErrorData,
errorOpen,
} = useContext(alertContext);
const [inputState, setInputState] =
useState<inputStateType>(CONTROL_INPUT_STATE);
const { password, cnfPassword, username } = inputState;
function handleInput({ target: { name, value } }: inputHandlerEventType): void {
function handleInput({
target: { name, value },
}: inputHandlerEventType): void {
setInputState((prev) => ({ ...prev, [name]: value }));
};
function handleSignUpPass() {
if (password !== cnfPassword) {
const errorDat = {
title: "Passwords are not equal",
};
return setErrorData(errorDat);
}
let err = [];
Object.keys(inputState)
.forEach((key) => {
if (inputState[key] === '') {
err.push(key);
}
});
setErrorData({
title: "Mandatory fields are empty",
list: err,
});
}
return (
<Form.Root
onSubmit={(event) => {
if (password !== cnfPassword) {
event.preventDefault();
return;
}
const data = Object.fromEntries(new FormData(event.currentTarget));
event.preventDefault();
}}
className="w-full h-full"
>
<div className="flex h-full w-full flex-col items-center justify-center bg-muted">
<div className="flex w-72 flex-col items-center justify-center gap-2">
<span className="mb-4 text-5xl">⛓️</span>
@ -52,53 +42,116 @@ export default function SignUp(): JSX.Element {
</span>
<div className="flex w-full items-center justify-center gap-2">
<Button variant="primary" className="w-full py-6">
<FaApple className="h-6 w-6" />
<IconComponent
name="FaApple"
className="h-6 w-6"
/>
</Button>
<Button variant="primary" className="w-full py-6">
<FaGithub className="h-6 w-6" />
<IconComponent
name="FaGithub"
className="h-6 w-6"
/>
</Button>
<Button variant="primary" className="w-full py-6">
<div className="h-6 w-6">
<GoogleIcon />
</div>
<IconComponent
name="GoogleSearchRun"
className="h-6 w-6"
/>
</Button>
</div>
<span className="text-sm text-muted-foreground">or</span>
<div className="w-full mb-3">
<Form.Field name="username">
<Form.Label className="data-[invalid]:label-invalid">
Username <span className="font-medium text-destructive">*</span>
</Form.Label>
<Form.Control asChild>
<Input
className="bg-background"
placeholder="Username"
name="username"
onChange={({ target: { value } }) => {
handleInput({ target: { name: "username", value } });
}}
value={username}
onChange={handleInput}
type="text"
className="w-full"
required
placeholder="Username"
/>
</Form.Control>
<Form.Message match="valueMissing" className="field-invalid">
Please enter your username
</Form.Message>
</Form.Field>
</div>
<div className="w-full mb-3">
<Form.Field name="password" serverInvalid={password != cnfPassword}>
<Form.Label className="data-[invalid]:label-invalid">
Password <span className="font-medium text-destructive">*</span>
</Form.Label>
<Form.Control asChild>
<InputComponent
onChange={(value) => {
handleInput({ target: { name: "password", value } });
}}
value={password}
onChange={(value) => handleInput({ target: { name: 'password', value } })}
password={true}
placeholder="Password"
/>
<InputComponent
value={cnfPassword}
onChange={(value) => handleInput({ target: { name: 'cnfPassword', value } })}
password={true}
placeholder="Confirm your password"
/>
<Button
variant="default"
className="w-full"
onClick={() => {
handleSignUpPass();
}}
/>
</Form.Control>
<Form.Message className="field-invalid" match="valueMissing">
Please enter a password
</Form.Message>
{password != cnfPassword && (
<Form.Message className="field-invalid">
Passwords do not match
</Form.Message>
)}
</Form.Field>
</div>
<div className="w-full">
<Form.Field
name="confirmpassword"
serverInvalid={password != cnfPassword}
>
Sign up
</Button>
<Link to="/login" className="mt-6 w-full">
<Button variant="outline" className="mt-6 w-full">
<Form.Label className="data-[invalid]:label-invalid">
Confirm your password{" "}
<span className="font-medium text-destructive">*</span>
</Form.Label>
<Form.Control asChild>
<InputComponent
onChange={(value) => {
handleInput({ target: { name: "cnfPassword", value } });
}}
value={cnfPassword}
password={true}
/>
</Form.Control>
<Form.Message className="field-invalid" match="valueMissing">
Please confirm your password
</Form.Message>
</Form.Field>
</div>
<div className="w-full">
<Form.Submit asChild>
<Button className="mr-3 mt-6 w-full">Sign up</Button>
</Form.Submit>
</div>
<div className="w-full">
<Link to="/login">
<Button className="w-full" variant="outline">
Already have an account?&nbsp;<b>Sign in</b>
</Button>
</Link>
</div>
</div>
</div>
</Form.Root>
);
}

View file

@ -1,12 +1,12 @@
import { Route, Routes } from "react-router-dom";
import AdminPage from "./pages/AdminPage";
import LoginAdminPage from "./pages/AdminPage/LoginPage";
import CommunityPage from "./pages/CommunityPage";
import FlowPage from "./pages/FlowPage";
import HomePage from "./pages/MainPage";
import DeleteAccountPage from "./pages/deleteAccountPage";
import LoginPage from "./pages/loginPage";
import SignUp from "./pages/signUpPage";
import LoginAdminPage from "./pages/AdminPage/LoginPage";
import AdminPage from "./pages/AdminPage";
const Router = () => {
return (
@ -19,7 +19,7 @@ const Router = () => {
<Route path="*" element={<HomePage />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/signup" element={<SignUp/>} />
<Route path="/signup" element={<SignUp />} />
<Route path="/login/admin" element={<LoginAdminPage />} />
<Route path="/admin" element={<AdminPage />} />

View file

@ -11,6 +11,7 @@ export type InputComponentType = {
onChangePass?: (value: boolean | boolean) => void;
showPass?: boolean;
placeholder?: string;
className?: string;
};
export type ToggleComponentType = {
enabled: boolean;
@ -165,7 +166,7 @@ export interface IVarHighlightType {
export type IconComponentProps = {
name: string;
className: string;
className?: string;
iconColor?: string;
};
@ -205,7 +206,7 @@ export type ConfirmationModalType = {
data: any;
index: number;
onConfirm: (index, data) => void;
}
};
export type UserManagementType = {
title: string;
@ -217,4 +218,4 @@ export type UserManagementType = {
data?: any;
index?: number;
onConfirm: (index, data) => void;
}
};

View file

@ -5,6 +5,8 @@ import {
ChevronDown,
ChevronLeft,
ChevronRight,
ChevronsLeft,
ChevronsRight,
ChevronsUpDown,
Circle,
Clipboard,
@ -44,6 +46,7 @@ import {
MoonIcon,
MoreHorizontal,
Paperclip,
Pencil,
Plus,
Redo,
Rocket,
@ -66,9 +69,6 @@ import {
X,
XCircle,
Zap,
Pencil,
ChevronsRight,
ChevronsLeft
} from "lucide-react";
import { AirbyteIcon } from "../icons/Airbyte";
import { AnthropicIcon } from "../icons/Anthropic";
@ -96,6 +96,7 @@ import SvgWikipedia from "../icons/Wikipedia/Wikipedia";
import SvgWolfram from "../icons/Wolfram/Wolfram";
import { HackerNewsIcon } from "../icons/hackerNews";
import { SupabaseIcon } from "../icons/supabase";
import { FaApple, FaGithub } from "react-icons/fa";
export const gradients = [
"bg-gradient-to-br from-gray-800 via-rose-700 to-violet-900",
@ -284,5 +285,7 @@ export const nodeIconsLucide = {
UserPlus2,
Pencil,
ChevronsRight,
ChevronsLeft
ChevronsLeft,
FaGithub,
FaApple,
};