# -*- coding: utf-8 -*- """ 당무 변경 다이얼로그 오늘의 당무자(부팀장, 운용)를 선택합니다. """ from datetime import date from typing import Optional from PySide6.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QLabel ) from PySide6.QtCore import Qt, Signal from PySide6.QtGui import QFont from ui.base.base_dialog import BaseDialog from ui.components.custom_input import CustomComboBox, LabeledInput from ui.styles.style_manager import StyleManager from database.crud import CRUDManager from database.models import TeamMember from core.logger import get_logger logger = get_logger(__name__) class DutyChangeDialog(BaseDialog): """ 당무 변경 다이얼로그 오늘의 당무자를 선택합니다. 부팀장과 운용을 각각 선택할 수 있습니다. """ duty_changed = Signal(str, str) # vice_leader_name, operator_name def __init__( self, parent=None, team: str = "", shift: str = "" ): self.team = team self.shift = shift self.crud = CRUDManager() self.style_manager = StyleManager() super().__init__( parent, title=f"당무 변경 - {team} {shift}", width=400, height=350, min_width=350, min_height=600, resizable=True ) self._setup_content() self.add_confirm_cancel_buttons("저장", "취소") self._load_current_duty() def change_UI_Info(self, team: str, shift: str): """UI 정보 변경""" self.team = team self.shift = shift self.title = f"당무 변경 - {team} {shift}" self.setWindowTitle(self.title) self._setup_content() self._load_current_duty() self.add_confirm_cancel_buttons("저장", "취소") def _setup_content(self): """컨텐츠 설정""" colors = self.style_manager.get_colors() # 날짜 표시 today = date.today() date_label = QLabel(f"📅 {today.year}년 {today.month}월 {today.day}일") date_font = self.style_manager.get_font("dialog", "title") date_label.setFont(date_font) date_label.setAlignment(Qt.AlignCenter) date_height = self.style_manager.calculate_label_height( font=date_font, area="dialog", style="title" ) date_label.setStyleSheet(f""" color: {colors['text_primary']}; min-height: {date_height}px; """) self.content_layout.addWidget(date_label) # 팀/근무 정보 info_label = QLabel(f"🏢 {self.team} | {self.shift}") info_font = self.style_manager.get_font("dialog", "label") info_label.setFont(info_font) info_label.setAlignment(Qt.AlignCenter) info_height = self.style_manager.calculate_label_height( font=info_font, area="dialog", style="label" ) info_label.setStyleSheet(f""" color: {colors['text_tertiary']}; min-height: {info_height}px; margin-bottom: 16px; """) self.content_layout.addWidget(info_label) # 부팀장 선택 self.vice_leader_combo = CustomComboBox( placeholder="부팀장 선택" ) self._load_vice_leaders() self.content_layout.addWidget( LabeledInput("부팀장 당무", self.vice_leader_combo) ) # 운용 선택 self.operator_combo = CustomComboBox( placeholder="운용 선택" ) self._load_operators() self.content_layout.addWidget( LabeledInput("운용 당무", self.operator_combo) ) # 자동 선택 버튼들 auto_section = QWidget() auto_layout = QHBoxLayout(auto_section) auto_layout.setContentsMargins(0, 16, 0, 0) auto_layout.setSpacing(8) from ui.components.custom_button import CustomButton # 다음 순번 버튼 next_btn = CustomButton( "다음 순번 자동선택", style_type="outline", fixed_height=36 ) next_btn.clicked.connect(self._select_next_duty) auto_layout.addWidget(next_btn) self.content_layout.addWidget(auto_section) self.content_layout.addStretch() def _on_text_scale_changed(self, scale: float, label_font, input_font): """ 텍스트 스케일 변경 시 호출 당무 변경 다이얼로그의 텍스트만 동적으로 조정합니다. """ colors = self.style_manager.get_colors() # 날짜 라벨 폰트 조정 base_date_font = self.style_manager.get_font("dialog", "title") date_size = int(base_date_font.pointSize() * scale) date_font = QFont(base_date_font.family(), date_size, base_date_font.weight()) date_height = self.style_manager.calculate_label_height( font=date_font, area="dialog", style="title" ) # 날짜 라벨 찾기 및 업데이트 for i in range(self.content_layout.count()): widget = self.content_layout.itemAt(i).widget() if isinstance(widget, QLabel) and "📅" in widget.text(): widget.setFont(date_font) widget.setStyleSheet(f""" color: {colors['text_primary']}; min-height: {date_height}px; """) break # 팀/근무 정보 라벨 폰트 조정 base_info_font = self.style_manager.get_font("dialog", "label") info_size = int(base_info_font.pointSize() * scale) info_font = QFont(base_info_font.family(), info_size, base_info_font.weight()) info_height = self.style_manager.calculate_label_height( font=info_font, area="dialog", style="label" ) # 팀/근무 정보 라벨 찾기 및 업데이트 for i in range(self.content_layout.count()): widget = self.content_layout.itemAt(i).widget() if isinstance(widget, QLabel) and "🏢" in widget.text(): widget.setFont(info_font) widget.setStyleSheet(f""" color: {colors['text_tertiary']}; min-height: {info_height}px; margin-bottom: 16px; """) break # LabeledInput 내부 라벨 및 입력 필드도 조정 for i in range(self.content_layout.count()): item = self.content_layout.itemAt(i) if item and item.widget(): widget = item.widget() if isinstance(widget, LabeledInput): # 라벨 폰트 조정 label = widget.label label.setFont(label_font) label_height = self.style_manager.calculate_label_height( font=label_font, area="dialog", style="label" ) label.setStyleSheet(f""" color: {colors['text_primary']}; font-family: '{label_font.family()}'; font-size: {label_font.pointSize()}pt; min-height: {label_height}px; """) # 입력 필드 폰트 및 높이 조정 input_widget = widget.input_widget if hasattr(input_widget, 'setFont'): input_widget.setFont(input_font) input_height = self.style_manager.calculate_input_height( font=input_font, area="dialog", style="input" ) if hasattr(input_widget, 'setMinimumHeight'): input_widget.setMinimumHeight(input_height) def _load_vice_leaders(self): """부팀장 목록 로드""" members = self.crud.get_team_members_by_team( self.team, "부팀장", active_only=True ) for member in members: self.vice_leader_combo.addItem(member.name, member.id) def _load_operators(self): """운용 목록 로드""" members = self.crud.get_team_members_by_team( self.team, "운용", active_only=True ) for member in members: self.operator_combo.addItem(member.name, member.id) def _load_current_duty(self): """현재 당무 정보 로드""" today = date.today() duty = self.crud.get_duty_schedule(today, self.team, self.shift) if duty: # 부팀장 선택 if duty.vice_leader_name: idx = self.vice_leader_combo.findText(duty.vice_leader_name) if idx >= 0: self.vice_leader_combo.setCurrentIndex(idx) # 운용 선택 if duty.operator_name: idx = self.operator_combo.findText(duty.operator_name) if idx >= 0: self.operator_combo.setCurrentIndex(idx) def _select_next_duty(self): """다음 순번 자동 선택""" today = date.today() # 현재 당무 정보 조회 current_duty = self.crud.get_duty_schedule(today, self.team, self.shift) # 부팀장 다음 순번 current_vice_leader_id = current_duty.vice_leader_id if current_duty else None next_vice_leader = self.crud.get_next_duty_member( self.team, "부팀장", current_vice_leader_id ) if next_vice_leader: idx = self.vice_leader_combo.findText(next_vice_leader.name) if idx >= 0: self.vice_leader_combo.setCurrentIndex(idx) # 운용 다음 순번 current_operator_id = current_duty.operator_id if current_duty else None next_operator = self.crud.get_next_duty_member( self.team, "운용", current_operator_id ) if next_operator: idx = self.operator_combo.findText(next_operator.name) if idx >= 0: self.operator_combo.setCurrentIndex(idx) def _on_confirm(self): """저장 버튼 클릭""" today = date.today() # 선택된 부팀장 vice_leader_name = self.vice_leader_combo.currentText() vice_leader_id = self.vice_leader_combo.currentData() # 선택된 운용 operator_name = self.operator_combo.currentText() operator_id = self.operator_combo.currentData() # placeholder 체크 if self.vice_leader_combo.currentIndex() == 0: vice_leader_name = "" vice_leader_id = None if self.operator_combo.currentIndex() == 0: operator_name = "" operator_id = None # DB에 저장 self.crud.upsert_duty_schedule( duty_date=today, team=self.team, shift_type=self.shift, vice_leader_id=vice_leader_id, operator_id=operator_id, vice_leader_name=vice_leader_name, operator_name=operator_name ) logger.info( "당무 변경: %s %s - 부팀장: %s, 운용: %s", self.team, self.shift, vice_leader_name, operator_name ) self.duty_changed.emit(vice_leader_name, operator_name) self.accept()