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
generated
vendored
Normal file
5
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
13
.idea/cv.iml
generated
Normal file
13
.idea/cv.iml
generated
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
generated
Normal file
6
.idea/dictionaries
generated
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
generated
Normal file
6
.idea/encodings.xml
generated
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
generated
Normal file
6
.idea/inspectionProfiles/Project_Default.xml
generated
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
generated
Normal file
8
.idea/modules.xml
generated
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
generated
Normal file
0
.idea/sonarlint/issuestore/index.pb
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
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
generated
Normal file
4
.idea/watcherTasks.xml
generated
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
|
# 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…
x
Reference in New Issue
Block a user