Files
protocol/sites/dev0x-portal/app/routes/_dashboard.app.$appId.tsx
2023-04-06 20:47:43 +02:00

149 lines
6.4 KiB
TypeScript

import { json, redirect } from '@remix-run/node';
import { Outlet, useLoaderData } from '@remix-run/react';
import { twMerge } from 'tailwind-merge';
import { Badge, isBadgeColor } from '../components/Badge';
import { LinkButton } from '../components/Button';
import { Key2 } from '../icons/Key2';
import { Settings4 } from '../icons/Settings4';
import { GoToExplorer } from '../components/GoToExplorer';
import { SwapCodeBlock } from '../components/SwapCodeBlock';
import { getAppById } from '../data/zippo.server';
import type { LoaderArgs, MetaFunction } from '@remix-run/node';
import type { ComponentPropsWithoutRef } from 'react';
import type { ClientApp } from '../types';
import { ZIPPO_ROUTE_TAG_TO_PRODUCT } from '../utils/utils';
import type { TZippoRouteTag } from 'zippo-interface';
export const meta: MetaFunction<typeof loader> = ({ data }) => {
return {
title: `${data.app.name} Dashboard | 0x`,
description: `${data.app.name} Dashboard`,
};
};
export const loader = async ({ params, request }: LoaderArgs) => {
if (!params.appId) throw redirect('/apps');
const app = await getAppById(params.appId);
if (app.result === 'ERROR') {
throw app.error;
}
return json({
app: app.data,
});
};
function ViewDocsLink({ className, ...other }: ComponentPropsWithoutRef<'a'>) {
return (
<a
className={twMerge('text-blue-brand font-sans text-base hover:opacity-80', className)}
href="https://docs.0x.org/"
rel="noreferrer"
target="_blank"
{...other}
>
View docs
</a>
);
}
export type AppOutletContext = {
app: ClientApp;
};
export default function AppDashboard() {
const { app } = useLoaderData<typeof loader>();
return (
<>
<div className="border-grey-200 border-b border-solid pt-8 pb-9">
<div className="max-w-page-size mx-auto flex items-start justify-between px-24">
<div>
<div className="flex items-center">
<h1 className="inline-block text-5xl font-normal">{app.name}</h1>
{app.onChainTag?.name && (
<span className="items text-grey-800 bg-grey-100 ml-4 rounded-full px-4 py-2 text-lg antialiased">
{app.onChainTag.name}
</span>
)}
</div>
<div className="mt-2 grid auto-cols-max grid-flow-col gap-4">
{(app.productAccess || []).map((product: string) => {
const { name, color } = ZIPPO_ROUTE_TAG_TO_PRODUCT[product as TZippoRouteTag] || {};
if (!name || !color) {
console.warn('Invalid product', product);
return null;
}
const badgeColor = isBadgeColor(color) ? color : undefined;
if (badgeColor) {
console.warn('Invalid color for Badge', color);
}
return (
<Badge color={badgeColor} key={name}>
{name}
</Badge>
);
})}
</div>
</div>
<div className="flex items-center">
<LinkButton
size="sm"
color="transparent"
endIcon={<Key2 className="relative -top-[1px]" />}
className="mr-4"
to={`/app/${app.id}/api-key`}
>
API Key
</LinkButton>
<LinkButton
size="sm"
color="transparent"
endIcon={<Settings4 className="relative -top-[1px]" />}
to={`/app/${app.id}/settings`}
>
Settings
</LinkButton>
</div>
</div>
</div>
<div className="max-w-page-size mx-auto px-24">
<div className=" bg-grey-100 mx-auto my-11 grid h-[236px] grid-cols-5 rounded-2xl p-5">
<div className="p-4">
<h2 className="text-1.5lg mb-3.5 leading-none">Make a live API call</h2>
<div className="text-grey-700/50 mb-12 max-w-[200px] font-sans text-base">
Make your first live request with your API key.
</div>
<ViewDocsLink />
</div>
<SwapCodeBlock className="col-span-2" />
<div className="col-span-2 flex justify-evenly pt-4">
<div className="min-w-max">
<h3 className="font-sans text-base">Build a gasless dApp</h3>
<ViewDocsLink
className="mt-2 mb-5 inline-block"
href="https://docs.0x.org/tx-relay-api/introduction"
/>
<img src="/assets/buildGaslessDApp.svg" alt="Gasless dApp" />
</div>
<div className="min-w-max">
<h3 className="font-sans text-base">Try Limit orders</h3>
<ViewDocsLink
className="mt-2 mb-5 inline-block"
href="https://docs.0x.org/0x-orderbook-api/introduction"
/>
<img src="/assets/tryLimitOrder.svg" alt="Limit order" />
</div>
</div>
</div>
</div>
<div className="max-w-page-size mx-auto mb-44 px-24">
<GoToExplorer url="https://explorer.0x.org/apps" className="p-9" buttonClassName="mt-6" />
</div>
<Outlet context={{ app }} />
</>
);
}