Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -508,7 +508,7 @@ export function OrderRegistration({
|
||||
// 폼 콘텐츠 렌더링
|
||||
const renderFormContent = useCallback(
|
||||
() => (
|
||||
<div className="space-y-6 max-w-4xl">
|
||||
<div className="space-y-6">
|
||||
{/* Validation 에러 Alert */}
|
||||
{Object.keys(fieldErrors).length > 0 && (
|
||||
<Alert className="bg-red-50 border-red-200">
|
||||
|
||||
@@ -296,6 +296,7 @@ export function IntegratedListTemplateV2<T = any>({
|
||||
const [accumulatedMobileData, setAccumulatedMobileData] = useState<T[]>([]);
|
||||
const [lastAccumulatedPage, setLastAccumulatedPage] = useState(0);
|
||||
const mobileScrollSentinelRef = useRef<HTMLDivElement>(null);
|
||||
const mobileCardAreaRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// 클라이언트 사이드 인피니티용 (allData가 있는 경우)
|
||||
const [clientDisplayCount, setClientDisplayCount] = useState(mobileDisplayCount || 20);
|
||||
@@ -404,6 +405,45 @@ export function IntegratedListTemplateV2<T = any>({
|
||||
return () => observer.disconnect();
|
||||
}, [isServerSidePagination, allData, clientDisplayCount, enableMobileInfinityScroll, isMobileLoading, pagination.currentPage, pagination.totalPages, handleLoadMoreClient, handleLoadMoreMobile]);
|
||||
|
||||
// ===== 모바일 카드 영역 내부 스크롤 컨테인먼트 =====
|
||||
// 카드 영역이 뷰포트 남은 높이만큼만 차지하고, 내부에서만 스크롤되도록 설정
|
||||
// → 헤더/검색/탭은 항상 보이고, 카드만 스크롤
|
||||
useEffect(() => {
|
||||
const el = mobileCardAreaRef.current;
|
||||
if (!el) return;
|
||||
|
||||
const applyScrollContainment = () => {
|
||||
// xl(1280px) 이상은 데스크톱 → 테이블+페이지네이션 사용, 컨테인먼트 해제
|
||||
if (window.innerWidth >= 1280) {
|
||||
el.style.maxHeight = '';
|
||||
el.style.overflowY = '';
|
||||
el.style.overscrollBehavior = '';
|
||||
return;
|
||||
}
|
||||
|
||||
const rect = el.getBoundingClientRect();
|
||||
const available = window.innerHeight - rect.top - 16; // 16px 하단 여유
|
||||
|
||||
if (available > 200) {
|
||||
el.style.maxHeight = `${available}px`;
|
||||
el.style.overflowY = 'auto';
|
||||
el.style.overscrollBehavior = 'contain'; // 스크롤 누수 방지
|
||||
}
|
||||
};
|
||||
|
||||
// 페이지 스크롤을 최상단으로 리셋 후 정확한 위치 측정
|
||||
window.scrollTo(0, 0);
|
||||
el.scrollTop = 0;
|
||||
|
||||
const raf = requestAnimationFrame(applyScrollContainment);
|
||||
window.addEventListener('resize', applyScrollContainment);
|
||||
|
||||
return () => {
|
||||
cancelAnimationFrame(raf);
|
||||
window.removeEventListener('resize', applyScrollContainment);
|
||||
};
|
||||
}, [activeTab, isLoading]);
|
||||
|
||||
const startIndex = (pagination.currentPage - 1) * pagination.itemsPerPage;
|
||||
const allSelected = selectedItems.size === data.length && data.length > 0;
|
||||
|
||||
@@ -773,7 +813,7 @@ export function IntegratedListTemplateV2<T = any>({
|
||||
)}
|
||||
|
||||
{/* 모바일/태블릿/소형 노트북 (~1279px) 카드 뷰 */}
|
||||
<div className="xl:hidden space-y-4 md:space-y-0 md:grid md:grid-cols-2 md:gap-4 lg:grid-cols-3">
|
||||
<div ref={mobileCardAreaRef} className="xl:hidden space-y-4 md:space-y-0 md:grid md:grid-cols-2 md:gap-4 lg:grid-cols-3">
|
||||
{isLoading ? (
|
||||
<div className="col-span-full">
|
||||
<MobileCardGridSkeleton count={6} showCheckbox={showCheckbox} />
|
||||
|
||||
Reference in New Issue
Block a user