Files
hotdeal_alarm/index.html
2026-03-07 07:21:14 +09:00

1156 lines
29 KiB
HTML

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>핫딜 알람 - 실시간 핫딜 모아보기</title>
<meta name="description" content="실시간으로 모아보는 핫딜 정보 - 뽐뿌, 클리앙, 딜바다 등 다양한 핫딜 사이트의 정보를 한눈에" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Noto+Sans+KR:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
:root {
--bg-primary: #0f0f1a;
--bg-secondary: #1a1a2e;
--bg-card: #16162a;
--bg-card-hover: #1e1e3a;
--bg-input: #252545;
--text-primary: #ffffff;
--text-secondary: #a0a0b8;
--text-muted: #6b6b8a;
--accent-primary: #6366f1;
--accent-secondary: #8b5cf6;
--accent-gradient: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
--hot-badge-bg: rgba(239, 68, 68, 0.15);
--hot-badge-text: #ef4444;
--board-badge-bg: rgba(99, 102, 241, 0.15);
--board-badge-text: #818cf8;
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 20px rgba(0, 0, 0, 0.4);
--shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.5);
--border-color: rgba(255, 255, 255, 0.08);
--transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
[data-theme="light"] {
--bg-primary: #f8fafc;
--bg-secondary: #ffffff;
--bg-card: #ffffff;
--bg-card-hover: #f1f5f9;
--bg-input: #f1f5f9;
--text-primary: #0f172a;
--text-secondary: #475569;
--text-muted: #94a3b8;
--accent-primary: #4f46e5;
--accent-secondary: #7c3aed;
--hot-badge-bg: rgba(239, 68, 68, 0.1);
--hot-badge-text: #dc2626;
--board-badge-bg: rgba(79, 70, 229, 0.1);
--board-badge-text: #4f46e5;
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.06);
--shadow-md: 0 4px 20px rgba(0, 0, 0, 0.08);
--shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.12);
--border-color: rgba(0, 0, 0, 0.06);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
font-family: 'Inter', 'Noto Sans KR', -apple-system, BlinkMacSystemFont, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
min-height: 100vh;
line-height: 1.6;
transition: var(--transition);
}
/* Background Animation */
.bg-gradient {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 0;
overflow: hidden;
}
.bg-gradient::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: radial-gradient(ellipse at 20% 20%, rgba(99, 102, 241, 0.08) 0%, transparent 50%),
radial-gradient(ellipse at 80% 80%, rgba(139, 92, 246, 0.06) 0%, transparent 50%),
radial-gradient(ellipse at 50% 50%, rgba(99, 102, 241, 0.03) 0%, transparent 70%);
animation: bgFloat 20s ease-in-out infinite;
}
@keyframes bgFloat {
0%, 100% { transform: translate(0, 0) rotate(0deg); }
33% { transform: translate(2%, 2%) rotate(1deg); }
66% { transform: translate(-1%, 1%) rotate(-1deg); }
}
/* Container */
.container {
position: relative;
z-index: 1;
max-width: 800px;
margin: 0 auto;
padding: 24px 20px;
}
/* Header */
.header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 28px;
padding: 8px 0;
}
.header-left {
display: flex;
align-items: center;
gap: 16px;
}
.logo {
width: 52px;
height: 52px;
background: var(--accent-gradient);
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
box-shadow: var(--shadow-md), 0 0 30px rgba(99, 102, 241, 0.3);
animation: logoPulse 2s ease-in-out infinite;
}
@keyframes logoPulse {
0%, 100% { transform: scale(1); box-shadow: var(--shadow-md), 0 0 30px rgba(99, 102, 241, 0.3); }
50% { transform: scale(1.02); box-shadow: var(--shadow-md), 0 0 40px rgba(99, 102, 241, 0.4); }
}
.header-title {
display: flex;
flex-direction: column;
}
.header-title h1 {
font-size: 24px;
font-weight: 800;
letter-spacing: -0.02em;
background: var(--accent-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.header-title span {
font-size: 13px;
color: var(--text-muted);
font-weight: 500;
}
.header-actions {
display: flex;
gap: 8px;
}
.icon-btn {
width: 44px;
height: 44px;
border-radius: 12px;
border: 1px solid var(--border-color);
background: var(--bg-secondary);
color: var(--text-secondary);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
transition: var(--transition);
}
.icon-btn:hover {
background: var(--bg-card-hover);
color: var(--text-primary);
transform: translateY(-2px);
box-shadow: var(--shadow-sm);
}
.icon-btn:active {
transform: translateY(0);
}
/* Search Section */
.search-section {
margin-bottom: 24px;
}
.search-box {
position: relative;
display: flex;
align-items: center;
}
.search-icon {
position: absolute;
left: 18px;
font-size: 18px;
color: var(--text-muted);
pointer-events: none;
}
.search-input {
width: 100%;
padding: 16px 18px 16px 50px;
border-radius: 16px;
border: 1px solid var(--border-color);
background: var(--bg-input);
color: var(--text-primary);
font-size: 15px;
font-family: inherit;
transition: var(--transition);
outline: none;
}
.search-input::placeholder {
color: var(--text-muted);
}
.search-input:focus {
border-color: var(--accent-primary);
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.15);
}
.search-clear {
position: absolute;
right: 18px;
width: 24px;
height: 24px;
border-radius: 50%;
border: none;
background: var(--text-muted);
color: var(--bg-primary);
cursor: pointer;
display: none;
align-items: center;
justify-content: center;
font-size: 12px;
transition: var(--transition);
}
.search-clear:hover {
background: var(--text-secondary);
}
.search-clear.visible {
display: flex;
}
/* Stats Bar */
.stats-bar {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
flex-wrap: wrap;
gap: 12px;
}
.stats-left {
display: flex;
align-items: center;
gap: 12px;
}
.count-badge {
display: inline-flex;
align-items: center;
gap: 8px;
background: var(--bg-secondary);
padding: 10px 16px;
border-radius: 12px;
font-weight: 600;
font-size: 14px;
border: 1px solid var(--border-color);
box-shadow: var(--shadow-sm);
}
.count-badge .number {
color: var(--accent-primary);
font-weight: 700;
}
.live-indicator {
display: flex;
align-items: center;
gap: 6px;
font-size: 13px;
color: var(--text-muted);
}
.live-dot {
width: 8px;
height: 8px;
background: #22c55e;
border-radius: 50%;
animation: livePulse 1.5s ease-in-out infinite;
}
@keyframes livePulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.5; transform: scale(0.8); }
}
.filter-tabs {
display: flex;
gap: 8px;
}
.filter-tab {
padding: 8px 16px;
border-radius: 10px;
border: 1px solid var(--border-color);
background: transparent;
color: var(--text-secondary);
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: var(--transition);
font-family: inherit;
}
.filter-tab:hover {
background: var(--bg-secondary);
color: var(--text-primary);
}
.filter-tab.active {
background: var(--accent-gradient);
color: white;
border-color: transparent;
}
/* Deal Cards */
.deal-list {
display: flex;
flex-direction: column;
gap: 16px;
}
.deal-card {
background: var(--bg-card);
border-radius: 20px;
padding: 20px;
border: 1px solid var(--border-color);
box-shadow: var(--shadow-sm);
transition: var(--transition);
cursor: pointer;
position: relative;
overflow: hidden;
}
.deal-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: var(--accent-gradient);
transform: scaleX(0);
transition: transform 0.3s ease;
}
.deal-card:hover {
background: var(--bg-card-hover);
transform: translateY(-3px);
box-shadow: var(--shadow-lg);
}
.deal-card:hover::before {
transform: scaleX(1);
}
.deal-card.favorite {
border-color: rgba(99, 102, 241, 0.3);
}
.deal-card.hidden {
display: none;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 14px;
}
.badges {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.badge {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 12px;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
transition: var(--transition);
}
.badge-hot {
background: var(--hot-badge-bg);
color: var(--hot-badge-text);
}
.badge-hot::before {
content: '';
width: 6px;
height: 6px;
background: currentColor;
border-radius: 50%;
animation: hotPulse 1s ease-in-out infinite;
}
@keyframes hotPulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
.badge-board {
background: var(--board-badge-bg);
color: var(--board-badge-text);
}
.card-actions {
display: flex;
gap: 8px;
}
.action-btn {
width: 36px;
height: 36px;
border-radius: 10px;
border: 1px solid var(--border-color);
background: transparent;
color: var(--text-muted);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
transition: var(--transition);
}
.action-btn:hover {
background: var(--bg-input);
color: var(--text-primary);
transform: scale(1.05);
}
.action-btn.favorite.active {
background: rgba(239, 68, 68, 0.15);
color: #ef4444;
border-color: rgba(239, 68, 68, 0.3);
}
.card-title {
font-size: 16px;
font-weight: 600;
line-height: 1.6;
color: var(--text-primary);
margin-bottom: 16px;
word-break: keep-all;
}
.card-title .highlight {
background: rgba(99, 102, 241, 0.2);
color: var(--accent-primary);
padding: 0 4px;
border-radius: 4px;
font-weight: 700;
}
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
.card-meta {
display: flex;
align-items: center;
gap: 16px;
font-size: 13px;
color: var(--text-muted);
}
.card-meta span {
display: flex;
align-items: center;
gap: 6px;
}
.card-arrow {
width: 36px;
height: 36px;
border-radius: 10px;
background: var(--accent-gradient);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
transition: var(--transition);
}
.deal-card:hover .card-arrow {
transform: translateX(4px);
}
/* Empty State */
.empty-state {
text-align: center;
padding: 60px 20px;
color: var(--text-muted);
}
.empty-state-icon {
font-size: 64px;
margin-bottom: 20px;
opacity: 0.5;
}
.empty-state h3 {
font-size: 18px;
font-weight: 600;
color: var(--text-secondary);
margin-bottom: 8px;
}
.empty-state p {
font-size: 14px;
}
/* Toast Notification */
.toast-container {
position: fixed;
bottom: 24px;
left: 50%;
transform: translateX(-50%);
z-index: 1000;
display: flex;
flex-direction: column;
gap: 8px;
pointer-events: none;
}
.toast {
background: var(--bg-secondary);
color: var(--text-primary);
padding: 14px 24px;
border-radius: 12px;
font-size: 14px;
font-weight: 500;
box-shadow: var(--shadow-lg);
border: 1px solid var(--border-color);
display: flex;
align-items: center;
gap: 10px;
animation: toastSlideUp 0.3s ease, toastFadeOut 0.3s ease 2.7s forwards;
pointer-events: auto;
}
@keyframes toastSlideUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes toastFadeOut {
to {
opacity: 0;
transform: translateY(-10px);
}
}
/* Loading Skeleton */
.skeleton {
background: linear-gradient(90deg, var(--bg-input) 25%, var(--bg-card-hover) 50%, var(--bg-input) 75%);
background-size: 200% 100%;
animation: skeletonLoading 1.5s infinite;
border-radius: 8px;
}
@keyframes skeletonLoading {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
/* Scroll to Top */
.scroll-top {
position: fixed;
bottom: 24px;
right: 24px;
width: 48px;
height: 48px;
border-radius: 50%;
background: var(--accent-gradient);
color: white;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
box-shadow: var(--shadow-lg);
opacity: 0;
visibility: hidden;
transform: translateY(20px);
transition: var(--transition);
z-index: 100;
}
.scroll-top.visible {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.scroll-top:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(99, 102, 241, 0.4);
}
/* Responsive */
@media (max-width: 640px) {
.container {
padding: 16px;
}
.header {
margin-bottom: 20px;
}
.header-title h1 {
font-size: 20px;
}
.logo {
width: 44px;
height: 44px;
font-size: 20px;
}
.icon-btn {
width: 40px;
height: 40px;
}
.deal-card {
padding: 16px;
border-radius: 16px;
}
.card-title {
font-size: 15px;
}
.stats-bar {
flex-direction: column;
align-items: flex-start;
}
.filter-tabs {
width: 100%;
overflow-x: auto;
padding-bottom: 4px;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
}
.filter-tabs::-webkit-scrollbar {
display: none;
}
.filter-tab {
white-space: nowrap;
}
}
/* Reduced Motion */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
</style>
</head>
<body>
<div class="bg-gradient"></div>
<div class="container">
<!-- Header -->
<header class="header">
<div class="header-left">
<div class="logo">🔔</div>
<div class="header-title">
<h1>핫딜 알람</h1>
<span>실시간 핫딜 모아보기</span>
</div>
</div>
<div class="header-actions">
<button class="icon-btn" id="themeToggle" title="테마 변경">
🌙
</button>
<button class="icon-btn" id="refreshBtn" title="새로고침">
</button>
<button class="icon-btn" id="menuBtn" title="메뉴">
</button>
</div>
</header>
<!-- Search -->
<section class="search-section">
<div class="search-box">
<span class="search-icon">🔍</span>
<input
type="text"
class="search-input"
id="searchInput"
placeholder="제목, 상점, 가격으로 검색..."
autocomplete="off"
/>
<button class="search-clear" id="searchClear"></button>
</div>
</section>
<!-- Stats & Filters -->
<div class="stats-bar">
<div class="stats-left">
<div class="count-badge">
📋 <span class="number" id="dealCount">0</span>개의 핫딜
</div>
<div class="live-indicator">
<span class="live-dot"></span>
실시간 업데이트
</div>
</div>
<div class="filter-tabs">
<button class="filter-tab active" data-filter="all">전체</button>
<button class="filter-tab" data-filter="ppomppu">뽐뿌</button>
<button class="filter-tab" data-filter="clien">클리앙</button>
<button class="filter-tab" data-filter="dealbada">딜바다</button>
<button class="filter-tab" data-filter="favorite">즐겨찾기</button>
</div>
</div>
<!-- Deal List -->
<div class="deal-list" id="dealList"></div>
</div>
<!-- Toast Container -->
<div class="toast-container" id="toastContainer"></div>
<!-- Scroll to Top -->
<button class="scroll-top" id="scrollTop"></button>
<script>
// Deal Data
const dealsData = [
{
id: 1,
title: "[네이버] TCL 85Q6C 4K QD 미니LED 85인치 스마트TV (1,431,540원/묶음배송)",
site: "ppomppu",
siteName: "뽐뿌",
time: "방금 전",
url: "#"
},
{
id: 2,
title: "[SSG] 스노우피크 바람막이 자켓 블랙 (78,053원/묶음배송)",
site: "ppomppu",
siteName: "뽐뿌",
time: "2분 전",
url: "#"
},
{
id: 3,
title: "[옥션] 자연산 반건조 민어 5팩 특가 (19,900원/묶음배송)",
site: "dealbada",
siteName: "딜바다",
time: "5분 전",
url: "#"
},
{
id: 4,
title: "[네이버] 카스 무알코올 맥주 330ml 14캔 (100원/유료배송)",
site: "clien",
siteName: "클리앙",
time: "8분 전",
url: "#"
},
{
id: 5,
title: "[쿠팡] 삼성 갤럭시 버즈2 프로 블루투스 이어폰 (89,000원/로켓배송)",
site: "ppomppu",
siteName: "뽐뿌",
time: "12분 전",
url: "#"
},
{
id: 6,
title: "[11번가] LG 울트라와이드 모니터 34인치 3440x1440 (399,000원/묶음배송)",
site: "clien",
siteName: "클리앙",
time: "15분 전",
url: "#"
},
{
id: 7,
title: "[G마켓] 다이슨 에어랩 컴플리트 스타일러 (499,000원/묶음배송)",
site: "dealbada",
siteName: "딜바다",
time: "18분 전",
url: "#"
},
{
id: 8,
title: "[네이버] 애플 에어팟 프로 2세대 (279,000원/묶음배송)",
site: "ppomppu",
siteName: "뽐뿌",
time: "23분 전",
url: "#"
},
{
id: 9,
title: "[쿠팡] 코멧 물티슈 캡형 100매 10팩 (8,990원/로켓배송)",
site: "clien",
siteName: "클리앙",
time: "25분 전",
url: "#"
},
{
id: 10,
title: "[티몬] 닌텐도 스위치 OLED 모델 화이트 (359,000원/묶음배송)",
site: "dealbada",
siteName: "딜바다",
time: "30분 전",
url: "#"
},
{
id: 11,
title: "[SSG] 노스페이스 화이트라벨 패딩 자켓 (129,000원/묶음배송)",
site: "ppomppu",
siteName: "뽐뿌",
time: "35분 전",
url: "#"
},
{
id: 12,
title: "[옥션] 국내산 한돈 삼겹살 500g x 3팩 (29,900원/묶음배송)",
site: "dealbada",
siteName: "딜바다",
time: "42분 전",
url: "#"
}
];
// State
let favorites = JSON.parse(localStorage.getItem('hotdeal_favorites') || '[]');
let currentFilter = 'all';
let searchQuery = '';
// DOM Elements
const dealList = document.getElementById('dealList');
const searchInput = document.getElementById('searchInput');
const searchClear = document.getElementById('searchClear');
const dealCount = document.getElementById('dealCount');
const themeToggle = document.getElementById('themeToggle');
const refreshBtn = document.getElementById('refreshBtn');
const scrollTop = document.getElementById('scrollTop');
const toastContainer = document.getElementById('toastContainer');
const filterTabs = document.querySelectorAll('.filter-tab');
// Theme Management
const currentTheme = localStorage.getItem('hotdeal_theme') || 'dark';
document.documentElement.setAttribute('data-theme', currentTheme);
updateThemeIcon(currentTheme);
themeToggle.addEventListener('click', () => {
const current = document.documentElement.getAttribute('data-theme');
const next = current === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', next);
localStorage.setItem('hotdeal_theme', next);
updateThemeIcon(next);
showToast(next === 'dark' ? '🌙 다크 모드로 변경되었습니다' : '☀️ 라이트 모드로 변경되었습니다');
});
function updateThemeIcon(theme) {
themeToggle.textContent = theme === 'dark' ? '☀️' : '🌙';
}
// Search Functionality
searchInput.addEventListener('input', (e) => {
searchQuery = e.target.value.trim();
searchClear.classList.toggle('visible', searchQuery.length > 0);
renderDeals();
});
searchClear.addEventListener('click', () => {
searchInput.value = '';
searchQuery = '';
searchClear.classList.remove('visible');
searchInput.focus();
renderDeals();
});
// Filter Tabs
filterTabs.forEach(tab => {
tab.addEventListener('click', () => {
filterTabs.forEach(t => t.classList.remove('active'));
tab.classList.add('active');
currentFilter = tab.dataset.filter;
renderDeals();
});
});
// Render Deals
function renderDeals() {
let filtered = dealsData;
// Apply site filter
if (currentFilter === 'favorite') {
filtered = filtered.filter(d => favorites.includes(d.id));
} else if (currentFilter !== 'all') {
filtered = filtered.filter(d => d.site === currentFilter);
}
// Apply search filter
if (searchQuery) {
filtered = filtered.filter(d =>
d.title.toLowerCase().includes(searchQuery.toLowerCase())
);
}
// Update count
dealCount.textContent = filtered.length;
// Render
if (filtered.length === 0) {
dealList.innerHTML = `
<div class="empty-state">
<div class="empty-state-icon">📭</div>
<h3>검색 결과가 없습니다</h3>
<p>다른 키워드로 검색핳거나 필터를 변경핳세요</p>
</div>
`;
return;
}
dealList.innerHTML = filtered.map(deal => {
const isFavorite = favorites.includes(deal.id);
const highlightedTitle = searchQuery
? deal.title.replace(
new RegExp(`(${escapeRegex(searchQuery)})`, 'gi'),
'<span class="highlight">$1</span>'
)
: deal.title;
return `
<article class="deal-card ${isFavorite ? 'favorite' : ''}" data-id="${deal.id}">
<div class="card-header">
<div class="badges">
<span class="badge badge-hot">HOT</span>
<span class="badge badge-board">${deal.siteName}</span>
</div>
<div class="card-actions">
<button class="action-btn favorite ${isFavorite ? 'active' : ''}" data-id="${deal.id}" title="즐겨찾기">
${isFavorite ? '♥' : '♡'}
</button>
<button class="action-btn share" data-id="${deal.id}" title="공유하기">
🔗
</button>
</div>
</div>
<h2 class="card-title">${highlightedTitle}</h2>
<div class="card-footer">
<div class="card-meta">
<span>🕒 ${deal.time}</span>
</div>
<div class="card-arrow">→</div>
</div>
</article>
`;
}).join('');
// Attach event listeners
document.querySelectorAll('.action-btn.favorite').forEach(btn => {
btn.addEventListener('click', (e) => {
e.stopPropagation();
toggleFavorite(parseInt(btn.dataset.id));
});
});
document.querySelectorAll('.action-btn.share').forEach(btn => {
btn.addEventListener('click', (e) => {
e.stopPropagation();
shareDeal(parseInt(btn.dataset.id));
});
});
document.querySelectorAll('.deal-card').forEach(card => {
card.addEventListener('click', () => {
const id = parseInt(card.dataset.id);
openDeal(id);
});
});
}
function escapeRegex(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
// Favorite Management
function toggleFavorite(id) {
const index = favorites.indexOf(id);
if (index > -1) {
favorites.splice(index, 1);
showToast('♡ 즐겨찾기에서 제거되었습니다');
} else {
favorites.push(id);
showToast('♥ 즐겨찾기에 추가되었습니다');
}
localStorage.setItem('hotdeal_favorites', JSON.stringify(favorites));
renderDeals();
}
// Share Functionality
async function shareDeal(id) {
const deal = dealsData.find(d => d.id === id);
if (!deal) return;
const shareData = {
title: '핫딜 알람',
text: deal.title,
url: window.location.href
};
try {
if (navigator.share) {
await navigator.share(shareData);
} else {
await navigator.clipboard.writeText(`${deal.title}\n${window.location.href}`);
showToast('📋 클립보드에 복사되었습니다');
}
} catch (err) {
console.log('Share failed:', err);
}
}
// Open Deal
function openDeal(id) {
const deal = dealsData.find(d => d.id === id);
if (deal) {
window.open(deal.url, '_blank');
}
}
// Toast Notification
function showToast(message) {
const toast = document.createElement('div');
toast.className = 'toast';
toast.textContent = message;
toastContainer.appendChild(toast);
setTimeout(() => {
toast.remove();
}, 3000);
}
// Refresh
refreshBtn.addEventListener('click', () => {
refreshBtn.style.animation = 'spin 0.5s ease';
setTimeout(() => {
refreshBtn.style.animation = '';
showToast('🔄 목록을 새로고침했습니다');
renderDeals();
}, 500);
});
// Scroll to Top
window.addEventListener('scroll', () => {
if (window.scrollY > 300) {
scrollTop.classList.add('visible');
} else {
scrollTop.classList.remove('visible');
}
});
scrollTop.addEventListener('click', () => {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
// Add spin animation
const style = document.createElement('style');
style.textContent = `
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
`;
document.head.appendChild(style);
// Menu Button
document.getElementById('menuBtn').addEventListener('click', () => {
showToast('📋 메뉴 기능은 준비 중입니다');
});
// Initial Render
renderDeals();
// Simulate real-time updates
setInterval(() => {
const dots = document.querySelectorAll('.live-dot');
dots.forEach(dot => {
dot.style.animation = 'none';
setTimeout(() => {
dot.style.animation = '';
}, 10);
});
}, 5000);
</script>
</body>
</html>