Skip to content

Commit

Permalink
Merge pull request #868 from CodeForAfrica/ft/render-blog
Browse files Browse the repository at this point in the history
ft/Engineering Blog: Render a blog
  • Loading branch information
kelvinkipruto authored Sep 7, 2024
2 parents 1293a12 + 2276210 commit 8876e47
Show file tree
Hide file tree
Showing 29 changed files with 3,623 additions and 1,603 deletions.
7 changes: 6 additions & 1 deletion apps/engineeringblog/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
module.exports = {
root: true,
extends: ["next/core-web-vitals", "plugin:prettier/recommended"],
extends: [
"next/core-web-vitals",
"plugin:prettier/recommended",
"plugin:mdx/recommended",
],
settings: {
"import/resolver": {
webpack: {
config: "./eslint.webpack.config.js",
},
},
"mdx/code-blocks": true,
},
};
12 changes: 12 additions & 0 deletions apps/engineeringblog/app/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ArticleContent } from "@/engineeringblog/components/Article";
import { Box } from "@mui/material";
import { getContent } from "@/engineeringblog/utils";

export default async function Page({ params }: { params: { slug: string } }) {
const post = await getContent(params.slug);
return (
<Box component="article">
<ArticleContent article={post} />
</Box>
);
}
3 changes: 0 additions & 3 deletions apps/engineeringblog/app/articles/page.tsx

This file was deleted.

17 changes: 0 additions & 17 deletions apps/engineeringblog/app/articles/sample-1/demo-1.tsx

This file was deleted.

14 changes: 0 additions & 14 deletions apps/engineeringblog/app/articles/sample-1/page.mdx

This file was deleted.

22 changes: 18 additions & 4 deletions apps/engineeringblog/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
import { Box, Container } from "@mui/material";
import { Container } from "@mui/material";
import { ArticleList } from "@/engineeringblog/components/Article";
import { getAllContents } from "@/engineeringblog/utils";
import NoPosts from "@/engineeringblog/components/NoPosts";

