mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-29 07:20:43 +00:00
233 lines
11 KiB
TypeScript
233 lines
11 KiB
TypeScript
'use client'
|
|
|
|
import React, { useState } from "react";
|
|
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@hanzo/ui";
|
|
import { Box } from '@hanzo/ui'
|
|
import { Grid } from '@hanzo/ui/grid'
|
|
import { Band, FADE, Head, Words } from '@/components/marketing/band'
|
|
import { Leaf } from '@hanzo/ui/marketing'
|
|
|
|
/**
|
|
* NO TAILWIND. The section frame is `Band` + `Head`, the panels and the tab
|
|
* strip are gui props, and each endpoint card is `Leaf` — the role
|
|
* app/globals.css already holds for a card whose edge lifts on approach, which
|
|
* is the one thing a style attribute cannot say. Its two knobs carry this
|
|
* card's resting and lifted edge; only the corner is stated beside it, because
|
|
* these are 12px and a leaf is 16.
|
|
*
|
|
* The band's ground is `FADE`, the site's named fade off the page ground. It is
|
|
* neutral-900 at 20% where this section wrote 30% — one wash, named once,
|
|
* instead of a fifth spelling of it.
|
|
*
|
|
* The active tab is drawn from the STATE this component already holds. It used
|
|
* to be a `data-[state=active]:` pair — a selector, so it could only be a class
|
|
* — and `activeCategory` was set on every change and read nowhere.
|
|
*/
|
|
|
|
interface EndpointProps {
|
|
path: string;
|
|
description: string;
|
|
}
|
|
|
|
/** The card's edge at rest and on approach, and the corner it turns. */
|
|
const LEAF = {
|
|
borderColor: 'var(--neutral-800)',
|
|
hoverStyle: { borderColor: 'var(--border)' },
|
|
rounded: 'var(--radius-lg)',
|
|
bg: 'color-mix(in oklab, var(--neutral-900) 40%, transparent)',
|
|
} as const
|
|
|
|
/** The ink the paths and the group heading share: the foreground at 60%. */
|
|
const DIM = 'color-mix(in oklab, var(--foreground) 60%, transparent)'
|
|
|
|
/** The showing tab's ground. */
|
|
const SHOWING = 'color-mix(in oklab, var(--primary) 5%, transparent)'
|
|
|
|
/** How narrow a column may get before the deck drops to one. */
|
|
const PAIR = { min: 320, max: 2 } as const
|
|
|
|
const EndpointCard = ({ path, description }: EndpointProps) => {
|
|
return (
|
|
<Leaf minW={0} {...LEAF}>
|
|
<Words render="div" mb={8} fontFamily="$mono" fontSize="$2" lineHeight="1.4286" color={DIM} $platform-web={{ wordBreak: 'break-all' }}>{path}</Words>
|
|
<Words render="p" fontSize="$2" lineHeight="1.4286" color="var(--muted-foreground)">{description}</Words>
|
|
</Leaf>
|
|
);
|
|
};
|
|
|
|
const APIEndpoints = () => {
|
|
const [activeCategory, setActiveCategory] = useState("commerce");
|
|
|
|
const endpointCategories = {
|
|
commerce: [
|
|
{ path: "/cart", description: "List all carts for the current session/user" },
|
|
{ path: "/cart/{id}", description: "Get details for a specific cart" },
|
|
{ path: "/cart/{id}/set", description: "Update cart items and quantities" },
|
|
{ path: "/cart/{id}/discard", description: "Remove a cart" },
|
|
{ path: "/checkout/capture/{id}", description: "Capture payment for a previously authorized checkout" },
|
|
{ path: "/checkout/charge", description: "Process a direct checkout charge" },
|
|
{ path: "/checkout/authorize", description: "Authorize payment for later capture" },
|
|
{ path: "/collection/{id}", description: "Get a specific product collection" },
|
|
{ path: "/collection", description: "List all product collections" },
|
|
{ path: "/coupon", description: "List all available coupons" },
|
|
{ path: "/coupon/{id}", description: "Get details for a specific coupon" },
|
|
{ path: "/discount", description: "List all available discounts" },
|
|
{ path: "/discount/{id}", description: "Get details for a specific discount" },
|
|
{ path: "/order/{id}", description: "Get a specific order" },
|
|
{ path: "/order", description: "List all orders" },
|
|
{ path: "/order/{id}/refund", description: "Process a refund for an order" },
|
|
{ path: "/order/{id}/payments", description: "View payment details for an order" },
|
|
{ path: "/order/{id}/capture", description: "Capture payment for a previously authorized order" },
|
|
{ path: "/product", description: "List all products" },
|
|
{ path: "/product/{id}", description: "Get a specific product" },
|
|
{ path: "/return/{id}", description: "Get details for a specific return" },
|
|
{ path: "/return", description: "List all returns" },
|
|
{ path: "/review", description: "List all product reviews" },
|
|
{ path: "/review/{id}", description: "Get a specific product review" },
|
|
{ path: "/store/{id}", description: "Get a specific store" },
|
|
{ path: "/store", description: "List all stores" },
|
|
{ path: "/site/{siteid}/deploy", description: "Deploy a site/storefront" },
|
|
{ path: "/store/{id}/product/{key}", description: "Get a specific product in a store" },
|
|
{ path: "/store/{id}/variant/{key}", description: "Get a specific variant in a store" },
|
|
{ path: "/variant/{id}", description: "Get a specific product variant" },
|
|
{ path: "/variant", description: "List all product variants" }
|
|
],
|
|
identity: [
|
|
{ path: "/account/login", description: "User authentication endpoint" },
|
|
{ path: "/account", description: "Manage user account details" },
|
|
{ path: "/account/create", description: "Create a new user account" },
|
|
{ path: "/user/{id}", description: "Get or update a specific user" },
|
|
{ path: "/user", description: "List all users (admin)" }
|
|
],
|
|
marketing: [
|
|
{ path: "/affiliate/{id}", description: "Get a specific affiliate" },
|
|
{ path: "/affiliate/{id}/connect", description: "Connect an affiliate to an account" },
|
|
{ path: "/affiliate", description: "List all affiliates" },
|
|
{ path: "/affiliate/{id}/transactions", description: "View affiliate transactions" },
|
|
{ path: "/referral", description: "List all referrals" },
|
|
{ path: "/referral/{id}", description: "Get a specific referral" },
|
|
{ path: "/campaign/{id}", description: "Get a specific marketing campaign" },
|
|
{ path: "/campaign", description: "List all marketing campaigns" },
|
|
{ path: "/form/{id}", description: "Get a specific marketing form" },
|
|
{ path: "/form", description: "List all marketing forms" },
|
|
{ path: "/form/{id}/submit", description: "Submit data to a marketing form" },
|
|
{ path: "/referrer/{id}", description: "Get a specific referrer" },
|
|
{ path: "/referrer/{id}/referrals", description: "List referrals for a specific referrer" },
|
|
{ path: "/referrer", description: "List all referrers" },
|
|
{ path: "/referrer/{id}/transactions", description: "View referrer transactions" },
|
|
{ path: "/submission/{id}", description: "Get a specific form submission" },
|
|
{ path: "/submission", description: "List all form submissions" },
|
|
{ path: "/subscriber/{id}", description: "Get a specific subscriber" },
|
|
{ path: "/subscriber", description: "List all subscribers" },
|
|
{ path: "/transaction/{id}", description: "Get a specific marketing transaction" }
|
|
],
|
|
payments: [
|
|
{ path: "/invoice/{id}", description: "Get a specific invoice" },
|
|
{ path: "/invoice", description: "List all invoices" },
|
|
{ path: "/payment/{id}", description: "Get a specific payment" },
|
|
{ path: "/payment", description: "List all payments" },
|
|
{ path: "/payment/{id}/refund", description: "Process a refund for a payment" },
|
|
{ path: "/plan/{id}", description: "Get a specific subscription plan" },
|
|
{ path: "/plan", description: "List all subscription plans" },
|
|
{ path: "/plan/{id}/refund", description: "Process a refund for a subscription plan" },
|
|
{ path: "/subscription/{id}", description: "Get a specific subscription" },
|
|
{ path: "/subscription", description: "List all subscriptions" }
|
|
],
|
|
platform: [
|
|
{ path: "/media", description: "List all media assets" },
|
|
{ path: "/media/{id}", description: "Get a specific media asset" },
|
|
{ path: "/organization/{id}", description: "Get a specific organization" },
|
|
{ path: "/organization", description: "List all organizations" },
|
|
{ path: "/organization/{id}/integrations", description: "List all integrations for an organization" },
|
|
{ path: "/organization/{id}/integrations/{integrationId}", description: "Get a specific integration" },
|
|
{ path: "/webhook", description: "List all webhooks" },
|
|
{ path: "/webhook/{id}", description: "Get a specific webhook" }
|
|
]
|
|
};
|
|
|
|
/**
|
|
* A tab, at rest and while its panel is the one showing. The showing one
|
|
* takes a faint primary ground in place of the trigger's own; `activeStyle`
|
|
* says it too, with the trigger's shadow, so whichever of the two gui applies
|
|
* paints the same. The label keeps the trigger's ink.
|
|
*/
|
|
const tab = (value: string) =>
|
|
activeCategory === value
|
|
? {
|
|
flex: 1,
|
|
borderBottomWidth: 0,
|
|
background: SHOWING,
|
|
activeStyle: { background: SHOWING, shadowColor: '$shadowColor', shadowOpacity: 0.12, shadowRadius: 3, shadowOffset: { width: 0, height: 1 } },
|
|
} as const
|
|
: { flex: 1, borderBottomWidth: 0 } as const
|
|
|
|
return (
|
|
<Band rule={false} pad="$10" ground={FADE}>
|
|
<Head
|
|
title="The endpoints"
|
|
lede="Grouped by what they are about. Every one of them is scoped to your organisation by the token you call with, so multi-tenancy is not something you implement on top."
|
|
/>
|
|
|
|
<Box width="100%" maxW={1024} mx="auto">
|
|
<Tabs defaultValue="commerce" width="100%" onValueChange={setActiveCategory}>
|
|
<TabsList
|
|
width="100%"
|
|
flexWrap="wrap"
|
|
height="auto"
|
|
marginBottom="$5"
|
|
padding="$1"
|
|
borderWidth={1}
|
|
borderColor="var(--neutral-800)"
|
|
borderRadius="var(--radius-lg)"
|
|
backgroundColor="$panel"
|
|
>
|
|
<TabsTrigger value="commerce" {...tab("commerce")}>
|
|
Commerce
|
|
</TabsTrigger>
|
|
<TabsTrigger value="identity" {...tab("identity")}>
|
|
Identity
|
|
</TabsTrigger>
|
|
<TabsTrigger value="marketing" {...tab("marketing")}>
|
|
Marketing
|
|
</TabsTrigger>
|
|
<TabsTrigger value="payments" {...tab("payments")}>
|
|
Payments
|
|
</TabsTrigger>
|
|
<TabsTrigger value="platform" {...tab("platform")}>
|
|
Platform
|
|
</TabsTrigger>
|
|
</TabsList>
|
|
|
|
{Object.keys(endpointCategories).map((category) => (
|
|
<TabsContent key={category} value={category} mt={0}>
|
|
<Box
|
|
p="$5"
|
|
borderWidth={1}
|
|
borderColor="var(--neutral-800)"
|
|
rounded="var(--radius-xl)"
|
|
bg="$panel"
|
|
>
|
|
<Words render="h3" mb={16} fontSize="$6" lineHeight="1.4" weight="600" color={DIM}>
|
|
Hanzo {category.charAt(0).toUpperCase() + category.slice(1)} API Endpoints
|
|
</Words>
|
|
|
|
<Grid columns={PAIR} gap={12}>
|
|
{endpointCategories[category as keyof typeof endpointCategories].map((endpoint, index) => (
|
|
<EndpointCard
|
|
key={index}
|
|
path={endpoint.path}
|
|
description={endpoint.description}
|
|
/>
|
|
))}
|
|
</Grid>
|
|
</Box>
|
|
</TabsContent>
|
|
))}
|
|
</Tabs>
|
|
</Box>
|
|
</Band>
|
|
);
|
|
};
|
|
|
|
export default APIEndpoints;
|