Spaces:
Sleeping
Sleeping
File size: 10,200 Bytes
ad08f08 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
const DatasetsPage = () => {
const [datasets, setDatasets] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [searchTerm, setSearchTerm] = useState('');
const [categoryFilter, setCategoryFilter] = useState('All');
useEffect(() => {
// In a real app, this would fetch from an API
// For demo purposes, we'll use mock data
const mockDatasets = [
{
id: 1,
title: 'Cold Chain Infrastructure Map',
description: 'Geospatial data on refrigeration facilities across Sub-Saharan Africa. Includes location, capacity, and operational status of cold storage facilities.',
category: 'Infrastructure',
size: '2.4 GB',
downloads: 1240,
tags: ['geospatial', 'refrigeration', 'Africa', 'logistics']
},
{
id: 2,
title: 'Post-Harvest Loss Hotspots',
description: 'Identified areas with highest food loss rates in South Asia. Contains data on crop types, loss percentages, and contributing factors.',
category: 'Analytics',
size: '890 MB',
downloads: 890,
tags: ['analytics', 'loss assessment', 'South Asia', 'crops']
},
{
id: 3,
title: 'Processing Capacity Database',
description: 'List of food processing facilities with available capacity. Includes contact information, equipment types, and scheduling availability.',
category: 'Industry',
size: '1.1 GB',
downloads: 1560,
tags: ['processing', 'manufacturing', 'capacity', 'directory']
},
{
id: 4,
title: 'Food Waste Composition Analysis',
description: 'Detailed analysis of food waste streams in urban environments. Data covers waste composition by type, seasonal variations, and disposal methods.',
category: 'Waste Management',
size: '3.2 GB',
downloads: 2100,
tags: ['waste', 'composition', 'urban', 'analysis']
},
{
id: 5,
title: 'Agricultural Surplus Mapping',
description: 'Real-time mapping of agricultural surpluses available for redistribution. Updated weekly with data from farms and cooperatives.',
category: 'Supply Chain',
size: '1.7 GB',
downloads: 980,
tags: ['surplus', 'redistribution', 'mapping', 'real-time']
},
{
id: 6,
title: 'Policy Instruments Database',
description: 'Comprehensive database of food loss and waste reduction policies worldwide. Includes policy descriptions, implementation status, and impact assessments.',
category: 'Policy',
size: '520 MB',
downloads: 1650,
tags: ['policy', 'regulations', 'government', 'database']
}
];
setTimeout(() => {
setDatasets(mockDatasets);
setLoading(false);
}, 500);
}, []);
const categories = ['All', ...new Set(datasets.map(dataset => dataset.category))];
const filteredDatasets = datasets.filter(dataset => {
const matchesSearch = dataset.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
dataset.description.toLowerCase().includes(searchTerm.toLowerCase()) ||
dataset.tags.some(tag => tag.toLowerCase().includes(searchTerm.toLowerCase()));
const matchesCategory = categoryFilter === 'All' || dataset.category === categoryFilter;
return matchesSearch && matchesCategory;
});
if (loading) {
return (
<div className="py-16 bg-gradient-to-br from-white to-gray-100 dark:from-gray-900 dark:to-gray-800 transition-colors duration-300 min-h-screen">
<div className="container mx-auto px-4">
<h2 className="text-3xl font-bold mb-8 text-gray-800 dark:text-white drop-shadow bg-gradient-to-r from-bio-green to-bio-blue bg-clip-text text-transparent">Open Datasets</h2>
<div className="flex justify-center">
<div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-bio-green"></div>
</div>
</div>
</div>
);
}
if (error) {
return (
<div className="py-16 bg-gradient-to-br from-white to-gray-100 dark:from-gray-900 dark:to-gray-800 transition-colors duration-300 min-h-screen">
<div className="container mx-auto px-4">
<h2 className="text-3xl font-bold mb-8 text-gray-800 dark:text-white drop-shadow bg-gradient-to-r from-bio-green to-bio-blue bg-clip-text text-transparent">Open Datasets</h2>
<div className="text-center text-red-500">
<p>Error loading datasets: {error}</p>
</div>
</div>
</div>
);
}
return (
<div className="py-16 bg-gradient-to-br from-white to-gray-100 dark:from-gray-900 dark:to-gray-800 transition-colors duration-300 min-h-screen">
<div className="container mx-auto px-4">
<h2 className="text-3xl font-bold mb-8 text-gray-800 dark:text-white drop-shadow bg-gradient-to-r from-bio-green to-bio-blue bg-clip-text text-transparent">Open Datasets</h2>
<div className="mb-8 bg-white dark:bg-gray-800 rounded-2xl shadow-lg p-6 border border-gray-100 dark:border-gray-700 bg-gradient-to-br from-white to-gray-100 dark:from-gray-800 dark:to-gray-900">
<div className="flex flex-col md:flex-row gap-4">
<div className="flex-grow">
<input
type="text"
placeholder="Search datasets..."
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-bio-green focus:border-transparent dark:bg-gray-700 dark:text-white drop-shadow bg-gradient-to-r from-white to-gray-50 dark:from-gray-700 dark:to-gray-800"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
</div>
<div className="w-full md:w-48">
<select
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-bio-green focus:border-transparent dark:bg-gray-700 dark:text-white drop-shadow bg-gradient-to-r from-white to-gray-50 dark:from-gray-700 dark:to-gray-800"
value={categoryFilter}
onChange={(e) => setCategoryFilter(e.target.value)}
>
{categories.map(category => (
<option key={category} value={category}>{category}</option>
))}
</select>
</div>
</div>
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
{filteredDatasets.map((dataset) => (
<div key={dataset.id} className="bg-gradient-to-br from-blue-50 to-purple-50 dark:from-gray-700 dark:to-gray-800 rounded-2xl shadow-lg p-6 border border-blue-100 dark:border-gray-600 transition-all duration-300 transform hover:-translate-y-1 hover:shadow-xl bg-gradient-to-br from-blue-50/50 to-purple-50/50 dark:from-gray-700/50 dark:to-gray-800/50">
<div className="flex justify-between items-start mb-4">
<h3 className="text-xl font-bold text-gray-800 dark:text-white drop-shadow bg-gradient-to-r from-gray-800 to-gray-600 bg-clip-text text-transparent dark:from-white dark:to-gray-300">{dataset.title}</h3>
<span className="inline-block px-3 py-1 text-xs font-semibold text-bio-blue bg-blue-100 dark:bg-blue-900/30 dark:text-blue-300 rounded-full drop-shadow bg-gradient-to-r from-blue-100 to-blue-200 dark:from-blue-900/30 dark:to-blue-800/30">
{dataset.category}
</span>
</div>
<p className="text-gray-600 dark:text-gray-300 mb-4 drop-shadow">{dataset.description}</p>
<div className="flex flex-wrap gap-2 mb-4">
{dataset.tags.map((tag, index) => (
<span key={index} className="px-2 py-1 text-xs bg-gray-200 dark:bg-gray-600 text-gray-700 dark:text-gray-300 rounded-full drop-shadow bg-gradient-to-r from-gray-200 to-gray-300 dark:from-gray-600 dark:to-gray-700">
{tag}
</span>
))}
</div>
<div className="flex justify-between items-center">
<div className="text-sm text-gray-500 dark:text-gray-400 drop-shadow">
<span className="mr-4">Size: {dataset.size}</span>
<span>{dataset.downloads} downloads</span>
</div>
<div className="flex gap-2">
<button className="bg-gradient-to-r from-bio-blue to-blue-500 text-white px-4 py-2 rounded-lg hover:from-blue-500 hover:to-blue-600 transition shadow-md hover:shadow-lg drop-shadow">
Download
</button>
<button className="border border-bio-blue text-bio-blue dark:text-blue-400 px-4 py-2 rounded-lg hover:bg-blue-50 dark:hover:bg-blue-900/30 transition drop-shadow bg-gradient-to-r from-white to-blue-50 dark:from-gray-800 dark:to-blue-900/30">
Preview
</button>
</div>
</div>
</div>
))}
</div>
{filteredDatasets.length === 0 && (
<div className="text-center py-12 bg-white dark:bg-gray-800 rounded-2xl shadow-lg bg-gradient-to-br from-white to-gray-100 dark:from-gray-800 dark:to-gray-900">
<p className="text-gray-600 dark:text-gray-400 drop-shadow">No datasets found matching your criteria.</p>
<button
className="mt-4 text-bio-blue dark:text-blue-400 hover:underline drop-shadow bg-gradient-to-r from-bio-blue to-blue-500 bg-clip-text text-transparent"
onClick={() => {
setSearchTerm('');
setCategoryFilter('All');
}}
>
Clear filters
</button>
</div>
)}
</div>
</div>
);
};
export default DatasetsPage; |