added basic portfolio page

This commit is contained in:
Kim, Jimin 2022-01-06 12:27:42 +09:00
parent fc51c78f1e
commit dcbfe24de0
13 changed files with 230 additions and 9 deletions

View file

@ -5,14 +5,15 @@
"editor.detectIndentation": false,
"editor.insertSpaces": false,
"cSpell.words": [
"Fontawesome",
"YYYYMMDD",
"developomp",
"developomp's",
"dompurify",
"elasticlunr",
"Fontawesome",
"hljs",
"katex",
"texmath"
"texmath",
"tinycolor",
"YYYYMMDD"
]
}

View file

@ -1,6 +1,7 @@
import fs from "fs"
import simpleIcons from "simple-icons" // badge icons
import readTimeEstimate from "read-time-estimate" // post read time estimation
import tinycolor from "tinycolor2" // color manipulation
import { path2FileOrFolderName, path2URL, writeToFile } from "./util"
import { generateToc, parseFrontMatter } from "./parseMarkdown"
@ -354,12 +355,15 @@ function parsePortfolio(data: DataToPass): void {
;(markdownData.badges as string[]).forEach((slug) => {
const icon = simpleIcons.Get(slug)
const color = tinycolor(icon.hex).lighten(5).desaturate(5)
// save svg icon
writeToFile(
`${iconsDirectoryPath}/${icon.slug}.json`,
JSON.stringify({
svg: icon.svg,
hex: icon.hex,
hex: color.toHexString(),
isDark: color.isDark(),
title: icon.title,
})
)

View file

@ -2,6 +2,4 @@
github: https://github.com/developomp
---
## Skills
## Education

View file

@ -1,7 +1,7 @@
---
name: Mocha Downloader
overview: A cross-platform desktop download manager built with web technologies.
image: /img/icon.png
image: /img/portfolio/mocha-downloader.png
repo: https://github.com/Mocha-Downloader
badges:
- typescript

View file

@ -1,7 +1,7 @@
---
name: War Brokers Mods
overview: A game mod for a unity game. Provides in-game UI and OBS overlays.
image: /img/icon.png
image: /img/portfolio/wbm.png
repo: https://github.com/War-Brokers-Mods
badges:
- csharp

View file

@ -45,6 +45,7 @@
"@types/react-router-hash-link": "^2.4.4",
"@types/react-select": "^5.0.1",
"@types/styled-components": "^5.1.19",
"@types/tinycolor2": "^1.4.3",
"@typescript-eslint/eslint-plugin": "^5.9.0",
"@typescript-eslint/parser": "^5.9.0",
"canvas": "^2.8.0",
@ -68,6 +69,7 @@
"prettier": "^2.5.1",
"read-time-estimate": "^0.0.3",
"simple-icons": "^6.5.0",
"tinycolor2": "^1.4.2",
"ts-node": "^10.4.0",
"tslint-config-prettier": "^1.18.0",
"typescript": "^4.5.4"

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 759 KiB

View file

@ -15,6 +15,7 @@ import PostList from "./pages/PostList"
import Search from "./pages/Search"
import Page from "./pages/Page"
import NotFound from "./pages/NotFound"
import Portfolio from "./pages/Portfolio"
import theming from "./styles/theming"
import GlobalStyle from "./styles/globalStyle"
@ -94,9 +95,10 @@ const App = () => {
path="/"
element={<PostList howMany={5} title="Home" />}
/>
<Route path="/loading" element={<Loading />} />
<Route path="/search" element={<Search />} />
<Route path="/portfolio" element={<Portfolio />} />
<Route path="/404" element={<NotFound />} />
<Route path="/loading" element={<Loading />} />
<Route path="/*" element={<Page />} />
</Routes>
)}

View file

@ -0,0 +1,73 @@
import { useEffect, useState } from "react"
import styled from "styled-components"
import theming from "../styles/theming"
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;
font-size: 0.8rem;
background-color: ${(props) => props.color};
color: ${(props) =>
props.isDark ? theming.dark.color1 : theming.light.color1};
`
const StyledSVG = styled.div<{ isDark: boolean }>`
display: inline-block;
vertical-align: middle;
margin-right: 0.2rem;
svg {
height: 16px;
fill: ${(props) =>
props.isDark
? theming.dark.color1
: theming.light.color1} !important;
}
`
interface Badge {
svg: string
hex: string
isDark: boolean
title: string
}
interface BadgeProps {
slug: string
}
const Badge = (props: BadgeProps) => {
const [badgeData, setBadgeData] = useState<Badge | undefined>(undefined)
const { slug } = props
const getBadgeData = async () => {
return await require(`../data/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>
)
}
export default Badge

