feat: 건조시럽 환산계수 모달 구현 - GET/POST/PUT API 추가 - PMR 약품명 더블클릭 → 모달 오픈 - 신규 등록/수정 기능
This commit is contained in:
parent
9531b74d0e
commit
98d370104b
192
backend/app.py
192
backend/app.py
@ -3953,6 +3953,198 @@ def api_conversion_factor(sung_code):
|
||||
})
|
||||
|
||||
|
||||
@app.route('/api/drug-info/drysyrup/<sung_code>', methods=['GET'])
|
||||
def api_drysyrup_get(sung_code):
|
||||
"""
|
||||
건조시럽 전체 정보 조회 API
|
||||
|
||||
PostgreSQL drysyrup 테이블에서 SUNG_CODE로 전체 정보 조회
|
||||
"""
|
||||
try:
|
||||
session = db_manager.get_postgres_session()
|
||||
if session is None:
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'exists': False,
|
||||
'error': 'PostgreSQL 연결 실패'
|
||||
})
|
||||
|
||||
query = text("""
|
||||
SELECT
|
||||
ingredient_code,
|
||||
ingredient_name,
|
||||
product_name,
|
||||
conversion_factor,
|
||||
post_prep_amount,
|
||||
main_ingredient_amt,
|
||||
storage_conditions,
|
||||
expiration_date
|
||||
FROM drysyrup
|
||||
WHERE ingredient_code = :sung_code
|
||||
LIMIT 1
|
||||
""")
|
||||
row = session.execute(query, {'sung_code': sung_code}).fetchone()
|
||||
|
||||
if not row:
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'exists': False
|
||||
})
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'exists': True,
|
||||
'sung_code': row[0],
|
||||
'ingredient_name': row[1],
|
||||
'product_name': row[2],
|
||||
'conversion_factor': float(row[3]) if row[3] is not None else None,
|
||||
'post_prep_amount': row[4],
|
||||
'main_ingredient_amt': row[5],
|
||||
'storage_conditions': row[6],
|
||||
'expiration_date': row[7]
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"건조시럽 조회 오류 (SUNG_CODE={sung_code}): {e}")
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'exists': False,
|
||||
'error': str(e)
|
||||
})
|
||||
|
||||
|
||||
@app.route('/api/drug-info/drysyrup', methods=['POST'])
|
||||
def api_drysyrup_create():
|
||||
"""
|
||||
건조시럽 신규 등록 API
|
||||
"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
if not data or not data.get('sung_code'):
|
||||
return jsonify({'success': False, 'error': '성분코드 필수'}), 400
|
||||
|
||||
session = db_manager.get_postgres_session()
|
||||
if session is None:
|
||||
return jsonify({'success': False, 'error': 'PostgreSQL 연결 실패'}), 500
|
||||
|
||||
# 중복 체크
|
||||
check_query = text("SELECT 1 FROM drysyrup WHERE ingredient_code = :sung_code")
|
||||
existing = session.execute(check_query, {'sung_code': data['sung_code']}).fetchone()
|
||||
if existing:
|
||||
return jsonify({'success': False, 'error': '이미 등록된 성분코드'}), 400
|
||||
|
||||
insert_query = text("""
|
||||
INSERT INTO drysyrup (
|
||||
ingredient_code, ingredient_name, product_name,
|
||||
conversion_factor, post_prep_amount, main_ingredient_amt,
|
||||
storage_conditions, expiration_date
|
||||
) VALUES (
|
||||
:sung_code, :ingredient_name, :product_name,
|
||||
:conversion_factor, :post_prep_amount, :main_ingredient_amt,
|
||||
:storage_conditions, :expiration_date
|
||||
)
|
||||
""")
|
||||
|
||||
session.execute(insert_query, {
|
||||
'sung_code': data.get('sung_code'),
|
||||
'ingredient_name': data.get('ingredient_name', ''),
|
||||
'product_name': data.get('product_name', ''),
|
||||
'conversion_factor': data.get('conversion_factor'),
|
||||
'post_prep_amount': data.get('post_prep_amount', ''),
|
||||
'main_ingredient_amt': data.get('main_ingredient_amt', ''),
|
||||
'storage_conditions': data.get('storage_conditions', '실온'),
|
||||
'expiration_date': data.get('expiration_date', '')
|
||||
})
|
||||
session.commit()
|
||||
|
||||
return jsonify({'success': True, 'message': '등록 완료'})
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"건조시럽 등록 오류: {e}")
|
||||
try:
|
||||
session.rollback()
|
||||
except:
|
||||
pass
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
|
||||
@app.route('/api/drug-info/drysyrup/<sung_code>', methods=['PUT'])
|
||||
def api_drysyrup_update(sung_code):
|
||||
"""
|
||||
건조시럽 정보 수정 API
|
||||
"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
if not data:
|
||||
return jsonify({'success': False, 'error': '데이터 필수'}), 400
|
||||
|
||||
session = db_manager.get_postgres_session()
|
||||
if session is None:
|
||||
return jsonify({'success': False, 'error': 'PostgreSQL 연결 실패'}), 500
|
||||
|
||||
# 존재 여부 확인
|
||||
check_query = text("SELECT 1 FROM drysyrup WHERE ingredient_code = :sung_code")
|
||||
existing = session.execute(check_query, {'sung_code': sung_code}).fetchone()
|
||||
|
||||
if not existing:
|
||||
# 없으면 신규 등록으로 처리
|
||||
insert_query = text("""
|
||||
INSERT INTO drysyrup (
|
||||
ingredient_code, ingredient_name, product_name,
|
||||
conversion_factor, post_prep_amount, main_ingredient_amt,
|
||||
storage_conditions, expiration_date
|
||||
) VALUES (
|
||||
:sung_code, :ingredient_name, :product_name,
|
||||
:conversion_factor, :post_prep_amount, :main_ingredient_amt,
|
||||
:storage_conditions, :expiration_date
|
||||
)
|
||||
""")
|
||||
session.execute(insert_query, {
|
||||
'sung_code': sung_code,
|
||||
'ingredient_name': data.get('ingredient_name', ''),
|
||||
'product_name': data.get('product_name', ''),
|
||||
'conversion_factor': data.get('conversion_factor'),
|
||||
'post_prep_amount': data.get('post_prep_amount', ''),
|
||||
'main_ingredient_amt': data.get('main_ingredient_amt', ''),
|
||||
'storage_conditions': data.get('storage_conditions', '실온'),
|
||||
'expiration_date': data.get('expiration_date', '')
|
||||
})
|
||||
else:
|
||||
# 있으면 업데이트
|
||||
update_query = text("""
|
||||
UPDATE drysyrup SET
|
||||
ingredient_name = :ingredient_name,
|
||||
product_name = :product_name,
|
||||
conversion_factor = :conversion_factor,
|
||||
post_prep_amount = :post_prep_amount,
|
||||
main_ingredient_amt = :main_ingredient_amt,
|
||||
storage_conditions = :storage_conditions,
|
||||
expiration_date = :expiration_date
|
||||
WHERE ingredient_code = :sung_code
|
||||
""")
|
||||
session.execute(update_query, {
|
||||
'sung_code': sung_code,
|
||||
'ingredient_name': data.get('ingredient_name', ''),
|
||||
'product_name': data.get('product_name', ''),
|
||||
'conversion_factor': data.get('conversion_factor'),
|
||||
'post_prep_amount': data.get('post_prep_amount', ''),
|
||||
'main_ingredient_amt': data.get('main_ingredient_amt', ''),
|
||||
'storage_conditions': data.get('storage_conditions', '실온'),
|
||||
'expiration_date': data.get('expiration_date', '')
|
||||
})
|
||||
|
||||
session.commit()
|
||||
return jsonify({'success': True, 'message': '저장 완료'})
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"건조시럽 수정 오류 (SUNG_CODE={sung_code}): {e}")
|
||||
try:
|
||||
session.rollback()
|
||||
except:
|
||||
pass
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
|
||||
# ==================== 입고이력 API ====================
|
||||
|
||||
@app.route('/api/drugs/<drug_code>/purchase-history')
|
||||
|
||||
56
backend/templates/partials/drysyrup_modal.html
Normal file
56
backend/templates/partials/drysyrup_modal.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!-- 건조시럽 환산계수 모달 -->
|
||||
<div id="drysyrupModal" class="drysyrup-modal">
|
||||
<div class="drysyrup-modal-content">
|
||||
<div class="drysyrup-modal-header">
|
||||
<h3>🧪 건조시럽 환산계수</h3>
|
||||
<button class="drysyrup-modal-close" onclick="closeDrysyrupModal()">×</button>
|
||||
</div>
|
||||
<div class="drysyrup-modal-body">
|
||||
<div class="drysyrup-form">
|
||||
<div class="drysyrup-form-row">
|
||||
<label>성분코드</label>
|
||||
<input type="text" id="drysyrup_sung_code" readonly class="readonly">
|
||||
</div>
|
||||
<div class="drysyrup-form-row">
|
||||
<label>성분명</label>
|
||||
<input type="text" id="drysyrup_ingredient_name" placeholder="예: 아목시실린">
|
||||
</div>
|
||||
<div class="drysyrup-form-row">
|
||||
<label>제품명</label>
|
||||
<input type="text" id="drysyrup_product_name" placeholder="예: 오구멘틴듀오시럽">
|
||||
</div>
|
||||
<div class="drysyrup-form-row">
|
||||
<label>환산계수 (g/ml)</label>
|
||||
<input type="number" id="drysyrup_conversion_factor" step="0.001" placeholder="예: 0.11">
|
||||
<span class="hint">ml × 환산계수 = g</span>
|
||||
</div>
|
||||
<div class="drysyrup-form-row">
|
||||
<label>조제 후 함량</label>
|
||||
<input type="text" id="drysyrup_post_prep_amount" placeholder="예: 4.8mg/ml">
|
||||
</div>
|
||||
<div class="drysyrup-form-row">
|
||||
<label>분말 중 주성분량</label>
|
||||
<input type="text" id="drysyrup_main_ingredient_amt" placeholder="예: 0.787g/100g">
|
||||
</div>
|
||||
<div class="drysyrup-form-row">
|
||||
<label>보관조건</label>
|
||||
<select id="drysyrup_storage_conditions">
|
||||
<option value="실온">실온</option>
|
||||
<option value="냉장">냉장</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="drysyrup-form-row">
|
||||
<label>조제 후 유효기간</label>
|
||||
<input type="text" id="drysyrup_expiration_date" placeholder="예: 15일">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="drysyrup-modal-footer">
|
||||
<span id="drysyrup_status" class="status-text"></span>
|
||||
<div class="button-group">
|
||||
<button class="btn-cancel" onclick="closeDrysyrupModal()">취소</button>
|
||||
<button class="btn-save" onclick="saveDrysyrup()">💾 저장</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1226,6 +1226,133 @@
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
/* 건조시럽 환산계수 모달 */
|
||||
.drysyrup-modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0; left: 0; right: 0; bottom: 0;
|
||||
background: rgba(0,0,0,0.6);
|
||||
z-index: 1100;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.drysyrup-modal.show { display: flex; justify-content: center; align-items: flex-start; padding: 40px 20px; }
|
||||
.drysyrup-modal-content {
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
background: #fff;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
|
||||
overflow: hidden;
|
||||
}
|
||||
.drysyrup-modal-header {
|
||||
background: linear-gradient(135deg, #10b981, #059669);
|
||||
color: #fff;
|
||||
padding: 18px 25px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.drysyrup-modal-header h3 { margin: 0; font-size: 1.2rem; }
|
||||
.drysyrup-modal-close {
|
||||
background: rgba(255,255,255,0.2);
|
||||
border: none;
|
||||
color: #fff;
|
||||
font-size: 1.5rem;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
.drysyrup-modal-close:hover { background: rgba(255,255,255,0.3); }
|
||||
.drysyrup-modal-body { padding: 25px; }
|
||||
.drysyrup-form { display: flex; flex-direction: column; gap: 16px; }
|
||||
.drysyrup-form-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
.drysyrup-form-row label {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: #374151;
|
||||
}
|
||||
.drysyrup-form-row input,
|
||||
.drysyrup-form-row select {
|
||||
padding: 10px 14px;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 8px;
|
||||
font-size: 0.95rem;
|
||||
transition: border-color 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
.drysyrup-form-row input:focus,
|
||||
.drysyrup-form-row select:focus {
|
||||
outline: none;
|
||||
border-color: #10b981;
|
||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);
|
||||
}
|
||||
.drysyrup-form-row input.readonly {
|
||||
background: #f3f4f6;
|
||||
color: #6b7280;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.drysyrup-form-row .hint {
|
||||
font-size: 0.75rem;
|
||||
color: #9ca3af;
|
||||
}
|
||||
.drysyrup-modal-footer {
|
||||
background: #f9fafb;
|
||||
padding: 16px 25px;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.drysyrup-modal-footer .status-text {
|
||||
font-size: 0.85rem;
|
||||
color: #6b7280;
|
||||
}
|
||||
.drysyrup-modal-footer .button-group {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
.drysyrup-modal-footer .btn-cancel {
|
||||
padding: 10px 20px;
|
||||
background: #e5e7eb;
|
||||
color: #374151;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
.drysyrup-modal-footer .btn-cancel:hover { background: #d1d5db; }
|
||||
.drysyrup-modal-footer .btn-save {
|
||||
padding: 10px 24px;
|
||||
background: linear-gradient(135deg, #10b981, #059669);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
.drysyrup-modal-footer .btn-save:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
|
||||
}
|
||||
|
||||
/* 약품명 더블클릭 힌트 */
|
||||
.med-name[data-sung-code]:not([data-sung-code=""]) {
|
||||
cursor: pointer;
|
||||
}
|
||||
.med-name[data-sung-code]:not([data-sung-code=""]):hover {
|
||||
text-decoration: underline;
|
||||
text-decoration-style: dotted;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -3278,5 +3405,190 @@
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
<!-- 건조시럽 환산계수 모달 -->
|
||||
<div id="drysyrupModal" class="drysyrup-modal">
|
||||
<div class="drysyrup-modal-content">
|
||||
<div class="drysyrup-modal-header">
|
||||
<h3>🧪 건조시럽 환산계수</h3>
|
||||
<button class="drysyrup-modal-close" onclick="closeDrysyrupModal()">×</button>
|
||||
</div>
|
||||
<div class="drysyrup-modal-body">
|
||||
<div class="drysyrup-form">
|
||||
<div class="drysyrup-form-row">
|
||||
<label>성분코드</label>
|
||||
<input type="text" id="drysyrup_sung_code" readonly class="readonly">
|
||||
</div>
|
||||
<div class="drysyrup-form-row">
|
||||
<label>성분명</label>
|
||||
<input type="text" id="drysyrup_ingredient_name" placeholder="예: 아목시실린">
|
||||
</div>
|
||||
<div class="drysyrup-form-row">
|
||||
<label>제품명</label>
|
||||
<input type="text" id="drysyrup_product_name" placeholder="예: 오구멘틴듀오시럽">
|
||||
</div>
|
||||
<div class="drysyrup-form-row">
|
||||
<label>환산계수 (g/ml)</label>
|
||||
<input type="number" id="drysyrup_conversion_factor" step="0.001" placeholder="예: 0.11">
|
||||
<span class="hint">ml × 환산계수 = g</span>
|
||||
</div>
|
||||
<div class="drysyrup-form-row">
|
||||
<label>조제 후 함량</label>
|
||||
<input type="text" id="drysyrup_post_prep_amount" placeholder="예: 4.8mg/ml">
|
||||
</div>
|
||||
<div class="drysyrup-form-row">
|
||||
<label>분말 중 주성분량</label>
|
||||
<input type="text" id="drysyrup_main_ingredient_amt" placeholder="예: 0.787g/100g">
|
||||
</div>
|
||||
<div class="drysyrup-form-row">
|
||||
<label>보관조건</label>
|
||||
<select id="drysyrup_storage_conditions">
|
||||
<option value="실온">실온</option>
|
||||
<option value="냉장">냉장</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="drysyrup-form-row">
|
||||
<label>조제 후 유효기간</label>
|
||||
<input type="text" id="drysyrup_expiration_date" placeholder="예: 15일">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="drysyrup-modal-footer">
|
||||
<span id="drysyrup_status" class="status-text"></span>
|
||||
<div class="button-group">
|
||||
<button class="btn-cancel" onclick="closeDrysyrupModal()">취소</button>
|
||||
<button class="btn-save" onclick="saveDrysyrup()">💾 저장</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// ==================== 건조시럽 환산계수 모달 ====================
|
||||
let drysyrupIsNew = false;
|
||||
|
||||
// 약품명 더블클릭 이벤트 등록
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// 동적으로 생성되는 요소를 위해 이벤트 위임 사용
|
||||
document.addEventListener('dblclick', function(e) {
|
||||
// 약품 행(tr)에서 더블클릭 감지
|
||||
const row = e.target.closest('tr[data-sung-code]');
|
||||
if (row) {
|
||||
const sungCode = row.dataset.sungCode;
|
||||
const medName = row.dataset.medName || '';
|
||||
if (sungCode) {
|
||||
openDrysyrupModal(sungCode, medName);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 모달 열기
|
||||
async function openDrysyrupModal(sungCode, medName) {
|
||||
const modal = document.getElementById('drysyrupModal');
|
||||
const statusEl = document.getElementById('drysyrup_status');
|
||||
|
||||
// 폼 초기화
|
||||
document.getElementById('drysyrup_sung_code').value = sungCode;
|
||||
document.getElementById('drysyrup_ingredient_name').value = '';
|
||||
document.getElementById('drysyrup_product_name').value = medName || '';
|
||||
document.getElementById('drysyrup_conversion_factor').value = '';
|
||||
document.getElementById('drysyrup_post_prep_amount').value = '';
|
||||
document.getElementById('drysyrup_main_ingredient_amt').value = '';
|
||||
document.getElementById('drysyrup_storage_conditions').value = '실온';
|
||||
document.getElementById('drysyrup_expiration_date').value = '';
|
||||
statusEl.textContent = '로딩 중...';
|
||||
|
||||
modal.classList.add('show');
|
||||
|
||||
// API 호출
|
||||
try {
|
||||
const resp = await fetch('/api/drug-info/drysyrup/' + encodeURIComponent(sungCode));
|
||||
const data = await resp.json();
|
||||
|
||||
if (data.exists) {
|
||||
// 기존 데이터 채우기
|
||||
document.getElementById('drysyrup_ingredient_name').value = data.ingredient_name || '';
|
||||
document.getElementById('drysyrup_product_name').value = data.product_name || '';
|
||||
document.getElementById('drysyrup_conversion_factor').value = data.conversion_factor || '';
|
||||
document.getElementById('drysyrup_post_prep_amount').value = data.post_prep_amount || '';
|
||||
document.getElementById('drysyrup_main_ingredient_amt').value = data.main_ingredient_amt || '';
|
||||
document.getElementById('drysyrup_storage_conditions').value = data.storage_conditions || '실온';
|
||||
document.getElementById('drysyrup_expiration_date').value = data.expiration_date || '';
|
||||
statusEl.textContent = '✅ 등록된 데이터';
|
||||
drysyrupIsNew = false;
|
||||
} else {
|
||||
statusEl.textContent = '🆕 신규 등록';
|
||||
drysyrupIsNew = true;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('드라이시럽 조회 오류:', err);
|
||||
statusEl.textContent = '⚠️ 조회 실패 (신규 등록 가능)';
|
||||
drysyrupIsNew = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 모달 닫기
|
||||
function closeDrysyrupModal() {
|
||||
document.getElementById('drysyrupModal').classList.remove('show');
|
||||
}
|
||||
|
||||
// 저장
|
||||
async function saveDrysyrup() {
|
||||
const sungCode = document.getElementById('drysyrup_sung_code').value;
|
||||
const statusEl = document.getElementById('drysyrup_status');
|
||||
|
||||
const data = {
|
||||
sung_code: sungCode,
|
||||
ingredient_name: document.getElementById('drysyrup_ingredient_name').value,
|
||||
product_name: document.getElementById('drysyrup_product_name').value,
|
||||
conversion_factor: parseFloat(document.getElementById('drysyrup_conversion_factor').value) || null,
|
||||
post_prep_amount: document.getElementById('drysyrup_post_prep_amount').value,
|
||||
main_ingredient_amt: document.getElementById('drysyrup_main_ingredient_amt').value,
|
||||
storage_conditions: document.getElementById('drysyrup_storage_conditions').value,
|
||||
expiration_date: document.getElementById('drysyrup_expiration_date').value
|
||||
};
|
||||
|
||||
statusEl.textContent = '저장 중...';
|
||||
|
||||
try {
|
||||
const url = drysyrupIsNew ? '/api/drug-info/drysyrup' : '/api/drug-info/drysyrup/' + encodeURIComponent(sungCode);
|
||||
const method = drysyrupIsNew ? 'POST' : 'PUT';
|
||||
|
||||
const resp = await fetch(url, {
|
||||
method: method,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
const result = await resp.json();
|
||||
|
||||
if (result.success) {
|
||||
statusEl.textContent = '✅ 저장 완료!';
|
||||
window.showToast && window.showToast('환산계수 저장 완료', 'success');
|
||||
setTimeout(closeDrysyrupModal, 1000);
|
||||
} else {
|
||||
statusEl.textContent = '❌ ' + (result.error || '저장 실패');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('드라이시럽 저장 오류:', err);
|
||||
statusEl.textContent = '❌ 저장 오류';
|
||||
}
|
||||
}
|
||||
|
||||
// ESC 키로 모달 닫기
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
closeDrysyrupModal();
|
||||
}
|
||||
});
|
||||
|
||||
// 모달 바깥 클릭시 닫기
|
||||
document.getElementById('drysyrupModal').addEventListener('click', function(e) {
|
||||
if (e.target === this) {
|
||||
closeDrysyrupModal();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user