deepsite / booknap project /json-blog.html
aakash1777's picture
Upload 38 files
0a96199 verified
raw
history blame
8.82 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Blog with JSON Dataset</title>
<style>
body {
font-family: 'Inter', sans-serif;
background: linear-gradient(180deg, #0b1020, #0b1022 30%, #0b1124);
color: #e2e8f0;
margin: 0;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.controls {
display: flex;
gap: 1rem;
margin: 2rem 0;
flex-wrap: wrap;
}
.search-bar, .category-filter {
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 25px;
padding: 0.75rem 1.5rem;
color: #e2e8f0;
}
.search-bar {
flex: 1;
min-width: 200px;
}
.category-filter {
min-width: 150px;
}
.blog-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 2rem;
margin-top: 2rem;
}
.blog-card {
background: rgba(255, 255, 255, 0.05);
border-radius: 16px;
overflow: hidden;
border: 1px solid rgba(255, 255, 255, 0.1);
transition: transform 0.3s ease;
}
.blog-card:hover {
transform: translateY(-8px);
}
.blog-card-image {
width: 100%;
height: 200px;
background-size: cover;
background-position: center;
}
.blog-card-content {
padding: 1.5rem;
}
.blog-card-title {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 0.5rem;
}
.blog-card-date {
color: #94a3b8;
font-size: 0.875rem;
margin-bottom: 1rem;
}
.blog-card-link {
color: #8b5cf6;
text-decoration: none;
font-weight: 600;
font-size: 0.875rem;
text-transform: uppercase;
}
.tags {
display: flex;
gap: 0.5rem;
margin-top: 1rem;
flex-wrap: wrap;
}
.tag {
background: rgba(139, 92, 246, 0.2);
color: #a78bfa;
padding: 0.25rem 0.75rem;
border-radius: 15px;
font-size: 0.75rem;
}
.loading {
text-align: center;
padding: 2rem;
color: #94a3b8;
}
.stats {
display: flex;
gap: 2rem;
margin: 1rem 0;
color: #94a3b8;
font-size: 0.875rem;
}
</style>
</head>
<body>
<div class="container">
<h1>Blog with JSON Dataset</h1>
<div class="stats" id="stats">
<span>Loading...</span>
</div>
<div class="controls">
<input type="text" class="search-bar" placeholder="Search articles..." id="searchInput">
<select class="category-filter" id="categoryFilter" aria-label="Filter by category">
<option value="">All Categories</option>
</select>
</div>
<div class="blog-grid" id="blogGrid">
<div class="loading">Loading articles...</div>
</div>
</div>
<script>
let allArticles = [];
let filteredArticles = [];
// Load data from JSON file
async function loadDataset() {
try {
const response = await fetch('data/news.json');
const data = await response.json();
allArticles = data.articles;
filteredArticles = [...allArticles];
// Populate category filter
populateCategoryFilter(data.categories);
// Display articles
displayArticles(filteredArticles);
// Update stats
updateStats();
} catch (error) {
console.error('Error loading dataset:', error);
document.getElementById('blogGrid').innerHTML =
'<div class="loading">Error loading data. Please check if data/news.json exists.</div>';
}
}
// Populate category filter dropdown
function populateCategoryFilter(categories) {
const categoryFilter = document.getElementById('categoryFilter');
categories.forEach(category => {
const option = document.createElement('option');
option.value = category;
option.textContent = category;
categoryFilter.appendChild(option);
});
}
// Create article card
function createArticleCard(article) {
const tags = article.tags ? article.tags.map(tag =>
`<span class="tag">${tag}</span>`
).join('') : '';
return `
<article class="blog-card">
<div class="blog-card-image" style="background-image: url('${article.image}');"></div>
<div class="blog-card-content">
<h3 class="blog-card-title">${article.title}</h3>
<p class="blog-card-date">${article.date}${article.source}${article.category}</p>
<p style="color: #94a3b8; font-size: 0.875rem; margin-bottom: 1rem;">${article.description}</p>
<div class="tags">${tags}</div>
<a href="#" class="blog-card-link">READ MORE</a>
</div>
</article>
`;
}
// Display articles
function displayArticles(articles) {
const blogGrid = document.getElementById('blogGrid');
if (articles.length === 0) {
blogGrid.innerHTML = '<div class="loading">No articles found.</div>';
} else {
blogGrid.innerHTML = articles.map(createArticleCard).join('');
}
}
// Filter articles
function filterArticles() {
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
const selectedCategory = document.getElementById('categoryFilter').value;
filteredArticles = allArticles.filter(article => {
const matchesSearch =
article.title.toLowerCase().includes(searchTerm) ||
article.description.toLowerCase().includes(searchTerm) ||
article.tags.some(tag => tag.toLowerCase().includes(searchTerm));
const matchesCategory = !selectedCategory || article.category === selectedCategory;
return matchesSearch && matchesCategory;
});
displayArticles(filteredArticles);
updateStats();
}
// Update statistics
function updateStats() {
const stats = document.getElementById('stats');
stats.innerHTML = `
<span>Total Articles: ${allArticles.length}</span>
<span>Showing: ${filteredArticles.length}</span>
<span>Categories: ${new Set(allArticles.map(a => a.category)).size}</span>
`;
}
// Initialize the page
document.addEventListener('DOMContentLoaded', function() {
// Load dataset
loadDataset();
// Add event listeners
document.getElementById('searchInput').addEventListener('input', filterArticles);
document.getElementById('categoryFilter').addEventListener('change', filterArticles);
});
// Example functions for data manipulation
function getArticlesByCategory(category) {
return allArticles.filter(article => article.category === category);
}
function getLatestArticles(count = 3) {
return allArticles
.sort((a, b) => new Date(b.date) - new Date(a.date))
.slice(0, count);
}
function searchByTags(tags) {
return allArticles.filter(article =>
tags.some(tag => article.tags.includes(tag))
);
}
</script>
</body>
</html>