diff --git a/client/package.json b/client/package.json index 08a7785..fbd370a 100644 --- a/client/package.json +++ b/client/package.json @@ -15,7 +15,8 @@ "react-konva": "^18.2.10", "konva": "^9.3.18", "use-image": "^1.1.1", - "@xenova/transformers": "^2.17.2" + "@xenova/transformers": "^2.17.2", + "react-filerobot-image-editor": "^4.8.1" }, "devDependencies": { "@eslint/js": "^9.39.4", diff --git a/client/src/components/editor/PhotoPreEditor.jsx b/client/src/components/editor/PhotoPreEditor.jsx new file mode 100644 index 0000000..7167c41 --- /dev/null +++ b/client/src/components/editor/PhotoPreEditor.jsx @@ -0,0 +1,58 @@ +import { useState } from 'react'; +import FilerobotImageEditor from 'react-filerobot-image-editor'; + +export function PhotoPreEditor({ imageSrc, onComplete, onClose }) { + const [saving, setSaving] = useState(false); + + const handleComplete = (editedImageObject, designState) => { + setSaving(true); + + // Export the edited image + editedImageObject.exportAsync({ + quality: 1, + mimeType: 'image/png', + }).then((blob) => { + const url = URL.createObjectURL(blob); + setSaving(false); + onComplete(url); + }).catch((error) => { + console.error('Export failed:', error); + setSaving(false); + onClose(); + }); + }; + + return ( +
+
+ +
+
+ ); +} diff --git a/client/src/components/editor/index.js b/client/src/components/editor/index.js new file mode 100644 index 0000000..d18f55a --- /dev/null +++ b/client/src/components/editor/index.js @@ -0,0 +1 @@ +export { PhotoPreEditor } from './PhotoPreEditor'; diff --git a/client/src/components/sidebar/UploadTab.jsx b/client/src/components/sidebar/UploadTab.jsx index 51325eb..4dbab0c 100644 --- a/client/src/components/sidebar/UploadTab.jsx +++ b/client/src/components/sidebar/UploadTab.jsx @@ -1,9 +1,11 @@ -import { useRef, useState } from 'react'; +import { useState } from 'react'; +import { PhotoPreEditor } from '../editor/PhotoPreEditor'; export function UploadTab({ onUpload }) { - const fileInputRef = useRef(null); + const fileInputRef = useState(null)[0]; const [isDragging, setIsDragging] = useState(false); const [uploading, setUploading] = useState(false); + const [editingImage, setEditingImage] = useState(null); const handleFile = async (file) => { if (!file || !file.type.startsWith('image/')) return; @@ -20,7 +22,8 @@ export function UploadTab({ onUpload }) { if (response.ok) { const data = await response.json(); - onUpload(data); + // Open photo editor with uploaded image + setEditingImage(data.original.url); } } catch (error) { console.error('Upload failed:', error); @@ -45,6 +48,25 @@ export function UploadTab({ onUpload }) { setIsDragging(false); }; + const handleEditorComplete = (editedImageUrl) => { + onUpload({ preview: { url: editedImageUrl } }); + setEditingImage(null); + }; + + const handleEditorClose = () => { + setEditingImage(null); + }; + + if (editingImage) { + return ( + + ); + } + return (

Upload Image

@@ -53,7 +75,7 @@ export function UploadTab({ onUpload }) { onDrop={handleDrop} onDragOver={handleDragOver} onDragLeave={handleDragLeave} - onClick={() => fileInputRef.current?.click()} + onClick={() => fileInputRef?.click()} > {uploading ? (
@@ -65,6 +87,9 @@ export function UploadTab({ onUpload }) {
📁

Drop image here or click to upload

PNG, JPG, WEBP up to 20MB

+

+ Edit with crop, filters, and effects before adding to design +

)}