o2o-negosium-original/frontend/src/layouts/MainLayout.tsx
민헌 482c8ed97c feat(chat): 반응형 레이아웃(~1024px) + 리드타임 "일" 표시 + 완료세션 인디케이터 숨김
- 반응형: 최소 폭 1350→1024px, max-[1350px]/max-[1180px] 2단계 축소
  - 사이드바 350→310→280, 우측 메뉴 360→320→280, 채팅 거터 140/126→80/72→48/40 (헤더 패딩 동기)
  - 가격·할인율 입력 min-w 480→420→320, 가운데 버튼 패딩·최소폭 축소, 상품목록 버튼 1180px 미만 아이콘만
  - 상품 이미지 220→200, 사이드바 정보 행 값 영역 고정 150px → flex-1
- 리드타임: formatLeadTime 헬퍼 신설 — 좌측 상품정보·협상 결과 요약 카드에 "일" 접미 표시
- 인디케이터: init 의 session_status 를 스토어에 적재, 협상중(IN_PROGRESS) 세션에서만 표시
- 사이드바 정보 영역 의미 없는 가로 스크롤 제거 (shrink 금지 컬럼 + overflow-x 자동 계산이 원인)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 16:37:18 +09:00

75 lines
2.1 KiB
TypeScript

import { type ReactNode } from 'react'
import { Logo } from '@/components'
import { cn } from '@/lib'
// 좌측 폭: list=반응형 비율 / chat=고정폭 단계 축소
const SIDEBAR_WIDTH = {
list:
'w-[20%] max-w-[320px] ' +
'max-[1520px]:w-[23%] max-[1410px]:w-[25%] ' +
'max-[1180px]:w-[27%] max-[1024px]:w-[29%] max-[960px]:w-[33%]',
chat: 'w-[350px] max-[1350px]:w-[310px] max-[1180px]:w-[280px]',
} as const
const styles = {
root: 'flex w-full min-h-screen max-h-screen bg-background',
scrollX: 'flex w-full min-h-screen max-h-screen overflow-x-auto overflow-y-hidden',
scrollXInner: 'flex w-full min-h-screen max-h-screen min-w-[1024px] bg-background',
sidebar: 'flex flex-col h-screen pt-2 bg-background',
logoHeader:
'flex w-full h-[56px] pl-[32px] pr-[24px] py-[8px] items-center justify-between shrink-0',
main: 'flex flex-1 flex-col h-screen overflow-hidden pt-2 pr-2 pb-2 pl-0',
// 다크 헤더와 합쳐져 카드 형태
content: 'flex flex-1 flex-col min-h-0 w-full overflow-hidden rounded-b-[8px] bg-surface',
} as const
export type SidebarWidth = keyof typeof SIDEBAR_WIDTH
export interface MainLayoutProps {
sidebarWidth?: SidebarWidth
/** 루트 가로 스크롤 + 최소폭 (chat 전용) */
scrollX?: boolean
logoAction?: ReactNode
sidebar: ReactNode
header: ReactNode
children?: ReactNode
}
export function MainLayout({
sidebarWidth = 'list',
scrollX = false,
logoAction,
sidebar,
header,
children,
}: MainLayoutProps) {
const panes = (
<>
<aside className={cn(styles.sidebar, SIDEBAR_WIDTH[sidebarWidth])}>
<div className={styles.logoHeader}>
<Logo size="sm" />
{logoAction}
</div>
{sidebar}
</aside>
<main className={styles.main}>
{header}
<div className={styles.content}>{children}</div>
</main>
</>
)
if (!scrollX) {
return <div className={styles.root}>{panes}</div>
}
return (
<div className={styles.scrollX}>
<div className={styles.scrollXInner}>{panes}</div>
</div>
)
}
export default MainLayout