const mockArticleList = mockFetch(
() => [
{ id: '1', title: 'first' },
{ id: '2', title: 'second' },
],
'mockArticleList',
);
const mockArticleDetail = mockFetch(
({ id }) =>
({
'1': {
id: '1',
title: 'first',
content: 'long',
createdAt: '2011-10-05T14:48:00.000Z',
},
'2': {
id: '2',
title: 'second',
content: 'short',
createdAt: '2011-10-05T14:48:00.000Z',
},
}[id]),
'mockArticleDetail',
);
class ArticlePreview extends Entity {
readonly id: string = '';
readonly title: string = '';
pk() {
return this.id;
}
static get key() {
return 'Article';
}
}
const articleList = new Endpoint(mockArticleList, { schema: [ArticlePreview] });
class ArticleFull extends ArticlePreview {
readonly content: string = '';
readonly createdAt: Date = new Date(0);
static schema = {
createdAt: Date,
};
static validate(processedEntity) {
if (!Object.hasOwn(processedEntity, 'content')) return 'Missing content';
}
}
const articleDetail = new Endpoint(mockArticleDetail, {
schema: ArticleFull,
});
function ArticleDetail({ id, onHome }: { id: string; onHome: () => void }) {
const article = useResource(articleDetail, { id });
return (
<div>
<h4>
<a onClick={onHome} style={{cursor: 'pointer'}}><</a> {article.title}
</h4>
<div>
<p>{article.content}</p>
<div>
Created:{' '}
<time>
{Intl.DateTimeFormat('en-US', { dateStyle: 'medium' }).format(
article.createdAt,
)}
</time>
</div>
</div>
</div>
);
}
function ArticleList() {
const [route, setRoute] = React.useState<string>();
const articles = useResource(articleList, {});
if (!route) {
return (
<div>
{articles.map(article => (
<div key={article.pk()} onClick={() => setRoute(article.id)} style={{cursor: 'pointer'}}>
{article.title}
</div>
))}
</div>
);
}
return <ArticleDetail id={route} onHome={() => setRoute()} />;
}
render(<ArticleList />);