using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; using UnityEngine.InputSystem; using DDD.MVVM; namespace DDD { /// /// MVVM 패턴을 적용한 새로운 레스토랑 관리 UI /// 기존 RestaurantManagementUi의 기능을 ViewModel과 분리하여 구현 /// [RequireComponent(typeof(RestaurantManagementViewModel))] public class RestaurantManagementUi : PopupUi { [Header("Sub Views")] [SerializeField] private ChecklistView _checklistView; [SerializeField] private InventoryView _inventoryView; [SerializeField] private ItemDetailView _itemDetailView; [SerializeField] private TodayMenuView _todayMenuView; [SerializeField] private TodayRestaurantStateView _todayRestaurantStateView; [Header("Tab Groups")] [SerializeField] private TabGroupUi _sectionTabs; [SerializeField] private TabGroupUi _menuCategoryTabs; [SerializeField] private TabGroupUi _cookwareCategoryTabs; [Header("Hold Progress UI")] [SerializeField, BindTo(nameof(RestaurantManagementViewModel.NormalizedHoldProgress))] private Image _completeBatchFilledImage; protected override void Awake() { base.Awake(); SetupViewModelEvents(); } protected override void Update() { base.Update(); if (_viewModel != null && _viewModel.IsHolding) { _viewModel.UpdateHoldProgress(); } } public override void Open(OpenPopupUiEvent evt) { base.Open(evt); InitializeViews(); SetupTabs(); } protected override GameObject GetInitialSelected() { // ViewModel의 현재 상태에 따라 초기 선택 UI 결정 var inventoryInitialSelected = _inventoryView.GetInitialSelected(); if (inventoryInitialSelected) return inventoryInitialSelected; var menuCategoryButton = _menuCategoryTabs.GetFirstInteractableButton(); if (menuCategoryButton != null && menuCategoryButton.activeInHierarchy) return menuCategoryButton; var cookwareCategoryButton = _cookwareCategoryTabs.GetFirstInteractableButton(); if (cookwareCategoryButton != null && cookwareCategoryButton.activeInHierarchy) return cookwareCategoryButton; return null; } protected override void SetupBindings() { // Attribute 기반 자동 바인딩이 처리됨 // 추가적인 수동 바인딩이 필요한 경우 여기에 구현 } protected override void HandleCustomPropertyChanged(string propertyName) { switch (propertyName) { case nameof(RestaurantManagementViewModel.CurrentSection): UpdateSectionTabs(); break; case nameof(RestaurantManagementViewModel.CurrentCategory): UpdateCategoryTabs(); break; } } private void SetupViewModelEvents() { if (!_viewModel) return; _viewModel.OnBatchCompleted = HandleBatchCompleted; _viewModel.OnChecklistFailed = HandleChecklistFailed; _viewModel.OnMenuSectionSelected = HandleMenuSectionSelected; _viewModel.OnCookwareSectionSelected = HandleCookwareSectionSelected; _viewModel.OnCategoryChanged = HandleCategoryChanged; _viewModel.OnTabMoved = HandleTabMoved; _viewModel.OnInteractRequested = HandleInteractRequested; _viewModel.OnCloseRequested = HandleCloseRequested; _viewModel.OnMenuCategorySelected = HandleMenuCategorySelected; } private void InitializeViews() { _checklistView.Initalize(); _inventoryView.Initialize(); _itemDetailView.Initialize(); _todayMenuView.Initialize(); _todayRestaurantStateView.Initialize(); } private void SetupTabs() { SetupCategoryTabs(); InitializeTabGroups(); SelectInitialTabs(); } private void SetupCategoryTabs() { _menuCategoryTabs.UseDefaultAllowedValues(); _cookwareCategoryTabs.UseDefaultAllowedValues(); } private void InitializeTabGroups() { _sectionTabs.Initialize(OnSectionTabSelected); _menuCategoryTabs.Initialize(OnCategoryTabSelected); _cookwareCategoryTabs.Initialize(OnCategoryTabSelected); } private void SelectInitialTabs() { _sectionTabs.SelectFirstTab(); _menuCategoryTabs.SelectFirstTab(); } private void UpdateSectionTabs() { if (_viewModel == null) return; _sectionTabs.SelectTab((int)_viewModel.CurrentSection); } private void UpdateCategoryTabs() { if (_viewModel == null) return; switch (_viewModel.CurrentSection) { case SectionButtonType.Menu: _menuCategoryTabs.SelectTab((int)_viewModel.CurrentCategory); break; case SectionButtonType.Cookware: _cookwareCategoryTabs.SelectTab((int)_viewModel.CurrentCategory); break; } } // ViewModel 이벤트 핸들러들 private void HandleBatchCompleted() { Close(); } private void HandleChecklistFailed() { var evt = GameEvents.OpenPopupUiEvent; evt.UiType = typeof(ConfirmUi); evt.IsCancelButtonVisible = true; evt.NewMessageKey = "checklist_failed_message"; evt.OnConfirm = ClosePanel; EventBus.Broadcast(evt); } private void HandleMenuSectionSelected() { _menuCategoryTabs.SelectFirstTab(); } private void HandleCookwareSectionSelected() { _cookwareCategoryTabs.SelectFirstTab(); } private void HandleCategoryChanged(InventoryCategoryType category) { _inventoryView.UpdateCategoryView(category); _itemDetailView.UpdateCategory(category); } private void HandleTabMoved(int direction) { _sectionTabs.Move(direction); } private void HandleInteractRequested() { var selected = EventSystem.current.currentSelectedGameObject; var interactable = selected?.GetComponent(); interactable?.OnInteract(); } private void HandleCloseRequested() { Close(); } private void HandleMenuCategorySelected(InventoryCategoryType category) { _menuCategoryTabs.SelectTab((int)category); } // UI 이벤트 핸들러들 (TabGroupUi 콜백) private void OnSectionTabSelected(int sectionValue) { _viewModel?.SetSection((SectionButtonType)sectionValue); } private void OnCategoryTabSelected(int categoryValue) { _viewModel?.SetCategory((InventoryCategoryType)categoryValue); } // 입력 처리 - ViewModel로 위임 protected override bool OnInputPerformed(RestaurantUiActions actionEnum, InputAction.CallbackContext context) { var isHandled = base.OnInputPerformed(actionEnum, context); if (isHandled && _viewModel != null) { switch (actionEnum) { case RestaurantUiActions.Cancel: _viewModel.CloseUi(); break; case RestaurantUiActions.PreviousTab: _viewModel.MoveTab(-1); break; case RestaurantUiActions.NextTab: _viewModel.MoveTab(1); break; case RestaurantUiActions.Interact1: _viewModel.InteractWithSelected(); break; case RestaurantUiActions.Interact2: _viewModel.StartHold(); break; } } return isHandled; } protected override bool OnInputCanceled(RestaurantUiActions actionEnum, InputAction.CallbackContext context) { var isHandled = base.OnInputCanceled(actionEnum, context); if (isHandled && _viewModel != null) { switch (actionEnum) { case RestaurantUiActions.Interact2: _viewModel.CancelHold(); break; } } return isHandled; } } }