From 78cad0bebd3ade3603e30a87eedddff57afbfa32 Mon Sep 17 00:00:00 2001 From: Gram Liu Date: Mon, 4 Dec 2023 00:52:12 -0800 Subject: [PATCH] Create homepage with avatar --- apps/web/app/canvas/page.tsx | 288 ++++++++++++++++++ apps/web/app/page.tsx | 313 ++------------------ apps/web/src/components/home-icon.tsx | 13 + packages/config/tailwind/tailwind.config.js | 1 + packages/ui/package.json | 1 + packages/ui/src/components/ui/avatar.tsx | 50 ++++ packages/ui/src/components/ui/index.tsx | 1 + pnpm-lock.yaml | 27 ++ 8 files changed, 400 insertions(+), 294 deletions(-) create mode 100644 apps/web/app/canvas/page.tsx create mode 100644 apps/web/src/components/home-icon.tsx create mode 100644 packages/ui/src/components/ui/avatar.tsx diff --git a/apps/web/app/canvas/page.tsx b/apps/web/app/canvas/page.tsx new file mode 100644 index 0000000..79a6ba1 --- /dev/null +++ b/apps/web/app/canvas/page.tsx @@ -0,0 +1,288 @@ +"use client"; +import { Editor, TLPageId } from "@tldraw/tldraw"; +import "@tldraw/tldraw/tldraw.css"; +import { + Badge, + Button, + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + Popover, + PopoverContent, + PopoverTrigger, + SkeletonPlaceholder, + Tabs, + TabsContent, + TabsList, + TabsTrigger, + Toaster, + useToast, +} from "@ui/components"; +import Canvas from "@ui/components/canvas"; +import IconLabel from "@ui/components/icon-label"; +import clsx from "clsx"; +import { + CheckIcon, + ChevronsUpDownIcon, + GitBranchIcon, + GithubIcon, + Loader2, +} from "lucide-react"; +import { useEffect, useReducer, useState } from "react"; +import { CopyBlock, nord } from "react-code-blocks"; +import HomeIcon from "~/components/home-icon"; +import { convertEditorToCode } from "~/lib/editorToCode"; + +const projects = [ + { + label: "My Journal", + value: "my_journal", + }, + { + label: "Portfolio Website", + value: "portfolio_website", + }, + { + label: "Sandbox", + value: "sandbox", + }, +]; +const repo = "gramliu/custom-journal"; +const branch = "main"; +const framework = "Next.js"; +const options = ["App Router"]; + +interface ReducerState { + [key: string]: string; +} + +interface ReducerAction { + type: "add_page"; + pageId: string; + code: string; +} + +function reducer(state: ReducerState, action: ReducerAction): ReducerState { + if (action.type === "add_page") { + return { + ...state, + [action.pageId]: action.code, + }; + } + return state; +} + +export default function IndexPage() { + const [editor, setEditor] = useState(); + const [standaloneCode, setStandaloneCode] = useState(); + const [loading, setLoading] = useState(false); + const { toast } = useToast(); + + const [pageId, setPageId] = useState(); + const [page, setPage] = useState(""); + + const [projectSelectionOpen, setProjectSelectionOpen] = useState(false); + const [selectedProject, setSelectedProject] = useState(projects[0].value); + + const [state, dispatch] = useReducer(reducer, {} as ReducerState); + + // Update page ID to trigger secondary effect + useEffect(() => { + if (editor != null) { + setPageId(editor.getCurrentPageId()); + } + }, [editor]); + + // Update page name in output pane + useEffect(() => { + if (pageId != null && editor != null) { + const page = editor.getPage(pageId); + if (page != null) { + setPage(page.name); + setStandaloneCode(state[pageId] ?? ""); + } + } + }, [pageId, editor]); + + const sectionWidth = "w-[45vw]"; + + return ( +
+
+ +

+ {projects.find((project) => project.value === selectedProject).label} +

+ + + + + + + + No projects found + + {projects.map(({ value, label }) => ( + { + setSelectedProject(value); + setProjectSelectionOpen(false); + }} + > + + {label} + + ))} + + + + +
+ {/* Project info */} +
+
+ } label={repo} /> +
+ {framework} + {options.map((option) => ( + + {option} + + ))} +
+
+
+ } label={branch} /> +
+
+ {/* Panels */} +
+ {/* Editor */} +
+ { + setPageId(newPageId); + }} + /> +
+ {/* Output */} +
+ + +
{page}
+
+ Preview + + Code (Standalone) + +
+
+ {loading ? ( + + ) : ( + <> + +