update: dashboard page admin

This commit is contained in:
Nathan FONTEYNE 2026-07-09 16:48:09 +02:00
parent a1ec2263a5
commit 1f9c290010
11 changed files with 248 additions and 2 deletions

View file

@ -130,6 +130,26 @@ async function removeSong(setlistId, setlistSongId) {
]);
}
async function getStats() {
const { rows } = await pool.query(`
SELECT
COUNT(*) FILTER (WHERE concert_date < CURRENT_DATE)::int AS past_concerts,
COUNT(*) FILTER (WHERE concert_date >= CURRENT_DATE)::int AS upcoming_concerts,
COALESCE((
SELECT AVG(song_count)
FROM (
SELECT sl.id, COUNT(ss.id) AS song_count
FROM setlists sl
LEFT JOIN setlist_songs ss ON ss.setlist_id = sl.id
WHERE sl.concert_date < CURRENT_DATE
GROUP BY sl.id
) t
), 0)::numeric(10,1) AS avg_songs_per_concert
FROM setlists
`);
return rows[0];
}
module.exports = {
findNext,
findHistory,
@ -142,4 +162,5 @@ module.exports = {
replaceSongs,
addSong,
removeSong,
getStats,
};

View file

@ -75,6 +75,16 @@ async function removeTutorial(songId, tutorialId) {
]);
}
async function getStats() {
const { rows } = await pool.query(`
SELECT COUNT(*)::int AS total_songs,
COUNT(DISTINCT NULLIF(artist, ''))::int AS distinct_artists,
(SELECT COUNT(*)::int FROM song_tutorials) AS tutorials_added
FROM songs
`);
return rows[0];
}
module.exports = {
findAll,
findById,
@ -84,4 +94,5 @@ module.exports = {
findTutorials,
addTutorial,
removeTutorial,
getStats,
};

View file

@ -84,6 +84,18 @@ async function removeVote(suggestionId, userId) {
]);
}
async function getStats() {
const { rows } = await pool.query(`
SELECT COUNT(*)::int AS total,
COUNT(*) FILTER (WHERE status = 'pending')::int AS pending,
COUNT(*) FILTER (WHERE status = 'approved')::int AS approved,
COUNT(*) FILTER (WHERE status = 'rejected')::int AS rejected,
(SELECT COUNT(*)::int FROM suggestion_votes) AS total_votes
FROM suggestions
`);
return rows[0];
}
async function promoteToSong(suggestionId, addedBy) {
const client = await pool.connect();
try {
@ -134,4 +146,5 @@ module.exports = {
upsertVote,
removeVote,
promoteToSong,
getStats,
};

View file

@ -32,4 +32,19 @@ async function getActivityStats(userId) {
};
}
module.exports = { findById, upsertFromClaims, getActivityStats };
async function findAllWithActivity() {
const { rows } = await pool.query(`
SELECT u.id, u.name, u.avatar_url, u.is_admin, u.created_at, u.updated_at,
COALESCE(s.count, 0) AS songs_added,
COALESCE(sg.count, 0) AS suggestions_proposed,
COALESCE(v.count, 0) AS votes_cast
FROM users u
LEFT JOIN (SELECT added_by, COUNT(*)::int AS count FROM songs GROUP BY added_by) s ON s.added_by = u.id
LEFT JOIN (SELECT suggested_by, COUNT(*)::int AS count FROM suggestions GROUP BY suggested_by) sg ON sg.suggested_by = u.id
LEFT JOIN (SELECT user_id, COUNT(*)::int AS count FROM suggestion_votes GROUP BY user_id) v ON v.user_id = u.id
ORDER BY (COALESCE(s.count, 0) + COALESCE(sg.count, 0) + COALESCE(v.count, 0)) DESC, u.name
`);
return rows;
}
module.exports = { findById, upsertFromClaims, getActivityStats, findAllWithActivity };