Files
hanzo.ai/components/payments/PaymentsSuite.tsx

135 lines
5.1 KiB
TypeScript

'use client'
import React from "react";
import { motion } from "@/components/motion";
import { CreditCard, Calendar, Send } from "lucide-react";
import { Band, Disc, Head, INK, Words } from '@/components/marketing/band'
import { Body, Bullet, Heading, Tile } from './kit'
import { Box, View, XStack, YStack } from '@hanzo/ui'
import { Grid } from '@hanzo/ui/grid'
import { Lattice, Title } from '@hanzo/ui/marketing'
const suiteItems = [
{
icon: CreditCard,
title: "Smart routing",
description: "Choose the processor per payment on cost, success rate or latency. The rule lives here, so tuning it is a config change rather than a deploy."
},
{
icon: Calendar,
title: "Cascading retries",
description: "A soft decline is often a fact about one processor, not about the card. Failed attempts fall through to a backup automatically, and the customer sees one outcome."
},
{
icon: Send,
title: "Normalized webhooks",
description: "Every processor announces a settlement differently. You subscribe to one event shape and keep it when you add or drop a provider."
},
]
/** The panel's own wash, and the decorative grid it fades out. */
const PANEL = 'linear-gradient(to bottom right, color-mix(in oklab, var(--neutral-900) 50%, transparent), var(--white-10))'
/** The panel's lattice dissolves upward, so it reads under the chart and not the heading. */
const FADE_IN = 'linear-gradient(to bottom, transparent, black)'
/** One bar of the seven-day chart. */
const BAR = { width: 24, borderTopLeftRadius: 4, borderTopRightRadius: 4, background: 'linear-gradient(to top, var(--pure-white), var(--white-10))' } as const
const PaymentsSuite = () => {
return (
<Band rule={false} pad="$11" measure={1152} ground={INK}>
<Head
title="What sits behind the one integration"
lede="Each processor has its own API, its own idea of an error, and its own webhook format. This normalises all three, so your code sees one shape whichever of them took the payment."
/>
<View
render={<motion.div initial={{ opacity: 0 }} whileInView={{ opacity: 1 }} viewport={{ once: true }} transition={{ duration: 0.5 }} />}
display="block"
mb={64}
>
<Title render="h3" quiet mb={32} text="center">
Unified Payments Suite
</Title>
<Grid columns={{ min: 300, max: 3 }} gap={24}>
{suiteItems.map((item, index) => (
<XStack
key={item.title}
render={<motion.div initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} transition={{ duration: 0.5, delay: index * 0.1 }} />}
>
<Tile flex={1}>
<Disc>
<item.icon size={24} />
</Disc>
<Heading render="h4">{item.title}</Heading>
<Body>{item.description}</Body>
</Tile>
</XStack>
))}
</Grid>
</View>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
>
<Box
position="relative"
overflow="hidden"
rounded="var(--radius-xl)"
borderWidth={1}
borderColor="var(--neutral-800)"
p="$6"
background={PANEL}
>
<Lattice position="absolute" inset={0} maskImage={FADE_IN} />
<YStack
position="relative"
z="var(--z-raised)"
gap="$6"
items="center"
$md={{ flexDirection: 'row' }}
>
<Box flex={2} minW={0}>
<Title render="h3" quiet mb={16}>
What you can see once it is one pipe
</Title>
<YStack render="ul" gap="$3">
<Bullet>Approval rates, cost and latency compared across processors, on one screen.</Bullet>
<Bullet>3D Secure where the issuer asks for it, without a second integration.</Bullet>
<Bullet>Open source, so the routing logic is readable before you trust it.</Bullet>
</YStack>
</Box>
<Box
flex={1}
minW={0}
rounded="var(--radius-lg)"
borderWidth={1}
borderColor="var(--neutral-700)"
bg="$hover"
p={20}
>
<Box $platform-web={{ textAlign: 'center' }}>
<Heading render="h4" fontSize="$4" lineHeight="var(--leading-lg)">
Payment Growth
</Heading>
<XStack height={128} mb="$4" items="flex-end" justify="center" gap="$2">
{[20, 35, 28, 45, 60, 75, 90].map((height, i) => (
<View key={i} {...BAR} height={`${height}%`} />
))}
</XStack>
<Words render="div" fontSize="$2" lineHeight="var(--leading-sm)" color="var(--muted-foreground)">
Last 7 days
</Words>
</Box>
</Box>
</YStack>
</Box>
</motion.div>
</Band>
);
};
export default PaymentsSuite;