o2o-negosium-original/landing/app/components/sections/roi-simulator.tsx
Haewon Kam 55e3ab02aa [fix] landing: 섹션 세로 리듬 통일 — 간격을 SectionHeading 이 소유
디자인 시스템이 색·활자만 소유하고 간격은 각 섹션 파일에 흩어져 있어,
같은 관계에 값이 여러 개 생겼다. 스크롤할 때 섹션마다 호흡이 달라지던 원인.

  eyebrow → title      12/20px      → 16px
  title → description  16/20/32px   → 20px (display 티어 32px)
  머리 → 본문          48~96px 5종  → 56px / 80px(md)
  컨트롤 → 본문        56/64px      → 48px
  리드 → CTA           56/48px      → 48px

- SectionHeading 이 리듬을 소유하고 HEADING_GAP·CONTROL_GAP·CTA_GAP·
  DISPLAY_LEAD_GAP 를 노출. 섹션 파일에서 mb-24 같은 값을 직접 쓰지 않는다.
- negotiation-demo·final-cta 가 Section/SectionHeading 을 우회해 머리를 직접
  조판하고 있었다 — 아이브로우 간격이 이 둘만 20px 이던 원인. 프리미티브로 환원.
- SectionHeading 이 eyebrow 없이도 빈 span 을 렌더해 유령 여백이 생기던 버그 수정.
- descriptionClassName 의 text-[17px] 중복 선언 제거. lead 변형이 이미 갖고 있는
  모바일 축소 단계(text-[16px] sm:text-[17px])를 지우고 있었다.
- reinforcement: text-balance 가 쉼표를 넘어 끊던 헤드라인을 <br /> 로 명시.

reinforcement 만 gap="none" 인데, 머리가 그리드 셀 안이라 마진이 상쇄되지 않아
items-center 정렬을 밀기 때문. 간격은 그리드 래퍼가 진다.

검증: tsc --noEmit 통과, 프로덕션 빌드 통과. DOM 실측으로 375/868/1440px
전 구간에서 머리→본문·eyebrow→title·컨트롤→본문 값 일치 확인.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 16:22:24 +09:00

157 lines
6.9 KiB
TypeScript

