anycoder-3a383f21 / index.html
raphael0202's picture
Update index.html
b7b107a verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Open Prices - Proof Visualizer</title>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary-color: #4CAF50;
--secondary-color: #45a049;
--accent-color: #ff9800;
--background-color: #f5f5f5;
--card-bg: #ffffff;
--text-color: #333333;
--border-radius: 12px;
--box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
--transition: all 0.3s ease;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background-color: var(--background-color);
color: var(--text-color);
line-height: 1.6;
padding: 20px;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
}
header {
width: 100%;
max-width: 1200px;
margin-bottom: 30px;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 15px;
}
.logo-container {
display: flex;
align-items: center;
gap: 10px;
}
.logo {
width: 50px;
height: 50px;
background-color: var(--primary-color);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-weight: bold;
font-size: 18px;
}
h1 {
font-size: 1.8rem;
color: var(--primary-color);
}
.anycoder-link {
color: var(--primary-color);
text-decoration: none;
font-size: 0.9rem;
display: flex;
align-items: center;
gap: 5px;
}
.anycoder-link:hover {
text-decoration: underline;
}
.input-container {
width: 100%;
max-width: 600px;
margin-bottom: 30px;
display: flex;
flex-direction: column;
gap: 15px;
}
.input-group {
display: flex;
gap: 10px;
}
input {
flex: 1;
padding: 12px 15px;
border: 2px solid #ddd;
border-radius: var(--border-radius);
font-size: 1rem;
transition: var(--transition);
}
input:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: var(--box-shadow);
}
button {
padding: 12px 20px;
background-color: var(--primary-color);
color: white;
border: none;
border-radius: var(--border-radius);
font-size: 1rem;
cursor: pointer;
transition: var(--transition);
display: flex;
align-items: center;
gap: 8px;
}
button:hover {
background-color: var(--secondary-color);
transform: translateY(-2px);
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
transform: none;
}
.loading {
display: none;
text-align: center;
margin: 20px 0;
}
.loading.active {
display: block;
}
.spinner {
border: 4px solid rgba(0, 0, 0, 0.1);
border-radius: 50%;
border-top: 4px solid var(--primary-color);
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
margin: 0 auto 10px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.error-message {
color: #e74c3c;
background-color: #fadbd8;
padding: 15px;
border-radius: var(--border-radius);
margin-bottom: 20px;
display: none;
}
.error-message.active {
display: block;
}
.proof-container {
width: 100%;
max-width: 1200px;
margin-bottom: 40px;
display: none;
}
.proof-container.active {
display: block;
}
.proof-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
flex-wrap: wrap;
gap: 15px;
}
.proof-title {
font-size: 1.5rem;
color: var(--primary-color);
}
.proof-id {
font-size: 1.2rem;
color: var(--accent-color);
font-weight: bold;
}
.proof-image-container {
background-color: var(--card-bg);
border-radius: var(--border-radius);
box-shadow: var(--box-shadow);
padding: 20px;
margin-bottom: 30px;
text-align: center;
}
.proof-image {
max-width: 100%;
height: auto;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.price-tags-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
}
.price-tag-card {
background-color: var(--card-bg);
border-radius: var(--border-radius);
box-shadow: var(--box-shadow);
overflow: hidden;
transition: var(--transition);
}
.price-tag-card:hover {
transform: translateY(-5px);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
}
.price-tag-image {
width: 100%;
height: 200px;
object-fit: contain;
background-color: #f9f9f9;
padding: 10px;
}
.price-tag-info {
padding: 15px;
}
.price-tag-id {
font-size: 0.9rem;
color: #777;
margin-bottom: 5px;
}
.price-tag-details {
display: flex;
flex-direction: column;
gap: 8px;
}
.detail-row {
display: flex;
justify-content: space-between;
font-size: 0.9rem;
}
.detail-label {
font-weight: bold;
color: var(--primary-color);
}
.detail-value {
color: var(--text-color);
}
.no-price-tags {
text-align: center;
padding: 40px;
color: #777;
font-style: italic;
}
@media (max-width: 768px) {
.input-group {
flex-direction: column;
}
button {
width: 100%;
justify-content: center;
}
.price-tags-container {
grid-template-columns: 1fr;
}
.proof-header {
flex-direction: column;
align-items: flex-start;
}
}
@media (max-width: 480px) {
h1 {
font-size: 1.5rem;
}
.proof-title {
font-size: 1.2rem;
}
.proof-id {
font-size: 1rem;
}
}
</style>
</head>
<body>
<header>
<div class="logo-container">
<div class="logo">OP</div>
<h1>Open Prices - Proof Visualizer</h1>
</div>
<a href="https://huggingface.co/spaces/akhaliq/anycoder" class="anycoder-link" target="_blank">
<i class="fas fa-code"></i> Built with anycoder
</a>
</header>
<div class="input-container">
<div class="input-group">
<input type="number" id="proofIdInput" placeholder="Enter proof ID (integer)" min="1">
<button id="fetchProofBtn">
<i class="fas fa-search"></i> Fetch Proof
</button>
</div>
</div>
<div class="loading" id="loading">
<div class="spinner"></div>
<p>Loading data...</p>
</div>
<div class="error-message" id="errorMessage"></div>
<div class="proof-container" id="proofContainer">
<div class="proof-header">
<h2 class="proof-title">Proof Image</h2>
<div class="proof-id" id="proofIdDisplay"></div>
</div>
<div class="proof-image-container">
<img id="proofImage" class="proof-image" alt="Proof image">
</div>
<h2 class="proof-title">Associated Price Tags</h2>
<div class="price-tags-container" id="priceTagsContainer">
<!-- Price tags will be inserted here -->
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const proofIdInput = document.getElementById('proofIdInput');
const fetchProofBtn = document.getElementById('fetchProofBtn');
const loading = document.getElementById('loading');
const errorMessage = document.getElementById('errorMessage');
const proofContainer = document.getElementById('proofContainer');
const proofImage = document.getElementById('proofImage');
const proofIdDisplay = document.getElementById('proofIdDisplay');
const priceTagsContainer = document.getElementById('priceTagsContainer');
fetchProofBtn.addEventListener('click', fetchProofData);
proofIdInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
fetchProofData();
}
});
async function fetchProofData() {
const proofId = proofIdInput.value.trim();
// Validate input
if (!proofId || isNaN(proofId) || proofId <= 0) {
showError('Please enter a valid positive integer for the proof ID.');
return;
}
// Clear previous results and errors
clearResults();
hideError();
// Show loading
showLoading();
try {
// Fetch proof data
const proofResponse = await axios.get(`https://prices.openfoodfacts.org/api/v1/proofs/${proofId}`);
// Check if the proof type is PRICE_TAG
if (proofResponse.data.type !== 'PRICE_TAG') {
showError('The provided proof is not a price tag.');
return;
}
// Display proof information
displayProof(proofResponse.data);
// Fetch price tags
const priceTagsResponse = await axios.get(`https://prices.openfoodfacts.org/api/v1/price-tags?proof_id=${proofId}`);
// Display price tags
displayPriceTags(priceTagsResponse.data.items);
} catch (error) {
console.error('Error fetching data:', error);
showError('Failed to fetch data. Please check the proof ID and try again.');
} finally {
hideLoading();
}
}
function displayProof(proofData) {
// Set proof ID
proofIdDisplay.textContent = `Proof ID: ${proofData.id}`;
// Set proof image
if (proofData.image_thumb_path) {
proofImage.src = `https://prices.openfoodfacts.org/img/${proofData.image_thumb_path}`;
proofImage.alt = `Proof ${proofData.id} image`;
} else {
proofImage.src = '';
proofImage.alt = 'No proof image available';
}
// Show proof container
proofContainer.classList.add('active');
}
function displayPriceTags(priceTags) {
if (!priceTags || priceTags.length === 0) {
priceTagsContainer.innerHTML = '<div class="no-price-tags">No price tags found for this proof.</div>';
return;
}
priceTagsContainer.innerHTML = '';
priceTags.forEach(tag => {
const tagCard = document.createElement('div');
tagCard.className = 'price-tag-card';
let imageUrl = '';
if (tag.image_path) {
imageUrl = `https://prices.openfoodfacts.org/img/${tag.image_path}`;
}
tagCard.innerHTML = `
<div class="price-tag-image-container">
${imageUrl ? `<img src="${imageUrl}" class="price-tag-image" alt="Price tag ${tag.id}">` : '<div class="price-tag-image" style="display: flex; justify-content: center; align-items: center; color: #999;">No image</div>'}
</div>
<div class="price-tag-info">
<div class="price-tag-id">Price Tag ID: ${tag.id}</div>
<div class="price-tag-details">
${tag.barcode ? `<div class="detail-row"><span class="detail-label">Barcode:</span><span class="detail-value">${tag.barcode}</span></div>` : ''}
${tag.price ? `<div class="detail-row"><span class="detail-label">Price:</span><span class="detail-value">${tag.price}</span></div>` : ''}
${tag.currency ? `<div class="detail-row"><span class="detail-label">Currency:</span><span class="detail-value">${tag.currency}</span></div>` : ''}
${tag.product_name ? `<div class="detail-row"><span class="detail-label">Product:</span><span class="detail-value">${tag.product_name}</span></div>` : ''}
</div>
</div>
`;
priceTagsContainer.appendChild(tagCard);
});
}
function showLoading() {
loading.classList.add('active');
fetchProofBtn.disabled = true;
}
function hideLoading() {
loading.classList.remove('active');
fetchProofBtn.disabled = false;
}
function showError(message) {
errorMessage.textContent = message;
errorMessage.classList.add('active');
}
function hideError() {
errorMessage.classList.remove('active');
}
function clearResults() {
proofContainer.classList.remove('active');
proofImage.src = '';
proofIdDisplay.textContent = '';
priceTagsContainer.innerHTML = '';
}
});
</script>
</body>
</html>