diff --git a/src/Home.jsx b/src/Home.jsx
index 6b4a77f..8572ad9 100644
--- a/src/Home.jsx
+++ b/src/Home.jsx
@@ -11,35 +11,52 @@ import { useQuery } from '@tanstack/react-query';
import { generateToken } from './api/authApi';
import { useNavigate } from "react-router-dom";
import { Toaster } from '@/components/ui/toaster';
+import { getProjectById } from './api/projectApi';
+import { Loader } from 'lucide-react';
+import CanvasContext from './components/Context/canvasContext/CanvasContext';
export const Home = () => {
const { activeObject } = useContext(ActiveObjectContext);
+ const { canvas, selectedPanel } = useContext(CanvasContext);
const params = useParams();
- const getToken = localStorage.getItem('canvas_token');
-
- const { id } = params;
const navigate = useNavigate();
+ const getToken = () => localStorage.getItem('canvas_token');
+
+ const { id } = params;
+
+ // Fetch token only if it doesn't exist
const { data, isLoading } = useQuery({
queryKey: ['get-token'],
queryFn: () => generateToken(id),
- enabled: !getToken
- })
- console.log(data);
+ });
+
+ // Fetch project data only if token and id exist
+ const { data: projectData, isLoading: projectLoading } = useQuery({
+ queryKey: ['project', id],
+ queryFn: async () => await getProjectById(id),
+ enabled: !!getToken() && !!id && selectedPanel === "project",
+ });
useEffect(() => {
- if (!getToken && !isLoading) {
+ const token = getToken(); // Get latest token
+
+ if (!token && !isLoading) {
navigate("/unAuthenticated");
}
- if (getToken && !isLoading && data?.status === 201) {
+ if (token && !isLoading && data?.status === 201) {
navigate("/");
}
- }, [getToken, navigate, isLoading, data])
+ if (projectData?.status === 200 & !projectLoading && projectData?.data?.object && canvas && canvas?._objects?.length === 0 && selectedPanel === "project") {
+ canvas.loadFromJSON(projectData?.data?.object);
+ canvas.renderAll();
+ }
+ }, [navigate, isLoading, data, projectData, projectLoading, canvas, selectedPanel]);
return (
{
- isLoading &&
Loading...
+ isLoading &&
}
{!isLoading &&
<>
diff --git a/src/api/projectApi.ts b/src/api/projectApi.ts
index 4289d2c..f4f2191 100644
--- a/src/api/projectApi.ts
+++ b/src/api/projectApi.ts
@@ -8,7 +8,7 @@ interface Project {
export const getProjects = async () => {
try {
- const response = await fetch(`${import.meta.env.VITE_SERVER_URL}/projects`, {
+ const response = await fetch(`${import.meta.env.VITE_SERVER_URL}/projects/`, {
method: 'GET',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
diff --git a/src/components/CanvasSetting.jsx b/src/components/CanvasSetting.jsx
index c5c9c91..e27c25a 100644
--- a/src/components/CanvasSetting.jsx
+++ b/src/components/CanvasSetting.jsx
@@ -31,7 +31,12 @@ const CanvasSetting = () => {
const createEmptyProject = async () => {
try {
const response = await createProject();
- console.log(response);
+ if (response?.status === 200) {
+ toast({
+ title: response?.status,
+ description: response?.message
+ })
+ }
if (response?.data?.id) {
navigate(`/${response.data.id}`);
}
@@ -42,7 +47,7 @@ const CanvasSetting = () => {
if (!id) {
createEmptyProject();
}
- }, [id, navigate]);
+ }, [id, navigate, toast]);
// upload bg-image handler
const { mutate: uploadBackgroundImage } = useMutation({
diff --git a/src/components/EachComponent/UploadImage.jsx b/src/components/EachComponent/UploadImage.jsx
index 753ab95..6f9960f 100644
--- a/src/components/EachComponent/UploadImage.jsx
+++ b/src/components/EachComponent/UploadImage.jsx
@@ -26,9 +26,9 @@ import ImageCustomization from "./Customization/ImageCustomization";
import { Separator } from "../ui/separator";
import ActiveObjectContext from "../Context/activeObject/ObjectContext";
import { useNavigate, useParams } from "react-router-dom";
-import { useMutation } from "@tanstack/react-query";
+import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { deleteImage, uploadImage } from "../../api/uploadApi";
-import { createProject } from "../../api/projectApi";
+import { createProject, getProjectById, updateProject } from "../../api/projectApi";
import { useToast } from "../../hooks/use-toast";
const UploadImage = () => {
@@ -56,6 +56,12 @@ const UploadImage = () => {
const createEmptyProject = async () => {
try {
const response = await createProject();
+ if (response?.status === 200) {
+ toast({
+ title: response?.status,
+ description: response?.message
+ })
+ }
if (response?.data?.id) {
navigate(`/${response.data.id}`);
}
@@ -66,7 +72,38 @@ const UploadImage = () => {
if (!id) {
createEmptyProject();
}
- }, [id, navigate]);
+ }, [id, navigate, toast]);
+
+ const queryClient = useQueryClient();
+
+ // to get each canvas_project data
+ const { data: projectData } = useQuery({
+ queryKey: ['project', id],
+ queryFn: async () => await getProjectById(id),
+ enabled: !!id,
+ });
+
+ console.log(projectData);
+
+ // to update the project
+ const { mutate: projectUpdate } = useMutation({
+ mutationFn: async ({ id, updateData }) => {
+ return await updateProject({ id, ...updateData })
+ },
+ onSuccess: (data) => {
+ if (data?.status === 200) {
+ // Invalidate a single query key
+ queryClient.invalidateQueries({ queryKey: ["project", id] });
+ }
+ else {
+ toast({
+ title: data?.status,
+ description: data?.message,
+ variant: "destructive"
+ })
+ }
+ }
+ });
// upload image handler
const { mutate } = useMutation({
@@ -94,6 +131,12 @@ const UploadImage = () => {
},
{ crossOrigin: "anonymous" }
);
+ if (canvas) {
+ const object = canvas.toJSON(['id', 'selectable']); // Include any custom properties you need
+ const updateData = { ...projectData?.data, object, preview_url: "" };
+ // Wait for the project update before continuing
+ projectUpdate({ id, updateData });
+ }
}
else {
toast({
@@ -104,7 +147,7 @@ const UploadImage = () => {
removeFile();
}
}
- })
+ });
// handle image remove
const { mutate: deleteMutate } = useMutation({
@@ -117,6 +160,12 @@ const UploadImage = () => {
title: data?.status,
description: data?.message
})
+ if (canvas) {
+ const object = canvas.toJSON(['id', 'selectable']); // Include any custom properties you need
+ const updateData = { ...projectData?.data, object };
+ // Wait for the project update before continuing
+ projectUpdate({ id, updateData });
+ }
}
else {
toast({
diff --git a/src/components/Panel/EditorPanel.jsx b/src/components/Panel/EditorPanel.jsx
index ef328b0..3180b83 100644
--- a/src/components/Panel/EditorPanel.jsx
+++ b/src/components/Panel/EditorPanel.jsx
@@ -12,6 +12,8 @@ import PositionPanel from "./PositionPanel";
import ImagePanel from "./ImagePanel";
import GroupObjectPanel from "./GroupObjectPanel";
import CanvasPanel from "./CanvasPanel";
+import { ProjectPanel } from "./ProjectPanel";
+import ImageLibrary from "./ImageLibrary";
const EditorPanel = () => {
const { selectedPanel } = useContext(CanvasContext);
@@ -42,6 +44,10 @@ const EditorPanel = () => {
return
;
case "canvas":
return
;
+ case "project":
+ return
;
+ case "image":
+ return
;
default:
return;
}
diff --git a/src/components/Panel/ImageLibrary.jsx b/src/components/Panel/ImageLibrary.jsx
new file mode 100644
index 0000000..f5a2e76
--- /dev/null
+++ b/src/components/Panel/ImageLibrary.jsx
@@ -0,0 +1,28 @@
+import { useContext } from 'react'
+import CanvasContext from '../Context/canvasContext/CanvasContext';
+import { Button } from '../ui/button';
+import { X } from 'lucide-react';
+import { ScrollArea } from '../ui/scroll-area';
+const ImageLibrary = () => {
+ const { setSelectedPanel } = useContext(CanvasContext);
+ return (
+
+
+
Image Library
+
+
+
+
+ {/* Image library content goes here */}
+
+
+ );
+}
+
+export default ImageLibrary
\ No newline at end of file
diff --git a/src/components/Panel/ProjectPanel.jsx b/src/components/Panel/ProjectPanel.jsx
new file mode 100644
index 0000000..7ce1176
--- /dev/null
+++ b/src/components/Panel/ProjectPanel.jsx
@@ -0,0 +1,119 @@
+import { useContext } from 'react';
+import CanvasContext from '../Context/canvasContext/CanvasContext';
+import { Button } from '../ui/button';
+import { Loader, Trash, X } from 'lucide-react';
+import { ScrollArea } from '../ui/scroll-area';
+import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
+import { deleteProject, getProjects } from '@/api/projectApi';
+import { useNavigate } from 'react-router-dom';
+import { toast } from '@/hooks/use-toast';
+import ActiveObjectContext from '../Context/activeObject/ObjectContext';
+import { FixedSizeList as List } from 'react-window'; // Import FixedSizeList from react-window
+
+export const ProjectPanel = () => {
+ const { setSelectedPanel, canvas } = useContext(CanvasContext);
+ const { setActiveObject } = useContext(ActiveObjectContext);
+ const navigate = useNavigate();
+ const queryClient = useQueryClient(); // Initialize query client
+
+ const { data: projects, isLoading: projectLoading, isSuccess: projectSuccess } = useQuery({
+ queryKey: ['projects'],
+ queryFn: getProjects, // Simplified function call
+ });
+
+ // To delete a project
+ const { mutate: projectDelete, isPending: deletePending } = useMutation({
+ mutationFn: async (id) => await deleteProject(id),
+ onSuccess: (data, id) => {
+ if (data?.status === 200) {
+ toast({
+ title: data?.status,
+ description: data?.message,
+ });
+
+ // Invalidate queries to refresh data
+ queryClient.invalidateQueries({ queryKey: ["projects"] });
+ queryClient.invalidateQueries({ queryKey: ["project", id] });
+
+ // Clear canvas if it exists
+ if (canvas) {
+ canvas.clear();
+ canvas.renderAll();
+ canvas.setBackgroundColor("#ffffff", canvas.renderAll.bind(canvas));
+ }
+ setActiveObject(null);
+
+ setSelectedPanel("");
+ navigate("/");
+
+ } else {
+ toast({
+ title: data?.status,
+ description: data?.message,
+ variant: "destructive"
+ });
+ }
+ },
+ onError: (error) => {
+ toast({
+ title: "Error",
+ description: error.message || "Failed to delete the project",
+ variant: "destructive",
+ });
+ }
+ });
+
+ // Row renderer for react-window
+ const Row = ({ index, style }) => {
+ const project = projects?.data?.[index]; // Get project by index
+
+ return (
+
+
navigate(`/${project.id}`)}>
+
{project?.name}
+
{project?.description}
+

+
+
+
+
+ );
+ };
+
+ return (
+
+
+
Projects
+
+
+
+
+ {
+ projectLoading &&
+ }
+ {
+ !projectLoading && projectSuccess && projects?.status === 200 &&
+
+ {Row}
+
+ }
+ {
+ projects?.status !== 200 && {projects?.message}
+ }
+
+
+ );
+};
diff --git a/src/components/SaveCanvas.jsx b/src/components/SaveCanvas.jsx
index 973363e..eb1ac24 100644
--- a/src/components/SaveCanvas.jsx
+++ b/src/components/SaveCanvas.jsx
@@ -49,16 +49,18 @@ const SaveCanvas = () => {
title: data?.status,
description: data?.message,
})
- console.log(data);
// Invalidate a single query key
queryClient.invalidateQueries({ queryKey: ["project", id] });
- // to load the object into canvas
- // canvas.loadFromJSON(data?.data?.object, () => {
- // canvas.renderAll();
- // }, (err) => {
- // console.error('Error loading object:', err);
- // });
+ // Clear canvas if it exists
+ if (canvas) {
+ canvas.clear();
+ canvas.renderAll();
+ canvas.setBackgroundColor("#ffffff", canvas.renderAll.bind(canvas));
+ }
+ setActiveObject(null);
+ setSelectedPanel("");
+ navigate("/");
}
else {
toast({
@@ -81,15 +83,19 @@ const SaveCanvas = () => {
title: data?.status,
description: data?.message,
})
+ // Clear canvas if it exists
+ if (canvas) {
+ canvas.clear();
+ canvas.renderAll();
+ canvas.setBackgroundColor("#ffffff", canvas.renderAll.bind(canvas));
+ }
+ setActiveObject(null);
+
// Invalidate a single query key
queryClient.invalidateQueries({ queryKey: ["project", id] });
setSelectedPanel("");
navigate("/");
- // for clear canvas
- canvas.clear();
- canvas.renderAll();
- canvas.setBackgroundColor("#ffffff", canvas.renderAll.bind(canvas));
- setActiveObject(null);
+
}
else {
toast({
@@ -179,19 +185,14 @@ const SaveCanvas = () => {
if (saveCanvas?.preview_url) {
try {
removeCanvasImage(saveCanvas?.preview_url);
- console.log("Image removed", saveCanvas?.preview_url);
} catch (error) {
console.error("Error removing image:", error);
}
} else {
try {
- console.log("Capturing image...");
const file = await captureImage();
- console.log("Captured file:", file);
-
if (file) {
uploadCanvasImage({ file, id });
- console.log("Image uploaded successfully");
}
} catch (error) {
console.error("Error capturing image:", error);
@@ -270,13 +271,18 @@ const SaveCanvas = () => {
return (
-
Save Canvas
-
- {
- saveCanvas?.preview_url &&
-

- }
-
+
Save Canvas
+
+ {
+ saveCanvas?.preview_url &&
+
+ {
+ saveCanvas?.preview_url &&
+

+ }
+
+ }
+