mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
135 lines
5.1 KiB
TypeScript
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;
|