import { useState } from "react"
import { ArrowRight, Clock, ShieldCheck } from "lucide-react"
import { RangeSlider } from "@/components/ui/range-slider"
import { Section } from "@/components/ui/section"
import { SectionHeading } from "@/components/ui/section-heading"
import { Typography } from "@/components/ui/typography"
/** 도입 ROI 시뮬레이터 — 예산·협력사 수 슬라이더로 예상 절감액을 즉시 계산. */
export function ROISimulator() {
// 연간 총 구매 예산(억 원)
const [budget, setBudget] = useState(50)
// 관리 중인 협력사 수
const [suppliers, setSuppliers] = useState(50)
// 보수적 절감율 2.8%~4.5% — 협력사가 많을수록 병렬 대안이 늘어 상향
const savingRate = Math.min(0.045, 0.028 + (suppliers / 300) * 0.015)
const estimatedSavingsValue = budget * savingRate
// 협력사당 왕복 흥정 수작업 절약분을 ~6.5시간으로 잡은 추산
const savedHours = Math.round(suppliers * 6.5)
return (
<Section id="benchmarks" width="lg" bordered className="border-b border-line">
<SectionHeading
align="center"
eyebrow="ROI Simulation"
title={
<>
negotium 도입 시 <br />
예상 절감액 확인하기
</>
}
description={
<>
아직 실제 도입 실증 사례가 없는 신규 카테고리여도 신뢰할 수 있습니다. <br />
연간 구매 예산과 공급사 수만 입력해 보수적인 시뮬레이션 성과를 즉시 시각화해 보세요.
</>
}
descriptionClassName="max-w-2xl"
/>
<div className="grid grid-cols-1 lg:grid-cols-12 gap-16 items-start">
{/* 좌: 입력 슬라이더 */}
<div className="lg:col-span-6 space-y-12">
<div className="space-y-4">
<div className="flex justify-between items-center">
<label className="text-[16px] font-bold text-ink">연간 총 구매 예산</label>
<span className="text-lg font-black text-primary font-mono">{formatCurrency(budget)}</span>
</div>
<Typography variant="caption">원자재, 부자재, 가공비, 운송비 등 협상에 연동할 총 연간 구매 규모입니다.</Typography>
<div className="pt-2">
<RangeSlider min={5} max={1000} step={5} value={budget} onChange={setBudget} />
<div className="flex justify-between text-[11px] text-ink-faint font-bold pt-2">
<span>5억 원</span>
<span>500억 원</span>
<span>1조 원</span>
</div>
</div>
</div>
<div className="space-y-4">
<div className="flex justify-between items-center">
<label className="text-[16px] font-bold text-ink">관리 중인 총 협력사 수</label>
<span className="text-lg font-black text-primary font-mono">{suppliers}개사</span>
</div>
<Typography variant="caption">에이전트가 동시에 1:1로 조율할 협력사 수입니다.</Typography>
<div className="pt-2">
<RangeSlider min={5} max={300} step={5} value={suppliers} onChange={setSuppliers} />
<div className="flex justify-between text-[11px] text-ink-faint font-bold pt-2">
<span>5개사</span>
<span>150개사</span>
<span>300개사</span>
</div>
</div>
</div>
<div className="flex gap-3 bg-surface p-5 rounded-card border border-line">
<ShieldCheck className="w-5 h-5 text-positive flex-shrink-0 mt-0.5" />
<Typography variant="caption" className="text-ink-soft">
최저가 스캔(LPS) 시세와 B2B 협상 데이터의 보수적 평균(3.1~4.2% 절감)을 적용한 추정치입니다.
실제 데이터로 검증해 보시려면 파일만 주시면 됩니다.
</Typography>
</div>
</div>
{/* 우: 결과 지표 */}
<div className="lg:col-span-6 lg:pl-10 space-y-12">
<div className="space-y-3">
<Typography variant="micro" className="text-primary block">
ESTIMATED ANNUAL SAVINGS
</Typography>
<h3 className="text-sm font-semibold text-ink-muted">매년 절감 가능한 구매 원가 (보수적 추산)</h3>
<div className="text-3xl sm:text-[44px] font-black text-primary font-mono tracking-tight leading-tight pt-1">
{formatSavings(estimatedSavingsValue)}
</div>
<Typography variant="caption" className="text-ink-soft font-medium pt-1">
그동안 손이 못 가던 꼬리 거래(Tail Spend)까지 동시에 협상합니다. 수동으로는 놓치던 구간입니다.
</Typography>
</div>
<div className="border-t border-line pt-8 space-y-3">
<div className="flex items-center gap-3">
<Clock className="w-5 h-5 text-ink-muted" />
<span className="text-xs font-bold text-ink-soft">
연간 실무 단축 시간: <b className="text-ink font-mono text-sm ml-1">{savedHours.toLocaleString()}시간</b>
</span>
</div>
<Typography variant="caption">
메일 전송, 유선 협의, 엑셀 취합에 쓰이던 시간이 링크 한 번과 에이전트 응대로
완전히 생략되어 고부가가치 전략 구매 기획에 전념할 수 있습니다.
</Typography>
</div>
<div className="border-t border-line pt-8 flex items-center justify-between">
<div>
<h4 className="text-xs font-bold text-ink">예상 도입 ROI 회수 기간</h4>
<p className="text-[11px] text-ink-muted font-semibold mt-1">도입 즉시 마진 확보 개시</p>
</div>
<a
href="#contact-section"
className="inline-flex items-center gap-2 text-xs font-bold text-primary hover:gap-3 transition-all"
>
<span>무상 맞춤 검증 신청하기</span>
<ArrowRight className="w-4 h-4" />
</a>
</div>
</div>
</div>
</Section>
)
}
/** 억 원 단위 → "50억 원" / "1조 200억 원" 표기 */
function formatCurrency(val: number) {
if (val >= 100) {
const b = Math.floor(val / 100)
const m = val % 100
return m > 0 ? `${b}조 ${m}00억 원` : `${b}조 원`
}
return `${val}억 원`
}
/** 억 원 단위 → "1억 5,500만 원" 표기 */
function formatSavings(val: number) {
const rawWon = val * 100000000
if (rawWon >= 100000000) {
const eonPart = Math.floor(rawWon / 100000000)
const manPart = Math.floor((rawWon % 100000000) / 10000)
if (manPart > 0) {
return `${eonPart}억 ${manPart.toLocaleString()}만 원`
}
return `${eonPart}억 원`
}
return `${Math.floor(rawWon / 10000).toLocaleString()}만 원`
}