Skip to content

Commit 81e6df8

Browse files
authored
Merge pull request #24 from TryShape/implement-like-functionality
feat: Implemented basic likes functionality
2 parents 94d7d59 + eb9180c commit 81e6df8

2 files changed

Lines changed: 144 additions & 11 deletions

File tree

components/core/App.js

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,37 +25,63 @@ const App = (props) => {
2525
let shapes = [];
2626

2727
if(user.length === 0) {
28-
// User is not logged In
28+
// User is not logged In. Fetch all the public shapes
2929
shapes = await harperFetch({
3030
operation: "sql",
3131
sql: `SELECT *
3232
FROM tryshape.shapes s
3333
INNER JOIN tryshape.users u
3434
ON s.createdBy=u.email
35-
WHERE s.private=false`,
35+
WHERE s.private=false
36+
ORDER BY s.likes DESC`,
3637
});
3738
} else {
38-
// User is logged in. Let's fetch the private shape and pther public shapes.
39+
// User is logged in. Let's fetch the private shape and other public shapes.
3940
shapes = await harperFetch({
4041
operation: "sql",
4142
sql: `SELECT *
4243
FROM tryshape.shapes s
4344
INNER JOIN tryshape.users u
4445
ON s.createdBy=u.email
4546
WHERE s.private=false
46-
OR createdBy = '${user.email}'`,
47+
OR createdBy = '${user.email}'
48+
ORDER BY s.likes DESC`,
4749
});
50+
51+
// Fetch the shapes liked by the logged-in user
52+
const likedShapes = await harperFetch({
53+
operation: "sql",
54+
sql: `SELECT *
55+
FROM tryshape.likes
56+
WHERE email = '${user.email}'`,
57+
});
58+
59+
// If there are liked shapes, take out the shape_id
60+
if (likedShapes.length > 0) {
61+
let likedShapeIds = likedShapes.map((liked, index) => {
62+
return liked['shape_id'];
63+
})
64+
shapes.map((shape, index) => {
65+
66+
if (likedShapeIds.includes(shape['shape_id'])) {
67+
shape['liked'] = true;
68+
} else {
69+
shape['liked'] = false;
70+
}
71+
return shape;
72+
});
73+
}
4874
}
4975

50-
console.log(shapes);
51-
let modifiedShapes = shapes.map((shape, index) => {
76+
// Add the showAdvanced property
77+
shapes.map((shape, index) => {
5278
shape.showAdvanced = false;
5379
return shape;
5480
});
5581

56-
console.log(modifiedShapes);
82+
console.log(shapes);
5783

58-
await setData(modifiedShapes);
84+
await setData(shapes);
5985
setLoading(false);
6086
}, [user]);
6187

components/utils/ShapeList.js

Lines changed: 110 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import styled from "styled-components";
66
// dynamic from Next.js
77
import dynamic from "next/dynamic";
88

9+
// harperDb fetch call
10+
import { harperFetch } from "../../utils/HarperFetch";
11+
912
// Toast
1013
import toast from "react-hot-toast";
1114

@@ -16,8 +19,9 @@ const Shape = dynamic(import("react-clip-path"), { ssr: false });
1619
import Switch from "react-switch";
1720

1821
// icons
19-
import { FiCopy, FiDownload, FiHeart, FiLock } from 'react-icons/fi';
22+
import { FiCopy, FiDownload, FiLock } from 'react-icons/fi';
2023
import { BiExport } from "react-icons/bi";
24+
import { BsFillHeartFill, BsHeart} from "react-icons/bs";
2125

2226
// Export Shape
2327
import { ExportShape } from '..';
@@ -97,8 +101,17 @@ const ExportIcon = styled(BiExport)`
97101
}
98102
`;
99103

100-
const LikeIcon = styled(FiHeart)`
104+
const LikeIcon = styled(BsHeart)`
105+
cursor: pointer;
106+
color: red;
107+
&:hover {
108+
color: #f71b6f;
109+
}
110+
`;
111+
112+
const LikeFilledIcon = styled(BsFillHeartFill)`
101113
cursor: pointer;
114+
color: red;
102115
&:hover {
103116
color: #f71b6f;
104117
}
@@ -124,6 +137,9 @@ const ShapeList = ({ setOpen, user, data }) => {
124137
setShapes(...[modifiedShapes]);
125138
};
126139

140+
/**
141+
* Copy the clip-path value to clipboard
142+
*/
127143
async function performCopy(event, formula) {
128144
event.preventDefault();
129145
try {
@@ -135,15 +151,96 @@ const ShapeList = ({ setOpen, user, data }) => {
135151
}
136152
}
137153

154+
/**
155+
* Method to execute when user clicks on the export shape
156+
*/
138157
const performExport = shape => {
158+
// Check if user logged-in
139159
if (user.length === 0) {
160+
// Show the login modal if user is not authenticated
140161
setOpen(true);
141162
} else {
163+
// Set the shape details to export
142164
setShapeToExport(shape);
165+
// Show the export modal
143166
setShowExportModal(true);
144167
}
145168
}
146169

170+
/**
171+
* Method to execute when user clicks on the likes
172+
*/
173+
const performLike = async (event, shapeId) => {
174+
// Check if user logged-in
175+
if (user.length === 0) {
176+
// Show the login modal if user is not authenticated
177+
setOpen(true);
178+
} else {
179+
// Good to go. Initialize likes
180+
let likes = 0;
181+
182+
// Check if already an entry for this user's like
183+
// for the shape present.
184+
const isPresent = await harperFetch({
185+
operation: "sql",
186+
sql: `SELECT *
187+
FROM tryshape.likes
188+
WHERE shape_id='${shapeId}' AND email='${user.email}'`,
189+
});
190+
// Get the latest likes count from db
191+
const returnValue = await harperFetch({
192+
operation: "sql",
193+
sql: `SELECT s.likes
194+
FROM tryshape.shapes s
195+
WHERE s.shape_id='${shapeId}'`,
196+
});
197+
198+
if (isPresent.length === 0) {
199+
// If not present, add for like
200+
const insertLike = await harperFetch({
201+
operation: "sql",
202+
sql: `INSERT into tryshape.likes(shape_id, email)
203+
values('${shapeId}', '${user.email}')`,
204+
});
205+
206+
if (insertLike) {
207+
// Update the count by 1
208+
likes = returnValue[0].likes + 1;
209+
}
210+
} else {
211+
// If present, delete to remove like
212+
const deleteLike = await harperFetch({
213+
operation: "sql",
214+
sql: `DELETE from tryshape.likes
215+
WHERE shape_id='${shapeId}' AND email='${user.email}'`,
216+
});
217+
if (deleteLike) {
218+
// update the like count decrease by 1
219+
likes = returnValue[0].likes - 1;
220+
}
221+
}
222+
223+
// Update the shape data with the updated count
224+
const updated = await harperFetch({
225+
operation: "sql",
226+
sql: `UPDATE tryshape.shapes SET likes = ${likes} WHERE shape_id='${shapeId}'`
227+
});
228+
229+
// Update the shape data in the shapes array
230+
let modifiedShapes = shapes.map((shape, index) => {
231+
if (shape['shape_id'] === shapeId) {
232+
return {
233+
...shape,
234+
liked: !shape.liked,
235+
likes: likes
236+
};
237+
}
238+
return shape;
239+
});
240+
setShapes(...[modifiedShapes]);
241+
}
242+
};
243+
147244
return (
148245
<ShapePallete>
149246
<ShapeCards>
@@ -161,7 +258,17 @@ const ShapeList = ({ setOpen, user, data }) => {
161258
{shape.private && <FiLock />}
162259
<ShapeActions>
163260
<span title="Like">
164-
<LikeIcon size={24} />
261+
{
262+
shape.liked ?
263+
(<LikeFilledIcon
264+
size={24}
265+
onClick={(event, shapeId) => performLike(event, shape['shape_id'])}/>)
266+
:
267+
(<LikeIcon
268+
size={24}
269+
onClick={(event, shapeId) => performLike(event, shape['shape_id'])}/>)
270+
}
271+
{shape.likes}
165272
</span>{" "}
166273
<span title="Export">
167274
<ExportIcon

0 commit comments

Comments
 (0)