From 125c18a00014eb0f3570acbfe77fa371dee66bcf Mon Sep 17 00:00:00 2001 From: Mahen Date: Mon, 2 Mar 2026 10:06:20 +0700 Subject: [PATCH] refactor(frontend): integrate ABSA payload and remove profession selection logic --- src/app/validation/analyze.schema.ts | 12 +--- src/hooks/useAnalyzeText.ts | 93 +++++++++++++++++++++------- src/services/analyze.service.ts | 46 +++++++++----- src/types/index.ts | 39 +++++++++++- 4 files changed, 140 insertions(+), 50 deletions(-) diff --git a/src/app/validation/analyze.schema.ts b/src/app/validation/analyze.schema.ts index 31750f4..4cc337d 100644 --- a/src/app/validation/analyze.schema.ts +++ b/src/app/validation/analyze.schema.ts @@ -14,17 +14,11 @@ import z from "zod"; // "OTHER", // ]); -const professionEnum = z.enum([ - "PROGRAMMER", - "STUDENT", - "GAMER", - "DESIGNER", - "OTHER", -]); +// cony export const analyzeSchema = z.object({ - profession: professionEnum, -// brands: brandEnum, + // profession: professionEnum, + // brands: brandEnum, url1: z.string().min(10, "Tautan 1 minimal 10 karakter"), url2: z.string().min(10, "Tautan 2 minimal 10 karakter"), url3: z.string().optional().or(z.literal("")), diff --git a/src/hooks/useAnalyzeText.ts b/src/hooks/useAnalyzeText.ts index 7d1fb77..a9c61d0 100644 --- a/src/hooks/useAnalyzeText.ts +++ b/src/hooks/useAnalyzeText.ts @@ -36,29 +36,66 @@ export const useAnalyseText = () => { }, }); - useEffect(() => { - const fetchProfession = async () => { - try { - const user = await getAnotherUserData(); + // useEffect(() => { + // const fetchProfession = async () => { + // try { + // const user = await getAnotherUserData(); - const userProfession = - user?.preference?.profession || user?.preference?.profession; + // const userProfession = + // user?.preference?.profession || user?.preference?.profession; - if (userProfession) { - setValue("profession", userProfession, { - shouldValidate: true, - shouldDirty: true, - }); - } - } catch (error) { - console.error("Gagal mengambil data profesi user:", error); - } - }; + // if (userProfession) { + // setValue("profession", userProfession, { + // shouldValidate: true, + // shouldDirty: true, + // }); + // } + // } catch (error) { + // console.error("Gagal mengambil data profesi user:", error); + // } + // }; - if (session?.user) { - fetchProfession(); - } - }, [session, setValue]); + // if (session?.user) { + // fetchProfession(); + // } + // }, [session, setValue]); + + // const onSubmit = async (data: AnalyzeFormData) => { + // if (!session?.user?.email) { + // alert("Anda harus login terlebih dahulu."); + // return; + // } + + // setLoading(true); + // setResult(null); + + // try { + // const urlsToScrape = [data.url1, data.url2, data.url3].filter( + // (url) => url && url.trim() !== "", + // ) as string[]; + + // const scrapePromises = urlsToScrape.map((url) => scrapeProduct(url)); + // const scrapeResults = await Promise.all(scrapePromises); + + // const candidates = scrapeResults.map((res) => ({ + // name: res.data.name, + // url: res.data.url, + // reviews: res.data.reviews, + // })); + + // const aiResult = await getAIRecommendation({ + // user_email: session.user.email, + // // profession: data.profession, + // candidates, + // }); + + // setResult(aiResult); + // } catch (error: any) { + // alert("Terjadi kesalahan: " + error.message); + // } finally { + // setLoading(false); + // } + // }; const onSubmit = async (data: AnalyzeFormData) => { if (!session?.user?.email) { @@ -67,7 +104,7 @@ export const useAnalyseText = () => { } setLoading(true); - setResult(null); + setResult(null); try { const urlsToScrape = [data.url1, data.url2, data.url3].filter( @@ -85,13 +122,21 @@ export const useAnalyseText = () => { const aiResult = await getAIRecommendation({ user_email: session.user.email, - profession: data.profession, - candidates, + candidates: candidates, }); setResult(aiResult); + + setTimeout(() => { + document + .getElementById("analysis-result") + ?.scrollIntoView({ behavior: "smooth" }); + }, 100); } catch (error: any) { - alert("Terjadi kesalahan: " + error.message); + console.error("Analysis Error:", error); + alert( + "Terjadi kesalahan: " + (error.message || "Gagal menganalisis ulasan."), + ); } finally { setLoading(false); } diff --git a/src/services/analyze.service.ts b/src/services/analyze.service.ts index 2a4a9b8..e9b4ec5 100644 --- a/src/services/analyze.service.ts +++ b/src/services/analyze.service.ts @@ -1,4 +1,5 @@ import prisma from "@/lib/prisma"; +import { AIRecommendationResponse } from "../types"; export const scrapeProduct = async (url: string) => { const res = await fetch("/api/scrape", { @@ -18,24 +19,23 @@ export const scrapeProduct = async (url: string) => { return data; }; -export const getAIRecommendation = async (payload: { - user_email: string; - profession: string; - candidates: { name: string; url: string; reviews: any[] }[]; -}) => { - const aiRes = await fetch("http://localhost:8000/recommend", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(payload), - }); +// export const getAIRecommendation = async (payload: { +// user_email: string; +// // profession: string; +// candidates: { name: string; url: string; reviews: any[] }[]; +// }) => { +// const aiRes = await fetch("http://localhost:8000/recommend", { +// method: "POST", +// headers: { "Content-Type": "application/json" }, +// body: JSON.stringify(payload), +// }); - if (!aiRes.ok) throw new Error("Gagal melakukan analisis AI"); +// if (!aiRes.ok) throw new Error("Gagal melakukan analisis AI"); - return await aiRes.json(); -}; +// return await aiRes.json(); +// }; export const getAnalysisData = async (email: string) => { - const userAnalyses = await prisma.analysis.findMany({ where: { user: { @@ -64,3 +64,21 @@ export const getAnalysisData = async (email: string) => { }); return userAnalyses; }; + +export const getAIRecommendation = async (payload: { + user_email: string; + candidates: { name: string; url: string; reviews: string[] }[]; +}): Promise => { + const aiRes = await fetch("http://localhost:8000/recommend", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload), + }); + + if (!aiRes.ok) { + const errorData = await aiRes.json(); + throw new Error(errorData.detail || "Gagal melakukan analisis AI"); + } + + return await aiRes.json(); +}; diff --git a/src/types/index.ts b/src/types/index.ts index 07f9616..b71755b 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -198,10 +198,43 @@ export interface ProductDetail { top_keywords: string[]; } -export interface AnalysisResults { - profession_target: string; +// export interface AnalysisResults { +// // profession_target: string; +// winning_product: string; +// details: ProductDetail[]; +// } + +export interface AspectScores { + performa: number; + layar: number; + baterai: number; + harga: number; +} + +export interface ProductAnalysisResult { + name: string; + url: string; + general_score: number; + aspect_scores: AspectScores; + verdict: string; + description: string; + total_reviews: number; + positive_count: number; + negative_count: number; +} + +export interface AIRecommendationResponse { + user_email: string; + analysis_type: string; winning_product: string; - details: ProductDetail[]; + details: ProductAnalysisResult[]; +} + +export interface AnalysisResults { + user_email: string; + analysis_type: string; + winning_product: string; + details: ProductAnalysisResult[]; } export interface ResultProps {