(function () { 'use strict'; var YS = window.YS || {}; var csrfToken = YS.csrfToken || ''; // ── Helpers ── function $(sel) { return document.querySelector(sel); } function $$(sel) { return document.querySelectorAll(sel); } function escapeHTML(s) { var d = document.createElement('div'); d.textContent = s || ''; return d.innerHTML; } function escapeAttr(s) { if (!s) return ''; return s.replace(/&/g, '&') .replace(/"/g, '"') .replace(/'/g, ''') .replace(//g, '>'); } async function fetchJSON(url) { var r = await fetch(url); var data = await r.json(); if (!data.success) throw new Error(data.error || '요청 실패'); return data; } async function postForm(url, params) { params.csrf_token = csrfToken; var body = new URLSearchParams(params); var r = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: body, }); var data = await r.json(); if (!data.success) throw new Error(data.error || '요청 실패'); return data; } function showToast(msg, type) { var toast = document.querySelector('.community-toast'); if (!toast) { toast = document.createElement('div'); toast.className = 'community-toast'; toast.style.cssText = 'position:fixed;bottom:24px;left:50%;transform:translateX(-50%);padding:10px 24px;border-radius:8px;color:#fff;font-size:14px;z-index:9999;transition:opacity 0.3s;pointer-events:none;'; document.body.appendChild(toast); } toast.textContent = msg; toast.style.background = type === 'error' ? '#e74c3c' : '#00b894'; toast.style.opacity = '1'; clearTimeout(toast._timer); toast._timer = setTimeout(function () { toast.style.opacity = '0'; }, 2500); } function renderLevelBadge(level, label, cls) { if (!level) return ''; return 'Lv.' + level + ' ' + escapeHTML(label || '') + ''; } function renderPagination(container, pg, onPageClick) { if (!pg || pg.total_pages <= 1) { container.innerHTML = ''; return; } var html = ''; var start = Math.max(1, pg.page - 2); var end = Math.min(pg.total_pages, pg.page + 2); if (pg.page > 1) { html += ''; } for (var i = start; i <= end; i++) { html += ''; } if (pg.page < pg.total_pages) { html += ''; } container.innerHTML = html; container.onclick = function (e) { var btn = e.target.closest('[data-page]'); if (btn) onPageClick(parseInt(btn.dataset.page)); }; } // ── Page Router ── var page = YS.communityPage || ''; if (page === 'board') initBoard(); if (page === 'post') initPostDetail(); if (page === 'write') initWriteForm(); // ================================================================ // Board Page // ================================================================ function initBoard() { var state = { page: 1, keyword: '', storeId: YS.filterStoreId || 0, regionId: 0, industryId: 0 }; var boardType = YS.boardType; var boardId = YS.boardId; var isReview = boardType === 'review'; var isAnonymous = boardType === 'anonymous'; // ── Review Board Filters ── var _saveReviewFilterTimer = null; if (isReview) { initReviewFilters(); } function initReviewFilters() { var regions = YS.reviewRegions || []; var industries = YS.reviewIndustries || []; var regionSelect = document.getElementById('reviewFilterRegion'); var subRegionSelect = document.getElementById('reviewFilterSubRegion'); var industrySelect = document.getElementById('reviewFilterIndustry'); if (!regionSelect) return; // Populate parent regions regions.forEach(function (r) { var opt = document.createElement('option'); opt.value = r.region_id; opt.textContent = r.region_name; regionSelect.appendChild(opt); }); // Populate industries industries.forEach(function (ind) { var opt = document.createElement('option'); opt.value = ind.industry_id; opt.textContent = ind.industry_name; industrySelect.appendChild(opt); }); // Restore saved filter var initRegionId = YS.reviewInitRegionId || 0; var initIndustryId = YS.reviewInitIndustryId || 0; if (initRegionId > 0) { restoreReviewRegion(initRegionId, regions, regionSelect, subRegionSelect); } if (initIndustryId > 0) { industrySelect.value = initIndustryId; state.industryId = initIndustryId; } // Region change regionSelect.addEventListener('change', function () { var parentId = parseInt(regionSelect.value, 10); updateReviewSubRegion(parentId, regions, subRegionSelect); state.regionId = parentId; state.page = 1; loadPosts(); saveReviewFilterToServer(); }); // Sub-region change subRegionSelect.addEventListener('change', function () { var subId = parseInt(subRegionSelect.value, 10); if (subId > 0) { state.regionId = subId; } else { state.regionId = parseInt(regionSelect.value, 10); } state.page = 1; loadPosts(); saveReviewFilterToServer(); }); // Industry change industrySelect.addEventListener('change', function () { state.industryId = parseInt(industrySelect.value, 10); state.page = 1; loadPosts(); saveReviewFilterToServer(); }); } function restoreReviewRegion(regionId, regions, regionSelect, subRegionSelect) { // Check if it's a parent region var parentRegion = regions.find(function (r) { return parseInt(r.region_id, 10) === regionId; }); if (parentRegion) { regionSelect.value = regionId; updateReviewSubRegion(regionId, regions, subRegionSelect); state.regionId = regionId; } else { // It's a child region: find its parent for (var i = 0; i < regions.length; i++) { var p = regions[i]; if (p.children) { var child = p.children.find(function (c) { return parseInt(c.region_id, 10) === regionId; }); if (child) { var parentId = parseInt(p.region_id, 10); regionSelect.value = parentId; updateReviewSubRegion(parentId, regions, subRegionSelect); subRegionSelect.value = regionId; state.regionId = regionId; break; } } } } } function updateReviewSubRegion(parentRegionId, regions, subRegionSelect) { subRegionSelect.innerHTML = ''; if (parentRegionId === 0) { subRegionSelect.disabled = true; return; } var parent = regions.find(function (r) { return parseInt(r.region_id, 10) === parentRegionId; }); if (parent && parent.children && parent.children.length > 0) { parent.children.forEach(function (child) { var opt = document.createElement('option'); opt.value = child.region_id; opt.textContent = child.region_name; subRegionSelect.appendChild(opt); }); subRegionSelect.disabled = false; } else { subRegionSelect.disabled = true; } } function saveReviewFilterToServer() { if (!YS.isLoggedIn) return; clearTimeout(_saveReviewFilterTimer); _saveReviewFilterTimer = setTimeout(function () { var body = new URLSearchParams({ region_id: state.regionId, industry_id: state.industryId, csrf_token: csrfToken, }); fetch('/api/save_review_filter.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: body, }).catch(function () { /* silent */ }); }, 1000); } // Search UI var searchInput = document.getElementById('boardSearchInput'); var searchBtn = document.getElementById('boardSearchBtn'); var clearBtn = document.getElementById('clearStoreFilter'); if (searchBtn) { searchBtn.addEventListener('click', function () { state.keyword = searchInput ? searchInput.value.trim() : ''; state.page = 1; loadPosts(); }); } if (searchInput) { searchInput.addEventListener('keydown', function (e) { if (e.key === 'Enter') { state.keyword = searchInput.value.trim(); state.page = 1; loadPosts(); } }); } if (clearBtn) { clearBtn.addEventListener('click', function () { state.storeId = 0; var filterEl = document.getElementById('boardStoreFilter'); if (filterEl) filterEl.style.display = 'none'; state.page = 1; loadPosts(); }); } loadPosts(); // Row click → navigate to post (single listener, persists across re-renders) $('#postList').addEventListener('click', function (e) { var row = e.target.closest('tr[data-href]'); if (!row) return; if (e.target.closest('a')) return; location.href = row.dataset.href; }); async function loadPosts() { try { var params = new URLSearchParams({ board_id: boardId, page: state.page }); if (isReview && state.storeId) params.set('store_id', state.storeId); if (isReview && state.regionId) params.set('region_id', state.regionId); if (isReview && state.industryId) params.set('industry_id', state.industryId); if (state.keyword) params.set('keyword', state.keyword); var data = await fetchJSON('/api/community/posts.php?' + params); var posts = data.data.posts; var pg = data.data.pagination; $('#loading').style.display = 'none'; if (!posts.length && state.page === 1) { var hasFilter = (state.keyword || (isReview && (state.storeId || state.regionId || state.industryId))); var emptyEl = $('#emptyState'); var emptyMsg = emptyEl.querySelector('p'); var emptyBtn = emptyEl.querySelector('a'); if (hasFilter) { emptyMsg.textContent = '검색 결과가 없습니다.'; if (emptyBtn) emptyBtn.style.display = 'none'; } else { emptyMsg.textContent = '아직 게시글이 없습니다.'; if (emptyBtn) emptyBtn.style.display = ''; } emptyEl.style.display = ''; $('#content').style.display = 'none'; return; } $('#emptyState').style.display = 'none'; $('#content').style.display = ''; if (boardType === 'photo') { renderPhotoGrid(posts); } else { renderNormalList(posts, pg); } renderPagination($('#pagination'), pg, function (p) { state.page = p; loadPosts(); window.scrollTo({ top: 0, behavior: 'smooth' }); }); } catch (e) { $('#loading').innerHTML = '

' + escapeHTML(e.message) + '

'; } } function renderNormalList(posts, pg) { var startNum = pg.total - (pg.page - 1) * pg.per_page; var html = '' + '' + '' + '' + '' + '' + '' + '' + ''; posts.forEach(function (p, i) { var num = startNum - i; var postUrl = '/community/post.php?id=' + p.post_id; var titleHtml = ''; // Review board: add [region-store] prefix and therapist name if (isReview && p.store_name && !p.is_blinded) { var prefix = '[' + escapeHTML(p.region_name || '') + '-' + escapeHTML(p.store_name) + '] '; titleHtml += '' + prefix + ''; if (p.therapist_name) { titleHtml += '' + escapeHTML(p.therapist_name) + ' '; } } titleHtml += p.is_blinded ? '' + escapeHTML(p.title) + '' : '' + escapeHTML(p.title) + ''; if (p.comment_count > 0) { titleHtml += '[' + p.comment_count + ']'; } var authorHtml = isAnonymous ? escapeHTML(p.author_name) : renderLevelBadge(p.author_level, p.author_level_label, p.author_level_class) + ' ' + escapeHTML(p.author_name); var rowAttr = p.is_blinded ? '' : ' data-href="' + postUrl + '"'; html += '' + '' + '' + '' + '' + '' + '' + ''; }); html += '
번호제목작성자조회날짜
' + num + '' + titleHtml + '' + authorHtml + '' + p.view_count + '' + escapeHTML((p.created_at || '').substring(5, 10)) + '
'; $('#postList').innerHTML = html; } function renderPhotoGrid(posts) { var html = '
'; posts.forEach(function (p) { var thumbHtml = p.thumbnail_url ? '' : '
📷
'; html += '' + thumbHtml + '
' + '
' + escapeHTML(p.title) + '
' + '
' + '' + escapeHTML(p.author_name) + '' + '❤ ' + p.like_count + '' + '💬 ' + p.comment_count + '' + '
' + '
'; }); html += '
'; $('#postList').innerHTML = html; } } // ================================================================ // Post Detail Page // ================================================================ function initPostDetail() { var postId = YS.postId; var postData = null; var boardData = null; loadPost(); // Record view fetch('/api/community/view.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: 'post_id=' + postId + '&csrf_token=' + encodeURIComponent(csrfToken), }).catch(function () { }); async function loadPost() { try { var data = await fetchJSON('/api/community/post_detail.php?id=' + postId); postData = data.data.post; boardData = data.data.board; $('#loading').style.display = 'none'; $('#content').style.display = ''; // Update mobile back link var backLink = document.getElementById('mobileBackLink'); if (backLink && boardData) { backLink.href = '/community/board.php?slug=' + encodeURIComponent(boardData.board_slug); backLink.innerHTML = ' ' + escapeHTML(boardData.board_name); } renderPost(data.data); renderActions(data.data); renderNav(data.data); loadComments(); // Update page title document.title = escapeHTML(postData.title) + ' - 커뮤니티'; } catch (e) { $('#loading').style.display = 'none'; $('#errorMsg').textContent = e.message; $('#errorState').style.display = ''; } } function renderPost(d) { var p = d.post; var b = d.board; var isAnonBoard = b.board_type === 'anonymous'; var authorHtml = isAnonBoard ? '' + escapeHTML(p.author_name) + '' : renderLevelBadge(p.author_level, p.author_level_label, p.author_level_class) + ' ' + escapeHTML(p.author_name) + ''; if (!isAnonBoard && p.author_is_specialist) { authorHtml += ' 인증'; } // Store link for review board var storeLinkHtml = ''; var storeBarHtml = ''; if (p.store_id && p.store_name) { storeLinkHtml = '
' + '[' + escapeHTML(p.region_name || '') + '-' + escapeHTML(p.store_name) + ']'; if (p.therapist_name) { storeLinkHtml += ' 담당: ' + escapeHTML(p.therapist_name) + ''; } storeLinkHtml += '
'; // Store action buttons (rendered inside content area top) var storeActionsHtml = ''; // Attendance (always show if store_id exists) storeActionsHtml += '' + '📅' + '출근부'; // Phone if (p.phone_number) { storeActionsHtml += '' + '📞' + '전화'; } // Kakao if (p.messenger_kakao) { storeActionsHtml += '' + '💬' + '카카오'; } // Telegram if (p.messenger_telegram) { storeActionsHtml += '' + '' + '텔레그램'; } // WhatsApp if (p.messenger_whatsapp) { storeActionsHtml += '' + '💬' + '왓츠앱'; } storeBarHtml = '
' + storeActionsHtml + '
'; } var html = '
' + '
' + '커뮤니티 › ' + '' + escapeHTML(b.board_name) + '' + '
' + storeLinkHtml + '

' + escapeHTML(p.title) + '

' + '
' + authorHtml + '' + escapeHTML((p.created_at || '').substring(0, 16)) + '' + '조회 ' + p.view_count + '' + '
' + '
' + '
' + storeBarHtml + p.content + '
'; $('#postDetail').innerHTML = html; } function renderActions(d) { var p = d.post; var html = ''; if (boardData.allow_likes) { html += ''; } if (YS.isLoggedIn || YS.isOwner) { html += ''; } html += '
'; if (p.is_mine) { html += '✎ 수정'; html += ''; } else if (YS.isAdmin) { html += ''; } html += '📝 목록'; $('#postActions').innerHTML = html; // Like toggle var likeBtn = $('#likeBtn'); if (likeBtn) { likeBtn.addEventListener('click', async function () { if (!YS.isLoggedIn && !YS.isOwner) { showToast('로그인이 필요합니다.', 'error'); return; } try { var data = await postForm('/api/community/like.php', { target_type: 'post', target_id: postId }); var liked = data.data.liked; likeBtn.className = 'post-actions__btn' + (liked ? ' post-actions__btn--liked' : ''); likeBtn.innerHTML = (liked ? '❤' : '♡') + ' ' + data.data.like_count + ''; } catch (e) { showToast(e.message, 'error'); } }); } // Report var reportBtn = document.querySelector('.js-report-post'); if (reportBtn) { reportBtn.addEventListener('click', function () { openReportModal('post', postId); }); } // Delete var deleteBtn = document.querySelector('.js-delete-post'); if (deleteBtn) { deleteBtn.addEventListener('click', async function () { if (!confirm('게시글을 삭제하시겠습니까?')) return; try { await postForm('/api/community/posts.php', { action: 'delete', post_id: postId }); showToast('삭제되었습니다.', 'success'); setTimeout(function () { location.href = '/community/board.php?slug=' + boardData.board_slug; }, 500); } catch (e) { showToast(e.message, 'error'); } }); } } function renderNav(d) { var html = ''; if (d.prev_post) { html += '' + '« 이전글' + escapeHTML(d.prev_post.title) + ''; } else { html += ''; } if (d.next_post) { html += '' + '다음글 »' + escapeHTML(d.next_post.title) + ''; } $('#postNav').innerHTML = html; } // ── Comments ── async function loadComments() { try { var data = await fetchJSON('/api/community/comments.php?post_id=' + postId); var comments = data.data.comments; $('#commentCount').textContent = data.data.total; renderCommentForm(); renderComments(comments); } catch (e) { /* ignore */ } } function renderCommentForm() { var formEl = $('#commentForm'); if (!YS.isLoggedIn && !YS.isOwner) { formEl.innerHTML = '

댓글을 작성하려면 로그인하세요.

'; return; } formEl.innerHTML = '
' + '' + '
'; $('#commentSubmitBtn').addEventListener('click', async function () { var content = $('#commentTextarea').value.trim(); if (!content) { showToast('댓글을 입력해주세요.', 'error'); return; } this.disabled = true; try { await postForm('/api/community/comments.php', { post_id: postId, content: content }); $('#commentTextarea').value = ''; loadComments(); showToast('댓글이 작성되었습니다.', 'success'); } catch (e) { showToast(e.message, 'error'); } this.disabled = false; }); } function renderComments(comments) { // Build nested structure var topLevel = []; var replies = {}; comments.forEach(function (c) { if (c.parent_comment_id) { if (!replies[c.parent_comment_id]) replies[c.parent_comment_id] = []; replies[c.parent_comment_id].push(c); } else { topLevel.push(c); } }); var html = ''; topLevel.forEach(function (c) { html += renderCommentItem(c, false); if (replies[c.comment_id]) { replies[c.comment_id].forEach(function (r) { html += renderCommentItem(r, true); }); } }); $('#commentList').innerHTML = html || '

아직 댓글이 없습니다.

'; } function renderCommentItem(c, isReply) { var cls = 'comment-item' + (isReply ? ' comment-item--reply' : '') + (c.is_blinded ? ' comment-item--blinded' : ''); var isAnonBoard = boardData && boardData.board_type === 'anonymous'; var authorHtml = isAnonBoard ? '' + escapeHTML(c.author_name) + '' : renderLevelBadge(c.author_level, c.author_level_label, c.author_level_class) + ' ' + escapeHTML(c.author_name) + ''; if (!isAnonBoard && c.author_is_specialist) authorHtml += ' 인증'; var actionsHtml = ''; if (!c.is_blinded) { if (boardData && boardData.allow_likes) { actionsHtml += ''; } if (!isReply && (YS.isLoggedIn || YS.isOwner)) { actionsHtml += ''; } if (YS.isLoggedIn || YS.isOwner) { actionsHtml += ''; } if (c.is_mine || YS.isAdmin) { actionsHtml += ''; } } return '
' + '
' + authorHtml + ' ' + escapeHTML((c.created_at || '').substring(0, 16)) + '
' + '
' + escapeHTML(c.content) + '
' + '
' + actionsHtml + '
' + '
' + '
'; } // Event delegation for comments document.addEventListener('click', function (e) { // Like comment var likeBtn2 = e.target.closest('.js-like-comment'); if (likeBtn2) { if (!YS.isLoggedIn && !YS.isOwner) { showToast('로그인이 필요합니다.', 'error'); return; } var cid = likeBtn2.dataset.id; postForm('/api/community/like.php', { target_type: 'comment', target_id: cid }) .then(function () { loadComments(); }) .catch(function (err) { showToast(err.message, 'error'); }); } // Reply toggle var replyBtn = e.target.closest('.js-reply-toggle'); if (replyBtn) { var parentId = replyBtn.dataset.id; var container = $('#replyForm_' + parentId); if (container.innerHTML) { container.innerHTML = ''; return; } container.innerHTML = '
' + '' + '
'; } // Reply cancel var cancelBtn = e.target.closest('.js-reply-cancel'); if (cancelBtn) { var pid = cancelBtn.dataset.id; $('#replyForm_' + pid).innerHTML = ''; } // Reply submit var submitBtn = e.target.closest('.js-reply-submit'); if (submitBtn) { var pid2 = submitBtn.dataset.id; var textarea = $('#replyForm_' + pid2 + ' textarea'); var content2 = textarea.value.trim(); if (!content2) { showToast('답글을 입력해주세요.', 'error'); return; } submitBtn.disabled = true; postForm('/api/community/comments.php', { post_id: postId, content: content2, parent_comment_id: pid2 }) .then(function () { loadComments(); showToast('답글이 작성되었습니다.', 'success'); }) .catch(function (err) { showToast(err.message, 'error'); submitBtn.disabled = false; }); } // Delete comment var delBtn = e.target.closest('.js-delete-comment'); if (delBtn) { if (!confirm('댓글을 삭제하시겠습니까?')) return; var dcid = delBtn.dataset.id; postForm('/api/community/comments.php', { action: 'delete', comment_id: dcid }) .then(function () { loadComments(); showToast('삭제되었습니다.', 'success'); }) .catch(function (err) { showToast(err.message, 'error'); }); } // Report comment var reportComBtn = e.target.closest('.js-report-comment'); if (reportComBtn) { openReportModal('comment', reportComBtn.dataset.id); } }); // ── Report Modal ── function openReportModal(type, id) { $('#reportTargetType').value = type; $('#reportTargetId').value = id; $('#reportDetail').value = ''; var radios = document.querySelectorAll('[name="reportReason"]'); radios.forEach(function (r) { r.checked = r.value === 'other'; }); $('#reportModal').classList.add('modal-overlay--active'); } if ($('#reportClose')) { $('#reportClose').addEventListener('click', function () { $('#reportModal').classList.remove('modal-overlay--active'); }); } if ($('#reportCancel')) { $('#reportCancel').addEventListener('click', function () { $('#reportModal').classList.remove('modal-overlay--active'); }); } if ($('#reportModal')) { $('#reportModal').addEventListener('click', function (e) { if (e.target === this) this.classList.remove('modal-overlay--active'); }); } if ($('#reportSubmit')) { $('#reportSubmit').addEventListener('click', async function () { var reason = document.querySelector('[name="reportReason"]:checked'); if (!reason) { showToast('신고 사유를 선택해주세요.', 'error'); return; } this.disabled = true; try { await postForm('/api/community/report.php', { target_type: $('#reportTargetType').value, target_id: $('#reportTargetId').value, reason: reason.value, detail_text: $('#reportDetail').value, }); showToast('신고가 접수되었습니다.', 'success'); $('#reportModal').classList.remove('modal-overlay--active'); } catch (e2) { showToast(e2.message, 'error'); } this.disabled = false; }); } } // ================================================================ // Write / Edit Form // ================================================================ function initWriteForm() { var boardId = YS.boardId; var editMode = YS.editMode; var postIdEdit = YS.postId; var boardType = YS.boardType; var boardSlug = YS.boardSlug; // Init Summernote if (typeof $ === 'function' && typeof jQuery !== 'undefined') { jQuery('#postEditor').summernote({ height: 400, lang: 'ko-KR', placeholder: '내용을 입력하세요...', toolbar: [ ['style', ['style']], ['font', ['bold', 'italic', 'underline', 'strikethrough']], ['color', ['color']], ['para', ['ul', 'ol', 'paragraph']], ['table', ['table']], ['insert', ['link', 'picture']], ['view', ['fullscreen', 'codeview']], ], callbacks: { onImageUpload: function (files) { uploadImage(files[0], function (url) { jQuery('#postEditor').summernote('insertImage', url); }); }, }, }); } // Thumbnail upload (photo boards) var thumbnailFileEl = document.getElementById('thumbnailFile'); if (thumbnailFileEl) { thumbnailFileEl.addEventListener('change', function () { if (this.files[0]) { uploadImage(this.files[0], function (url) { document.getElementById('thumbnailUrl').value = url; document.getElementById('thumbnailPreview').innerHTML = ''; }, 'thumbnail'); } }); } function uploadImage(file, callback, type) { var fd = new FormData(); fd.append('file', file); fd.append('csrf_token', csrfToken); if (type) fd.append('type', type); fetch('/api/community/upload_image.php', { method: 'POST', body: fd }) .then(function (r) { return r.json(); }) .then(function (data) { if (data.success) callback(data.url); else showToast(data.error || '업로드 실패', 'error'); }) .catch(function () { showToast('업로드 실패', 'error'); }); } // Store selector (review board) if (boardType === 'review') { var storeSearchEl = document.getElementById('storeSearch'); var storeIdInput = document.getElementById('storeIdInput'); var storeSelectedEl = document.getElementById('storeSelected'); var storeResultsEl = document.getElementById('storeResults'); var searchTimer = null; function selectStore(id, name, region) { storeIdInput.value = id; storeSearchEl.style.display = 'none'; storeResultsEl.style.display = 'none'; storeSelectedEl.innerHTML = '' + escapeHTML('[' + region + '-' + name + ']') + '' + ''; storeSelectedEl.style.display = ''; storeSelectedEl.querySelector('.store-selector__clear').addEventListener('click', function () { storeIdInput.value = ''; storeSelectedEl.style.display = 'none'; storeSearchEl.style.display = ''; storeSearchEl.value = ''; storeSearchEl.focus(); }); } // Pre-fill store if (YS.prefillStoreId) { selectStore(YS.prefillStoreId, YS.prefillStoreName || '', YS.prefillStoreRegion || ''); } // Auto-focus therapist name field if requested via URL param if (YS.focusField === 'therapist') { var therapistEl = document.getElementById('therapistName'); if (therapistEl) { setTimeout(function () { therapistEl.focus(); }, 300); } } if (storeSearchEl) { storeSearchEl.addEventListener('input', function () { clearTimeout(searchTimer); var kw = this.value.trim(); if (kw.length < 1) { storeResultsEl.style.display = 'none'; return; } searchTimer = setTimeout(function () { fetch('/api/community/search_stores.php?keyword=' + encodeURIComponent(kw)) .then(function (r) { return r.json(); }) .then(function (data) { if (!data.success || !data.data.stores.length) { storeResultsEl.innerHTML = '
검색 결과가 없습니다.
'; storeResultsEl.style.display = ''; return; } storeResultsEl.innerHTML = data.data.stores.map(function (s) { return '
' + escapeHTML('[' + s.region_name + '] ' + s.store_name) + '
'; }).join(''); storeResultsEl.style.display = ''; }) .catch(function () { storeResultsEl.style.display = 'none'; }); }, 300); }); storeResultsEl.addEventListener('click', function (e) { var item = e.target.closest('.store-selector__item[data-id]'); if (!item) return; selectStore(item.dataset.id, item.dataset.name, item.dataset.region); }); // Hide results on outside click document.addEventListener('click', function (e) { if (!storeResultsEl.contains(e.target) && e.target !== storeSearchEl) { storeResultsEl.style.display = 'none'; } }); } } // Form submit var form = document.getElementById('writeForm'); if (form) { form.addEventListener('submit', async function (e) { e.preventDefault(); var title = document.getElementById('postTitle').value.trim(); var content = jQuery ? jQuery('#postEditor').summernote('code') : ''; var thumbnailUrl = document.getElementById('thumbnailUrl') ? document.getElementById('thumbnailUrl').value : ''; if (!title) { showError('제목을 입력해주세요.'); return; } if (!content || content === '


') { showError('내용을 입력해주세요.'); return; } // Review board: store_id required, therapist_name optional var storeIdVal = null; var therapistNameVal = ''; if (boardType === 'review') { var sid = document.getElementById('storeIdInput'); storeIdVal = sid ? sid.value : ''; if (!storeIdVal) { showError('매장을 선택해주세요.'); return; } var tnEl = document.getElementById('therapistName'); therapistNameVal = tnEl ? tnEl.value.trim() : ''; } var submitBtn = document.getElementById('submitBtn'); submitBtn.disabled = true; submitBtn.textContent = '처리 중...'; try { var params = { title: title, content: content }; if (thumbnailUrl) params.thumbnail_url = thumbnailUrl; if (storeIdVal) params.store_id = storeIdVal; if (boardType === 'review') params.therapist_name = therapistNameVal; if (editMode) { params.action = 'update'; params.post_id = postIdEdit; await postForm('/api/community/posts.php', params); showToast('수정되었습니다.', 'success'); setTimeout(function () { location.href = '/community/post.php?id=' + postIdEdit; }, 500); } else { params.board_id = boardId; var data = await postForm('/api/community/posts.php', params); showToast('작성되었습니다.', 'success'); setTimeout(function () { location.href = '/community/post.php?id=' + data.data.post_id; }, 500); } } catch (err) { showError(err.message); submitBtn.disabled = false; submitBtn.textContent = editMode ? '수정' : '작성'; } }); } function showError(msg) { var el = document.getElementById('writeError'); el.textContent = msg; el.style.display = ''; setTimeout(function () { el.style.display = 'none'; }, 3000); } } })();