Compare commits
5 Commits
be8b18a31b
...
695746a507
Author | SHA1 | Date | |
---|---|---|---|
|
695746a507 | ||
|
0d90e4c166 | ||
|
ebed0c208c | ||
|
42b7167eec | ||
|
5f1b0016f2 |
107
.drone.yml
Normal file
107
.drone.yml
Normal file
@ -0,0 +1,107 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: analyseAndBuild
|
||||
|
||||
steps:
|
||||
- name: code-analysis
|
||||
image: sonarsource/sonar-scanner-cli
|
||||
detach: true
|
||||
failure: ignore
|
||||
commands:
|
||||
- sonar-scanner -Dsonar.projectKey=cv -Dsonar.sources=. -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$SONAR_LOGIN
|
||||
environment:
|
||||
SONAR_HOST_URL:
|
||||
from_secret: sonarScannerHostUrl
|
||||
SONAR_LOGIN:
|
||||
from_secret: sonarScannerLogin
|
||||
|
||||
- name: lintAndBuild
|
||||
image: node:14
|
||||
commands:
|
||||
- npm install
|
||||
- npm run lint
|
||||
- npm run build:prod
|
||||
environment:
|
||||
VUE_APP_API_BASE_URL:
|
||||
from_secret: baseurl
|
||||
|
||||
- name: saveNodeModules
|
||||
image: drillster/drone-volume-cache
|
||||
volumes:
|
||||
- name: cache
|
||||
path: /cache
|
||||
settings:
|
||||
rebuild: true
|
||||
mount:
|
||||
- ./node_modules
|
||||
cache_key: [ DRONE_REPO_NAME, DRONE_BRANCH ]
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
volumes:
|
||||
- name: cache
|
||||
host:
|
||||
path: /tmp/cache
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: Deploy
|
||||
|
||||
steps:
|
||||
- name: getNodeModules
|
||||
image: drillster/drone-volume-cache
|
||||
volumes:
|
||||
- name: cache
|
||||
path: /cache
|
||||
settings:
|
||||
restore: true
|
||||
mount:
|
||||
- ./node_modules
|
||||
cache_key: [ DRONE_REPO_NAME, DRONE_BRANCH ]
|
||||
|
||||
- name: build
|
||||
image: node:14
|
||||
commands:
|
||||
- npm run build:prod
|
||||
environment:
|
||||
VUE_APP_API_BASE_URL:
|
||||
from_secret: baseurl
|
||||
|
||||
- name: scpFiles
|
||||
image: appleboy/drone-scp
|
||||
settings:
|
||||
host: amine-louveau.fr
|
||||
username: ubuntu
|
||||
key:
|
||||
from_secret: privateKey
|
||||
port: 22
|
||||
target: /home/ubuntu/courses
|
||||
source: dist/*
|
||||
|
||||
- name: deploy
|
||||
image: appleboy/drone-ssh
|
||||
settings:
|
||||
host: amine-louveau.fr
|
||||
user: ubuntu
|
||||
key:
|
||||
from_secret: privateKey
|
||||
command_timeout: 2m
|
||||
script:
|
||||
- cd /home/ubuntu/courses
|
||||
- mv dist/* ./
|
||||
- sudo chown www-data:www-data ./*
|
||||
- sudo rm -rf /var/www/amine/courses/*
|
||||
- sudo mv ./* /var/www/amine/courses/
|
||||
trigger:
|
||||
event:
|
||||
- promote
|
||||
target:
|
||||
- production
|
||||
|
||||
volumes:
|
||||
- name: cache
|
||||
host:
|
||||
path: /tmp/cache
|
23
.gitignore
vendored
Normal file
23
.gitignore
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
5
.idea/.gitignore
vendored
Normal file
5
.idea/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
13
.idea/cv.iml
Normal file
13
.idea/cv.iml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
6
.idea/dictionaries
Normal file
6
.idea/dictionaries
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="amine" />
|
||||
</component>
|
||||
</project>
|
6
.idea/encodings.xml
Normal file
6
.idea/encodings.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="PROJECT" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
6
.idea/inspectionProfiles/Project_Default.xml
Normal file
6
.idea/inspectionProfiles/Project_Default.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/cv.iml" filepath="$PROJECT_DIR$/.idea/cv.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
0
.idea/sonarlint/issuestore/index.pb
Normal file
0
.idea/sonarlint/issuestore/index.pb
Normal file
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
4
.idea/watcherTasks.xml
Normal file
4
.idea/watcherTasks.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectTasksOptions" suppressed-tasks="Sass;SCSS" />
|
||||
</project>
|
0
.scannerwork/.sonar_lock
Normal file
0
.scannerwork/.sonar_lock
Normal file
6
.scannerwork/report-task.txt
Normal file
6
.scannerwork/report-task.txt
Normal file
@ -0,0 +1,6 @@
|
||||
projectKey=cv
|
||||
serverUrl=http://18.0.0.7:9000
|
||||
serverVersion=9.6.0.59041
|
||||
dashboardUrl=http://18.0.0.7:9000/dashboard?id=cv
|
||||
ceTaskId=AYOJWrb2HpE7RRVya8HT
|
||||
ceTaskUrl=http://18.0.0.7:9000/api/ce/task?id=AYOJWrb2HpE7RRVya8HT
|
@ -1,3 +1,3 @@
|
||||
# cv
|
||||
|
||||
A CV template, inspired by https://techrez.io/resume/andrew-lu
|
||||
A CV template, inspired by https://techrez.io/resume/andrew-lu
|
||||
|
28477
package-lock.json
generated
Normal file
28477
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
54
package.json
Normal file
54
package.json
Normal file
@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "cv",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@headlessui/react": "^1.7.2",
|
||||
"@heroicons/react": "^2.0.11",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/lodash": "^4.14.186",
|
||||
"@types/node": "^16.11.62",
|
||||
"@types/react": "^18.0.21",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"lodash": "^4.17.21",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"typescript": "^4.8.4",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.7",
|
||||
"autoprefixer": "^10.4.12",
|
||||
"postcss": "^8.4.16",
|
||||
"sass": "^1.55.0",
|
||||
"tailwindcss": "^3.1.8"
|
||||
}
|
||||
}
|
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
27
public/index.html
Normal file
27
public/index.html
Normal file
@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<title>React App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
25
src/Assets/scss/CV.scss
Normal file
25
src/Assets/scss/CV.scss
Normal file
@ -0,0 +1,25 @@
|
||||
.card {
|
||||
@apply container p-3 bg-gray-200 rounded-md mt-8 mb-8 drop-shadow;
|
||||
}
|
||||
|
||||
.icon {
|
||||
@apply w-5 inline-block mr-2;
|
||||
}
|
||||
|
||||
.tag {
|
||||
@apply mb-2 rounded-full p-3 pt-1 pb-1 text-white shadow mr-1 prose prose-sm;
|
||||
}
|
||||
|
||||
.details {
|
||||
& > * {
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
& > *:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
& > *:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
71
src/CV.tsx
Normal file
71
src/CV.tsx
Normal file
@ -0,0 +1,71 @@
|
||||
import React, {useEffect} from 'react';
|
||||
import Header from './Components/Header';
|
||||
import './Assets/scss/CV.scss'
|
||||
import Jobs from './Components/Jobs';
|
||||
import Education from './Components/Education';
|
||||
import SideProjects from './Components/SideProjects';
|
||||
import Languages from './Components/Languages';
|
||||
import Interests from './Components/Interests';
|
||||
import Skills from './Components/Skills';
|
||||
import {Tag, TagCategory} from './Model/tag';
|
||||
import {Lang} from './Model/lang';
|
||||
import {EducationYear} from './Model/education';
|
||||
import {SideProjectCats} from './Model/side-project';
|
||||
import {JobAtCompany} from './Model/job-at-company';
|
||||
import {Interest} from './Model/interests';
|
||||
import {Profile} from './Model/profile';
|
||||
|
||||
function CV() {
|
||||
const tags: Tag[] = []
|
||||
|
||||
const langs: Lang[] = []
|
||||
|
||||
const ed: EducationYear[] = []
|
||||
|
||||
const projs: SideProjectCats[] = []
|
||||
|
||||
const jobs: JobAtCompany[] = []
|
||||
|
||||
const interests: Interest[] = []
|
||||
|
||||
const profile: Profile = {
|
||||
"name": "",
|
||||
"title": "",
|
||||
"quote": "",
|
||||
"picture": ""
|
||||
}
|
||||
|
||||
document.title = profile.name;
|
||||
|
||||
useEffect(() => {
|
||||
let link = document.querySelector("link[rel~='icon']");
|
||||
if (!link) {
|
||||
link = document.createElement('link');
|
||||
// @ts-ignore
|
||||
link.rel = 'icon';
|
||||
document.getElementsByTagName('head')[0].appendChild(link);
|
||||
}
|
||||
// @ts-ignore
|
||||
link.href = profile.picture
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="CV">
|
||||
<Header tags={tags} profile={profile}/>
|
||||
<div className="card flex divide-x divide-gray-600">
|
||||
<div className="basis-3/4 pr-2 divide-y divide-gray-400 details">
|
||||
<Jobs jobs={jobs}/>
|
||||
<Education education={ed}/>
|
||||
<SideProjects projs={projs}/>
|
||||
</div>
|
||||
<div className="basis-1/4 pl-2 divide-y divide-gray-400 details">
|
||||
<Skills tags={tags}/>
|
||||
<Languages langs={langs}/>
|
||||
<Interests interests={interests}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default CV;
|
17
src/Components/Education.tsx
Normal file
17
src/Components/Education.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import React, {ComponentProps} from 'react';
|
||||
import {AcademicCapIcon, BriefcaseIcon} from '@heroicons/react/24/outline';
|
||||
import {EducationYear} from '../Model/education';
|
||||
|
||||
function Education(props: ComponentProps<any>) {
|
||||
return (<div className="prose max-w-none">
|
||||
<h3><AcademicCapIcon className="icon"/> Formations</h3>
|
||||
{props.education.map((e: EducationYear) => <div key={e.endDate} className="mb-5">
|
||||
<div className="flex justify-between w-full"><h4 className="m-0">{e.school}</h4>
|
||||
<div>{e.endDate}</div>
|
||||
</div>
|
||||
<div>{e.name}</div>
|
||||
</div>)}
|
||||
</div>);
|
||||
}
|
||||
|
||||
export default Education;
|
43
src/Components/Header.tsx
Normal file
43
src/Components/Header.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import React, {ComponentProps} from 'react';
|
||||
import {CodeBracketIcon, EnvelopeIcon, PhoneIcon, UserPlusIcon} from '@heroicons/react/24/outline';
|
||||
import {getTagColor, Tag} from '../Model/tag';
|
||||
import {Profile} from '../Model/profile';
|
||||
|
||||
function Header(props: ComponentProps<any>) {
|
||||
const tags = props.tags.filter((t: Tag) => t.workThing)
|
||||
const profile: Profile = props.profile
|
||||
return (<div
|
||||
className="card flex flex-wrap-reverse">
|
||||
<div className="basis-1/4">
|
||||
<img className="w-60 rounded-full shadow-lg lg:divide-x divide-gray-600" src={profile.picture}
|
||||
/>
|
||||
</div>
|
||||
<div className="basis-2/4 prose p-3 prose-sm grow">
|
||||
<h1>{profile.name}</h1>
|
||||
<h2>{profile.title}</h2>
|
||||
<blockquote>{profile.quote}</blockquote>
|
||||
<div className="prose flex flex-wrap justify-between"> {/* Tags */}
|
||||
{tags.map((t: Tag) => <button key={t.name} className={"tag " + getTagColor(t)}>{t.name}</button>)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="basis-1/4 lg:divide-y divide-gray-400 prose p-3 grow">
|
||||
<div className="text-center lg:text-left">
|
||||
<h3 className="mt-2 mb-1">Me contacter</h3>
|
||||
<div><EnvelopeIcon className="icon"/><a className="" href={"mailto:" + profile.email}>Par
|
||||
mail</a></div>
|
||||
<div><PhoneIcon className="icon"/><a className="" href={"tel:" + profile.phone}>Par
|
||||
téléphone</a></div>
|
||||
<h3 className="mt-2 mb-1">Me connaitre</h3>
|
||||
<div><UserPlusIcon className="icon"/><a className=""
|
||||
href={profile.linkedin}
|
||||
|
||||
target="_blank">Mon linkedin</a></div>
|
||||
<div><CodeBracketIcon className="icon"/><a className=""
|
||||
href={profile.source} target="_blank">Mon
|
||||
code</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
|
||||
export default Header;
|
14
src/Components/Interests.tsx
Normal file
14
src/Components/Interests.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import React, {ComponentProps} from 'react';
|
||||
import {CalendarDaysIcon, FaceSmileIcon, LanguageIcon} from '@heroicons/react/24/outline';
|
||||
import {Interest} from '../Model/interests';
|
||||
|
||||
function Interests(props: ComponentProps<any>) {
|
||||
return (<div className="prose">
|
||||
<h3><FaceSmileIcon className="icon"/> Centre d'intérets</h3>
|
||||
<ul>
|
||||
{props.interests.map((i: Interest) => <li key={i.theme}><strong>{i.theme}</strong> : {i.description}</li>)}
|
||||
</ul>
|
||||
</div>);
|
||||
}
|
||||
|
||||
export default Interests;
|
16
src/Components/Job.tsx
Normal file
16
src/Components/Job.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import React, {ComponentProps} from 'react';
|
||||
import {BriefcaseIcon} from '@heroicons/react/24/outline';
|
||||
|
||||
function Job(props: ComponentProps<any>) {
|
||||
return (<div className="mb-5">
|
||||
<div className="flex justify-between w-full"><h4 className="m-0">{props.jobTitle}</h4>
|
||||
<div>{props.start} - {props.end}</div>
|
||||
</div>
|
||||
<h5>{props.company}</h5>
|
||||
<ul>
|
||||
{props.tasks.map((task: string) => <li key={task}>{task}</li>)}
|
||||
</ul>
|
||||
</div>);
|
||||
}
|
||||
|
||||
export default Job;
|
14
src/Components/Jobs.tsx
Normal file
14
src/Components/Jobs.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import React, {ComponentProps} from 'react';
|
||||
import {BriefcaseIcon} from '@heroicons/react/24/outline';
|
||||
import Job from './Job';
|
||||
import {JobAtCompany} from '../Model/job-at-company';
|
||||
|
||||
function Jobs(props: ComponentProps<any>) {
|
||||
return (<div className="prose max-w-none">
|
||||
<h3><BriefcaseIcon className="icon"/> Expériences professionnelles</h3>
|
||||
{props.jobs.map((j: JobAtCompany) => <Job jobTitle={j.jobTitle} start={j.start} end={j.end} company={j.company} tasks={j.tasks} key={j.start}></Job>)}
|
||||
|
||||
</div>);
|
||||
}
|
||||
|
||||
export default Jobs;
|
14
src/Components/Languages.tsx
Normal file
14
src/Components/Languages.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import React, {ComponentProps} from 'react';
|
||||
import {CalendarDaysIcon, LanguageIcon} from '@heroicons/react/24/outline';
|
||||
import {Lang} from '../Model/lang';
|
||||
|
||||
function Languages(props: ComponentProps<any>) {
|
||||
return (<div className="prose">
|
||||
<h3><LanguageIcon className="icon"/> Langues</h3>
|
||||
<ul>
|
||||
{props.langs.map((l: Lang) => <li key={l.lang}>{l.lang} : {l.level}</li>)}
|
||||
</ul>
|
||||
</div>);
|
||||
}
|
||||
|
||||
export default Languages;
|
23
src/Components/SideProjects.tsx
Normal file
23
src/Components/SideProjects.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import React, {ComponentProps} from 'react';
|
||||
import {BeakerIcon} from '@heroicons/react/24/outline';
|
||||
import {SideProjectCats} from '../Model/side-project';
|
||||
|
||||
function SideProjects(props: ComponentProps<any>) {
|
||||
return (<div className="prose">
|
||||
<h3><BeakerIcon className="icon"/> Projets personnels</h3>
|
||||
{props.projs.map((proj: SideProjectCats) => {
|
||||
return (<div key={proj.category}>
|
||||
<h4>{proj.category}</h4>
|
||||
<ul>
|
||||
{proj.projects.map(p => {
|
||||
return (<li key={p.description}>
|
||||
{p.title ? <div><a href={p.url}>{p.title}</a> {p.description}</div> : <div>{p.description}</div>}
|
||||
</li>)
|
||||
})}
|
||||
</ul>
|
||||
</div>)
|
||||
})}
|
||||
</div>);
|
||||
}
|
||||
|
||||
export default SideProjects;
|
23
src/Components/Skills.tsx
Normal file
23
src/Components/Skills.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import React, {ComponentProps} from 'react';
|
||||
import {CalendarDaysIcon, CheckBadgeIcon, LanguageIcon} from '@heroicons/react/24/outline';
|
||||
import {getTagColor, Tag, TagCategory} from '../Model/tag';
|
||||
import {forIn, groupBy, map} from 'lodash';
|
||||
|
||||
function Skills(props: ComponentProps<any>) {
|
||||
const tagsByCat = groupBy(props.tags, 'category')
|
||||
return (<div className="prose">
|
||||
<h3><CheckBadgeIcon className="icon"/> Compétences</h3>
|
||||
<div className="flex flex-wrap justify-between">
|
||||
{map(tagsByCat, (tags, cat) => {
|
||||
return (<div key={cat}>
|
||||
<h4 className="m-0 mb-1.5">{cat}</h4>
|
||||
<div>
|
||||
{tags.map((t: Tag) => <button key={t.name} className={"tag " + getTagColor(t)}>{t.name}</button>)}
|
||||
</div>
|
||||
</div>)
|
||||
})}
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
|
||||
export default Skills;
|
5
src/Model/education.ts
Normal file
5
src/Model/education.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export class EducationYear {
|
||||
endDate!: string
|
||||
school!: string
|
||||
name!: string
|
||||
}
|
4
src/Model/interests.ts
Normal file
4
src/Model/interests.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export class Interest {
|
||||
theme!: string
|
||||
description!: string
|
||||
}
|
7
src/Model/job-at-company.ts
Normal file
7
src/Model/job-at-company.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export class JobAtCompany {
|
||||
jobTitle!: string
|
||||
start!: string
|
||||
end!: string
|
||||
company!: string
|
||||
tasks!: string[]
|
||||
}
|
4
src/Model/lang.ts
Normal file
4
src/Model/lang.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export class Lang {
|
||||
lang!: string
|
||||
level!: string
|
||||
}
|
10
src/Model/profile.ts
Normal file
10
src/Model/profile.ts
Normal file
@ -0,0 +1,10 @@
|
||||
export class Profile {
|
||||
name!: string
|
||||
title!: string
|
||||
quote!: string
|
||||
picture!: string
|
||||
email?: string
|
||||
phone?: string
|
||||
linkedin?: string
|
||||
source?: string
|
||||
}
|
10
src/Model/side-project.ts
Normal file
10
src/Model/side-project.ts
Normal file
@ -0,0 +1,10 @@
|
||||
export class SideProject {
|
||||
title?: string
|
||||
url?: string
|
||||
description!: string
|
||||
}
|
||||
|
||||
export class SideProjectCats {
|
||||
category!: string
|
||||
projects!: SideProject[];
|
||||
}
|
29
src/Model/tag.ts
Normal file
29
src/Model/tag.ts
Normal file
@ -0,0 +1,29 @@
|
||||
export function getTagColor(t: Tag) {
|
||||
switch (t.category) {
|
||||
case TagCategory.FRONT:
|
||||
return "bg-rose-500"
|
||||
case TagCategory.BACK:
|
||||
return "bg-indigo-600"
|
||||
case TagCategory.MOBILE:
|
||||
return "bg-yellow-500"
|
||||
case TagCategory.DB:
|
||||
return "bg-emerald-500"
|
||||
case TagCategory.OTHER:
|
||||
return "bg-stone-300"
|
||||
}
|
||||
};
|
||||
|
||||
export enum TagCategory {
|
||||
FRONT = 'Developpement Front',
|
||||
BACK = 'Developpement Back',
|
||||
MOBILE = 'Developpement Mobile',
|
||||
DB = 'Bases de données',
|
||||
OTHER = 'Autre'
|
||||
}
|
||||
|
||||
export class Tag {
|
||||
name: string = ""
|
||||
workThing: Boolean = true
|
||||
category!: TagCategory
|
||||
}
|
||||
|
3
src/index.css
Normal file
3
src/index.css
Normal file
@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
19
src/index.tsx
Normal file
19
src/index.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import './index.css';
|
||||
import CV from './CV';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
|
||||
const root = ReactDOM.createRoot(
|
||||
document.getElementById('root') as HTMLElement
|
||||
);
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<CV />
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
// to log results (for example: reportWebVitals(console.log))
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||
reportWebVitals();
|
1
src/react-app-env.d.ts
vendored
Normal file
1
src/react-app-env.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
/// <reference types="react-scripts" />
|
15
src/reportWebVitals.ts
Normal file
15
src/reportWebVitals.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { ReportHandler } from 'web-vitals';
|
||||
|
||||
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
|
||||
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||
getCLS(onPerfEntry);
|
||||
getFID(onPerfEntry);
|
||||
getFCP(onPerfEntry);
|
||||
getLCP(onPerfEntry);
|
||||
getTTFB(onPerfEntry);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default reportWebVitals;
|
5
src/setupTests.ts
Normal file
5
src/setupTests.ts
Normal file
@ -0,0 +1,5 @@
|
||||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import '@testing-library/jest-dom';
|
20
tailwind.config.js
Normal file
20
tailwind.config.js
Normal file
@ -0,0 +1,20 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: [
|
||||
"./src/**/*.{js,jsx,ts,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
container: {
|
||||
center: true,
|
||||
},
|
||||
screens: {
|
||||
sm: '640px',
|
||||
md: '768px',
|
||||
lg: '1024px'
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
require('@tailwindcss/typography')
|
||||
],
|
||||
}
|
26
tsconfig.json
Normal file
26
tsconfig.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user