feat: add portfolio site
Before Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 213 KiB |
Before Width: | Height: | Size: 1.7 MiB |
Before Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 759 KiB |
Before Width: | Height: | Size: 350 KiB |
|
@ -15,7 +15,6 @@ import Home from "./pages/Home"
|
|||
import Search from "./pages/Search"
|
||||
import Page from "./pages/Page"
|
||||
import NotFound from "./pages/NotFound"
|
||||
import Portfolio from "./pages/Portfolio"
|
||||
|
||||
import GlobalStyle from "./styles/globalStyle"
|
||||
|
||||
|
@ -83,7 +82,6 @@ export default function App() {
|
|||
<Routes>
|
||||
<Route index element={<Home />} />
|
||||
<Route path="search" element={<Search />} />
|
||||
<Route path="portfolio" element={<Portfolio />} />
|
||||
<Route path="404" element={<NotFound />} />
|
||||
<Route path="loading" element={<Loading />} />
|
||||
<Route path="*" element={<Page />} />
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
import dark from "@developomp-site/theme/dist/dark.json"
|
||||
import light from "@developomp-site/theme/dist/light.json"
|
||||
|
||||
import { Badge } from "@developomp-site/blog-content/src/types/types"
|
||||
import { useEffect, useState } from "react"
|
||||
import styled from "styled-components"
|
||||
|
||||
const StyledBadge = styled.div<{ color: string; isDark: boolean }>`
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
|
||||
padding: 0.2rem 0.4rem 0 0.4rem;
|
||||
margin-right: 0.4rem;
|
||||
margin-bottom: 0.4rem;
|
||||
|
||||
font-size: 0.8rem;
|
||||
|
||||
background-color: ${(props) => props.color};
|
||||
color: ${(props) =>
|
||||
props.isDark ? dark.color.text.default : light.color.text.default};
|
||||
`
|
||||
|
||||
const StyledSVG = styled.div<{ isDark: boolean }>`
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
||||
margin-right: 0.2rem;
|
||||
|
||||
svg {
|
||||
height: 16px;
|
||||
fill: ${(props) =>
|
||||
props.isDark
|
||||
? dark.color.text.default
|
||||
: light.color.text.default} !important;
|
||||
}
|
||||
`
|
||||
|
||||
interface BadgeProps {
|
||||
slug: string
|
||||
}
|
||||
|
||||
export default (props: BadgeProps) => {
|
||||
const [badgeData, setBadgeData] = useState<Badge | undefined>(undefined)
|
||||
const { slug } = props
|
||||
|
||||
const getBadgeData = async () => {
|
||||
return await require(`@developomp-site/blog-content/dist/icons/${slug}.json`)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getBadgeData().then((data) => {
|
||||
setBadgeData(data)
|
||||
})
|
||||
}, [])
|
||||
|
||||
if (!badgeData) return <></>
|
||||
|
||||
return (
|
||||
<StyledBadge color={badgeData.hex} isDark={badgeData.isDark}>
|
||||
<StyledSVG
|
||||
isDark={badgeData.isDark}
|
||||
dangerouslySetInnerHTML={{ __html: badgeData.svg }}
|
||||
/>
|
||||
<span>{badgeData.title}</span>
|
||||
</StyledBadge>
|
||||
)
|
||||
}
|
|
@ -26,7 +26,7 @@ const NavbarData: Item[] = [
|
|||
},
|
||||
{
|
||||
title: "Portfolio",
|
||||
path: "/portfolio",
|
||||
path: "https://portfolio.developomp.com",
|
||||
icon: <FontAwesomeIcon icon={faFileLines} />,
|
||||
},
|
||||
{
|
||||
|
|
|
@ -19,10 +19,10 @@ const NotFound = () => {
|
|||
|
||||
<meta property="og:title" content="Page Not Found" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="http://developomp.com" />
|
||||
<meta property="og:url" content="http://blog.developomp.com" />
|
||||
<meta
|
||||
property="og:image"
|
||||
content="http://developomp.com/icon/icon.svg"
|
||||
content="http://blog.developomp.com/icon/icon.svg"
|
||||
/>
|
||||
<meta property="og:description" content="Page does not exist" />
|
||||
</Helmet>
|
||||
|
|
|
@ -3,12 +3,10 @@ import { Helmet } from "react-helmet-async"
|
|||
import { useLocation } from "react-router-dom"
|
||||
import styled from "styled-components"
|
||||
|
||||
import GithubLinkIcon from "../../components/GithubLinkIcon"
|
||||
import MainContent from "../../components/MainContent"
|
||||
import PostCard from "../../components/PostCard"
|
||||
import Loading from "../../components/Loading"
|
||||
import TagList from "../../components/TagList"
|
||||
import Badge from "../../components/Badge"
|
||||
import Tag from "../../components/Tag"
|
||||
import NotFound from "../NotFound"
|
||||
|
||||
|
@ -26,21 +24,10 @@ import type { PageData } from "@developomp-site/blog-content/src/types/types"
|
|||
|
||||
import contentMap from "../../contentMap"
|
||||
|
||||
const StyledTitle = styled.h1<{ pageType: PageType }>`
|
||||
const StyledTitle = styled.h1`
|
||||
margin-bottom: 1rem;
|
||||
|
||||
word-wrap: break-word;
|
||||
|
||||
${(props) => {
|
||||
if (props.pageType == PageType.PORTFOLIO_PROJECT) {
|
||||
return "margin-right: 3rem;"
|
||||
}
|
||||
}}
|
||||
`
|
||||
|
||||
const PortfolioGithubLinkContainer = styled.div`
|
||||
float: right;
|
||||
margin-top: 1rem;
|
||||
`
|
||||
|
||||
const ProjectImage = styled.img`
|
||||
|
@ -97,17 +84,7 @@ export default function Page() {
|
|||
/>
|
||||
)}
|
||||
|
||||
{pageType == PageType.PORTFOLIO_PROJECT && pageData.repo && (
|
||||
<PortfolioGithubLinkContainer>
|
||||
<GithubLinkIcon link={pageData.repo} />
|
||||
</PortfolioGithubLinkContainer>
|
||||
)}
|
||||
<StyledTitle pageType={PageType.PORTFOLIO_PROJECT}>
|
||||
{pageData.title}
|
||||
</StyledTitle>
|
||||
|
||||
{pageType == PageType.PORTFOLIO_PROJECT &&
|
||||
pageData.badges.map((badge) => <Badge key={badge} slug={badge} />)}
|
||||
<StyledTitle>{pageData.title}</StyledTitle>
|
||||
|
||||
<small>
|
||||
{/* Post tags */}
|
||||
|
@ -136,10 +113,6 @@ export default function Page() {
|
|||
{/* add table of contents if it exists */}
|
||||
<Toc data={pageData.toc} />
|
||||
|
||||
{pageType == PageType.PORTFOLIO_PROJECT && (
|
||||
<ProjectImage src={pageData.image} alt="project example image" />
|
||||
)}
|
||||
|
||||
{/* page content */}
|
||||
<div
|
||||
dangerouslySetInnerHTML={{
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
import { useEffect, useState } from "react"
|
||||
import { Helmet } from "react-helmet-async"
|
||||
|
||||
import MainContent from "../../components/MainContent"
|
||||
import Badge from "../../components/Badge"
|
||||
import ProjectCard from "./ProjectCard"
|
||||
|
||||
import portfolio from "@developomp-site/blog-content/dist/portfolio.json"
|
||||
|
||||
import type { PortfolioProject } from "@developomp-site/blog-content/src/types/types"
|
||||
|
||||
const Portfolio = () => {
|
||||
const [projects, setProjects] = useState<JSX.Element[]>([])
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [skills, setSkills] = useState<JSX.Element[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
const _projects: JSX.Element[] = []
|
||||
|
||||
for (const projectID in portfolio.projects) {
|
||||
_projects.push(
|
||||
<ProjectCard
|
||||
key={projectID}
|
||||
projectID={projectID}
|
||||
project={
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
portfolio.projects[projectID] as PortfolioProject
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
setProjects(_projects)
|
||||
|
||||
setSkills(
|
||||
portfolio.skills.map((slug) => {
|
||||
return <Badge key={slug} slug={slug} />
|
||||
})
|
||||
)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>pomp | Portfolio</title>
|
||||
|
||||
<meta property="og:title" content="Portfolio" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="http://developomp.com" />
|
||||
<meta
|
||||
property="og:image"
|
||||
content="http://developomp.com/icon/icon.svg"
|
||||
/>
|
||||
<meta property="og:description" content="developomp's Portfolio" />
|
||||
</Helmet>
|
||||
|
||||
<MainContent>
|
||||
<h1>Portfolio</h1>
|
||||
|
||||
<hr />
|
||||
|
||||
{/* Projects */}
|
||||
|
||||
<h2 id="projects">
|
||||
<a className="header-anchor" href="#projects">
|
||||
#
|
||||
</a>
|
||||
{" Projects"}
|
||||
</h2>
|
||||
|
||||
{/* todo: filter projects by skill */}
|
||||
|
||||
{skills}
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
{projects}
|
||||
</MainContent>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Portfolio
|
|
@ -1,64 +0,0 @@
|
|||
import { useEffect, useState } from "react"
|
||||
import styled from "styled-components"
|
||||
import { Link } from "react-router-dom"
|
||||
|
||||
import Badge from "../../components/Badge"
|
||||
import { cardCSS } from "../../components/Card"
|
||||
|
||||
import { PortfolioProject } from "@developomp-site/blog-content/src/types/types"
|
||||
|
||||
const StyledProjectCard = styled.div`
|
||||
${cardCSS}
|
||||
|
||||
color: ${(props) => props.theme.theme.color.text.default};
|
||||
margin-bottom: 2rem;
|
||||
word-wrap: break-word;
|
||||
|
||||
:hover {
|
||||
cursor: pointer;
|
||||
|
||||
box-shadow: 0 4px 10px
|
||||
${(props) => props.theme.theme.component.card.color.hoverGlow};
|
||||
}
|
||||
`
|
||||
|
||||
const StyledImg = styled.img`
|
||||
width: 100%;
|
||||
|
||||
object-fit: cover;
|
||||
margin-bottom: 1rem;
|
||||
`
|
||||
|
||||
interface ProjectCardProps {
|
||||
projectID: string
|
||||
project: PortfolioProject
|
||||
}
|
||||
|
||||
const ProjectCard = (props: ProjectCardProps) => {
|
||||
const { projectID, project } = props
|
||||
|
||||
const [badges, setBadges] = useState<JSX.Element[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
setBadges(project.badges.map((badge) => <Badge key={badge} slug={badge} />))
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Link to={projectID}>
|
||||
<StyledProjectCard>
|
||||
<h1>{project.name}</h1>
|
||||
<StyledImg src={project.image} />
|
||||
|
||||
{badges}
|
||||
<hr />
|
||||
<div
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: project.overview,
|
||||
}}
|
||||
/>
|
||||
</StyledProjectCard>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProjectCard
|
|
@ -1,3 +0,0 @@
|
|||
import Portfolio from "./Portfolio"
|
||||
|
||||
export default Portfolio
|