카테고리 없음

스파르타 AI-8기 TIL(1/14)-TeamProject

kimjunki-8 2025. 1. 14. 22:06

오늘 구현한 것, 칼로리 계산기 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>
솔직히 미완성. 팀원의 미션을 감히 내가 어떻게 막으리.(사실 저의 파트가 아니기에 안 만들어도 되었던 부분...)