View file

@ -0,0 +1,67 @@
import styled from "styled-components"
import { faGithub } from "@fortawesome/free-brands-svg-icons"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
import MainContent from "../../components/MainContent"
import Badge from "../../components/Badge"
import { PortfolioProject } from "../../../types/types"
import theming from "../../styles/theming"
const StyledProjectCard = styled(MainContent)`
margin-bottom: 2rem;
`
const StyledImg = styled.img`
width: 100%;
object-fit: cover;
margin-bottom: 1rem;
`
const StyledGithubLink = styled.a`
display: flex;
float: right;
align-items: center;
gap: 0.5rem;
margin-top: 1.5rem;
color: ${(props) =>
theming.theme(props.theme.currentTheme, {
light: theming.light.color1,
dark: theming.dark.color1,
})};
svg {
font-size: 2rem;
}
`
interface ProjectCardProps {
project: PortfolioProject
}
const ProjectCard = (props: ProjectCardProps) => {
const { project } = props
return (
<StyledProjectCard>
<StyledGithubLink href={project.repo}>
<FontAwesomeIcon icon={faGithub} />
Github
</StyledGithubLink>
<h1>{project.name}</h1>
<StyledImg src={project.image} />
{project.badges.map((badge) => {
return <Badge key={badge} slug={badge} />
})}
<hr />
<div dangerouslySetInnerHTML={{ __html: project.overview }} />
</StyledProjectCard>
)
}
export default ProjectCard

View file

@ -0,0 +1,64 @@
import { useEffect, useState } from "react"
import { Helmet } from "react-helmet-async"
import MainContent from "../../components/MainContent"
import ProjectCard from "./ProjectCard"
import portfolio from "../../data/portfolio.json"
import { PortfolioProject } from "../../../types/types"
const Portfolio = () => {
const [projects, setProjects] = useState<JSX.Element[]>([])
useEffect(() => {
const _projects: JSX.Element[] = []
for (const projectID in portfolio.projects) {
_projects.push(
<ProjectCard
key={projectID}
project={
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
portfolio.projects[projectID] as PortfolioProject
}
/>
)
}
setProjects(_projects)
}, [])
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 />
<div dangerouslySetInnerHTML={{ __html: portfolio.overview }} />
</MainContent>
<br />
{projects}
</>
)
}
export default Portfolio

View file

@ -2077,6 +2077,11 @@
"@types/react" "*"
csstype "^3.0.2"
"@types/tinycolor2@^1.4.3":
version "1.4.3"
resolved "https://registry.yarnpkg.com/@types/tinycolor2/-/tinycolor2-1.4.3.tgz#ed4a0901f954b126e6a914b4839c77462d56e706"
integrity sha512-Kf1w9NE5HEgGxCRyIcRXR/ZYtDv0V8FVPtYHwLxl0O+maGX0erE77pQlD0gpP+/KByMZ87mOA79SjifhSB3PjQ==
"@types/tough-cookie@*":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.1.tgz#8f80dd965ad81f3e1bc26d6f5c727e132721ff40"
@ -9161,6 +9166,11 @@ timsort@^0.3.0:
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
tinycolor2@^1.4.2:
version "1.4.2"
resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.2.tgz#3f6a4d1071ad07676d7fa472e1fac40a719d8803"
integrity sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==
tmpl@1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"