Files
sst_site/.history/routes/portfolio_20251019204435.js
2025-10-22 21:22:44 +09:00

209 lines
5.1 KiB
JavaScript

const express = require('express');
const router = express.Router();
const { Portfolio } = require('../models');
const { Op } = require('sequelize');
// Get all portfolio items
router.get('/', async (req, res) => {
try {
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 12;
const skip = (page - 1) * limit;
const category = req.query.category;
const search = req.query.search;
const featured = req.query.featured;
// Build query
let whereClause = { isPublished: true };
if (category && category !== 'all') {
whereClause.category = category;
}
if (featured === 'true') {
whereClause.featured = true;
}
if (search) {
whereClause = {
...whereClause,
[Op.or]: [
{ title: { [Op.iLike]: `%${search}%` } },
{ description: { [Op.iLike]: `%${search}%` } },
{ shortDescription: { [Op.iLike]: `%${search}%` } }
]
};
}
// Get portfolio items
const [portfolio, total] = await Promise.all([
Portfolio.findAll({
where: whereClause,
order: [['featured', 'DESC'], ['publishedAt', 'DESC']],
offset: skip,
limit: limit,
attributes: ['id', 'title', 'shortDescription', 'category', 'technologies', 'images', 'status', 'publishedAt', 'viewCount']
}),
Portfolio.count({ where: whereClause })
]);
const totalPages = Math.ceil(total / limit);
res.json({
success: true,
portfolio,
pagination: {
current: page,
total: totalPages,
limit,
totalItems: total,
hasNext: page < totalPages,
hasPrev: page > 1
}
});
} catch (error) {
console.error('Portfolio API error:', error);
res.status(500).json({
success: false,
message: 'Error fetching portfolio'
});
}
});
// Get single portfolio item
router.get('/:id', async (req, res) => {
try {
const portfolio = await Portfolio.findByPk(req.params.id);
if (!portfolio || !portfolio.isPublished) {
return res.status(404).json({
success: false,
message: 'Portfolio item not found'
});
}
// Increment view count
portfolio.viewCount += 1;
await portfolio.save();
// Get related projects
const relatedProjects = await Portfolio.findAll({
where: {
id: { [Op.ne]: portfolio.id },
category: portfolio.category,
isPublished: true
},
attributes: ['id', 'title', 'shortDescription', 'images'],
limit: 3
});
res.json({
success: true,
portfolio,
relatedProjects
});
} catch (error) {
console.error('Portfolio detail API error:', error);
res.status(500).json({
success: false,
message: 'Error fetching portfolio item'
});
}
});
// Get portfolio categories
router.get('/meta/categories', async (req, res) => {
try {
const categories = await Portfolio.distinct('category', { isPublished: true });
// Get count for each category
const categoriesWithCount = await Promise.all(
categories.map(async (category) => {
const count = await Portfolio.countDocuments({
category,
isPublished: true
});
return { category, count };
})
);
res.json({
success: true,
categories: categoriesWithCount
});
} catch (error) {
console.error('Portfolio categories API error:', error);
res.status(500).json({
success: false,
message: 'Error fetching categories'
});
}
});
// Like portfolio item
router.post('/:id/like', async (req, res) => {
try {
const portfolio = await Portfolio.findByPk(req.params.id);
if (!portfolio || !portfolio.isPublished) {
return res.status(404).json({
success: false,
message: 'Portfolio item not found'
});
}
portfolio.likes += 1;
await portfolio.save();
res.json({
success: true,
likes: portfolio.likes
});
} catch (error) {
console.error('Portfolio like API error:', error);
res.status(500).json({
success: false,
message: 'Error liking portfolio item'
});
}
});
// Search portfolio
router.get('/search/:term', async (req, res) => {
try {
const searchTerm = req.params.term;
const limit = parseInt(req.query.limit) || 10;
const portfolio = await Portfolio.findAll({
where: {
[Op.and]: [
{ isPublished: true },
{
[Op.or]: [
{ title: { [Op.iLike]: `%${searchTerm}%` } },
{ description: { [Op.iLike]: `%${searchTerm}%` } },
{ technologies: { [Op.contains]: [searchTerm] } }
]
}
]
},
attributes: ['id', 'title', 'shortDescription', 'images', 'category'],
limit: limit
});
res.json({
success: true,
portfolio,
searchTerm,
count: portfolio.length
});
} catch (error) {
console.error('Portfolio search API error:', error);
res.status(500).json({
success: false,
message: 'Error searching portfolio'
});
}
});
module.exports = router;