diff --git a/lib/withAuth.ts b/lib/withAuth.ts new file mode 100644 index 0000000..ab4a311 --- /dev/null +++ b/lib/withAuth.ts @@ -0,0 +1,19 @@ +import { authOptions } from "@/src/app/api/auth/[...nextauth]/route"; +import { ApiHandler } from "@/src/types"; +import { getServerSession } from "next-auth"; +import { NextResponse } from "next/server"; + +export function withAuth(handler: ApiHandler) { + return async (req: Request, context: any) => { + const session = await getServerSession(authOptions); + + if (!session?.user?.email) { + return NextResponse.json( + { success: false, message: "Unauthorized. User belum login." }, + { status: 401 }, + ); + } + + return handler(req, context, session); + }; +} diff --git a/src/app/api/product/route.ts b/src/app/api/product/route.ts index d292337..271f7d3 100644 --- a/src/app/api/product/route.ts +++ b/src/app/api/product/route.ts @@ -3,39 +3,6 @@ import { NextResponse } from "next/server"; export const dynamic = "force-dynamic"; -// export async function POST(_request: Request) { -// try { -// const products = [ -// { name: "ZenBook 14", brand: "ASUS" }, -// { name: "Swift 3", brand: "Acer" }, -// { name: "Surface Laptop 5", brand: "Microsoft" }, -// ]; - -// const result = await prisma.product.createMany({ -// data: products, -// }); - -// return NextResponse.json( -// { -// message: "Booking successful", -// data: result, -// }, -// { status: 201 }, -// ); -// } catch (error: unknown) { -// console.error("Create product error:", error); - -// if (error instanceof Prisma.PrismaClientKnownRequestError) { -// return NextResponse.json({ error: error.message }, { status: 400 }); -// } - -// return NextResponse.json( -// { error: "Internal Server Error" }, -// { status: 500 }, -// ); -// } -// } - export async function GET() { try { const count = await prisma.product.count(); diff --git a/src/app/api/profile/route.ts b/src/app/api/profile/route.ts index 784994b..83c776c 100644 --- a/src/app/api/profile/route.ts +++ b/src/app/api/profile/route.ts @@ -1,71 +1,20 @@ -import { getServerSession } from "next-auth"; import { NextResponse } from "next/server"; -import { authOptions } from "../auth/[...nextauth]/route"; -import prisma from "@/lib/prisma"; - -export async function POST(req: Request) { - const session = await getServerSession(authOptions); - - if (!session?.user?.email) { - return NextResponse.json( - { success: false, message: "Unauthorized. User belum login." }, - { status: 401 }, - ); - } - - const body = await req.json(); - - const { - name, - bio, - profession, - preferredBrand, - preferredOS, - budgetMin, - budgetMax, - } = body; - - const user = await prisma.user.findUnique({ - where: { email: session.user.email }, - select: { id: true }, - }); - - if (!user) { - return NextResponse.json( - { success: false, message: "User tidak ditemukan." }, - { status: 404 }, - ); - } +import { userService } from "@/src/services/profile.service"; +import { withAuth } from "@/lib/withAuth"; +export const POST = withAuth(async (req, _context, session) => { try { - const updatedUser = await prisma.user.update({ - where: { id: user.id }, - data: { - name, - bio, - preference: { - upsert: { - update: { - profession, - preferredBrand, - preferredOS, - budgetMin: budgetMin ? Number(budgetMin) : null, - budgetMax: budgetMax ? Number(budgetMax) : null, - }, - create: { - profession, - preferredBrand, - preferredOS, - budgetMin: budgetMin ? Number(budgetMin) : null, - budgetMax: budgetMax ? Number(budgetMax) : null, - }, - }, - }, - }, - include: { - preference: true, - }, - }); + const email = session.user?.email as string; + const body = await req.json(); + + const updatedUser = await userService.updateProfileByEmail(email, body); + + if (!updatedUser) { + return NextResponse.json( + { success: false, message: "User tidak ditemukan." }, + { status: 404 }, + ); + } return NextResponse.json({ success: true, @@ -73,44 +22,36 @@ export async function POST(req: Request) { data: updatedUser, }); } catch (error) { + console.error("[UPDATE_PROFILE_ERROR]", error); return NextResponse.json( { success: false, message: "Terjadi kesalahan server." }, { status: 500 }, ); } -} +}); -export async function GET() { - const session = await getServerSession(authOptions); +export const GET = withAuth(async (_req, _context, session) => { + try { + const email = session.user?.email as string; - if (!session?.user?.email) { + const user = await userService.getProfileByEmail(email); + + if (!user) { + return NextResponse.json( + { success: false, message: "User not found" }, + { status: 404 }, + ); + } + + return NextResponse.json({ + success: true, + data: user, + }); + } catch (error) { + console.error("[GET_PROFILE_ERROR]", error); return NextResponse.json( - { success: false, message: "Unauthorized" }, - { status: 401 }, + { success: false, message: "Terjadi kesalahan server." }, + { status: 500 }, ); } - - const user = await prisma.user.findUnique({ - where: { email: session.user.email }, - include: { - preference: { - select: { - preferredBrand: true, - preferredOS: true, - profession: true, - budgetMax: true, - budgetMin: true, - }, - }, - }, - }); - - if (!user) { - return NextResponse.json( - { success: false, message: "User not found" }, - { status: 404 }, - ); - } - - return NextResponse.json(user); -} +}); diff --git a/src/app/api/review/route.ts b/src/app/api/review/route.ts index 9163c3c..ba1d958 100644 --- a/src/app/api/review/route.ts +++ b/src/app/api/review/route.ts @@ -1,45 +1,13 @@ -import prisma from "@/lib/prisma"; -import { Prisma, Sentiment } from "@prisma/client"; -import { getServerSession } from "next-auth"; +import { Prisma } from "@prisma/client"; import { NextResponse } from "next/server"; -import { authOptions } from "../auth/[...nextauth]/route"; +import { getReviewService, reviewService } from "@/src/services/review.service"; +import { withAuth } from "@/lib/withAuth"; export const dynamic = "force-dynamic"; -export async function POST(_request: Request) { +export const POST = async () => { try { - const reviews = [ - { - productId: 2, - modelId: 1, - content: - "Laptop ini sangat ringan dan performanya cepat untuk kerja harian.", - keywords: ["ringan", "cepat", "kerja"], - sentiment: Sentiment.POSITIVE, - confidenceScore: 0.92, - }, - { - productId: 3, - modelId: 1, - content: "Baterainya awet, tapi harganya cukup mahal.", - keywords: ["baterai", "awet", "mahal"], - sentiment: Sentiment.NEUTRAL, - confidenceScore: 0.75, - }, - { - productId: 4, - modelId: 1, - content: "Performa kurang stabil dan sering panas.", - keywords: ["performa", "panas", "stabil"], - sentiment: Sentiment.NEGATIVE, - confidenceScore: 0.88, - }, - ]; - - const result = await prisma.review.createMany({ - data: reviews, - }); - + const result = await reviewService(); return NextResponse.json( { message: "Analysis successful", @@ -59,51 +27,13 @@ export async function POST(_request: Request) { { status: 500 }, ); } -} - -export async function GET() { - const session = await getServerSession(authOptions); - - if (!session?.user?.email) { - return NextResponse.json( - { success: false, message: "Unauthorized. User belum login." }, - { status: 401 }, - ); - } - - const user = await prisma.user.findUnique({ - where: { email: session.user.email }, - select: { id: true }, - }); - - if (!user) { - return NextResponse.json( - { success: false, message: "User tidak ditemukan." }, - { status: 404 }, - ); - } +}; +export const GET = withAuth(async (_req, _context, session) => { try { - const review = await prisma.review.findMany({ - where: { userId: user.id }, - orderBy: { - createdAt: "asc", - }, - select: { - id: true, - createdAt: true, - confidenceScore: true, - sentiment: true, - content: true, - keywords: true, - product: { - select: { - name: true, - brand: true, - }, - }, - }, - }); + const email = session.user?.email as string; + + const review = await getReviewService(email); return NextResponse.json( { @@ -116,4 +46,4 @@ export async function GET() { console.log(error); return NextResponse.json({ message: "Error", data: [] }, { status: 500 }); } -} +}); diff --git a/src/app/api/review/sentiment-stats/route.ts b/src/app/api/review/sentiment-stats/route.ts index 14f86bc..87256d6 100644 --- a/src/app/api/review/sentiment-stats/route.ts +++ b/src/app/api/review/sentiment-stats/route.ts @@ -1,52 +1,12 @@ -import prisma from "@/lib/prisma"; import { NextResponse } from "next/server"; -import { getServerSession } from "next-auth"; -import { authOptions } from "../../auth/[...nextauth]/route"; +import { withAuth } from "@/lib/withAuth"; +import { sentimentStatsService } from "@/src/services/sentimentStats.service"; -export async function GET() { +export const GET = withAuth(async (_req, _context, session) => { try { - const session = await getServerSession(authOptions); + const email = session.user?.email as string; - if (!session?.user?.email) { - return NextResponse.json( - { success: false, message: "Unauthorized. User belum login." }, - { status: 401 }, - ); - } - - const user = await prisma.user.findUnique({ - where: { email: session.user.email }, - select: { id: true }, - }); - - if (!user) { - return NextResponse.json( - { success: false, message: "User tidak ditemukan." }, - { status: 404 }, - ); - } - - const grouped = await prisma.review.groupBy({ - by: ["sentiment"], - where: { - userId: user.id, - }, - _count: { - _all: true, - }, - }); - - const result = { - positive: 0, - negative: 0, - neutral: 0, - }; - - grouped.forEach((item) => { - if (item.sentiment === "POSITIVE") result.positive = item._count._all; - if (item.sentiment === "NEGATIVE") result.negative = item._count._all; - if (item.sentiment === "NEUTRAL") result.neutral = item._count._all; - }); + const result = await sentimentStatsService(email); return NextResponse.json({ success: true, data: result }, { status: 200 }); } catch (error) { @@ -56,4 +16,4 @@ export async function GET() { { status: 500 }, ); } -} +}); diff --git a/src/app/api/word-cloud/route.ts b/src/app/api/word-cloud/route.ts index 35fa16c..f801671 100644 --- a/src/app/api/word-cloud/route.ts +++ b/src/app/api/word-cloud/route.ts @@ -1,42 +1,14 @@ -import prisma from "@/lib/prisma"; import { NextResponse } from "next/server"; -import { getServerSession } from "next-auth"; -import { authOptions } from "../auth/[...nextauth]/route"; +import { withAuth } from "@/lib/withAuth"; +import { wordCloudService } from "@/src/services/wordCloud.service"; -export async function GET() { +export const GET = withAuth(async (_req, _context, session) => { try { - const session = await getServerSession(authOptions); + const email = session.user?.email as string; - if (!session?.user?.email) { - return NextResponse.json( - { success: false, message: "Unauthorized" }, - { status: 401 }, - ); - } + const allKeywords = await wordCloudService(email); - const user = await prisma.user.findUnique({ - where: { email: session.user.email }, - select: { id: true }, - }); - - if (!user) { - return NextResponse.json( - { success: false, message: "User not found" }, - { status: 404 }, - ); - } - - const analyses = await prisma.analysis.findMany({ - where: { userId: user.id }, - select: { topKeywords: true }, - }); - - const allKeywords: string[] = analyses.flatMap((a) => { - if (Array.isArray(a.topKeywords)) { - return a.topKeywords.filter((k): k is string => typeof k === "string"); - } - return []; - }); + console.log(allKeywords); return NextResponse.json( { success: true, data: allKeywords }, @@ -49,4 +21,4 @@ export async function GET() { { status: 500 }, ); } -} +}); diff --git a/src/components/dashboards/Header.tsx b/src/components/dashboards/Header.tsx index 0f9696c..8a86c7b 100644 --- a/src/components/dashboards/Header.tsx +++ b/src/components/dashboards/Header.tsx @@ -48,7 +48,7 @@ export function Header() {