mirror of
https://github.com/nfonteyne/octane-website.git
synced 2026-09-03 23:24:48 +02:00
106 lines
3.2 KiB
JavaScript
106 lines
3.2 KiB
JavaScript
const express = require('express');
|
|
const suggestionsRepo = require('../repositories/suggestionsRepo');
|
|
const { requireAdmin } = require('../auth/middleware');
|
|
const { isValidYoutubeUrl } = require('../lib/youtube');
|
|
const { isValidSpotifyUrl } = require('../lib/spotify');
|
|
const asyncHandler = require('../lib/asyncHandler');
|
|
|
|
const router = express.Router();
|
|
|
|
router.get(
|
|
'/',
|
|
asyncHandler(async (req, res) => {
|
|
res.json(await suggestionsRepo.findAll(req.user.id));
|
|
})
|
|
);
|
|
|
|
router.get(
|
|
'/:id',
|
|
asyncHandler(async (req, res) => {
|
|
const suggestion = await suggestionsRepo.findById(req.params.id);
|
|
if (!suggestion) return res.status(404).json({ error: 'not_found' });
|
|
const votes = await suggestionsRepo.findVotes(req.params.id);
|
|
res.json({ ...suggestion, votes });
|
|
})
|
|
);
|
|
|
|
router.post(
|
|
'/',
|
|
asyncHandler(async (req, res) => {
|
|
const { title, artist, youtubeUrl, spotifyUrl, description } = req.body || {};
|
|
if (!title || !title.trim() || !youtubeUrl || !youtubeUrl.trim()) {
|
|
return res.status(400).json({ error: 'title_and_youtube_url_required' });
|
|
}
|
|
if (!isValidYoutubeUrl(youtubeUrl.trim())) {
|
|
return res.status(400).json({ error: 'invalid_youtube_url' });
|
|
}
|
|
if (spotifyUrl && !isValidSpotifyUrl(spotifyUrl.trim())) {
|
|
return res.status(400).json({ error: 'invalid_spotify_url' });
|
|
}
|
|
const suggestion = await suggestionsRepo.create({
|
|
title: title.trim(),
|
|
artist: artist ? artist.trim() : null,
|
|
youtubeUrl: youtubeUrl.trim(),
|
|
spotifyUrl: spotifyUrl ? spotifyUrl.trim() : null,
|
|
description: description ? description.trim() : null,
|
|
suggestedBy: req.user.id,
|
|
});
|
|
res.status(201).json(suggestion);
|
|
})
|
|
);
|
|
|
|
router.patch(
|
|
'/:id',
|
|
requireAdmin,
|
|
asyncHandler(async (req, res) => {
|
|
const { status } = req.body || {};
|
|
if (!['pending', 'approved', 'rejected'].includes(status)) {
|
|
return res.status(400).json({ error: 'invalid_status' });
|
|
}
|
|
const suggestion = await suggestionsRepo.updateStatus(req.params.id, status);
|
|
if (!suggestion) return res.status(404).json({ error: 'not_found' });
|
|
res.json(suggestion);
|
|
})
|
|
);
|
|
|
|
router.delete(
|
|
'/:id',
|
|
requireAdmin,
|
|
asyncHandler(async (req, res) => {
|
|
await suggestionsRepo.remove(req.params.id);
|
|
res.status(204).end();
|
|
})
|
|
);
|
|
|
|
router.post(
|
|
'/:id/vote',
|
|
asyncHandler(async (req, res) => {
|
|
const { vote, comment } = req.body || {};
|
|
if (!['approve', 'reject'].includes(vote)) {
|
|
return res.status(400).json({ error: 'invalid_vote' });
|
|
}
|
|
const suggestion = await suggestionsRepo.findById(req.params.id);
|
|
if (!suggestion) return res.status(404).json({ error: 'not_found' });
|
|
const result = await suggestionsRepo.upsertVote(req.params.id, req.user.id, { vote, comment });
|
|
res.status(200).json(result);
|
|
})
|
|
);
|
|
|
|
router.delete(
|
|
'/:id/vote',
|
|
asyncHandler(async (req, res) => {
|
|
await suggestionsRepo.removeVote(req.params.id, req.user.id);
|
|
res.status(204).end();
|
|
})
|
|
);
|
|
|
|
router.post(
|
|
'/:id/promote',
|
|
asyncHandler(async (req, res) => {
|
|
const song = await suggestionsRepo.promoteToSong(req.params.id, req.user.id);
|
|
if (!song) return res.status(404).json({ error: 'not_found' });
|
|
res.status(201).json(song);
|
|
})
|
|
);
|
|
|
|
module.exports = router;
|