diff --git a/README.md b/README.md index 198f09b..4877435 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,60 @@ # cv-generator -Application web pour générer des CV professionnels en PDF \ No newline at end of file +Application web pour générer des CV professionnels. + +--- + +## 🚀 Lancer le projet + +> ⚠️ Le projet utilise des **ES Modules natifs** (`import`/`export`). +> Les navigateurs bloquent les modules via le protocole `file://` (CORS). +> **Il faut obligatoirement servir le projet depuis un serveur local.** + +```bash +# Option 1 — serveur rapide avec Node.js +npx serve . + +# Option 2 — extension Live Server dans VSCode +# Clic droit sur index.html → "Open with Live Server" +``` + +Puis ouvrir [http://localhost:3000](http://localhost:3000) (ou le port indiqué). + +> ❌ Ne pas ouvrir `index.html` directement par double-clic — les modules ne se chargeront pas. + +--- + +## 📁 Structure du projet + +``` +css/ + form.css # Styles de la page et du formulaire + cv.css # Styles du rendu CV (à venir) +js/ + main.js # Point d'entrée : listeners DOM + orchestration + sections/ + identite.js # Collect + render de la section Identité + competences.js # Stub — Section Compétences (à implémenter) + formation.js # Stub — Section Formation (à implémenter) + experience.js # Stub — Section Expérience pro (à implémenter) + hobbies.js # Stub — Section Hobbies (à implémenter) +sections/ + identite/ # Fragment HTML de la section Identité + competences/ # Stub — à venir + formation/ # Stub — à venir + experience/ # Stub — à venir + hobbies/ # Stub — à venir +index.html +``` + +--- + +## 🗺️ Sections à venir + +| Section | Dossier | Module JS | Statut | +|---------------|--------------------------|---------------------------------|--------------| +| Identité | `sections/identite/` | `js/sections/identite.js` | ✅ Actif | +| Compétences | `sections/competences/` | `js/sections/competences.js` | 🚧 Stub | +| Formation | `sections/formation/` | `js/sections/formation.js` | 🚧 Stub | +| Expérience | `sections/experience/` | `js/sections/experience.js` | 🚧 Stub | +| Hobbies | `sections/hobbies/` | `js/sections/hobbies.js` | 🚧 Stub | diff --git a/css/cv.css b/css/cv.css new file mode 100644 index 0000000..5bc95df --- /dev/null +++ b/css/cv.css @@ -0,0 +1,90 @@ +/* ============================================= + cv.css — Styles du rendu CV généré + ============================================= */ + +/* ── Conteneur principal du CV ── */ +.cv-container { + background: #fff; + color: #1a1a2e; + border-radius: 8px; + overflow: hidden; + box-shadow: 0 4px 24px rgba(0, 0, 0, 0.3); + margin-top: 32px; + display: none; /* masqué par défaut, affiché après génération */ +} + +.cv-container.visible { + display: block; +} + +/* ── En-tête du CV ── */ +.cv-header { + background: #e94560; + color: #fff; + padding: 32px; +} + +.cv-header h2 { + font-size: 1.8rem; + font-weight: 700; + margin-bottom: 4px; +} + +.cv-header .cv-titre { + font-size: 1rem; + opacity: 0.9; + margin-bottom: 12px; +} + +.cv-header .cv-contacts { + font-size: 0.85rem; + opacity: 0.85; + display: flex; + gap: 16px; + flex-wrap: wrap; +} + +/* ── Corps du CV ── */ +.cv-body { + padding: 28px 32px; +} + +.cv-section { + margin-bottom: 28px; +} + +.cv-section h3 { + font-size: 0.8rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.1em; + color: #e94560; + border-bottom: 2px solid #e94560; + padding-bottom: 6px; + margin-bottom: 14px; +} + +/* ── Barres de compétences ── */ +.skill-bar-container { + margin-bottom: 10px; +} + +.skill-name { + font-size: 0.9rem; + margin-bottom: 4px; + color: #333; +} + +.skill-bar { + height: 6px; + background: #e0e0e0; + border-radius: 3px; + overflow: hidden; +} + +.skill-level { + height: 100%; + background: #e94560; + border-radius: 3px; + transition: width 0.4s ease; +} diff --git a/css/form.css b/css/form.css new file mode 100644 index 0000000..bc9398e --- /dev/null +++ b/css/form.css @@ -0,0 +1,123 @@ +/* ============================================= + form.css — Styles de la page et du formulaire + ============================================= */ + +*, *::before, *::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background: #0f0f0f; + color: #e0e0e0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, sans-serif; + padding: 20px; +} + +/* ── Layout ── */ +.container { + max-width: 520px; + width: 100%; +} + +header { + text-align: center; + margin-bottom: 32px; +} + +h1 { + font-size: 2.2rem; + font-weight: 700; + color: #e94560; + margin-bottom: 10px; +} + +header p { + color: #a0a0b0; + font-size: 0.95rem; +} + +footer { + text-align: center; + margin-top: 28px; + font-size: 0.8rem; + color: #4a4a6a; +} + +/* ── Card ── */ +.card { + background: #16213e; + border: 1px solid #2a2a4a; + border-radius: 12px; + padding: 32px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4); +} + +/* ── Formulaire ── */ +.form-group { + margin-bottom: 20px; +} + +label { + display: block; + font-size: 0.85rem; + color: #a0a0b0; + margin-bottom: 6px; + font-weight: 500; + letter-spacing: 0.03em; +} + +input { + width: 100%; + padding: 11px 14px; + background: #1a1a2e; + border: 1px solid #2a2a4a; + border-radius: 6px; + color: #e0e0e0; + font-size: 0.95rem; + outline: none; + transition: border-color 0.2s ease, box-shadow 0.2s ease; +} + +input::placeholder { + color: #4a4a6a; +} + +input:focus { + border-color: #e94560; + box-shadow: 0 0 0 3px rgba(233, 69, 96, 0.15); +} + +/* ── Bouton ── */ +.btn-generate { + width: 100%; + background: #e94560; + color: #fff; + border: none; + padding: 13px; + border-radius: 6px; + font-size: 1rem; + font-weight: 600; + cursor: pointer; + margin-top: 8px; + transition: background 0.2s ease; +} + +.btn-generate:hover { + background: #f05a73; +} + +/* ── Message de succès ── */ +.success-message { + display: none; + color: #4caf50; + text-align: center; + padding-top: 16px; + font-size: 0.95rem; +} diff --git a/index.html b/index.html index f9c0c29..06d87a8 100644 --- a/index.html +++ b/index.html @@ -4,122 +4,8 @@ CV Generator - + +
@@ -130,6 +16,9 @@
+ + +
+ +

