- 협상대화: 사용 카드 번호/멘트(Slate 서식본)/와일드 조건·메모 표시, SlateRenderer
밑줄·헥스색·{변수} 치환 보정, 말풍선 우측정렬·발신자 아바타 제거
- 견적상세 헤더: DB 컬럼명 라벨 제거, 견적정보/(진행상태+세팅)/상품(이미지) 2열 재배치,
협상카드 탭에 사용 카드 수 표시
- DataTable 행 패딩 축소, 협력사명 아바타 제거, 카드관리 본인 카드 안내문
- orval 재생성(QuotationCardData 신규 필드)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
36 lines
1.5 KiB
TypeScript
36 lines
1.5 KiB
TypeScript
import { useSearchParams } from 'react-router';
|
|
|
|
// 시트/드로어/모달 같은 "오버레이" 열림 상태를 쿼리스트링으로 표현하는 단일 출처.
|
|
// 로컬 useState 대신 URL 에 담아 딥링크·뒤로가기·새로고침을 지원한다.
|
|
// 같은 그룹(keys) 안에서는 한 번에 하나만 연다(상호배타: 열 때 나머지 키 제거).
|
|
//
|
|
// const overlay = useOverlayParams(['edit', 'new', 'modal']);
|
|
// overlay.get('edit') // ?edit=<id> 의 값(없으면 null) — 값 있는 오버레이
|
|
// overlay.has('new') // ?new 존재 여부 — 플래그 오버레이
|
|
// overlay.open('edit', id) // ?edit=<id> (다른 오버레이 키는 지움)
|
|
// overlay.open('new') // ?new (값 생략 시 '1')
|
|
// overlay.close() // 그룹 내 모든 오버레이 키 제거
|
|
export function useOverlayParams<K extends string>(keys: readonly K[]) {
|
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
|
|
const get = (key: K) => searchParams.get(key);
|
|
const has = (key: K) => searchParams.has(key);
|
|
|
|
const open = (key: K, value = '1') =>
|
|
setSearchParams((prev) => {
|
|
const next = new URLSearchParams(prev);
|
|
keys.forEach((k) => next.delete(k));
|
|
next.set(key, value);
|
|
return next;
|
|
});
|
|
|
|
const close = () =>
|
|
setSearchParams((prev) => {
|
|
const next = new URLSearchParams(prev);
|
|
keys.forEach((k) => next.delete(k));
|
|
return next;
|
|
});
|
|
|
|
return { get, has, open, close };
|
|
}
|