From 5a67c1bdd45cc494eb443d6865d42c860a724d50 Mon Sep 17 00:00:00 2001 From: Zeke Abshire Date: Sun, 21 May 2023 20:50:31 -0500 Subject: [PATCH] Refactored SidePanel --- src/components/NewProposalPopup.tsx | 168 ++++++++++++++++ src/components/SidePanel.tsx | 147 ++++++++++++++ src/components/layouts/MainLayout.tsx | 278 +------------------------- src/utils/constants/sidepanel.ts | 24 +++ 4 files changed, 342 insertions(+), 275 deletions(-) create mode 100644 src/components/NewProposalPopup.tsx create mode 100644 src/components/SidePanel.tsx create mode 100644 src/utils/constants/sidepanel.ts diff --git a/src/components/NewProposalPopup.tsx b/src/components/NewProposalPopup.tsx new file mode 100644 index 0000000..fa6df5b --- /dev/null +++ b/src/components/NewProposalPopup.tsx @@ -0,0 +1,168 @@ +import { zodResolver } from "@hookform/resolvers/zod"; +import * as Dialog from "@radix-ui/react-dialog"; +import { api } from "@utils/api"; +import { getRootContainer } from "@utils/constants/htmlTools"; +import { proposalSchema } from "@utils/constants/schema/project"; +import type { Children } from "@utils/types/props"; +import { cx } from "class-variance-authority"; +import { useForm, type SubmitHandler } from "react-hook-form"; +import toast from "react-hot-toast"; +import Button from "./Button"; +import { Divider } from "./Divider"; +import { WithScroll } from "./SidePanel"; +import { TextInput, MultilineTextInput } from "./TextInput"; +import type { z } from "zod"; +import { useState } from "react"; + +type ProposalForm = z.infer; +interface NewProposalPopupProps extends Children { + onOpen?: () => void; + onClose?: () => void; + onSubmit?: () => void; +} + +export const NewProposalPopup: React.FC = ({ + children, + onOpen, + onClose, + onSubmit, +}) => { + // === Constants ============================================================ + + const container = getRootContainer(); + + // === Hooks ================================================================ + + const [isOpen, setIsOpen] = useState(false); + const ctx = api.useContext(); + + const { handleSubmit, register, formState, reset } = useForm({ + resolver: zodResolver(proposalSchema), + }); + + const { mutate, isLoading: isPosting } = + api.projects.createProposal.useMutation({ + onSuccess: () => { + toast.success("Successfully created a new proposal"); + + // Close form + setIsOpen(false); + + // Invalidate project caches + void ctx.projects.getAll.invalidate(); + void ctx.projects.getAllByCurrentUser.invalidate(); + + // Handle any extra functions + onSubmit?.(); + }, + onError: (e) => { + toast.error(e.message); + }, + }); + + // === Functions ============================================================ + + const handleOnSubmit: SubmitHandler = (data): void => { + if (isPosting) return; + mutate(data); + }; + + const handleOnClose = () => { + // Close form + setIsOpen(false); + + // Clear form + reset(); + + // Handle any extra functions + onClose?.(); + }; + + const handleOnOpen = () => { + // Open form + setIsOpen(true); + + // Handle any extra functions + onOpen?.(); + }; + + // === Components =========================================================== + + const FullDivider = () => ( +
+ +
+ ); + + return ( + { + isOpen ? handleOnOpen() : handleOnClose(); + }} + > + {children} + + + + + +
+ +

+ Create new proposal +

+
+ +

+ Let others know a little about your project idea. +

