전체적인 스타일 수정
This commit is contained in:
@@ -202,166 +202,152 @@ export function RestApiConnectionList() {
|
||||
return (
|
||||
<>
|
||||
{/* 검색 및 필터 */}
|
||||
<Card className="mb-6 shadow-sm">
|
||||
<CardContent className="pt-6">
|
||||
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
|
||||
<div className="flex flex-col gap-4 md:flex-row md:items-center">
|
||||
{/* 검색 */}
|
||||
<div className="relative">
|
||||
<Search className="absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-gray-400" />
|
||||
<Input
|
||||
placeholder="연결명 또는 URL로 검색..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
className="w-64 pl-10"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 인증 타입 필터 */}
|
||||
<Select value={authTypeFilter} onValueChange={setAuthTypeFilter}>
|
||||
<SelectTrigger className="w-40">
|
||||
<SelectValue placeholder="인증 타입" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{supportedAuthTypes.map((type) => (
|
||||
<SelectItem key={type.value} value={type.value}>
|
||||
{type.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
{/* 활성 상태 필터 */}
|
||||
<Select value={activeStatusFilter} onValueChange={setActiveStatusFilter}>
|
||||
<SelectTrigger className="w-32">
|
||||
<SelectValue placeholder="상태" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{ACTIVE_STATUS_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 추가 버튼 */}
|
||||
<Button onClick={handleAddConnection} className="shrink-0">
|
||||
<Plus className="mr-2 h-4 w-4" />새 연결 추가
|
||||
</Button>
|
||||
<div className="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
|
||||
<div className="flex flex-col gap-4 sm:flex-row sm:items-center">
|
||||
{/* 검색 */}
|
||||
<div className="relative w-full sm:w-[300px]">
|
||||
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
|
||||
<Input
|
||||
placeholder="연결명 또는 URL로 검색..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
className="h-10 pl-10 text-sm"
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 인증 타입 필터 */}
|
||||
<Select value={authTypeFilter} onValueChange={setAuthTypeFilter}>
|
||||
<SelectTrigger className="h-10 w-full sm:w-[160px]">
|
||||
<SelectValue placeholder="인증 타입" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{supportedAuthTypes.map((type) => (
|
||||
<SelectItem key={type.value} value={type.value}>
|
||||
{type.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
{/* 활성 상태 필터 */}
|
||||
<Select value={activeStatusFilter} onValueChange={setActiveStatusFilter}>
|
||||
<SelectTrigger className="h-10 w-full sm:w-[120px]">
|
||||
<SelectValue placeholder="상태" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{ACTIVE_STATUS_OPTIONS.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 추가 버튼 */}
|
||||
<Button onClick={handleAddConnection} className="h-10 gap-2 text-sm font-medium">
|
||||
<Plus className="h-4 w-4" />
|
||||
새 연결 추가
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* 연결 목록 */}
|
||||
{loading ? (
|
||||
<div className="flex h-64 items-center justify-center">
|
||||
<div className="text-gray-500">로딩 중...</div>
|
||||
<div className="flex h-64 items-center justify-center rounded-lg border bg-card shadow-sm">
|
||||
<div className="text-sm text-muted-foreground">로딩 중...</div>
|
||||
</div>
|
||||
) : connections.length === 0 ? (
|
||||
<Card className="shadow-sm">
|
||||
<CardContent className="pt-6">
|
||||
<div className="py-8 text-center text-gray-500">
|
||||
<TestTube className="mx-auto mb-4 h-12 w-12 text-gray-400" />
|
||||
<p className="mb-2 text-lg font-medium">등록된 REST API 연결이 없습니다</p>
|
||||
<p className="mb-4 text-sm text-gray-400">새 REST API 연결을 추가해보세요.</p>
|
||||
<Button onClick={handleAddConnection}>
|
||||
<Plus className="mr-2 h-4 w-4" />첫 번째 연결 추가
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<div className="flex h-64 flex-col items-center justify-center rounded-lg border bg-card shadow-sm">
|
||||
<div className="flex flex-col items-center gap-2 text-center">
|
||||
<p className="text-sm text-muted-foreground">등록된 REST API 연결이 없습니다</p>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<Card className="shadow-sm">
|
||||
<CardContent className="p-0">
|
||||
<Table>
|
||||
<div className="rounded-lg border bg-card shadow-sm">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[180px]">연결명</TableHead>
|
||||
<TableHead className="w-[280px]">기본 URL</TableHead>
|
||||
<TableHead className="w-[100px]">인증 타입</TableHead>
|
||||
<TableHead className="w-[80px]">헤더 수</TableHead>
|
||||
<TableHead className="w-[80px]">상태</TableHead>
|
||||
<TableHead className="w-[140px]">마지막 테스트</TableHead>
|
||||
<TableHead className="w-[100px]">연결 테스트</TableHead>
|
||||
<TableHead className="w-[120px] text-right">작업</TableHead>
|
||||
<TableRow className="border-b bg-muted/50 hover:bg-muted/50">
|
||||
<TableHead className="h-12 text-sm font-semibold">연결명</TableHead>
|
||||
<TableHead className="h-12 text-sm font-semibold">기본 URL</TableHead>
|
||||
<TableHead className="h-12 text-sm font-semibold">인증 타입</TableHead>
|
||||
<TableHead className="h-12 text-sm font-semibold">헤더 수</TableHead>
|
||||
<TableHead className="h-12 text-sm font-semibold">상태</TableHead>
|
||||
<TableHead className="h-12 text-sm font-semibold">마지막 테스트</TableHead>
|
||||
<TableHead className="h-12 text-sm font-semibold">연결 테스트</TableHead>
|
||||
<TableHead className="h-12 text-right text-sm font-semibold">작업</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{connections.map((connection) => (
|
||||
<TableRow key={connection.id} className="hover:bg-gray-50">
|
||||
<TableCell>
|
||||
<TableRow key={connection.id} className="border-b transition-colors hover:bg-muted/50">
|
||||
<TableCell className="h-16 text-sm">
|
||||
<div className="font-medium">{connection.connection_name}</div>
|
||||
{connection.description && (
|
||||
<div className="mt-1 text-xs text-gray-500">{connection.description}</div>
|
||||
<div className="mt-1 text-xs text-muted-foreground">{connection.description}</div>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell className="font-mono text-xs">{connection.base_url}</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant="outline" className="text-xs">
|
||||
<TableCell className="h-16 font-mono text-sm">{connection.base_url}</TableCell>
|
||||
<TableCell className="h-16 text-sm">
|
||||
<Badge variant="outline">
|
||||
{AUTH_TYPE_LABELS[connection.auth_type] || connection.auth_type}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="text-center">
|
||||
<TableCell className="h-16 text-center text-sm">
|
||||
{Object.keys(connection.default_headers || {}).length}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant={connection.is_active === "Y" ? "default" : "secondary"} className="text-xs">
|
||||
<TableCell className="h-16 text-sm">
|
||||
<Badge variant={connection.is_active === "Y" ? "default" : "secondary"}>
|
||||
{connection.is_active === "Y" ? "활성" : "비활성"}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="text-xs">
|
||||
<TableCell className="h-16 text-sm">
|
||||
{connection.last_test_date ? (
|
||||
<div>
|
||||
<div>{new Date(connection.last_test_date).toLocaleDateString()}</div>
|
||||
<Badge
|
||||
variant={connection.last_test_result === "Y" ? "default" : "destructive"}
|
||||
className="mt-1 text-xs"
|
||||
className="mt-1"
|
||||
>
|
||||
{connection.last_test_result === "Y" ? "성공" : "실패"}
|
||||
</Badge>
|
||||
</div>
|
||||
) : (
|
||||
<span className="text-gray-400">-</span>
|
||||
<span className="text-muted-foreground">-</span>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<TableCell className="h-16 text-sm">
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => handleTestConnection(connection)}
|
||||
disabled={testingConnections.has(connection.id!)}
|
||||
className="h-7 px-2 text-xs"
|
||||
className="h-9 text-sm"
|
||||
>
|
||||
{testingConnections.has(connection.id!) ? "테스트 중..." : "테스트"}
|
||||
</Button>
|
||||
{testResults.has(connection.id!) && (
|
||||
<Badge
|
||||
variant={testResults.get(connection.id!) ? "default" : "destructive"}
|
||||
className="text-xs text-white"
|
||||
>
|
||||
<Badge variant={testResults.get(connection.id!) ? "default" : "destructive"}>
|
||||
{testResults.get(connection.id!) ? "성공" : "실패"}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<div className="flex justify-end gap-1">
|
||||
<TableCell className="h-16 text-right">
|
||||
<div className="flex justify-end gap-2">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
size="icon"
|
||||
onClick={() => handleEditConnection(connection)}
|
||||
className="h-8 w-8 p-0"
|
||||
className="h-8 w-8"
|
||||
>
|
||||
<Pencil className="h-4 w-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
size="icon"
|
||||
onClick={() => handleDeleteConnection(connection)}
|
||||
className="h-8 w-8 p-0 text-red-600 hover:bg-red-50 hover:text-red-700"
|
||||
className="h-8 w-8 text-destructive hover:bg-destructive/10"
|
||||
>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
</Button>
|
||||
@@ -371,8 +357,7 @@ export function RestApiConnectionList() {
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 연결 설정 모달 */}
|
||||
@@ -387,20 +372,25 @@ export function RestApiConnectionList() {
|
||||
|
||||
{/* 삭제 확인 다이얼로그 */}
|
||||
<AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogContent className="max-w-[95vw] sm:max-w-[500px]">
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>연결 삭제 확인</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
<AlertDialogTitle className="text-base sm:text-lg">연결 삭제 확인</AlertDialogTitle>
|
||||
<AlertDialogDescription className="text-xs sm:text-sm">
|
||||
"{connectionToDelete?.connection_name}" 연결을 삭제하시겠습니까?
|
||||
<br />
|
||||
<span className="font-medium text-red-600">이 작업은 되돌릴 수 없습니다.</span>
|
||||
이 작업은 되돌릴 수 없습니다.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel onClick={cancelDeleteConnection}>취소</AlertDialogCancel>
|
||||
<AlertDialogFooter className="gap-2 sm:gap-0">
|
||||
<AlertDialogCancel
|
||||
onClick={cancelDeleteConnection}
|
||||
className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
|
||||
>
|
||||
취소
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={confirmDeleteConnection}
|
||||
className="bg-red-600 text-white hover:bg-red-700 focus:ring-red-600"
|
||||
className="h-8 flex-1 bg-destructive text-xs hover:bg-destructive/90 sm:h-10 sm:flex-none sm:text-sm"
|
||||
>
|
||||
삭제
|
||||
</AlertDialogAction>
|
||||
|
||||
Reference in New Issue
Block a user