- Families: add "New Family" button - Users: add "Add User" form with family selector - Add delete user option - Include member_id for proper removal Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
113 lines
No EOL
3.4 KiB
TypeScript
113 lines
No EOL
3.4 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { sql } from "@/db";
|
|
|
|
// GET all users
|
|
export async function GET(request: Request) {
|
|
try {
|
|
const authHeader = request.headers.get("authorization");
|
|
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
}
|
|
|
|
// Get all users
|
|
const users = await sql`
|
|
SELECT
|
|
u.id,
|
|
u.email,
|
|
u.name,
|
|
fm.family_id,
|
|
fm.id as member_id,
|
|
f.name as family_name,
|
|
u.created_at
|
|
FROM users u
|
|
LEFT JOIN family_members fm ON fm.user_id = u.id
|
|
LEFT JOIN families f ON f.id = fm.family_id
|
|
ORDER BY u.created_at DESC
|
|
`;
|
|
|
|
return NextResponse.json({
|
|
users: users.map((u: any) => ({
|
|
id: u.id,
|
|
email: u.email,
|
|
name: u.name,
|
|
familyId: u.family_id,
|
|
memberId: u.member_id,
|
|
familyName: u.family_name,
|
|
createdAt: u.created_at ? new Date(u.created_at).toISOString() : null,
|
|
})),
|
|
});
|
|
} catch (error) {
|
|
console.error("Admin users error:", error);
|
|
return NextResponse.json({ error: String(error) }, { status: 500 });
|
|
}
|
|
}
|
|
|
|
// Create user or add to family
|
|
export async function POST(request: Request) {
|
|
try {
|
|
const authHeader = request.headers.get("authorization");
|
|
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
}
|
|
|
|
const body = await request.json();
|
|
const { email, familyId, role, name } = body;
|
|
|
|
if (!email) {
|
|
return NextResponse.json({ error: "email required" }, { status: 400 });
|
|
}
|
|
|
|
// Check if user exists
|
|
let existing = await sql`SELECT id FROM users WHERE email = ${email}`;
|
|
let userId = existing?.[0]?.id;
|
|
|
|
if (!userId) {
|
|
userId = crypto.randomUUID();
|
|
await sql`
|
|
INSERT INTO users (id, email, name, created_at, updated_at)
|
|
VALUES (${userId}, ${email}, ${name || email}, NOW(), NOW())
|
|
`;
|
|
}
|
|
|
|
// Add to family if familyId provided
|
|
if (familyId) {
|
|
await sql`
|
|
INSERT INTO family_members (id, family_id, user_id, role, display_name, created_at)
|
|
VALUES (${crypto.randomUUID()}, ${familyId}, ${userId}, ${role || 'caregiver'}, ${name || email}, NOW())
|
|
ON CONFLICT DO NOTHING
|
|
`;
|
|
}
|
|
|
|
return NextResponse.json({ success: true, userId });
|
|
} catch (error) {
|
|
console.error("Admin users error:", error);
|
|
return NextResponse.json({ error: String(error) }, { status: 500 });
|
|
}
|
|
}
|
|
|
|
// Remove user from family
|
|
export async function DELETE(request: Request) {
|
|
try {
|
|
const authHeader = request.headers.get("authorization");
|
|
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
}
|
|
|
|
const { searchParams } = new URL(request.url);
|
|
const memberId = searchParams.get("memberId");
|
|
const userId = searchParams.get("userId");
|
|
|
|
if (memberId) {
|
|
await sql`DELETE FROM family_members WHERE id = ${memberId}`;
|
|
} else if (userId) {
|
|
// Delete user entirely (careful!)
|
|
await sql`DELETE FROM family_members WHERE user_id = ${userId}`;
|
|
await sql`DELETE FROM users WHERE id = ${userId}`;
|
|
}
|
|
|
|
return NextResponse.json({ success: true });
|
|
} catch (error) {
|
|
console.error("Admin delete error:", error);
|
|
return NextResponse.json({ error: String(error) }, { status: 500 });
|
|
}
|
|
} |