"use client"; import React, { useEffect, useMemo, useState } from "react"; import Image from "next/image"; import Link from "next/link"; import { MemoriesIcon, CanvasIcon, AddIcon, HomeIcon as HomeIconWeb, } from "@repo/ui/icons"; import { Button } from "@repo/ui/shadcn/button"; import { MinusIcon, PlusCircleIcon } from "lucide-react"; import Editor from "@/components/editor/advanced-editor"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@repo/ui/shadcn/dialog"; import { Label } from "@repo/ui/shadcn/label"; import { Textarea } from "@repo/ui/shadcn/textarea"; import { toast } from "sonner"; import { getSpaces } from "../actions/fetchers"; import { HomeIcon } from "@heroicons/react/24/solid"; import { createMemory, createSpace } from "../actions/doers"; import ComboboxWithCreate from "@repo/ui/shadcn/combobox"; import { StoredSpace } from "@repo/db/schema"; import { useKeyPress } from "@/lib/useKeyPress"; import { useFormStatus } from "react-dom"; import { usePendingJob } from "@/contexts/PendingJobContext"; function Menu() { useKeyPress("a", () => { if (!dialogOpen) { setDialogOpen(true); } }); const menuItems = [ { icon: HomeIconWeb, text: "Home", url: "/home", disabled: false, }, { icon: MemoriesIcon, text: "Memories", url: "/memories", disabled: false, }, { icon: CanvasIcon, text: "Thinkpad", url: "/thinkpad", disabled: false, }, ]; const [dialogOpen, setDialogOpen] = useState(false); return (
{/* Desktop Menu */}
Logo

Add

{menuItems.map((item) => ( {`${item.text}

{item.text}

))}
setDialogOpen(false)} /> {/* Mobile Menu */}

Home

Logo

Add

{menuItems.slice(1, 2).map((item) => ( item.disabled && e.preventDefault()} > {`${item.text}

{item.text}

))}
); } function DialogContentMenu({ setDialogClose }: { setDialogClose: () => void }) { const [spaces, setSpaces] = useState([]); useEffect(() => { (async () => { let spaces = await getSpaces(); if (!spaces.success || !spaces.data) { toast.warning("Unable to get spaces", { richColors: true, }); setSpaces([]); return; } setSpaces(spaces.data); })(); }, []); const [content, setContent] = useState(""); const [selectedSpaces, setSelectedSpaces] = useState([]); const autoDetectedType = useMemo(() => { if (content.length === 0) { return "none"; } if ( content.match(/https?:\/\/(x\.com|twitter\.com)\/[\w]+\/[\w]+\/[\d]+/) ) { return "tweet"; } else if ( content.match( /^(https?:\/\/)?(www\.)?[a-z0-9]+([-.]{1}[a-z0-9]+)*\.[a-z]{2,5}(\/.*)?$/i, ) ) { return "page"; } else { return "note"; } }, [content]); const options = useMemo( () => spaces.map((x) => ({ label: x.name, value: x.id.toString(), })), [spaces], ); const handleSubmit = async (content?: string, spaces?: number[]) => { setDialogClose(); if (!content || content.length === 0) { throw new Error("Content is required"); } const cont = await createMemory({ content: content, spaces: spaces ?? undefined, }); setContent(""); setSelectedSpaces([]); return cont; }; const { pendingJobs, setPendingJobs } = usePendingJob(); const formSubmit = () => { toast.promise(handleSubmit(content, selectedSpaces), { loading: ( {" "} Creating memory... ), success: (data) => { setPendingJobs(pendingJobs + 1); return "Memory queued"; }, error: (error) => { setPendingJobs(pendingJobs - 1); return `Memory creation failed: ${error}`; }, richColors: true, }); }; const [editorOpen, setEditorOpen] = useState(false); return (
Add memory
({ label: x.name, value: x.id.toString(), }))} onSelect={(v) => setSelectedSpaces((prev) => { if (v === "") { return []; } return [...prev, parseInt(v)]; }) } onSubmit={async (spaceName) => { const space = options.find((x) => x.label === spaceName); toast.info("Creating space..."); if (space) { toast.error("A space with that name already exists."); } const creationTask = await createSpace(spaceName); if (creationTask.success && creationTask.data) { toast.success("Space created " + creationTask.data); setSpaces((prev) => [ ...prev, { name: spaceName, id: creationTask.data!, createdAt: new Date(), user: null, numItems: 0, }, ]); setSelectedSpaces((prev) => [...prev, creationTask.data!]); } else { toast.error("Space creation failed: " + creationTask.error); } }} />