Skip to content

Commit d222b03

Browse files
committed
feat: make simple custom apps as blog sample
1 parent 37dfd83 commit d222b03

5 files changed

Lines changed: 216 additions & 76 deletions

File tree

apps/my_sample_app/src/App.tsx

Lines changed: 17 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,30 @@
1-
import { ErrorNotFound } from '#components/ErrorNotFound'
21
import { appRoutes } from '#data/routes'
3-
import {
4-
Button,
5-
EmptyState,
6-
HomePageLayout,
7-
Spacer,
8-
useTokenProvider
9-
} from '@commercelayer/app-elements'
2+
import { Routes } from '@commercelayer/app-elements'
103
import type { FC } from 'react'
11-
import { Route, Router, Switch } from 'wouter'
4+
import { Router } from 'wouter'
125

136
interface AppProps {
147
routerBase?: string
158
}
169

1710
export const App: FC<AppProps> = ({ routerBase }) => {
18-
const { canUser } = useTokenProvider()
19-
2011
return (
2112
<Router base={routerBase}>
22-
<Switch>
23-
<Route path={appRoutes.home.path}>
24-
<HomePageLayout title='My Sample App'>
25-
<Spacer top='14'>
26-
<EmptyState
27-
title='Welcome'
28-
description='This is a starter template. Start building your application by modifying this `App.tsx` component.'
29-
/>
30-
</Spacer>
31-
<Spacer top='14'>
32-
{canUser('create', 'orders') ? (
33-
<EmptyState
34-
title="canUser('create', 'orders') ?"
35-
description={
36-
<>
37-
You can use the helper <code>canUser()</code> to check
38-
user permissions.
39-
<br />
40-
In this case, you can see that the user has permission to
41-
create orders.
42-
</>
43-
}
44-
action={
45-
<Button variant='primary'>
46-
Create an Order (not implemented)
47-
</Button>
48-
}
49-
/>
50-
) : canUser('read', 'orders') ? (
51-
<EmptyState
52-
title="canUser('read', 'orders') ?"
53-
description={
54-
<>
55-
You can use the helper <code>canUser()</code> to check
56-
user permissions.
57-
<br />
58-
In this case, you can see that the user has permission to
59-
read orders.
60-
</>
61-
}
62-
/>
63-
) : (
64-
<EmptyState
65-
title="canUser('read', 'orders') ?"
66-
description={
67-
<>
68-
You can use the helper <code>canUser()</code> to check
69-
user permissions.
70-
<br />
71-
In this case, you can see that the user does not have
72-
permission to read orders. This is the classic "Not
73-
Authorized" case.
74-
</>
75-
}
76-
/>
77-
)}
78-
</Spacer>
79-
</HomePageLayout>
80-
</Route>
81-
<Route>
82-
<ErrorNotFound />
83-
</Route>
84-
</Switch>
13+
<Routes
14+
routes={appRoutes}
15+
list={{
16+
home: {
17+
component: async () => await import('#pages/Home')
18+
},
19+
list: {
20+
component: async () => await import('#pages/List')
21+
},
22+
details: {
23+
component: async () => await import('#pages/Details'),
24+
overlay: true
25+
}
26+
}}
27+
/>
8528
</Router>
8629
)
8730
}
Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { createRoute } from '@commercelayer/app-elements'
1+
import { createRoute, createTypedRoute } from '@commercelayer/app-elements'
2+
import type { ListableResourceType } from '@commercelayer/sdk'
23

34
export type AppRoute = keyof typeof appRoutes
45

