Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -172,6 +172,21 @@ if __name__ == '__main__':
|
|
172 |
margin-bottom: 1rem;
|
173 |
}
|
174 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
175 |
.user-controls {
|
176 |
display: flex;
|
177 |
justify-content: space-between;
|
@@ -237,19 +252,43 @@ if __name__ == '__main__':
|
|
237 |
}
|
238 |
|
239 |
.card {
|
240 |
-
border: 1px solid #
|
241 |
-
border-radius:
|
242 |
padding: 1rem;
|
243 |
width: 300px;
|
244 |
-
box-shadow:
|
245 |
position: relative;
|
246 |
-
background-color: #
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
247 |
}
|
248 |
|
249 |
.card a {
|
250 |
text-decoration: none;
|
251 |
-
color: #
|
252 |
word-break: break-all;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
}
|
254 |
|
255 |
.like-button {
|
@@ -258,18 +297,40 @@ if __name__ == '__main__':
|
|
258 |
right: 1rem;
|
259 |
border: none;
|
260 |
background: transparent;
|
261 |
-
font-size: 1.
|
262 |
cursor: pointer;
|
263 |
-
transition:
|
|
|
|
|
|
|
|
|
|
|
264 |
}
|
265 |
|
266 |
.like-button.liked {
|
267 |
-
color:
|
|
|
268 |
}
|
269 |
|
270 |
.like-button.not-liked {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
271 |
color: white;
|
272 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
273 |
}
|
274 |
|
275 |
.status-message {
|
@@ -312,6 +373,23 @@ if __name__ == '__main__':
|
|
312 |
margin-top: 1rem;
|
313 |
}
|
314 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
315 |
@media (max-width: 768px) {
|
316 |
.user-controls {
|
317 |
flex-direction: column;
|
@@ -325,6 +403,12 @@ if __name__ == '__main__':
|
|
325 |
.card {
|
326 |
width: 100%;
|
327 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
328 |
}
|
329 |
</style>
|
330 |
</head>
|
@@ -351,12 +435,19 @@ if __name__ == '__main__':
|
|
351 |
</div>
|
352 |
</div>
|
353 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
354 |
<div class="filter-controls">
|
355 |
<label>
|
356 |
-
<input type="checkbox" id="showOnlyLiked" />
|
357 |
-
λ΄κ° μ’μμν URLλ§ λ³΄κΈ°
|
358 |
-
</label>
|
359 |
-
<label style="margin-left: 1rem;">
|
360 |
<input type="text" id="searchInput" placeholder="URL λλ μ λͺ©μΌλ‘ κ²μ" style="width: 250px;" />
|
361 |
</label>
|
362 |
</div>
|
@@ -378,17 +469,23 @@ if __name__ == '__main__':
|
|
378 |
cardsContainer: document.getElementById('cardsContainer'),
|
379 |
loadingIndicator: document.getElementById('loadingIndicator'),
|
380 |
statusMessage: document.getElementById('statusMessage'),
|
381 |
-
showOnlyLiked: document.getElementById('showOnlyLiked'),
|
382 |
searchInput: document.getElementById('searchInput'),
|
383 |
loginSection: document.getElementById('loginSection'),
|
384 |
-
loggedInSection: document.getElementById('loggedInSection')
|
|
|
|
|
|
|
|
|
|
|
385 |
};
|
386 |
|
387 |
// μ ν리μΌμ΄μ
μν
|
388 |
const state = {
|
389 |
username: null,
|
390 |
likedURLs: {},
|
391 |
-
|
|
|
|
|
392 |
};
|
393 |
|
394 |
// λ‘컬 μ€ν λ¦¬μ§ ν€
|
@@ -413,6 +510,15 @@ if __name__ == '__main__':
|
|
413 |
localStorage.setItem(key, JSON.stringify(state.likedURLs));
|
414 |
}
|
415 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
416 |
// λ‘λ© μν νμ ν¨μ
|
417 |
function setLoading(isLoading) {
|
418 |
state.isLoading = isLoading;
|
@@ -451,6 +557,7 @@ if __name__ == '__main__':
|
|
451 |
elements.currentUser.textContent = data.username;
|
452 |
elements.loginSection.style.display = 'none';
|
453 |
elements.loggedInSection.style.display = 'block';
|
|
|
454 |
|
455 |
// λ‘컬 μ€ν 리μ§μμ μ’μμ μ 보 λ‘λ
|
456 |
state.likedURLs = loadLikesFromStorage();
|
@@ -492,6 +599,7 @@ if __name__ == '__main__':
|
|
492 |
elements.currentUser.textContent = state.username;
|
493 |
elements.loginSection.style.display = 'none';
|
494 |
elements.loggedInSection.style.display = 'block';
|
|
|
495 |
|
496 |
showMessage(`${state.username}λμΌλ‘ λ‘κ·ΈμΈλμμ΅λλ€.`);
|
497 |
|
@@ -522,11 +630,13 @@ if __name__ == '__main__':
|
|
522 |
if (data.success) {
|
523 |
state.username = null;
|
524 |
state.likedURLs = {};
|
|
|
525 |
|
526 |
elements.currentUser.textContent = 'λ‘κ·ΈμΈλμ§ μμ';
|
527 |
elements.tokenInput.value = '';
|
528 |
elements.loginSection.style.display = 'block';
|
529 |
elements.loggedInSection.style.display = 'none';
|
|
|
530 |
|
531 |
showMessage('λ‘κ·Έμμλμμ΅λλ€.');
|
532 |
|
@@ -549,27 +659,13 @@ if __name__ == '__main__':
|
|
549 |
const response = await fetch('/api/urls');
|
550 |
const urls = await handleApiResponse(response);
|
551 |
|
552 |
-
|
553 |
-
const showOnlyLiked = elements.showOnlyLiked.checked;
|
554 |
-
const searchText = elements.searchInput.value.toLowerCase();
|
555 |
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
// μ’μμ νν°λ§
|
560 |
-
if (showOnlyLiked && !state.likedURLs[url]) {
|
561 |
-
return false;
|
562 |
-
}
|
563 |
-
|
564 |
-
// κ²μ νν°λ§
|
565 |
-
if (searchText && !url.toLowerCase().includes(searchText) && !title.toLowerCase().includes(searchText)) {
|
566 |
-
return false;
|
567 |
-
}
|
568 |
-
|
569 |
-
return true;
|
570 |
-
});
|
571 |
|
572 |
-
|
|
|
573 |
} catch (error) {
|
574 |
console.error('URL λͺ©λ‘ λ‘λ μ€λ₯:', error);
|
575 |
showMessage(`URL λ‘λ μ€λ₯: ${error.message}`, true);
|
@@ -578,8 +674,32 @@ if __name__ == '__main__':
|
|
578 |
}
|
579 |
}
|
580 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
581 |
// μ’μμ ν κΈ
|
582 |
-
function toggleLike(url,
|
583 |
if (!state.username) {
|
584 |
showMessage('μ’μμλ₯Ό νλ €λ©΄ νκΉ
νμ΄μ€ API ν ν°μΌλ‘ μΈμ¦μ΄ νμν©λλ€.', true);
|
585 |
return;
|
@@ -594,22 +714,33 @@ if __name__ == '__main__':
|
|
594 |
// μν ν κΈ
|
595 |
if (isCurrentlyLiked) {
|
596 |
delete state.likedURLs[url];
|
597 |
-
|
598 |
-
|
|
|
|
|
|
|
|
|
599 |
showMessage('μ’μμλ₯Ό μ·¨μνμ΅λλ€.');
|
600 |
} else {
|
601 |
state.likedURLs[url] = true;
|
602 |
-
|
603 |
-
|
|
|
|
|
|
|
|
|
604 |
showMessage('μ’μμλ₯Ό μΆκ°νμ΅λλ€.');
|
605 |
}
|
606 |
|
607 |
// λ‘컬 μ€ν 리μ§μ μ μ₯
|
608 |
saveLikesToStorage();
|
609 |
|
610 |
-
//
|
611 |
-
|
612 |
-
|
|
|
|
|
|
|
613 |
}
|
614 |
} catch (error) {
|
615 |
console.error('μ’μμ ν κΈ μ€λ₯:', error);
|
@@ -638,10 +769,17 @@ if __name__ == '__main__':
|
|
638 |
|
639 |
// μΉ΄λ μμ±
|
640 |
const card = document.createElement('div');
|
641 |
-
card.className =
|
|
|
|
|
|
|
|
|
|
|
|
|
642 |
|
643 |
// μ λͺ©
|
644 |
const titleEl = document.createElement('h3');
|
|
|
645 |
titleEl.textContent = title;
|
646 |
card.appendChild(titleEl);
|
647 |
|
@@ -656,10 +794,11 @@ if __name__ == '__main__':
|
|
656 |
const likeBtn = document.createElement('button');
|
657 |
likeBtn.className = `like-button ${isLiked ? 'liked' : 'not-liked'}`;
|
658 |
likeBtn.textContent = 'β₯';
|
|
|
659 |
|
660 |
likeBtn.addEventListener('click', function(e) {
|
661 |
e.preventDefault();
|
662 |
-
toggleLike(url,
|
663 |
});
|
664 |
card.appendChild(likeBtn);
|
665 |
|
@@ -668,6 +807,18 @@ if __name__ == '__main__':
|
|
668 |
});
|
669 |
}
|
670 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
671 |
// μ΄λ²€νΈ 리μ€λ μ€μ
|
672 |
elements.loginButton.addEventListener('click', () => {
|
673 |
login(elements.tokenInput.value);
|
@@ -682,14 +833,17 @@ if __name__ == '__main__':
|
|
682 |
}
|
683 |
});
|
684 |
|
685 |
-
//
|
686 |
-
elements.showOnlyLiked.addEventListener('change', loadUrls);
|
687 |
elements.searchInput.addEventListener('input', () => {
|
688 |
-
// μ
λ ₯ μ§μ° μ²λ¦¬ (νμ΄νν λλ§λ€
|
689 |
clearTimeout(state.searchTimeout);
|
690 |
-
state.searchTimeout = setTimeout(
|
691 |
});
|
692 |
|
|
|
|
|
|
|
|
|
693 |
// μ΄κΈ°ν
|
694 |
checkSessionStatus();
|
695 |
</script>
|
|
|
172 |
margin-bottom: 1rem;
|
173 |
}
|
174 |
|
175 |
+
.stats-bar {
|
176 |
+
background-color: #e9f7ef;
|
177 |
+
padding: 1rem;
|
178 |
+
border-radius: 5px;
|
179 |
+
margin-bottom: 1rem;
|
180 |
+
display: flex;
|
181 |
+
justify-content: space-between;
|
182 |
+
align-items: center;
|
183 |
+
}
|
184 |
+
|
185 |
+
.stats-bar .liked-count {
|
186 |
+
font-weight: bold;
|
187 |
+
color: #e74c3c;
|
188 |
+
}
|
189 |
+
|
190 |
.user-controls {
|
191 |
display: flex;
|
192 |
justify-content: space-between;
|
|
|
252 |
}
|
253 |
|
254 |
.card {
|
255 |
+
border: 1px solid #ddd;
|
256 |
+
border-radius: 8px;
|
257 |
padding: 1rem;
|
258 |
width: 300px;
|
259 |
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
260 |
position: relative;
|
261 |
+
background-color: #fff;
|
262 |
+
transition: all 0.3s ease;
|
263 |
+
}
|
264 |
+
|
265 |
+
.card:hover {
|
266 |
+
transform: translateY(-5px);
|
267 |
+
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
|
268 |
+
}
|
269 |
+
|
270 |
+
.card.liked {
|
271 |
+
border-color: #e74c3c;
|
272 |
+
background-color: #fff9f9;
|
273 |
}
|
274 |
|
275 |
.card a {
|
276 |
text-decoration: none;
|
277 |
+
color: #2980b9;
|
278 |
word-break: break-all;
|
279 |
+
display: block;
|
280 |
+
margin-top: 0.5rem;
|
281 |
+
}
|
282 |
+
|
283 |
+
.card a:hover {
|
284 |
+
text-decoration: underline;
|
285 |
+
}
|
286 |
+
|
287 |
+
.card-title {
|
288 |
+
margin-top: 0;
|
289 |
+
color: #333;
|
290 |
+
font-size: 1.2rem;
|
291 |
+
padding-right: 30px; /* μ’μμ λ²νΌ κ³΅κ° ν보 */
|
292 |
}
|
293 |
|
294 |
.like-button {
|
|
|
297 |
right: 1rem;
|
298 |
border: none;
|
299 |
background: transparent;
|
300 |
+
font-size: 1.8rem;
|
301 |
cursor: pointer;
|
302 |
+
transition: all 0.2s;
|
303 |
+
z-index: 2;
|
304 |
+
}
|
305 |
+
|
306 |
+
.like-button:hover {
|
307 |
+
transform: scale(1.2);
|
308 |
}
|
309 |
|
310 |
.like-button.liked {
|
311 |
+
color: #e74c3c;
|
312 |
+
text-shadow: 0 0 5px rgba(231, 76, 60, 0.3);
|
313 |
}
|
314 |
|
315 |
.like-button.not-liked {
|
316 |
+
color: #ccc;
|
317 |
+
}
|
318 |
+
|
319 |
+
.like-label {
|
320 |
+
position: absolute;
|
321 |
+
top: 10px;
|
322 |
+
left: 10px;
|
323 |
+
background-color: #e74c3c;
|
324 |
color: white;
|
325 |
+
padding: 2px 8px;
|
326 |
+
border-radius: 10px;
|
327 |
+
font-size: 0.7rem;
|
328 |
+
font-weight: bold;
|
329 |
+
display: none;
|
330 |
+
}
|
331 |
+
|
332 |
+
.card.liked .like-label {
|
333 |
+
display: block;
|
334 |
}
|
335 |
|
336 |
.status-message {
|
|
|
373 |
margin-top: 1rem;
|
374 |
}
|
375 |
|
376 |
+
.view-toggle {
|
377 |
+
margin-bottom: 1rem;
|
378 |
+
display: flex;
|
379 |
+
gap: 0.5rem;
|
380 |
+
}
|
381 |
+
|
382 |
+
.view-toggle button {
|
383 |
+
background-color: #f8f9fa;
|
384 |
+
color: #333;
|
385 |
+
border: 1px solid #ddd;
|
386 |
+
}
|
387 |
+
|
388 |
+
.view-toggle button.active {
|
389 |
+
background-color: #4CAF50;
|
390 |
+
color: white;
|
391 |
+
}
|
392 |
+
|
393 |
@media (max-width: 768px) {
|
394 |
.user-controls {
|
395 |
flex-direction: column;
|
|
|
403 |
.card {
|
404 |
width: 100%;
|
405 |
}
|
406 |
+
|
407 |
+
.stats-bar {
|
408 |
+
flex-direction: column;
|
409 |
+
gap: 0.5rem;
|
410 |
+
align-items: flex-start;
|
411 |
+
}
|
412 |
}
|
413 |
</style>
|
414 |
</head>
|
|
|
435 |
</div>
|
436 |
</div>
|
437 |
|
438 |
+
<!-- μ’μμ ν΅κ³ λ° νμ ν κΈ -->
|
439 |
+
<div id="statsBar" class="stats-bar" style="display: none;">
|
440 |
+
<div>
|
441 |
+
μ΄ <span id="totalCount">0</span>κ° μ€ <span id="likedCount" class="liked-count">0</span>κ° μ’μμ ν¨
|
442 |
+
</div>
|
443 |
+
<div class="view-toggle">
|
444 |
+
<button id="allViewBtn" class="active">μ 체 보기</button>
|
445 |
+
<button id="likedViewBtn">μ’μμλ§ λ³΄κΈ°</button>
|
446 |
+
</div>
|
447 |
+
</div>
|
448 |
+
|
449 |
<div class="filter-controls">
|
450 |
<label>
|
|
|
|
|
|
|
|
|
451 |
<input type="text" id="searchInput" placeholder="URL λλ μ λͺ©μΌλ‘ κ²μ" style="width: 250px;" />
|
452 |
</label>
|
453 |
</div>
|
|
|
469 |
cardsContainer: document.getElementById('cardsContainer'),
|
470 |
loadingIndicator: document.getElementById('loadingIndicator'),
|
471 |
statusMessage: document.getElementById('statusMessage'),
|
|
|
472 |
searchInput: document.getElementById('searchInput'),
|
473 |
loginSection: document.getElementById('loginSection'),
|
474 |
+
loggedInSection: document.getElementById('loggedInSection'),
|
475 |
+
statsBar: document.getElementById('statsBar'),
|
476 |
+
totalCount: document.getElementById('totalCount'),
|
477 |
+
likedCount: document.getElementById('likedCount'),
|
478 |
+
allViewBtn: document.getElementById('allViewBtn'),
|
479 |
+
likedViewBtn: document.getElementById('likedViewBtn')
|
480 |
};
|
481 |
|
482 |
// μ ν리μΌμ΄μ
μν
|
483 |
const state = {
|
484 |
username: null,
|
485 |
likedURLs: {},
|
486 |
+
allURLs: [],
|
487 |
+
isLoading: false,
|
488 |
+
viewMode: 'all' // 'all' λλ 'liked'
|
489 |
};
|
490 |
|
491 |
// λ‘컬 μ€ν λ¦¬μ§ ν€
|
|
|
510 |
localStorage.setItem(key, JSON.stringify(state.likedURLs));
|
511 |
}
|
512 |
|
513 |
+
// μ’μμ ν΅κ³ μ
λ°μ΄νΈ
|
514 |
+
function updateLikeStats() {
|
515 |
+
const totalCount = state.allURLs.length;
|
516 |
+
const likedCount = Object.keys(state.likedURLs).length;
|
517 |
+
|
518 |
+
elements.totalCount.textContent = totalCount;
|
519 |
+
elements.likedCount.textContent = likedCount;
|
520 |
+
}
|
521 |
+
|
522 |
// λ‘λ© μν νμ ν¨μ
|
523 |
function setLoading(isLoading) {
|
524 |
state.isLoading = isLoading;
|
|
|
557 |
elements.currentUser.textContent = data.username;
|
558 |
elements.loginSection.style.display = 'none';
|
559 |
elements.loggedInSection.style.display = 'block';
|
560 |
+
elements.statsBar.style.display = 'flex';
|
561 |
|
562 |
// λ‘컬 μ€ν 리μ§μμ μ’μμ μ 보 λ‘λ
|
563 |
state.likedURLs = loadLikesFromStorage();
|
|
|
599 |
elements.currentUser.textContent = state.username;
|
600 |
elements.loginSection.style.display = 'none';
|
601 |
elements.loggedInSection.style.display = 'block';
|
602 |
+
elements.statsBar.style.display = 'flex';
|
603 |
|
604 |
showMessage(`${state.username}λμΌλ‘ λ‘κ·ΈμΈλμμ΅λλ€.`);
|
605 |
|
|
|
630 |
if (data.success) {
|
631 |
state.username = null;
|
632 |
state.likedURLs = {};
|
633 |
+
state.allURLs = [];
|
634 |
|
635 |
elements.currentUser.textContent = 'λ‘κ·ΈμΈλμ§ μμ';
|
636 |
elements.tokenInput.value = '';
|
637 |
elements.loginSection.style.display = 'block';
|
638 |
elements.loggedInSection.style.display = 'none';
|
639 |
+
elements.statsBar.style.display = 'none';
|
640 |
|
641 |
showMessage('λ‘κ·Έμμλμμ΅λλ€.');
|
642 |
|
|
|
659 |
const response = await fetch('/api/urls');
|
660 |
const urls = await handleApiResponse(response);
|
661 |
|
662 |
+
state.allURLs = urls;
|
|
|
|
|
663 |
|
664 |
+
// νν°λ§ λ° λ λλ§
|
665 |
+
filterAndRenderCards();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
666 |
|
667 |
+
// μ’μμ ν΅κ³ μ
λ°μ΄νΈ
|
668 |
+
updateLikeStats();
|
669 |
} catch (error) {
|
670 |
console.error('URL λͺ©λ‘ λ‘λ μ€λ₯:', error);
|
671 |
showMessage(`URL λ‘λ μ€λ₯: ${error.message}`, true);
|
|
|
674 |
}
|
675 |
}
|
676 |
|
677 |
+
// νν°λ§ λ° μΉ΄λ λ λλ§
|
678 |
+
function filterAndRenderCards() {
|
679 |
+
const searchText = elements.searchInput.value.toLowerCase();
|
680 |
+
|
681 |
+
// νν°λ§ μ μ©
|
682 |
+
const filteredUrls = state.allURLs.filter(item => {
|
683 |
+
const { url, title } = item;
|
684 |
+
|
685 |
+
// μ’μμ νν°λ§ (μ’μμλ§ λ³΄κΈ° λͺ¨λ)
|
686 |
+
if (state.viewMode === 'liked' && !state.likedURLs[url]) {
|
687 |
+
return false;
|
688 |
+
}
|
689 |
+
|
690 |
+
// κ²μ νν°λ§
|
691 |
+
if (searchText && !url.toLowerCase().includes(searchText) && !title.toLowerCase().includes(searchText)) {
|
692 |
+
return false;
|
693 |
+
}
|
694 |
+
|
695 |
+
return true;
|
696 |
+
});
|
697 |
+
|
698 |
+
renderCards(filteredUrls);
|
699 |
+
}
|
700 |
+
|
701 |
// μ’μμ ν κΈ
|
702 |
+
function toggleLike(url, card) {
|
703 |
if (!state.username) {
|
704 |
showMessage('μ’μμλ₯Ό νλ €λ©΄ νκΉ
νμ΄μ€ API ν ν°μΌλ‘ μΈμ¦μ΄ νμν©λλ€.', true);
|
705 |
return;
|
|
|
714 |
// μν ν κΈ
|
715 |
if (isCurrentlyLiked) {
|
716 |
delete state.likedURLs[url];
|
717 |
+
card.classList.remove('liked');
|
718 |
+
const likeBtn = card.querySelector('.like-button');
|
719 |
+
if (likeBtn) {
|
720 |
+
likeBtn.classList.remove('liked');
|
721 |
+
likeBtn.classList.add('not-liked');
|
722 |
+
}
|
723 |
showMessage('μ’μμλ₯Ό μ·¨μνμ΅λλ€.');
|
724 |
} else {
|
725 |
state.likedURLs[url] = true;
|
726 |
+
card.classList.add('liked');
|
727 |
+
const likeBtn = card.querySelector('.like-button');
|
728 |
+
if (likeBtn) {
|
729 |
+
likeBtn.classList.add('liked');
|
730 |
+
likeBtn.classList.remove('not-liked');
|
731 |
+
}
|
732 |
showMessage('μ’μμλ₯Ό μΆκ°νμ΅λλ€.');
|
733 |
}
|
734 |
|
735 |
// λ‘컬 μ€ν 리μ§μ μ μ₯
|
736 |
saveLikesToStorage();
|
737 |
|
738 |
+
// μ’μμ ν΅κ³ μ
λ°μ΄νΈ
|
739 |
+
updateLikeStats();
|
740 |
+
|
741 |
+
// μ’μμλ§ λ³΄κΈ° λͺ¨λμΈ κ²½μ° λͺ©λ‘ λ€μ λ λλ§
|
742 |
+
if (state.viewMode === 'liked') {
|
743 |
+
filterAndRenderCards();
|
744 |
}
|
745 |
} catch (error) {
|
746 |
console.error('μ’μμ ν κΈ μ€λ₯:', error);
|
|
|
769 |
|
770 |
// μΉ΄λ μμ±
|
771 |
const card = document.createElement('div');
|
772 |
+
card.className = `card ${isLiked ? 'liked' : ''}`;
|
773 |
+
|
774 |
+
// μ’μμ λΌλ²¨
|
775 |
+
const likeLabel = document.createElement('span');
|
776 |
+
likeLabel.className = 'like-label';
|
777 |
+
likeLabel.textContent = 'μ’μμ';
|
778 |
+
card.appendChild(likeLabel);
|
779 |
|
780 |
// μ λͺ©
|
781 |
const titleEl = document.createElement('h3');
|
782 |
+
titleEl.className = 'card-title';
|
783 |
titleEl.textContent = title;
|
784 |
card.appendChild(titleEl);
|
785 |
|
|
|
794 |
const likeBtn = document.createElement('button');
|
795 |
likeBtn.className = `like-button ${isLiked ? 'liked' : 'not-liked'}`;
|
796 |
likeBtn.textContent = 'β₯';
|
797 |
+
likeBtn.title = isLiked ? 'μ’μμ μ·¨μ' : 'μ’μμ';
|
798 |
|
799 |
likeBtn.addEventListener('click', function(e) {
|
800 |
e.preventDefault();
|
801 |
+
toggleLike(url, card);
|
802 |
});
|
803 |
card.appendChild(likeBtn);
|
804 |
|
|
|
807 |
});
|
808 |
}
|
809 |
|
810 |
+
// λͺ¨λ λ³κ²½ ν¨μ
|
811 |
+
function changeViewMode(mode) {
|
812 |
+
state.viewMode = mode;
|
813 |
+
|
814 |
+
// λ²νΌ μν μ
λ°μ΄νΈ
|
815 |
+
elements.allViewBtn.classList.toggle('active', mode === 'all');
|
816 |
+
elements.likedViewBtn.classList.toggle('active', mode === 'liked');
|
817 |
+
|
818 |
+
// μΉ΄λ λ€μ λ λλ§
|
819 |
+
filterAndRenderCards();
|
820 |
+
}
|
821 |
+
|
822 |
// μ΄λ²€νΈ 리μ€λ μ€μ
|
823 |
elements.loginButton.addEventListener('click', () => {
|
824 |
login(elements.tokenInput.value);
|
|
|
833 |
}
|
834 |
});
|
835 |
|
836 |
+
// κ²μ μ΄λ²€νΈ 리μ€λ
|
|
|
837 |
elements.searchInput.addEventListener('input', () => {
|
838 |
+
// μ
λ ₯ μ§μ° μ²λ¦¬ (νμ΄νν λλ§λ€ νν°λ§ λ°©μ§)
|
839 |
clearTimeout(state.searchTimeout);
|
840 |
+
state.searchTimeout = setTimeout(filterAndRenderCards, 300);
|
841 |
});
|
842 |
|
843 |
+
// 보기 λͺ¨λ μ ν λ²νΌ
|
844 |
+
elements.allViewBtn.addEventListener('click', () => changeViewMode('all'));
|
845 |
+
elements.likedViewBtn.addEventListener('click', () => changeViewMode('liked'));
|
846 |
+
|
847 |
// μ΄κΈ°ν
|
848 |
checkSessionStatus();
|
849 |
</script>
|