Files
Church-Music/new-site/backend/routes/profiles.js

252 lines
6.4 KiB
JavaScript

const express = require("express");
const router = express.Router();
const { query } = require("../db");
const { v4: uuidv4 } = require("uuid");
// GET all profiles
router.get("/", async (req, res) => {
try {
const result = await query("SELECT * FROM profiles ORDER BY name ASC");
res.json({ success: true, profiles: result.rows });
} catch (err) {
console.error("Error fetching profiles:", err);
res
.status(500)
.json({ success: false, message: "Failed to fetch profiles" });
}
});
// GET single profile by ID
router.get("/:id", async (req, res) => {
try {
const result = await query("SELECT * FROM profiles WHERE id = $1", [
req.params.id,
]);
if (result.rows.length === 0) {
return res
.status(404)
.json({ success: false, message: "Profile not found" });
}
// Also get profile's songs with their preferred keys
const songsResult = await query(
`
SELECT s.*, psk.song_key as preferred_key
FROM songs s
INNER JOIN profile_songs ps ON s.id = ps.song_id
LEFT JOIN profile_song_keys psk ON ps.profile_id = psk.profile_id AND ps.song_id = psk.song_id
WHERE ps.profile_id = $1
ORDER BY s.title ASC
`,
[req.params.id],
);
res.json({
success: true,
profile: result.rows[0],
songs: songsResult.rows,
});
} catch (err) {
console.error("Error fetching profile:", err);
res
.status(500)
.json({ success: false, message: "Failed to fetch profile" });
}
});
// POST create new profile
router.post("/", async (req, res) => {
try {
const {
first_name,
last_name,
name,
email,
contact_number,
notes,
default_key,
} = req.body;
const profileName = name || `${first_name || ""} ${last_name || ""}`.trim();
if (!profileName) {
return res
.status(400)
.json({ success: false, message: "Name is required" });
}
const id = uuidv4();
const result = await query(
`INSERT INTO profiles (id, first_name, last_name, name, email, contact_number, notes, default_key)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
RETURNING *`,
[
id,
first_name || "",
last_name || "",
profileName,
email || "",
contact_number || "",
notes || "",
default_key || "C",
],
);
res.status(201).json({ success: true, profile: result.rows[0] });
} catch (err) {
console.error("Error creating profile:", err);
res
.status(500)
.json({ success: false, message: "Failed to create profile" });
}
});
// PUT update profile
router.put("/:id", async (req, res) => {
try {
const {
first_name,
last_name,
name,
email,
contact_number,
notes,
default_key,
} = req.body;
const result = await query(
`UPDATE profiles
SET first_name = COALESCE($1, first_name),
last_name = COALESCE($2, last_name),
name = COALESCE($3, name),
email = COALESCE($4, email),
contact_number = COALESCE($5, contact_number),
notes = COALESCE($6, notes),
default_key = COALESCE($7, default_key)
WHERE id = $8
RETURNING *`,
[
first_name,
last_name,
name,
email,
contact_number,
notes,
default_key,
req.params.id,
],
);
if (result.rows.length === 0) {
return res
.status(404)
.json({ success: false, message: "Profile not found" });
}
res.json({ success: true, profile: result.rows[0] });
} catch (err) {
console.error("Error updating profile:", err);
res
.status(500)
.json({ success: false, message: "Failed to update profile" });
}
});
// DELETE profile
router.delete("/:id", async (req, res) => {
try {
const result = await query(
"DELETE FROM profiles WHERE id = $1 RETURNING id",
[req.params.id],
);
if (result.rows.length === 0) {
return res
.status(404)
.json({ success: false, message: "Profile not found" });
}
res.json({ success: true, message: "Profile deleted" });
} catch (err) {
console.error("Error deleting profile:", err);
res
.status(500)
.json({ success: false, message: "Failed to delete profile" });
}
});
// POST add song to profile
router.post("/:id/songs/:songId", async (req, res) => {
try {
const { id, songId } = req.params;
const { song_key } = req.body;
const psId = uuidv4();
// Add song to profile
await query(
`INSERT INTO profile_songs (id, profile_id, song_id)
VALUES ($1, $2, $3)
ON CONFLICT (profile_id, song_id) DO NOTHING`,
[psId, id, songId],
);
// If key provided, set it
if (song_key) {
const pskId = uuidv4();
await query(
`INSERT INTO profile_song_keys (id, profile_id, song_id, song_key)
VALUES ($1, $2, $3, $4)
ON CONFLICT (profile_id, song_id) DO UPDATE SET song_key = $4`,
[pskId, id, songId, song_key],
);
}
res.json({ success: true, message: "Song added to profile" });
} catch (err) {
console.error("Error adding song to profile:", err);
res
.status(500)
.json({ success: false, message: "Failed to add song to profile" });
}
});
// DELETE remove song from profile
router.delete("/:id/songs/:songId", async (req, res) => {
try {
const { id, songId } = req.params;
await query(
"DELETE FROM profile_songs WHERE profile_id = $1 AND song_id = $2",
[id, songId],
);
await query(
"DELETE FROM profile_song_keys WHERE profile_id = $1 AND song_id = $2",
[id, songId],
);
res.json({ success: true, message: "Song removed from profile" });
} catch (err) {
console.error("Error removing song from profile:", err);
res
.status(500)
.json({ success: false, message: "Failed to remove song from profile" });
}
});
// GET profile count
router.get("/stats/count", async (req, res) => {
try {
const result = await query("SELECT COUNT(*) as count FROM profiles");
res.json({ success: true, count: parseInt(result.rows[0].count) });
} catch (err) {
console.error("Error counting profiles:", err);
res
.status(500)
.json({ success: false, message: "Failed to count profiles" });
}
});
module.exports = router;