localgreenchain/pages/api/plants/search.ts
Claude 1e14a700c7
Implement LocalGreenChain: Plant Cloning Blockchain System
This commit implements a complete blockchain-based plant tracking system
that preserves lineage across clones, seeds, and all plant offspring while
connecting growers through geographic proximity.

Features implemented:
- Custom blockchain with proof-of-work consensus
- Plant registration and cloning with lineage tracking
- Geographic discovery to find nearby plants and growers
- Integration with plants.net API for plant identification
- Comprehensive web UI for plant management
- RESTful API endpoints for all operations
- Network statistics and visualization

Core Components:
- lib/blockchain/: PlantBlock, PlantChain, and blockchain manager
- lib/services/: plants.net API and geolocation services
- pages/api/plants/: REST API endpoints for all operations
- pages/: Frontend UI pages for registration, exploration, and lineage

Technical Details:
- TypeScript for type safety
- Next.js for server-side rendering
- Tailwind CSS for responsive design
- JSON file-based blockchain storage
- Haversine distance calculations for geolocation
- OpenStreetMap integration for geocoding

This system enables large-scale adoption by:
- Making plant lineage tracking accessible to everyone
- Connecting local communities through plant sharing
- Providing immutable proof of plant provenance
- Supporting unlimited generations of plant propagation
- Scaling from individual growers to global networks

Documentation includes comprehensive README with:
- Quick start guide
- API reference
- Architecture details
- Scaling recommendations
- Use cases for various audiences
- Roadmap for future enhancements
2025-11-16 05:11:55 +00:00

87 lines
2.4 KiB
TypeScript

/**
* API Route: Search for plants
* GET /api/plants/search?q=tomato&type=species
*/
import type { NextApiRequest, NextApiResponse } from 'next';
import { getBlockchain } from '../../../lib/blockchain/manager';
import { getPlantsNetService } from '../../../lib/services/plantsnet';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== 'GET') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
const { q, type } = req.query;
if (!q || typeof q !== 'string') {
return res.status(400).json({ error: 'Missing search query parameter: q' });
}
const blockchain = getBlockchain();
const searchTerm = q.toLowerCase();
// Search in blockchain
const allPlants = Array.from(
new Set(blockchain.chain.map(block => block.plant.id))
).map(id => blockchain.getPlant(id)!);
let results = allPlants.filter(plant => {
if (!plant) return false;
const searchIn = [
plant.commonName?.toLowerCase(),
plant.scientificName?.toLowerCase(),
plant.genus?.toLowerCase(),
plant.family?.toLowerCase(),
plant.owner.name?.toLowerCase(),
].filter(Boolean);
return searchIn.some(field => field?.includes(searchTerm));
});
// Filter by type if specified
if (type) {
switch (type) {
case 'species':
results = results.filter(p =>
p.scientificName?.toLowerCase().includes(searchTerm)
);
break;
case 'owner':
results = results.filter(p =>
p.owner.name?.toLowerCase().includes(searchTerm)
);
break;
case 'location':
results = results.filter(
p =>
p.location.city?.toLowerCase().includes(searchTerm) ||
p.location.country?.toLowerCase().includes(searchTerm)
);
break;
}
}
// Also search plants.net if API key is available
let plantsNetResults = [];
if (process.env.PLANTS_NET_API_KEY) {
const plantsNet = getPlantsNetService();
plantsNetResults = await plantsNet.searchPlant(q);
}
res.status(200).json({
success: true,
count: results.length,
results: results,
plantsNetResults: plantsNetResults,
});
} catch (error: any) {
console.error('Error searching plants:', error);
res.status(500).json({ error: error.message || 'Internal server error' });
}
}