Skip to content

Commit 9e7fa02

Browse files
committedDec 22, 2024·
Set Preview.tsx Function
1 parent b81cd6e commit 9e7fa02

File tree

11 files changed

+175
-29
lines changed

11 files changed

+175
-29
lines changed
 

‎src/assets/loading.gif

1.12 MB
Loading

‎src/components/canvas/Canvas.tsx

+19-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ import {
55
Rect,
66
Circle,
77
Line
8-
} from 'fabric';
8+
} from 'fabric';
99

1010
// STORES
1111
import useTools from '@/stores/tools/useTools';
12+
import useCanvasStore from '@/stores/canvasStore/useCanvasStore';
1213

1314
export default function Canvas() {
1415
const canvasRef = useRef<HTMLCanvasElement | null>(null);
@@ -39,7 +40,9 @@ export default function Canvas() {
3940
setAddVerticalLine,
4041
} = useTools();
4142

42-
43+
44+
// Update the canvas store with the current canvas data
45+
const { setJsonData } = useCanvasStore();
4346

4447
useEffect(() => {
4548
if (canvasRef.current) {
@@ -80,10 +83,24 @@ export default function Canvas() {
8083

8184
window.addEventListener('keydown', handleKeyDown);
8285

86+
// Update JSON data whenever the canvas changes
87+
const updateJsonData = () => {
88+
const json = canvas.toJSON();
89+
const jsonString = JSON.stringify(json);
90+
setJsonData(jsonString);
91+
};
92+
93+
canvas.on('object:added', updateJsonData);
94+
canvas.on('object:modified', updateJsonData);
95+
canvas.on('object:removed', updateJsonData);
96+
8397
// Cleanup function
8498
return () => {
8599
canvas.dispose();
86100
window.removeEventListener('keydown', handleKeyDown);
101+
canvas.off('object:added', updateJsonData);
102+
canvas.off('object:modified', updateJsonData);
103+
canvas.off('object:removed', updateJsonData);
87104
};
88105
}
89106
}, []);

‎src/components/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ export { default as Manage } from './manage/Manage';
33
export { default as Canvas } from './canvas/Canvas';
44
export { default as Preview } from './preview/Preview';
55
export { default as Displays } from './displays/Displays';
6+
export { default as LoadingState } from './ui/LoadingState';
7+

‎src/components/preview/Preview.tsx

+117-21
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,126 @@
1+
import { useRef, useEffect, useState } from "react";
2+
import { Canvas } from "fabric";
3+
14
// UI
25
import { Button } from "../ui/button";
6+
import LoadingState from "../ui/LoadingState";
37

48
// ICONS
59
import { FcWebcam } from "react-icons/fc";
610

11+
// STORES
12+
import useLivePreview from "@/stores/livePreview/useLivePreview";
13+
import useCanvasStore from "@/stores/canvasStore/useCanvasStore";
14+
715
export default function Preview() {
16+
const previewCanvasRef = useRef<HTMLCanvasElement | null>(null);
17+
const canvasInstance = useRef<Canvas | null>(null);
18+
const { jsonData } = useCanvasStore();
19+
const { loadingLivePreview, setLoadingLivePreview } = useLivePreview();
20+
21+
const [canvasReady, setCanvasReady] = useState<boolean>(false);
22+
23+
const [hiddenCanvas, setHiddenCanvas] = useState<boolean>(true);
24+
25+
26+
// Function to initialize the canvas
27+
const initializeCanvas = () => {
28+
if (previewCanvasRef.current && jsonData) {
29+
if (canvasInstance.current) {
30+
canvasInstance.current.dispose();
31+
}
32+
33+
const canvas = new Canvas(previewCanvasRef.current);
34+
canvasInstance.current = canvas;
35+
36+
// Set canvas dimensions
37+
canvas.setDimensions({ width: 263, height: 130 });
38+
canvas.getContext().scale(1, 1);
39+
40+
// Make the objects smaller
41+
canvas.setZoom(0.27);
42+
43+
// Load JSON data and apply restrictions
44+
canvas.loadFromJSON(jsonData, () => {
45+
46+
// Prevent selection
47+
canvas.on("selection:created", () => {
48+
canvas.discardActiveObject(); // Deselect any selection
49+
});
50+
51+
setTimeout(() => {
52+
canvas.renderAll(); // Re-render the canvas
53+
setHiddenCanvas(false);
54+
}, 3000)
55+
setTimeout(() => {
56+
setLoadingLivePreview(false);
57+
}, 3500)
58+
});
59+
} else {
60+
console.error("Canvas data is not available yet.");
61+
setLoadingLivePreview(false);
62+
}
63+
};
64+
65+
66+
67+
// Ensure the reference is ready before initializing
68+
useEffect(() => {
69+
if (previewCanvasRef.current) {
70+
setCanvasReady(true); // Mark the canvas as ready
71+
}
72+
}, []);
73+
74+
// Handle live preview button click
75+
const handleLivePreviewClick = () => {
76+
if (!canvasReady) {
77+
console.error("Canvas is not ready yet.");
78+
return;
79+
}
80+
setLoadingLivePreview(true);
81+
setHiddenCanvas(true);
82+
initializeCanvas();
83+
};
84+
885
return (
9-
<div className="mt-5 mb-6 px-3">
10-
11-
{/* TITLE + Live preview btn */}
12-
<div className="flex justify-between items-center mb-6">
13-
<h6 className="font-semibold">Preview</h6>
14-
<Button variant="secondary" className="flex justify-between items-center border-[1px] border-gray-300">
15-
<FcWebcam className="!size-5" />
16-
<span>Live Preview</span>
17-
</Button>
18-
</div>
19-
20-
{/* PREVIEW BOX */}
21-
<div id="previewBox" className="px-3 bg-[ghostwhite] border-[1px] border-gray-200 w-full h-[150px] rounded-md shadow-sm">
22-
23-
<span id="noPreview">
24-
<div className="flex justify-center items-center h-full text-gray-500 font-normal">Preview</div>
25-
</span>
26-
</div>
27-
28-
</div>
29-
)
86+
<div className="mt-5 mb-6 px-3">
87+
{/* TITLE + Live preview btn */}
88+
<div className="flex justify-between items-center mb-6">
89+
<h6 className="font-semibold">Live Preview</h6>
90+
<Button
91+
disabled={loadingLivePreview || !canvasReady}
92+
onClick={handleLivePreviewClick}
93+
variant="secondary"
94+
className="flex justify-between items-center border-[1px] border-gray-300"
95+
>
96+
<FcWebcam className="!size-5" />
97+
<span>Refresh</span>
98+
</Button>
99+
</div>
100+
101+
{/* PREVIEW BOX */}
102+
<div id="previewBox" className={`${hiddenCanvas ? 'hidden' : 'block'} rounded-md shadow-sm hover:shadow-md transition-shadow duration-300
103+
overflow-hidden border-[1px] border-gray-200 py-1 pl-[3.3px]`}>
104+
105+
<canvas ref={previewCanvasRef} className="rounded-md min-w-[263px] max-h-[130px]"></canvas>
106+
107+
</div>
108+
109+
{/* PRE-PREVIEW */}
110+
<div className={`${hiddenCanvas ? 'block' : 'hidden'} rounded-md border-[1px] border-gray-200 min-h-[138px]`}>
111+
112+
{/* Loading State */}
113+
{loadingLivePreview ? (
114+
<div className="flex justify-center items-center min-h-[138px]">
115+
<LoadingState setWidth="50" />
116+
</div>
117+
) : (
118+
<div className="flex justify-center items-center min-h-[138px] text-gray-500 font-normal">
119+
Refresh to see live preview
120+
</div>
121+
)}
122+
</div>
123+
124+
</div>
125+
);
30126
}

‎src/components/ui/LoadingState.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default function LoadingState({setWidth}: { setWidth: string }) {
2+
return (
3+
<img src="/src/assets/loading.gif" width={setWidth} />
4+
)
5+
}

‎src/interfaces/index.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
export type { default as useTools_interface } from './tools/useTools_interface'
1+
export type { default as useTools_interface } from './tools/useTools_interface'
2+
export type { default as useFileName_interface } from './settings/useFileName_interface'
3+
export type { default as useLivePreview_interface } from './livePreview/useLivePreview_interface'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export default interface useLivePreview_interface {
2+
loadingLivePreview: boolean;
3+
setLoadingLivePreview: (data: boolean) => void;
4+
}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
interface useFileName_interface {
1+
export default interface useFileName_interface {
22
currentFileName: string,
33
setCurrentFileName: (state: string) => void,
44

55
newFileName: string,
66
setNewFileName: (state: string) => void,
77

8-
}
9-
10-
export default useFileName_interface
8+
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { create } from 'zustand';
2+
3+
interface CanvasStore_interface {
4+
jsonData: string;
5+
setJsonData: (data: string) => void;
6+
}
7+
8+
export const useCanvasStore = create<CanvasStore_interface>((set) => ({
9+
jsonData: '',
10+
setJsonData: (data) => set({ jsonData: data }),
11+
}));
12+
13+
export default useCanvasStore;
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { create } from 'zustand';
2+
import { useLivePreview_interface } from '@/interfaces';
3+
4+
export const useLivePreview = create<useLivePreview_interface>((set) => ({
5+
loadingLivePreview: false,
6+
setLoadingLivePreview: (data) => set({ loadingLivePreview: data }),
7+
}));
8+
9+
export default useLivePreview;

‎src/stores/settings/useFileName.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { create } from 'zustand';
2-
import useFileName_interface from '@/interfaces/settings/useFileName_interface';
2+
import { useFileName_interface } from '@/interfaces';
33

44
const useFileName = create<useFileName_interface>((set) => ({
55

0 commit comments

Comments
 (0)
Please sign in to comment.