From 9cb0f8220e37182375e8eb8890ef4df2c58c2aa4 Mon Sep 17 00:00:00 2001 From: jaemin Date: Fri, 29 Nov 2024 15:05:26 +0900 Subject: [PATCH] =?UTF-8?q?update:=20skills=20=EB=B0=98=EC=9D=91=ED=98=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 11 ++- app/data/repositories/SkillRepositoryImpl.ts | 87 +++++++++++++++++++ app/data/repositories/index.ts | 3 + app/domain/entities/skill.entity.ts | 10 +++ app/domain/repositories/skill.repo.ts | 5 ++ .../component/ParallaxContainer.tsx | 2 +- app/presentation/component/article/Skills.tsx | 17 +++- .../component/section/SkillCategory.tsx | 28 ++++++ 8 files changed, 157 insertions(+), 6 deletions(-) create mode 100644 app/data/repositories/SkillRepositoryImpl.ts create mode 100644 app/data/repositories/index.ts create mode 100644 app/domain/entities/skill.entity.ts create mode 100644 app/domain/repositories/skill.repo.ts create mode 100644 app/presentation/component/section/SkillCategory.tsx diff --git a/README.md b/README.md index ef7f7c8..2458a4d 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,17 @@ # jm-portfolio + 프론트엔드 개발자 포트폴리오 웹사이트입니다 ## 📝 개요 + React와 Next.js를 활용한 개인 포트폴리오 사이트로, 프로젝트 경험과 기술 스택을 소개합니다. ## 🔗 배포 링크 + 웹사이트: https://jaemin-s.github.io ## 🛠 기술 스택 + - Framework: React, Next.js - Language: TypeScript - Styling: TailwindCSS @@ -16,6 +20,7 @@ React와 Next.js를 활용한 개인 포트폴리오 사이트로, 프로젝트 - Deployment: GitHub Pages ## 📌 실행 방법 + ``` # Install dependencies yarn install @@ -28,6 +33,7 @@ yarn build ``` ## 📊 프로젝트 구조 + ``` app/ ├── presentation/ # UI 계층 @@ -56,9 +62,12 @@ app/ ``` ## 참고 링크 + 기술스택 이미지 : https://simpleicons.org/ +기술스택 뱃지 : https://shields.io/badges 아이콘 이미지 : https://fonts.google.com/icons ## ✏️ 개선 사항 + +- - -- diff --git a/app/data/repositories/SkillRepositoryImpl.ts b/app/data/repositories/SkillRepositoryImpl.ts new file mode 100644 index 0000000..57e43c3 --- /dev/null +++ b/app/data/repositories/SkillRepositoryImpl.ts @@ -0,0 +1,87 @@ +import { SkillCategory } from '@/app/domain/entities/skill.entity' +import { SkillRepository } from '@/app/domain/repositories/skill.repo' + +export class SkillRepositoryImpl implements SkillRepository { + /* + Languages : TypeScript, JavaScript, HTML, CSS, Kotlin, + Frameworks : React, Next.js, React Native, Android, Jetpack Compose + State Management : Redux, Recoil, Zustand, Context API, React Query + Styling : Styled-components, Tailwind CSS, Emotion + Testing : Jest, React Testing Library + DevOps : Webpack, Vite, Babel, npm, yarnm ESLint, Prettier, Husky, git, github, GitHub Actions, Vercel + + Build Tools: Webpack, Vite, Babel + Package Manager: npm, yarn + Code Quality: ESLint, Prettier, Husky + Version Control: git, github + CI/CD: GitHub Actions, Vercel + */ + private readonly mockData: SkillCategory[] = [ + { + categoryName: 'Languages', + skillList: [ + { name: 'TypeScript', color: '3178C6', logoName: 'typescript' }, + { name: 'JavaScript', color: 'F7DF1E', logoName: 'javascript' }, + { name: 'HTML', color: 'E34F26', logoName: 'html5' }, + { name: 'CSS', color: '1572B6', logoName: 'css3' }, + { name: 'Kotlin', color: '7F52FF', logoName: 'kotlin' }, + ], + }, + { + categoryName: 'Frameworks', + skillList: [ + { name: 'React', color: '61DAFB', logoName: 'react' }, + { name: 'Next.js', color: '000000', logoName: 'nextdotjs' }, + { name: 'React Native', color: '0088CC', logoName: 'react' }, + { name: 'Android', color: '34A853', logoName: 'android' }, + { name: 'Jetpack Compose', color: '4285F4', logoName: 'jetpackcompose' }, + ], + }, + { + categoryName: 'State', + skillList: [ + { name: 'Redux', color: '764ABC', logoName: 'redux' }, + { name: 'Recoil', color: '3578E5', logoName: 'recoil' }, + { name: 'Zustand', color: '', logoName: '' }, + { name: 'Context API', color: '0088CC', logoName: 'react' }, + { name: 'React Query', color: 'FF4154', logoName: 'reactquery' }, + ], + }, + { + categoryName: 'Styling', + skillList: [ + { name: 'StyledComponents', color: 'DB7093', logoName: 'styledcomponents' }, + { name: 'Tailwind CSS', color: '06B6D4', logoName: 'tailwindcss' }, + { name: 'Emotion', color: '', logoName: '' }, + ], + }, + { + categoryName: 'Testing', + skillList: [ + { name: 'Jest', color: 'C21325', logoName: 'jest' }, + { name: 'React Testing Library', color: '', logoName: '' }, + ], + }, + { + categoryName: 'DevOps', + skillList: [ + { name: 'Vite', color: '646CFF', logoName: 'vite' }, + { name: 'Webpack', color: '8DD6F9', logoName: 'webpack' }, + { name: 'npm', color: 'CB3837', logoName: 'npm' }, + { name: 'Yarn', color: '2C8EBB', logoName: 'yarn' }, + { name: 'Vercel', color: '000000', logoName: 'vercel' }, + { name: 'Git', color: 'F05032', logoName: 'git' }, + { name: 'Github', color: '181717', logoName: 'github' }, + { name: 'Github Actions', color: '2088FF', logoName: 'githubactions' }, + { name: 'Husky', color: '', logoName: '' }, + { name: 'Slack', color: '4A154B', logoName: 'slack' }, + ], + }, + ] + + async getSkillCategories(): Promise { + //API 처럼 지연 + await new Promise((resolve) => setTimeout(resolve, 200)) + return this.mockData + } +} diff --git a/app/data/repositories/index.ts b/app/data/repositories/index.ts new file mode 100644 index 0000000..a7758bc --- /dev/null +++ b/app/data/repositories/index.ts @@ -0,0 +1,3 @@ +import { SkillRepositoryImpl } from './SkillRepositoryImpl' + +export const skillRepository = new SkillRepositoryImpl() diff --git a/app/domain/entities/skill.entity.ts b/app/domain/entities/skill.entity.ts new file mode 100644 index 0000000..fdf342f --- /dev/null +++ b/app/domain/entities/skill.entity.ts @@ -0,0 +1,10 @@ +export interface SkillCategory { + categoryName: string + skillList: Array +} + +export interface Skill { + name: string + color: string + logoName: string +} diff --git a/app/domain/repositories/skill.repo.ts b/app/domain/repositories/skill.repo.ts new file mode 100644 index 0000000..16f84a6 --- /dev/null +++ b/app/domain/repositories/skill.repo.ts @@ -0,0 +1,5 @@ +import { SkillCategory } from '../entities/skill.entity' + +export interface SkillRepository { + getSkillCategories(): Promise +} diff --git a/app/presentation/component/ParallaxContainer.tsx b/app/presentation/component/ParallaxContainer.tsx index 4c0e8c8..5e29738 100644 --- a/app/presentation/component/ParallaxContainer.tsx +++ b/app/presentation/component/ParallaxContainer.tsx @@ -8,7 +8,7 @@ interface ParallaxProps { const ParallaxContainer: React.FC = ({ children, imgSrc }) => { return (
{children} diff --git a/app/presentation/component/article/Skills.tsx b/app/presentation/component/article/Skills.tsx index c43bb62..008fe60 100644 --- a/app/presentation/component/article/Skills.tsx +++ b/app/presentation/component/article/Skills.tsx @@ -1,12 +1,21 @@ import React from 'react' import ArticleHeader from '../text/ArticleHeader' +import SkillCategoryComponent from '../section/SkillCategory' +import { skillRepository } from '@/app/data/repositories' + +const Skills = async () => { + const skillCategoryList = await skillRepository.getSkillCategories() -const Skills = () => { return ( -
- +
+ +
+ {skillCategoryList.map((item) => ( + + ))} +
) } -export default Skills \ No newline at end of file +export default Skills diff --git a/app/presentation/component/section/SkillCategory.tsx b/app/presentation/component/section/SkillCategory.tsx new file mode 100644 index 0000000..9a255ac --- /dev/null +++ b/app/presentation/component/section/SkillCategory.tsx @@ -0,0 +1,28 @@ +import React from 'react' +import SubHeaderText from '../text/SubHeaderText' +import { Skill, SkillCategory } from '@/app/domain/entities/skill.entity' + +const SkillCategoryComponent = ({ categoryName, skillList }: SkillCategory) => { + function getLogoUrl(item: Skill) { + const baseUrl = 'https://img.shields.io/badge/' + const param = !!item.logoName + ? `${item.name}-${item.color}?style=flat-square&logo=${item.logoName}&logoColor=ffffff` + : `${item.name}-444444?style=flat-square` + return baseUrl + param + } + + return ( +
+
+ +
+
+ {skillList.map((item) => ( + Static Badge + ))} +
+
+ ) +} + +export default SkillCategoryComponent