You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
355 lines
14 KiB
355 lines
14 KiB
import useFadeIn from "../../hooks/useFadeIn"; |
|
import SubHero from "../../components/SubHero"; |
|
import { Fragment, useRef } from "react"; |
|
import { motion, useInView } from "framer-motion"; |
|
import { Search, Armchair, CalendarClock, Wallet, Ticket } from "lucide-react"; |
|
|
|
const ease = [0.22, 1, 0.36, 1]; |
|
|
|
function IbePage() { |
|
const basePath = import.meta.env.BASE_URL; |
|
const ref = useFadeIn(); |
|
const introRef = useRef(null); |
|
const introInView = useInView(introRef, { once: true, margin: "-60px" }); |
|
const channelRef = useRef(null); |
|
const channelInView = useInView(channelRef, { once: true, margin: "-60px" }); |
|
const bookingRef = useRef(null); |
|
const bookingInView = useInView(bookingRef, { once: true, margin: "-60px" }); |
|
|
|
const SOLUTION_NAV = [ |
|
{ label: "비행상황관리 시스템", to: "/solution/flight-control" }, |
|
{ label: "IBE", to: "/solution/ibe" }, |
|
]; |
|
|
|
return ( |
|
<article ref={ref}> |
|
<SubHero |
|
label="SOLUTION" |
|
title={ |
|
<> |
|
<em>IBE</em> |
|
</> |
|
} |
|
navItems={SOLUTION_NAV} |
|
/> |
|
|
|
<div className="sub-content"> |
|
<div className="inner-wrap"> |
|
{/* 개요 인트로 */} |
|
<section className="fc-intro" ref={introRef}> |
|
<div className="fc-intro__left"> |
|
<motion.span |
|
className="fc-eyebrow" |
|
initial={{ opacity: 0, y: 16 }} |
|
animate={introInView ? { opacity: 1, y: 0 } : {}} |
|
transition={{ duration: 0.6, ease }} |
|
> |
|
Overview |
|
</motion.span> |
|
<motion.h2 |
|
className="fc-intro__title" |
|
initial={{ opacity: 0, y: 24 }} |
|
animate={introInView ? { opacity: 1, y: 0 } : {}} |
|
transition={{ duration: 0.7, ease, delay: 0.1 }} |
|
> |
|
항공 예약의 모든 과정을 |
|
<br /> |
|
하나로 연결하는 통합 플랫폼 |
|
</motion.h2> |
|
<motion.p |
|
className="fc-intro__desc" |
|
initial={{ opacity: 0, y: 16 }} |
|
animate={introInView ? { opacity: 1, y: 0 } : {}} |
|
transition={{ duration: 0.6, ease, delay: 0.2 }} |
|
> |
|
IBE(Internet Booking Engine)는 항공권 검색부터 예약, 결제, |
|
<br /> |
|
발권까지 모든 프로세스를 지원하는 차세대 예약 엔진 입니다. |
|
<br /> |
|
다양한 채널과 시스템을 유연하게 연동하여 최적의 예약 경험을 |
|
제공합니다. |
|
</motion.p> |
|
<motion.div |
|
className="fc-intro__icons" |
|
initial={{ opacity: 0, y: 16 }} |
|
animate={introInView ? { opacity: 1, y: 0 } : {}} |
|
transition={{ duration: 0.6, ease, delay: 0.3 }} |
|
> |
|
{[ |
|
{ img: "ibe_intro_icon1.png", label: "다중 채널 연동" }, |
|
{ img: "ibe_intro_icon2.png", label: "실시간 예약/재고" }, |
|
{ img: "ibe_intro_icon3.png", label: "안정성과 확장성" }, |
|
{ img: "ibe_intro_icon4.png", label: "데이터 기반 운영" }, |
|
].map((item, i) => ( |
|
<div key={i} className="fc-intro__icon-item"> |
|
<img |
|
src={`${basePath}images/${item.img}`} |
|
alt={item.label} |
|
/> |
|
<span>{item.label}</span> |
|
</div> |
|
))} |
|
</motion.div> |
|
</div> |
|
<motion.div |
|
className="fc-intro__right" |
|
initial={{ opacity: 0, x: 40 }} |
|
animate={introInView ? { opacity: 1, x: 0 } : {}} |
|
transition={{ duration: 0.9, ease, delay: 0.15 }} |
|
> |
|
<img |
|
src={`${basePath}images/ibe_computer.png`} |
|
alt="IBE" |
|
className="fc-intro__monitor" |
|
/> |
|
</motion.div> |
|
</section> |
|
|
|
{/* BOOKING PROCESS */} |
|
<section className="ibe-booking-section" ref={bookingRef}> |
|
<motion.span |
|
className="fc-eyebrow" |
|
initial={{ opacity: 0, y: 16 }} |
|
animate={bookingInView ? { opacity: 1, y: 0 } : {}} |
|
transition={{ duration: 0.6, ease }} |
|
> |
|
Booking Process |
|
</motion.span> |
|
<motion.h2 |
|
className="ibe-booking__title" |
|
initial={{ opacity: 0, y: 24 }} |
|
animate={bookingInView ? { opacity: 1, y: 0 } : {}} |
|
transition={{ duration: 0.7, ease, delay: 0.1 }} |
|
> |
|
직관적이고 간편한 예약 프로세스 |
|
</motion.h2> |
|
|
|
<div className="ibe-booking__flow"> |
|
<svg width="0" height="0" style={{ position: "absolute" }}> |
|
<defs> |
|
<linearGradient |
|
id="ibe-icon-grad" |
|
x1="0%" |
|
y1="0%" |
|
x2="100%" |
|
y2="100%" |
|
> |
|
<stop offset="0%" stopColor="#60a5fa" /> |
|
<stop offset="100%" stopColor="#f472b6" /> |
|
</linearGradient> |
|
</defs> |
|
</svg> |
|
{[ |
|
{ |
|
num: "01", |
|
icon: Search, |
|
label: "검색", |
|
desc: "출발지, 도착지, 일정,\n탑승객 정보를 입력하여\n최적의 항공편 검색", |
|
}, |
|
{ |
|
num: "02", |
|
icon: Armchair, |
|
label: "선택", |
|
desc: "운임, 스케줄, 좌석 등\n다양한 옵션을 비교하고\n원하는 항공편 선택", |
|
}, |
|
{ |
|
num: "03", |
|
icon: CalendarClock, |
|
label: "예약", |
|
desc: "승객 정보 입력 및\n부가 서비스 선택을 통해\n예약을 진행", |
|
}, |
|
{ |
|
num: "04", |
|
icon: Wallet, |
|
label: "결제", |
|
desc: "다양한 결제 수단을 지원하여\n안전하고 간편하게\n결제 진행", |
|
}, |
|
{ |
|
num: "05", |
|
icon: Ticket, |
|
label: "발권", |
|
desc: "E-Ticket 발행 후\n예약 정보를 확인하고\n예약 완료", |
|
}, |
|
].map((item, i) => { |
|
const Icon = item.icon; |
|
return ( |
|
<Fragment key={i}> |
|
<motion.div |
|
className="ibe-booking__item" |
|
initial={{ opacity: 0, y: 24 }} |
|
animate={bookingInView ? { opacity: 1, y: 0 } : {}} |
|
transition={{ |
|
duration: 0.6, |
|
ease, |
|
delay: 0.2 + i * 0.1, |
|
}} |
|
> |
|
<div className="ibe-booking__circle"> |
|
<Icon |
|
size={32} |
|
strokeWidth={1.5} |
|
stroke="url(#ibe-icon-grad)" |
|
/> |
|
</div> |
|
<span className="ibe-booking__num">{item.num}</span> |
|
<span className="ibe-booking__label">{item.label}</span> |
|
<p className="ibe-booking__desc"> |
|
{item.desc.split("\n").map((line, j) => ( |
|
<span key={j}> |
|
{line} |
|
<br /> |
|
</span> |
|
))} |
|
</p> |
|
</motion.div> |
|
{i < 4 && ( |
|
<div |
|
className="ibe-booking__connector" |
|
style={{ "--delay": `${i * 0.4}s` }} |
|
> |
|
<div className="ibe-booking__line-bg" /> |
|
<div className="ibe-booking__line-flow" /> |
|
</div> |
|
)} |
|
</Fragment> |
|
); |
|
})} |
|
</div> |
|
</section> |
|
|
|
{/* MULTI CHANNEL INTEGRATION */} |
|
<section className="ibe-channel-section" ref={channelRef}> |
|
<motion.span |
|
className="fc-eyebrow" |
|
initial={{ opacity: 0, y: 16 }} |
|
animate={channelInView ? { opacity: 1, y: 0 } : {}} |
|
transition={{ duration: 0.6, ease }} |
|
> |
|
Multi Channel Integration |
|
</motion.span> |
|
<motion.h2 |
|
className="ibe-channel__title" |
|
initial={{ opacity: 0, y: 24 }} |
|
animate={channelInView ? { opacity: 1, y: 0 } : {}} |
|
transition={{ duration: 0.7, ease, delay: 0.1 }} |
|
> |
|
다양한 시스템과의 유연한 연동 |
|
</motion.h2> |
|
<motion.p |
|
className="ibe-channel__desc" |
|
initial={{ opacity: 0, y: 16 }} |
|
animate={channelInView ? { opacity: 1, y: 0 } : {}} |
|
transition={{ duration: 0.6, ease, delay: 0.2 }} |
|
> |
|
항공사 GDS, 호텔, 결제, 보험 등 다양한 외부 시스템과 API 기반 |
|
연동을 통해 확장성 높은 예약 환경을 제공합니다. |
|
</motion.p> |
|
|
|
<motion.div |
|
className="ibe-channel__diagram" |
|
initial={{ opacity: 0, y: 40 }} |
|
animate={channelInView ? { opacity: 1, y: 0 } : {}} |
|
transition={{ duration: 0.8, ease, delay: 0.3 }} |
|
> |
|
<svg |
|
className="ibe-channel__svg" |
|
viewBox="0 0 1540 430" |
|
preserveAspectRatio="none" |
|
> |
|
<path |
|
className="ibe-channel__path" |
|
d="M350 95 C520 95 560 185 710 185" |
|
/> |
|
<path |
|
className="ibe-channel__path" |
|
d="M350 215 C520 215 560 215 710 215" |
|
/> |
|
<path |
|
className="ibe-channel__path" |
|
d="M350 335 C520 335 560 245 710 245" |
|
/> |
|
<path |
|
className="ibe-channel__path" |
|
d="M830 185 C980 185 1020 95 1190 95" |
|
/> |
|
<path |
|
className="ibe-channel__path" |
|
d="M830 215 C980 215 1020 215 1190 215" |
|
/> |
|
<path |
|
className="ibe-channel__path" |
|
d="M830 245 C980 245 1020 335 1190 335" |
|
/> |
|
<circle cx="350" cy="95" r="4" className="ibe-channel__dot" /> |
|
<circle cx="350" cy="215" r="4" className="ibe-channel__dot" /> |
|
<circle cx="350" cy="335" r="4" className="ibe-channel__dot" /> |
|
<circle cx="1190" cy="95" r="4" className="ibe-channel__dot" /> |
|
<circle cx="1190" cy="215" r="4" className="ibe-channel__dot" /> |
|
<circle cx="1190" cy="335" r="4" className="ibe-channel__dot" /> |
|
</svg> |
|
|
|
<div className="ibe-channel__cols-wrap"> |
|
<div className="ibe-channel__col ibe-channel__col--left"> |
|
{[ |
|
{ img: "ibe_pal_icon1.png", label: "항공사" }, |
|
{ img: "ibe_pal_icon2.png", label: "GDS" }, |
|
{ img: "ibe_pal_icon3.png", label: "호텔" }, |
|
].map((item, i) => ( |
|
<motion.div |
|
key={i} |
|
className="ibe-channel__card" |
|
initial={{ opacity: 0, x: -24 }} |
|
animate={channelInView ? { opacity: 1, x: 0 } : {}} |
|
transition={{ duration: 0.6, ease, delay: 0.4 + i * 0.1 }} |
|
> |
|
<img |
|
src={`${basePath}images/${item.img}`} |
|
alt={item.label} |
|
/> |
|
<span>{item.label}</span> |
|
</motion.div> |
|
))} |
|
</div> |
|
|
|
<div className="ibe-channel__center"> |
|
<motion.img |
|
src={`${basePath}images/ibe_pal_item.png`} |
|
alt="PAL IBE" |
|
className="ibe-channel__center-img" |
|
initial={{ opacity: 0, scale: 0.8 }} |
|
animate={channelInView ? { opacity: 1, scale: 1 } : {}} |
|
transition={{ duration: 0.8, ease, delay: 0.5 }} |
|
/> |
|
</div> |
|
|
|
<div className="ibe-channel__col ibe-channel__col--right"> |
|
{[ |
|
{ img: "ibe_pal_icon4.png", label: "결제 시스템" }, |
|
{ img: "ibe_pal_icon5.png", label: "여행사/OTA" }, |
|
{ img: "ibe_pal_icon6.png", label: "보험" }, |
|
].map((item, i) => ( |
|
<motion.div |
|
key={i} |
|
className="ibe-channel__card" |
|
initial={{ opacity: 0, x: 24 }} |
|
animate={channelInView ? { opacity: 1, x: 0 } : {}} |
|
transition={{ duration: 0.6, ease, delay: 0.4 + i * 0.1 }} |
|
> |
|
<img |
|
src={`${basePath}images/${item.img}`} |
|
alt={item.label} |
|
/> |
|
<span>{item.label}</span> |
|
</motion.div> |
|
))} |
|
</div> |
|
</div> |
|
</motion.div> |
|
</section> |
|
</div> |
|
</div> |
|
</article> |
|
); |
|
} |
|
|
|
export default IbePage;
|
|
|