1156 lines
29 KiB
HTML
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>
|