fix(capture+loading): 이미지 캡쳐 후 input 사라짐 fix + 처리 중 로딩 오버레이
Deploy momo-erp / deploy (push) Successful in 1m56s

1) capture-share: display:none 으로 빈 input 숨기던 처리 제거.
   외형(border/bg/padding) 만 잠시 제거하고 cssText 로 원복. 캡쳐 후
   날짜 input 이 사라지던 문제 fix (React 가 같은 DOM 재사용 시 hidden
   상태로 남던 케이스 회피).
2) 처리 중 로딩 오버레이 — components/ui/Loading 컴포넌트 활용:
   · admin/orders 페이지 (busy = 일괄 출고)
   · admin/orders StatementPreview (shipping = 단건 출고)
   · admin/inbounds (busy = 입고 저장)
   · admin/proc-payments (busy = 입금 처리)
   가운데 spinner + 메시지 + 반투명 black overlay.
This commit is contained in:
chpark
2026-05-15 02:29:44 +09:00
parent aeafeb9daf
commit 0139282231
4 changed files with 12 additions and 15 deletions
+2
View File
@@ -3,6 +3,7 @@
import { useEffect, useState, useCallback } from "react";
import { Save, RefreshCcw, CheckCircle2, Clock } from "lucide-react";
import Swal from "sweetalert2";
import { Loading } from "@/components/ui/loading";
interface ProcRow {
OBJID: string; PROC_NO: string; PROC_DATE: string;
@@ -213,6 +214,7 @@ export default function InboundsPage() {
return (
<div className="space-y-3">
{busy && <Loading message="입고 처리 중..." />}
<div className="flex items-end justify-between flex-wrap gap-2">
<div>
<h1 className="text-xl font-bold"> </h1>
+3
View File
@@ -4,6 +4,7 @@ import { useEffect, useMemo, useState, useCallback, useRef } from "react";
import { Check, Download, X, RefreshCcw, Truck, AlertCircle, Package, PhoneCall } from "lucide-react";
import Swal from "sweetalert2";
import { captureAndShare } from "@/lib/capture-share";
import { Loading } from "@/components/ui/loading";
// SearchableSelect/useRouter 는 이전 수기 발주 모달용 — 단순 인라인 흐름으로 변경되어 제거
interface Order {
@@ -242,6 +243,7 @@ export default function AdminOrdersPage() {
return (
<div className="space-y-3">
{busy && <Loading message="처리 중..." />}
{/* 헤더 */}
<div className="flex items-end justify-between flex-wrap gap-2">
<div>
@@ -608,6 +610,7 @@ function StatementPreview({
return (
<div className="text-[12px] text-slate-800 space-y-3">
{shipping && <Loading message="출고 처리 중..." />}
{/* 공유/캡처/엑셀/출고 버튼 — 캡처 영역 밖에 배치 */}
<div className="flex justify-end gap-2 print:hidden flex-wrap">
<button
@@ -3,6 +3,7 @@
import { useEffect, useState, useMemo, useCallback } from "react";
import Swal from "sweetalert2";
import { SearchableSelect } from "@/components/ui/searchable-select";
import { Loading } from "@/components/ui/loading";
interface Proc {
OBJID: string;
@@ -126,6 +127,7 @@ export default function ProcPaymentsPage() {
return (
<div className="space-y-3">
{busy && <Loading message="저장 중..." />}
<div>
<h1 className="text-xl sm:text-2xl font-bold"> </h1>
<p className="text-xs text-slate-500 mt-0.5"> . .</p>
+5 -15
View File
@@ -23,28 +23,18 @@ export async function captureAndShare({ node, filename, shareTitle, shareText, f
const prev: { el: HTMLElement; display: string }[] = [];
hideEls.forEach((el) => { prev.push({ el, display: el.style.display }); el.style.display = "none"; });
// input/select/textarea 의 외형(테두리/배경/padding) 제거 → 텍스트만 깔끔하게.
// - select 의 화살표 아이콘도 appearance:none 으로 가림
// - 비고 등 빈 인풋은 가리기 (값 없으면 영역만 차지)
// input/select/textarea 의 외형(테두리/배경/padding) 만 잠시 제거 — 값은 그대로 표시.
// display:none 으로 숨기지 않음 (React 가 같은 DOM 재사용 시 사라진 채 남는 케이스 회피)
const fields = node.querySelectorAll<HTMLElement>("input, select, textarea");
const fieldPrev: { el: HTMLElement; cssText: string; hidden: boolean }[] = [];
const fieldPrev: { el: HTMLElement; cssText: string }[] = [];
fields.forEach((el) => {
fieldPrev.push({ el, cssText: el.style.cssText, hidden: false });
const tag = el.tagName.toLowerCase();
const val = (el as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement).value;
// 빈 인풋은 숨김 (비고 등) — checkbox 류는 제외
const type = (el as HTMLInputElement).type;
if (tag !== "select" && type !== "checkbox" && type !== "radio" && (!val || !val.trim())) {
el.style.display = "none";
fieldPrev[fieldPrev.length - 1].hidden = true;
return;
}
// 외형 제거 — 값만 텍스트처럼 보이게
fieldPrev.push({ el, cssText: el.style.cssText });
el.style.border = "none";
el.style.background = "transparent";
el.style.boxShadow = "none";
el.style.padding = "0";
el.style.outline = "none";
const tag = el.tagName.toLowerCase();
if (tag === "select") {
el.style.appearance = "none";
(el.style as CSSStyleDeclaration & { webkitAppearance?: string }).webkitAppearance = "none";