o2o-negosium-original/frontend/src/features/chat/components/MobileDrawer.tsx
Mina Choi db07a60cfa [fix] negosium·negodata·landing: 채팅 진입·부가정보 저장 오류 수정, 모바일 여백·스크롤·노치 대응
- 채팅 링크로 바로 진입하면 세션이 협상생성(1)에 머물러 오프닝 메시지가 seed 되지 않던 문제:
  chat init/messages 에서 participate 와 동일하게 협상중(2)으로 전이(마감 견적·마감시간 초과는 제외)
- 부가정보 저장이 1301 로 실패하던 문제: '협상완료' 요약은 chat_end=false 라 세션이 아직 협상중이므로,
  마지막 말풍선이 summaryRSP/CM 이면 협상중 세션도 저장 허용
- 채팅 언마운트 시 messages 캐시도 제거 — staleTime:Infinity 라 빈 목록이 남아 재진입해도 빈 화면이던 문제
- 채팅 스크롤을 컨테이너 기준 scrollTo 로 변경(rAF 후 실행) — 요약·폼이 뒤늦게 레이아웃되면 중간에 멈추던 문제
- 모바일 채팅 상단 여백 제거(pt-[64px] 는 우측 협상절차 카드가 있는 lg 이상만)
- 노치 대응: viewport-fit=cover + safe-t/b/x 유틸 신설, 헤더·하단 액션 덱·드로어·랜딩 헤더에 적용, h-screen→100dvh
2026-07-23 12:50:40 +09:00

51 lines
1.8 KiB
TypeScript

import { type ReactNode, useEffect } from 'react'
import { createPortal } from 'react-dom'
import { X } from 'lucide-react'
import { cn } from '@/lib'
interface MobileDrawerProps {
open: boolean
onClose: () => void
side?: 'left' | 'right'
title: string
children: ReactNode
}
// 모바일 전용 슬라이드 드로어(lg 미만). 데스크톱에선 절대 노출되지 않도록 lg:hidden 을 강제한다.
export function MobileDrawer({ open, onClose, side = 'left', title, children }: MobileDrawerProps) {
useEffect(() => {
if (!open) return
const onKey = (e: KeyboardEvent) => e.key === 'Escape' && onClose()
window.addEventListener('keydown', onKey)
return () => window.removeEventListener('keydown', onKey)
}, [open, onClose])
if (!open) return null
return createPortal(
<div className="fixed inset-0 z-[60] lg:hidden">
<div className="absolute inset-0 bg-black/50 animate-fade-in" onClick={onClose} />
<div
className={cn(
'absolute top-0 bottom-0 flex w-[88%] max-w-[360px] flex-col bg-white shadow-xl',
side === 'left' ? 'left-0' : 'right-0',
)}
>
<div className="flex h-14 box-content safe-t shrink-0 items-center justify-between border-b border-border px-5">
<span className="text-base font-bold text-neutral-90">{title}</span>
<button
type="button"
onClick={onClose}
aria-label="닫기"
className="flex size-8 items-center justify-center rounded-full text-neutral-60 hover:bg-neutral-10"
>
<X className="size-4" />
</button>
</div>
<div className="flex min-h-0 flex-1 flex-col overflow-y-auto safe-b">{children}</div>
</div>
</div>,
document.body,
)
}