Initial commit - Church Music Database
This commit is contained in:
251
new-site/backend/routes/profiles.js
Normal file
251
new-site/backend/routes/profiles.js
Normal file
@@ -0,0 +1,251 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user