using Cysharp.Threading.Tasks; using Simulator.Config; using Simulator.Data; using System; using System.Collections.Generic; using TMPro; using UnityEngine; using UVC.Network; namespace Simulator.UI { /// /// 시뮬레이션 목록을 표시하는 View 스크립트 /// UI Prefab의 루트에 붙여서 사용합니다. /// public class SimulationListView : MonoBehaviour { [Header("리스트")] [SerializeField] private Transform listContainer; [SerializeField] private GameObject rowPrefab; [Header("검색")] [SerializeField] private TMP_InputField searchInput; [Header("정보")] [SerializeField] private TMP_Text dataCountText; private List allRows = new List(); private List rowViews = new List(); private SimulationRowData selectedRow; /// /// 행 선택 시 호출되는 이벤트 (선택된 SimulationRowData 전달) /// public event Action OnRowSelected; private void OnEnable() { FetchSimulationList().Forget(); } /// /// API에서 시뮬레이션 목록을 가져옵니다. /// public async UniTaskVoid FetchSimulationList() { try { var response = await HttpRequester.RequestGet( $"{Constants.HTTP_DOMAIN}/simulation/projects", null, null, true); if (response?.data?.rows == null) return; allRows = response.data.rows; ApplyFilter(); } catch (Exception e) { Debug.LogError($"시뮬레이션 목록 조회 실패: {e.Message}"); } } /// /// 검색 필터를 적용하여 목록을 갱신합니다. /// public void ApplyFilter() { string keyword = searchInput != null ? searchInput.text.Trim() : ""; List filtered; if (string.IsNullOrEmpty(keyword)) { filtered = allRows; } else { filtered = allRows.FindAll(row => row.name != null && row.name.Contains(keyword, StringComparison.OrdinalIgnoreCase)); } RenderRows(filtered); if (dataCountText != null) { dataCountText.text = $"검색된 데이터 수: {filtered.Count} / {allRows.Count}"; } } /// /// 행 UI를 생성/갱신합니다. /// private void RenderRows(List rows) { // 기존 행 제거 foreach (var view in rowViews) { Destroy(view.gameObject); } rowViews.Clear(); selectedRow = null; // 새로운 행 생성 foreach (var row in rows) { var go = Instantiate(rowPrefab, listContainer); var rowView = go.GetComponent(); if (rowView != null) { rowView.SetData(row); rowView.OnClicked += OnRowClicked; rowViews.Add(rowView); } } } private void OnRowClicked(SimulationListRowView rowView) { // 기존 선택 해제 foreach (var view in rowViews) { view.SetSelected(false); } // 새 선택 rowView.SetSelected(true); selectedRow = rowView.Data; OnRowSelected?.Invoke(selectedRow); } /// /// 현재 선택된 시뮬레이션 데이터를 반환합니다. /// public SimulationRowData GetSelectedRow() { return selectedRow; } /// /// 검색 InputField의 OnValueChanged에 연결할 수 있는 public 메서드 /// public void OnSearchValueChanged(string value) { ApplyFilter(); } /// /// 새로고침 버튼에 연결할 수 있는 public 메서드 /// public void Refresh() { FetchSimulationList().Forget(); } private void OnDestroy() { foreach (var view in rowViews) { if (view != null) view.OnClicked -= OnRowClicked; } } } }