o2o-negosium-original/frontend/src/features/list/components/GuidePopup.tsx

93 lines
4.6 KiB
TypeScript

import { X } from 'lucide-react'
import { Modal } from '@/components'
import { cn, interactive } from '@/lib'
// 공급사 포털 목록 화면 이용안내. 상태(진행)·결과(마감)·재협상 3파트로 최근 추가된 용어를 설명한다.
// 헤더의 '이용안내' 버튼으로 여는 수동형 팝업. X·배경 클릭·ESC 로 닫는다.
export function GuidePopup({ onClose }: { onClose: () => void }) {
return (
<Modal onClose={onClose}>
<div className="m-4 flex max-h-[90vh] w-full max-w-[560px] flex-col overflow-y-auto rounded-2xl border border-border bg-white p-6 shadow-xl animate-scale-in sm:p-8">
<div className="mb-5 flex items-start justify-between gap-4">
<div>
<h2 className="text-lg font-extrabold text-neutral-90">이용안내</h2>
<p className="mt-1 text-[13px] text-neutral-60">협상 목록의 상태·결과·재협상을 안내합니다.</p>
</div>
<button
type="button"
aria-label="닫기"
onClick={onClose}
className={cn('flex size-9 shrink-0 items-center justify-center rounded-full bg-neutral-10 text-neutral-70 hover:bg-neutral-20', interactive)}
>
<X size={18} />
</button>
</div>
<div className="flex flex-col gap-6">
<Section title="진행 상태" desc="협상 세션이 지금 어느 단계인지 — 내가 무엇을 할지 알려줍니다.">
<Row badge="협상 대기" tone="wait" text="초청받은 협상. 입장해서 가격 협상을 시작하세요." />
<Row badge="협상 중" tone="prog" text="가격을 조율하는 중입니다. 이어서 진행하세요." />
<Row badge="협상 완료" tone="done" text="가격 제출을 마쳤습니다. 최종 결과는 견적 마감 후 아래 '결과'로 표시됩니다." />
<Row badge="협상 미참여" tone="none" text="기한 내 참여하지 않아 종료된 건입니다." />
<Row badge="협상 거절" tone="reject" text="내가 참여를 거절한 건입니다." />
</Section>
<Section title="협상 결과" desc="견적이 마감된 뒤 정해지는 낙찰 결과입니다. 마감 전에는 표시되지 않습니다.">
<Row badge="낙찰" tone="win" text="내가 낙찰되어 계약 대상이 된 건입니다." />
<Row badge="미낙찰" tone="lost" text="다른 공급사가 낙찰되어 이번 계약에서는 제외된 건입니다." />
<Row badge="결렬" tone="open" text="낙찰자 없이 마감된 건입니다. 조건이 바뀌었다면 재협상을 요청할 수 있습니다." />
</Section>
<Section title="재협상 요청" desc="결렬(낙찰자 미정 마감) 건에 한해 가능합니다.">
<p className="text-[13px] leading-relaxed text-neutral-70">
결렬 건의 <b className="font-bold text-neutral-90">재협상 요청</b> 버튼으로 사유·희망가를 담아 요청하면,
구매 담당자 검토 후 <b className="font-bold text-neutral-90">승인 시 다음 차수 협상</b>이 새로 열립니다.
요청 상태(심사 중·승인·반려)는 목록에서 확인할 수 있습니다.
</p>
</Section>
</div>
<button
type="button"
onClick={onClose}
className="mt-7 h-11 w-full rounded-xl bg-brand-600 text-sm font-bold text-white transition-colors hover:bg-brand-700"
>
확인했어요
</button>
</div>
</Modal>
)
}
function Section({ title, desc, children }: { title: string; desc: string; children: React.ReactNode }) {
return (
<section>
<h3 className="text-sm font-extrabold text-neutral-90">{title}</h3>
<p className="mb-3 mt-0.5 text-xs text-neutral-60">{desc}</p>
<div className="flex flex-col gap-2.5">{children}</div>
</section>
)
}
const TONE: Record<string, string> = {
wait: 'bg-brand-light text-brand-700',
prog: 'bg-[#FFF3E5] text-[#F5A623]',
done: 'bg-[#EAFDF3] text-success',
none: 'bg-neutral-20 text-neutral-60',
reject: 'bg-[#FFEBEB] text-[#FF4D4F]',
win: 'bg-[#EAFDF3] text-success',
lost: 'bg-neutral-20 text-neutral-60',
open: 'bg-[#FFF3E5] text-[#F5A623]',
}
function Row({ badge, tone, text }: { badge: string; tone: string; text: string }) {
return (
<div className="flex items-start gap-2.5">
<span className={cn('mt-0.5 inline-flex shrink-0 items-center rounded-full px-2.5 py-1 text-xs font-bold', TONE[tone])}>
{badge}
</span>
<p className="text-[13px] leading-relaxed text-neutral-70">{text}</p>
</div>
)
}