vega-frontend-monorepo/apps/trading/pages/markets/[marketId].page.tsx

159 lines
4.5 KiB
TypeScript
Raw Normal View History

import { gql, useQuery } from '@apollo/client';
import AutoSizer from 'react-virtualized-auto-sizer';
import classNames from 'classnames';
import { useRouter } from 'next/router';
2022-03-01 22:14:33 +00:00
import React, { Children, isValidElement, ReactNode } from 'react';
import { Market, MarketVariables } from './__generated__/Market';
// Top level page query
const MARKET_QUERY = gql`
query Market($marketId: ID!) {
market(id: $marketId) {
id
name
trades {
id
price
size
createdAt
}
}
}
`;
const MarketPage = () => {
const { query } = useRouter();
const { data, loading, error } = useQuery<Market, MarketVariables>(
MARKET_QUERY,
{
variables: { marketId: query.marketId as string },
2022-03-01 21:01:52 +00:00
skip: !query.marketId,
}
);
if (loading || !data) {
return <div>Loading...</div>;
}
return (
<>
{error ? (
<div>Something went wrong: {error.message}</div>
) : (
2022-03-01 22:46:42 +00:00
<div className="h-full max-h-full grid gap-[1px] bg-[#ddd] grid-cols-[1fr_325px_325px] grid-rows-[min-content_1fr_200px]">
<header className="col-start-1 col-end-2 row-start-1 row-end-1 bg-white p-8">
<h1>Market: {data.market.name}</h1>
</header>
2022-03-01 22:46:42 +00:00
<GridChild className="col-start-1 col-end-2">TODO: Chart</GridChild>
<GridChild className="row-start-1 row-end-3">TODO: Ticket</GridChild>
<GridChild className="row-start-1 row-end-3">
2022-03-01 22:14:33 +00:00
<GridTabs group="trade">
<GridTab name="trades">
<pre>{JSON.stringify(data, null, 2)}</pre>
</GridTab>
2022-03-01 22:14:33 +00:00
<GridTab name="orderbook">Orderbook TODO:</GridTab>
</GridTabs>
</GridChild>
2022-03-01 22:46:42 +00:00
<GridChild className="col-span-3">
2022-03-01 22:14:33 +00:00
<GridTabs group="portfolio">
<GridTab name="orders">TODO: Orders</GridTab>
<GridTab name="positions">TODO: Positions</GridTab>
<GridTab name="collateral">TODO: Collateral</GridTab>
</GridTabs>
</GridChild>
</div>
)}
</>
);
};
export default MarketPage;
interface GridChildProps {
children: ReactNode;
className?: string;
}
const GridChild = ({ children, className }: GridChildProps) => {
const gridChildClasses = classNames('bg-white', className);
return (
<section className={gridChildClasses}>
<AutoSizer>
{({ width, height }) => (
<div style={{ width, height }} className="overflow-auto">
{children}
</div>
)}
</AutoSizer>
</section>
);
};
interface GridTabsProps {
children: ReactNode;
2022-03-01 22:14:33 +00:00
group: string;
}
2022-03-01 22:14:33 +00:00
const GridTabs = ({ children, group }: GridTabsProps) => {
const { query, asPath, replace } = useRouter();
return (
<div className="h-full grid grid-rows-[min-content_1fr]">
{/* the tabs */}
2022-03-01 22:46:42 +00:00
<div className="flex gap-[2px] bg-[#ddd]" role="tablist">
{Children.map(children, (child) => {
if (!isValidElement(child)) return null;
2022-03-01 22:33:28 +00:00
const isActive = query[group] === child.props.name;
2022-03-01 22:48:16 +00:00
const buttonClass = classNames('py-4 px-12', {
2022-03-01 22:33:28 +00:00
'text-vega-pink': isActive,
2022-03-01 22:46:42 +00:00
'bg-white': isActive,
});
return (
<button
className={buttonClass}
2022-03-01 22:14:33 +00:00
onClick={() => {
const [url, queryString] = asPath.split('?');
const searchParams = new URLSearchParams(queryString);
searchParams.set(group, child.props.name);
replace(`${url}?${searchParams.toString()}`);
}}
2022-03-01 22:33:28 +00:00
role="tab"
aria-selected={isActive}
aria-controls={`tabpanel-${group}-${child.props.name}`}
id={`tab-${group}-${child.props.name}`}
>
{child.props.name}
</button>
);
})}
</div>
{/* the content */}
2022-03-01 22:18:49 +00:00
<div className="h-full overflow-auto">
{Children.map(children, (child) => {
2022-03-01 22:14:33 +00:00
if (isValidElement(child) && query[group] === child.props.name) {
2022-03-01 22:33:28 +00:00
return (
<div
role="tabpanel"
id={`tabpanel-${group}-${child.props.name}`}
aria-labelledby={`tab-${group}-${child.props.name}`}
>
{child.props.children}
</div>
);
}
return null;
})}
</div>
</div>
);
};
interface GridTabProps {
children: ReactNode;
name: string;
}
const GridTab = ({ children }: GridTabProps) => {
return <div>{children}</div>;
};