Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 17 additions & 74 deletions apps/my_sample_app/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,87 +1,30 @@
import { ErrorNotFound } from '#components/ErrorNotFound'
import { appRoutes } from '#data/routes'
import {
Button,
EmptyState,
HomePageLayout,
Spacer,
useTokenProvider
} from '@commercelayer/app-elements'
import { Routes } from '@commercelayer/app-elements'
import type { FC } from 'react'
import { Route, Router, Switch } from 'wouter'
import { Router } from 'wouter'

interface AppProps {
routerBase?: string
}

export const App: FC<AppProps> = ({ routerBase }) => {
const { canUser } = useTokenProvider()

return (
<Router base={routerBase}>
<Switch>
<Route path={appRoutes.home.path}>
<HomePageLayout title='My Sample App'>
<Spacer top='14'>
<EmptyState
title='Welcome'
description='This is a starter template. Start building your application by modifying this `App.tsx` component.'
/>
</Spacer>
<Spacer top='14'>
{canUser('create', 'orders') ? (
<EmptyState
title="canUser('create', 'orders') ?"
description={
<>
You can use the helper <code>canUser()</code> to check
user permissions.
<br />
In this case, you can see that the user has permission to
create orders.
</>
}
action={
<Button variant='primary'>
Create an Order (not implemented)
</Button>
}
/>
) : canUser('read', 'orders') ? (
<EmptyState
title="canUser('read', 'orders') ?"
description={
<>
You can use the helper <code>canUser()</code> to check
user permissions.
<br />
In this case, you can see that the user has permission to
read orders.
</>
}
/>
) : (
<EmptyState
title="canUser('read', 'orders') ?"
description={
<>
You can use the helper <code>canUser()</code> to check
user permissions.
<br />
In this case, you can see that the user does not have
permission to read orders. This is the classic "Not
Authorized" case.
</>
}
/>
)}
</Spacer>
</HomePageLayout>
</Route>
<Route>
<ErrorNotFound />
</Route>
</Switch>
<Routes
routes={appRoutes}
list={{
home: {
component: async () => await import('#pages/Home')
},
list: {
component: async () => await import('#pages/List')
},
details: {
component: async () => await import('#pages/Details'),
overlay: true
}
}}
/>
</Router>
)
}
12 changes: 10 additions & 2 deletions apps/my_sample_app/src/data/routes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createRoute } from '@commercelayer/app-elements'
import { createRoute, createTypedRoute } from '@commercelayer/app-elements'
import type { ListableResourceType } from '@commercelayer/sdk'

export type AppRoute = keyof typeof appRoutes

Expand All @@ -7,5 +8,12 @@ export type AppRoute = keyof typeof appRoutes
// a `path` property to be used as patter matching in <Route path> component
// and `makePath` method to be used to generate the path used in navigation and links
export const appRoutes = {
home: createRoute('/')
home: createRoute('/'),
list: createTypedRoute<{ resourceType: ListableResourceType }>()(
'/:resourceType/'
),
details: createTypedRoute<{
resourceType: ListableResourceType
resourceId: string
}>()('/:resourceType/:resourceId/')
}
60 changes: 60 additions & 0 deletions apps/my_sample_app/src/pages/Details.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { appRoutes } from '#data/routes'
import {
EmptyState,
PageLayout,
type PageProps,
ResourceDetails,
ResourceMetadata,
Spacer,
formatResourceName,
useCoreApi
} from '@commercelayer/app-elements'
import type { FC } from 'react'
import { useLocation } from 'wouter'

const Page: FC<PageProps<typeof appRoutes.details>> = ({ params }) => {
const { resourceType, resourceId } = params
const [, setLocation] = useLocation()
const { data, isLoading, mutate } = useCoreApi(resourceType, 'retrieve', [
resourceId
])

return (
<PageLayout
title={formatResourceName({
resource: resourceType,
format: 'title',
count: 'singular'
})}
navigationButton={{
label: 'Back',
onClick: () => {
setLocation(appRoutes.list.makePath({ resourceType }))
}
}}
>
{isLoading ? (
<div>Loading...</div>
) : data == null ? (
<EmptyState title='Resource not found' />
) : (
<>
<Spacer bottom='14'>
<ResourceDetails
resource={data}
onUpdated={async () => {
void mutate()
}}
/>
</Spacer>
<ResourceMetadata
resourceType={resourceType}
resourceId={resourceId}
/>
</>
)}
</PageLayout>
)
}

export default Page
48 changes: 48 additions & 0 deletions apps/my_sample_app/src/pages/Home.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { appRoutes } from '#data/routes'
import {
formatResourceName,
HomePageLayout,
Icon,
List,
ListItem,
Spacer
} from '@commercelayer/app-elements'
import type { ListableResourceType } from '@commercelayer/sdk'
import type { FC } from 'react'
import { useLocation } from 'wouter'

const resources: ListableResourceType[] = [
'customers',
'markets',
'shipments',
'skus'
]

const Page: FC = () => {
const [, setLocation] = useLocation()
return (
<HomePageLayout title='My Sample App'>
<Spacer top='14'>
<List title='Resources'>
{resources.map((resourceType) => (
<ListItem
key={resourceType}
onClick={() => {
setLocation(appRoutes.list.makePath({ resourceType }))
}}
>
{formatResourceName({
resource: resourceType,
format: 'title',
count: 'plural'
})}
<Icon name='caretRight' />
</ListItem>
))}
</List>
</Spacer>
</HomePageLayout>
)
}

export default Page
81 changes: 81 additions & 0 deletions apps/my_sample_app/src/pages/List.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { appRoutes } from '#data/routes'
import {
Icon,
ListItem,
PageLayout,
type PageProps,
Text,
formatResourceName,
useResourceList
} from '@commercelayer/app-elements'
import type { FC } from 'react'
import { useLocation } from 'wouter'

const Page: FC<PageProps<typeof appRoutes.list>> = ({ params }) => {
const { resourceType } = params
const [, setLocation] = useLocation()
const { ResourceList, isLoading } = useResourceList({
type: resourceType,
query: {
pageSize: 25
}
})

if (isLoading) {
return null
}

return (
<PageLayout
title={formatResourceName({
resource: resourceType,
format: 'title',
count: 'plural'
})}
navigationButton={{
label: 'Select type',
onClick: () => {
setLocation(appRoutes.home.makePath({}))
}
}}
>
<ResourceList
title='All'
ItemTemplate={({ resource }) => {
if (resource == null) {
return null
}
return (
<ListItem
onClick={() => {
setLocation(
appRoutes.details.makePath({
resourceType,
resourceId: resource.id
})
)
}}
>
<div>
<Text tag='div' weight='semibold'>
#{resource.id}
</Text>
<Text tag='div' variant='info'>
{/* for customers */}
{'email' in resource && resource.email}
{/* for other markets and skus */}
{'name' in resource && resource.name}
{/* for other shipments */}
{'number' in resource && resource.number}
</Text>
</div>
<Icon name='caretRight' />
</ListItem>
)
}}
/>
</PageLayout>
)
}

export default Page