@@ -196,26 +92,6 @@
- + diff --git a/js/main.js b/js/main.js new file mode 100644 index 0000000..de8c496 --- /dev/null +++ b/js/main.js @@ -0,0 +1,32 @@ +import { collectIdentite, renderIdentite } from './sections/identite.js'; +import { collectCompetences, renderCompetences } from './sections/competences.js'; +import { collectFormation, renderFormation } from './sections/formation.js'; +import { collectExperience, renderExperience } from './sections/experience.js'; +import { collectHobbies, renderHobbies } from './sections/hobbies.js'; + +function generateCV() { + const identite = collectIdentite(); + + if (!identite.nom || !identite.prenom || !identite.email || !identite.titre) return; + + renderIdentite(identite); + renderCompetences(collectCompetences()); + renderFormation(collectFormation()); + renderExperience(collectExperience()); + renderHobbies(collectHobbies()); + + localStorage.setItem('cvData', JSON.stringify(identite)); + + const success = document.getElementById('success'); + if (success) { + success.textContent = `CV prêt à être généré pour ${identite.prenom} ${identite.nom} !`; + success.style.display = 'block'; + } +} + +document.addEventListener('DOMContentLoaded', () => { + document.getElementById('cv-form')?.addEventListener('submit', (e) => { + e.preventDefault(); + generateCV(); + }); +}); diff --git a/js/sections/competences.js b/js/sections/competences.js new file mode 100644 index 0000000..5339375 --- /dev/null +++ b/js/sections/competences.js @@ -0,0 +1,5 @@ +// Stub — Section Compétences +// À implémenter : collectCompetences(), addCompetence(), renderCompetences() + +export function collectCompetences() { return []; } +export function renderCompetences(_competences) { /* no-op */ } diff --git a/js/sections/experience.js b/js/sections/experience.js new file mode 100644 index 0000000..4b310ec --- /dev/null +++ b/js/sections/experience.js @@ -0,0 +1,5 @@ +// Stub — Section Expérience professionnelle +// À implémenter : collectExperience(), addExperienceEntry(), renderExperience() + +export function collectExperience() { return []; } +export function renderExperience(_entries) { /* no-op */ } diff --git a/js/sections/formation.js b/js/sections/formation.js new file mode 100644 index 0000000..5cc479c --- /dev/null +++ b/js/sections/formation.js @@ -0,0 +1,5 @@ +// Stub — Section Formation +// À implémenter : collectFormation(), addFormationEntry(), renderFormation() + +export function collectFormation() { return []; } +export function renderFormation(_entries) { /* no-op */ } diff --git a/js/sections/hobbies.js b/js/sections/hobbies.js new file mode 100644 index 0000000..387cdc3 --- /dev/null +++ b/js/sections/hobbies.js @@ -0,0 +1,5 @@ +// Stub — Section Centres d'intérêt +// À implémenter : collectHobbies(), addHobby(), renderHobbies() + +export function collectHobbies() { return []; } +export function renderHobbies(_hobbies) { /* no-op */ } diff --git a/js/sections/identite.js b/js/sections/identite.js new file mode 100644 index 0000000..b99b02a --- /dev/null +++ b/js/sections/identite.js @@ -0,0 +1,30 @@ +/** + * identite.js — Section Identité + * Collecte les champs nom, prénom, email, titre depuis le formulaire. + */ + +/** + * @returns {{ nom: string, prenom: string, email: string, titre: string }} + */ +export function collectIdentite() { + const get = (id) => document.getElementById(id)?.value.trim() ?? ''; + return { + nom: get('nom'), + prenom: get('prenom'), + email: get('email'), + titre: get('titre'), + }; +} + +/** + * @param {{ nom: string, prenom: string, email: string, titre: string }} identite + */ +export function renderIdentite(identite) { + const set = (id, value) => { + const el = document.getElementById(id); + if (el) el.textContent = value; + }; + set('cv-nom', `${identite.prenom} ${identite.nom}`); + set('cv-titre', identite.titre); + set('cv-email', identite.email); +} diff --git a/sections/competences/.gitkeep b/sections/competences/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sections/competences/README.md b/sections/competences/README.md new file mode 100644 index 0000000..37ab4ff --- /dev/null +++ b/sections/competences/README.md @@ -0,0 +1,7 @@ +# Section : competences + +> 🚧 À implémenter — cette section sera ajoutée dans une prochaine itération. + +## Contenu prévu +- Compétences techniques (langages, outils…) +- Compétences transverses (langues, soft skills…) diff --git a/sections/experience/.gitkeep b/sections/experience/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sections/experience/README.md b/sections/experience/README.md new file mode 100644 index 0000000..ac7acca --- /dev/null +++ b/sections/experience/README.md @@ -0,0 +1,9 @@ +# Section : experience + +> 🚧 À implémenter — cette section sera ajoutée dans une prochaine itération. + +## Contenu prévu +- Poste occupé +- Entreprise +- Période (début / fin) +- Description des missions diff --git a/sections/formation/.gitkeep b/sections/formation/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sections/formation/README.md b/sections/formation/README.md new file mode 100644 index 0000000..b824669 --- /dev/null +++ b/sections/formation/README.md @@ -0,0 +1,8 @@ +# Section : formation + +> 🚧 À implémenter — cette section sera ajoutée dans une prochaine itération. + +## Contenu prévu +- Diplôme / intitulé +- Établissement +- Année d'obtention diff --git a/sections/hobbies/.gitkeep b/sections/hobbies/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sections/hobbies/README.md b/sections/hobbies/README.md new file mode 100644 index 0000000..3599422 --- /dev/null +++ b/sections/hobbies/README.md @@ -0,0 +1,6 @@ +# Section : hobbies + +> 🚧 À implémenter — cette section sera ajoutée dans une prochaine itération. + +## Contenu prévu +- Liste des centres d'intérêt / loisirs diff --git a/sections/identite/identite.html b/sections/identite/identite.html new file mode 100644 index 0000000..067352f --- /dev/null +++ b/sections/identite/identite.html @@ -0,0 +1,55 @@ + +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +