diff --git a/package-lock.json b/package-lock.json index e916d75..38a04ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,17 @@ { - "name": "clipfusion-community", + "name": "clipfusion", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "clipfusion-editor", + "name": "clipfusion", "version": "1.0.0", "dependencies": { "@hookform/resolvers": "^5.1.1", + "@radix-ui/react-alert-dialog": "^1.1.14", "@radix-ui/react-aspect-ratio": "^1.1.7", + "@radix-ui/react-checkbox": "^1.3.2", "@radix-ui/react-dialog": "^1.1.14", "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-separator": "^1.1.7", @@ -17,6 +19,7 @@ "@radix-ui/react-switch": "^1.2.5", "@radix-ui/react-toggle": "^1.1.9", "@radix-ui/react-tooltip": "^1.2.7", + "@react-hook/hotkey": "^3.1.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "dexie": "^4.0.11", @@ -27,6 +30,7 @@ "react": "19.1.0", "react-dom": "19.1.0", "react-hook-form": "^7.60.0", + "sonner": "^2.0.6", "tailwind-merge": "^3.3.1", "zod": "^4.0.5" }, @@ -1041,6 +1045,34 @@ "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==", "license": "MIT" }, + "node_modules/@radix-ui/react-alert-dialog": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.14.tgz", + "integrity": "sha512-IOZfZ3nPvN6lXpJTBCunFQPRSvK8MDgSc1FB85xnIpUKOw9en0dJj8JmCAxV7BiZdtYlUpmrQjoTFkVYtdoWzQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dialog": "1.1.14", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-arrow": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", @@ -1087,6 +1119,36 @@ } } }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.2.tgz", + "integrity": "sha512-yd+dI56KZqawxKZrJ31eENUwqc1QSqg4OZ15rybGjF2ZNwMO+wCyHzAVLRp9qoYJf7kYy0YpZ2b0JCzJ42HZpA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-compose-refs": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", @@ -1658,6 +1720,27 @@ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", "license": "MIT" }, + "node_modules/@react-hook/event": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@react-hook/event/-/event-1.2.6.tgz", + "integrity": "sha512-JUL5IluaOdn5w5Afpe/puPa1rj8X6udMlQ9dt4hvMuKmTrBS1Ya6sb4sVgvfe2eU4yDuOfAhik8xhbcCekbg9Q==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/@react-hook/hotkey": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@react-hook/hotkey/-/hotkey-3.1.0.tgz", + "integrity": "sha512-ekIIW8S12P/fP9krrsOWZCIqzQPzjz2WVkD3v1epP6SAy/XxDIWgJrItd2ySh0RKLkYcfW8z+eii3W/h1TKjOg==", + "license": "MIT", + "dependencies": { + "@react-hook/event": "^1.2.1" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -6356,6 +6439,16 @@ "is-arrayish": "^0.3.1" } }, + "node_modules/sonner": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.6.tgz", + "integrity": "sha512-yHFhk8T/DK3YxjFQXIrcHT1rGEeTLliVzWbO0xN8GberVun2RiBnxAjXAYpZrqwEVHBG9asI/Li8TAAhN9m59Q==", + "license": "MIT", + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", diff --git a/package.json b/package.json index d64aa46..922a380 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "clipfusion-community", + "name": "clipfusion", "version": "1.0.0", "private": true, "scripts": { @@ -10,7 +10,9 @@ }, "dependencies": { "@hookform/resolvers": "^5.1.1", + "@radix-ui/react-alert-dialog": "^1.1.14", "@radix-ui/react-aspect-ratio": "^1.1.7", + "@radix-ui/react-checkbox": "^1.3.2", "@radix-ui/react-dialog": "^1.1.14", "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-separator": "^1.1.7", @@ -18,6 +20,7 @@ "@radix-ui/react-switch": "^1.2.5", "@radix-ui/react-toggle": "^1.1.9", "@radix-ui/react-tooltip": "^1.2.7", + "@react-hook/hotkey": "^3.1.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "dexie": "^4.0.11", @@ -28,6 +31,7 @@ "react": "19.1.0", "react-dom": "19.1.0", "react-hook-form": "^7.60.0", + "sonner": "^2.0.6", "tailwind-merge": "^3.3.1", "zod": "^4.0.5" }, diff --git a/src/Dockerfile b/src/Dockerfile index a640085..af50048 100644 --- a/src/Dockerfile +++ b/src/Dockerfile @@ -1,7 +1,3 @@ -ARG ENABLE_ANALYTICS=false -ARG ANALYTICS_SCRIPT -ARG ANALYTICS_WEBSITE_ID - FROM node:lts-alpine3.22 AS base FROM base AS deps diff --git a/src/app/favicon.ico b/src/app/favicon.ico new file mode 100644 index 0000000..d37e877 Binary files /dev/null and b/src/app/favicon.ico differ diff --git a/src/app/favicon.svg b/src/app/favicon.svg deleted file mode 100644 index f23a57c..0000000 --- a/src/app/favicon.svg +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 44b2931..3e747d0 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -6,6 +6,8 @@ import Dashboard from "@/components/dashboard"; import "./globals.css"; import ThemeProvider from "./theme-provider"; import Analytics from "./analytics"; +import PersistenceProvider from "./persistence-provider"; +import { Toaster } from "@/components/ui/sonner"; const geist = Geist({ variable: "--font-geist", @@ -23,7 +25,7 @@ export const metadata: Metadata = { }; -export default function RootLayout({ +export default async function RootLayout({ children, }: Readonly<{ children: ReactNode; @@ -37,10 +39,13 @@ export default function RootLayout({ -
- {children} +
+ + {children} +
+ diff --git a/src/app/page.tsx b/src/app/page.tsx index 66b4e90..af8c306 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,23 +1,41 @@ "use client"; import { SidebarTrigger } from "@/components/ui/sidebar"; -import { ReactNode } from "react"; +import { FormEvent, ReactNode, useState } from "react"; import { useLiveQuery } from "dexie-react-hooks"; import { db } from "@/lib/db"; import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; -import { ListIcon, PlusIcon } from "lucide-react"; +import { ListCheckIcon, PlusIcon } from "lucide-react"; import { Toggle } from "@/components/ui/toggle"; import Search from "@/components/search"; import { useIsMobile } from "@/hooks/use-mobile"; import { AspectRatio } from "@/components/ui/aspect-ratio"; import { Card } from "@/components/ui/card"; +import Project from "@/types/Project"; +import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; +import { z } from "zod"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod" +import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; +import { Textarea } from "@/components/ui/textarea"; +import { generateUUID } from "@/lib/uuid"; -const Project = (): ReactNode => { +const NewProjectFormSchema = z.object({ + title: z.string().nonempty("Title cannot be empty"), + description: z.string().or(z.literal("")) +}); + +const ProjectContainer = ({ + project +}: { + project: Project +}): ReactNode => { return ( - + -

Project Title

-

Project description goes here.

+

{project.title}

+ {project.description &&

{project.description}

}
) @@ -25,39 +43,104 @@ const Project = (): ReactNode => { export default function Home(): ReactNode { const isMobile = useIsMobile(); + const [search, setSearch] = useState(''); - const projectsCount = useLiveQuery(() => { - return db.projects.count(); + const projects = useLiveQuery(() => { + return db.projects.filter((project) => project.title.includes(search)).toArray(); }); + const newProjectForm = useForm>({ + resolver: zodResolver(NewProjectFormSchema), + defaultValues: { + title: "New ClipFusion Project", + description: "" + } + }); + + const newProjectSubmit = async (data: z.infer) => { + const date = Date.now(); + await db.projects.add({ + uuid: generateUUID(), + creationDate: date, + editDate: date, + title: data.title, + description: data.description, + origin: "" + }); + }; + return ( -
+

Project Library

- + {projects && }
- + + + + + + + + Create New Project + + + Fill in the information about your project. You can change it at any time later. + + +
+ + ( + + Title + + + + + + )}/> + ( + + Description + +