@@ -7,5 +8,12 @@ export type AppRoute = keyof typeof appRoutes
78
// a `path` property to be used as patter matching in <Route path> component
89
// and `makePath` method to be used to generate the path used in navigation and links
910
export const appRoutes = {
10-
home: createRoute('/')
11+
home: createRoute('/'),
12+
list: createTypedRoute<{ resourceType: ListableResourceType }>()(
13+
'/:resourceType/'
14+
),
15+
details: createTypedRoute<{
16+
resourceType: ListableResourceType
17+
resourceId: string
18+
}>()('/:resourceType/:resourceId/')
1119
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { appRoutes } from '#data/routes'
2+
import {
3+
EmptyState,
4+
PageLayout,
5+
type PageProps,
6+
ResourceDetails,
7+
ResourceMetadata,
8+
Spacer,
9+
formatResourceName,
10+
useCoreApi
11+
} from '@commercelayer/app-elements'
12+
import type { FC } from 'react'
13+
import { useLocation } from 'wouter'
14+
15+
const Page: FC<PageProps<typeof appRoutes.details>> = ({ params }) => {
16+
const { resourceType, resourceId } = params
17+
const [, setLocation] = useLocation()
18+
const { data, isLoading, mutate } = useCoreApi(resourceType, 'retrieve', [
19+
resourceId
20+
])
21+
22+
return (
23+
<PageLayout
24+
title={formatResourceName({
25+
resource: resourceType,
26+
format: 'title',
27+
count: 'singular'
28+
})}
29+
navigationButton={{
30+
label: 'Back',
31+
onClick: () => {
32+
setLocation(appRoutes.list.makePath({ resourceType }))
33+
}
34+
}}
35+
>
36+
{isLoading ? (
37+
<div>Loading...</div>
38+
) : data == null ? (
39+
<EmptyState title='Resource not found' />
40+
) : (
41+
<>
42+
<Spacer bottom='14'>
43+
<ResourceDetails
44+
resource={data}
45+
onUpdated={async () => {
46+
void mutate()
47+
}}
48+
/>
49+
</Spacer>
50+
<ResourceMetadata
51+
resourceType={resourceType}
52+
resourceId={resourceId}
53+
/>
54+
</>
55+
)}
56+
</PageLayout>
57+
)
58+
}
59+
60+
export default Page
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { appRoutes } from '#data/routes'
2+
import {
3+
formatResourceName,
4+
HomePageLayout,
5+
Icon,
6+
List,
7+
ListItem,
8+
Spacer
9+
} from '@commercelayer/app-elements'
10+
import type { ListableResourceType } from '@commercelayer/sdk'
11+
import type { FC } from 'react'
12+
import { useLocation } from 'wouter'
13+
14+
const resources: ListableResourceType[] = [
15+
'customers',
16+
'markets',
17+
'shipments',
18+
'skus'
19+
]
20+
21+
const Page: FC = () => {
22+
const [, setLocation] = useLocation()
23+
return (
24+
<HomePageLayout title='My Sample App'>
25+
<Spacer top='14'>
26+
<List title='Resources'>
27+
{resources.map((resourceType) => (
28+
<ListItem
29+
key={resourceType}
30+
onClick={() => {
31+
setLocation(appRoutes.list.makePath({ resourceType }))
32+
}}
33+
>
34+
{formatResourceName({
35+
resource: resourceType,
36+
format: 'title',
37+
count: 'plural'
38+
})}
39+
<Icon name='caretRight' />
40+
</ListItem>
41+
))}
42+
</List>
43+
</Spacer>
44+
</HomePageLayout>
45+
)
46+
}
47+
48+
export default Page
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { appRoutes } from '#data/routes'
2+
import {
3+
Icon,
4+
ListItem,
5+
PageLayout,
6+
type PageProps,
7+
Text,
8+
formatResourceName,
9+
useResourceList
10+
} from '@commercelayer/app-elements'
11+
import type { FC } from 'react'
12+
import { useLocation } from 'wouter'
13+
14+
const Page: FC<PageProps<typeof appRoutes.list>> = ({ params }) => {
15+
const { resourceType } = params
16+
const [, setLocation] = useLocation()
17+
const { ResourceList, isLoading } = useResourceList({
18+
type: resourceType,
19+
query: {
20+
pageSize: 25
21+
}
22+
})
23+
24+
if (isLoading) {
25+
return null
26+
}
27+
28+
return (
29+
<PageLayout
30+
title={formatResourceName({
31+
resource: resourceType,
32+
format: 'title',
33+
count: 'plural'
34+
})}
35+
navigationButton={{
36+
label: 'Select type',
37+
onClick: () => {
38+
setLocation(appRoutes.home.makePath({}))
39+
}
40+
}}
41+
>
42+
<ResourceList
43+
title='All'
44+
ItemTemplate={({ resource }) => {
45+
if (resource == null) {
46+
return null
47+
}
48+
return (
49+
<ListItem
50+
onClick={() => {
51+
setLocation(
52+
appRoutes.details.makePath({
53+
resourceType,
54+
resourceId: resource.id
55+
})
56+
)
57+
}}
58+
>
59+
<div>
60+
<Text tag='div' weight='semibold'>
61+
#{resource.id}
62+
</Text>
63+
<Text tag='div' variant='info'>
64+
{/* for customers */}
65+
{'email' in resource && resource.email}
66+
{/* for other markets and skus */}
67+
{'name' in resource && resource.name}
68+
{/* for other shipments */}
69+
{'number' in resource && resource.number}
70+
</Text>
71+
</div>
72+
<Icon name='caretRight' />
73+
</ListItem>
74+
)
75+
}}
76+
/>
77+
</PageLayout>
78+
)
79+
}
80+
81+
export default Page

0 commit comments

Comments
 (0)