"use client"; import { useState, type FormEvent } from "react"; import { useRouter } from "next/navigation"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Card, CardContent } from "@/components/ui/card"; import { Globe, Loader2 } from "lucide-react"; import { api, ApiError } from "@/lib/api"; import { isValidUrl } from "@/lib/constants"; import { useSiteInspectionStore } from "@/stores/useSiteInspectionStore"; import { cn } from "@/lib/utils"; import { AccessibilityStandardSelect, type AccessibilityStandard, } from "./AccessibilityStandardSelect"; /** 최대 페이지 수 옵션 (0 = 무제한) */ const MAX_PAGES_OPTIONS = [10, 20, 50, 0] as const; /** 크롤링 깊이 옵션 */ const MAX_DEPTH_OPTIONS = [1, 2, 3] as const; /** 동시 검사 수 옵션 */ const CONCURRENCY_OPTIONS = [1, 2, 4, 8] as const; /** 사이트 크롤링 폼 */ export function SiteCrawlForm() { const [url, setUrl] = useState(""); const [error, setError] = useState(null); const [isLoading, setIsLoading] = useState(false); const [maxPages, setMaxPages] = useState(20); const [maxDepth, setMaxDepth] = useState(2); const [concurrency, setConcurrency] = useState(4); const [accessibilityStandard, setAccessibilityStandard] = useState("wcag_2.1_aa"); const router = useRouter(); const { setSiteInspection } = useSiteInspectionStore(); const handleSubmit = async (e: FormEvent) => { e.preventDefault(); setError(null); const trimmedUrl = url.trim(); if (!trimmedUrl) { setError("URL을 입력해주세요"); return; } if (!isValidUrl(trimmedUrl)) { setError("유효한 URL을 입력해주세요 (http:// 또는 https://로 시작)"); return; } setIsLoading(true); try { const response = await api.startSiteInspection( trimmedUrl, maxPages, maxDepth, concurrency, accessibilityStandard ); setSiteInspection(response.site_inspection_id, trimmedUrl); router.push( `/site-inspections/${response.site_inspection_id}/progress` ); } catch (err) { if (err instanceof ApiError) { setError(err.detail); } else { setError("사이트 크롤링 시작 중 오류가 발생했습니다. 다시 시도해주세요."); } } finally { setIsLoading(false); } }; return (
{/* URL 입력 필드 */}
{ setUrl(e.target.value); if (error) setError(null); }} placeholder="https://example.com" className="pl-10 h-12 text-base" disabled={isLoading} aria-label="크롤링할 사이트 URL 입력" aria-invalid={!!error} aria-describedby={error ? "site-url-error" : undefined} />
{/* 옵션 영역 */}
{/* 최대 페이지 수 */}
{MAX_PAGES_OPTIONS.map((option) => ( ))}
{/* 크롤링 깊이 */}
{MAX_DEPTH_OPTIONS.map((option) => ( ))}
{/* 동시 검사 수 */}
{CONCURRENCY_OPTIONS.map((option) => ( ))}
{/* 접근성 기준 */}
{/* 사이트 크롤링 시작 버튼 */}
{error && ( )}
); }