1
+ 'use client' ;
2
+
3
+ import React , { useState , useRef } from 'react' ;
4
+ import Canvas from '@/components/Projects/(classifications)/Annotation/Canvas' ;
5
+ import Toolbar from '@/components/Projects/(classifications)/Annotation/Toolbar' ;
6
+ import AnnotationList from '@/components/Projects/(classifications)/Annotation/AnnotationList' ;
7
+ import { Annotation } from '@/types/Annotation' ;
8
+ import { Upload } from 'lucide-react' ;
9
+ import dynamic from 'next/dynamic' ;
10
+
11
+ function AnnotationCreate ( ) {
12
+ const [ imageUrl , setImageUrl ] = useState < string > ( '' ) ;
13
+ const [ currentTool , setCurrentTool ] = useState < string > ( '' ) ;
14
+ const [ isDrawing , setIsDrawing ] = useState ( false ) ;
15
+ const [ annotations , setAnnotations ] = useState < Annotation [ ] > ( [ ] ) ;
16
+ const containerRef = useRef < HTMLDivElement > ( null ) ;
17
+ const canvasRef = useRef < HTMLCanvasElement > ( null ) ;
18
+
19
+ const handleFileUpload = ( event : React . ChangeEvent < HTMLInputElement > ) => {
20
+ const file = event . target . files ?. [ 0 ] ;
21
+ if ( file ) {
22
+ const url = URL . createObjectURL ( file ) ;
23
+ setImageUrl ( url ) ;
24
+ }
25
+ } ;
26
+
27
+ const handleAddAnnotation = ( annotation : Annotation ) => {
28
+ setAnnotations ( [ ...annotations , annotation ] ) ;
29
+ } ;
30
+
31
+ const handleLabelChange = ( index : number , newLabel : string ) => {
32
+ const newAnnotations = [ ...annotations ] ;
33
+ newAnnotations [ index ] . label = newLabel ;
34
+ setAnnotations ( newAnnotations ) ;
35
+ } ;
36
+
37
+ const handleDownload = ( ) => {
38
+ if ( ! canvasRef . current ) return ;
39
+
40
+ const canvas = canvasRef . current ;
41
+ const ctx = canvas . getContext ( '2d' ) ;
42
+ if ( ! ctx ) return ;
43
+
44
+ // Draw the image onto the canvas
45
+ const img = new Image ( ) ;
46
+ img . src = imageUrl ;
47
+ img . onload = ( ) => {
48
+ // Clear the canvas before drawing
49
+ ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
50
+ ctx . drawImage ( img , 0 , 0 ) ;
51
+
52
+ // Now draw the annotations (example, adjust based on how you manage annotations)
53
+ annotations . forEach ( ( annotation ) => {
54
+ const x = annotation . x ?? 0 ;
55
+ const y = annotation . y ?? 0 ;
56
+ const width = annotation . width ?? 0 ;
57
+ const height = annotation . height ?? 0 ;
58
+
59
+ ctx . beginPath ( ) ;
60
+ ctx . rect ( x , y , width , height ) ; // Safe to call now
61
+ ctx . strokeStyle = 'red' ;
62
+ ctx . lineWidth = 2 ;
63
+ ctx . stroke ( ) ;
64
+ ctx . fillStyle = 'red' ;
65
+ ctx . fillText ( annotation . label , x , y - 5 ) ; // Add label with default x and y
66
+ } ) ;
67
+
68
+ // Generate the data URL and trigger download
69
+ const dataUrl = canvas . toDataURL ( 'image/png' ) ;
70
+ const link = document . createElement ( 'a' ) ;
71
+ link . download = 'annotated-image.png' ;
72
+ link . href = dataUrl ;
73
+ link . click ( ) ;
74
+ } ;
75
+ } ;
76
+
77
+ const handleShare = async ( ) => {
78
+ if ( ! canvasRef . current ) return ;
79
+
80
+ const canvas = canvasRef . current ;
81
+ const dataUrl = canvas . toDataURL ( 'image/png' ) ;
82
+ const blob = await ( await fetch ( dataUrl ) ) . blob ( ) ;
83
+ const file = new File ( [ blob ] , 'annotated-image.png' , { type : 'image/png' } ) ;
84
+
85
+ if ( navigator . share ) {
86
+ await navigator . share ( {
87
+ files : [ file ] ,
88
+ title : 'Annotated Image' ,
89
+ } ) ;
90
+ } else {
91
+ alert ( 'Web Share API is not supported in your browser' ) ;
92
+ }
93
+ } ;
94
+
95
+ return (
96
+ < div className = "min-h-screen bg-gray-50 p-8" >
97
+ < div className = "max-w-6xl mx-auto" >
98
+ < h1 className = "text-3xl font-bold text-gray-900 mb-8" > Image Annotator</ h1 >
99
+
100
+ < div className = "flex gap-8" >
101
+ < div className = "flex-1" >
102
+ { ! imageUrl ? (
103
+ < label className = "flex flex-col items-center justify-center w-full h-[600px] border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50" >
104
+ < div className = "flex flex-col items-center justify-center pt-5 pb-6" >
105
+ < Upload className = "w-12 h-12 text-gray-400 mb-4" />
106
+ < p className = "mb-2 text-sm text-gray-500" >
107
+ < span className = "font-semibold" > Click to upload</ span > or drag and drop
108
+ </ p >
109
+ < p className = "text-xs text-gray-500" > PNG, JPG or GIF</ p >
110
+ </ div >
111
+ < input
112
+ type = "file"
113
+ className = "hidden"
114
+ accept = "image/*"
115
+ onChange = { handleFileUpload }
116
+ />
117
+ </ label >
118
+ ) : (
119
+ < div className = "space-y-4" >
120
+ < Toolbar
121
+ currentTool = { currentTool }
122
+ onToolSelect = { setCurrentTool }
123
+ onDownload = { handleDownload }
124
+ onShare = { handleShare }
125
+ />
126
+ < div ref = { containerRef } >
127
+ { /* <Canvas
128
+ imageUrl={imageUrl}
129
+ annotations={annotations}
130
+ currentTool={currentTool}
131
+ isDrawing={isDrawing}
132
+ setIsDrawing={setIsDrawing}
133
+ onAddAnnotation={handleAddAnnotation}
134
+ /> */ }
135
+ </ div >
136
+ { /* Create a hidden canvas to draw the image and annotations */ }
137
+ < canvas ref = { canvasRef } style = { { display : 'none' } } width = { 800 } height = { 600 } />
138
+ </ div >
139
+ ) }
140
+ </ div >
141
+
142
+ < AnnotationList
143
+ annotations = { annotations }
144
+ onLabelChange = { handleLabelChange }
145
+ />
146
+ </ div >
147
+ </ div >
148
+ </ div >
149
+ ) ;
150
+ }
151
+
152
+ export default AnnotationCreate ;
0 commit comments