[feat] landing: 데모 영상 3종 실화면 재촬영(라이브 협상·견적생성·협상결과, 줌인 연출) + 도입문의·데모요청 폼 mailto 임시연결

This commit is contained in:
Mina Choi 2026-08-12 17:04:46 +09:00
parent 1a859b198c
commit 8112394aef
13 changed files with 33 additions and 27 deletions

View File

@ -175,9 +175,9 @@ export function Contact() {
<div className="w-12 h-12 bg-primary text-white rounded-full flex items-center justify-center mx-auto mb-6">
<Check className="w-6 h-6" strokeWidth={2.5} />
</div>
<h3 className="text-[24px] font-semibold tracking-[-0.02em] text-ink mb-3"> </h3>
<h3 className="text-[24px] font-semibold tracking-[-0.02em] text-ink mb-3"> </h3>
<p className="text-ink-soft text-[15px] leading-[1.6] max-w-md mx-auto mb-8">
{formData.contactName} .
. , {formData.contactName} .
</p>
<Button
type="button"

View File

@ -238,11 +238,11 @@ const DEMO_TABS: DemoTab[] = [
],
checks: ["협력사별 1:1 비대면 협상 포털", "같은 기준으로 응대해 관계 부담 없음"],
mockup: "phone",
/* mp4 1.7MB GIF(390x780) .
mp4 786K, 540x1080 .
( . .) */
/* ( UI) . 390x780
( 4)(18,480 ), 1.5. gif JS ( 228). */
gif: "/gifs/negotiation.gif",
video: "/gifs/negotiation.mp4",
poster: "/gifs/negotiation.jpg",
gifAlt: "협력사 포털 모바일 협상 화면",
fallback: {
icon: Smartphone,

View File

@ -125,12 +125,10 @@ export function DemoRequestModal({ open, onClose }: { open: boolean; onClose: ()
<Check className="w-6 h-6" />
</div>
<Typography variant="cardTitle" as="h2" id={titleId} className="mb-3">
</Typography>
{/* "Demo " .
"일정을 잡아 연락드립니다" . */}
<Typography variant="small">
Demo를 .
. Demo를 .
</Typography>
</div>
) : (

View File

@ -1,16 +1,13 @@
/*
* .
*
* (api/lead.ts). ssr:false
* Vercel /api POST .
* , CORS .
*
* . 1.2
* "접수되었습니다" .
* ok .
* [] / mailto .
* '열릴' , UI "접수 완료"
* "메일 앱을 열었습니다 — 전송해 주세요" (fake success ). API/ .
*/
const ENDPOINT = "/api/lead"
// 리드 수신 주소 — 임시. 실제 영업 주소로 바꾸고, 이후 API 붙이면 mailto 자체를 교체할 것.
const LEAD_EMAIL = "o2odev@o2o.kr"
export type LeadSource = "demo-request" | "contact"
@ -36,15 +33,26 @@ export function isEmailLike(value: string) {
export async function submitLead(lead: Lead): Promise<LeadResult> {
if (!lead.name.trim() || !isEmailLike(lead.email)) return { ok: false, reason: "invalid" }
try {
const res = await fetch(ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(lead),
})
return res.ok ? { ok: true } : { ok: false, reason: "rejected" }
} catch {
// 로컬 dev(react-router dev)에는 /api 가 없어서 여기로 온다. 확인은 `vercel dev` 로.
return { ok: false, reason: "network" }
const label = lead.source === "demo-request" ? "데모 요청" : "도입 문의"
const body = [
`[${label}]`,
`회사명: ${lead.company || "-"}`,
`담당자: ${lead.name}`,
`이메일: ${lead.email}`,
`연락처: ${lead.phone || "-"}`,
`내용: ${lead.message || "-"}`,
].join("\n")
const href = `mailto:${LEAD_EMAIL}?subject=${encodeURIComponent(`[${label}] ${lead.company || lead.name}`)}&body=${encodeURIComponent(body)}`
// 방문자의 메일 앱을 연다 — 앵커 클릭이 location.href 할당보다 핸들러 발동이 확실하다.
// 실제 전송은 방문자가 하므로 성공을 단정하지 않는다(호출부 UI 는 안내 문구).
if (typeof document !== "undefined") {
const a = document.createElement("a")
a.href = href
a.style.display = "none"
document.body.appendChild(a)
a.click()
a.remove()
}
return { ok: true }
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 42 KiB