diff options
| author | codeTorso <[email protected]> | 2024-08-12 04:36:54 +0530 |
|---|---|---|
| committer | codeTorso <[email protected]> | 2024-08-12 04:36:54 +0530 |
| commit | 28f8149c342ecbbff278521127903f66fc545d67 (patch) | |
| tree | 77655e10def6c64f640540d93267c0e3712628a4 /apps/web | |
| parent | why is this novel shit broke (diff) | |
| download | supermemory-28f8149c342ecbbff278521127903f66fc545d67.tar.xz supermemory-28f8149c342ecbbff278521127903f66fc545d67.zip | |
alert when deleting space
Diffstat (limited to 'apps/web')
| -rw-r--r-- | apps/web/app/(dash)/(memories)/content.tsx | 118 | ||||
| -rw-r--r-- | apps/web/app/(dash)/layout.tsx | 2 | ||||
| -rw-r--r-- | apps/web/app/(dash)/menu.tsx | 14 |
3 files changed, 73 insertions, 61 deletions
diff --git a/apps/web/app/(dash)/(memories)/content.tsx b/apps/web/app/(dash)/(memories)/content.tsx index 6e2659cb..5d81e823 100644 --- a/apps/web/app/(dash)/(memories)/content.tsx +++ b/apps/web/app/(dash)/(memories)/content.tsx @@ -1,7 +1,7 @@ "use client"; import { Content, StoredSpace } from "@repo/db/schema"; -import { MemoriesIcon, NextIcon, SearchIcon, UrlIcon } from "@repo/ui/icons"; +import { MemoriesIcon, NextIcon, UrlIcon } from "@repo/ui/icons"; import { ArrowLeftIcon, MenuIcon, @@ -37,20 +37,22 @@ import { toast } from "sonner"; import { Input } from "@repo/ui/shadcn/input"; import { motion } from "framer-motion"; import { useSearchParams } from "next/navigation"; +import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@repo/ui/shadcn/alert-dialog"; + +type TMemoriesPage = { + memoriesAndSpaces: { memories: Content[]; spaces: StoredSpace[] }; + title?: string; + currentSpace?: StoredSpace; + usersWithAccess?: string[]; +}; export function MemoriesPage({ memoriesAndSpaces, title = "Your Memories", currentSpace, usersWithAccess, -}: { - memoriesAndSpaces: { memories: Content[]; spaces: StoredSpace[] }; - title?: string; - currentSpace?: StoredSpace; - usersWithAccess?: string[]; -}) { +}: TMemoriesPage) { const searchParams = useSearchParams(); - const tab = searchParams.get("tab"); const initialFilter = useMemo(() => { @@ -64,7 +66,6 @@ export function MemoriesPage({ const [filter, setFilter] = useState(initialFilter); const [spaces, setSpaces] = useState<StoredSpace[]>(memoriesAndSpaces.spaces); - // to delete a space const handleDeleteSpace = async (id: number) => { const response = await deleteSpace(id); @@ -72,7 +73,7 @@ export function MemoriesPage({ setSpaces(spaces.filter((space) => space.id !== id)); toast.success("Space deleted"); } else { - toast.error("Failed to delete space"); + toast.error("Failed to delete the space"); } }; @@ -96,25 +97,22 @@ export function MemoriesPage({ URL.revokeObjectURL(url); }; - // Sort Both memories and spaces by their savedAt and createdAt dates respectfully. - // The output should be just one single list of items - // And it will look something like { item: "memory" | "space", date: Date, data: Content | StoredSpace } const sortedItems = useMemo(() => { - // Merge the lists + // merge spaces & memories to { item: "memory" | "space", date: Date, data: Content | StoredSpace } const unifiedItems = [ ...memoriesAndSpaces.memories.map((memory) => ({ item: "memory", - date: new Date(memory.savedAt), // Assuming savedAt is a string date + date: new Date(memory.savedAt), data: memory, })), ...spaces.map((space) => ({ item: "space", - date: new Date(space.createdAt), // Assuming createdAt is a string date + date: new Date(space.createdAt), data: space, })), ].map((item) => ({ ...item, - date: Number(item.date), // Convert the date to a number + date: Number(item.date), })); // Sort the merged list @@ -142,28 +140,22 @@ export function MemoriesPage({ }, [memoriesAndSpaces.memories, spaces, filter]); return ( - <div - key={`${memoriesAndSpaces.memories.length + memoriesAndSpaces.spaces.length}`} - className="px-2 md:px-32 py-36 h-full flex mx-auto w-full flex-col gap-6" - > - {currentSpace && ( - <Link href={"/memories"} className="flex gap-2 items-center"> - <ArrowLeftIcon className="w-3 h-3" /> Back to all memories - </Link> - )} + <div className="px-2 md:px-32 py-36 h-full flex mx-auto w-full flex-col gap-6"> + <div className="space-y-2"> + {currentSpace && ( + <Link href={"/memories"}> + <Button className="px-0 text-gray-300" variant="link"> + <ArrowLeftIcon className="w-3 h-3" /> Back to all memories + </Button> + </Link> + )} + <h2 className="text-white w-full text-3xl text-left font-semibold"> + {title} + </h2> + </div> - <h2 className="text-white w-full text-3xl text-left font-semibold"> - {title} - </h2> {currentSpace && ( <div className="flex flex-col gap-2"> - <div className="flex gap-4 items-center"> - Space - <div className="flex items-center gap-2 bg-secondary p-2 rounded-xl"> - <Image src={MemoriesIcon} alt="Spaces icon" className="w-3 h-3" /> - <span className="text-[#fff]">{currentSpace.name}</span> - </div> - </div> {usersWithAccess && usersWithAccess.length > 0 && ( <div className="flex gap-4 items-center"> @@ -202,7 +194,11 @@ export function MemoriesPage({ }} className="flex gap-2 max-w-xl mt-2" > - <Input name="email" placeholder="Add user by email" /> + <Input + className="focus-visible:ring-0 border-[1px]" + name="email" + placeholder="Add user by email" + /> <Button variant="secondary">Add</Button> </form> </div> @@ -218,7 +214,7 @@ export function MemoriesPage({ /> <button onClick={handleExport} - className={`transition px-6 py-2 rounded-xl hover:text-[#369DFD]" text-[#B3BCC5] bg-secondary hover:bg-secondary hover:text-[#76a3cc]`} + className={`transition px-4 py-2 rounded-lg text-[#B3BCC5] bg-secondary hover:bg-secondary hover:text-[#76a3cc]`} > JSON Export </button> @@ -235,7 +231,7 @@ export function MemoriesPage({ {sortedItems.map((item) => { if (item.item === "memory") { return ( - <LinkComponent + <MemoryComponent type={(item.data as Content).type ?? "note"} content={(item.data as Content).content} title={(item.data as Content).title ?? "Untitled"} @@ -256,7 +252,7 @@ export function MemoriesPage({ if (item.item === "space") { return ( - <TabComponent + <SpaceComponent title={(item.data as StoredSpace).name} description={`${(item.data as StoredSpace).numItems} memories`} id={(item.data as StoredSpace).id} @@ -272,7 +268,7 @@ export function MemoriesPage({ ); } -function TabComponent({ +function SpaceComponent({ title, description, id, @@ -284,7 +280,7 @@ function TabComponent({ handleDeleteSpace: (id: number) => void; }) { return ( - <div className="flex group flex-col gap-4 bg-[#161f2a]/30 backdrop-blur-md border-2 border-border w-full rounded-xl p-4"> + <div className="flex group flex-col gap-4 bg-[#161f2a]/25 backdrop-blur-md border-[1px] shadow-md border-border w-full rounded-xl p-4"> <div className="flex items-center gap-2 text-xs"> <Image alt="Spaces icon" src={MemoriesIcon} className="size-3" /> Space </div> @@ -296,7 +292,7 @@ function TabComponent({ > <div> <div className="h-12 w-12 flex justify-center items-center rounded-md"> - {title.slice(0, 2).toUpperCase()} {id} + {title.slice(0, 2).toUpperCase()}{id} </div> </div> <div className="grow px-2"> @@ -308,17 +304,15 @@ function TabComponent({ </div> </Link> <div className="absolute z-40 right-3 top-3 opacity-0 group-hover:opacity-100 hover:text-red-600"> - <TrashIcon - onClick={() => handleDeleteSpace(id)} - className="w-4 cursor-pointer" - /> + + <SpaceDeleteAlert onClick={()=> {handleDeleteSpace(id)}} /> </div> </div> </div> ); } -function LinkComponent({ +function MemoryComponent({ type, content, title, @@ -445,12 +439,12 @@ function Filters({ filterMethods: string[]; }) { return ( - <div className="flex gap-4 flex-wrap"> + <div className="flex gap-3 flex-wrap"> {filterMethods.map((i) => { return ( <button onClick={() => setFilter(i)} - className={`transition px-6 py-2 rounded-xl bg-border ${i === filter ? " text-[#369DFD]" : "text-[#B3BCC5] bg-secondary hover:bg-secondary hover:text-[#76a3cc]"}`} + className={`transition px-4 py-2 shadow-md rounded-lg bg-border ${i === filter ? " text-[#369DFD]" : "text-[#B3BCC5] bg-secondary drop-shadow-md hover:bg-secondary hover:text-[#76a3cc]"}`} > {i} </button> @@ -460,4 +454,26 @@ function Filters({ ); } -export default MemoriesPage; +function SpaceDeleteAlert({onClick}: {onClick: ()=> void}){ + return ( + <AlertDialog> + <AlertDialogTrigger> <TrashIcon + className="w-4 cursor-pointer" + /></AlertDialogTrigger> + <AlertDialogContent> + <AlertDialogHeader> + <AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle> + <AlertDialogDescription> + This is irreversible. This will delete the space and all memories inside it. + </AlertDialogDescription> + </AlertDialogHeader> + <AlertDialogFooter> + <AlertDialogCancel>Cancel</AlertDialogCancel> + <AlertDialogAction onClick={onClick}>Delete</AlertDialogAction> + </AlertDialogFooter> + </AlertDialogContent> +</AlertDialog> + ) +} + +export default MemoriesPage;
\ No newline at end of file diff --git a/apps/web/app/(dash)/layout.tsx b/apps/web/app/(dash)/layout.tsx index c6174945..348263f0 100644 --- a/apps/web/app/(dash)/layout.tsx +++ b/apps/web/app/(dash)/layout.tsx @@ -26,7 +26,7 @@ async function Layout({ children }: { children: React.ReactNode }) { <Header /> </div> - <div className="relative flex justify-center z-40 pointer-events-none"> + <div className="relative flex justify-center z-[45] pointer-events-none"> <div className="absolute -z-10 left-0 top-[10%] h-32 w-[90%] overflow-x-hidden bg-[rgb(54,157,253)] bg-opacity-100 md:bg-opacity-70 blur-[337.4px]" style={{ transform: "rotate(-30deg)" }} diff --git a/apps/web/app/(dash)/menu.tsx b/apps/web/app/(dash)/menu.tsx index 51e97108..3124bdeb 100644 --- a/apps/web/app/(dash)/menu.tsx +++ b/apps/web/app/(dash)/menu.tsx @@ -66,11 +66,11 @@ function Menu() { <> {/* Desktop Menu */} <Dialog open={dialogOpen} onOpenChange={setDialogOpen}> - <div className="hidden lg:flex fixed h-screen pb-20 w-full p-4 items-center justify-start top-0 left-0 pointer-events-none z-[39]"> + <div className="hidden lg:flex fixed h-screen w-full p-4 items-center top-0 left-0 pointer-events-none z-[39]"> <div className="pointer-events-auto group flex w-14 text-foreground-menu text-[15px] font-medium flex-col items-start gap-6 overflow-hidden rounded-[28px] border-2 border-border bg-secondary px-3 py-4 duration-200 hover:w-40 z-[99999]"> <div className="border-b border-border pb-4 w-full"> <DialogTrigger - className={`flex w-full text-white brightness-75 hover:brightness-125 focus:brightness-125 cursor-pointer items-center gap-3 px-1 duration-200 justify-start`} + className="flex w-full text-white brightness-75 hover:brightness-125 focus:brightness-125 cursor-pointer items-center gap-3 px-1 duration-200 justify-start" > <Image src={AddIcon} @@ -86,14 +86,9 @@ function Menu() { </div> {menuItems.map((item) => ( <Link - aria-disabled={item.disabled} - href={item.disabled ? "#" : item.url} + href={item.url} key={item.url} - className={`flex w-full ${ - item.disabled - ? "cursor-not-allowed opacity-30" - : "text-white brightness-75 hover:brightness-125 cursor-pointer" - } items-center gap-3 px-1 duration-200 hover:scale-105 active:scale-90 justify-start`} + className="flex w-full items-center gap-3 px-1 duration-200 hover:scale-105 active:scale-90 justify-start text-white brightness-75 hover:brightness-125 cursor-pointer" > <Image src={item.icon} @@ -297,6 +292,7 @@ function DialogContentMenu({setDialogClose}: {setDialogClose: ()=> void}){ <div> <Label htmlFor="name">Resource (URL or content)</Label> <Textarea + autoFocus className={`bg-[#2F353C] text-[#DBDEE1] max-h-[35vh] overflow-auto focus-visible:ring-0 border-none focus-visible:ring-offset-0 mt-2 ${/^https?:\/\/\S+$/i.test(content) && "text-[#1D9BF0] underline underline-offset-2"}`} id="content" name="content" |