pranit144's picture
Update templates/index2.html
ed2a37c verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Soil Report Analysis & Recommendations Generator</title>
<!-- Include Chart.js library -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
:root {
--primary-color: #007BFF;
--primary-dark: #0056b3;
--secondary-color: #2c5282;
--bg-color: #f4f4f4;
--text-color: #333;
--white: #ffffff;
--error-bg: #f8d7da;
--error-text: #721c24;
--container-bg: #ffffff;
--shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
/* Distinct section background colors */
--section-bg-overview: #e0f7fa;
--section-bg-composition: #ffe0b2;
--section-bg-nutrients: #c8e6c9;
--section-bg-ph: #f3e5f5;
--section-bg-recommendations: #d1c4e9;
}
/* Base Styles */
body {
font-family: 'Roboto', sans-serif;
background-color: var(--bg-color);
margin: 0;
padding: 0;
color: var(--text-color);
}
.container {
max-width: 900px;
margin: 50px auto;
background: var(--container-bg);
padding: 30px;
border-radius: 10px;
box-shadow: var(--shadow);
}
/* Title and Header */
.main-title {
font-size: 2.5rem;
text-align: center;
margin-bottom: 30px;
display: flex;
align-items: center;
justify-content: center;
color: var(--secondary-color);
}
.title-icon {
font-size: 2.5rem;
margin-right: 10px;
}
/* Upload Section */
.upload-section {
background: var(--white);
padding: 25px;
border-radius: 10px;
margin-bottom: 30px;
box-shadow: var(--shadow);
}
.upload-section h2 {
text-align: center;
margin-bottom: 20px;
color: var(--secondary-color);
}
.file-input-container {
border: 2px dashed #cbd5e1;
padding: 30px;
border-radius: 10px;
text-align: center;
transition: border-color 0.3s ease;
cursor: pointer;
}
.file-input-container:hover {
border-color: var(--primary-color);
}
/* Button Styles */
button,
.upload-button {
background-color: var(--primary-color);
color: var(--white);
padding: 12px 24px;
border: none;
border-radius: 5px;
font-size: 1rem;
cursor: pointer;
display: block;
width: 100%;
transition: background-color 0.3s ease;
margin-top: 20px;
}
.upload-button:hover {
background-color: var(--primary-dark);
}
/* Loading Spinner */
.loading {
text-align: center;
margin: 20px 0;
}
.loading-spinner {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid var(--primary-color);
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 20px auto;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
/* Flash Messages */
.flash-message {
background-color: var(--error-bg);
color: var(--error-text);
padding: 10px 15px;
border-radius: 5px;
margin-bottom: 20px;
text-align: center;
}
/* Markdown Content Styling */
.markdown-body {
background-color: var(--white);
padding: 30px;
border-radius: 8px;
border: 1px solid #e1e4e8;
margin-top: 20px;
line-height: 1.6;
}
/* Section Heading Styles with distinct colors */
.markdown-body h1 {
background-color: var(--section-bg-overview);
padding: 10px;
border-radius: 5px;
font-size: 2em; /* Default for larger screens */
margin-bottom: 15px;
}
.markdown-body h2 { /* Apply to all H2s initially */
padding: 8px;
border-radius: 5px;
margin-top: 20px;
margin-bottom: 10px;
font-size: 1.5em; /* Default for larger screens */
}
.markdown-body h2:nth-of-type(1) {
background-color: var(--section-bg-overview);
}
.markdown-body h2:nth-of-type(2) {
background-color: var(--section-bg-composition);
}
.markdown-body h2:nth-of-type(3) {
background-color: var(--section-bg-nutrients);
}
.markdown-body h2:nth-of-type(4) {
background-color: var(--section-bg-ph);
}
.markdown-body h2:nth-of-type(5) {
background-color: var(--section-bg-recommendations);
}
/* Chart Container */
#chartContainer {
margin-top: 20px;
padding: 20px;
background-color: #f9f9f9;
border: 1px solid #ddd;
border-radius: 5px;
display: none; /* Initially hidden until chart code is executed */
}
/* Ensure canvas fills the container */
#chartContainer canvas {
max-width: 100%;
height: auto; /* Maintain aspect ratio */
}
/* --- Responsive Adjustments --- */
/* For tablets and smaller desktops (up to 768px wide) */
@media (max-width: 768px) {
.container {
margin: 20px;
padding: 20px;
}
.main-title {
font-size: 2rem;
margin-bottom: 25px;
}
.title-icon {
font-size: 2rem;
}
.upload-section {
padding: 20px;
margin-bottom: 25px;
}
.file-input-container {
padding: 25px;
}
.upload-button {
font-size: 0.95rem;
padding: 10px 20px;
margin-top: 15px;
}
.markdown-body {
padding: 20px;
}
.markdown-body h1 {
font-size: 1.8em;
}
.markdown-body h2 {
font-size: 1.3em;
margin-top: 15px;
}
#chartContainer {
padding: 15px;
}
}
/* For mobile phones (up to 480px wide) */
@media (max-width: 480px) {
.container {
margin: 15px;
padding: 15px;
}
.main-title {
font-size: 1.6rem;
margin-bottom: 20px;
text-align: center; /* Ensure centering even if icon is present */
flex-direction: column; /* Stack icon and text */
gap: 5px;
}
.title-icon {
font-size: 1.8rem;
margin-right: 0; /* Remove right margin when stacked */
}
.upload-section {
padding: 15px;
margin-bottom: 20px;
}
.file-input-container {
padding: 20px;
font-size: 0.9rem;
}
.upload-button {
font-size: 0.9rem;
padding: 10px 15px;
margin-top: 15px;
}
.flash-message {
padding: 8px 10px;
font-size: 0.9rem;
}
.loading p {
font-size: 0.9rem;
}
.loading-spinner {
width: 30px;
height: 30px;
border-width: 3px;
}
.markdown-body {
padding: 15px;
}
.markdown-body h1 {
font-size: 1.5em;
padding: 8px;
margin-bottom: 10px;
}
.markdown-body h2 {
font-size: 1.2em;
padding: 6px;
margin-top: 12px;
margin-bottom: 8px;
}
#chartContainer {
padding: 10px;
}
}
</style>
</head>
<body>
<div class="container">
<h1 class="main-title">
<span class="title-icon">🌱</span>
Soil Report Analysis & Recommendations Generator
</h1>
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="flash-message">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
<div class="upload-section">
<h2>Upload Soil Reports</h2>
<form id="uploadForm">
<div class="file-input-container">
<input type="file" name="files" accept=".pdf,.jpg,.jpeg,.png" multiple required>
<p>Drag & drop your soil reports here or click to select</p>
</div>
<button type="submit" class="upload-button">Generate Soil Analysis & Recommendations</button>
</form>
</div>
<div class="loading" id="loading" style="display:none;">
<div class="loading-spinner"></div>
<p>Analyzing soil reports and generating analysis...</p>
</div>
<div id="summaryContainer" class="markdown-body" style="display: none;"></div>
<!-- Chart Container with a canvas element -->
<div id="chartContainer">
<!-- The chart image will be inserted here by JavaScript -->
</div>
</div>
<script>
document.getElementById('uploadForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
const loading = document.getElementById('loading');
const summaryContainer = document.getElementById('summaryContainer');
const chartContainer = document.getElementById('chartContainer');
loading.style.display = 'block';
summaryContainer.style.display = 'none';
chartContainer.style.display = 'none'; // Ensure chart is hidden on new submission
fetch('/', { method: 'POST', body: formData })
.then(response => response.json())
.then(data => {
loading.style.display = 'none';
summaryContainer.style.display = 'block';
if (data.error) {
summaryContainer.innerHTML = `<div class="flash-message">${data.error}</div>`;
} else {
summaryContainer.innerHTML = data.html_summary;
if (data.chart_img) {
chartContainer.style.display = 'block';
chartContainer.innerHTML = `<img src="${data.chart_img}" alt="Nutrient Chart" style="max-width:100%; height:auto;"/>`;
} else {
chartContainer.style.display = 'none'; // Hide if no chart data
}
}
})
.catch(error => {
loading.style.display = 'none';
summaryContainer.style.display = 'block';
summaryContainer.innerHTML = `<div class="flash-message">Error: An unexpected error occurred. Please try again.</div>`;
console.error('Fetch error:', error);
});
});
// Drag and drop functionality
const fileInput = document.querySelector('input[type="file"]');
const dropZone = document.querySelector('.file-input-container');
// Prevent default drag behaviors
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropZone.addEventListener(eventName, preventDefaults, false);
document.body.addEventListener(eventName, preventDefaults, false); // Prevent drop anywhere on body
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
// Highlight drop zone when dragging over
['dragenter', 'dragover'].forEach(eventName => {
dropZone.addEventListener(eventName, highlight, false);
});
// Remove highlight when dragging leaves or drops
['dragleave', 'drop'].forEach(eventName => {
dropZone.addEventListener(eventName, unhighlight, false);
});
function highlight(e) {
dropZone.style.borderColor = '#3b82f6';
dropZone.style.backgroundColor = 'rgba(0, 123, 255, 0.05)'; /* Light blue overlay */
}
function unhighlight(e) {
dropZone.style.borderColor = '#cbd5e1';
dropZone.style.backgroundColor = ''; /* Reset background */
}
// Handle dropped files
dropZone.addEventListener('drop', handleDrop, false);
function handleDrop(e) {
const dt = e.dataTransfer;
const files = dt.files;
fileInput.files = files; // Assign files to the input element
// Optionally, display selected file names
if (files.length > 0) {
let fileNames = Array.from(files).map(f => f.name).join(', ');
dropZone.querySelector('p').textContent = `Selected: ${fileNames}`;
}
}
// Handle explicit file input change (when user clicks and selects)
fileInput.addEventListener('change', function() {
if (this.files.length > 0) {
let fileNames = Array.from(this.files).map(f => f.name).join(', ');
dropZone.querySelector('p').textContent = `Selected: ${fileNames}`;
} else {
dropZone.querySelector('p').textContent = `Drag & drop your soil reports here or click to select`;
}
});
</script>
</body>
</html>