export default async function index() {
const posts = await getAllContents();

if (!posts.length) {
return <NoPosts />;
}

export default function index() {
return (
<Container>
<Box minHeight="1000px">Homepage</Box>
<Container
sx={{
px: { xs: 2.5, sm: 0 },
py: { xs: 2.5, sm: 5 },
}}
>
<ArticleList articles={posts} />
</Container>
);
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
57 changes: 57 additions & 0 deletions apps/engineeringblog/components/Article/ArticleCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"use client";
import { StyledLink } from "@/commons-ui/next/Link";
import { ArticleWithoutContent } from "@/engineeringblog/utils";
import {
Card,
CardActionArea,
CardContent,
CardMedia,
Typography,
} from "@mui/material";
import React from "react";

const ArticleCard = React.forwardRef(function ArticleCard(
{ title, publishDate, featuredImage, slug }: ArticleWithoutContent,
ref: React.Ref<HTMLDivElement>,
) {
return (
<Card
elevation={0}
square={true}
variant="outlined"
sx={{
"&:hover": {
border: `1px solid "#ED1C24"`,
img: {
filter: "none",
},
},
border: "1px solid #DAD5D5",
filter: "drop-shadow(0px 4px 8px rgba(0, 0, 0, 0.1))",
}}
>
<CardActionArea component={slug ? StyledLink : "div"} href={slug}>
<CardMedia
component="img"
src={featuredImage}
sx={{
height: "217.64px",
filter:
"contrast(60%) sepia(100%) hue-rotate(190deg) saturate(500%)",
}}
/>
<CardContent>
<Typography variant="subtitle1">{title}</Typography>
<Typography
sx={{ color: "#9F9494", display: "block", mt: 2 }}
variant="caption"
>
{publishDate}
</Typography>
</CardContent>
</CardActionArea>
</Card>
);
});

export default ArticleCard;
40 changes: 40 additions & 0 deletions apps/engineeringblog/components/Article/ArticleContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"use client";
import { Section } from "@commons-ui/core";
import React from "react";
import { Figure } from "@commons-ui/next";
import { Box } from "@mui/material";
import ArticleHeader from "./ArticleHeader";
import { Article } from "@/engineeringblog/utils";
import Markdown from "@/engineeringblog/components/Markdown";
const ArticleContent = React.forwardRef(function ArticleContent(
{
article,
}: {
article: Article;
},
ref: React.Ref<HTMLDivElement>,
) {
const { title, description, featuredImage, date, content } = article;

return (
<Box ref={ref}>
<ArticleHeader date={date} excerpt={description} title={title} sx={{}} />
<Section
component="header"
sx={{
px: { xs: 2.5, sm: 0 },
py: 2.5,
maxWidth: {
sm: "648px",
md: "912px",
},
}}
ref={ref}
>
<Markdown markdown={content} />
</Section>
</Box>
);
});

export default ArticleContent;
54 changes: 54 additions & 0 deletions apps/engineeringblog/components/Article/ArticleHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"use client";

import { Section } from "@commons-ui/core";
import { Typography } from "@mui/material";
import React from "react";

const ArticleHeader = React.forwardRef(function ArticleHeader(
{
date,
excerpt,
sx,
title,
}: { date: string; excerpt: string; sx: any; title: string },
ref,
) {
return (
<Section
component="header"
sx={{
px: { xs: 2.5, sm: 0 },
maxWidth: {
sm: "648px",
md: "912px",
},
...sx,
}}
ref={ref}
>
<Typography
component="div"
variant="body2"
sx={{ mt: { xs: 2.5, md: 7.5 } }}
>
{date}
</Typography>
<Typography component="div" variant="h1" sx={{ mt: { xs: 2.5, md: 5 } }}>
{title}
</Typography>
<Typography
component="div"
variant="body1"
sx={{
color: "primary.main",
mt: { xs: 2.5, md: 5 },
typography: { md: "subheading" },
}}
>
{excerpt}
</Typography>
</Section>
);
});

export default ArticleHeader;
34 changes: 34 additions & 0 deletions apps/engineeringblog/components/Article/ArticleList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"use client";

import { Section } from "@commons-ui/core";
import { Grid } from "@mui/material";
import React from "react";
import ArticleCard from "./ArticleCard";
import { ArticleWithoutContent } from "@/engineeringblog/utils";

const ArticleList = React.forwardRef(function ArtilceList(
{
articles,
}: {
articles: ArticleWithoutContent[];
},
ref: React.Ref<HTMLDivElement>,
) {
return (
<Section ref={ref}>
<Grid
container
rowSpacing={{ xs: "28px", md: 5 }}
columnSpacing={{ xs: 0, sm: "18px", lg: "28px" }}
>
{articles?.map((article) => (
<Grid item xs={12} sm={4} key={article.slug}>
<ArticleCard {...article} />
</Grid>
))}
</Grid>
</Section>
);
});

export default ArticleList;
5 changes: 5 additions & 0 deletions apps/engineeringblog/components/Article/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import ArticleList from "./ArticleList";
import ArticleCard from "./ArticleCard";
import ArticleContent from "./ArticleContent";

export { ArticleList, ArticleCard, ArticleContent };
48 changes: 48 additions & 0 deletions apps/engineeringblog/components/Markdown/CopyCodeButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from "react";
import { IconButton } from "@mui/material";
import CopyIcon from "@/engineeringblog/assets/icons/Type=copy, Size=24, Color=White.svg";
import CheckIcon from "@/engineeringblog/assets/icons/Type=check-circle, Size=24, Color=White.svg";

export default function CopyCodeButton({
children,
}: {
children: JSX.Element;
}) {
const [copyOk, setCopyOk] = React.useState(false);

const handleClick = (_e: React.MouseEvent) => {
navigator.clipboard.writeText(children.props.children);

setCopyOk(true);
setTimeout(() => {
setCopyOk(false);
}, 500);
};

return (
<IconButton
sx={{
color: "white",
position: "absolute",
top: "10px",
right: "10px",
fontSize: "1.5em",
cursor: "pointer",
transition: "all 0.3s ease -in -out",
}}
>
{copyOk ? (
<CheckIcon />
) : (
<CopyIcon
sx={{
"&:hover": {
color: "#fff",
},
}}
onClick={handleClick}
/>
)}
</IconButton>
);
}
Loading

0 comments on commit 8876e47

Please sign in to comment.