From 43542f2c34747228b95a11a9a47b7e264d14ef85 Mon Sep 17 00:00:00 2001 From: corgifist Date: Sat, 26 Jul 2025 02:36:11 +0300 Subject: [PATCH] implemented barebones project selection ui --- src/app/layout.tsx | 2 +- src/app/page.tsx | 93 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 84 insertions(+), 11 deletions(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index cf9047d..c58a68a 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -48,7 +48,7 @@ export default async function RootLayout({ -
+
{children} diff --git a/src/app/page.tsx b/src/app/page.tsx index 525c384..1a04148 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,11 +1,11 @@ "use client"; import { SidebarTrigger } from "@/components/ui/sidebar"; -import { ReactNode, useState } from "react"; +import { createContext, Dispatch, ReactNode, SetStateAction, useContext, useEffect, useState } from "react"; import { useLiveQuery } from "dexie-react-hooks"; import { addProject, db, deleteProject } from "@/lib/db"; import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; -import { CopyIcon, EditIcon, EllipsisIcon, InfoIcon, ListCheckIcon, PencilIcon, PlusIcon, TrashIcon } from "lucide-react"; +import { CopyIcon, EditIcon, EllipsisIcon, Grid2X2CheckIcon, InfoIcon, ListCheckIcon, PencilIcon, PlusIcon, TrashIcon } from "lucide-react"; import { Toggle } from "@/components/ui/toggle"; import Search from "@/components/search"; import { useIsMobile } from "@/hooks/use-mobile"; @@ -24,6 +24,22 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog"; import { useDebounce } from "use-debounce"; +import { Checkbox } from "@/components/ui/checkbox"; + +interface SelectContextData { + selecting: boolean; + setSelecting: Dispatch>; + selectedProjects: string[]; + setSelectedProjects: Dispatch>; +}; + +const SelectContext = createContext(null); + +const useSelectContext = (): SelectContextData => { + const context = useContext(SelectContext); + if (!context) throw new Error("SelectContext is not provided"); + return context; +}; const ProjectInfoFormSchema = z.object({ title: z.string().nonempty("Title cannot be empty"), @@ -116,7 +132,16 @@ const DeleteProjectDialog = ({ project }: { project: Project }) => { ); } -const ProjectDropdown = ({ project }: { project: Project }): ReactNode => { +const ProjectDropdown = ({ + project, + selected, + setSelected +}: { + project: Project, + selected: boolean, + setSelected: Dispatch> + }): ReactNode => { + const { selecting, setSelecting } = useSelectContext(); const [renameDialogOpen, setRenameDialogOpen] = useState(false); const [deleteAlertOpen, setDeleteAlertOpen] = useState(false); const isMobile = useIsMobile(); @@ -145,6 +170,11 @@ const ProjectDropdown = ({ project }: { project: Project }): ReactNode => { addProject(newProject as Project); }; + const handleSelect = () => { + if (!selecting) setSelecting(true); + setSelected(!selected); + }; + return ( @@ -161,6 +191,9 @@ const ProjectDropdown = ({ project }: { project: Project }): ReactNode => { + + Select + console.log("Edit Project")}> Edit @@ -211,9 +244,35 @@ const ProjectContainer = ({ }: { project: Project }): ReactNode => { + const { selecting, selectedProjects, setSelectedProjects } = useSelectContext(); + const [selected, setSelected] = useState(false); + const [mounted, setMounted] = useState(false); + + if (!selecting && selected) setSelected(false); + const date = new Date(project.editDate); + const handleClick = () => { + if (selecting) { + setSelected(!selected); + } + }; + + // Automatically add UUID to the selectedProjects + useEffect(() => { + if (mounted) { + if (selected) { + setSelectedProjects([...selectedProjects, project.uuid]); + } else { + const newSelectedProject = selectedProjects; + newSelectedProject.splice(newSelectedProject.indexOf(project.uuid), 1); + setSelectedProjects(newSelectedProject); + } + } + setMounted(true); + }, [selected]); + return ( - +
@@ -224,9 +283,14 @@ const ProjectContainer = ({
- +
+ {selecting && ( +
+ setSelected(checked as boolean)}/> +
+ )}
) @@ -235,6 +299,8 @@ const ProjectContainer = ({ export default function Home(): ReactNode { const isMobile = useIsMobile(); const [search, setSearch] = useState(''); + const [selecting, setSelecting] = useState(false); + const [selectedProjects, setSelectedProjects] = useState([]); const [debouncedSearch] = useDebounce(search, 300); const projects = useLiveQuery(() => ( @@ -261,15 +327,22 @@ export default function Home(): ReactNode { } as Project); }; + const context: SelectContextData = { + selecting, + setSelecting, + selectedProjects, + setSelectedProjects + }; + return ( - <> -
+ +

Project Library

{projects && }
-
+
@@ -303,7 +376,7 @@ export default function Home(): ReactNode {
- + setSelecting(pressed)}> {!isMobile && "Select Projects"} setSearch(e.target.value)} /> @@ -318,6 +391,6 @@ export default function Home(): ReactNode {
)}
- + ); };