oramap/backend/server.js
dvirlabs 016d58ac75
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Add comprehensive logging for add family functionality
- Backend: Log all requests with timestamps
- Backend: Log POST /api/families with validation details
- Frontend: Log fetch requests and responses
- Frontend: Better error messages with status codes
- Frontend: Handle non-JSON responses gracefully
2026-03-25 11:23:05 +02:00

172 lines
4.9 KiB
JavaScript

const express = require('express');
const cors = require('cors');
const path = require('path');
const connectDB = require('./config/database');
const Family = require('./models/Family');
const app = express();
// Enable CORS for frontend
app.use(cors());
// Body parser middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Request logging middleware
app.use((req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`);
if (req.method === 'POST' || req.method === 'PUT') {
console.log(' Body:', JSON.stringify(req.body));
}
next();
});
// Connect to MongoDB
connectDB();
// Serve static files from the public directory (for standalone mode)
if (process.env.SERVE_STATIC === 'true') {
app.use(express.static(path.join(__dirname, '../public')));
}
// API endpoint for family search
app.get('/api/search', async (req, res) => {
try {
const query = req.query.family?.toLowerCase();
if (!query) {
return res.json([]);
}
// Search by family name (case-insensitive)
const matches = await Family.find({
family: { $regex: query, $options: 'i' }
}).select('-__v -createdAt -updatedAt');
res.json(matches);
} catch (error) {
console.error('Search error:', error);
res.status(500).json({ error: 'Search failed', message: error.message });
}
});
// Get all families
app.get('/api/families', async (req, res) => {
try {
const families = await Family.find()
.select('-__v -createdAt -updatedAt')
.sort({ family: 1 });
res.json(families);
} catch (error) {
console.error('Get families error:', error);
res.status(500).json({ error: 'Failed to fetch families', message: error.message });
}
});
// Create new family
app.post('/api/families', async (req, res) => {
try {
console.log('📝 POST /api/families - Creating new family');
const { family, city, lat, lng } = req.body;
console.log(` Data: ${family}, ${city}, (${lat}, ${lng})`);
// Validation
if (!family || !city || lat === undefined || lng === undefined) {
console.log(' ❌ Validation failed: Missing fields');
return res.status(400).json({
error: 'Missing required fields',
required: ['family', 'city', 'lat', 'lng'],
received: { family: !!family, city: !!city, lat: lat !== undefined, lng: lng !== undefined }
});
}
// Validate coordinates
if (lat < -90 || lat > 90 || lng < -180 || lng > 180) {
console.log(' ❌ Validation failed: Invalid coordinates');
return res.status(400).json({
error: 'Invalid coordinates',
message: 'Latitude must be between -90 and 90, Longitude between -180 and 180'
});
}
const newFamily = new Family({ family, city, lat, lng });
await newFamily.save();
console.log(` ✅ Family created successfully: ${newFamily._id}`);
res.status(201).json({
message: 'Family added successfully',
family: newFamily
});
} catch (error) {
console.error('❌ Create family error:', error);
res.status(500).json({ error: 'Failed to create family', message: error.message });
}
});
// Update family
app.put('/api/families/:id', async (req, res) => {
try {
const { id } = req.params;
const { family, city, lat, lng } = req.body;
const updatedFamily = await Family.findByIdAndUpdate(
id,
{ family, city, lat, lng },
{ new: true, runValidators: true }
);
if (!updatedFamily) {
return res.status(404).json({ error: 'Family not found' });
}
res.json({
message: 'Family updated successfully',
family: updatedFamily
});
} catch (error) {
console.error('Update family error:', error);
res.status(500).json({ error: 'Failed to update family', message: error.message });
}
});
// Delete family
app.delete('/api/families/:id', async (req, res) => {
try {
const { id } = req.params;
const deletedFamily = await Family.findByIdAndDelete(id);
if (!deletedFamily) {
return res.status(404).json({ error: 'Family not found' });
}
res.json({
message: 'Family deleted successfully',
family: deletedFamily
});
} catch (error) {
console.error('Delete family error:', error);
res.status(500).json({ error: 'Failed to delete family', message: error.message });
}
});
// Health check endpoint
app.get('/api/health', (req, res) => {
const mongoose = require('mongoose');
const dbStatus = mongoose.connection.readyState === 1 ? 'connected' : 'disconnected';
res.json({
status: 'ok',
timestamp: new Date().toISOString(),
database: dbStatus
});
});
const port = process.env.PORT || 3000;
app.listen(port, '0.0.0.0', () => {
console.log(`🗺️ Ora Map Backend API running at http://localhost:${port}`);
console.log(`📍 Search endpoint: http://localhost:${port}/api/search`);
console.log(`💚 Health endpoint: http://localhost:${port}/api/health`);
});