⚠️ Để áp dụng những ưu đãi hấp dẫn cho tất cả các bài đăng, bạn cần nhấp vào liên kết và đăng nhập hoặc nhận một phiếu giảm giá.
컴퓨터 본체나 화장대 주변 벽에 걸어 쓰면
번잡스럼 없이 사용도 할 수 있습니다.
무드등 온오프 되고 4단계 바람조절도 되네여
28,900원 에서 오픈딜 쿠폰 받고 적립금 받으면
실체감가 17845원 나옵니다.
💬 댓글 0개
더보기
0/1000
취소
댓글 작성
등록일: 2026-04-30 22:04
신고하기
×
.hdz-report-root .report-message {
margin-top: 12px;
padding: 9px 10px;
border-radius: 6px;
font-size: 12px;
border: 1px solid var(–border-light);
background: var(–hover-bg);
color: var(–text-primary);
}
.hdz-report-root .report-message.success {
border-color: rgba(40, 167, 69, 0.3);
background: rgba(40, 167, 69, 0.08);
color: #28a745;
}
.hdz-report-root .report-message.error {
border-color: rgba(255, 68, 68, 0.3);
background: rgba(255, 68, 68, 0.06);
color: #ff4444;
}
.hdz-report-root .report-hp {
position: absolute;
left: -9999px;
top: -9999px;
width: 1px;
height: 1px;
overflow: hidden;
}
.hdz-report-root .report-panel {
margin-top: 14px;
border: 1px solid var(–border-light);
border-radius: 8px;
background: var(–surface-color);
padding: 14px;
}
.hdz-report-root .deal-title {
overflow-wrap: anywhere;
word-break: break-word;
margin-bottom: 10px;
}
.hdz-report-root .deal-meta span {
max-width: 100%;
overflow-wrap: anywhere;
word-break: break-word;
line-height: 1.35;
}
.hdz-report-root .report-form-grid {
display: grid;
grid-template-columns: 1fr;
gap: 12px;
}
.hdz-report-root .comment-form label {
display: block;
font-size: 12px;
color: var(–text-secondary);
margin-bottom: 6px;
}
.hdz-report-root .comment-form select,
.hdz-report-root .comment-form textarea {
width: 100%;
padding: 9px 10px;
border: 1px solid var(–border-light);
border-radius: 6px;
font-size: 12px;
background: var(–surface-color);
color: var(–text-primary);
transition: all 0.2s ease;
font-family: inherit;
}
.hdz-report-root .comment-form textarea {
resize: vertical;
min-height: 110px;
line-height: 1.4;
}
.hdz-report-root .comment-form select:focus,
.hdz-report-root .comment-form textarea:focus {
outline: none;
border-color: var(–accent-color);
box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.10);
}
.hdz-report-root .hint {
margin-top: 5px;
font-size: 11px;
color: var(–text-secondary);
}
.hdz-report-root .report-actions {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
margin-top: 4px;
}
.hdz-report-root .report-submit {
border: none;
border-radius: 6px;
background: var(–accent-color);
color: #fff;
padding: 8px 14px;
font-size: 12px;
font-weight: 600;
cursor: pointer;
}
.hdz-report-root .report-submit:hover {
background: var(–accent-hover);
}
@media (min-width: 720px) {
.hdz-report-root .report-form-grid {
grid-template-columns: 1fr 1fr;
}
.hdz-report-root .report-form-grid .full {
grid-column: 1 / -1;
}
}
@media (max-width: 768px) {
.hdz-report-root .deal-title {
font-size: 16px;
}
.hdz-report-root .report-panel {
padding: 12px;
}
}
🚨 신고하기
📦 화장실 벽걸이 탁상용 화장대 무선 선풍기 (충전선+벽걸이 후크)
웹사이트
신고 항목
선택해주세요
가격 정보가 이상해요
구매 링크가 이상해요
중복/스팸 게시물 같아요
불법/유해/위험한 내용이에요
기타 (직접 입력)
기타를 선택하면 신고 내용을 꼭 입력해주세요.
신고 내용
최대 2000자
기타 항목은 신고 내용을 꼭 입력해주세요
신고 보내기
(function () {
const reason = document.getElementById(
‘report-in-view-reason’
);
const details = document.getElementById(
‘report-in-view-details’
);
if (!reason || !details) {
return;
}
function sync() {
const isOther = reason.value === ‘other’;
details.required = isOther;
details.placeholder = isOther
? ‘기타 사유를 자세히 입력해주세요.’
: ‘상세 내용은 선택 입력입니다.’;
}
reason.addEventListener(‘change’, sync);
sync();
})();
// PHP 데이터를 JavaScript로 전달
window.viewPageData = {
currentProduct: {
id: 134727,
seo_url: ‘화장실-벽걸이-탁상용-화장대-무선-선풍기-충전선-벽걸이-후크-113a’,
title: ‘화장실 벽걸이 탁상용 화장대 무선 선풍기 (충전선+벽걸이 후크)’,
price: ‘18,900원’,
site: ‘네이버’,
category: ‘가전’,
thumbnail: ”,
url: ‘https://hotdeal.zip/화장실-벽걸이-탁상용-화장대-무선-선풍기-충전선-벽걸이-후크-113a’,
post_url: ‘https://hotdealzip.mycafe24.com/ppomppu_view.php?url=view.php%3Fid%3Dppomppu%26page%3D1%26divpage%3D111%26no%3D700605’
},
shareData: {
url: ‘https://hotdeal.zip/화장실-벽걸이-탁상용-화장대-무선-선풍기-충전선-벽걸이-후크-113a’,
title: ‘화장실 벽걸이 탁상용 화장대 무선 선풍기 (충전선+벽걸이 후크)’,
description: ‘네이버에서 판매중인 화장실 벽걸이 탁상용 화장대 무선 선풍기 (충전선+벽걸이 후크) 핫딜 정보’,
image: ‘https://hotdeal.zip/images/product-default-og.jpg’
},
comments: {
dealId: 134727,
currentPage: 1,
hasMore: true
}
};
function openReportModal(event) {
if (event) {
event.preventDefault();
}
const modal = document.getElementById(‘reportModal’);
if (!modal) {
return false;
}
modal.classList.add(‘is-open’);
modal.setAttribute(‘aria-hidden’, ‘false’);
document.body.classList.add(‘report-modal-open’);
return false;
}
function closeReportModal() {
const modal = document.getElementById(‘reportModal’);
if (!modal) {
return;
}
modal.classList.remove(‘is-open’);
modal.setAttribute(‘aria-hidden’, ‘true’);
document.body.classList.remove(‘report-modal-open’);
}
document.addEventListener(‘DOMContentLoaded’, function() {
const modal = document.getElementById(‘reportModal’);
if (!modal) {
return;
}
modal.addEventListener(‘click’, function(event) {
if (event.target === modal) {
closeReportModal();
}
});
document.addEventListener(‘keydown’, function(event) {
if (event.key === ‘Escape’ && modal.classList.contains(‘is-open’)) {
closeReportModal();
}
});
const shouldOpenModal = false;
if (shouldOpenModal) {
openReportModal();
}
});
function handleBackButton(event) {
event.preventDefault();
// 히스토리 길이 체크 (1이면 첫 페이지)
const hasHistory = window.history.length > 1;
// 이전 페이지가 자신의 사이트인지 체크
const referrer = document.referrer;
const currentDomain = window.location.hostname;
const isFromOwnSite = referrer && referrer.includes(currentDomain);
console.log(‘뒤로가기 체크:’, {
히스토리길이: window.history.length,
이전페이지: referrer,
자신의사이트: isFromOwnSite
});
// 자신의 사이트에서 왔고 히스토리가 있으면 뒤로가기
if (hasHistory && isFromOwnSite) {
console.log(‘✅ 히스토리 뒤로가기’);
window.history.back();
} else {
// 다이렉트 접속이거나 외부 사이트에서 온 경우 메인으로
console.log(‘🏠 메인으로 이동 (다이렉트 접속 또는 외부 유입)’);
window.location.href = ‘/’;
}
}
document.addEventListener(‘DOMContentLoaded’, function() {
// 댓글 관련 변수
let currentPage = 1;
let hasMoreComments = true;
let isReplyMode = false;
// DOM 요소들
const commentForm = document.getElementById(‘commentForm’);
const commentsList = document.getElementById(‘comments-list’);
const loadMoreBtn = document.getElementById(‘load-more-comments’);
const loadMoreSection = document.getElementById(‘load-more-section’);
const charCounter = document.getElementById(‘char-counter’);
const commentContent = document.getElementById(‘comment_content’);
const cancelReplyBtn = document.getElementById(‘cancel-reply’);
const commentCount = document.getElementById(‘comment-count’);
const authorNameInput = document.getElementById(‘author_name’);
// 익명 닉네임 생성 및 관리
function getOrCreateAnonymousName() {
let anonymousName = localStorage.getItem(‘hotdeal_anonymous_name’);
if (!anonymousName) {
// 고유한 익명 닉네임 생성
const randomId = Math.random().toString(36).substr(2, 6).toUpperCase();
anonymousName = ‘익명_’ + randomId;
localStorage.setItem(‘hotdeal_anonymous_name’, anonymousName);
}
return anonymousName;
}
// 닉네임 입력 필드 초기화
function initializeNickname() {
const anonymousName = getOrCreateAnonymousName();
const savedNickname = localStorage.getItem(‘hotdeal_user_nickname’);
// 사용자가 설정한 닉네임이 있으면 사용, 없으면 익명 닉네임 사용
if (savedNickname && savedNickname !== anonymousName) {
authorNameInput.value = savedNickname;
authorNameInput.setAttribute(‘data-is-default’, ‘false’);
} else {
authorNameInput.value = anonymousName;
authorNameInput.setAttribute(‘data-is-default’, ‘true’);
}
// 사용자가 닉네임을 수정하면 기본값이 아님을 표시하고 저장
authorNameInput.addEventListener(‘input’, function() {
const currentValue = this.value.trim();
if (currentValue && currentValue !== anonymousName) {
this.setAttribute(‘data-is-default’, ‘false’);
localStorage.setItem(‘hotdeal_user_nickname’, currentValue);
} else if (currentValue === anonymousName) {
this.setAttribute(‘data-is-default’, ‘true’);
localStorage.removeItem(‘hotdeal_user_nickname’);
}
});
// 포커스 시 기본값이면 선택
authorNameInput.addEventListener(‘focus’, function() {
if (this.getAttribute(‘data-is-default’) === ‘true’) {
this.select();
}
});
// 빈 값으로 변경하려고 할 때 익명 닉네임으로 되돌리기
authorNameInput.addEventListener(‘blur’, function() {
if (!this.value.trim()) {
this.value = anonymousName;
this.setAttribute(‘data-is-default’, ‘true’);
localStorage.removeItem(‘hotdeal_user_nickname’);
}
});
}
// 닉네임 초기화 실행
initializeNickname();
// 문자 수 카운터
commentContent.addEventListener(‘input’, function() {
const count = this.value.length;
charCounter.textContent = count;
if (count > 1000) {
charCounter.style.color = ‘#ff4444’;
} else {
charCounter.style.color = ‘#666’;
}
});
// 댓글 로드
function loadComments(page = 1, append = false) {
console.log(‘댓글 로드 시작:’, { deal_id: window.viewPageData.comments.dealId, page: page });
fetch(`/api/comments.php?deal_id=${window.viewPageData.comments.dealId}&page=${page}`)
.then(response => {
console.log(‘응답 상태:’, response.status);
return response.json();
})
.then(data => {
console.log(‘응답 데이터:’, data);
if (data.success) {
if (!append) {
commentsList.innerHTML = ”;
}
if (data.comments.length > 0) {
data.comments.forEach(comment => {
commentsList.appendChild(createCommentElement(comment));
});
} else if (!append) {
// 댓글이 없을 때 메시지 표시
commentsList.innerHTML = ‘아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!’;
}
// 더보기 버튼 표시/숨김
hasMoreComments = data.hasMore;
if (hasMoreComments && data.comments.length > 0) {
loadMoreSection.style.display = ‘block’;
} else {
loadMoreSection.style.display = ‘none’;
}
// 댓글 수 업데이트
if (data.totalCount !== undefined) {
commentCount.textContent = data.totalCount.toLocaleString();
}
} else {
console.error(‘댓글 로드 실패:’, data.message);
commentsList.innerHTML = ‘댓글을 불러오는데 실패했습니다.’;
}
})
.catch(error => {
console.error(‘댓글 로드 오류:’, error);
commentsList.innerHTML = ‘댓글을 불러오는데 실패했습니다. 네트워크를 확인해주세요.’;
});
}
// 댓글 HTML 요소 생성
function createCommentElement(comment) {
const commentDiv = document.createElement(‘div’);
commentDiv.className = ‘comment-item’;
commentDiv.dataset.commentId = comment.id;
if (comment.parent_id) {
commentDiv.classList.add(‘reply-comment’);
}
const timeAgo = getTimeAgo(comment.created_at);
commentDiv.innerHTML = `
${escapeHtml(comment.author_name)}
${timeAgo}
${!comment.parent_id ? `답글` : ”}
${escapeHtml(comment.content).replace(/n/g, ”)}
${comment.likes || 0}
${comment.dislikes || 0}
${comment.replies && comment.replies.length > 0 ? `
${comment.replies.map(reply => createReplyHtml(reply)).join(”)}
` : ”}
`;
return commentDiv;
}
// 답글 HTML 생성
function createReplyHtml(reply) {
const timeAgo = getTimeAgo(reply.created_at);
return `
${escapeHtml(reply.author_name)}
${timeAgo}
${escapeHtml(reply.content).replace(/n/g, ”)}
${reply.likes || 0}
${reply.dislikes || 0}
`;
}
// 시간 계산 함수
function getTimeAgo(dateString) {
const now = new Date();
const date = new Date(dateString);
const diff = now – date;
const minutes = Math.floor(diff / (1000 * 60));
const hours = Math.floor(diff / (1000 * 60 * 60));
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
if (days > 0) {
return days + ‘일 전’;
} else if (hours > 0) {
return hours + ‘시간 전’;
} else if (minutes > 0) {
return minutes + ‘분 전’;
} else {
return ‘방금 전’;
}
}
// HTML 이스케이프
function escapeHtml(text) {
const div = document.createElement(‘div’);
div.textContent = text;
return div.innerHTML;
}
// 답글 모드 시작
window.startReply = function(parentId, parentAuthor) {
document.getElementById(‘parent_id’).value = parentId;
document.getElementById(‘comment_content’).placeholder = `${parentAuthor}님에게 답글을 남겨보세요…`;
cancelReplyBtn.style.display = ‘inline-block’;
document.getElementById(‘submit-comment’).textContent = ‘답글 작성’;
isReplyMode = true;
// 폼으로 스크롤
commentForm.scrollIntoView({ behavior: ‘smooth’, block: ‘center’ });
commentContent.focus();
};
// 답글 취소
cancelReplyBtn.addEventListener(‘click’, function() {
document.getElementById(‘parent_id’).value = ‘0’;
document.getElementById(‘comment_content’).placeholder = ‘댓글을 입력해주세요…’;
cancelReplyBtn.style.display = ‘none’;
document.getElementById(‘submit-comment’).textContent = ‘댓글 작성’;
isReplyMode = false;
});
// 댓글 작성 폼 제출
commentForm.addEventListener(‘submit’, function(e) {
e.preventDefault();
const formData = new FormData();
formData.append(‘deal_id’, document.getElementById(‘deal_id’).value);
formData.append(‘seo_url’, document.getElementById(‘seo_url’).value);
formData.append(‘parent_id’, document.getElementById(‘parent_id’).value);
formData.append(‘author_name’, document.getElementById(‘author_name’).value);
formData.append(‘content’, document.getElementById(‘comment_content’).value);
// 버튼 비활성화
const submitBtn = document.getElementById(‘submit-comment’);
const originalText = submitBtn.textContent;
submitBtn.disabled = true;
submitBtn.textContent = ‘작성 중…’;
fetch(‘/api/comments.php’, {
method: ‘POST’,
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
// 폼 리셋
commentForm.reset();
charCounter.textContent = ‘0’;
// 답글 모드 해제
if (isReplyMode) {
cancelReplyBtn.click();
}
// 댓글 목록 새로고침
currentPage = 1;
loadComments(1, false);
// 성공 메시지
showMessage(‘댓글이 성공적으로 등록되었습니다!’, ‘success’);
} else {
showMessage(data.message || ‘댓글 등록에 실패했습니다.’, ‘error’);
}
})
.catch(error => {
console.error(‘댓글 등록 오류:’, error);
showMessage(‘댓글 등록 중 오류가 발생했습니다.’, ‘error’);
})
.finally(() => {
// 버튼 활성화
submitBtn.disabled = false;
submitBtn.textContent = originalText;
});
});
// 더보기 버튼
loadMoreBtn.addEventListener(‘click’, function() {
currentPage++;
loadComments(currentPage, true);
});
// 메시지 표시 함수
function showMessage(message, type) {
const messageDiv = document.createElement(‘div’);
messageDiv.className = `comment-message ${type}`;
messageDiv.textContent = message;
commentForm.insertBefore(messageDiv, commentForm.firstChild);
setTimeout(() => {
messageDiv.remove();
}, 5000);
}
// 댓글 투표 함수
window.voteComment = function(commentId, voteType) {
const formData = new FormData();
formData.append(‘action’, ‘vote’);
formData.append(‘comment_id’, commentId);
formData.append(‘vote_type’, voteType);
fetch(‘/api/comments.php’, {
method: ‘POST’,
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
// 해당 댓글의 투표 수 업데이트
const commentElement = document.querySelector(`[data-comment-id=”${commentId}”]`);
if (commentElement) {
const likeBtn = commentElement.querySelector(‘.like-btn .vote-count’);
const dislikeBtn = commentElement.querySelector(‘.dislike-btn .vote-count’);
if (likeBtn) likeBtn.textContent = data.likes || 0;
if (dislikeBtn) dislikeBtn.textContent = data.dislikes || 0;
// 투표한 버튼 하이라이트
const allVoteBtns = commentElement.querySelectorAll(‘.vote-btn’);
allVoteBtns.forEach(btn => btn.classList.remove(‘voted’));
if (data.userVote) {
const votedBtn = commentElement.querySelector(`.${data.userVote}-btn`);
if (votedBtn) votedBtn.classList.add(‘voted’);
}
}
if (data.message) {
showMessage(data.message, ‘success’);
}
} else {
showMessage(data.message || ‘투표 처리에 실패했습니다.’, ‘error’);
}
})
.catch(error => {
console.error(‘투표 오류:’, error);
showMessage(‘투표 처리 중 오류가 발생했습니다.’, ‘error’);
});
};
// 초기 댓글 로드
loadComments(1, false);
});
document.addEventListener(‘DOMContentLoaded’, function() {
// 탭 버튼들
const tabButtons = document.querySelectorAll(‘.tab-btn’);
const tabContents = document.querySelectorAll(‘.tab-content’);
const priceFlowTabBtn = document.getElementById(‘priceFlowTabBtn’);
const priceFlowTabContent = document.getElementById(‘lowest-price-tab’);
const priceComparisonSection = document.getElementById(‘priceComparisonSection’);
const hasAiTab = !!document.getElementById(‘ai-price-tab’);
let lowestPriceRequested = false;
let priceFlowRemoved = false;
let priceFlowDataLoaded = false;
function showPriceFlowUI() {
if (!priceFlowTabBtn || !priceFlowTabContent || priceFlowRemoved) {
return;
}
priceFlowTabBtn.style.display = ”;
priceFlowTabContent.style.display = ”;
if (priceComparisonSection && !hasAiTab) {
priceComparisonSection.style.display = ”;
}
if (!hasAiTab) {
tabButtons.forEach(btn => btn.classList.remove(‘active’));
tabContents.forEach(content => content.classList.remove(‘active’));
priceFlowTabBtn.classList.add(‘active’);
priceFlowTabContent.classList.add(‘active’);
}
}
function removePriceFlowUI() {
if (priceFlowRemoved) {
return;
}
priceFlowRemoved = true;
const tabButton = document.getElementById(‘priceFlowTabBtn’);
const tabContent = document.getElementById(‘lowest-price-tab’);
if (tabButton) {
tabButton.remove();
}
if (tabContent) {
tabContent.remove();
}
const aiPriceTabBtn = document.querySelector(‘.tab-btn[data-tab=”ai-price”]’);
const aiPriceContent = document.getElementById(‘ai-price-tab’);
if (aiPriceTabBtn && aiPriceContent) {
tabButtons.forEach(btn => btn.classList.remove(‘active’));
tabContents.forEach(content => content.classList.remove(‘active’));
aiPriceTabBtn.classList.add(‘active’);
aiPriceContent.classList.add(‘active’);
} else {
const priceSection = document.getElementById(‘priceComparisonSection’);
if (priceSection) {
priceSection.style.display = ‘none’;
}
}
}
function ensureLowestPriceData() {
if (lowestPriceRequested || priceFlowRemoved) {
return;
}
lowestPriceRequested = true;
loadLowestPriceData();
}
// 탭 전환 기능
tabButtons.forEach(button => {
button.addEventListener(‘click’, function() {
const tabName = this.getAttribute(‘data-tab’);
// 모든 탭 버튼 비활성화
tabButtons.forEach(btn => btn.classList.remove(‘active’));
// 모든 탭 컨텐츠 숨기기
tabContents.forEach(content => content.classList.remove(‘active’));
// 선택된 탭 활성화
this.classList.add(‘active’);
document.getElementById(tabName + ‘-tab’).classList.add(‘active’);
// 가격 흐름 탭이면서 아직 로드되지 않았다면 데이터 로드
if (tabName === ‘lowest-price’ && !priceFlowDataLoaded) {
ensureLowestPriceData();
}
});
});
// 최저가 데이터 로드 함수
function loadLowestPriceData() {
if (priceFlowRemoved) {
return;
}
const dealId = window.viewPageData.currentProduct.id;
const lowestPriceContent = document.querySelector(‘.lowest-price-content’);
if (!lowestPriceContent) {
removePriceFlowUI();
return;
}
// FormData 생성
const formData = new FormData();
formData.append(‘deal_id’, dealId);
fetch(‘/api/price_info.php’, {
method: ‘POST’,
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success && data.data) {
if (data.data.price_data && Object.keys(data.data.price_data).length > 0) {
displayLowestPriceChart(data.data);
priceFlowDataLoaded = true;
return;
}
}
removePriceFlowUI();
})
.catch(error => {
console.error(‘최저가 데이터 로드 오류:’, error);
removePriceFlowUI();
});
}
// 가격 흐름 표시 함수
function displayLowestPriceChart(data) {
const lowestPriceContent = document.querySelector(‘.lowest-price-content’);
if (!lowestPriceContent) {
removePriceFlowUI();
return;
}
const priceData = data.price_data;
// 사용 가능한 기간 필터링
const availablePeriods = [‘1’, ‘3’, ‘6’, ’12’, ’24’].filter(p => priceData[p] && priceData[p].count > 0);
if (availablePeriods.length === 0) {
removePriceFlowUI();
return;
}
// 기본 선택 기간 (3개월 우선, 없으면 사용 가능한 첫 번째 기간)
let selectedPeriod = availablePeriods.includes(‘3’) ? ‘3’ : availablePeriods[0];
let html = ”;
html += ”;
html += ‘비슷하거나 일치하는 상품을 찾아서 가격 흐름을 알려드려요!’;
html += ” + escapeHtml(data.danawa_title || ‘상품명’) + ”;
html += ”;
// 기간 버튼들
html += ”;
const periodLabels = {‘1’: ‘1개월’, ‘3’: ‘3개월’, ‘6’: ‘6개월’, ’12’: ’12개월’, ’24’: ’24개월’};
availablePeriods.forEach(period => {
const active = period === selectedPeriod ? ‘active’ : ”;
html += `${periodLabels[period]}`;
});
html += ”;
// 최저가/최고가 통계 영역 (동적으로 업데이트됨)
html += ”;
// 가격 차트 영역 (Canvas)
html += ”;
html += ”;
html += ”;
html += ”;
lowestPriceContent.innerHTML = html;
// Chart.js 인스턴스를 저장할 변수
let priceChartInstance = null;
// 이벤트 리스너 등록
const periodButtons = lowestPriceContent.querySelectorAll(‘.period-btn’);
periodButtons.forEach(btn => {
btn.addEventListener(‘click’, function() {
periodButtons.forEach(b => b.classList.remove(‘active’));
this.classList.add(‘active’);
updatePriceChart(priceData, this.dataset.period);
});
});
showPriceFlowUI();
// 초기 표시
updatePriceChart(priceData, selectedPeriod);
// Chart.js로 차트 업데이트하는 함수
function updatePriceChart(priceData, period) {
const data = priceData[period];
if (!data || !data.result || data.result.length === 0) return;
// 기존 차트 제거
if (priceChartInstance) {
priceChartInstance.destroy();
}
// 데이터 준비
const labels = data.result.map(item => formatShortDate(item.Fulldate || item.date));
const prices = data.result.map(item => parseInt(item.minPrice));
const maxPrice = Math.max(…prices);
const minPrice = Math.min(…prices);
const priceRange = maxPrice – minPrice;
const pricePadding = Math.max(
Math.round(priceRange * 0.15),
Math.round(maxPrice * 0.05),
1000
);
const suggestedMax = maxPrice + pricePadding;
const suggestedMin = Math.max(0, minPrice – pricePadding);
// 통계 박스 업데이트
const statsHtml = `
최저
${formatPrice(minPrice)}
최고
${formatPrice(maxPrice)}
`;
document.getElementById(‘priceStats’).innerHTML = statsHtml;
const highlightIndices = new Set();
if (prices.length > 0) {
highlightIndices.add(0); // 첫 번째
highlightIndices.add(prices.length – 1); // 마지막
}
const minIndex = prices.indexOf(minPrice);
if (minIndex !== -1) {
highlightIndices.add(minIndex);
}
const maxIndex = prices.indexOf(maxPrice);
if (maxIndex !== -1) {
highlightIndices.add(maxIndex);
}
// Canvas 요소 가져오기
const ctx = document.getElementById(‘priceChart’);
if (!ctx) return;
// 모바일 여부 확인
const isMobile = window.innerWidth
p === minPrice ? ‘#ff4444’ : (p === maxPrice ? ‘#4285f4’ : ‘rgb(66, 133, 244)’)
),
pointBorderColor: ‘#fff’,
pointBorderWidth: 2,
datalabels: {
display: function(context) {
const chartWidth = context?.chart?.canvas?.parentNode?.clientWidth || context?.chart?.width || window.innerWidth;
const isCompactView = chartWidth <= 768;
return !isCompactView || highlightIndices.has(context.dataIndex);
},
align: 'top',
offset: 4,
formatter: function(value) {
return formatPrice(value);
},
font: {
size: isMobile ? 8 : 10,
weight: 'bold'
},
color: function(context) {
const price = context.dataset.data[context.dataIndex];
return price === minPrice ? '#ff4444' : (price === maxPrice ? '#4285f4' : '#666');
},
clamp: true,
clip: false,
padding: {
top: 4,
bottom: 2
}
}
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
layout: {
padding: {
top: isMobile ? 28 : 36,
right: isMobile ? 8 : 12,
left: isMobile ? 6 : 10,
bottom: isMobile ? 6 : 10
}
},
plugins: {
legend: {
display: false
},
tooltip: {
enabled: true,
callbacks: {
label: function(context) {
return '최저가: ' + formatPrice(context.parsed.y);
}
}
}
},
scales: {
y: {
beginAtZero: false,
suggestedMax: suggestedMax,
suggestedMin: suggestedMin,
grace: '5%',
ticks: {
callback: function(value) {
return (value / 1000).toFixed(0) + 'k';
},
font: {
size: isMobile ? 9 : 11
}
}
},
x: {
ticks: {
maxRotation: isMobile ? 90 : 45,
minRotation: isMobile ? 90 : 45,
font: {
size: isMobile ? 8 : 10
}
}
}
}
},
plugins: [ChartDataLabels]
});
}
}
// 짧은 날짜 포맷 (YY.MM.DD)
function formatShortDate(dateStr) {
if (!dateStr) return '';
// "25-11-11" 또는 "25-11" 형식
return dateStr.replace(/-/g, '.');
}
// 가격 포맷팅 함수
function formatPrice(price) {
if (!price) return '-';
return Number(price).toLocaleString('ko-KR') + '원';
}
// HTML 이스케이프 함수
function escapeHtml(text) {
if (!text) return '';
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// 페이지 로드 시 AI 가격 비교 탭이 없고 가격 흐름만 있으면 자동 로드
const aiPriceTab = document.getElementById('ai-price-tab');
if (priceFlowTabBtn) {
ensureLowestPriceData();
}
});
(function() {
const productId = 134727;
const storageKey = ‘viewed_products’;
// sessionStorage에서 조회 기록 가져오기
let viewedProducts = [];
try {
const stored = sessionStorage.getItem(storageKey);
viewedProducts = stored ? JSON.parse(stored) : [];
} catch (e) {
console.error(‘sessionStorage 읽기 실패:’, e);
viewedProducts = [];
}
// 이미 본 상품인지 확인
if (!viewedProducts.includes(productId)) {
// 조회수 증가 API 호출
fetch(‘/api/increment_view.php’, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’
},
body: JSON.stringify({ product_id: productId })
})
.then(response => response.json())
.then(data => {
if (data.success) {
console.log(‘조회수 증가:’, data.view_count);
// 페이지의 조회수 업데이트 (있다면)
const viewsElement = document.querySelector(‘.deal-meta .views’);
if (viewsElement && data.view_count) {
viewsElement.textContent = ‘조회 ‘ + data.view_count.toLocaleString();
}
}
})
.catch(error => {
console.error(‘조회수 증가 실패:’, error);
// 실패해도 사용자 경험에 영향 없음
});
// sessionStorage에 기록 (최대 1000개 유지)
viewedProducts.unshift(productId);
viewedProducts = viewedProducts.slice(0, 1000);
try {
sessionStorage.setItem(storageKey, JSON.stringify(viewedProducts));
} catch (e) {
// quota 초과 시 오래된 데이터 삭제 후 재시도
viewedProducts = viewedProducts.slice(0, 500);
try {
sessionStorage.setItem(storageKey, JSON.stringify(viewedProducts));
} catch (e2) {
console.error(‘sessionStorage 저장 실패:’, e2);
}
}
} else {
console.log(‘이미 본 상품 (조회수 증가 안 함)’);
}
})();
/* 푸터 스타일 – 다크모드 지원 */
.footer {
background: var(–surface-color);
border-top: 1px solid var(–border-color);
margin-top: 60px;
padding: 20px 0;
transition: background-color 0.3s ease, border-color 0.3s ease;
}
.footer-content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 16px;
}
.footer-links {
display: flex;
gap: 20px;
flex-wrap: wrap;
justify-content: center;
}
.footer-links a {
color: var(–text-secondary);
text-decoration: none;
font-size: 12px;
transition: color 0.3s ease;
}
.footer-links a:hover {
color: var(–accent-color);
}
/* 앱 스토어 링크 스타일 */
.app-store-links {
display: flex;
gap: 12px;
align-items: center;
flex-wrap: wrap;
justify-content: center;
}
.app-store-link {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border-radius: 8px;
transition: all 0.3s ease;
text-decoration: none;
position: relative;
overflow: hidden;
}
.app-store-link.play-store {
background: linear-gradient(135deg, #34A853, #4285F4);
}
.app-store-link.app-store {
background: linear-gradient(135deg, #007AFF, #0056B3);
}
.app-store-link.app-store.disabled {
background: var(–border-color);
cursor: not-allowed;
opacity: 0.6;
}
.app-store-link i {
color: white;
font-size: 18px;
z-index: 1;
position: relative;
}
.app-store-link.app-store.disabled i {
color: var(–text-secondary);
}
.app-store-link:hover:not(.disabled) {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.app-store-link::before {
content: ”;
position: absolute;
inset: 0;
background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.2) 50%, transparent 70%);
transform: translateX(-100%);
transition: transform 0.6s ease;
}
.app-store-link:hover:not(.disabled)::before {
transform: translateX(100%);
}
/* 툴팁 스타일 */
.app-store-link::after {
content: attr(data-tooltip);
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
background: var(–text-primary);
color: var(–surface-color);
padding: 6px 8px;
border-radius: 4px;
font-size: 11px;
white-space: nowrap;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
margin-bottom: 8px;
z-index: 1000;
}
.app-store-link:hover::after {
opacity: 1;
visibility: visible;
transform: translateX(-50%) translateY(-4px);
}
/* 접근성을 위한 시각적 숨김 클래스 */
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* 반응형 */
@media (max-width: 768px) {
.footer-links {
gap: 16px;
}
.app-store-links {
gap: 16px;
}
.app-store-link {
width: 36px;
height: 36px;
}
.app-store-link i {
font-size: 20px;
}
}
App Store에서 다운로드
(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement(‘script’);d.innerHTML=”window.__CF$cv$params={r:’9f46c58dbb164008′,t:’MTc3NzU1NDQ3MA==’};var a=document.createElement(‘script’);a.src=’/cdn-cgi/challenge-platform/scripts/jsd/main.js’;document.getElementsByTagName(‘head’)[0].appendChild(a);”;b.getElementsByTagName(‘head’)[0].appendChild(d)}}if(document.body){var a=document.createElement(‘iframe’);a.height=1;a.width=1;a.style.position=’absolute’;a.style.top=0;a.style.left=0;a.style.border=’none’;a.style.visibility=’hidden’;document.body.appendChild(a);if(‘loading’!==document.readyState)c();else if(window.addEventListener)document.addEventListener(‘DOMContentLoaded’,c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);’loading’!==document.readyState&&(document.onreadystatechange=e,c())}}}})();
Chưa có bình luận nào.
💬 댓글 0개