| | <!DOCTYPE html> |
| | <html lang="en"> |
| |
|
| | <head> |
| | <meta charset="UTF-8"> |
| | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| | <title>Cropiee | Agricultural Intelligence</title> |
| | <link rel="preconnect" href="https://fonts.googleapis.com"> |
| | <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
| | <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet"> |
| | <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> |
| | <style> |
| | :root { |
| | |
| | --primary: #1a4d2e; |
| | --primary-light: #4f6f52; |
| | --accent: #ff9f1c; |
| | --bg-gradient: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%); |
| | --glass: rgba(255, 255, 255, 0.7); |
| | --glass-border: rgba(255, 255, 255, 0.3); |
| | --text-main: #1b4332; |
| | --text-muted: #52796f; |
| | --shadow: 0 12px 40px rgba(0, 0, 0, 0.08); |
| | --bot-bubble: #ffffff; |
| | --user-bubble: linear-gradient(135deg, #2d6a4f 0%, #1a4d2e 100%); |
| | --input-bg: #f8fbf8; |
| | } |
| | |
| | [data-theme="dark"] { |
| | |
| | --primary: #95d5b2; |
| | --primary-light: #74c69d; |
| | --accent: #ff9f1c; |
| | --bg-solid: #081c15; |
| | --bg-gradient: linear-gradient(135deg, #081c15 0%, #1b4332 100%); |
| | --glass: rgba(27, 67, 50, 0.95); |
| | --glass-border: rgba(255, 255, 255, 0.1); |
| | --text-main: #d8f3dc; |
| | --text-muted: #b7e4c7; |
| | --shadow: 0 12px 40px rgba(0, 0, 0, 0.6); |
| | --bot-bubble: #1b4332; |
| | --user-bubble: linear-gradient(135deg, #40916c 0%, #2d6a4f 100%); |
| | --input-bg: #081c15; |
| | } |
| | |
| | * { |
| | box-sizing: border-box; |
| | transition: background-color 0.3s, color 0.3s, border-color 0.3s; |
| | } |
| | |
| | body, |
| | html { |
| | min-height: 100vh; |
| | margin: 0; |
| | padding: 0; |
| | font-family: 'Outfit', sans-serif; |
| | background: var(--bg-solid, #e8f5e9); |
| | background: var(--bg-gradient); |
| | background-attachment: fixed; |
| | display: flex; |
| | justify-content: center; |
| | align-items: center; |
| | overflow-x: hidden; |
| | width: 100vw; |
| | } |
| | |
| | #particles-js { |
| | position: fixed; |
| | width: 100%; |
| | height: 100%; |
| | z-index: -1; |
| | top: 0; |
| | left: 0; |
| | } |
| | |
| | .dashboard { |
| | display: flex; |
| | width: 95%; |
| | max-width: 1200px; |
| | height: 90vh; |
| | gap: 20px; |
| | margin: 20px; |
| | animation: fadeIn 0.8s ease; |
| | } |
| | |
| | @keyframes fadeIn { |
| | from { |
| | opacity: 0; |
| | transform: translateY(20px); |
| | } |
| | |
| | to { |
| | opacity: 1; |
| | transform: translateY(0); |
| | } |
| | } |
| | |
| | #chat-container { |
| | flex: 1; |
| | display: flex; |
| | flex-direction: column; |
| | background: var(--glass); |
| | backdrop-filter: blur(20px); |
| | -webkit-backdrop-filter: blur(20px); |
| | border-radius: 32px; |
| | box-shadow: var(--shadow); |
| | border: 1px solid var(--glass-border); |
| | overflow: hidden; |
| | position: relative; |
| | } |
| | |
| | .visual-panel { |
| | flex: 1.2; |
| | display: flex; |
| | flex-direction: column; |
| | justify-content: center; |
| | align-items: center; |
| | position: relative; |
| | background: transparent; |
| | } |
| | |
| | .visual-panel h2 { |
| | color: var(--primary); |
| | font-size: 2.2rem; |
| | margin-bottom: 20px; |
| | text-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); |
| | font-weight: 700; |
| | } |
| | |
| | .agri-core { |
| | width: 400px; |
| | height: 400px; |
| | position: relative; |
| | display: flex; |
| | justify-content: center; |
| | align-items: center; |
| | } |
| | |
| | .orbit { |
| | position: absolute; |
| | border-radius: 50%; |
| | border: 1px solid rgba(149, 213, 178, 0.2); |
| | animation: rotateOrbit linear infinite; |
| | } |
| | |
| | .orbit-1 { |
| | width: 300px; |
| | height: 300px; |
| | animation-duration: 15s; |
| | } |
| | |
| | .orbit-2 { |
| | width: 220px; |
| | height: 220px; |
| | animation-duration: 20s; |
| | animation-direction: reverse; |
| | } |
| | |
| | @keyframes rotateOrbit { |
| | from { |
| | transform: rotate(0deg); |
| | } |
| | |
| | to { |
| | transform: rotate(360deg); |
| | } |
| | } |
| | |
| | .node { |
| | position: absolute; |
| | width: 12px; |
| | height: 12px; |
| | background: var(--accent); |
| | border-radius: 50%; |
| | box-shadow: 0 0 15px var(--accent); |
| | } |
| | |
| | .plant-container { |
| | width: 180px; |
| | height: 180px; |
| | background: rgba(45, 106, 79, 0.1); |
| | border-radius: 50%; |
| | display: flex; |
| | justify-content: center; |
| | align-items: center; |
| | border: 2px solid rgba(45, 106, 79, 0.2); |
| | position: relative; |
| | overflow: hidden; |
| | backdrop-filter: blur(5px); |
| | } |
| | |
| | .scanning-beam { |
| | position: absolute; |
| | width: 100%; |
| | height: 60px; |
| | background: linear-gradient(to bottom, transparent, rgba(255, 159, 28, 0.4), transparent); |
| | animation: scanLoop 3s ease-in-out infinite; |
| | z-index: 2; |
| | } |
| | |
| | @keyframes scanLoop { |
| | |
| | 0%, |
| | 100% { |
| | transform: translateY(-100px); |
| | } |
| | |
| | 50% { |
| | transform: translateY(100px); |
| | } |
| | } |
| | |
| | #chat-header { |
| | padding: 20px 30px; |
| | display: flex; |
| | align-items: center; |
| | justify-content: space-between; |
| | border-bottom: 1px solid rgba(255, 255, 255, 0.1); |
| | } |
| | |
| | .bot-avatar { |
| | width: 48px; |
| | height: 48px; |
| | background: var(--primary); |
| | border-radius: 12px; |
| | display: flex; |
| | align-items: center; |
| | justify-content: center; |
| | color: #ffffff; |
| | } |
| | |
| | [data-theme="dark"] .bot-avatar { |
| | color: #081c15; |
| | } |
| | |
| | #chat-box { |
| | flex: 1; |
| | padding: 25px; |
| | overflow-y: auto; |
| | scroll-behavior: smooth; |
| | } |
| | |
| | .msg-wrapper { |
| | margin-bottom: 20px; |
| | display: flex; |
| | flex-direction: column; |
| | } |
| | |
| | .user-wrapper { |
| | align-items: flex-end; |
| | } |
| | |
| | .bot-wrapper { |
| | align-items: flex-start; |
| | } |
| | |
| | .user-bubble { |
| | background: var(--user-bubble); |
| | color: white; |
| | border-radius: 20px 20px 4px 20px; |
| | padding: 12px 18px; |
| | box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05); |
| | } |
| | |
| | .bot-bubble { |
| | background: var(--bot-bubble); |
| | color: var(--text-main); |
| | border-radius: 20px 20px 20px 4px; |
| | padding: 12px 18px; |
| | border: 1px solid var(--glass-border); |
| | line-height: 1.5; |
| | } |
| | |
| | .chart-container { |
| | width: 100%; |
| | max-width: 250px; |
| | margin-top: 10px; |
| | background: rgba(255, 255, 255, 0.05); |
| | border-radius: 12px; |
| | padding: 10px; |
| | } |
| | |
| | #input-container { |
| | padding: 20px; |
| | background: var(--bot-bubble); |
| | display: flex; |
| | gap: 15px; |
| | border-top: 1px solid var(--glass-border); |
| | } |
| | |
| | #user-input { |
| | flex: 1; |
| | padding: 14px 20px; |
| | background: var(--input-bg); |
| | border: 1px solid var(--glass-border); |
| | border-radius: 12px; |
| | outline: none; |
| | font-size: 0.95rem; |
| | color: var(--text-main); |
| | } |
| | |
| | #send-btn { |
| | width: 50px; |
| | height: 50px; |
| | background: var(--primary); |
| | border: none; |
| | border-radius: 12px; |
| | color: #ffffff; |
| | cursor: pointer; |
| | display: flex; |
| | align-items: center; |
| | justify-content: center; |
| | } |
| | |
| | [data-theme="dark"] #send-btn { |
| | color: #081c15; |
| | } |
| | |
| | .suggestion-chip { |
| | padding: 8px 16px; |
| | background: var(--bot-bubble); |
| | border: 1px solid var(--glass-border); |
| | border-radius: 20px; |
| | font-size: 0.85rem; |
| | cursor: pointer; |
| | color: var(--text-main); |
| | transition: 0.2s; |
| | white-space: nowrap; |
| | } |
| | |
| | .suggestion-chip:hover { |
| | background: var(--primary); |
| | color: #ffffff; |
| | } |
| | |
| | .suggestions { |
| | padding: 0 25px 15px; |
| | display: flex; |
| | flex-wrap: wrap; |
| | gap: 10px; |
| | overflow-x: auto; |
| | scrollbar-width: none; |
| | } |
| | |
| | |
| | #onboarding { |
| | position: absolute; |
| | top: 0; |
| | left: 0; |
| | width: 100%; |
| | height: 100%; |
| | background: rgba(0, 0, 0, 0.6); |
| | z-index: 100; |
| | display: none; |
| | flex-direction: column; |
| | justify-content: center; |
| | align-items: center; |
| | border-radius: 32px; |
| | backdrop-filter: blur(4px); |
| | } |
| | |
| | .onboarding-card { |
| | background: var(--bot-bubble); |
| | padding: 30px; |
| | border-radius: 24px; |
| | max-width: 80%; |
| | text-align: center; |
| | color: var(--text-main); |
| | box-shadow: var(--shadow); |
| | position: relative; |
| | } |
| | |
| | .onboarding-card h3 { |
| | margin: 0 0 15px; |
| | color: var(--primary); |
| | } |
| | |
| | .onboarding-btn { |
| | background: var(--primary); |
| | color: #ffffff; |
| | border: none; |
| | padding: 10px 20px; |
| | border-radius: 10px; |
| | cursor: pointer; |
| | margin-top: 20px; |
| | font-weight: 600; |
| | } |
| | |
| | |
| | .theme-toggle { |
| | padding: 8px; |
| | border-radius: 10px; |
| | background: var(--glass-border); |
| | cursor: pointer; |
| | display: flex; |
| | gap: 5px; |
| | align-items: center; |
| | } |
| | |
| | @media (max-width: 992px) { |
| | .visual-panel { |
| | display: none; |
| | } |
| | |
| | .dashboard { |
| | max-width: 520px; |
| | } |
| | } |
| | |
| | @media (max-width: 480px) { |
| | .dashboard { |
| | width: 100%; |
| | height: 100vh; |
| | margin: 0; |
| | border-radius: 0; |
| | } |
| | |
| | #chat-container { |
| | border-radius: 0; |
| | } |
| | } |
| | </style> |
| | </head> |
| |
|
| | <body data-theme="light"> |
| | <div id="particles-js"></div> |
| |
|
| | <div class="dashboard"> |
| | <div id="chat-container"> |
| | |
| | <div id="onboarding"> |
| | <div class="onboarding-card"> |
| | <h3 id="ob-title">Welcome to Cropiee!</h3> |
| | <p id="ob-text">I'm your AI agriculture assistant. Let's get started on your farming journey.</p> |
| | <button class="onboarding-btn" onclick="nextOb()">Next Step</button> |
| | <div style="margin-top:10px; font-size: 0.8rem; opacity: 0.7;" id="ob-count">1 / 3</div> |
| | </div> |
| | </div> |
| |
|
| | <div id="chat-header"> |
| | <div style="display: flex; align-items: center; gap: 12px;"> |
| | <div class="bot-avatar"> |
| | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" |
| | stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"> |
| | <rect x="5" y="10" width="14" height="10" rx="3"></rect> |
| | <circle cx="9" cy="14" r="1.2" fill="currentColor"></circle> |
| | <circle cx="15" cy="14" r="1.2" fill="currentColor"></circle> |
| | <path d="M10 17h4"></path> |
| | <path d="M12 10V7"></path> |
| | <path d="M12 7c1.5-1.5 2.5-1.5 2.5-3s-1-1.5-2.5 0"></path> |
| | <path d="M12 7c-1.5-1.5-2.5-1.5-2.5-3s1-1.5 2.5 0"></path> |
| | </svg> |
| | </div> |
| | <div> |
| | <h1 style="margin:0; font-size:1.1rem; font-weight:700; color:var(--text-main)">Cropiee</h1> |
| | </div> |
| | </div> |
| | <div style="display: flex; gap: 10px; align-items: center;"> |
| | <button class="theme-toggle" |
| | style="border:none; color:inherit; font-weight:600; font-family:inherit; font-size: 0.9rem;" |
| | onclick="showOnboarding()"> |
| | ❓ Guide |
| | </button> |
| | <div class="theme-toggle" onclick="toggleTheme()" title="Toggle Dark Mode"> |
| | <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" |
| | stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| | <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path> |
| | </svg> |
| | </div> |
| | </div> |
| | </div> |
| |
|
| | <div id="chat-box"></div> |
| |
|
| | <div class="suggestions"> |
| | <div class="suggestion-chip" onclick="quickSend('Suggest a crop')">🌿 Recommend</div> |
| | <div class="suggestion-chip" onclick="quickSend('Soil analysis')">🌱 Soil Advice</div> |
| | </div> |
| |
|
| | <div id="input-container"> |
| | <input type="text" id="user-input" placeholder="Cultivate a query..." autocomplete="off"> |
| | <button id="send-btn" onclick="sendMessage()"> |
| | <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" |
| | stroke-linecap="round" stroke-linejoin="round"> |
| | <line x1="22" y1="2" x2="11" y2="13"></line> |
| | <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon> |
| | </svg> |
| | </button> |
| | </div> |
| | </div> |
| |
|
| | <div class="visual-panel"> |
| | <h2>Hybrid AI Analytics</h2> |
| | <div class="agri-core"> |
| | <div class="orbit orbit-1"> |
| | <div class="node" style="top:0; left:50%; transform:translateX(-50%)"></div> |
| | <div class="node" style="bottom:0; left:50%; transform:translateX(-50%)"></div> |
| | </div> |
| | <div class="orbit orbit-2"> |
| | <div class="node" style="left:0; top:50%; transform:translateY(-50%)"></div> |
| | <div class="node" style="right:0; top:50%; transform:translateY(-50%)"></div> |
| | </div> |
| | <div class="plant-container"> |
| | <div class="scanning-beam"></div> |
| | <svg width="100" height="100" viewBox="0 0 24 24" fill="none" stroke="var(--primary)" |
| | stroke-width="1.8"> |
| | <path |
| | d="M7 20l3-3 3 3m-3-3V10m0 0a4 4 0 0 1 4-4c1.5 0 3 .5 3 2s-1.5 2-3 2a4 4 0 0 1-4 4zm0-6a4 4 0 0 0-4-4c-1.5 0-3 .5-3 2s1.5 2 3 2a4 4 0 0 0 4 4z"> |
| | </path> |
| | </svg> |
| | </div> |
| | </div> |
| | <div style="margin-top:40px; text-align:center; color: var(--text-muted); font-size: 0.9rem;"> |
| | <span id="stat-text" style="color:var(--primary); font-weight:600;">Processing Agro-Neural |
| | Data...</span> |
| | </div> |
| | </div> |
| | </div> |
| |
|
| | <script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script> |
| | <script> |
| | |
| | function toggleTheme() { |
| | const body = document.body; |
| | const current = body.getAttribute('data-theme'); |
| | const target = current === 'light' ? 'dark' : 'light'; |
| | body.setAttribute('data-theme', target); |
| | localStorage.setItem('cropiee-theme', target); |
| | updateChartThemes(); |
| | } |
| | |
| | |
| | const obData = [ |
| | { title: "Smart Recommendations 🌿", text: "Ask me 'What can I grow in Delhi?' and I'll use real-time weather and ML models to suggest the best crop." }, |
| | { title: "Soil Analysis 🌱", text: "Type 'soil for rice' to get precise chemical requirement charts for your favorite crops." }, |
| | { title: "Market Insights 📊", text: "I fetch current mandi prices to tell you the profit potential of your farm." } |
| | ]; |
| | let obIdx = 0; |
| | function showOnboarding() { document.getElementById('onboarding').style.display = 'flex'; obIdx = 0; updateOb(); } |
| | function nextOb() { |
| | obIdx++; |
| | if (obIdx >= obData.length) { document.getElementById('onboarding').style.display = 'none'; return; } |
| | updateOb(); |
| | } |
| | function updateOb() { |
| | document.getElementById('ob-title').innerText = obData[obIdx].title; |
| | document.getElementById('ob-text').innerText = obData[obIdx].text; |
| | document.getElementById('ob-count').innerText = `${obIdx + 1} / 3`; |
| | } |
| | |
| | |
| | particlesJS('particles-js', { |
| | "particles": { "number": { "value": 40 }, "color": { "value": "#2d6a4f" }, "shape": { "type": "circle" }, "opacity": { "value": 0.3 }, "size": { "value": 3 }, "line_linked": { "enable": true, "distance": 150, "color": "#2d6a4f", "opacity": 0.2, "width": 1 }, "move": { "enable": true, "speed": 1.5 } } |
| | }); |
| | |
| | |
| | const chatBox = document.getElementById('chat-box'); |
| | const userInput = document.getElementById('user-input'); |
| | const charts = []; |
| | |
| | function updateChartThemes() { |
| | const isDark = document.body.getAttribute('data-theme') === 'dark'; |
| | const color = isDark ? '#d8f3dc' : '#1b4332'; |
| | charts.forEach(c => { |
| | c.options.scales.r.grid.color = isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.05)'; |
| | c.options.scales.r.pointLabels.color = color; |
| | c.update(); |
| | }); |
| | } |
| | |
| | function createChart(canvasId, labels, values, labelTitle) { |
| | const ctx = document.getElementById(canvasId).getContext('2d'); |
| | const isDark = document.body.getAttribute('data-theme') === 'dark'; |
| | const primary = isDark ? '#95d5b2' : '#1a4d2e'; |
| | |
| | const newChart = new Chart(ctx, { |
| | type: 'radar', |
| | data: { |
| | labels: labels, |
| | datasets: [{ |
| | label: labelTitle, |
| | data: values, |
| | backgroundColor: isDark ? 'rgba(149, 213, 178, 0.3)' : 'rgba(26, 77, 46, 0.3)', |
| | borderColor: primary, |
| | borderWidth: 2, |
| | pointBackgroundColor: primary |
| | }] |
| | }, |
| | options: { |
| | scales: { |
| | r: { |
| | angleLines: { color: isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.05)' }, |
| | grid: { color: isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.05)' }, |
| | pointLabels: { color: isDark ? '#d8f3dc' : '#1b4332', font: { size: 10 } }, |
| | ticks: { display: false } |
| | } |
| | }, |
| | plugins: { legend: { display: false } } |
| | } |
| | }); |
| | charts.push(newChart); |
| | } |
| | |
| | function addMessage(text, isUser = false, chartData = null) { |
| | const wrapper = document.createElement('div'); |
| | wrapper.className = `msg-wrapper ${isUser ? 'user-wrapper' : 'bot-wrapper'}`; |
| | |
| | const bubble = document.createElement('div'); |
| | bubble.className = `msg-bubble ${isUser ? 'user-bubble' : 'bot-bubble'}`; |
| | bubble.innerHTML = text; |
| | |
| | wrapper.appendChild(bubble); |
| | |
| | if (chartData) { |
| | const chartDiv = document.createElement('div'); |
| | chartDiv.className = 'chart-container'; |
| | const canvasId = 'chart-' + Date.now(); |
| | chartDiv.innerHTML = `<canvas id="${canvasId}"></canvas>`; |
| | bubble.appendChild(chartDiv); |
| | |
| | setTimeout(() => { |
| | createChart(canvasId, chartData.labels, chartData.values, isUser ? "Your Input" : "Ideal soil Readings"); |
| | }, 100); |
| | } |
| | |
| | chatBox.appendChild(wrapper); |
| | chatBox.scrollTo({ top: chatBox.scrollHeight, behavior: 'smooth' }); |
| | } |
| | |
| | async function sendMessage() { |
| | const text = userInput.value.trim(); |
| | if (!text) return; |
| | userInput.value = ''; |
| | addMessage(text, true); |
| | |
| | try { |
| | let response = await fetch('/chatbot', { |
| | method: 'POST', |
| | headers: { 'Content-Type': 'application/json' }, |
| | body: JSON.stringify({ message: text }) |
| | }); |
| | const data = await response.json(); |
| | addMessage(data.reply, false, data.chart); |
| | } catch (e) { |
| | addMessage("I'm momentarily offline. 🌿"); |
| | } |
| | } |
| | |
| | userInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') sendMessage(); }); |
| | function quickSend(v) { userInput.value = v; sendMessage(); } |
| | |
| | window.onload = () => { |
| | const saved = localStorage.getItem('cropiee-theme'); |
| | if (saved) document.body.setAttribute('data-theme', saved); |
| | |
| | addMessage("Hello! I'm <b>Cropiee</b>. 😊\nWelcome to your intelligent agricultural dashboard."); |
| | |
| | |
| | if (!localStorage.getItem('ob-seen')) { |
| | showOnboarding(); |
| | localStorage.setItem('ob-seen', 'true'); |
| | } |
| | } |
| | |
| | |
| | const statText = document.getElementById('stat-text'); |
| | const states = ["Analyzing N-P-K Levels...", "Syncing IoT Sensor Data...", "Predicting Hybrid Yields...", "Matching Mandi Price API..."]; |
| | let sIdx = 0; |
| | setInterval(() => { |
| | statText.innerText = states[sIdx]; |
| | sIdx = (sIdx + 1) % states.length; |
| | }, 4000); |
| | </script> |
| | </body> |
| |
|
| | </html> |