MIF_E31220277/denta-api/app/api/users/[userId]/route.ts

490 lines
13 KiB
TypeScript

import { NextResponse } from 'next/server';
import { Prisma } from '@/prisma/generated/client';
import db from '@/lib/db';
import { getFirebaseAdmin } from '@/lib/firebase-admin';
import { Role } from '@/config/enum';
import { getUserById, setHashPassword } from '@/helpers/user';
export async function GET(
req: Request,
props: { params: Promise<{ userId: string }> }
) {
const params = await props.params;
const { searchParams } = new URL(req.url);
const userId = searchParams.get('userId') || params.userId;
try {
if (!userId) {
return NextResponse.json(
{ error: 'User userId is required' },
{ status: 400 }
);
}
const user = await db.user.findUnique({
where: {
id: userId,
} as Prisma.UserWhereUniqueInput,
include: {
KoasProfile: {
include: {
Review: {
include: {
user: true,
},
},
},
},
PasienProfile: true,
FasilitatorProfile: true,
},
});
if (!user) {
return NextResponse.json({ error: 'User not found' }, { status: 404 });
}
// Filter profile berdasarkan role
const filteredUser = await (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 review = await db.review.findMany({
// where: {
// koasId: user.KoasProfile!.userId,
// },
// });
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
};
}
})(user);
return NextResponse.json(
{
...filteredUser,
},
{ status: 200 }
);
} catch (error) {
console.error('Error fetching user', error);
return NextResponse.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
}
}
// Perbaikan PUT method
export async function PUT(
req: Request,
props: { params: Promise<{ userId: string }> }
) {
const params = await props.params;
const { searchParams } = new URL(req.url);
const userId = searchParams.get('userId') || params.userId;
let body: any;
try {
body = await req.json();
} catch (err) {
return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 });
}
// Ambil semua field yang mungkin diupdate
const {
givenName,
familyName,
name,
email,
password,
phone,
image,
address,
role,
profile,
} = body;
try {
if (!userId) {
return NextResponse.json(
{ error: 'User Id is required' },
{ status: 400 }
);
}
// Ambil user lama
const existingUser = await db.user.findUnique({
where: { id: userId },
include: {
KoasProfile: true,
PasienProfile: true,
FasilitatorProfile: true,
},
});
if (!existingUser) {
return NextResponse.json({ error: 'User not found' }, { status: 404 });
}
// Hash password jika ada perubahan password
// let hash = existingUser.password;
// if (typeof password === 'string' && password.length > 0) {
// hash = await setHashPassword(password, existingUser.password ?? '');
// }
// Siapkan data update, gunakan data baru jika ada, jika tidak pakai data lama
const updateData: Prisma.UserUpdateInput = {
givenName: givenName !== undefined ? givenName : existingUser.givenName,
familyName:
familyName !== undefined ? familyName : existingUser.familyName,
name: name !== undefined ? name : existingUser.name,
email: email !== undefined ? email : existingUser.email,
// password: hash,
phone: phone !== undefined ? phone : existingUser.phone,
image: image !== undefined ? image : existingUser.image,
address: address !== undefined ? address : existingUser.address,
role: role !== undefined ? role : existingUser.role,
};
// Update user
const updatedUser = await db.user.update({
where: { id: String(userId) },
data: updateData,
});
// Jika role berubah, hapus profile lama dan buat profile baru
let newProfile = null;
if (role && role !== existingUser.role) {
// Hapus semua profile lama
await db.koasProfile.deleteMany({ where: { userId } });
await db.pasienProfile.deleteMany({ where: { userId } });
await db.fasilitatorProfile.deleteMany({ where: { userId } });
// Buat profile baru sesuai role
if (role === Role.Koas) {
newProfile = await db.koasProfile.create({
data: {
...(profile || {}),
userId: userId,
},
});
} else if (role === Role.Pasien) {
newProfile = await db.pasienProfile.create({
data: {
...(profile || {}),
userId: userId,
},
});
} else if (role === Role.Fasilitator) {
newProfile = await db.fasilitatorProfile.create({
data: {
...(profile || {}),
userId: userId,
},
});
} else {
return NextResponse.json({ error: 'Role not found' }, { status: 404 });
}
}
return NextResponse.json(
{
status: 'Success',
message: 'Update user successfully',
data: { user: updatedUser, ...(newProfile ? { newProfile } : {}) },
},
{ status: 200 }
);
} catch (error) {
console.error('Error updating user', error);
return NextResponse.json(
{
error: 'Internal Server Error',
message: error instanceof Error ? error.message : undefined,
},
{ status: 500 }
);
}
}
export async function PATCH(
req: Request,
props: { params: Promise<{ userId: string }> }
) {
const params = await props.params;
const { searchParams } = new URL(req.url);
const userId = searchParams.get('userId') || params.userId;
const body = await req.json();
const {
givenName,
familyName,
name,
email,
password,
phone,
image,
address,
role,
} = body;
console.log('receive body : ', body);
try {
if (!userId) {
return NextResponse.json(
{ error: 'User id is required' },
{ status: 400 }
);
}
const existingUser = await db.user.findUnique({
where: { id: userId },
include: {
KoasProfile: true,
PasienProfile: true,
FasilitatorProfile: true,
},
});
// const isOauth =
// password === null ||
// (password === undefined && existingUser?.emailVerified !== null);
if (!existingUser) {
return NextResponse.json({ error: 'User not found' }, { status: 404 });
}
const hash = await setHashPassword(password, existingUser.password);
// Update user dengan data baru
const user = await db.user.update({
where: { id: String(userId) },
data: {
givenName: givenName || existingUser.givenName,
familyName: familyName || existingUser.familyName,
name: name || existingUser.name,
email: email || existingUser.email,
password: hash || existingUser.password,
phone: phone || existingUser.phone,
image: image || existingUser.image,
address: address || existingUser.address,
role: role || existingUser.role,
} as Prisma.UserUpdateInput,
});
if (role === null) {
return NextResponse.json(
{
status: 'Success',
message: 'Update user successfully',
data: { ...user },
},
{ status: 200 }
);
}
// Operasi untuk menangani profil
if (role) {
// Hapus profil lama sebelum membuat yang baru jika role berubah
if (existingUser.role !== role) {
await db.koasProfile.deleteMany({ where: { userId } });
await db.pasienProfile.deleteMany({ where: { userId } });
await db.fasilitatorProfile.deleteMany({ where: { userId } });
let newProfile = null;
// Buat profil baru sesuai role
if (role === Role.Koas) {
newProfile = await db.koasProfile.create({
data: {
...body.profile,
userId: userId,
},
});
} else if (role === Role.Pasien) {
newProfile = await db.pasienProfile.create({
data: {
...body.profile,
userId: userId,
},
});
} else if (role === Role.Fasilitator) {
newProfile = await db.fasilitatorProfile.create({
data: {
...body.profile,
userId: userId,
},
});
} else {
return NextResponse.json(
{ error: 'Role not found' },
{ status: 404 }
);
}
return NextResponse.json(
{
status: 'Success',
message: 'Update user successfully',
data: { ...user, newProfile },
},
{ status: 200 }
);
}
}
return NextResponse.json(
{
...user,
},
{ status: 200 }
);
} catch (error) {
if (error instanceof Error) {
// console.error("Error details:", error);
return NextResponse.json(
{
error: 'Internal Server Error : ' + error.message,
},
{ status: 500 }
);
}
}
}
export async function DELETE(
req: Request,
props: { params: Promise<{ userId: string }> }
) {
const params = await props.params;
const { searchParams } = new URL(req.url);
const userId = searchParams.get('userId') || params.userId;
try {
if (!userId) {
return NextResponse.json(
{ error: 'user Id is required' },
{ status: 400 }
);
}
// Get user data before deletion
const user = await db.user.findUnique({
where: { id: userId },
});
if (!user) {
return NextResponse.json({ error: 'User not found' }, { status: 404 });
}
// Delete user from database first
await db.user.delete({
where: { id: userId },
});
// Delete user from Firebase Authentication if user exists
try {
const admin = getFirebaseAdmin();
await admin.auth().deleteUser(userId);
console.log(`Firebase user ${userId} deleted successfully`);
} catch (firebaseError: any) {
// Log Firebase error but don't fail the entire operation
// since database deletion was successful
console.error('Failed to delete Firebase user:', firebaseError);
// Check if error is because user doesn't exist in Firebase
if (firebaseError.code === 'auth/user-not-found') {
console.log(`Firebase user ${userId} was not found, continuing...`);
} else {
console.warn(
'Firebase user deletion failed, but database deletion was successful'
);
}
}
return NextResponse.json(
{
status: 'Success',
message: 'User deleted successfully',
},
{ status: 200 }
);
} catch (error) {
if (error instanceof Error) {
console.log(error.stack);
console.error('Failed to delete user:', error.stack);
return NextResponse.json(
{ error: 'Internal Server Error', message: error.message },
{ status: 500 }
);
}
// Handle case where error is not an Error instance
return NextResponse.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
}
}