Added detail page routing to AdminX demo app (#19101)

refs https://github.com/TryGhost/Product/issues/4183
This commit is contained in:
Jono M 2023-11-22 15:43:03 +00:00 committed by GitHub
parent ec332520eb
commit 9848469568
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 261 additions and 236 deletions

View File

@ -0,0 +1,10 @@
import {Button} from '@tryghost/admin-x-design-system';
import {useRouting} from '@tryghost/admin-x-framework/routing';
const DetailPage: React.FC = () => {
const {updateRoute} = useRouting();
return <>Detail page <Button label='Back' onClick={() => updateRoute('')} /></>;
};
export default DetailPage;

View File

@ -0,0 +1,244 @@
import {Avatar, Button, ButtonGroup, DynamicTable, DynamicTableColumn, DynamicTableRow, Heading, Hint, Page, SortMenu, ViewContainer} from '@tryghost/admin-x-design-system';
import {useRouting} from '@tryghost/admin-x-framework/routing';
import {useState} from 'react';
const ListPage = () => {
const {updateRoute} = useRouting();
const [view, setView] = useState<string>('list');
const dummyActions = [
<Button label='Filter' onClick={() => {
alert('Clicked filter');
}} />,
<SortMenu
direction='desc'
items={[
{
id: 'date-added',
label: 'Date added',
selected: true
},
{
id: 'name',
label: 'Name'
},
{
id: 'redemptions',
label: 'Open Rate'
}
]}
position="left"
onDirectionChange={() => {}}
onSortChange={() => {}}
/>,
<Button icon='magnifying-glass' size='sm' onClick={() => {
alert('Clicked search');
}} />,
<ButtonGroup buttons={[
{
icon: 'listview',
size: 'sm',
iconColorClass: (view === 'list' ? 'text-black' : 'text-grey-500'),
onClick: () => {
setView('list');
}
},
{
icon: 'cardview',
size: 'sm',
iconColorClass: (view === 'card' ? 'text-black' : 'text-grey-500'),
onClick: () => {
setView('card');
}
}
]} clearBg={false} link />
];
const testColumns: DynamicTableColumn[] = [
{
title: 'Member',
noWrap: true,
minWidth: '1%',
maxWidth: '1%'
},
{
title: 'Status'
},
{
title: 'Open rate'
},
{
title: 'Location',
noWrap: true
},
{
title: 'Created',
noWrap: true
},
{
title: 'Signed up on post',
noWrap: true,
maxWidth: '150px'
},
{
title: 'Newsletter'
},
{
title: 'Billing period'
},
{
title: 'Email sent'
},
{
title: '',
hidden: true,
disableRowClick: true
}
];
const testRows = (noOfRows: number) => {
const data: DynamicTableRow[] = [];
for (let i = 0; i < noOfRows; i++) {
data.push(
{
onClick: () => {
updateRoute('detail');
},
cells: [
(<div className='flex items-center gap-3 whitespace-nowrap pr-10'>
<Avatar image={`https://i.pravatar.cc/150?img=${i}`} />
<div>
{i % 3 === 0 && <div className='whitespace-nowrap text-md'>Jamie Larson</div>}
{i % 3 === 1 && <div className='whitespace-nowrap text-md'>Giana Septimus</div>}
{i % 3 === 2 && <div className='whitespace-nowrap text-md'>Zaire Bator</div>}
<div className='text-grey-700'>jamie@larson.com</div>
</div>
</div>),
'Free',
'40%',
'London, UK',
<div>
<div>22 June 2023</div>
<div className='text-grey-500'>5 months ago</div>
</div>,
'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
'Subscribed',
'Monthly',
'1,303',
<Button color='green' label='Edit' link onClick={() => {
alert('Clicked Edit in row:' + i);
}} />
]
}
);
}
return data;
};
const dummyCards = (noOfCards: number) => {
const cards = [];
for (let i = 0; i < noOfCards; i++) {
cards.push(
<div className='flex min-h-[20vh] cursor-pointer flex-col items-center gap-5 rounded-sm bg-grey-100 p-7 pt-9 transition-all hover:bg-grey-200' onClick={() => {
alert('Clicked');
}}>
<Avatar image={`https://i.pravatar.cc/150?img=${i}`} size='xl' />
<div className='flex flex-col items-center'>
<Heading level={5}>
{i % 3 === 0 && 'Jamie Larson'}
{i % 3 === 1 && 'Giana Septimus'}
{i % 3 === 2 && 'Zaire Bator'}
</Heading>
<div className='mt-1 text-sm text-grey-700'>
{i % 3 === 0 && 'jamie@larson.com'}
{i % 3 === 1 && 'giana@septimus.com'}
{i % 3 === 2 && 'zaire@bator.com'}
</div>
</div>
<div className='flex w-full flex-col gap-4 border-t border-grey-300 pt-5'>
{i % 3 === 0 && (<>
<div className='flex gap-4'>
<div className='basis-1/2 text-center'>
<Heading level={6}>Open rate</Heading>
<div className='text-lg'>83%</div>
</div>
<div className='basis-1/2 text-center'>
<Heading level={6}>Click rate</Heading>
<div className='text-lg'>19%</div>
</div>
</div>
</>)}
{i % 3 === 1 && (<>
<div className='flex gap-4'>
<div className='basis-1/2 text-center'>
<Heading level={6}>Open rate</Heading>
<div className='text-lg'>68%</div>
</div>
<div className='basis-1/2 text-center'>
<Heading level={6}>Click rate</Heading>
<div className='text-lg'>21%</div>
</div>
</div>
</>)}
{i % 3 === 2 && (<>
<div className='flex gap-4'>
<div className='basis-1/2 text-center'>
<Heading level={6}>Open rate</Heading>
<div className='text-lg'>89%</div>
</div>
<div className='basis-1/2 text-center'>
<Heading level={6}>Click rate</Heading>
<div className='text-lg'>34%</div>
</div>
</div>
</>)}
</div>
</div>
);
}
return cards;
};
let contents = <></>;
switch (view) {
case 'list':
contents = <DynamicTable
cellClassName='text-sm'
columns={testColumns}
footer={
<Hint>30 members</Hint>
}
rows={testRows(30)}
stickyFooter
stickyHeader
/>;
break;
case 'card':
contents = <div className='grid grid-cols-4 gap-8 py-8'>{dummyCards(30)}</div>;
break;
}
const demoPage = (
<Page>
<ViewContainer
actions={dummyActions}
primaryAction={{
title: 'About',
onClick: () => {
updateRoute('demo-modal');
}
}}
title='AdminX Demo App'
toolbarBorder={view === 'card'}
type='page'
>
{contents}
</ViewContainer>
</Page>
);
return demoPage;
};
export default ListPage;

View File

@ -1,244 +1,15 @@
import {Avatar, Button, ButtonGroup, DynamicTable, DynamicTableColumn, DynamicTableRow, Heading, Hint, Page, SortMenu, ViewContainer} from '@tryghost/admin-x-design-system';
import DetailPage from './DetailPage';
import ListPage from './ListPage';
import {useRouting} from '@tryghost/admin-x-framework/routing';
import {useState} from 'react';
const MainContent = () => {
const {updateRoute} = useRouting();
const [view, setView] = useState<string>('list');
const {route} = useRouting();
const dummyActions = [
<Button label='Filter' onClick={() => {
alert('Clicked filter');
}} />,
<SortMenu
direction='desc'
items={[
{
id: 'date-added',
label: 'Date added',
selected: true
},
{
id: 'name',
label: 'Name'
},
{
id: 'redemptions',
label: 'Open Rate'
}
]}
position="left"
onDirectionChange={() => {}}
onSortChange={() => {}}
/>,
<Button icon='magnifying-glass' size='sm' onClick={() => {
alert('Clicked search');
}} />,
<ButtonGroup buttons={[
{
icon: 'listview',
size: 'sm',
iconColorClass: (view === 'list' ? 'text-black' : 'text-grey-500'),
onClick: () => {
setView('list');
}
},
{
icon: 'cardview',
size: 'sm',
iconColorClass: (view === 'card' ? 'text-black' : 'text-grey-500'),
onClick: () => {
setView('card');
}
}
]} clearBg={false} link />
];
const testColumns: DynamicTableColumn[] = [
{
title: 'Member',
noWrap: true,
minWidth: '1%',
maxWidth: '1%'
},
{
title: 'Status'
},
{
title: 'Open rate'
},
{
title: 'Location',
noWrap: true
},
{
title: 'Created',
noWrap: true
},
{
title: 'Signed up on post',
noWrap: true,
maxWidth: '150px'
},
{
title: 'Newsletter'
},
{
title: 'Billing period'
},
{
title: 'Email sent'
},
{
title: '',
hidden: true,
disableRowClick: true
}
];
const testRows = (noOfRows: number) => {
const data: DynamicTableRow[] = [];
for (let i = 0; i < noOfRows; i++) {
data.push(
{
onClick: () => {
alert('Clicked on row: ' + i);
},
cells: [
(<div className='flex items-center gap-3 whitespace-nowrap pr-10'>
<Avatar image={`https://i.pravatar.cc/150?img=${i}`} />
<div>
{i % 3 === 0 && <div className='whitespace-nowrap text-md'>Jamie Larson</div>}
{i % 3 === 1 && <div className='whitespace-nowrap text-md'>Giana Septimus</div>}
{i % 3 === 2 && <div className='whitespace-nowrap text-md'>Zaire Bator</div>}
<div className='text-grey-700'>jamie@larson.com</div>
</div>
</div>),
'Free',
'40%',
'London, UK',
<div>
<div>22 June 2023</div>
<div className='text-grey-500'>5 months ago</div>
</div>,
'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
'Subscribed',
'Monthly',
'1,303',
<Button color='green' label='Edit' link onClick={() => {
alert('Clicked Edit in row:' + i);
}} />
]
}
);
}
return data;
};
const dummyCards = (noOfCards: number) => {
const cards = [];
for (let i = 0; i < noOfCards; i++) {
cards.push(
<div className='flex min-h-[20vh] cursor-pointer flex-col items-center gap-5 rounded-sm bg-grey-100 p-7 pt-9 transition-all hover:bg-grey-200' onClick={() => {
alert('Clicked');
}}>
<Avatar image={`https://i.pravatar.cc/150?img=${i}`} size='xl' />
<div className='flex flex-col items-center'>
<Heading level={5}>
{i % 3 === 0 && 'Jamie Larson'}
{i % 3 === 1 && 'Giana Septimus'}
{i % 3 === 2 && 'Zaire Bator'}
</Heading>
<div className='mt-1 text-sm text-grey-700'>
{i % 3 === 0 && 'jamie@larson.com'}
{i % 3 === 1 && 'giana@septimus.com'}
{i % 3 === 2 && 'zaire@bator.com'}
</div>
</div>
<div className='flex w-full flex-col gap-4 border-t border-grey-300 pt-5'>
{i % 3 === 0 && (<>
<div className='flex gap-4'>
<div className='basis-1/2 text-center'>
<Heading level={6}>Open rate</Heading>
<div className='text-lg'>83%</div>
</div>
<div className='basis-1/2 text-center'>
<Heading level={6}>Click rate</Heading>
<div className='text-lg'>19%</div>
</div>
</div>
</>)}
{i % 3 === 1 && (<>
<div className='flex gap-4'>
<div className='basis-1/2 text-center'>
<Heading level={6}>Open rate</Heading>
<div className='text-lg'>68%</div>
</div>
<div className='basis-1/2 text-center'>
<Heading level={6}>Click rate</Heading>
<div className='text-lg'>21%</div>
</div>
</div>
</>)}
{i % 3 === 2 && (<>
<div className='flex gap-4'>
<div className='basis-1/2 text-center'>
<Heading level={6}>Open rate</Heading>
<div className='text-lg'>89%</div>
</div>
<div className='basis-1/2 text-center'>
<Heading level={6}>Click rate</Heading>
<div className='text-lg'>34%</div>
</div>
</div>
</>)}
</div>
</div>
);
}
return cards;
};
let contents = <></>;
switch (view) {
case 'list':
contents = <DynamicTable
cellClassName='text-sm'
columns={testColumns}
footer={
<Hint>30 members</Hint>
}
rows={testRows(30)}
stickyFooter
stickyHeader
/>;
break;
case 'card':
contents = <div className='grid grid-cols-4 gap-8 py-8'>{dummyCards(30)}</div>;
break;
if (route === 'detail') {
return <DetailPage />;
} else {
return <ListPage />;
}
const demoPage = (
<Page>
<ViewContainer
actions={dummyActions}
primaryAction={{
title: 'About',
onClick: () => {
updateRoute('demo-modal');
}
}}
title='AdminX Demo App'
toolbarBorder={view === 'card'}
type='page'
>
{contents}
</ViewContainer>
</Page>
);
return demoPage;
};
export default MainContent;