MIF_E31220277/denta-api/app/api/users/route.ts

316 lines
8.1 KiB
TypeScript

import { Prisma } from '@/prisma/generated/client';
import { NextResponse } from 'next/server';
import db from '@/lib/db';
import bcrypt from 'bcryptjs';
import { Role } from '@/config/enum';
import { SignUpSchema } from '@/lib/schemas';
import { UserQueryString } from '@/config/types';
import { getUserByEmail, parseSearchParams, genUsername } from '@/helpers/user';
export async function GET(req: Request) {
const { searchParams } = new URL(req.url);
const query: UserQueryString = parseSearchParams(searchParams);
const isKoas = Role.Koas;
const isPasien = Role.Pasien;
const isFasilitator = Role.Fasilitator;
try {
const user = await db.user.findMany({
where: {
...query,
} as Prisma.UserWhereInput,
orderBy: {
name: 'asc',
},
include: {
KoasProfile: {
include: {
Review: {
include: {
user: true,
},
},
},
},
PasienProfile: true,
FasilitatorProfile: true,
},
});
const users = await Promise.all(
user.map(async (user) => {
if (user.role === Role.Koas) {
const totalReviews = await db.review.count({
where: {
koasId: user.KoasProfile!.userId,
},
});
const averageRating = await db.review.aggregate({
_avg: {
rating: true,
},
where: {
koasId: user.KoasProfile!.userId,
},
});
const patientCount = await db.appointment.count({
where: {
koasId: user.KoasProfile!.id,
status: 'Completed',
},
});
const { createdAt, updateAt, ...koasProfileWithoutDates } =
user.KoasProfile!;
return {
...user,
KoasProfile: {
...koasProfileWithoutDates,
stats: {
totalReviews,
averageRating: parseFloat(
(averageRating._avg.rating || 0.0).toFixed(1)
),
patientCount,
},
createdAt,
updateAt,
},
PasienProfile: undefined, // sembunyikan pasien profile
FasilitatorProfile: undefined, // sembunyikan fasilitator profile
};
} else if (user.role === Role.Pasien) {
return {
...user,
KoasProfile: undefined, // sembunyikan koas profile
FasilitatorProfile: undefined, // sembunyikan fasilitator profile
};
} else if (user.role === Role.Fasilitator) {
return {
...user,
KoasProfile: undefined, // sembunyikan koas profile
PasienProfile: undefined, // sembunyikan pasien profile
};
} else {
return {
...user,
KoasProfile: undefined, // sembunyikan koas profile
PasienProfile: undefined, // sembunyikan pasien profile
FasilitatorProfile: undefined, // sembunyikan fasilitator profile
};
}
})
);
return NextResponse.json(
{
users,
},
{ status: 200 }
);
} catch (error) {
if (error instanceof Error) {
console.error('Error fetching user', error.stack);
} else {
console.error('Error fetching user', error);
}
return NextResponse.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
}
}
export async function POST(req: Request) {
try {
const body = await req.json();
// Accept both camelCase and snake_case for names
const {
id,
givenName,
familyName,
firstName,
lastName,
email,
password,
phone,
role,
profile,
image,
name: nameFromBody,
} = body;
console.log('Received Body:', body);
// Use givenName/familyName if present, else fallback to firstName/lastName
const userGivenName = givenName ?? firstName ?? '';
const userFamilyName = familyName ?? lastName ?? '';
// Check if this is an OAuth signup (no password)
const isOauth = !password || password === null || password === undefined;
// Validate required fields
if (!email || !role) {
return NextResponse.json(
{ error: 'Email and role are required.' },
{ status: 400 }
);
}
// Check for existing user
const existingUser = await getUserByEmail(email);
if (existingUser) {
console.log(`Attempted signup with existing email: ${email}`);
return NextResponse.json(
{ error: 'Email already in use.' },
{ status: 400 }
);
}
const university = await db.university.findFirst({
where: {
alias: 'UNEJ',
},
});
if (!university) {
return NextResponse.json(
{ error: 'University not found.' },
{ status: 400 }
);
}
// Only hash password if not OAuth and password is provided
let hash: string | null = null;
if (!isOauth) {
if (typeof password !== 'string' || password.length === 0) {
return NextResponse.json(
{ error: 'Password is required for non-OAuth signup.' },
{ status: 400 }
);
}
try {
hash = await bcrypt.hash(password, 10);
} catch (err) {
console.error('Error hashing password:', err);
return NextResponse.json(
{ error: 'Failed to process password.' },
{ status: 500 }
);
}
}
// Generate username if not provided
let name = nameFromBody;
if (!name) {
name = await genUsername(userGivenName, userFamilyName);
}
// Create the user
const newUser = await db.user.create({
data: {
id,
givenName: userGivenName,
familyName: userFamilyName,
name,
email,
password: hash,
phone,
image: image ?? null,
role: role ?? null,
} as Prisma.UserCreateInput,
});
// Create profile based on role
if (newUser.role === Role.Koas) {
await db.koasProfile.create({
data: {
...profile,
university: university.name,
universityId: university.id,
userId: newUser.id,
},
});
} else if (newUser.role === Role.Pasien) {
await db.pasienProfile.create({
data: {
...profile,
userId: newUser.id,
},
});
} else if (newUser.role === Role.Fasilitator) {
await db.fasilitatorProfile.create({
data: {
...profile,
university: university.name,
userId: newUser.id,
},
});
} else if (newUser.role === Role.Admin) {
// For admin, just update emailVerified
await db.user.update({
where: { id: newUser.id },
data: {
emailVerified: new Date(),
},
});
} else {
return NextResponse.json({ error: 'Invalid role' }, { status: 400 });
}
// If OAuth, mark email as verified
if (isOauth) {
await db.user.update({
where: { id: newUser.id },
data: { emailVerified: new Date() },
});
}
return NextResponse.json(
{
status: 'Success',
message: 'User created successfully',
data: { user: newUser },
},
{ status: 201 }
);
} catch (error) {
if (error instanceof Error) {
console.error('Error in POST /api/users:', error.stack);
return NextResponse.json({ error: error.message }, { status: 500 });
} else {
console.error('Unknown error in POST /api/users:', error);
return NextResponse.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
}
}
}
export async function DELETE(req: Request) {
try {
await db.user.deleteMany({});
return NextResponse.json(
{
status: 'Success',
message: 'All users deleted successfully',
},
{ status: 200 }
);
} catch (error) {
console.error('Error deleting all users', error);
return NextResponse.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
}
}