refactor: separate url input components
This commit is contained in:
parent
a106c5d6c1
commit
1593fd75bd
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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>>;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue