refactor: separate url input components

This commit is contained in:
Mahen 2026-03-28 20:07:23 +07:00
parent a106c5d6c1
commit 1593fd75bd
5 changed files with 92 additions and 36 deletions

View File

@ -5,6 +5,7 @@ import { Sparkles, X } from "lucide-react";
import { Input } from "../ui/input";
import { Button } from "../ui/button";
import ResultSection from "./ResultSection";
import UrlInputList from "./UrlInputList";
export default function AnalysisClient() {
const {
@ -23,39 +24,6 @@ export default function AnalysisClient() {
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>
{index === visibleFields - 1 && (
<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
@ -105,7 +73,11 @@ export default function AnalysisClient() {
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 items-end transition-all duration-500">
{urlInput()}
<UrlInputList
urlDatas={urlDatas}
visibleFields={visibleFields}
setVisibleFields={setVisibleFields}
/>
{visibleFields < 2 && (
<div

View File

@ -0,0 +1,40 @@
import { UrlInputItemProps } from "@/src/types";
import { Button } from "../ui/button";
import { Input } from "../ui/input";
const UrlInputItem = ({
item,
index,
visibleFields,
onRemove,
}: UrlInputItemProps) => {
return (
<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">
{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>
{index === visibleFields - 1 && (
<Button
type="button"
variant="ghost"
onClick={onRemove}
className="text-sentiment-negative hover:text-sentiment-negative hover:bg-sentiment-negative-light shrink-0"
>
</Button>
)}
</div>
</div>
);
};
export default UrlInputItem;

View File

@ -0,0 +1,24 @@
import { UrlInputListProps } from "@/src/types";
import UrlInputItem from "./UrlInputItem";
const UrlInputList = ({
urlDatas,
visibleFields,
setVisibleFields,
}: UrlInputListProps) => {
return (
<>
{urlDatas.slice(0, visibleFields).map((item, index) => (
<UrlInputItem
key={index}
item={item}
index={index}
visibleFields={visibleFields}
onRemove={() => setVisibleFields((prev) => prev - 1)}
/>
))}
</>
);
};
export default UrlInputList;

0
src/hooks/useUrlInput.ts Normal file
View File

View File

@ -5,6 +5,7 @@ import { profileSchema } from "../app/validation/profile.schema";
import { Session } from "next-auth";
import { NextResponse } from "next/server";
import { analyzeSchema } from "../app/validation/analyze.schema";
import { FieldError, UseFormRegisterReturn } from "react-hook-form";
export interface ModelDB {
modelName: string;
@ -19,7 +20,7 @@ export interface ModelDB {
export interface ProfileClientProps {
name: string;
bio?: string;
preferenceBrand: string
preferenceBrand: string;
preferenceOS: string;
budgetMin: number;
budgetMax: number;
@ -371,4 +372,23 @@ export interface AnalysisWithMetric {
metricId: number;
name: string;
} | null;
}
}
type UrlData = {
labels: string;
errors: FieldError | undefined;
title: UseFormRegisterReturn;
};
export type UrlInputItemProps = {
item: UrlData;
index: number;
visibleFields: number;
onRemove: () => void;
};
export type UrlInputListProps = {
urlDatas: UrlData[];
visibleFields: number;
setVisibleFields: React.Dispatch<React.SetStateAction<number>>;
};