기존: user.role === "USER" 일 때 숨김 → 거래처라도 role 필드 비어있으면 노출되는 버그
변경: user.isAdmin === true || role === "ADMIN" 일 때만 노출 → 그 외는 모두 숨김
admin 계정만 거래명세표 이미지 공유 가능.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
기존: mount 시 한 번만 history sentinel push → 사용자가 navigation 하면 sentinel 잃어버려 토스트 안 뜸.
변경: usePathname 의존성 useEffect → pathname 변경마다 sentinel 새로 push. lastBackRef 도 ref 로 변경(렌더 의존성 없이 상태 유지).
+ swal toast z-index 9999 강제 (다른 모달 위)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- middleware: User-Agent 가 모바일이면 /login → /m/login 으로 redirect (서버 측 분기)
- auth-store.logout: window 가 모바일이면 /m/login, 아니면 /login (클라이언트 측 분기)
- BackButtonGuard: TWA 일부 환경에서 display-mode 가 standalone 으로 보고되지 않는 케이스 대응 — fullscreen/minimal-ui 도 포함, 모바일 UA 면 무조건 활성화
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
m/orders 페이지의 거래명세표 DetailModal 에서 "이미지 공유" 버튼이 모든 사용자에게 노출되던 문제.
useAuthStore 의 user.role === "USER" 이면 버튼 hide. ADMIN 은 그대로 표시.
엑셀 다운로드 버튼은 그대로 유지 (사용자가 자기 주문 명세는 엑셀로 받을 수 있음).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- src/components/back-button-guard.tsx 신규: standalone(PWA/TWA) 모드에서만 작동
· 첫 뒤로가기 → sweetalert2 toast("한 번 더 누르면 앱이 종료됩니다") 표시
· 2초 안에 두 번째 뒤로가기 → history.back() 으로 native back 위임 → 앱 종료
· 일반 브라우저(non-standalone) 사용자에게는 영향 없음
- src/app/layout.tsx 의 RootLayout 에 BackButtonGuard 마운트
- src/app/(auth)/m/login/page.tsx 에 1.5초 스플래시 overlay 추가
· 모모 로고 + "모모유통 ERP" + spinner ("로딩 중...")
· z-60 fixed inset-0, 1.5s 후 opacity fade-out
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- src/lib/capture-share.ts 에 forceWidth 옵션 추가 → 캡처 직전 임시로 node width 강제 + 즉시 원복
- 출고 처리(거래명세표) 와 매입발주서 관리의 이미지 공유 호출에 forceWidth: 1100 적용
- 모바일 화면(좁은 viewport)에서 좁아진 표/품명 셀이 한 줄로 펼쳐져 엑셀 가로 출력처럼 캡처됨
- m/orders 페이지의 inline captureAndShare 를 capture-share lib 으로 통일 (toJpeg fallback / AbortError 처리 공유)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- src/app/(auth)/m/login/page.tsx 신규 — 한 화면에 딱 맞는 모바일 layout (logo + form + 푸터, safe-area inset 적용)
- middleware.ts publicPaths 에 /m/login + PWA 자원(/manifest.json, /sw.js, /.well-known) 추가
- 세션 있는 상태로 /m/login 진입 시 /m/dashboard 로 자동 redirect
- manifest.json 의 start_url 을 /m/login 으로 변경 → TWA APK 가 앱 실행 시 바로 로그인 화면
로그인 성공 시 /m/dashboard 로 이동 (기존 /login 은 API 응답의 redirectTo 사용, 모바일은 hardcode).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v1.0.0 APK (com.momotogether.erp) 의 서명 인증서 SHA-256 을 Digital Asset Links 에 등록.
이 commit 이 production 에 배포되면 TWA 앱이 URL bar 없이 풀스크린으로 동작.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- public/manifest.json + service worker(sw.js) 추가
- icon PNG 변환 (192/512/180)
- public/.well-known/assetlinks.json placeholder (Bubblewrap 빌드 후 APK 서명 SHA256 채울 자리)
- layout.tsx 에 manifest/theme-color/apple-touch-icon 메타데이터 + 서비스 워커 등록 스크립트 추가
Bubblewrap 으로 APK 빌드 시 https://www.momotogether.com/manifest.json 을 source 로 사용.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
운영 서비스 목록, 데이터 볼륨 위치, 노출 포트, 운영 중 적용한 hotfix(Mailu DNSSEC/MariaDB 11.8 등), Phase 별 이관 체크리스트.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
WebContent/ (JSP + SmartEditor2 + 정적 자원) 와 src/com/ (Spring Controller/Service/Mapper) 디렉토리 전체 삭제. 총 2,191 파일.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
docker compose build 시 latest 태그가 새 sha 로 갱신되면서 옛 sha 가 untagged
상태로 남아 매 배포마다 누적되던 문제. docker image prune -f 로 dangling 만 회수
(다른 프로젝트의 사용 중 이미지는 안 건드림).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
대시보드는 관리자 전용. USER 가 직접 URL 로 진입해도 즉시 출고 요청 화면으로
리다이렉트되게 차단. (메뉴 매핑 없어도 직접 URL 접근 방지)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 화면 제목: '통계 — 업체별 월간 매출' → '업체별 발주통계 (월별)'
- 메뉴명: '월간 매출' → '업체별 발주통계' (운영 DB menu_info 9000501)
- statistics/monthly API: status IN 에서 SHIPPED (dead code) 제거
- 기존 기능 그대로: 년/월 선택, 업체별 합계 + 면세/과세 분리, 엑셀 다운로드
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[원인]
- db/migrations/009_items_user_permissions.sql 가 user_type<>'C' AND
NOT IN (admin 7인) 사용자를 삭제하는 정리 쿼리를 포함
- user_type 'C' → 'U' 통합 이후 'U' 거래처 134명이 위 조건에 걸려
매 배포마다 통째로 삭제됨 (어제·오늘 두 번 사용자 관리에 거래처 0명)
[수정]
- 해당 DELETE 블록 통째로 주석 처리 — 마이그레이션은 idempotent 해야 하고
destructive 작업은 두지 않는다는 원칙
- 거래처 134명은 별도 복구 스크립트로 다시 INSERT (이 commit 직후)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[원인]
- lib/auth.ts verifyCredentials 는 user.role 을 설정하지 않음
- /api/m/items/list 가 `r.user.role === 'USER'` 만 체크 → 일반 거래처도
isUser=false 가 되어 status='ACTIVE' 필터 & view_hidden 필터 모두 우회
- 결과: 골드망고(status=active, is_hidden=Y) 가 모든 사용자에게 보임
[수정]
- isAdmin = role==='ADMIN' || isAdmin || userType==='A' (3가지 모두 검사)
- isUser = !isAdmin
- items/list: status 'ACTIVE' 비교를 UPPER(...) 로 대소문자 안전화
- orders/save: 숨김 품목(is_hidden='Y') 발주 시도를 view_hidden 권한 없으면 차단
- orders/new 클라이언트의 unlimitedQty 판정에도 userType==='A' 보강
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[부서 안 선택되던 문제]
- /api/admin/dept 가 DEPT_CODE/DEPT_NAME 대문자 반환인데 폼은 dept_code 소문자
로 접근 → 옵션 매칭 실패. 대문자로 통일
[필드 제거]
- 사번(sabun) 입력 제거 (요청)
- dead var isCustomer 제거
[레이아웃 컴팩트화 — 스크롤 없이 한 화면]
- 폰트 13→12, 인풋 h-9→h-8, 여백/마진 축소
- 출고 기준 창고 + 특수 권한 섹션을 별도 큰 카드 → 2열 그리드 안에 통합
- 특수 권한 체크 라벨도 컴팩트 (가로형 inline 칩)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
직전 commit 9e9922e 에서 ListView 내부에서 부모 scope 의 unlimitedQty 를
직접 참조 → TS2304. props 로 명시 전달
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[사용자 관리]
- /api/admin/users 목록에 UNLIMITED_QTY / VIEW_HIDDEN / USER_TYPE 컬럼 반환
- UserManagement 그리드에 '발주한도무시' / '숨김품목보기' 컬럼 추가 (✅/—)
- 사용자 수정 폼: '거래처 특수 권한' → '특수 권한 (발주 시 적용)' 으로 라벨 변경,
거래처(C) 전용이던 조건을 풀어서 일반 사용자(U) 도 권한 부여 가능
[출고요청 (/m/orders/new)]
- /api/auth/me 가 unlimitedQty / viewHidden 반환
- 클라이언트가 unlimitedQty true 면 MAX_ORDER_QTY 무시하고 재고만큼 발주 가능
- '한도 ≤ N' 라벨도 권한자에겐 숨김
(백엔드 검증 — /api/m/items/list 의 view_hidden, /api/m/orders/save 의
unlimited_qty 우회 — 는 이미 구현돼 있어 그대로 동작)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 권한그룹 생성 모달에서 권한CODE 입력 제거 (권한명만 입력)
- 서버: 신규 등록 시 auth_code 비어있으면 GRP_<base36 timestamp> 자동 생성
- 좌측 권한 목록에서도 코드 노출 제거 (내부 식별자만 유지)
- 수정 시 기존 auth_code 는 보존 (COALESCE)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
기존 SQL 은 $isAdmin=true 면 모든 메뉴 통과 → 권한 매핑이 의미 없었음.
사용자 요청: "로그인한 사용자 권한 그룹에 따른 메뉴가 동적으로 나오도록"
- /api/menu: isAdmin 분기 제거, authority_sub_user JOIN authority_sub_menu
매핑만 사용. 자식이 권한에 있으면 부모도 자동 노출(트리 유지) 로직은 유지
- 운영 DB: 관리자그룹에 active 메뉴 36개 일괄 매핑 (재고 이력 9000304 포함).
사용자 관리 화면에서 권한 그룹 멤버 / 메뉴 매핑을 직접 조정해 사용자별
사이드바를 동적으로 제어
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
운영 momo_warehouses.objid 가 text 타입(예: MOMOWH000000001)이라
default_wh_objid 도 text 로 일치시켜야 매핑 가능.
- db/migrations/022_user_default_wh_text.sql
- /api/admin/users/save: ::numeric 캐스트 제거
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[출고 상태 셀렉트 중복 fix]
- STATUS_LABEL 에 APPROVED='출고완료' / SHIPPED='출고완료' 둘 다 매핑돼
셀렉트 옵션에 '출고완료'가 두 번 노출됐음. 운영 DB 분포 확인 결과
SHIPPED 상태값은 0건(dead) → 라벨/색상 매핑에서 SHIPPED 제거.
StatementPreview 의 'SHIPPED' OR 분기도 정리
[입금 관리 검색조건]
- 시작일 / 종료일 / 입금 상태(전체·입금 전·입금완료) / 업체명·발주번호 키워드
- 기본 기간: 이번달 1일 ~ 오늘
- 입금 상태: UNPAID = APPROVED, PAID = PAID + INVOICED 묶어서 필터
- 초기화 / 조회 버튼
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[재고 관리]
- 새 기능 '재고 이동' (A창고 → B창고): 출발창고 잠금 + 충분재고 검증 + 도착
창고 upsert + 이동 로그 2건(OUT/IN, ref_type=TRANSFER) 트랜잭션 처리
- /api/m/inventory/transfer 신규
- 모바일에서 테이블 가로 스크롤이 안 되던 문제 → sm:hidden 카드 + sm:block
desktop 테이블로 분리. 페이지 자체 스크롤로 자연스러운 UX
- 검색 영역 모바일 1열 / sm 3열 그리드 정리
- 재고 이동 모달은 출발창고 선택 시 그 창고에 재고 있는 품목만 셀렉트
- list API 응답에 WH_OBJID 추가 (이동 모달에서 출발창고 필터 용도)
[창고 관리]
- 창고 코드는 자동생성(WH001, WH002 ...) — 등록/수정 폼에서 readonly + 회색.
save API: regist 시 nextWhCode() 로 MAX+1 패딩. update 시 wh_code 미변경
- 클라이언트가 whCode 보내도 무시되도록 서버에서 분기
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[대시보드 → 출고처리 카드 필터]
- 승인 대기 / 진행중 / 미수금 → ?status=...&dateFrom=&dateTo= (전체 기간, 빈 날짜)
- 오늘 발주 → ?dateFrom=오늘&dateTo=오늘
- 이번달 매출/누적 → ?dateFrom=이번달1일&dateTo=오늘
- orders 페이지: 쿼리에 dateFrom/dateTo 키가 있으면(빈값 포함) 그 값 사용,
키가 아예 없을 때만 기본값 오늘. 사용자 모드 페이지도 동일
[출고 요청 카드 그리드]
- grid-cols-3 / md-4 / lg-5 — PC 5개·모바일 3개/줄
- 카드 padding p-3~p-4 → p-2, 폰트/버튼/이미지 라벨 모두 컴팩트
- IS_TAX_FREE/REQUIRES_DELIVERY 배지를 이미지 위 좌상단으로 이동해 공간 절약
- 품목명 line-clamp-2 + min-h-[2em] 로 카드 높이 일정화
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 페이지명: '발주서 관리 · 출고처리' → '출고 처리'
- 검색바 신규: 시작일 / 종료일 / 상태 / 검색어(발주번호·업체명·이메일) / 초기화·조회
- 모바일 1열, sm 2열, lg 5열 그리드로 반응형 정리
- API list: keyword 파라미터 추가 (order_no/user_name/email LIKE)
- 기본 기간 = 오늘. 단 ?status= 으로 진입(대시보드 카드)한 경우 30일 범위
- 검색 조건 변경은 [조회] 버튼으로만 트리거 (자동 reload 제거 → 입력 도중 깜빡임 X)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- /api/menu: super admin 은 모든 메뉴, 일반 사용자는 authority_sub_menu 매핑된
메뉴만 노출. 자식이 권한에 있으면 부모 메뉴도 자동 포함 (트리 유지)
- 권한 관리 화면에서 메뉴 체크 → 다음 로그인부터 사이드바 즉시 반영
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- html-to-image 의 toPng 가 Pretendard CDN 임베드 단계에서 fail 하면 캡처 전체가
깨짐 (Windows Chrome 에서 자주 발생). skipFonts + cacheBust + jpeg fallback 추가
- 거래명세표(orders) / 발주서(procurements) 양쪽이 같은 코드를 복붙으로 갖고 있던
걸 lib/capture-share.ts 로 통합
- 실패 시 err.message 를 swal 에 노출 (이전엔 "잠시 후 다시 시도하세요" 만 떠서
사용자가 원인 추적 불가)
- navigator.share 의 AbortError(사용자 취소) 는 silent 처리 + 그 외엔 다운로드 폴백
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5cbc324 배포 시 --force-recreate 가 이름 충돌(Conflict, 65adeb31db46_momo-erp)을
일으켜 컨테이너 swap 실패. 명시적으로 down --remove-orphans 후 up 으로 분리.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 권한그룹 멤버 추가/제거 API: history insert 를 best-effort 로 분리해 메인 INSERT
실패가 누적 에러로 noisy 응답에 담김. 클라이언트는 fail 분기에서 swal 로 사유 표시
- admin-panel 좌측 사이드바: '메뉴관리' 카테고리는 항상 고정 노출되므로 DB groups
에서 같은 라벨이 다시 내려와도 중복 렌더링 안 함
- 로그인 화면: '아이디/비밀번호 저장' 체크박스 추가 (localStorage SAVE_KEY).
체크 후 로그인 → 다음 방문 시 자동 채움. 해제하면 즉시 삭제
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- useSearchParams 가 Next.js 15 prerender 단계에서 Suspense 경계를 강제해
/admin-panel 빌드 자체가 실패 → docker image 재빌드 안 됨 →
컨테이너 swap 누락(2시간째 옛 이미지). window.location.search 직접 읽기로 대체
- deploy.yml: set +e 제거 (빌드 실패가 워크플로우 success 로 묻히는 문제 차단)
- docker compose 에 --force-recreate 추가 (이미지가 같아도 컨테이너 강제 재생성)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 기존 마커(WORKFLOW/매입 발주/SCREEN PREVIEW)는 옛 빌드에도 들어있어
배포가 실패해도 success로 묻혔음 (사용자: 사이드바 변경이 운영에 안 반영됨)
- SSH 단계에서 git rev-parse HEAD → public/build-sha.txt 에 기록 후 빌드
- 헬스체크가 운영의 /build-sha.txt 를 GITHUB_SHA 와 비교 → 불일치면 워크플로우 fail
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 사이드바: '거래처' 키워드 필터 제거. 사용자 모드 = DB 권한 메뉴 전체,
관리자 모드 = 시스템 관리 가상 카테고리(사용자/권한/메뉴/공통코드/로그)
- admin-panel: ?tab= 쿼리로 진입 탭 결정. 좌상단 '← 사용자' 복귀 링크
- header: admin 자동 admin 모드 진입 제거 (기본 사용자 모드)
- 출고관리 거래명세표 미리보기: 엑셀 다운로드를 이미지 공유/인쇄 옆으로
이동, 출고요청 상태일 때 [출고] 버튼 추가하여 체크 없이 바로 처리
- 발주서 미리보기: [인쇄] 버튼 추가
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[DB 019]
- momo_procurements 에 delivery_place / delivery_period / payment_terms / freight_terms 컬럼 추가
- 기존 supply_mng (공급업체) 데이터 모두 삭제 + 샘플 10개 신규 등록
· (주)아바텍, 대성식품, (주)고기파는농부, 광이진천 농장, 단과일,
봉담수산, 명일동유기농, 울산단과일, 농부의아침, 초록마을 도매
- 시퀀스 가정 없이 MAX(objid)+1 로 안전하게 부여
[발주서 양식 — 표준 거래명세표 양식 반영]
- ProcurementForm: "2. 납품조건" 섹션 추가
· 1)~3) 표준 조항 (납기 지연 공제 / 검수 부적합 반출 / 수량 규격 변경)
· 4) 납품장소 5) 납품기간 6) 대금지불 7) 운임부담 — 표 형식 입력칸
· 8)~9) 표준 조항 (3일 이의 제기 효력 / 명시되지 않은 사항)
· 하단 "상기와 같이 발주함." + 발주일 + 발주자
- update-header API: 4개 필드 동적 업데이트
- /api/m/procurements/excel/[id]: 엑셀 출력에도 납품조건 9개 항목 + 4필드 표
- /api/m/procurements/send: 메일 본문 HTML 에도 납품조건 표 + 표준 조항
[관리자/사용자 모드 토글]
- 헤더 매뉴얼 옆에 [👥 사용자 / 🛡 관리자] 토글 버튼 (admin 권한자만 노출)
- menu-store: viewMode("user"|"admin") + setViewMode 추가
- 사이드바: viewMode 에 따라 대메뉴 필터링
· 사용자 모드: '거래처 주문' 그룹만
· 관리자 모드: 출고/정산 + 매입/입고 + 마스터 관리 + 통계
- admin 권한자 자동으로 로그인 시 관리자 모드 진입
[ItemPicker 모달 모바일 친화]
- 모바일에서 화면 하단 도킹(items-end) → 풀스크린 시트 처럼
- 헤더는 sticky top-0 으로 고정 → 긴 목록에서도 검색바 항상 보임
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[현재고 — 캡처/공유 시에만 숨김]
- 거래처에 보낼 이미지에서 내부 정보(현재고)가 보이면 안 됨
- 거래명세표 표의 현재고 th/td 와 재고 부족 경고 박스에 .js-no-export 클래스 추가
- captureAndShare 안에서 toPng 직전 임시로 display:none → 캡처 후 복원
- 화면에서는 그대로 보이고, 다운받은 PNG/공유 이미지에서만 빠짐
[로그인 유지 — 30일 세션]
- /api/auth/login 요청 body 에 remember 추가
- /lib/session.ts createSession(user, remember=false) — 24시간(기본) / 30일(remember=true)
- 로그인 폼에 [✓ 로그인 유지 (30일)] 체크박스 (기본 ON, 나이 많은 사용자 친화)
- 체크 해제하면 24시간 세션 유지 (기존 동작)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
증상: 모바일에서 좌-우 분할 화면(출고관리 등) 의 페이지 스크롤이 안 됨.
원인:
- 컨테이너 minHeight: calc(100vh - 200px) 가 모바일에서도 적용 →
좌·우 박스가 각각 거의 풀높이 차지
- 박스 내부의 overflow-auto 가 페이지 스크롤을 가로채 박스 안만 스크롤됨
수정:
- minHeight 인라인 스타일 → lg:min-h-[calc(100vh-200px)] 로 lg 이상에서만 적용
- 좌측 리스트 컨테이너: max-h-[60vh] lg:max-h-none 로 모바일에서 자연스러운 높이
- flex-1 overflow-auto → flex-1 lg:overflow-auto (모바일은 페이지 스크롤로 통일)
- 동일 패턴을 매입발주(/m/admin/procurements) + 입고처리(/m/admin/inbounds) 에도 적용
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[출고요청 화면 개선 — /m/orders/new]
- 카드에 [수량 입력 + 담기] 한 번에. 엔터 또는 버튼 클릭 시 그 수량만큼 카트에 추가
- 이미 담은 품목은 카드 안에 [- 1 +] 컨트롤 + [×] 빼기 버튼이 즉시 노출
· 카트 수량 그 자리에서 직접 수정. 카드 외 카트 펼치기 불필요
- 담은 품목 카드는 emerald 테두리 + 우상단에 "담은 N" 배지로 강조
[보기 모드 토글]
- 검색바 우측에 [카드 / 리스트] 토글
- 카드: 기존 그리드 (이미지 위주, 시각적)
- 리스트: 표 형태 (품목 많을 때 한눈에) — 행마다 동일 [수량+담기] 컨트롤
[관리자 거래명세표 라인 sync 버그 fix]
- /m/admin/orders 에서 [+택배/+용차] 클릭 시 합계만 올라가고 인풋 표시값이 안 바뀌던 문제
- ExtraRow key 를 `OBJID-QTY-UNIT_PRICE-LABEL` 로 변경해 line 변경 시 컴포넌트 강제 재마운트
- useState 초기값이 새 line 값으로 확실히 반영됨
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
증상: 모바일로 로그인 시 사이드바가 콘텐츠를 덮어 사용 불가능.
원인: 사이드바가 모든 폭에서 항상 정상 폭으로 자리잡음.
[레이아웃]
- 사이드바를 모바일에서 fixed + translate-x-full 로 화면 밖에 두고,
mobileOpen=true 시 translate-x-0 슬라이드 인 (200ms transition)
- 모바일 오버레이 배경 클릭 시 닫기
- lg 이상에서는 기존대로 좌측 고정
[헤더]
- 모바일에서만 햄버거(≡) 버튼 노출 → setMobileOpen(true)
- 사용자명 모바일 width 줄이고 부서명 숨김 (110px → sm 이상 200px)
[사이드바]
- 헤더 우측에 모바일 전용 X 버튼 추가 (lg:hidden)
- 데스크탑 햄버거 토글은 hidden lg:flex 로 분리
- handleSubMenuClick 에서 setMobileOpen(false) 호출 → 메뉴 선택 시 자동 닫힘
[스토어]
- mobileOpen 상태 + setMobileOpen 액션 추가
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>