269 lines
9.1 KiB
JavaScript
269 lines
9.1 KiB
JavaScript
const express = require('express');
|
|
const cors = require('cors');
|
|
const carpenterTasksData = require('./carpenter-tasks-database.js');
|
|
|
|
const app = express();
|
|
const PORT = process.env.CARPENTER_API_PORT || 3002;
|
|
|
|
// Middleware
|
|
app.use(cors());
|
|
app.use(express.json());
|
|
|
|
// Health check
|
|
app.get('/health', (req, res) => {
|
|
res.json({
|
|
status: 'OK',
|
|
service: 'Tømmer Opgave API',
|
|
timestamp: new Date().toISOString(),
|
|
totalTasks: carpenterTasksData.tasks.length,
|
|
totalCategories: carpenterTasksData.categories.length
|
|
});
|
|
});
|
|
|
|
// ===================================
|
|
// TØMMER OPGAVE ENDPOINTS
|
|
// ===================================
|
|
|
|
// Get alle kategorier
|
|
app.get('/api/carpenter/categories', (req, res) => {
|
|
try {
|
|
const categories = carpenterTasksData.categories.map(cat => ({
|
|
id: cat.id,
|
|
name: cat.name,
|
|
description: cat.description,
|
|
priority: cat.priority,
|
|
taskCount: carpenterTasksData.tasks.filter(task => task.categoryId === cat.id).length
|
|
}));
|
|
|
|
res.json({
|
|
success: true,
|
|
data: categories,
|
|
total: categories.length
|
|
});
|
|
} catch (error) {
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
});
|
|
|
|
// Get opgaver efter kategori
|
|
app.get('/api/carpenter/tasks/:categoryId', (req, res) => {
|
|
try {
|
|
const categoryId = parseInt(req.params.categoryId);
|
|
const tasks = carpenterTasksData.tasks.filter(task => task.categoryId === categoryId);
|
|
|
|
const enrichedTasks = tasks.map(task => ({
|
|
...task,
|
|
stepCount: carpenterTasksData.taskSteps.filter(step => step.taskId === task.id).length,
|
|
category: carpenterTasksData.categories.find(cat => cat.id === categoryId)?.name
|
|
}));
|
|
|
|
res.json({
|
|
success: true,
|
|
data: enrichedTasks,
|
|
total: enrichedTasks.length,
|
|
categoryName: carpenterTasksData.categories.find(cat => cat.id === categoryId)?.name
|
|
});
|
|
} catch (error) {
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
});
|
|
|
|
// Get alle opgaver med søgning
|
|
app.get('/api/carpenter/tasks', (req, res) => {
|
|
try {
|
|
const { search, difficulty, category } = req.query;
|
|
let filteredTasks = [...carpenterTasksData.tasks];
|
|
|
|
// Søg i navn og beskrivelse
|
|
if (search) {
|
|
const searchTerm = search.toLowerCase();
|
|
filteredTasks = filteredTasks.filter(task =>
|
|
task.name.toLowerCase().includes(searchTerm) ||
|
|
task.description.toLowerCase().includes(searchTerm) ||
|
|
task.materials.toLowerCase().includes(searchTerm) ||
|
|
task.tools.toLowerCase().includes(searchTerm)
|
|
);
|
|
}
|
|
|
|
// Filter efter sværhedsgrad
|
|
if (difficulty) {
|
|
filteredTasks = filteredTasks.filter(task =>
|
|
task.difficulty === difficulty
|
|
);
|
|
}
|
|
|
|
// Filter efter kategori
|
|
if (category) {
|
|
const categoryId = parseInt(category);
|
|
filteredTasks = filteredTasks.filter(task =>
|
|
task.categoryId === categoryId
|
|
);
|
|
}
|
|
|
|
// Berig med ekstra info
|
|
const enrichedTasks = filteredTasks.map(task => ({
|
|
...task,
|
|
stepCount: carpenterTasksData.taskSteps.filter(step => step.taskId === task.id).length,
|
|
categoryName: carpenterTasksData.categories.find(cat => cat.id === task.categoryId)?.name
|
|
}));
|
|
|
|
res.json({
|
|
success: true,
|
|
data: enrichedTasks,
|
|
total: enrichedTasks.length,
|
|
filters: { search, difficulty, category }
|
|
});
|
|
} catch (error) {
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
});
|
|
|
|
// Get specifik opgave med steps
|
|
app.get('/api/carpenter/task/:taskId', (req, res) => {
|
|
try {
|
|
const taskId = parseInt(req.params.taskId);
|
|
const task = carpenterTasksData.tasks.find(t => t.id === taskId);
|
|
|
|
if (!task) {
|
|
return res.status(404).json({ success: false, error: 'Opgave ikke fundet' });
|
|
}
|
|
|
|
const steps = carpenterTasksData.taskSteps
|
|
.filter(step => step.taskId === taskId)
|
|
.sort((a, b) => a.stepNumber - b.stepNumber);
|
|
|
|
const category = carpenterTasksData.categories.find(cat => cat.id === task.categoryId);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: {
|
|
...task,
|
|
categoryName: category?.name,
|
|
steps: steps,
|
|
totalEstimatedMinutes: steps.reduce((sum, step) => sum + step.estimatedMinutes, 0)
|
|
}
|
|
});
|
|
} catch (error) {
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
});
|
|
|
|
// Get materialer med søgning
|
|
app.get('/api/carpenter/materials', (req, res) => {
|
|
try {
|
|
const { search, type } = req.query;
|
|
let materials = [...carpenterTasksData.materials];
|
|
|
|
if (search) {
|
|
const searchTerm = search.toLowerCase();
|
|
materials = materials.filter(material =>
|
|
material.name.toLowerCase().includes(searchTerm) ||
|
|
material.specifications.toLowerCase().includes(searchTerm) ||
|
|
material.usage.toLowerCase().includes(searchTerm)
|
|
);
|
|
}
|
|
|
|
if (type) {
|
|
materials = materials.filter(material => material.type === type);
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
data: materials,
|
|
total: materials.length
|
|
});
|
|
} catch (error) {
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
});
|
|
|
|
// Get værktøjer med søgning
|
|
app.get('/api/carpenter/tools', (req, res) => {
|
|
try {
|
|
const { search, category } = req.query;
|
|
let tools = [...carpenterTasksData.tools];
|
|
|
|
if (search) {
|
|
const searchTerm = search.toLowerCase();
|
|
tools = tools.filter(tool =>
|
|
tool.name.toLowerCase().includes(searchTerm) ||
|
|
tool.description.toLowerCase().includes(searchTerm) ||
|
|
tool.usage.toLowerCase().includes(searchTerm)
|
|
);
|
|
}
|
|
|
|
if (category) {
|
|
tools = tools.filter(tool => tool.category === category);
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
data: tools,
|
|
total: tools.length
|
|
});
|
|
} catch (error) {
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
});
|
|
|
|
// Statistikker og oversigt
|
|
app.get('/api/carpenter/stats', (req, res) => {
|
|
try {
|
|
const stats = {
|
|
totalCategories: carpenterTasksData.categories.length,
|
|
totalTasks: carpenterTasksData.tasks.length,
|
|
totalSteps: carpenterTasksData.taskSteps.length,
|
|
totalMaterials: carpenterTasksData.materials.length,
|
|
totalTools: carpenterTasksData.tools.length,
|
|
|
|
tasksByDifficulty: {
|
|
'Begynder': carpenterTasksData.tasks.filter(t => t.difficulty === 'Begynder').length,
|
|
'Let øvet': carpenterTasksData.tasks.filter(t => t.difficulty === 'Let øvet').length,
|
|
'Erfaren': carpenterTasksData.tasks.filter(t => t.difficulty === 'Erfaren').length,
|
|
'Specialist': carpenterTasksData.tasks.filter(t => t.difficulty === 'Specialist').length
|
|
},
|
|
|
|
tasksByCategory: carpenterTasksData.categories.map(cat => ({
|
|
categoryName: cat.name,
|
|
taskCount: carpenterTasksData.tasks.filter(task => task.categoryId === cat.id).length,
|
|
avgEstimatedHours: Math.round(
|
|
carpenterTasksData.tasks
|
|
.filter(task => task.categoryId === cat.id)
|
|
.reduce((sum, task) => sum + task.estimatedHours, 0) /
|
|
carpenterTasksData.tasks.filter(task => task.categoryId === cat.id).length * 10
|
|
) / 10
|
|
})),
|
|
|
|
totalEstimatedHours: carpenterTasksData.tasks.reduce((sum, task) => sum + task.estimatedHours, 0)
|
|
};
|
|
|
|
res.json({
|
|
success: true,
|
|
data: stats
|
|
});
|
|
} catch (error) {
|
|
res.status(500).json({ success: false, error: error.message });
|
|
}
|
|
});
|
|
|
|
// Error handling
|
|
app.use((err, req, res, next) => {
|
|
console.error('Tømmer API fejl:', err);
|
|
res.status(500).json({
|
|
success: false,
|
|
error: 'Intern server fejl',
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
});
|
|
|
|
// Start server
|
|
app.listen(PORT, () => {
|
|
console.log(`🔨 Tømmer Opgave API kører på port ${PORT}`);
|
|
console.log(`📊 Statistikker:`);
|
|
console.log(` - ${carpenterTasksData.categories.length} kategorier`);
|
|
console.log(` - ${carpenterTasksData.tasks.length} opgaver`);
|
|
console.log(` - ${carpenterTasksData.taskSteps.length} detaljerede steps`);
|
|
console.log(` - ${carpenterTasksData.materials.length} materialer`);
|
|
console.log(` - ${carpenterTasksData.tools.length} værktøjer`);
|
|
console.log(`🚀 API klar til brug!`);
|
|
}); |