jhhackaton/frontend/script.js

224 lines
7.3 KiB
JavaScript

// 예시 텍스트 설정
function setExample(element) {
document.getElementById('searchInput').value = element.textContent;
}
// 쿼리 파싱 및 분석
async function parseQuery() {
const input = document.getElementById('searchInput').value.trim();
if (!input) {
alert('검색할 내용을 입력해주세요!');
return;
}
// UI 상태 변경
document.getElementById('loadingSection').style.display = 'block';
document.getElementById('resultSection').style.display = 'none';
document.getElementById('searchBtn').disabled = true;
try {
// /api/search 엔드포인트 호출 (파싱 + 실거래가 조회)
const response = await fetch('/api/search', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ text: input })
});
if (!response.ok) {
throw new Error('서버 오류가 발생했습니다.');
}
const data = await response.json();
displayResults(data);
} catch (error) {
alert('오류: ' + error.message);
console.error('Error:', error);
} finally {
document.getElementById('loadingSection').style.display = 'none';
document.getElementById('searchBtn').disabled = false;
}
}
// 결과 표시
function displayResults(data) {
const resultContent = document.getElementById('resultContent');
let html = '';
// 파싱된 정보 요약
if (data.parsed) {
html += '<div class="search-summary">';
html += '<h3>🔍 검색 조건</h3>';
html += '<div class="summary-items">';
if (data.parsed.property_type) {
html += `<span class="summary-item">${data.parsed.property_type}</span>`;
}
if (data.parsed.transaction_type) {
html += `<span class="summary-item">${data.parsed.transaction_type}</span>`;
}
if (data.parsed.location) {
html += `<span class="summary-item">${data.parsed.location}</span>`;
}
if (data.parsed.region_name) {
html += `<span class="summary-item">${data.parsed.region_name}</span>`;
}
html += '</div>';
html += '</div>';
}
// 실거래가 목록
if (data.listings && data.listings.length > 0) {
html += '<div class="listings-section">';
// 필터링 정보 표시
if (data.filtered) {
html += `<h3>🎯 AI 추천 매물 TOP ${data.count} (전체 ${data.total_count}건 중)</h3>`;
html += '<p class="filter-info">AI가 요구사항과 가장 일치하는 매물을 선별했습니다.</p>';
} else {
html += `<h3>📊 실거래가 정보 (${data.total_count || data.count}건)</h3>`;
}
html += '<div class="listings-container">';
// 매물 카드 표시
for (let i = 0; i < data.listings.length; i++) {
const item = data.listings[i];
html += createListingCard(item, data.filtered);
}
if (!data.filtered && data.total_count > data.count) {
html += `<p class="more-info">... 외 ${data.total_count - data.count}건</p>`;
}
html += '</div>';
html += '</div>';
} else {
html += '<div class="no-results">';
html += '<p>😔 검색 결과가 없습니다.</p>';
if (!data.parsed.region_code) {
html += '<p>지역 정보를 더 구체적으로 입력해주세요.</p>';
} else {
html += '<p>다른 조건으로 검색해보세요.</p>';
}
html += '</div>';
}
resultContent.innerHTML = html;
document.getElementById('resultSection').style.display = 'block';
}
// 실거래가 카드 생성
function createListingCard(item, isFiltered = false) {
let html = '<div class="listing-card">';
// 순위 표시 (필터링된 경우)
if (isFiltered && item.rank) {
html += `<div class="rank-badge">TOP ${item.rank}</div>`;
}
// 제목 (아파트명 또는 주소)
const title = item['아파트'] || item['법정동'] || '정보 없음';
html += `<h4>${title}</h4>`;
// 거래 정보
html += '<div class="listing-info">';
// 거래금액
if (item['거래금액']) {
const price = item['거래금액'].replace(/,/g, '').trim();
const priceNum = parseInt(price);
const priceText = priceNum >= 10000 ?
`${(priceNum / 10000).toFixed(1)}` :
`${priceNum.toLocaleString()}만원`;
html += `<div class="info-item">
<span class="label">거래금액</span>
<span class="value price">${priceText}</span>
</div>`;
}
// 보증금 (전세/월세)
if (item['보증금액']) {
const deposit = item['보증금액'].replace(/,/g, '').trim();
const depositNum = parseInt(deposit);
const depositText = depositNum >= 10000 ?
`${(depositNum / 10000).toFixed(1)}` :
`${depositNum.toLocaleString()}만원`;
html += `<div class="info-item">
<span class="label">보증금</span>
<span class="value">${depositText}</span>
</div>`;
}
// 월세
if (item['월세금액'] && item['월세금액'] !== '0') {
html += `<div class="info-item">
<span class="label">월세</span>
<span class="value">${item['월세금액']}만원</span>
</div>`;
}
// 면적
if (item['전용면적']) {
const area = parseFloat(item['전용면적']);
const pyeong = (area / 3.3).toFixed(1);
html += `<div class="info-item">
<span class="label">면적</span>
<span class="value">${area}㎡ (${pyeong}평)</span>
</div>`;
}
// 층
if (item['층']) {
html += `<div class="info-item">
<span class="label">층</span>
<span class="value">${item['층']}층</span>
</div>`;
}
// 거래일
if (item['년'] && item['월'] && item['일']) {
html += `<div class="info-item">
<span class="label">거래일</span>
<span class="value">${item['년']}.${item['월']}.${item['일']}</span>
</div>`;
}
// 건축년도
if (item['건축년도']) {
const age = new Date().getFullYear() - parseInt(item['건축년도']);
html += `<div class="info-item">
<span class="label">건축년도</span>
<span class="value">${item['건축년도']}년 (${age}년)</span>
</div>`;
}
// 주소
if (item['법정동'] && item['지번']) {
html += `<div class="info-item full-width">
<span class="label">주소</span>
<span class="value">${item['법정동']} ${item['지번']}</span>
</div>`;
}
html += '</div>';
html += '</div>';
return html;
}
// Enter 키로 검색
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('searchInput').addEventListener('keypress', function(e) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
parseQuery();
}
});
});