ERP-node/frontend/components/admin/dashboard/data-sources/DatabaseConfig.tsx

176 lines
6.6 KiB
TypeScript

"use client";
import React, { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import { ChartDataSource } from "../types";
import { ExternalDbConnectionAPI, ExternalDbConnection } from "@/lib/api/externalDbConnection";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { ExternalLink, Database, Server } from "lucide-react";
interface DatabaseConfigProps {
dataSource: ChartDataSource;
onChange: (updates: Partial<ChartDataSource>) => void;
}
/**
* 데이터베이스 설정 컴포넌트
* - 현재 DB / 외부 DB 선택
* - 외부 커넥션 목록 불러오기
*/
export function DatabaseConfig({ dataSource, onChange }: DatabaseConfigProps) {
const router = useRouter();
const [connections, setConnections] = useState<ExternalDbConnection[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
// 외부 커넥션 목록 불러오기
useEffect(() => {
if (dataSource.connectionType === "external") {
loadExternalConnections();
}
}, [dataSource.connectionType]);
const loadExternalConnections = async () => {
setLoading(true);
setError(null);
try {
const activeConnections = await ExternalDbConnectionAPI.getConnections({ is_active: "Y" });
setConnections(activeConnections);
} catch (err) {
const errorMessage = err instanceof Error ? err.message : "알 수 없는 오류가 발생했습니다";
setError(errorMessage);
} finally {
setLoading(false);
}
};
// 현재 선택된 커넥션 찾기
const selectedConnection = connections.find((conn) => String(conn.id) === dataSource.externalConnectionId);
return (
<div className="space-y-3">
{/* 현재 DB vs 외부 DB 선택 */}
<div>
<Label className="text-foreground mb-2 block text-xs font-medium"> </Label>
<div className="flex gap-2">
<button
onClick={() => {
onChange({ connectionType: "current", externalConnectionId: undefined });
}}
className={`flex flex-1 items-center gap-1.5 rounded border px-2 py-1.5 text-xs transition-colors ${
dataSource.connectionType === "current"
? "bg-primary border-primary text-white"
: "border-border bg-background hover:bg-muted"
}`}
>
<Database className="h-3 w-3" />
DB
</button>
<button
onClick={() => {
onChange({ connectionType: "external" });
}}
className={`flex flex-1 items-center gap-1.5 rounded border px-2 py-1.5 text-xs transition-colors ${
dataSource.connectionType === "external"
? "bg-primary border-primary text-white"
: "border-border bg-background hover:bg-muted"
}`}
>
<Server className="h-3 w-3" />
DB
</button>
</div>
</div>
{/* 외부 DB 선택 시 커넥션 목록 */}
{dataSource.connectionType === "external" && (
<div className="space-y-2">
<div className="flex items-center justify-between">
<Label className="text-foreground text-xs font-medium"> </Label>
<button
onClick={() => {
router.push("/admin/automaticMng/exconList");
}}
className="text-primary hover:text-primary flex items-center gap-1 text-[11px] transition-colors"
>
<ExternalLink className="h-3 w-3" />
</button>
</div>
{loading && (
<div className="flex items-center justify-center py-3">
<div className="border-border h-4 w-4 animate-spin rounded-full border-2 border-t-blue-600" />
<span className="text-foreground ml-2 text-xs"> ...</span>
</div>
)}
{error && (
<div className="bg-destructive/10 rounded px-2 py-1.5">
<div className="text-destructive text-xs">{error}</div>
<button
onClick={loadExternalConnections}
className="text-destructive mt-1 text-[11px] underline hover:no-underline"
>
</button>
</div>
)}
{!loading && !error && connections.length === 0 && (
<div className="bg-warning/10 rounded px-2 py-2 text-center">
<div className="text-warning mb-1 text-xs"> </div>
<button
onClick={() => {
router.push("/admin/automaticMng/exconList");
}}
className="text-warning text-[11px] underline hover:no-underline"
>
</button>
</div>
)}
{!loading && !error && connections.length > 0 && (
<>
<Select
value={dataSource.externalConnectionId || undefined}
onValueChange={(value) => {
onChange({ externalConnectionId: value });
}}
>
<SelectTrigger className="h-8 w-full text-xs">
<SelectValue placeholder="커넥션 선택" />
</SelectTrigger>
<SelectContent className="z-[9999]">
{connections.map((conn) => (
<SelectItem key={conn.id} value={String(conn.id)} className="text-xs">
<div className="flex items-center gap-1.5">
<span className="font-medium">{conn.connection_name}</span>
<span className="text-muted-foreground text-[10px]">({conn.db_type.toUpperCase()})</span>
</div>
</SelectItem>
))}
</SelectContent>
</Select>
{selectedConnection && (
<div className="bg-muted text-foreground space-y-0.5 rounded px-2 py-1.5 text-[11px]">
<div>
<span className="font-medium">:</span> {selectedConnection.connection_name}
</div>
<div>
<span className="font-medium">:</span> {selectedConnection.db_type.toUpperCase()}
</div>
</div>
)}
</>
)}
</div>
)}
</div>
);
}