teja141290's picture
Initial commit: restore working version for Hugging Face Space
cca62d0
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Car Damage Detection</title>
<link rel="stylesheet" href="/static/css/style.css">
<script>
function copyJSON() {
const pre = document.getElementById('json-pre');
if (pre) {
navigator.clipboard.writeText(pre.innerText);
alert('JSON copied to clipboard!');
}
}
function toggleJSON() {
const block = document.getElementById('json-block');
const btn = document.getElementById('toggle-json-btn');
if (block.style.display === 'none') {
block.style.display = 'block';
btn.innerText = 'Hide JSON';
} else {
block.style.display = 'none';
btn.innerText = 'Show JSON';
}
}
// Add new toggle function for LLM analysis
function toggleLLM() {
const block = document.getElementById('llm-block');
const btn = document.getElementById('toggle-llm-btn');
if (block.style.display === 'none') {
block.style.display = 'block';
btn.innerText = 'Hide Analysis';
} else {
block.style.display = 'none';
btn.innerText = 'Show Analysis';
}
}
function toggleBlock(blockId, btnId) {
const block = document.getElementById(blockId);
const btn = document.getElementById(btnId);
if (block.style.display === 'none' || !block.style.display) {
block.style.display = 'block';
btn.innerText = `Hide ${btnId.includes('json') ? 'JSON' : 'Analysis'}`;
} else {
block.style.display = 'none';
btn.innerText = `Show ${btnId.includes('json') ? 'JSON' : 'Analysis'}`;
}
}
</script>
<style>
/* Add new LLM analysis styles */
.llm-section {
margin-top: 20px;
padding: 15px;
background: #f8f9fa;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.llm-content {
width: 100%;
max-width: 800px;
margin: 10px auto;
display: none;
}
.llm-content pre {
white-space: pre-wrap;
word-wrap: break-word;
background: white;
padding: 15px;
border-radius: 4px;
border: 1px solid #dee2e6;
}
.toggle-llm-btn {
background-color: #007bff;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
margin: 10px 0;
}
.toggle-llm-btn:hover {
background-color: #0056b3;
}
.warning {
background-color: #fff3cd;
color: #856404;
padding: 1rem;
margin: 1rem 0;
border: 1px solid #ffeeba;
border-radius: 4px;
}
.llm-analysis {
margin-top: 2rem;
background: white; /* White background */
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
overflow: hidden;
transition: all 0.3s ease;
}
.analysis-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1.5rem;
background: linear-gradient(135deg, #805ad5 0%, #6b46c1 100%); /* Keep purple gradient header */
color: white;
}
.analysis-header h3 {
margin: 0;
font-size: 1.5rem;
display: flex;
align-items: center;
gap: 10px;
color: white;
}
.toggle-btn {
display: flex;
align-items: center;
gap: 8px;
background: rgba(255, 255, 255, 0.15);
color: white;
border: 1px solid rgba(255, 255, 255, 0.2);
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s ease;
}
.toggle-btn:hover {
background: rgba(255, 255, 255, 0.25);
}
.toggle-btn i {
transition: transform 0.3s ease;
}
.toggle-btn.active i {
transform: rotate(180deg);
}
.analysis-content {
padding: 1.5rem;
background: white;
color: #2d3748; /* Dark gray text */
}
.damage-grid {
display: grid;
gap: 1.5rem;
grid-template-columns: 1fr;
}
@media (min-width: 1024px) {
.damage-grid {
grid-template-columns: 3fr 2fr;
}
}
.table-container {
overflow-x: auto;
background: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.damage-table {
width: 100%;
border-collapse: collapse;
margin: 0;
font-size: 0.95rem;
color: #2d3748;
}
.damage-table th, .damage-table td {
padding: 12px 16px;
text-align: left;
border-bottom: 1px solid #e2e8f0;
}
.damage-table th {
background: #f7fafc;
font-weight: 600;
color: #4a5568;
text-transform: uppercase;
font-size: 0.85rem;
letter-spacing: 0.05em;
}
.damage-table tr:last-child td {
border-bottom: none;
}
.damage-table tbody tr {
transition: background-color 0.2s ease;
}
.damage-table tbody tr:hover {
background-color: #f7fafc;
}
.summary-section {
background: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
padding: 1.5rem;
}
.summary-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 1rem;
color: #4a5568;
}
.summary-header h4 {
margin: 0;
font-size: 1.2rem;
color: #2d3748;
}
.summary-content {
color: #4a5568;
line-height: 1.6;
}
.summary-content p {
margin: 0 0 1rem;
}
.summary-content p:last-child {
margin-bottom: 0;
}
/* Updated Severity colors for light background */
.severity-high {
color: #e53e3e; /* Red */
}
.severity-medium {
color: #d69e2e; /* Yellow */
}
.severity-low {
color: #38a169; /* Green */
}
/* Animation for content */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
.analysis-content.show {
animation: fadeIn 0.3s ease-out forwards;
}
</style>
</head>
<body>
<div class="header" style="position:relative;">
<h2 style="margin:0;">Car Damage & Parts Detection</h2>
<img src="/static/img/logo.jpg" alt="Logo" class="logo" style="position:absolute; top:18px; right:32px; max-width:110px;">
</div>
<div class="container">
<form method="post" action="/upload" enctype="multipart/form-data">
<input type="file" name="file" accept="image/*" required>
<button type="submit">Upload & Analyze</button>
</form>
{% if error %}<div class="error">{{ error }}</div>{% endif %}
{% if result %}
<div class="results">
<h3>Results</h3>
<div class="images-row">
<div>
<div class="result-label">Original</div>
<img src="{{ original_image }}" alt="Original Image" class="result-img">
</div>
{% if result.parts_image %}
<div>
<div class="result-label">Parts Prediction</div>
<img src="{{ result.parts_image }}" alt="Parts Prediction" class="result-img">
</div>
{% endif %}
</div>
{% if result.warning %}
<div class="warning">{{ result.warning }}</div>
{% endif %}
{% if result.json %}
<h4 style="margin-bottom:8px;">JSON Output</h4>
<button class="copy-btn" onclick="copyJSON()">Copy JSON</button>
<button class="toggle-btn" id="toggle-json-btn" onclick="toggleBlock('json-block', 'toggle-json-btn')">Show JSON</button>
<div id="json-block" style="display:none;">
<pre class="json-output" id="json-pre">{{ result.json | tojson(indent=2) }}</pre>
</div>
<a class="download-btn" href="{{ result.json_download }}" download>Download JSON</a>
{% endif %}
{% if result.parts_image %}
<a class="download-btn" href="{{ result.parts_image }}" download>Download Parts Image</a>
{% endif %}
{% if result.llm_analysis %}
<div class="llm-analysis">
<div class="analysis-header">
<h3><i class="fas fa-robot"></i> AI Damage Assessment Report</h3>
<button class="toggle-btn" id="toggle-analysis-btn" onclick="toggleBlock('analysis-block', 'toggle-analysis-btn')">
<span class="btn-text">Show Analysis</span>
<i class="fas fa-chevron-down"></i>
</button>
</div>
<div id="analysis-block" class="analysis-content" style="display:none;">
<div class="damage-grid">
<div class="table-container">
<table class="damage-table">
<thead>
<tr>
<th>Component</th>
<th>Status</th>
<th>Severity</th>
<th>Action Needed</th>
</tr>
</thead>
<tbody id="damageTbody">
</tbody>
</table>
</div>
<div class="summary-section">
<div class="summary-header">
<i class="fas fa-clipboard-list"></i>
<h4>Assessment Summary</h4>
</div>
<div id="summaryText" class="summary-content"></div>
</div>
</div>
</div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
<style>
.llm-analysis {
margin-top: 2rem;
background: white; /* White background */
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
overflow: hidden;
transition: all 0.3s ease;
}
.analysis-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1.5rem;
background: linear-gradient(135deg, #805ad5 0%, #6b46c1 100%); /* Keep purple gradient header */
color: white;
}
.analysis-header h3 {
margin: 0;
font-size: 1.5rem;
display: flex;
align-items: center;
gap: 10px;
color: white;
}
.toggle-btn {
display: flex;
align-items: center;
gap: 8px;
background: rgba(255, 255, 255, 0.15);
color: white;
border: 1px solid rgba(255, 255, 255, 0.2);
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s ease;
}
.toggle-btn:hover {
background: rgba(255, 255, 255, 0.25);
}
.toggle-btn i {
transition: transform 0.3s ease;
}
.toggle-btn.active i {
transform: rotate(180deg);
}
.analysis-content {
padding: 1.5rem;
background: white;
color: #2d3748; /* Dark gray text */
}
.damage-grid {
display: grid;
gap: 1.5rem;
grid-template-columns: 1fr;
}
@media (min-width: 1024px) {
.damage-grid {
grid-template-columns: 3fr 2fr;
}
}
.table-container {
overflow-x: auto;
background: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.damage-table {
width: 100%;
border-collapse: collapse;
margin: 0;
font-size: 0.95rem;
color: #2d3748;
}
.damage-table th, .damage-table td {
padding: 12px 16px;
text-align: left;
border-bottom: 1px solid #e2e8f0;
}
.damage-table th {
background: #f7fafc;
font-weight: 600;
color: #4a5568;
text-transform: uppercase;
font-size: 0.85rem;
letter-spacing: 0.05em;
}
.damage-table tr:last-child td {
border-bottom: none;
}
.damage-table tbody tr {
transition: background-color 0.2s ease;
}
.damage-table tbody tr:hover {
background-color: #f7fafc;
}
.summary-section {
background: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
padding: 1.5rem;
}
.summary-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 1rem;
color: #4a5568;
}
.summary-header h4 {
margin: 0;
font-size: 1.2rem;
color: #2d3748;
}
.summary-content {
color: #4a5568;
line-height: 1.6;
}
.summary-content p {
margin: 0 0 1rem;
}
.summary-content p:last-child {
margin-bottom: 0;
}
/* Updated Severity colors for light background */
.severity-high {
color: #e53e3e; /* Red */
}
.severity-medium {
color: #d69e2e; /* Yellow */
}
.severity-low {
color: #38a169; /* Green */
}
/* Animation for content */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
.analysis-content.show {
animation: fadeIn 0.3s ease-out forwards;
}
</style>
<script>
function parseAndDisplayDamageReport() {
const block = document.getElementById('analysis-block');
const tbody = document.getElementById('damageTbody');
const summaryDiv = document.getElementById('summaryText');
const analysisText = `{{ result.llm_analysis | safe }}`;
tbody.innerHTML = '';
summaryDiv.innerHTML = '';
const lines = analysisText.split('\n');
let summaryText = [];
lines.forEach(line => {
if (line.includes('|')) {
const parts = line.split('|').filter(part => part.trim() !== '');
if (parts.length === 4 && !line.includes('Component') && !line.includes('---')) {
const row = document.createElement('tr');
parts.forEach((part, index) => {
const td = document.createElement('td');
const text = part.trim();
td.textContent = text;
// Add severity class
if (index === 2) { // Severity column
if (text.toLowerCase().includes('high')) {
td.classList.add('severity-high');
} else if (text.toLowerCase().includes('medium')) {
td.classList.add('severity-medium');
} else if (text.toLowerCase().includes('low')) {
td.classList.add('severity-low');
}
}
row.appendChild(td);
});
tbody.appendChild(row);
}
} else if (line.trim() !== '' && !line.includes('**')) {
if (line.length > 10) {
summaryText.push(line.trim());
}
}
});
summaryText.forEach(text => {
const p = document.createElement('p');
p.textContent = text;
summaryDiv.appendChild(p);
});
}
function toggleBlock(blockId, btnId) {
const block = document.getElementById(blockId);
const btn = document.getElementById(btnId);
const isHidden = block.style.display === 'none' || !block.style.display;
block.style.display = isHidden ? 'block' : 'none';
btn.classList.toggle('active');
const btnText = btn.querySelector('.btn-text');
btnText.textContent = isHidden ? 'Hide Analysis' : 'Show Analysis';
if (isHidden) {
block.classList.add('show');
parseAndDisplayDamageReport();
} else {
block.classList.remove('show');
}
}
</script>
{% endif %}
</div>
{% endif %}
</div>
<div class="footer">
&copy; {{ 2025 }} DS Team. All rights reserved.
</div>
</body>
</html>