o2o-negosium-original/frontend/src/features/chat/components/menu/NegoStep.tsx

78 lines
2.9 KiB
TypeScript

import { Check, ChevronDown } from 'lucide-react'
import { cn } from '@/lib'
import { useChatStore } from '@/features/chat/stores/useChatStore'
import { STEPS } from '@/features/chat/lib/negoSteps'
interface Props {
isOpen: boolean
setIsOpen: (isOpen: boolean) => void
}
export function NegoStep({ isOpen, setIsOpen }: Props) {
const chats = useChatStore((s) => s.messages)
const currentStep = chats[chats.length - 1]?.display_step || '서비스안내'
const currentIndex = Math.max(
0,
STEPS.findIndex((s) => s.name === currentStep),
)
return (
<section className="w-full">
<button
type="button"
aria-expanded={isOpen}
onClick={() => setIsOpen(!isOpen)}
className="flex w-full items-center justify-between border-b border-border pb-2"
>
<span className="text-[11px] font-bold tracking-wide text-neutral-60"></span>
<ChevronDown
size={16}
className={cn('text-neutral-50 transition-transform duration-300', !isOpen && '-rotate-90')}
/>
</button>
{isOpen && (
<div className="animate-fade-in pt-4">
<div className="relative">
{/* 세로 레일 */}
<span className="absolute left-[9px] top-3 bottom-3 w-0.5 bg-neutral-20" />
{STEPS.map((step, i) => {
const done = i < currentIndex
const current = i === currentIndex
return (
<div key={step.name} className="relative flex items-start gap-3 py-1.5">
<div
className={cn(
'z-10 mt-0.5 flex size-5 shrink-0 items-center justify-center rounded-full text-[10px] font-bold transition-all',
done && 'bg-success text-white',
current && 'scale-110 bg-brand-600 text-white ring-4 ring-brand-light',
!done && !current && 'border border-border bg-white text-neutral-50',
)}
>
{done ? <Check className="size-3" strokeWidth={3} /> : i + 1}
</div>
<div className="min-w-0">
<p
className={cn(
'text-xs leading-tight',
current && 'font-extrabold text-brand-600',
done && 'font-semibold text-success',
!done && !current && 'font-medium text-neutral-80',
)}
>
{step.name}
</p>
<p className={cn('mt-0.5 text-[10px] leading-snug', current ? 'text-brand-600/80' : 'text-neutral-50')}>
{step.desc}
</p>
</div>
</div>
)
})}
</div>
</div>
)}
</section>
)
}