ERP-node/frontend/components/admin/HeadersManager.tsx

141 lines
4.4 KiB
TypeScript
Raw Normal View History

2025-10-21 10:59:15 +09:00
"use client";
import React, { useState, useEffect } from "react";
import { Plus, Trash2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
interface HeadersManagerProps {
headers: Record<string, string>;
onChange: (headers: Record<string, string>) => void;
}
interface HeaderItem {
key: string;
value: string;
}
export function HeadersManager({ headers, onChange }: HeadersManagerProps) {
const [headersList, setHeadersList] = useState<HeaderItem[]>([]);
// 초기 헤더 로드
useEffect(() => {
const list = Object.entries(headers || {}).map(([key, value]) => ({
key,
value,
}));
// 헤더가 없으면 기본 헤더 추가
if (list.length === 0) {
list.push({ key: "Content-Type", value: "application/json" });
}
setHeadersList(list);
}, []);
// 헤더 추가
const addHeader = () => {
setHeadersList([...headersList, { key: "", value: "" }]);
};
// 헤더 삭제
const removeHeader = (index: number) => {
const newList = headersList.filter((_, i) => i !== index);
setHeadersList(newList);
updateParent(newList);
};
// 헤더 업데이트
const updateHeader = (index: number, field: "key" | "value", value: string) => {
const newList = [...headersList];
newList[index][field] = value;
setHeadersList(newList);
updateParent(newList);
};
// 부모 컴포넌트에 변경사항 전달
const updateParent = (list: HeaderItem[]) => {
const headersObject = list.reduce(
(acc, { key, value }) => {
if (key.trim()) {
acc[key] = value;
}
return acc;
},
{} as Record<string, string>,
);
onChange(headersObject);
};
return (
<div className="space-y-4">
<div className="flex items-center justify-between">
<Label className="text-sm font-medium"> </Label>
<Button type="button" variant="outline" size="sm" onClick={addHeader}>
<Plus className="mr-1 h-3 w-3" />
</Button>
</div>
{headersList.length > 0 ? (
<div className="rounded-md border">
<Table>
<TableHeader>
<TableRow>
<TableHead className="w-[35%]"></TableHead>
<TableHead className="w-[55%]"></TableHead>
<TableHead className="w-[10%] text-right"></TableHead>
</TableRow>
</TableHeader>
<TableBody>
{headersList.map((header, index) => (
<TableRow key={index}>
<TableCell>
<Input
type="text"
value={header.key}
onChange={(e) => updateHeader(index, "key", e.target.value)}
placeholder="예: Authorization"
className="h-8"
/>
</TableCell>
<TableCell>
<Input
type="text"
value={header.value}
onChange={(e) => updateHeader(index, "value", e.target.value)}
placeholder="예: Bearer token123"
className="h-8"
/>
</TableCell>
<TableCell className="text-right">
<Button
type="button"
variant="ghost"
size="sm"
onClick={() => removeHeader(index)}
className="h-8 w-8 p-0 text-red-600 hover:bg-red-50 hover:text-red-700"
>
<Trash2 className="h-4 w-4" />
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
) : (
<div className="rounded-md border border-dashed p-4 text-center text-sm text-gray-500">
. .
</div>
)}
<p className="text-xs text-gray-500">
* HTTP . .
</p>
</div>
);
}