192 lines
5.0 KiB
JavaScript
192 lines
5.0 KiB
JavaScript
const pool = require("../db/pool");
|
|
|
|
// Get all households a user belongs to
|
|
exports.getUserHouseholds = async (userId) => {
|
|
const result = await pool.query(
|
|
`SELECT
|
|
h.id,
|
|
h.name,
|
|
h.invite_code,
|
|
h.created_at,
|
|
hm.role,
|
|
hm.joined_at,
|
|
(SELECT COUNT(*) FROM household_members WHERE household_id = h.id) as member_count
|
|
FROM households h
|
|
JOIN household_members hm ON h.id = hm.household_id
|
|
WHERE hm.user_id = $1
|
|
ORDER BY hm.joined_at DESC`,
|
|
[userId]
|
|
);
|
|
return result.rows;
|
|
};
|
|
|
|
// Get household by ID (with member check)
|
|
exports.getHouseholdById = async (householdId, userId) => {
|
|
const result = await pool.query(
|
|
`SELECT
|
|
h.id,
|
|
h.name,
|
|
h.invite_code,
|
|
h.created_at,
|
|
h.created_by,
|
|
hm.role as user_role,
|
|
(SELECT COUNT(*) FROM household_members WHERE household_id = h.id) as member_count
|
|
FROM households h
|
|
LEFT JOIN household_members hm ON h.id = hm.household_id AND hm.user_id = $2
|
|
WHERE h.id = $1`,
|
|
[householdId, userId]
|
|
);
|
|
return result.rows[0];
|
|
};
|
|
|
|
// Create new household
|
|
exports.createHousehold = async (name, createdBy) => {
|
|
// Generate random 6-digit invite code
|
|
const inviteCode = 'H' + Math.random().toString(36).substring(2, 8).toUpperCase();
|
|
|
|
const result = await pool.query(
|
|
`INSERT INTO households (name, created_by, invite_code)
|
|
VALUES ($1, $2, $3)
|
|
RETURNING id, name, invite_code, created_at`,
|
|
[name, createdBy, inviteCode]
|
|
);
|
|
|
|
// Add creator as admin
|
|
await pool.query(
|
|
`INSERT INTO household_members (household_id, user_id, role)
|
|
VALUES ($1, $2, 'admin')`,
|
|
[result.rows[0].id, createdBy]
|
|
);
|
|
|
|
return result.rows[0];
|
|
};
|
|
|
|
// Update household
|
|
exports.updateHousehold = async (householdId, updates) => {
|
|
const { name } = updates;
|
|
const result = await pool.query(
|
|
`UPDATE households
|
|
SET name = COALESCE($1, name)
|
|
WHERE id = $2
|
|
RETURNING id, name, invite_code, created_at`,
|
|
[name, householdId]
|
|
);
|
|
return result.rows[0];
|
|
};
|
|
|
|
// Delete household
|
|
exports.deleteHousehold = async (householdId) => {
|
|
await pool.query('DELETE FROM households WHERE id = $1', [householdId]);
|
|
};
|
|
|
|
// Refresh invite code
|
|
exports.refreshInviteCode = async (householdId) => {
|
|
const inviteCode = 'H' + Math.random().toString(36).substring(2, 8).toUpperCase();
|
|
const result = await pool.query(
|
|
`UPDATE households
|
|
SET invite_code = $1, code_expires_at = NULL
|
|
WHERE id = $2
|
|
RETURNING id, name, invite_code`,
|
|
[inviteCode, householdId]
|
|
);
|
|
return result.rows[0];
|
|
};
|
|
|
|
// Join household via invite code
|
|
exports.joinHousehold = async (inviteCode, userId) => {
|
|
const householdResult = await pool.query(
|
|
`SELECT id, name FROM households
|
|
WHERE invite_code = $1
|
|
AND (code_expires_at IS NULL OR code_expires_at > NOW())`,
|
|
[inviteCode]
|
|
);
|
|
|
|
|
|
if (householdResult.rows.length === 0) return null;
|
|
|
|
const household = householdResult.rows[0];
|
|
|
|
const existingMember = await pool.query(
|
|
`SELECT id FROM household_members
|
|
WHERE household_id = $1 AND user_id = $2`,
|
|
[household.id, userId]
|
|
);
|
|
|
|
if (existingMember.rows.length > 0) return { ...household, alreadyMember: true };
|
|
|
|
|
|
// Add as user role
|
|
await pool.query(
|
|
`INSERT INTO household_members (household_id, user_id, role)
|
|
VALUES ($1, $2, 'user')`,
|
|
[household.id, userId]
|
|
);
|
|
|
|
return { ...household, alreadyMember: false };
|
|
};
|
|
|
|
// Get household members
|
|
exports.getHouseholdMembers = async (householdId) => {
|
|
const result = await pool.query(
|
|
`SELECT
|
|
u.id,
|
|
u.username,
|
|
u.name,
|
|
u.display_name,
|
|
hm.role,
|
|
hm.joined_at
|
|
FROM household_members hm
|
|
JOIN users u ON hm.user_id = u.id
|
|
WHERE hm.household_id = $1
|
|
ORDER BY
|
|
CASE hm.role
|
|
WHEN 'admin' THEN 1
|
|
WHEN 'user' THEN 2
|
|
END,
|
|
hm.joined_at ASC`,
|
|
[householdId]
|
|
);
|
|
return result.rows;
|
|
};
|
|
|
|
// Update member role
|
|
exports.updateMemberRole = async (householdId, userId, newRole) => {
|
|
const result = await pool.query(
|
|
`UPDATE household_members
|
|
SET role = $1
|
|
WHERE household_id = $2 AND user_id = $3
|
|
RETURNING user_id, role`,
|
|
[newRole, householdId, userId]
|
|
);
|
|
return result.rows[0];
|
|
};
|
|
|
|
// Remove member from household
|
|
exports.removeMember = async (householdId, userId) => {
|
|
await pool.query(
|
|
`DELETE FROM household_members
|
|
WHERE household_id = $1 AND user_id = $2`,
|
|
[householdId, userId]
|
|
);
|
|
};
|
|
|
|
// Get user's role in household
|
|
exports.getUserRole = async (householdId, userId) => {
|
|
const result = await pool.query(
|
|
`SELECT role FROM household_members
|
|
WHERE household_id = $1 AND user_id = $2`,
|
|
[householdId, userId]
|
|
);
|
|
return result.rows[0]?.role || null;
|
|
};
|
|
|
|
// Check if user is household member
|
|
exports.isHouseholdMember = async (householdId, userId) => {
|
|
const result = await pool.query(
|
|
`SELECT 1 FROM household_members
|
|
WHERE household_id = $1 AND user_id = $2`,
|
|
[householdId, userId]
|
|
);
|
|
return result.rows.length > 0;
|
|
};
|