fix: reformat eslint issues
This commit is contained in:
parent
126772beca
commit
9029319096
|
|
@ -1,9 +1,10 @@
|
|||
import prisma from "@/lib/prisma";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export async function POST(request: Request) {
|
||||
export async function POST(_request: Request) {
|
||||
try {
|
||||
const products = [
|
||||
{ name: "ZenBook 14", brand: "ASUS" },
|
||||
|
|
@ -22,8 +23,13 @@ export async function POST(request: Request) {
|
|||
},
|
||||
{ status: 201 },
|
||||
);
|
||||
} catch (error: any) {
|
||||
console.error("Create product Error:", error);
|
||||
} 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 },
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import prisma from "@/lib/prisma";
|
||||
import { Sentiment } from "@prisma/client";
|
||||
import { Prisma, Sentiment } from "@prisma/client";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export async function POST(request: Request) {
|
||||
export async function POST(_request: Request) {
|
||||
try {
|
||||
const reviews = [
|
||||
{
|
||||
|
|
@ -40,13 +40,18 @@ export async function POST(request: Request) {
|
|||
|
||||
return NextResponse.json(
|
||||
{
|
||||
message: "Booking successful",
|
||||
message: "Analysis successful",
|
||||
data: result,
|
||||
},
|
||||
{ status: 201 },
|
||||
);
|
||||
} catch (error: any) {
|
||||
console.error("Create product Error:", error);
|
||||
} catch (error: unknown) {
|
||||
console.error("Create analysis error:", error);
|
||||
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
return NextResponse.json({ error: error.message }, { status: 400 });
|
||||
}
|
||||
|
||||
return NextResponse.json(
|
||||
{ error: "Internal Server Error" },
|
||||
{ status: 500 },
|
||||
|
|
|
|||
|
|
@ -1,25 +1,14 @@
|
|||
import type { Metadata } from "next";
|
||||
import { Geist, Geist_Mono, Inter } from "next/font/google";
|
||||
import { Inter } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import Providers from "./providers";
|
||||
|
||||
const geistSans = Geist({
|
||||
variable: "--font-geist-sans",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
const geistMono = Geist_Mono({
|
||||
variable: "--font-geist-mono",
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Create Next App",
|
||||
description: "Generated by create next app",
|
||||
};
|
||||
|
||||
const inter = Inter({ subsets: ["latin"], variable: "--font-inter" });
|
||||
// lalu di body: <body className={`${inter.variable} font-sans`}>
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { CLabelProps } from "@/src/types";
|
||||
|
||||
const renderCustomLabel = ({
|
||||
cx,
|
||||
cy,
|
||||
|
|
@ -5,7 +7,7 @@ const renderCustomLabel = ({
|
|||
innerRadius,
|
||||
outerRadius,
|
||||
percent,
|
||||
}: any) => {
|
||||
}: CLabelProps) => {
|
||||
if (percent < 0.05) return null;
|
||||
const RADIAN = Math.PI / 180;
|
||||
const radius = innerRadius + (outerRadius - innerRadius) * 0.5;
|
||||
|
|
|
|||
|
|
@ -1,16 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import { Header } from "./Header";
|
||||
import {
|
||||
Frown,
|
||||
Meh,
|
||||
MessageSquareText,
|
||||
Minus,
|
||||
Smile,
|
||||
ThumbsDown,
|
||||
ThumbsUp,
|
||||
TrendingUp,
|
||||
} from "lucide-react";
|
||||
import { Frown, Meh, MessageSquareText, Smile, TrendingUp } from "lucide-react";
|
||||
import { StatCard } from "./StatCard";
|
||||
import {
|
||||
brandData,
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ export function ReviewTable() {
|
|||
</TableCell>
|
||||
|
||||
<TableCell className="align-top">
|
||||
{getSentimentBadge(review.sentiment as any)}
|
||||
{getSentimentBadge(review.sentiment ?? null)}
|
||||
</TableCell>
|
||||
|
||||
<TableCell className="align-top">
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ export default function SentimentForm() {
|
|||
model XGBoost
|
||||
</p>
|
||||
|
||||
<form onSubmit={(e) => e.preventDefault()}>
|
||||
<form onSubmit={analyzeText}>
|
||||
<div className="space-y-4">
|
||||
{error && (
|
||||
<div className="p-3 text-sm text-red-600 bg-red-50 border border-red-200 rounded-md flex items-center gap-2">
|
||||
|
|
@ -76,7 +76,7 @@ export default function SentimentForm() {
|
|||
<ComboboxContent className="bg-card border-border shadow-lg animate-in fade-in zoom-in-95 duration-200 z-50">
|
||||
{filteredItems.length === 0 && (
|
||||
<ComboboxEmpty className="text-muted-foreground py-3 px-4 text-sm text-center">
|
||||
Model "{searchQuery}" tidak ditemukan.
|
||||
{` Model "${searchQuery}" tidak ditemukan.`}
|
||||
</ComboboxEmpty>
|
||||
)}
|
||||
<ComboboxList className="p-1">
|
||||
|
|
@ -119,7 +119,7 @@ export default function SentimentForm() {
|
|||
/>
|
||||
|
||||
<Button
|
||||
onClick={analyzeText}
|
||||
type="submit"
|
||||
disabled={!isFormValid || isAnalyzing}
|
||||
className="w-full gap-2"
|
||||
>
|
||||
|
|
@ -152,11 +152,9 @@ export default function SentimentForm() {
|
|||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
{(() => {
|
||||
const {
|
||||
icon: Icon,
|
||||
bgClass,
|
||||
textClass,
|
||||
} = getSentimentDisplay(result.sentiment);
|
||||
const { icon: Icon, textClass } = getSentimentDisplay(
|
||||
result.sentiment,
|
||||
);
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { useTrendChart } from "@/src/hooks/useTrendChart";
|
||||
import { TrendChartProps } from "@/src/types";
|
||||
import {
|
||||
Area,
|
||||
|
|
@ -15,7 +14,7 @@ import {
|
|||
import TrendChartTooltip from "./TrendChartToolTip";
|
||||
|
||||
export function TrendChart({ data }: TrendChartProps) {
|
||||
const { isMounted } = useTrendChart();
|
||||
const isMounted = true;
|
||||
|
||||
if (!isMounted) {
|
||||
return <div className="h-87.5 w-full bg-transparent" />;
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
import { TrendChartTooltipProps } from "@/src/types";
|
||||
import React from "react";
|
||||
import { LegendPayloadItem, TrendChartTooltipProps } from "@/src/types";
|
||||
|
||||
const TrendChartTooltip: React.FC<TrendChartTooltipProps> = ({
|
||||
const TrendChartTooltip = ({
|
||||
active,
|
||||
payload,
|
||||
label,
|
||||
}) => {
|
||||
}: TrendChartTooltipProps) => {
|
||||
if (active && payload && payload.length) {
|
||||
return (
|
||||
<div className="rounded-lg border bg-card px-4 py-3 shadow-lg">
|
||||
<p className="mb-2 font-semibold text-foreground">{label}</p>
|
||||
{payload.map((item: any, index: number) => (
|
||||
{payload.map((item: LegendPayloadItem, index: number) => (
|
||||
<div key={index} className="flex items-center gap-2 text-sm">
|
||||
<div
|
||||
className="h-3 w-3 rounded-full"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ import { useWordCloud } from "@/src/hooks/useWordCloud";
|
|||
import WordCloudItem from "./WordCloudItem";
|
||||
|
||||
export function WordCloud() {
|
||||
const { mounted, maxValue, minValue, shuffledWords } = useWordCloud();
|
||||
const mounted = true;
|
||||
const { maxValue, minValue, shuffledWords } = useWordCloud();
|
||||
|
||||
if (!mounted) {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ export const useSentimentForm = () => {
|
|||
|
||||
const isFormValid = selectedModel && laptopName.trim() && text.trim();
|
||||
|
||||
const analyzeText = async (e: any) => {
|
||||
const analyzeText = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
if (!isFormValid) return;
|
||||
|
||||
|
|
@ -54,9 +54,14 @@ export const useSentimentForm = () => {
|
|||
confidence: data.confidenceScore,
|
||||
keywords: data.keywords || [],
|
||||
});
|
||||
} catch (err) {
|
||||
} catch (err: unknown) {
|
||||
console.error("Failed to analyze:", err);
|
||||
setError("Gagal menghubungi server. Pastikan API berjalan.");
|
||||
|
||||
if (err instanceof Error) {
|
||||
setError(err.message);
|
||||
} else {
|
||||
setError("Gagal menghubungi server. Pastikan API berjalan.");
|
||||
}
|
||||
} finally {
|
||||
setIsAnalyzing(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { useEffect, useState } from "react";
|
||||
// import { useEffect, useState } from "react";
|
||||
|
||||
export const useTrendChart = () => {
|
||||
const [isMounted, setIsMounted] = useState(false);
|
||||
useEffect(() => {
|
||||
setIsMounted(true);
|
||||
}, []);
|
||||
return { isMounted, setIsMounted };
|
||||
};
|
||||
// export const useTrendChart = () => {
|
||||
// const isMounted = true;
|
||||
// useEffect(() => {
|
||||
// setIsMounted(true);
|
||||
// }, []);
|
||||
// return { isMounted, setIsMounted };
|
||||
// };
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import {
|
||||
KeywordStats,
|
||||
Review,
|
||||
|
|
@ -9,12 +9,11 @@ import {
|
|||
import { WORD_LIMIT } from "../utils/datas";
|
||||
|
||||
export const useWordCloud = () => {
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const [words, setWords] = useState<WordItem[]>([]);
|
||||
const [shuffledWords, setShuffledWords] = useState<WordItem[]>([]);
|
||||
const [ready, setReady] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
|
||||
const fetchWords = async () => {
|
||||
try {
|
||||
const res = await fetch("/api/review");
|
||||
|
|
@ -90,14 +89,26 @@ export const useWordCloud = () => {
|
|||
const maxValue = Math.max(...words.map((w) => w.value), 1);
|
||||
const minValue = Math.min(...words.map((w) => w.value), 0);
|
||||
|
||||
const shuffledWords = useMemo(() => {
|
||||
return [...words].sort(() => Math.random() - 0.5);
|
||||
useEffect(() => {
|
||||
const id = setTimeout(() => {
|
||||
const result = [...words];
|
||||
|
||||
for (let i = result.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[result[i], result[j]] = [result[j], result[i]];
|
||||
}
|
||||
|
||||
setShuffledWords(result);
|
||||
setReady(true);
|
||||
}, 0);
|
||||
|
||||
return () => clearTimeout(id);
|
||||
}, [words]);
|
||||
|
||||
return {
|
||||
mounted,
|
||||
maxValue,
|
||||
minValue,
|
||||
shuffledWords,
|
||||
ready,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ export interface SentimentChartProps {
|
|||
|
||||
export interface CustomTooltipProps {
|
||||
active?: boolean;
|
||||
payload?: any[];
|
||||
payload?: string[];
|
||||
total: number;
|
||||
}
|
||||
|
||||
|
|
@ -92,16 +92,10 @@ export interface TrendChartProps {
|
|||
|
||||
export interface TrendChartTooltipProps {
|
||||
active?: boolean;
|
||||
payload?: any[];
|
||||
payload?: LegendPayloadItem[];
|
||||
label?: string;
|
||||
}
|
||||
|
||||
// export type WordItem = {
|
||||
// text: string;
|
||||
// value: number;
|
||||
// sentiment: "positive" | "negative" | "neutral";
|
||||
// };
|
||||
|
||||
export interface WordCloudProps {
|
||||
words: WordItem[];
|
||||
}
|
||||
|
|
@ -128,7 +122,7 @@ export interface UseStatCardProps {
|
|||
export interface ReviewItem {
|
||||
id: number;
|
||||
content: string;
|
||||
sentiment: string;
|
||||
sentiment: Sentiment;
|
||||
confidenceScore: number;
|
||||
createdAt: string;
|
||||
keywords: string[];
|
||||
|
|
@ -164,3 +158,18 @@ export type WordCloudConfig = {
|
|||
minValue: number;
|
||||
maxValue: number;
|
||||
};
|
||||
|
||||
export interface CLabelProps {
|
||||
cx: number;
|
||||
cy: number;
|
||||
midAngle: number;
|
||||
innerRadius: number;
|
||||
outerRadius: number;
|
||||
percent: number;
|
||||
}
|
||||
|
||||
export type LegendPayloadItem = {
|
||||
color?: string;
|
||||
name?: string;
|
||||
value?: string;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Frown, Meh, Smile } from "lucide-react";
|
||||
import { WordCloudConfig, WordCloudItemProps, WordItem } from "../types";
|
||||
import { WordCloudConfig, WordItem } from "../types";
|
||||
|
||||
export const MODEL_OPTIONS = [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import type { Config } from "tailwindcss";
|
||||
import animate from "tailwindcss-animate";
|
||||
|
||||
const config: Config = {
|
||||
content: [
|
||||
|
|
@ -107,7 +108,7 @@ const config: Config = {
|
|||
},
|
||||
},
|
||||
},
|
||||
plugins: [require("tailwindcss-animate")],
|
||||
plugins: [animate],
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|
|
|||
Loading…
Reference in New Issue