style: fix URL input visibility handling

This commit is contained in:
Mahen 2026-03-22 17:38:57 +07:00
parent 7cc79f31c3
commit 225b3e842e
3 changed files with 68 additions and 102 deletions

View File

@ -9,19 +9,50 @@ import ResultSection from "./ResultSection";
export default function AnalysisClient() {
const {
errors,
isValid,
loading,
result,
showField,
resultRef,
progress,
visibleFields,
urlDatas,
register,
handleSubmit,
onSubmit,
setShowField,
handleCancel,
setVisibleFields,
} = useAnalyseText();
const urlInput = () => {
return urlDatas.slice(0, visibleFields).map((item, index) => (
<div
key={index}
className="animate-in fade-in slide-in-from-bottom-2 duration-300"
>
<label className="block mb-1 text-sm font-medium text-gray-700">
{item.labels}
</label>
<div className="flex gap-2">
<div className="flex-1">
<Input
type="url"
placeholder="Contoh: https://tokopedia.com/..."
className={`${item.errors ? "border-sentiment-negative" : "focus:ring-primary"}`}
{...item.title}
/>
</div>
<Button
type="button"
variant="ghost"
onClick={() => setVisibleFields((prev) => prev - 1)}
className="text-sentiment-negative hover:text-sentiment-negative hover:bg-sentiment-negative-light shrink-0"
>
</Button>
</div>
</div>
));
};
return (
<div className="w-full mx-auto">
<form
@ -35,44 +66,6 @@ export default function AnalysisClient() {
<div className="flex flex-col gap-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{/* <div className="w-full">
<label className="block mb-1 text-sm font-medium text-gray-700">
Pilih Profesi
</label>
<Controller
name="profession"
control={control}
render={({ field }) => (
<Select onValueChange={field.onChange} value={field.value}>
<SelectTrigger
className={`w-full ${errors.profession ? "border-sentiment-negative" : ""}`}
>
<SelectValue placeholder="Pilih Profesi" />
</SelectTrigger>
<SelectContent className="bg-card" position="popper">
{professionItems.map((item) => (
<SelectItem
key={item.value}
value={item.value}
className="focus:bg-primary focus:text-card"
>
<div className="flex gap-2 items-center">
<item.icon className="h-4 w-4" />
<span>{item.label}</span>
</div>
</SelectItem>
))}
</SelectContent>
</Select>
)}
/>
{errors.profession && (
<p className="text-sentiment-negative text-xs mt-1">
{errors.profession.message}
</p>
)}
</div> */}
<div className="w-full">
<label className="block mb-1 text-sm font-medium text-gray-700">
Tautan Produk 1
@ -89,6 +82,7 @@ export default function AnalysisClient() {
</p>
)}
</div>
<div className="w-full">
<label className="block mb-1 text-sm font-medium text-gray-700">
Tautan Produk 2
@ -107,66 +101,21 @@ export default function AnalysisClient() {
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="w-full">
<label className="block mb-1 text-sm font-medium text-gray-700">
Tautan Produk 3
</label>
<Input
type="url"
placeholder="Contoh: https://tokopedia.com/..."
className={`w-full ${errors.url3 ? "border-sentiment-negative" : "focus:ring-primary"}`}
{...register("url3")}
/>
{errors.url3 && (
<p className="text-sentiment-negative text-xs mt-1">
{errors.url3.message}
</p>
)}
</div>
<div className="w-full flex flex-col justify-end">
{showField ? (
<div className="animate-in fade-in slide-in-from-bottom-2 duration-300">
<label className="block mb-1 text-sm font-medium text-gray-700">
Tautan Produk 4
</label>
<div className="flex gap-2">
<div className="flex-1">
<Input
type="url"
placeholder="Contoh: https://tokopedia.com/..."
className={`${errors.url4 ? "border-sentiment-negative" : "focus:ring-primary"}`}
{...register("url4")}
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 items-end">
{urlInput()}
{visibleFields < 2 && (
<Button
type="button"
variant="ghost"
onClick={() => setShowField(false)}
className="text-sentiment-negative hover:text-sentiment-negative hover:bg-sentiment-negative-light shrink-0"
onClick={() => setVisibleFields((prev) => prev + 1)}
className="h-max bg-card text-primary hover:bg-[#F8FBFF] border-dashed border border-primary/20 transition-all shadow-xs"
>
</Button>
</div>
{errors.url4 && (
<p className="text-sentiment-negative text-xs mt-1">
{errors.url4.message}
</p>
)}
</div>
) : (
<Button
type="button"
onClick={() => setShowField(true)}
className="w-full h-max bg-card text-primary hover:bg-[#F8FBFF] border-dashed border border-primary/20 transition-all shadow-xs"
>
+ Tambah Tautan Produk Lainnya
{visibleFields === 0
? "+ Tambah Tautan Produk"
: "+ Tambah Tautan Produk Lainnya"}
</Button>
)}
</div>
</div>
</div>
{loading && (
<div className="mt-4 bg-transparent">

View File

@ -17,10 +17,10 @@ export const useAnalyseText = () => {
const { data: session } = useSession();
const [loading, setLoading] = useState(false);
const [result, setResult] = useState<AnalysisResults | null>(null);
const [showField, setShowField] = useState(false);
const resultRef = useRef<HTMLDivElement>(null);
const [progress, setProgress] = useState({ status: "", percent: 0 });
const abortControllerRef = useRef<AbortController | null>(null);
const [visibleFields, setVisibleFields] = useState(0);
const {
control,
@ -208,20 +208,36 @@ export const useAnalyseText = () => {
}
}, [loading, result]);
const urlDatas = [
{
labels: "Tautan Produk 3",
errors: errors.url3,
title: { ...register("url3") },
type: "url3",
},
{
labels: "Tautan Produk 4",
errors: errors.url4,
title: { ...register("url4") },
type: "url4",
},
];
return {
control,
errors,
isValid,
loading,
result,
showField,
visibleFields,
resultRef,
progress,
urlDatas,
register,
handleSubmit,
setValue,
onSubmit,
setShowField,
setVisibleFields,
handleCancel,
};
};

View File

@ -8,6 +8,7 @@ import {
import { SiAcer, SiAsus, SiLenovo, SiLinux, SiMacos } from "react-icons/si";
import { FaWindows } from "react-icons/fa";
import { Sentiment } from "@prisma/client";
import { useAnalyseText } from "../hooks/useAnalyzeText";
export const MODEL_OPTIONS = [
{