From 04572a8e5081b1e4871e273cde9dbaaa44c52fe0 Mon Sep 17 00:00:00 2001 From: MohamedBassem Date: Wed, 13 Mar 2024 21:43:44 +0000 Subject: structure: Create apps dir and copy tooling dir from t3-turbo repo --- apps/web/components/dashboard/sidebar/AllLists.tsx | 60 ++++++++ .../components/dashboard/sidebar/ModileSidebar.tsx | 24 +++ .../dashboard/sidebar/ModileSidebarItem.tsx | 27 ++++ .../components/dashboard/sidebar/NewListModal.tsx | 170 +++++++++++++++++++++ apps/web/components/dashboard/sidebar/Sidebar.tsx | 66 ++++++++ .../components/dashboard/sidebar/SidebarItem.tsx | 33 ++++ .../dashboard/sidebar/SidebarProfileOptions.tsx | 35 +++++ 7 files changed, 415 insertions(+) create mode 100644 apps/web/components/dashboard/sidebar/AllLists.tsx create mode 100644 apps/web/components/dashboard/sidebar/ModileSidebar.tsx create mode 100644 apps/web/components/dashboard/sidebar/ModileSidebarItem.tsx create mode 100644 apps/web/components/dashboard/sidebar/NewListModal.tsx create mode 100644 apps/web/components/dashboard/sidebar/Sidebar.tsx create mode 100644 apps/web/components/dashboard/sidebar/SidebarItem.tsx create mode 100644 apps/web/components/dashboard/sidebar/SidebarProfileOptions.tsx (limited to 'apps/web/components/dashboard/sidebar') diff --git a/apps/web/components/dashboard/sidebar/AllLists.tsx b/apps/web/components/dashboard/sidebar/AllLists.tsx new file mode 100644 index 00000000..a77252d0 --- /dev/null +++ b/apps/web/components/dashboard/sidebar/AllLists.tsx @@ -0,0 +1,60 @@ +"use client"; + +import { api } from "@/lib/trpc"; +import SidebarItem from "./SidebarItem"; +import NewListModal, { useNewListModal } from "./NewListModal"; +import { Plus } from "lucide-react"; +import Link from "next/link"; +import { ZBookmarkList } from "@hoarder/trpc/types/lists"; + +export default function AllLists({ + initialData, +}: { + initialData: { lists: ZBookmarkList[] }; +}) { + let { data: lists } = api.lists.list.useQuery(undefined, { + initialData, + }); + // TODO: This seems to be a bug in react query + lists ||= initialData; + const { setOpen } = useNewListModal(); + + return ( + + ); +} diff --git a/apps/web/components/dashboard/sidebar/ModileSidebar.tsx b/apps/web/components/dashboard/sidebar/ModileSidebar.tsx new file mode 100644 index 00000000..4bd6a347 --- /dev/null +++ b/apps/web/components/dashboard/sidebar/ModileSidebar.tsx @@ -0,0 +1,24 @@ +import MobileSidebarItem from "./ModileSidebarItem"; +import { + Tag, + PackageOpen, + Settings, + Search, + ClipboardList, +} from "lucide-react"; +import SidebarProfileOptions from "./SidebarProfileOptions"; + +export default async function MobileSidebar() { + return ( + + ); +} diff --git a/apps/web/components/dashboard/sidebar/ModileSidebarItem.tsx b/apps/web/components/dashboard/sidebar/ModileSidebarItem.tsx new file mode 100644 index 00000000..9389d2e4 --- /dev/null +++ b/apps/web/components/dashboard/sidebar/ModileSidebarItem.tsx @@ -0,0 +1,27 @@ +"use client"; + +import { cn } from "@/lib/utils"; +import Link from "next/link"; +import { usePathname } from "next/navigation"; + +export default function MobileSidebarItem({ + logo, + path, +}: { + logo: React.ReactNode; + path: string; +}) { + const currentPath = usePathname(); + return ( +
  • + + {logo} + +
  • + ); +} diff --git a/apps/web/components/dashboard/sidebar/NewListModal.tsx b/apps/web/components/dashboard/sidebar/NewListModal.tsx new file mode 100644 index 00000000..f51616ed --- /dev/null +++ b/apps/web/components/dashboard/sidebar/NewListModal.tsx @@ -0,0 +1,170 @@ +"use client"; + +import data from "@emoji-mart/data"; +import Picker from "@emoji-mart/react"; + +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; + +import { ActionButton } from "@/components/ui/action-button"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogClose, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { + Form, + FormControl, + FormField, + FormItem, + FormMessage, +} from "@/components/ui/form"; + +import { toast } from "@/components/ui/use-toast"; +import { api } from "@/lib/trpc"; + +import { z } from "zod"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { Input } from "@/components/ui/input"; + +import { create } from "zustand"; + +export const useNewListModal = create<{ + open: boolean; + setOpen: (v: boolean) => void; +}>((set) => ({ + open: false, + setOpen: (open: boolean) => set(() => ({ open })), +})); + +export default function NewListModal() { + const { open, setOpen } = useNewListModal(); + + const formSchema = z.object({ + name: z.string(), + icon: z.string(), + }); + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + name: "", + icon: "💡", + }, + }); + + const listsInvalidationFunction = api.useUtils().lists.list.invalidate; + + const { mutate: createList, isPending } = api.lists.create.useMutation({ + onSuccess: () => { + toast({ + description: "List has been created!", + }); + listsInvalidationFunction(); + setOpen(false); + }, + onError: (e) => { + if (e.data?.code == "BAD_REQUEST") { + toast({ + variant: "destructive", + description: e.message, + }); + } else { + toast({ + variant: "destructive", + title: "Something went wrong", + }); + } + }, + }); + + return ( + { + form.reset(); + setOpen(s); + }} + > + +
    + { + createList(value); + })} + > + + New List + +
    + { + return ( + + + + + {field.value} + + + + field.onChange(e.native) + } + /> + + + + + + ); + }} + /> + + { + return ( + + + + + + + ); + }} + /> +
    + + + + + + Create + + +
    + +
    +
    + ); +} diff --git a/apps/web/components/dashboard/sidebar/Sidebar.tsx b/apps/web/components/dashboard/sidebar/Sidebar.tsx new file mode 100644 index 00000000..a5c1d7a5 --- /dev/null +++ b/apps/web/components/dashboard/sidebar/Sidebar.tsx @@ -0,0 +1,66 @@ +import { Tag, Home, PackageOpen, Settings, Search, Shield } from "lucide-react"; +import { redirect } from "next/navigation"; +import SidebarItem from "./SidebarItem"; +import { getServerAuthSession } from "@/server/auth"; +import Link from "next/link"; +import SidebarProfileOptions from "./SidebarProfileOptions"; +import { Separator } from "@/components/ui/separator"; +import AllLists from "./AllLists"; +import serverConfig from "@hoarder/shared/config"; +import { api } from "@/server/api/client"; + +export default async function Sidebar() { + const session = await getServerAuthSession(); + if (!session) { + redirect("/"); + } + + const lists = await api.lists.list(); + + return ( + + ); +} diff --git a/apps/web/components/dashboard/sidebar/SidebarItem.tsx b/apps/web/components/dashboard/sidebar/SidebarItem.tsx new file mode 100644 index 00000000..856bdffd --- /dev/null +++ b/apps/web/components/dashboard/sidebar/SidebarItem.tsx @@ -0,0 +1,33 @@ +"use client"; + +import { cn } from "@/lib/utils"; +import Link from "next/link"; +import { usePathname } from "next/navigation"; + +export default function SidebarItem({ + name, + logo, + path, + className, +}: { + name: string; + logo: React.ReactNode; + path: string; + className?: string; +}) { + const currentPath = usePathname(); + return ( +
  • + + {logo} + {name} + +
  • + ); +} diff --git a/apps/web/components/dashboard/sidebar/SidebarProfileOptions.tsx b/apps/web/components/dashboard/sidebar/SidebarProfileOptions.tsx new file mode 100644 index 00000000..f931b63e --- /dev/null +++ b/apps/web/components/dashboard/sidebar/SidebarProfileOptions.tsx @@ -0,0 +1,35 @@ +"use client"; + +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { LogOut, MoreHorizontal } from "lucide-react"; +import { signOut } from "next-auth/react"; + +export default function SidebarProfileOptions() { + return ( + + + + + + + signOut({ + callbackUrl: "/", + }) + } + > + + Sign Out + + + + ); +} -- cgit v1.2.3-70-g09d2