1+ import React , { useState } from "react" ;
2+ import Container from "react-bootstrap/Container" ;
3+ import Row from "react-bootstrap/Row" ;
4+ import Col from "react-bootstrap/Col" ;
5+ import Modal from "react-bootstrap/Modal" ;
6+ import Button from "react-bootstrap/Button" ;
7+
8+ // Toast
9+ import toast from "react-hot-toast" ;
10+
11+ // harperDb fetch call
12+ import { harperFetch } from "../../utils/HarperFetch" ;
13+
14+ import { ShapeForm , ShapePreview } from ".." ;
15+
16+ const CreateShape = ( props ) => {
17+ const [ shapeInformation , setShapeInformation ] = useState ( {
18+ "name" : "Tilted Square" ,
19+ "formula" : "polygon(10% 10%, 90% 10%, 90% 90%, 10% 80%)" ,
20+ "vertices" : 4 ,
21+ "private" : false ,
22+ "edges" : 4 ,
23+ "notes" : "" ,
24+ "clipPathType" : "polygon" ,
25+ "showShadow" : true ,
26+ "backgroundColor" : "#d61284" ,
27+ "verticeCoordinates" : [
28+ {
29+ "x" : "10%" ,
30+ "y" : "10%" ,
31+ } ,
32+ {
33+ "x" : "90%" ,
34+ "y" : "10%" ,
35+ } ,
36+ {
37+ "x" : "90%" ,
38+ "y" : "90%" ,
39+ } ,
40+ {
41+ "x" : "10%" ,
42+ "y" : "80%" ,
43+ } ,
44+ ]
45+ } ) ;
46+
47+ function handleChange ( event , data , number ) {
48+ const name = event . target . name || event . type ;
49+ const value = event . target . type === "checkbox" ? event . target . checked : event . target . value ;
50+
51+ // console.log(event, data);
52+
53+ if ( name === "name" ) {
54+ setShapeInformation ( {
55+ ...shapeInformation ,
56+ "name" : value ,
57+ } ) ;
58+ } else if ( name === 'private' ) {
59+ setShapeInformation ( {
60+ ...shapeInformation ,
61+ "private" : ! shapeInformation . private ,
62+
63+ } ) ;
64+ } else if ( name === "formula" ) {
65+ const edgeVerticeNumber = shapeInformation . clipPathType === "polygon" ? value . split ( "," ) . length : 0 ;
66+
67+ if ( value === "" ) {
68+ handleFormulaChange ( shapeInformation . clipPathType + "()" , edgeVerticeNumber )
69+ } else if ( value . includes ( "polygon" ) ) {
70+ handleFormulaChange ( value , edgeVerticeNumber , "polygon" ) ;
71+ } else if ( value . includes ( "circle" ) ) {
72+ handleFormulaChange ( value , edgeVerticeNumber , "circle" ) ;
73+ } else if ( value . includes ( "ellipse" ) ) {
74+ handleFormulaChange ( value , edgeVerticeNumber , "ellipse" ) ;
75+ } else {
76+ handleFormulaChange ( value , edgeVerticeNumber ) ;
77+ }
78+ } else if ( name === "mousemove" ) {
79+ const newVerticeCoordinates = addNewVerticeCoordinates ( data . x , data . y , number ) ;
80+ const newFormula = generateNewFormula ( newVerticeCoordinates ) ;
81+
82+ setShapeInformation ( {
83+ ...shapeInformation ,
84+ "verticeCoordinates" : newVerticeCoordinates ,
85+ "formula" : newFormula ,
86+ } ) ;
87+ } else if ( name === "click" && event . target . id === "shapeShadow" ) {
88+ const newVerticeCoordinates = addNewVerticeCoordinates ( event . nativeEvent . offsetX , event . nativeEvent . offsetY , shapeInformation . verticeCoordinates . length ) ;
89+ const newFormula = generateNewFormula ( newVerticeCoordinates ) ;
90+
91+ setShapeInformation ( {
92+ ...shapeInformation ,
93+ "vertices" : shapeInformation . vertices + 1 ,
94+ "edges" : shapeInformation . edges + 1 ,
95+ "verticeCoordinates" : newVerticeCoordinates ,
96+ "formula" : newFormula ,
97+ } ) ;
98+ } else if ( ( event . target . id . includes ( "deleteButton" ) || event . target . localName === "line" ) && number !== undefined ) {
99+
100+ let newVerticeCoordinates = [ ] ;
101+
102+ for ( let i = 0 ; i < shapeInformation . verticeCoordinates . length ; i ++ ) {
103+ if ( i !== number ) {
104+ newVerticeCoordinates . push ( shapeInformation . verticeCoordinates [ i ] ) ;
105+ }
106+ }
107+
108+ const newFormula = generateNewFormula ( newVerticeCoordinates ) ;
109+
110+ setShapeInformation ( {
111+ ...shapeInformation ,
112+ "vertices" : shapeInformation . vertices - 1 ,
113+ "edges" : shapeInformation . edges - 1 ,
114+ "verticeCoordinates" : newVerticeCoordinates ,
115+ "formula" : newFormula ,
116+ } ) ;
117+
118+ } else if ( name === "clipPathType" ) {
119+ handleClipPathChange ( value ) ;
120+ } else {
121+ setShapeInformation ( {
122+ ...shapeInformation ,
123+ [ name ] : value ,
124+ } ) ;
125+ }
126+ }
127+
128+ function addNewVerticeCoordinates ( x , y , number ) {
129+ const xPercentage = Math . round ( ( x / 280.0 ) * 100.0 ) ;
130+ const yPercentage = Math . round ( ( y / 280.0 ) * 100.0 ) ;
131+
132+ let newVerticeCoordinates = shapeInformation . verticeCoordinates ;
133+ newVerticeCoordinates [ number ] = {
134+ "x" : xPercentage + "%" ,
135+ "y" : yPercentage + "%"
136+ }
137+
138+ return newVerticeCoordinates ;
139+ }
140+
141+ function generateNewFormula ( newVerticeCoordinates ) {
142+ let newFormula = shapeInformation . clipPathType + "(" ;
143+
144+ for ( let i = 0 ; i < newVerticeCoordinates . length ; i ++ ) {
145+ let newX = newVerticeCoordinates [ i ] . x ;
146+ let newY = newVerticeCoordinates [ i ] . y ;
147+
148+ i === newVerticeCoordinates . length - 1 ? newFormula = newFormula + newX + " " + newY + ")" : newFormula = newFormula + newX + " " + newY + ", " ;
149+ }
150+
151+ return newFormula ;
152+ }
153+
154+ function handleFormulaChange ( formula , edgeVerticeNumber , clipPathType ) {
155+ let newVerticeCoordinates = [ ] ;
156+
157+ if ( clipPathType === "polygon" ) {
158+ let formulaNumbers = formula . slice ( formula . indexOf ( "(" ) + 1 , formula . indexOf ( ")" ) ) ;
159+ formulaNumbers = formulaNumbers . split ( ", " ) ;
160+ newVerticeCoordinates = formulaNumbers . map ( x => {
161+ let percentageArray = x . split ( " " ) ;
162+ return {
163+ "x" : percentageArray [ 0 ] ,
164+ "y" : percentageArray [ 1 ] ,
165+ }
166+ } ) ;
167+ }
168+
169+ setShapeInformation ( prevState => {
170+ return {
171+ ...prevState ,
172+ "formula" : formula . includes ( "(" ) && formula . includes ( ")" ) ? formula : prevState . formula ,
173+ "clipPathType" : clipPathType === null ? prevState . clipPathType : clipPathType ,
174+ "vertices" : edgeVerticeNumber ,
175+ "edges" : edgeVerticeNumber ,
176+ "verticeCoordinates" : newVerticeCoordinates ,
177+ }
178+ } ) ;
179+ }
180+
181+ function handleClipPathChange ( clipPathType ) {
182+ if ( clipPathType === "polygon" ) {
183+ setShapeInformation ( {
184+ ...shapeInformation ,
185+ "name" : "Tilted Square" ,
186+ "formula" : "polygon(10% 10%, 90% 10%, 90% 90%, 10% 80%)" ,
187+ } ) ;
188+ }
189+
190+ if ( clipPathType === "circle" ) {
191+ setShapeInformation ( {
192+ ...shapeInformation ,
193+ "name" : "Circle" ,
194+ "formula" : "circle(50% at 50% 50%)" ,
195+ } ) ;
196+ }
197+
198+ if ( clipPathType === "ellipse" ) {
199+ setShapeInformation ( {
200+ ...shapeInformation ,
201+ "name" : "Ellipse" ,
202+ "formula" : "ellipse(25% 40% at 50% 50%)" ,
203+ } ) ;
204+ }
205+
206+ setShapeInformation ( prevState => {
207+ return {
208+ ...prevState ,
209+ "clipPathType" : clipPathType ,
210+ "edges" : clipPathType === "polygon" ? 4 : 0 ,
211+ "vertices" : clipPathType === "polygon" ? 4 : 0 ,
212+ "notes" : "" ,
213+ }
214+ } )
215+ }
216+
217+ const [ validated , setValidated ] = useState ( false ) ;
218+
219+ const handleSubmit = async ( event ) => {
220+ event . preventDefault ( ) ;
221+ const form = event . currentTarget ;
222+ if ( form . checkValidity ( ) === false ) {
223+ event . preventDefault ( ) ;
224+ event . stopPropagation ( ) ;
225+ }
226+ setValidated ( true ) ;
227+
228+ console . log ( shapeInformation ) ;
229+
230+ // Create the shape in the DB
231+ const insertShape = await harperFetch ( {
232+ operation : "sql" ,
233+ sql : `INSERT into tryshape.shapes(backgroundColor, createdAt, createdBy, edges, email, formula, likes, name, notes, private, type, vertices)
234+ values('${ shapeInformation . backgroundColor } ', null, '${ props . user . email } ', ${ shapeInformation . edges } , null, '${ shapeInformation . formula } ', 0, '${ shapeInformation . name } ', '${ shapeInformation . notes } ', ${ shapeInformation . private } , '${ shapeInformation . clipPathType } ', ${ shapeInformation . vertices } )` ,
235+ } ) ;
236+
237+ console . log ( insertShape ) ;
238+
239+ // Create the user in the db
240+ if ( insertShape [ 'inserted_hashes' ] . length > 0 ) {
241+ // First check if the user exist
242+ const result = await harperFetch ( {
243+ operation : "sql" ,
244+ sql : `SELECT count(*) from tryshape.users WHERE email='${ props . user . email } '` ,
245+ } ) ;
246+ const count = ( result [ 0 ] [ 'COUNT(*)' ] ) ;
247+ console . log ( { count} ) ;
248+ // If doesn't exist, create in db
249+ if ( count === 0 ) {
250+ const insertUser = await harperFetch ( {
251+ operation : "sql" ,
252+ sql : `INSERT into tryshape.users(email, name, photoURL)
253+ values('${ props . user . email } ', '${ props . user . displayName } ', '${ props . user . photoURL } ')` ,
254+ } ) ;
255+ } else {
256+ console . log ( `The user ${ props . user . email } present in DB` ) ;
257+ }
258+ }
259+ props . handleClose ( ) ;
260+ toast . success ( `Shape ${ shapeInformation . name } created successfully.` ) ;
261+ props . setShapeAction ( {
262+ ...props . shapeAction ,
263+ "action" : "add" ,
264+ "payload" : {
265+ "backgroundColor" : shapeInformation . backgroundColor ,
266+ "createdAt" : null ,
267+ "createdBy" : props . user . email ,
268+ "edges" : shapeInformation . edges ,
269+ "email" : null ,
270+ "email1" : props . user . email ,
271+ "formula" : shapeInformation . formula ,
272+ "likes" : 0 ,
273+ "name" : shapeInformation . name ,
274+ "name1" : props . user . displayName ,
275+ "notes" : shapeInformation . notes ,
276+ "photoURL" : props . user . photoURL ,
277+ "private" : shapeInformation . private ,
278+ "type" : shapeInformation . clipPathType
279+ }
280+ } ) ;
281+ }
282+
283+ return (
284+ < >
285+ < Modal
286+ show = { props . show }
287+ centered
288+ size = "lg"
289+ onHide = { props . handleClose }
290+ backdrop = "static"
291+ >
292+ < Modal . Header closeButton >
293+ < Modal . Title > Create a Shape</ Modal . Title >
294+ </ Modal . Header >
295+ < Modal . Body >
296+ < Container fluid >
297+ < Row lg = { 2 } md = { 1 } sm = { 1 } xs = { 1 } >
298+ < Col >
299+ < ShapeForm
300+ shapeInformation = { shapeInformation }
301+ handleChange = { handleChange }
302+ handleSubmit = { handleSubmit }
303+ validated = { validated }
304+ />
305+ </ Col >
306+ < Col >
307+ < ShapePreview
308+ shapeInformation = { shapeInformation }
309+ handleChange = { handleChange }
310+ />
311+ </ Col >
312+ </ Row >
313+ </ Container >
314+ </ Modal . Body >
315+ < Modal . Footer >
316+ < Button onClick = { ( ) => props . handleClose ( ) } variant = "outline-info" >
317+ Close
318+ </ Button >
319+ < Button variant = "secondary" type = "submit" form = "createShapeForm" >
320+ Save
321+ </ Button >
322+ </ Modal . Footer >
323+ </ Modal >
324+ </ >
325+ ) ;
326+ }
327+
328+ export default CreateShape ;
0 commit comments