diff options
Diffstat (limited to 'examples/hackernews/src/pages')
-rw-r--r-- | examples/hackernews/src/pages/[...stories].astro | 105 | ||||
-rw-r--r-- | examples/hackernews/src/pages/stories/[id].astro | 96 | ||||
-rw-r--r-- | examples/hackernews/src/pages/users/[id].astro | 69 |
3 files changed, 270 insertions, 0 deletions
diff --git a/examples/hackernews/src/pages/[...stories].astro b/examples/hackernews/src/pages/[...stories].astro new file mode 100644 index 000000000..fa227e0c1 --- /dev/null +++ b/examples/hackernews/src/pages/[...stories].astro @@ -0,0 +1,105 @@ +--- +import For from '../components/For.astro'; +import Show from '../components/Show.astro'; +import Story from '../components/Story.astro'; +import Layout from '../layouts/Layout.astro'; +import fetchAPI from '../lib/api'; +import type { IStory } from '../types.js'; + +const mapStories = { + top: 'news', + new: 'newest', + show: 'show', + ask: 'ask', + job: 'jobs', +}; + +function safeParseInt(value: any, fallback: number) { + try { + return parseInt(value) || fallback; + } catch { + return fallback; + } +} + +const page = safeParseInt(Astro.url.searchParams.get('page'), 1); +const type = + Astro.params.stories && Astro.params.stories in mapStories + ? (Astro.params.stories.toString() as keyof typeof mapStories) + : 'top'; + +const stories = (await fetchAPI(`${mapStories[type]}?page=${page}`)) as IStory[]; +--- + +<Layout> + <section> + <nav aria-labelledby="current-page"> + <Show when={page > 1}> + <a href={`/${type}?page=${page - 1}`} aria-label="Previous Page"> < prev</a> + <span slot="fallback" aria-disabled="true"> < prev</span> + </Show> + <span id="current-page">page {page}</span> + <Show when={stories?.length >= 29}> + <a href={`/${type}?page=${page + 1}`} aria-label="Next Page">more ></a> + <span slot="fallback" aria-disabled="true"> more ></span> + </Show> + </nav> + <main> + <Show when={stories}> + <ul> + <For each={stories}>{(story: IStory) => <Story story={story} />}</For> + </ul> + </Show> + </main> + </section> +</Layout> + +<style> + section { + padding-top: 45px; + } + + nav, + main { + background-color: rgb(248 250 252); + border-radius: 2px; + } + + nav { + padding: 15px 30px; + position: fixed; + text-align: center; + top: 55px; + left: 0; + right: 0; + z-index: 998; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); + } + + nav a { + margin: 0 1em; + } + + [aria-disabled='true'] { + color: rgb(71 85 105); + margin: 0 1em; + } + + main { + position: absolute; + margin: 30px 0; + width: 100%; + } + + ul { + list-style-type: none; + padding: 0; + margin: 0; + } + + @media (max-width: 600px) { + main { + margin: 10px 0; + } + } +</style> diff --git a/examples/hackernews/src/pages/stories/[id].astro b/examples/hackernews/src/pages/stories/[id].astro new file mode 100644 index 000000000..6cd17ea45 --- /dev/null +++ b/examples/hackernews/src/pages/stories/[id].astro @@ -0,0 +1,96 @@ +--- +import Comment from '../../components/Comment.astro'; +import For from '../../components/For.astro'; +import Show from '../../components/Show.astro'; +import Layout from '../../layouts/Layout.astro'; +import fetchAPI from '../../lib/api'; +import type { IComment, IStory } from '../../types.js'; + +const { id } = Astro.params as { id: string }; + +const story = (await fetchAPI(`item/${id}`)) as IStory; +--- + +<Layout> + <div> + <header> + <a href={story.url} target="_blank"> + <h1>{story.title}</h1> + </a> + <Show when={story.domain}> + <span class="host">({story.domain})</span> + </Show> + <p class="meta"> + {story.points} points | by + <a href={`/users/${story.user}`}> + {story.user} + </a> + {story.time_ago} ago + </p> + </header> + <main> + <p> + {story.comments_count ? story.comments_count + ' comments' : 'No comments yet.'} + </p> + <ul class="comment-children"> + <For each={story.comments}> + {(comment: IComment) => <Comment comment={comment} />} + </For> + </ul> + </main> + </div> +</Layout> + +<style> + header { + background-color: rgb(248 250 252); + padding: 1.8em 2em 1em; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); + } + + h1 { + display: inline; + font-size: 1.5em; + margin: 0; + margin-right: 0.5em; + } + + .host, + .meta, + .host a { + color: rgb(51 65 85); + } + + .meta a { + text-decoration: underline; + } + + main { + background-color: rgb(248 250 252); + margin-top: 10px; + padding: 0 2em 0.5em; + } + + main p { + margin: 0; + font-size: 1.1em; + padding: 1em 0; + position: relative; + } + + main :global(ul) { + list-style-type: none; + padding: 0; + margin: 0; + } + + @media (max-width: 600px) { + h1 { + font-size: 1.25em; + } + } + + ul :global(ul) { + margin-left: 1.5em; + } +</style> diff --git a/examples/hackernews/src/pages/users/[id].astro b/examples/hackernews/src/pages/users/[id].astro new file mode 100644 index 000000000..9b43c6958 --- /dev/null +++ b/examples/hackernews/src/pages/users/[id].astro @@ -0,0 +1,69 @@ +--- +import Show from '../../components/Show.astro'; +import Layout from '../../layouts/Layout.astro'; +import fetchAPI from '../../lib/api'; +import type { IUser } from '../../types.js'; + +const { id } = Astro.params as { id: string }; + +const user = (await fetchAPI(`user/${id}`)) as IUser; +--- + +<Layout> + <main> + <Show when={user}> + <Show when={!user.error}> + <h1 slot="fallback">User not found.</h1> + <h1>User : {user.id}</h1> + <ul class="meta"> + <li> + <span class="label">Created:</span> + {user.created} + </li> + <li> + <span class="label">Karma:</span> + {user.karma} + </li> + <Show when={user.about}> + <li set:html={user.about} class="about"></li>{' '} + </Show> + </ul> + <p> + <a href={`https://news.ycombinator.com/submitted?id=${user.id}`}>submissions</a> |{' '} + <a href={`https://news.ycombinator.com/threads?id=${user.id}`}>comments</a> + </p> + </Show> + </Show> + </main> +</Layout> + +<style> + main { + background-color: rgb(248 250 252); + box-sizing: border-box; + padding: 2em 3em; + } + + h1 { + margin: 0; + font-size: 1.5em; + } + + .meta { + list-style-type: none; + padding: 0; + } + + .label { + display: inline-block; + min-width: 4em; + } + + .about { + margin: 1em 0; + } + + p a { + text-decoration: underline; + } +</style> |