Skip to content

Commit

Permalink
Merge pull request #12 from krckyboy/#10
Browse files Browse the repository at this point in the history
  • Loading branch information
krckyboy authored Jan 22, 2024
2 parents ca78a9b + bbc5828 commit 8e0ee6c
Show file tree
Hide file tree
Showing 34 changed files with 455 additions and 221 deletions.
1 change: 0 additions & 1 deletion next/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ const path = require('path');

/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
webpack: (config) => {
config.resolve.alias['@'] = path.join(__dirname, 'src');
return config;
Expand Down
10 changes: 10 additions & 0 deletions next/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
},
"dependencies": {
"@types/nprogress": "^0.2.3",
"date-fns": "^3.2.0",
"next": "14.0.4",
"nprogress": "^0.2.0",
"path": "^0.12.7",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ import React, { FunctionComponent } from 'react';
import ReactMarkdown from 'react-markdown';
import rehypeHighlight from 'rehype-highlight';
import rehypeCodeTitles from 'rehype-code-titles';

import 'highlight.js/styles/github-dark-dimmed.css';
import './styles.scss';

interface Props {
markdown: string;
}

const BlogContent: FunctionComponent<Props> = async ({ markdown }) => {
return (
<div style={{ maxWidth: '100%', overflowX: 'auto' }}>
<section className={'blog-content'}>
<ReactMarkdown rehypePlugins={[rehypeCodeTitles, rehypeHighlight]}>{markdown}</ReactMarkdown>
</div>
</section>
);
};

Expand Down
47 changes: 47 additions & 0 deletions next/src/app/blog/[slug]/blog-content/styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
@import '@/styles/vars';

.blog-content {
overflow-x: hidden;
max-width: 100%;

h2 {
margin-bottom: 1.1rem;
font-weight: 500;
font-size: clamp(1.4rem, 1.1vw, 1.6rem);
}

p, ul, ol {
margin-bottom: 1.1rem;
}

img {
max-width: 100%;
}

.rehype-code-title {
background-color: darken($color-background, 2%);
color: lighten($color-background, 35%);
padding: .5em;
padding-inline: 1em;
}

pre {
font-size: clamp(1rem, .8vw, 1.2rem);
margin-bottom: 1.1rem;
}

ul {
list-style-type: disc;
}

ol {
list-style-type: decimal;
}

ul, ol {
display: flex;
flex-direction: column;
row-gap: 1rem;
padding-left: 1.5rem;
}
}
30 changes: 30 additions & 0 deletions next/src/app/blog/[slug]/blog-footer/BlogFooter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React, { FunctionComponent } from 'react';
import styles from './styles.module.scss';
import gStyles from '@/styles/global.module.scss';
import Image from 'next/image';
import Link from 'next/link';

const BlogFooter: FunctionComponent = () => {
return (
<footer className={styles.container}>
<Link href={'/'} className={styles.linkContainer}>
<Image src={'/images/dusan.png'}
priority
alt={'Dušan Todorović in a formal white shirt'}
width={80}
height={80}
className={styles.image}
/>
<section className={styles.textContainer}>
<h4 className={styles.writtenBy}>written by</h4>
<span className={styles.name}>Dušan Todorović</span>
<p className={gStyles.tagsMini}>
Developer <span>|</span> Team Leader <span>|</span> React Specialist
</p>
</section>
</Link>
</footer>
);
};

export default BlogFooter;
39 changes: 39 additions & 0 deletions next/src/app/blog/[slug]/blog-footer/styles.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
@import '@/styles/vars';

.container {
display: flex;
width: 100%;
margin-top: 3rem;
padding-top: 3rem;
border-top: solid lighten($color-background, 3%) 6px;

.linkContainer {
display: flex;

.image {
min-width: 70px;
width: 70px;
height: 70px;
object-fit: cover;
border-radius: 5000px;

@media (min-width: 420px) {
width: 80px;
height: 80px;
}
}

.textContainer {
margin-left: 1rem;

.writtenBy {
color: lighten($color-background, 35%);
font-size: clamp(1rem, .9vw, 3rem);
}

.name {
font-weight: 500;
}
}
}
}
26 changes: 26 additions & 0 deletions next/src/app/blog/[slug]/blog-header/BlogHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React, { FunctionComponent } from 'react';
import gStyles from '@/styles/global.module.scss';
import { Post } from '@/components/blog-post-item/types';

interface Props {
post: Post;
}

const BlogHeader: FunctionComponent<Props> = ({ post }) => {
const categories = post.attributes.categories?.data;

return (
<header>
<h1 className={`${gStyles.pageHeadingMini}`}>{post.attributes.title}</h1>
{categories && (
<ul>
{categories.map((category) => (
<li key={category.id}>{category.attributes.name}</li>
))}
</ul>
)}
</header>
);
};

export default BlogHeader;
41 changes: 26 additions & 15 deletions next/src/app/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import React from 'react';
import { NextPage } from 'next';
import gStyles from '@/styles/global.module.scss';
import { Metadata } from 'next';
import BlogContent from '@/app/blog/[slug]/blog-content/BlogContent';
import { db } from '@/scripts/fetch';
import './styles.scss';
import BlogContent from '@/app/blog/[slug]/BlogContent';
import gStyles from '@/styles/global.module.scss';
import './blog-content/styles.scss';
import BlogHeader from '@/app/blog/[slug]/blog-header/BlogHeader';
import BlogFooter from '@/app/blog/[slug]/blog-footer/BlogFooter';

interface Props {
params: {
Expand All @@ -14,23 +17,20 @@ interface Props {
const Page: NextPage<Props> = async (props) => {
const { slug } = props.params;
const { data: [post] } = await db.getPostBySlug(slug);
const categories = post?.attributes?.categories?.data;

return (
<article className={`${gStyles.section} ${gStyles.paddingInline} blog-post`}>
<h1 className={gStyles.pageHeadingMini}>{post.attributes.title}</h1>
{categories && (
<ul>
{categories.map((category) => (
<li key={category.id}>{category.attributes.name}</li>
))}
</ul>
)}
<BlogContent markdown={post.attributes.content} />
</article>
<main>
<article className={`${gStyles.section} ${gStyles.paddingInline} ${gStyles.text}`}>
<BlogHeader post={post} />
<BlogContent markdown={post.attributes.content} />
<BlogFooter />
</article>
</main>
);
};

export const revalidate = 3600;

export async function generateStaticParams() {
const posts = await db.getPostSlugs();
const slugs = posts.data.map((post) => post.attributes.slug);
Expand All @@ -40,4 +40,15 @@ export async function generateStaticParams() {
}));
}

export async function generateMetadata(
{ params: { slug } }: Props
): Promise<Metadata> {
const { data: [post] } = await db.getPostBySlug(slug);

return {
title: post.attributes.title,
description: post.attributes.summary
};
}

export default Page;
27 changes: 0 additions & 27 deletions next/src/app/blog/[slug]/styles.scss

This file was deleted.

13 changes: 10 additions & 3 deletions next/src/app/blog/page.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import { NextPage } from 'next';
import gStyles from '../../styles/global.module.scss';
import BlogPostItem from '../../components/blog-post-item/BlogPostItem';
import gStyles from '@/styles/global.module.scss';
import styles from './styles.module.scss';
import BlogPostItem from '@/components/blog-post-item/BlogPostItem';
import React from 'react';
import { db } from '@/scripts/fetch';

const Page: NextPage = async () => {
const posts = await db.getPosts();
const categories = await db.getCategories();

return (
<main>
<section className={`${gStyles.section} ${gStyles.paddingInline}`}>
<h1 className={gStyles.pageHeading}>Blog</h1>
<div className={gStyles.blogs}>
<ul className={styles.categories}>
{categories.data.map((category) => (
<li key={category.id}>#{category.attributes.name}</li>
))}
</ul>
<div className={`${gStyles.blogs} ${styles.blogs}`}>
{posts.data.map((post) => <BlogPostItem post={post} key={post.id} />)}
</div>
</section>
Expand Down
17 changes: 17 additions & 0 deletions next/src/app/blog/styles.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@import '@/styles/vars';

.blogs {
margin-top: 3rem;
gap: 3rem;
}

.categories {
margin-top: 2rem;
justify-content: flex-start;
display: flex;
gap: .5rem;

li {
color: darken($color-text, 40%);
}
}
2 changes: 1 addition & 1 deletion next/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import LoadingIndicator from '@/components/loading-indicator/LoadingIndicator';
const leagueSpartan = League_Spartan({ subsets: ['latin'] });

export const metadata: Metadata = {
title: 'dtodorovic.com',
title: 'Dušan Todorović - Developer | Team Leader | React Specialist',
description: 'Created by Dušan Todorović'
};

Expand Down
22 changes: 4 additions & 18 deletions next/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,13 @@
import React from 'react';
import { NextPage } from 'next';
import ImageAndText from '../components/image-and-text/ImageAndText';
import styles from './styles.module.scss';
import gStyles from '../styles/global.module.scss';
import BlogPostItem from '@/components/blog-post-item/BlogPostItem';
import Link from 'next/link';
import { db } from '@/scripts/fetch';
import ImageAndText from '@/components/home-components/image-and-text/ImageAndText';
import FeaturedPosts from '@/components/home-components/featured-posts/FeaturedPosts';

const Page: NextPage = async () => {
const posts = await db.getFeaturedPosts();

return (
<main>
<section className={`${gStyles.section} ${gStyles.paddingInline}`}>
<ImageAndText />
</section>
<section className={`${gStyles.section} ${gStyles.paddingInline}`}>
<h2 className={`${styles.featuredPostsHeading} ${gStyles.pageHeadingMini}`}>Featured posts</h2>
<div className={gStyles.blogs}>
{posts.data.map((post) => <BlogPostItem post={post} key={post.id} featured />)}
<Link href={'/blog'} className={styles.checkAllPosts}>Check all</Link>
</div>
</section>
<ImageAndText />
<FeaturedPosts />
</main>
);
};
Expand Down
Loading

0 comments on commit 8e0ee6c

Please sign in to comment.