+
+
+ + + +
+
+ + + {/* */} +
+
+ +
+
+
+
+
+
+ ); +}; diff --git a/src/components/SidePanel.tsx b/src/components/SidePanel.tsx new file mode 100644 index 0000000..93f8887 --- /dev/null +++ b/src/components/SidePanel.tsx @@ -0,0 +1,147 @@ +import type { Children } from "@utils/types/props"; +import Link from "next/link"; +import { + FiMoreVertical, + FiLogOut, + FiSettings, + FiExternalLink, + FiPlus, +} from "react-icons/fi"; +import { Button } from "@components/Button"; +import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; +import * as Dialog from "@radix-ui/react-dialog"; +import * as ScrollArea from "@radix-ui/react-scroll-area"; +import { cx } from "class-variance-authority"; +import { TextInput, MultilineTextInput } from "@components/TextInput"; +import { Divider } from "@components/Divider"; +import { ImageInput } from "@components/ImageInput"; +import { api } from "@utils/api"; +import { getRootContainer } from "@utils/constants/htmlTools"; +import toast from "react-hot-toast"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { proposalSchema } from "@utils/constants/schema/project"; +import type { z } from "zod"; +import type { SubmitHandler } from "react-hook-form"; +import { signOut } from "next-auth/react"; +import { navItems } from "@utils/constants/sidepanel"; +import { NewProposalPopup } from "./NewProposalPopup"; + +type ProposalForm = z.infer; + +export const SidePanel: React.FC = () => { + return ( +
+
+
+
+
+

+ + || Parallel + +

+ + + + +
+ +
+
+
+ ); +}; + +const MoreMenu: React.FC = () => { + const container = getRootContainer(); + + return ( + + + + + + + + {/* Settings */} + + +

Settings

+ + +
+ + {/* Landing page */} + + +

Parallel Homepage

+ + +
+ + {/* Sign out */} + + + +
+
+
+ ); +}; + +export const WithScroll: React.FC = ({ + height, + children, +}) => { + return ( + + + {children} + + + + + + ); +}; diff --git a/src/components/layouts/MainLayout.tsx b/src/components/layouts/MainLayout.tsx index 4a9be98..b1f3a3c 100644 --- a/src/components/layouts/MainLayout.tsx +++ b/src/components/layouts/MainLayout.tsx @@ -1,283 +1,11 @@ +import { SidePanel } from "@components/SidePanel"; import type { Children } from "@utils/types/props"; -import Link from "next/link"; -import { - FiMenu, - FiHome, - FiSearch, - FiClipboard, - FiEdit, - FiArchive, - FiUser, - FiLogOut, - FiSettings, - FiExternalLink, -} from "react-icons/fi"; -import type { IconType } from "react-icons/lib"; -import { Button } from "@components/Button"; -import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; -import * as Dialog from "@radix-ui/react-dialog"; -import * as ScrollArea from "@radix-ui/react-scroll-area"; -import { cx } from "class-variance-authority"; -import { TextInput, MultilineTextInput } from "@components/TextInput"; -import { Divider } from "@components/Divider"; -import { ImageInput } from "@components/ImageInput"; -import { api } from "@utils/api"; -import { getRootContainer } from "@utils/constants/htmlTools"; -import toast from "react-hot-toast"; -import { useForm } from "react-hook-form"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { proposalSchema } from "@utils/constants/schema/project"; -import type { z } from "zod"; -import type { SubmitHandler } from "react-hook-form"; -import { signOut } from "next-auth/react"; export const MainLayout: React.FC = ({ children }) => { return ( - <> +
-
{children}
- - ); -}; - -// === Side Panel ============================================================= - -interface NavItem { - label: string; - route: string; - Icon: IconType; -} - -const navItems: NavItem[] = [ - { label: "Home", route: "/projects", Icon: FiHome }, - { label: "Search", route: "/discover", Icon: FiSearch }, - { label: "Proposals", route: "/discover/proposals", Icon: FiClipboard }, - { label: "Revisions", route: "/discover/revisions", Icon: FiEdit }, - { label: "Archive", route: "/discover/archive", Icon: FiArchive }, - { label: "Profile", route: "/profile", Icon: FiUser }, -]; - -export const SidePanel: React.FC = () => { - return ( -
-
-
-

- - || Parallel - -

- - -
- -
+
{children}
); }; - -type ProposalForm = z.infer; - -const NewProposalButton: React.FC = () => { - // === Constants ============================================================ - - const container = getRootContainer(); - - // === Hooks ================================================================ - - const { handleSubmit, register, formState, reset } = useForm({ - resolver: zodResolver(proposalSchema), - }); - - const ctx = api.useContext(); - - const { mutate, isLoading: isPosting } = - api.projects.createProposal.useMutation({ - onSuccess: () => { - reset(); - void ctx.projects.getAll.invalidate(); - }, - onError: (e) => { - toast.error(e.message); - }, - }); - - // === Functions ============================================================ - - const onSubmit: SubmitHandler = (data): void => { - if (isPosting) return; - mutate(data); - }; - - // === Components =========================================================== - - const FullDivider = () => ( -
- -
- ); - - return ( - { - if (!isOpen) reset(); - }} - > - - - - - - - - -
- -

- Create new proposal -

-
- -

- Let others know a little about your project idea. -

-
-
- - - -
-
- - - {/* */} -
-
- -
-
-
-
-
-
- ); -}; - -const MoreMenu: React.FC = () => { - const container = getRootContainer(); - - return ( - - - - - - - - {/* Settings */} - - -

Settings

- - -
- - {/* Landing page */} - - -

Parallel Homepage

- - -
- - {/* Sign out */} - - - -
-
-
- ); -}; - -export const WithScroll: React.FC = ({ - height, - children, -}) => { - return ( - - - {children} - - - - - - ); -}; diff --git a/src/utils/constants/sidepanel.ts b/src/utils/constants/sidepanel.ts new file mode 100644 index 0000000..84aaee2 --- /dev/null +++ b/src/utils/constants/sidepanel.ts @@ -0,0 +1,24 @@ +import type { IconType } from "react-icons"; +import { + FiHome, + FiSearch, + FiClipboard, + FiEdit, + FiArchive, + FiUser, +} from "react-icons/fi"; + +interface NavItem { + label: string; + route: string; + Icon: IconType; +} + +export const navItems: NavItem[] = [ + { label: "Home", route: "/projects", Icon: FiHome }, + { label: "Search", route: "/discover", Icon: FiSearch }, + { label: "Proposals", route: "/discover/proposals", Icon: FiClipboard }, + { label: "Revisions", route: "/discover/revisions", Icon: FiEdit }, + { label: "Archive", route: "/discover/archive", Icon: FiArchive }, + { label: "Profile", route: "/profile", Icon: FiUser }, +];