Skip to content

Instantly share code, notes, and snippets.

@ndugger
Last active April 18, 2021 00:10
Show Gist options
  • Save ndugger/616d5102414e05d609dd102cb82f7fdc to your computer and use it in GitHub Desktop.
Save ndugger/616d5102414e05d609dd102cb82f7fdc to your computer and use it in GitHub Desktop.
import {
Application,
Fetch,
Route,
Router,
Theme,
Viewport,
createElement,
createStyleSheet
} from 'yuzu'
import { Flexbox } from './components/Flexbox'
import { Modal } from './components/Modal'
import { AboutPage } from './pages/AboutPage'
import { ArticlePage } from './pages/ArticlePage'
import { AuthorPage } from './pages/AuthorPage'
import { ContactPage } from './pages/ContactPage'
import { NewsPage } from './pages/NewsPage'
import { IndexPage } from './pages/IndexPage'
import { VideosPage } from './pages/VideosPage'
import { WatchPage } from './pages/WatchPage'
/**
* Application-level constants
* (Could potentially be retrieved from process.env)
*/
const APPLICATION_TITLE = 'Example App'
const APPLICATION_DESCRIPTION = 'Short description of application'
const APPLICATION_CSS = '...'
/**
* Application-level component
*/
export class ExampleApp extends Application {
/**
* Assign application metadata and global context providers
*/
protected configure() {
return [
<Application title={ APPLICATION_TITLE }>
<Application.Meta name='description' content={ APPLICATION_DESCRIPTION }/>
<Application.Meta name='viewport' content='width=device-width, initial-scale=1'/>
<Application.Meta name='color-scheme' content='dark'/>
<Application.Style textContent={ APPLICATION_CSS }/>
<Application.Context>
<Fetch/>
<Viewport/>
<Theme/>
<Router/>
</Application.Context>
</Application>
]
}
/**
* Render application layout and routes with templates
*/
protected render() {
return [
<Flexbox align={ Flexbox.Alignment.Center } direction={ Flexbox.Direction.Column } grow>
<Route path='/' template={ IndexPage }/>
<Route path='/about' template={ AboutPage }/>
<Route path='/authors' switch>
<Route path='/{ authorId }/{ authorSlug }' template={ AuthorPage }/>
</Route>
<Route path='/contact' template={ ContactPage }/>
<Route path='/news' switch>
<Route path='/' template={ NewsPage }/>
<Route path='/{ articleId }/{ articleSlug }' template={ ArticlePage }/>
</Route>
<Route path='/videos' switch>
<Route path='/' template={ VideosPage }/>
<Route path='/{ videoId }/{ videoSlug }' template={ WatchPage }/>
</Route>
<Modal.Portal/>
</Flexbox>
]
}
}
import {
Component,
Fragment,
createElement,
useRouter
} from 'yuzu'
import { useArticles } from '../hooks/useArticles'
import { useVideos } from '../hooks/useVideos'
import { routeToArticlePage } from '../utilities/routeToArticlePage'
import { routeToVideoPage } from '../utilities/routeToVideoPage'
import { Container } from '../components/Container'
import { Flexbox } from '../components/Flexbox'
import { Footer } from '../components/Footer'
import { Grid } from '../components/Grid'
import { Header } from '../components/Header'
import { Indicator } from '../components/Indicator'
import { Section } from '../components/Section'
import { Spacer } from '../components/Spacer'
import { Transition } from '../components/Transition'
import { Typography } from '../components/Typography'
import { FeaturedArticle } from '../templates/FeaturedArticle'
import { FeaturedExcerpt } from '../templates/FeaturedExcerpt'
import { FeaturedVideo } from '../templates/FeaturedVideo'
/**
* Page-level constants
* (Could potentially be retrieved from process.env)
*/
const GAP_PX = 40
const LATEST_FINDINGS = 'Latest Findings'
const LATEST_FINDINGS_GLYPH = 'base-station-fill'
const ON_DEMAND = 'On Demand'
const ON_DEMAND_GLYPH = 'play-circle-fill'
/**
* Example index page template using a functional component
*/
export const IndexPage: Component.Fn = () => {
const router = useRouter()
const articles = useArticles(10, 0)
const videos = useVideos(10, 0)
/**
* While fetch requests are pending, render a loading indicator (spinner)
*/
if ([ articles, videos ].some(req => req.pending)) return [
<Flexbox align={ Flexbox.Alignment.Center } grow justify={ Flexbox.Alignment.Center }>
<Indicator/>
</Flexbox>
]
/**
* If any fetch requests came back with error responses, render the error messages
*/
if ([ articles, videos ].some(req => req.error)) return [
<Flexbox align={ Flexbox.Alignment.Center } grow justify={ Flexbox.Alignment.Center }>
<Typography variant={ Typography.Variant.Heading }>
{ [ articles, videos ].filter(req => req.error).map(req => req.error.message) }
</Typography>
</Flexbox>
]
/**
* Finally, render page content
*/
return [
<Transition>
<Header/>
<Container padding={ 24 }>
<Section glyph={ LATEST_FINDINGS_GLYPH } heading={ LATEST_FINDINGS }>
<Grid columns={ 3 } gap={ GAP_PX }>
<Fragment>
{ articles.data.slice(0, 3).map(article => (
<FeaturedArticle
article={ article }
onclick={ () => routeToArticlePage(router, article) }/>
)) }
</Fragment>
</Grid>
<Spacer height={ GAP_PX }/>
<Grid columns={ 4 } gap={ GAP_PX }>
<Fragment>
{ articles.data.slice(0, 4).map(article => (
<FeaturedArticle
article={ article }
onclick={ () => routeToArticlePage(router, article) }/>
)) }
</Fragment>
</Grid>
<Spacer height={ GAP_PX }/>
<Grid columns={ 2 } gap={ GAP_PX }>
<Fragment>
{ articles.data.slice(0, 2).map(article => (
<FeaturedArticle
article={ article }
listing
onclick={ () => routeToArticlePage(router, article) }/>
)) }
</Fragment>
</Grid>
<Spacer height={ GAP_PX }/>
<Grid columns={ 3 } gap={ GAP_PX }>
<Container>
<Grid columns={ 1 } gap={ GAP_PX }>
<Fragment>
{ articles.data.slice(0, 4).map(article => (
<FeaturedExcerpt article={ article }/>
)) }
</Fragment>
</Grid>
</Container>
<Grid.Tile columnEnd='span 2' columnStart='2' rowEnd='span'>
<Section glyph={ ON_DEMAND_GLYPH } heading={ ON_DEMAND }>
<Grid columns={ 2 } gap={ GAP_PX }>
<Fragment>
{ videos.data.slice(0, 4).map(video => (
<FeaturedVideo
landscape
onclick={ () => routeToVideoPage(router, video) }
video={ video }/>
)) }
</Fragment>
</Grid>
</Section>
</Grid.Tile>
</Grid>
</Section>
</Container>
<Footer/>
</Transition>
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment