completed categories feature
This commit is contained in:
parent
03f01f65d3
commit
9f2b80a924
@ -3,7 +3,7 @@ import mongoose from 'mongoose';
|
|||||||
const { Schema } = mongoose;
|
const { Schema } = mongoose;
|
||||||
const CategorySchema = new Schema({
|
const CategorySchema = new Schema({
|
||||||
name: { type: String, required: true, index: { unique: true } },
|
name: { type: String, required: true, index: { unique: true } },
|
||||||
slug: { type: String, required: true, index: { unique: true } }
|
slug: { type: String, index: { unique: true } }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,11 +4,11 @@ import Category from '../../models/category.js';
|
|||||||
export async function get(req, res)
|
export async function get(req, res)
|
||||||
{
|
{
|
||||||
let { slug } = req.params;
|
let { slug } = req.params;
|
||||||
let articles;
|
let articles, cat;
|
||||||
if (slug === 'all') {
|
if (slug === 'all') {
|
||||||
articles = await Article.find().sort({ created_at: 'desc' });
|
articles = await Article.find().sort({ created_at: 'desc' }).populate({ path: 'category' });
|
||||||
} else {
|
} else {
|
||||||
let cat = await Category.findOne({ slug });
|
cat = await Category.findOne({ slug });
|
||||||
if (!cat) {
|
if (!cat) {
|
||||||
res.writeHead(404, {
|
res.writeHead(404, {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
@ -18,11 +18,13 @@ export async function get(req, res)
|
|||||||
}));
|
}));
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
articles = await Article.find({ category: cat.id }).sort({ created_at: 'desc' });
|
articles = await Article.find({ category: cat.id })
|
||||||
|
.sort({ created_at: 'desc' })
|
||||||
|
.populate({ path: 'category' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.writeHead(200, {
|
res.writeHead(200, {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
});
|
});
|
||||||
res.end(JSON.stringify(articles));
|
res.end(JSON.stringify({ category: cat, articles }));
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,70 @@
|
|||||||
|
<script context="module">
|
||||||
|
export async function preload({ params, query }) {
|
||||||
|
if (params.slug === 'all') {
|
||||||
|
this.redirect(302, '/');
|
||||||
|
}
|
||||||
|
const res = await this.fetch(`c/${params.slug}.json`);
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (res.status === 200) {
|
||||||
|
return {
|
||||||
|
articles: data.articles,
|
||||||
|
category: data.category
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
this.error(res.status, data.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>{category.name} Articles | HOWFEED.BIZ</title>
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
h1 {
|
||||||
|
margin: 0 auto;
|
||||||
|
color: whitesmoke;
|
||||||
|
margin-top: 1rem;
|
||||||
|
font-size: 2rem;
|
||||||
|
font-size: 3rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
@media (min-width: 800px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 4rem !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 1280px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 8rem !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export let articles;
|
||||||
|
export let category;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="background"></div>
|
||||||
|
<div class="floaty">
|
||||||
|
<h1>{category.name}</h1>
|
||||||
|
<div class="article-list">
|
||||||
|
{#each articles as {title, slug, image, created_at}}
|
||||||
|
<a rel="prefetch" href={`/a/${slug}`}>
|
||||||
|
<figure class="article-image">
|
||||||
|
<img src={image || '/logo.png'} alt={title}>
|
||||||
|
</figure>
|
||||||
|
<div class="article-meta">
|
||||||
|
<p class="article-title">{title}</p>
|
||||||
|
<p class="article-date">{new Date(created_at).toLocaleDateString()}</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{:else}
|
||||||
|
<p>No articles are in this category :(</p>
|
||||||
|
<p>Check back soon!</p>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -70,7 +70,7 @@
|
|||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ html, image, title })
|
body: JSON.stringify({ html, image, title, category })
|
||||||
});
|
});
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
goto(`/a/${json.slug}`);
|
goto(`/a/${json.slug}`);
|
||||||
@ -89,6 +89,7 @@
|
|||||||
body: JSON.stringify({ name })
|
body: JSON.stringify({ name })
|
||||||
});
|
});
|
||||||
categories = await res.json();
|
categories = await res.json();
|
||||||
|
category = categories.filter(c => c.name === name)[0].slug;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
export async function preload()
|
export async function preload()
|
||||||
{
|
{
|
||||||
const res = await this.fetch(`/c/all.json`);
|
const res = await this.fetch(`/c/all.json`);
|
||||||
const articles = await res.json();
|
const { articles } = await res.json();
|
||||||
return { articles };
|
return { articles };
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -19,22 +19,7 @@
|
|||||||
h1, h2, p {
|
h1, h2, p {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
h1 {
|
|
||||||
font-size: 3rem;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
figure {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
img {
|
|
||||||
object-fit: contain;
|
|
||||||
max-width: 100%;
|
|
||||||
margin: 1rem;
|
|
||||||
}
|
|
||||||
@media (min-width: 800px) {
|
@media (min-width: 800px) {
|
||||||
div.homepage {
|
|
||||||
padding-top: 5rem !important;
|
|
||||||
}
|
|
||||||
h1.welcome {
|
h1.welcome {
|
||||||
font-size: 8rem !important;
|
font-size: 8rem !important;
|
||||||
}
|
}
|
||||||
@ -50,42 +35,19 @@
|
|||||||
font-size: 3.5rem !important;
|
font-size: 3.5rem !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
div.background {
|
|
||||||
background: url('/cityscape.jpg') no-repeat center;
|
|
||||||
background-size: cover;
|
|
||||||
position: fixed;
|
|
||||||
height: 24rem;
|
|
||||||
width: 100%;
|
|
||||||
z-index: 0;
|
|
||||||
filter: blur(5px);
|
|
||||||
}
|
|
||||||
div.homepage {
|
|
||||||
padding-top: 8rem;
|
|
||||||
padding-bottom: 4rem;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1;
|
|
||||||
margin: 0 auto;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
h1.welcome, h2.desc {
|
h1.welcome, h2.desc {
|
||||||
color: whitesmoke;
|
color: whitesmoke;
|
||||||
}
|
}
|
||||||
h1.welcome {
|
h1.welcome {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
font-size: 3.75rem;
|
font-size: 3.75rem;
|
||||||
}
|
font-size: 3rem;
|
||||||
h2 {
|
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
h2.desc {
|
h2.desc {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
}
|
text-transform: uppercase;
|
||||||
div.article-list {
|
|
||||||
box-shadow: 0 0 5px #000;
|
|
||||||
}
|
|
||||||
div.article-meta {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@ -94,7 +56,7 @@
|
|||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<div class="background"></div>
|
<div class="background"></div>
|
||||||
<div class="homepage">
|
<div class="floaty">
|
||||||
<h1 class="welcome">Welcome</h1>
|
<h1 class="welcome">Welcome</h1>
|
||||||
<h2 class="desc">Find an Article</h2>
|
<h2 class="desc">Find an Article</h2>
|
||||||
<div class="article-list">
|
<div class="article-list">
|
||||||
@ -110,7 +72,7 @@
|
|||||||
</a>
|
</a>
|
||||||
{:else}
|
{:else}
|
||||||
<p>No articles have been published yet :(</p>
|
<p>No articles have been published yet :(</p>
|
||||||
<p>Come back soon!</p>
|
<p>Chcek back soon!</p>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -257,10 +257,10 @@ express()
|
|||||||
}
|
}
|
||||||
const cat = await new Category({ name });
|
const cat = await new Category({ name });
|
||||||
await cat.save();
|
await cat.save();
|
||||||
|
const categories = await Category.find();
|
||||||
res.writeHead(200, {
|
res.writeHead(200, {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
});
|
});
|
||||||
const categories = await Category.find();
|
|
||||||
res.end(JSON.stringify(categories));
|
res.end(JSON.stringify(categories));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res.writeHead(500, {
|
res.writeHead(500, {
|
||||||
|
@ -80,10 +80,14 @@ figure.article-image {
|
|||||||
align-self: center;
|
align-self: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 33.33%;
|
width: 33.33%;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
figure.article-image img {
|
figure.article-image img {
|
||||||
height: 6rem;
|
height: 6rem;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
object-fit: contain;
|
||||||
|
max-width: 100%;
|
||||||
|
margin: 1rem;
|
||||||
}
|
}
|
||||||
div.article-meta {
|
div.article-meta {
|
||||||
margin: 1rem;
|
margin: 1rem;
|
||||||
@ -95,9 +99,11 @@ div.article-meta {
|
|||||||
}
|
}
|
||||||
.article-title {
|
.article-title {
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
.article-date {
|
.article-date {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
@ -105,3 +111,34 @@ div.article-meta {
|
|||||||
margin: 8rem 0;
|
margin: 8rem 0;
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.background {
|
||||||
|
background: url('/cityscape.jpg') no-repeat center;
|
||||||
|
background-size: cover;
|
||||||
|
position: fixed;
|
||||||
|
height: 24rem;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 0;
|
||||||
|
filter: blur(5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
div.article-list {
|
||||||
|
box-shadow: 0 0 5px #000;
|
||||||
|
}
|
||||||
|
div.article-meta {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.floaty {
|
||||||
|
padding-top: 8rem;
|
||||||
|
padding-bottom: 4rem;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
@media (min-width: 800px) {
|
||||||
|
div.floaty {
|
||||||
|
padding-top: 5rem !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user