@@ -49,6 +49,10 @@ To understand why these discussions are vital, explore these insightful pieces o
4949 </div >
5050 <div >
5151 <a class =" talk-title-link " href =" {{ paper.url }} " >Details <i class =" bi bi-box-arrow-up-right " ></i ></a >
52+ <span class =" like-widget " data-paper-id =" {{ paper.title | slugify }} " >
53+ <button class =" like-button " ><i class =" bi bi-heart " ></i ></button >
54+ <span class =" likes-count " >0</span >
55+ </span >
5256 </div >
5357 <details >
5458 <summary >Abstract</summary >
@@ -210,6 +214,106 @@ document.addEventListener('DOMContentLoaded', function() {
210214 }
211215
212216 searchInput .addEventListener (' input' , filterPapers);
217+
218+ // --- Like functionality ---
219+
220+ const API_GATEWAY_URL = ' https://your-api-gateway-url.execute-api.us-east-1.amazonaws.com/prod' ; // Placeholder
221+ const WEBSOCKET_URL = ' wss://your-websocket-url.execute-api.us-east-1.amazonaws.com/prod' ; // Placeholder
222+
223+ function getLikedPapers () {
224+ return JSON .parse (localStorage .getItem (' likedPapers' ) || ' {}' );
225+ }
226+
227+ function isPaperLiked (paperId ) {
228+ return !! getLikedPapers ()[paperId];
229+ }
230+
231+ function setPaperLiked (paperId ) {
232+ const likedPapers = getLikedPapers ();
233+ likedPapers[paperId] = true ;
234+ localStorage .setItem (' likedPapers' , JSON .stringify (likedPapers));
235+ }
236+
237+ async function fetchLikes (paperId ) {
238+ // MOCK: In a real implementation, this would fetch from the backend.
239+ // const response = await fetch(`${API_GATEWAY_URL}/papers/${paperId}/likes`);
240+ // const data = await response.json();
241+ // return data.likes;
242+ return 0 ;
243+ }
244+
245+ async function postLike (paperId ) {
246+ // MOCK: In a real implementation, this would post to the backend.
247+ // const response = await fetch(`${API_GATEWAY_URL}/papers/${paperId}/like`, { method: 'POST' });
248+ // const data = await response.json();
249+ // return data.likes;
250+ const countEl = document .querySelector (` .like-widget[data-paper-id="${ paperId} "] .likes-count` );
251+ const currentLikes = parseInt (countEl .textContent , 10 );
252+ return currentLikes + 1 ;
253+ }
254+
255+ function updateLikeButtonUI (button , paperId ) {
256+ const icon = button .querySelector (' i' );
257+ if (isPaperLiked (paperId)) {
258+ button .classList .add (' liked' );
259+ icon .className = ' bi bi-heart-fill' ;
260+ } else {
261+ button .classList .remove (' liked' );
262+ icon .className = ' bi bi-heart' ;
263+ }
264+ }
265+
266+ document .querySelectorAll (' .like-widget' ).forEach (async (widget ) => {
267+ const paperId = widget .dataset .paperId ;
268+ const button = widget .querySelector (' .like-button' );
269+ const countEl = widget .querySelector (' .likes-count' );
270+
271+ const initialLikes = await fetchLikes (paperId);
272+ countEl .textContent = initialLikes;
273+
274+ updateLikeButtonUI (button, paperId);
275+
276+ button .addEventListener (' click' , async () => {
277+ if (isPaperLiked (paperId)) {
278+ console .log (' Already liked:' , paperId);
279+ return ;
280+ }
281+
282+ const newLikes = await postLike (paperId);
283+ countEl .textContent = newLikes;
284+ setPaperLiked (paperId);
285+ updateLikeButtonUI (button, paperId);
286+ });
287+ });
288+
289+ // Mock WebSocket for real-time updates
290+ function connectWebSocket () {
291+ // In a real implementation, you would connect to your WebSocket endpoint:
292+ // const socket = new WebSocket(WEBSOCKET_URL);
293+ // socket.onmessage = function(event) {
294+ // const data = JSON.parse(event.data);
295+ // if (data.paperId && data.likes) {
296+ // const countEl = document.querySelector(`.like-widget[data-paper-id="${data.paperId}"] .likes-count`);
297+ // if (countEl) {
298+ // countEl.textContent = data.likes;
299+ // }
300+ // }
301+ // };
302+
303+ // This is a mock to simulate another user liking a paper every few seconds
304+ setInterval (() => {
305+ const allWidgets = Array .from (document .querySelectorAll (' .like-widget' ));
306+ if (allWidgets .length === 0 ) return ;
307+
308+ const randomWidget = allWidgets[Math .floor (Math .random () * allWidgets .length )];
309+ const countEl = randomWidget .querySelector (' .likes-count' );
310+
311+ const currentLikes = parseInt (countEl .textContent , 10 );
312+ countEl .textContent = currentLikes + 1 ;
313+ }, 5000 );
314+ }
315+
316+ connectWebSocket ();
213317});
214318</script >
215319
@@ -221,8 +325,33 @@ document.addEventListener('DOMContentLoaded', function() {
221325 padding : 10px ;
222326 border-radius : 4px ;
223327}
328+ .like-widget {
329+ display : inline-flex ;
330+ align-items : center ;
331+ margin-left : 1em ;
332+ color : #dc3545 ;
333+ }
334+ .like-button {
335+ border : none ;
336+ background : transparent ;
337+ cursor : pointer ;
338+ color : inherit ;
339+ padding : 0 5px 0 0 ;
340+ font-size : 1.1em ;
341+ }
342+ .like-button .bi-heart-fill {
343+ display : none ;
344+ }
345+ .like-button.liked .bi-heart {
346+ display : none ;
347+ }
348+ .like-button.liked .bi-heart-fill {
349+ display : inline-block ;
350+ }
224351.likes-count {
225- margin-left : 10px ;
352+ margin-left : 0.25em ;
353+ min-width : 1em ;
354+ text-align : left ;
226355}
227356#paper-search-home {
228357 width : 100% ;
0 commit comments