"use client"; import React, { useState, useCallback, useEffect } from "react"; import { DashboardElement, ChartDataSource, QueryResult } from "../types"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { ChevronLeft, ChevronRight, Save, X } from "lucide-react"; import { DataSourceSelector } from "../data-sources/DataSourceSelector"; import { DatabaseConfig } from "../data-sources/DatabaseConfig"; import { ApiConfig } from "../data-sources/ApiConfig"; import { QueryEditor } from "../QueryEditor"; interface TodoWidgetConfigModalProps { isOpen: boolean; element: DashboardElement; onClose: () => void; onSave: (updates: Partial) => void; } /** * To-Do 위젯 설정 모달 * - 2단계 설정: 데이터 소스 → 쿼리 입력/테스트 */ export function TodoWidgetConfigModal({ isOpen, element, onClose, onSave }: TodoWidgetConfigModalProps) { const [currentStep, setCurrentStep] = useState<1 | 2>(1); const [title, setTitle] = useState(element.title || "✅ To-Do / 긴급 지시"); const [dataSource, setDataSource] = useState( element.dataSource || { type: "database", connectionType: "current", refreshInterval: 0 }, ); const [queryResult, setQueryResult] = useState(null); // 모달 열릴 때 element에서 설정 로드 useEffect(() => { if (isOpen) { setTitle(element.title || "✅ To-Do / 긴급 지시"); if (element.dataSource) { setDataSource(element.dataSource); } setCurrentStep(1); } }, [isOpen, element.id]); // 데이터 소스 타입 변경 const handleDataSourceTypeChange = useCallback((type: "database" | "api") => { if (type === "database") { setDataSource((prev) => ({ ...prev, type: "database", connectionType: "current", })); } else { setDataSource((prev) => ({ ...prev, type: "api", method: "GET", })); } setQueryResult(null); }, []); // 데이터 소스 업데이트 const handleDataSourceUpdate = useCallback((updates: Partial) => { setDataSource((prev) => ({ ...prev, ...updates })); }, []); // 쿼리 실행 결과 처리 const handleQueryTest = useCallback( (result: QueryResult) => { // console.log("🎯 TodoWidget - handleQueryTest 호출됨!"); // console.log("📊 쿼리 결과:", result); // console.log("📝 rows 개수:", result.rows?.length); // console.log("❌ error:", result.error); setQueryResult(result); // console.log("✅ setQueryResult 호출 완료!"); // 강제 리렌더링 확인 // setTimeout(() => { // console.log("🔄 1초 후 queryResult 상태:", result); // }, 1000); }, [], ); // 저장 const handleSave = useCallback(() => { if (!dataSource.query || !queryResult || queryResult.error) { alert("쿼리를 입력하고 테스트를 먼저 실행해주세요."); return; } if (!queryResult.rows || queryResult.rows.length === 0) { alert("쿼리 결과가 없습니다. 데이터가 반환되는 쿼리를 입력해주세요."); return; } onSave({ title, dataSource, }); onClose(); }, [title, dataSource, queryResult, onSave, onClose]); // 다음 단계로 const handleNext = useCallback(() => { if (currentStep === 1) { if (dataSource.type === "database") { if (!dataSource.connectionId && dataSource.connectionType === "external") { alert("외부 데이터베이스를 선택해주세요."); return; } } else if (dataSource.type === "api") { if (!dataSource.url) { alert("API URL을 입력해주세요."); return; } } setCurrentStep(2); } }, [currentStep, dataSource]); // 이전 단계로 const handlePrev = useCallback(() => { if (currentStep === 2) { setCurrentStep(1); } }, [currentStep]); if (!isOpen) return null; return (
{/* 헤더 */}

To-Do 위젯 설정

데이터 소스와 쿼리를 설정하면 자동으로 To-Do 목록이 표시됩니다

{/* 진행 상태 */}
1
데이터 소스 선택
2
쿼리 입력 및 테스트
{/* 본문 */}
{/* Step 1: 데이터 소스 선택 */} {currentStep === 1 && (
setTitle(e.target.value)} placeholder="예: ✅ 오늘의 할 일" className="mt-2" />
{dataSource.type === "database" && ( )} {dataSource.type === "api" && }
)} {/* Step 2: 쿼리 입력 및 테스트 */} {currentStep === 2 && (

💡 컬럼명 가이드

쿼리 결과에 다음 컬럼명이 있으면 자동으로 To-Do 항목으로 변환됩니다:

  • id - 고유 ID (없으면 자동 생성)
  • title,{" "} task,{" "} name - 제목 (필수)
  • description,{" "} desc,{" "} content - 상세 설명
  • priority - 우선순위 (urgent, high, normal, low)
  • status - 상태 (pending, in_progress, completed)
  • assigned_to,{" "} assignedTo,{" "} user - 담당자
  • due_date,{" "} dueDate,{" "} deadline - 마감일
  • is_urgent,{" "} isUrgent,{" "} urgent - 긴급 여부
{/* 디버그: 항상 표시되는 테스트 메시지 */}

🔍 디버그: queryResult 상태 = {queryResult ? "있음" : "없음"}

{queryResult && (

rows: {queryResult.rows?.length}개, error: {queryResult.error || "없음"}

)}
{queryResult && !queryResult.error && queryResult.rows && queryResult.rows.length > 0 && (

✅ 쿼리 테스트 성공!

{queryResult.rows.length}개의 To-Do 항목을 찾았습니다.

첫 번째 데이터 미리보기:

                      {JSON.stringify(queryResult.rows[0], null, 2)}
                    
)}
)}
{/* 하단 버튼 */}
{currentStep > 1 && ( )}
{currentStep < 2 ? ( ) : ( )}
); }