refactor: complete modal class-based architecture, design system integration, and map editor modularization
This commit is contained in:
@@ -1,5 +1,106 @@
|
||||
import { createIcons, X } from 'lucide';
|
||||
import { setEditLock } from './ModalUtils';
|
||||
|
||||
/**
|
||||
* 모든 모달의 공통 기능 (닫기, ESC 처리, 배경 클릭 등)을 관리하는 베이스 모듈입니다.
|
||||
* 모든 모달의 공통 기능을 관리하는 베이스 추상 클래스입니다.
|
||||
*/
|
||||
export abstract class BaseModal {
|
||||
protected idPrefix: string;
|
||||
protected title: string;
|
||||
protected currentAsset: any | null = null;
|
||||
protected isEditMode: boolean = false;
|
||||
protected modalEl: HTMLElement | null = null;
|
||||
protected formEl: HTMLFormElement | null = null;
|
||||
|
||||
constructor(idPrefix: string, title: string) {
|
||||
this.idPrefix = idPrefix;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* 모달 초기화: HTML 삽입 및 공통 이벤트 바인딩
|
||||
*/
|
||||
public init(onSave: () => void, closeModalsFn: () => void) {
|
||||
// 1. 프레임 HTML 삽입 (자식 클래스에서 정의한 HTML 사용)
|
||||
if (!document.getElementById(`${this.idPrefix}-asset-modal`)) {
|
||||
document.body.insertAdjacentHTML('beforeend', this.renderFrameHTML());
|
||||
}
|
||||
|
||||
this.modalEl = document.getElementById(`${this.idPrefix}-asset-modal`);
|
||||
this.formEl = document.getElementById(`${this.idPrefix}-asset-form`) as HTMLFormElement;
|
||||
|
||||
// 2. 공통 버튼 이벤트 바인딩 (닫기, 취소 등)
|
||||
const btnCloseHeader = document.getElementById(`btn-close-${this.idPrefix}-modal`);
|
||||
const btnCancelFooter = document.getElementById(`btn-cancel-${this.idPrefix}-modal`);
|
||||
|
||||
const closeAction = () => {
|
||||
this.close();
|
||||
closeModalsFn(); // 전역 모달 상태 해제 콜백
|
||||
};
|
||||
|
||||
btnCloseHeader?.addEventListener('click', closeAction);
|
||||
btnCancelFooter?.addEventListener('click', closeAction);
|
||||
|
||||
// 3. 자식 클래스 전용 초기화 로직 실행
|
||||
this.initChildLogic(onSave, closeModalsFn);
|
||||
|
||||
// 4. 아이콘 초기화
|
||||
createIcons({ icons: { X } });
|
||||
}
|
||||
|
||||
/**
|
||||
* 모달 열기: 데이터 바인딩 및 모드 설정
|
||||
*/
|
||||
public open(asset: any, mode: 'view' | 'edit' | 'add' = 'view') {
|
||||
this.currentAsset = asset;
|
||||
this.isEditMode = (mode === 'add' || mode === 'edit');
|
||||
|
||||
this.setEditLockMode(mode);
|
||||
this.fillFormData(asset);
|
||||
|
||||
if (this.modalEl) {
|
||||
this.modalEl.classList.remove('hidden');
|
||||
}
|
||||
|
||||
this.onAfterOpen(asset, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 모달 닫기: 상태 초기화
|
||||
*/
|
||||
public close() {
|
||||
if (this.modalEl) {
|
||||
this.modalEl.classList.add('hidden');
|
||||
}
|
||||
this.isEditMode = false;
|
||||
this.currentAsset = null;
|
||||
this.onAfterClose();
|
||||
}
|
||||
|
||||
/**
|
||||
* 조회/수정 모드에 따른 UI 잠금 및 버튼 제어
|
||||
*/
|
||||
protected setEditLockMode(mode: 'view' | 'edit' | 'add') {
|
||||
setEditLock(`${this.idPrefix}-asset-form`, mode, {
|
||||
saveBtnId: `btn-save-${this.idPrefix}-asset`,
|
||||
revertBtnId: `btn-revert-${this.idPrefix}-edit`,
|
||||
addLogBtnId: `btn-add-${this.idPrefix}-log`
|
||||
});
|
||||
}
|
||||
|
||||
// --- 추상 메서드: 자식 클래스에서 구현해야 함 ---
|
||||
protected abstract renderFrameHTML(): string;
|
||||
protected abstract initChildLogic(onSave: () => void, closeModals: () => void): void;
|
||||
protected abstract fillFormData(asset: any): void;
|
||||
protected abstract onAfterOpen(asset: any, mode: string): void;
|
||||
|
||||
// --- 훅(Hook) 메서드: 필요 시 오버라이드 ---
|
||||
protected onAfterClose(): void {}
|
||||
}
|
||||
|
||||
/**
|
||||
* --- 레거시 호환성을 위한 함수형 익스포트 ---
|
||||
* 기존 코드들이 참조하고 있는 함수들을 유지합니다.
|
||||
*/
|
||||
export function closeModals() {
|
||||
const modals = document.querySelectorAll('.modal-overlay');
|
||||
@@ -7,28 +108,14 @@ export function closeModals() {
|
||||
}
|
||||
|
||||
export function initBaseModal() {
|
||||
// ESC 키로 닫기
|
||||
// ESC 키로 모든 모달 닫기
|
||||
window.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') closeModals();
|
||||
});
|
||||
|
||||
// 배경(Overlay) 클릭 시 닫기 (요청에 의해 비활성화됨)
|
||||
/*
|
||||
document.addEventListener('click', (e) => {
|
||||
const target = e.target as HTMLElement;
|
||||
if (target.classList.contains('modal-overlay')) {
|
||||
closeModals();
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
return { closeAllModals: closeModals };
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 모달을 엽니다.
|
||||
* @param modalId 모달 엘리먼트의 ID
|
||||
*/
|
||||
export function openModal(modalId: string) {
|
||||
const modal = document.getElementById(modalId);
|
||||
if (modal) {
|
||||
|
||||
Reference in New Issue
Block a user