오늘 구현한 것, 칼로리 계산기 html, 그리고 챗 봇 fetch 오류 수정.
최종 수정된 fetch
<script>
const chatContainer = document.getElementById('chat-container');
const userInput = document.getElementById('user-input');
const categoryButtons = document.querySelectorAll('.category-btn');
// API URL (DRF의 엔드포인트 URL)
const apiUrl = '/api/chat/';
// 사용자 입력 핸들러
userInput.addEventListener('keypress', async (e) => {
if (e.key === 'Enter' && userInput.value.trim() !== '') {
const userMessage = userInput.value.trim();
appendMessage('user', userMessage); // 사용자 메시지 추가
userInput.value = '';
// 로딩 메시지 표시
appendMessage('bot', '검색 중입니다... 조금만 기다려 주세요');
// 서버로 메시지 전송 및 응답 처리
try {
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ message: userMessage }),
});
if (response.ok) {
const data = await response.json();
const botMessage = data.results || '답변을 불러오는 데 실패했습니다.';
updateLastBotMessage(botMessage); // 로딩 메시지 대체
} else {
updateLastBotMessage('서버 응답에 실패했습니다.');
}
} catch (error) {
updateLastBotMessage('오류가 발생했습니다. 나중에 다시 시도해 주세요.');
console.error('Error:', error);
}
}
});
// 카테고리 버튼 활성화 토글
categoryButtons.forEach(button => {
button.addEventListener('click', () => {
button.classList.toggle('active');
});
});
// 메시지 추가 함수 (appendMessage)
function appendMessage(sender, text) {
// Define the sender's side based on the input
const side = sender === 'user' ? 'right' : 'left';
// Construct the HTML for the message
const msgHTML = `
<div class="msg ${side}-msg">
<div class="msg-bubble">
<div class="msg-info">
<div class="msg-info-name">${sender === 'user' ? '사용자' : '봇'}</div>
<div class="msg-info-time">${formatDate(new Date())}</div>
</div>
<div class="msg-text">${text}</div>
</div>
</div>
`;
// Append the message to the chat container
chatContainer.insertAdjacentHTML('beforeend', msgHTML);
chatContainer.scrollTop = chatContainer.scrollHeight;
}
// 마지막 봇 메시지 업데이트 함수 (로딩 메시지 대체)
function updateLastBotMessage(text) {
const messages = chatContainer.querySelectorAll('.msg.left-msg');
if (messages.length > 0) {
messages[messages.length - 1].querySelector('.msg-text').textContent = text;
}
}
// 시간 포맷팅 함수
function formatDate(date) {
return `${date.getHours()}:${date.getMinutes().toString().padStart(2, '0')}`;
}
</script>
이전에 데이터를 부를 때, 즉 AI의 답변을 가져올 때, 이전의 대답을 그냥 덮어씌우는것을 발견하여
https://codepen.io/sajadhsm/pen/odaBdd
여기에 있는 JS 코드를 이용해 최종 목표 달성
칼로리 html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Food Intake Analyzer</title>
<style>
body {
margin: 0;
font-family: 'Arial', sans-serif;
display: flex;
height: 100vh;
color: #f8f9fa;
background: linear-gradient(to bottom, #1c1c1e, #2c2c2e);
}
.sidebar {
width: 30%;
background-color: #343a40;
padding: 20px;
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.3);
display: flex;
flex-direction: column;
gap: 15px;
}
.sidebar h2 {
color: #ffc107;
margin-bottom: 10px;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group input, .form-group select {
width: 100%;
padding: 10px;
font-size: 16px;
border: 1px solid #495057;
border-radius: 5px;
background-color: #2c2c2e;
color: #f8f9fa;
}
.form-group input:focus, .form-group select:focus {
outline: none;
border-color: #ffc107;
}
.submit-btn {
background-color: #ffc107;
border: none;
padding: 12px;
font-size: 18px;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.submit-btn:hover {
background-color: #ffcd39;
}
.results-panel {
flex: 1;
padding: 20px;
display: flex;
flex-direction: column;
gap: 20px;
}
.results-panel h2 {
color: #ffc107;
border-bottom: 2px solid #495057;
padding-bottom: 5px;
}
.result-box {
background-color: #495057;
padding: 15px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
}
.result-box p {
margin: 0;
}
</style>
</head>
<body>
<div class="sidebar">
<h2>Food Intake Form</h2>
<div class="form-group">
<label for="food">Food Name:</label>
<input type="text" id="food" placeholder="Enter food name">
</div>
<div class="form-group">
<label for="time">Time of Intake:</label>
<select id="time">
<option value="breakfast">Breakfast</option>
<option value="lunch">Lunch</option>
<option value="dinner">Dinner</option>
<option value="snack">Snack</option>
</select>
</div>
<div class="form-group">
<label for="age">Your Age:</label>
<input type="number" id="age" placeholder="Enter your age">
</div>
<div class="form-group">
<label for="diet">On a Diet?</label>
<select id="diet">
<option value="yes">Yes</option>
<option value="no">No</option>
</select>
</div>
<button class="submit-btn">Analyze</button>
</div>
<div class="results-panel">
<h2>Analysis Results</h2>
<div class="result-box">
<p><strong>Calories:</strong> 350 kcal</p>
<p><strong>Protein:</strong> 20 g</p>
<p><strong>Recommendations:</strong> Consider adding more fiber-rich foods for balance.</p>
</div>
<div class="result-box">
<p><strong>Time-Specific Benefit:</strong> Great choice for a post-workout meal!</p>
</div>
</div>
</body>
</html>
솔직히 미완성. 팀원의 미션을 감히 내가 어떻게 막으리.(사실 저의 파트가 아니기에 안 만들어도 되었던 부분...)