Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/subvisual/content-sub into …
Browse files Browse the repository at this point in the history
…rs/encapsulate-hub-head-block
  • Loading branch information
rccsousa committed Oct 4, 2024
2 parents f4f6c9e + 4046bfd commit 9c8133f
Show file tree
Hide file tree
Showing 39 changed files with 711 additions and 155 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Lint

on:
push:
branches: ["main"]
pull_request:
branches: ["main"]

jobs:
run-linters:
name: Run linters
runs-on: ubuntu-latest

steps:
- name: Check out Git repository
uses: actions/checkout@v2

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 22

- name: Install Node.js dependencies
run: npm install

- name: Run linters
run: npm run lint
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "7.45.4",
"react-router-dom": "5.3.4"
"react-router-dom": "5.3.4",
"react-share": "^5.1.0"
},
"devDependencies": {
"@next/eslint-plugin-next": "^13.1.6",
Expand Down
66 changes: 22 additions & 44 deletions src/app/(pages)/blogposts/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ import { notFound } from 'next/navigation'

import { Blogpost } from '../../../../payload/payload-types'
import { fetchDoc } from '../../../_api/fetchDoc'
import BlogpostContent from '../../../_blocks/Blogpost'
import { RecommendedContent } from '../../../_blocks/RecommendedContent'
import BlogpostChapters from '../../../_blocks/BlogpostChapters'
import BlogpostContent from '../../../_blocks/BlogpostContent'
import { RelatedContent } from '../../../_blocks/RelatedContent'
import { Subscribe } from '../../../_blocks/Subscribe'
import BackButton from '../../../_components/BackButton'
import ContentCard from '../../../_components/ContentCard'
import Categories from '../../../_components/Categories'
import PostSummary from '../../../_components/PostSummary'
import RecommendedPosts from '../../../_components/RecommendedPosts'
import Share from '../../../_components/Share'
import { getChapters } from '../../../_utilities/sanitizeAndAddChapters'
import styles from './styles.module.css'

export default async function BlogpostPage({ params: { slug } }) {
const blogpost: Blogpost | null = await fetchDoc({
Expand All @@ -16,63 +21,36 @@ export default async function BlogpostPage({ params: { slug } }) {
})

// TODO: implement a fetcher for related content to populate related cards

if (!blogpost) {
notFound()
}

const { relatedPosts } = blogpost
// instead of destructuring post multiple times, destructure just once here?
const { content_html, categories, relatedPosts } = blogpost
const chapters = getChapters(content_html)

return (
<div>
<div style={{ background: 'purple' }}>
<div className={styles.headContainer}>
{/* Head Block*/}
<BackButton />
<BackButton className={styles.backButton} color={'var(--soft-white-100)'} />
<PostSummary post={blogpost} />
</div>
<div style={{ display: 'flex' }}>
<div className={styles.contentContainer}>
{/* Left column: Navigation */}
<div
style={{
background: 'white',
color: 'black',
flex: '1',
padding: '10px',
borderRight: '1px solid black',
}}
>
<h1>Table of contents block</h1>
</div>
<BlogpostChapters chapters={chapters} />

{/* Middle column: Content block */}
<div style={{ background: 'white', color: 'black', flex: '2', padding: '10px' }}>
<BlogpostContent post={blogpost} />
</div>
<BlogpostContent post={blogpost} />

{/* Right column: Social sharing & recommended */}
<div
style={{
background: 'white',
color: 'black',
flex: '1',
padding: '10px',
borderLeft: '1px solid black',
}}
>
<div>
<h1>Share block goes here</h1>
<p>SocialMedia block with links</p>
</div>
<div>
<h1>Category block</h1>
</div>
<div>
<h1>Recommended Block</h1>
<ContentCard contentType={'Blogpost'} content={blogpost} />
<ContentCard contentType={'Blogpost'} content={blogpost} />
</div>
<div className={styles.sharingAndCategories}>
<Share />
<Categories categories={categories} />
<RecommendedPosts posts={relatedPosts} />
</div>
</div>
<RecommendedContent relatedContent={relatedPosts} />
<RelatedContent relatedContent={relatedPosts} />
<Subscribe />
</div>
)
Expand Down
58 changes: 58 additions & 0 deletions src/app/(pages)/blogposts/[slug]/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@

.headContainer {
background-color: var(--sub-purple-400);
color: var(--soft-white-100);
border-bottom-right-radius: 16px;
border-bottom-left-radius: 16px;
padding-left: 15px;
padding-right: 15px;
}

.backButton {
display: block;
font-family: Colfax, sans-serif;
padding-top: 40px;
padding-left: 15px;
padding-bottom: 40px;
}


.contentContainer {
display: grid;
grid-template-rows: 2fr;
font-family: var(--colfax);
padding-bottom: 40px;
}

.sharingAndCategories {
grid-row-start: 1;
}

@media (min-width: 1080px) {

.headContainer {
width: calc(100% - 40px);
margin: 0 auto;
}

.backButton {
padding-left: 95px;
color: var(--soft-white-100);
}

.contentContainer {
width: calc(100% - 40px);
margin: 20px auto;
display: grid;
grid-template-columns: 0.3fr 0.6fr 0.3fr;
}

.sharingAndCategories {
justify-content: left;
padding-left: 40px;
grid-column: 3 / 3;
}

}


4 changes: 2 additions & 2 deletions src/app/(pages)/podcast-episodes/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { notFound } from 'next/navigation'
import { fetchDoc } from '../../../_api/fetchDoc'
import EpisodeContent from '../../../_blocks/EpisodeContent'
import EpisodeHead from '../../../_blocks/EpisodeHead'
import { RecommendedContent } from '../../../_blocks/RecommendedContent'
import { RelatedContent } from '../../../_blocks/RelatedContent'
import { Subscribe } from '../../../_blocks/Subscribe'

export default async function PodcastEpisodesPage({ params: { slug } }) {
Expand Down Expand Up @@ -31,7 +31,7 @@ export default async function PodcastEpisodesPage({ params: { slug } }) {
<div>
<EpisodeHead episode={episode} />
<EpisodeContent episode={episode} />
<RecommendedContent relatedContent={relatedEpisodes} />
<RelatedContent relatedContent={relatedEpisodes} />
<Subscribe />
</div>
</div>
Expand Down
17 changes: 0 additions & 17 deletions src/app/_blocks/Blogpost/index.tsx

This file was deleted.

55 changes: 55 additions & 0 deletions src/app/_blocks/BlogpostChapters/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
'use client'

import { useEffect, useState } from 'react'

import styles from './styles.module.css'

export default function BlogpostChapters({ chapters }) {
const [visibleChapter, setVisibleChapter] = useState(null)

useEffect(() => {
const observer = new IntersectionObserver(
entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
setVisibleChapter(entry.target.id) // Update state with the visible chapter's ID
}
})
},
{ threshold: 0.1 }, // Trigger when 10% of the element is visible
)

const chapters = document.querySelectorAll('[id^="chapter"]')
chapters.forEach(chapter => observer.observe(chapter))

// unmount
return () => {
chapters.forEach(chapter => observer.unobserve(chapter))
}
}, [])

return (
<div className={styles.container}>
<div className={styles.navbar}>
<p className={`outline ${styles.title}`}>CHAPTER</p>
<ul>
{chapters.map((chapter, i) => (
<a href={`#${chapter.id}`}>
<li
style={{
borderColor:
visibleChapter === chapter.id
? 'var(--sub-purple-400)'
: 'var(--soft-white-100)',
}}
key={i}
>
{chapter.title}
</li>
</a>
))}
</ul>
</div>
</div>
)
}
30 changes: 30 additions & 0 deletions src/app/_blocks/BlogpostChapters/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.container {
display: none;
}

@media(min-width: 1024px) {
.container {
display: flex;
flex-direction: column;
grid-template-columns: repeat(2, 1fr);
width: 100%;
gap: 20px;
padding: 20px 50px;
}

.container ul {
margin-top: 20px;
list-style: none;
padding: 0;
}

.container li {
border-left: 4px solid;
padding: 10px 20px;
}

.navbar {
position: sticky;
top: 20px;
}
}
19 changes: 19 additions & 0 deletions src/app/_blocks/BlogpostContent/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use client'

import { Blogpost } from '../../../payload/payload-types'
import FeaturedImage from '../../_components/FeaturedImage'
import { sanitizeAndAddChapters } from '../../_utilities/sanitizeAndAddChapters'
import styles from './styles.module.css'

export default function BlogpostContent({ post }: { post: Blogpost }) {
const { summary, content_html, featuredImage } = post
const sanitizedContent = sanitizeAndAddChapters(content_html)

return (
<div className={styles.container}>
<FeaturedImage className={styles.featuredImage} src={featuredImage} />
<div className={styles.summary}>{summary}</div>
<div className={styles.content} dangerouslySetInnerHTML={{ __html: sanitizedContent }} />
</div>
)
}
25 changes: 25 additions & 0 deletions src/app/_blocks/BlogpostContent/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.container {
width: 100%;
padding: 20px;
}

.featuredImage {
margin: auto;
border-radius: 45px;
}

.summary {
font-size: var(--size-18);
margin: 20px auto;
}

.content {
display: flex;
flex-direction: column;
gap: 20px;
text-align: justify;
word-wrap: break-word;
white-space: normal;
overflow-wrap: break-word;
}

Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import Link from 'next/link'

export function RecommendedContent({ relatedContent }) {
import styles from './styles.module.css'

import ContentCard from '@/app/_components/ContentCard'
export function RelatedContent({ relatedContent }) {
return (
<div style={{ backgroundColor: '#F6F6F6', color: '#403F4C', marginTop: '20px' }}>
<h1>You may also like</h1>
<div className={styles.container}>
<h5>You may also like</h5>
<div
style={{
display: 'grid',
Expand All @@ -12,8 +15,8 @@ export function RecommendedContent({ relatedContent }) {
}}
>
{relatedContent.map((contentPiece, i) => (
<div key={i} style={{ border: 'black solid 1px', padding: '16px' }}>
Content card placeholder
<div key={i} className={styles.contentCard}>
<ContentCard contentType={'Blogpost'} content={contentPiece} />
<br />
<Link href={`${contentPiece.slug}`}>{contentPiece.title}</Link>
</div>
Expand Down
Loading

0 comments on commit 9c8133f

Please sign in to comment.