├── README.md ├── assets └── favicon-32x32.png ├── index.html ├── script.js └── styles.css /README.md: -------------------------------------------------------------------------------- 1 | # Click CV 2 | 3 | Click CV é um projeto que permite criar seu currículo de forma interativa, apenas clicando e ajustando os elementos na tela. Após finalizar, você pode baixar o CV diretamente em PDF. 4 | ## Sobre o Projeto 5 | 6 | - Manipulação do DOM com JavaScript – O currículo interativo permite que o usuário adicione, edite e remova seções dinamicamente, proporcionando uma experiência personalizável. 7 | - Geração de PDF a partir do HTML – Implementação da biblioteca html2pdf para converter o currículo criado pelo usuário em um documento PDF pronto para impressão. 8 | - Eventos e interatividade – Uso de eventos JavaScript para permitir a edição inline dos campos do currículo, facilitando a personalização sem necessidade de recarregar a página. 9 | 10 | O projeto foi criado para tornar a criação de currículos mais intuitiva e acessível, permitindo que qualquer pessoa construa e exporte seu CV de forma prática e rápida. 🚀 11 | ## Layout 12 | 13 | 14 | 15 | 16 | ![Captura de tela_26-2-2025_21101_click-cv vercel app](https://github.com/user-attachments/assets/a2ca0fd2-c885-47d3-b887-4a4638915f49) 17 | 18 | 19 | 20 | 21 | 22 | 23 | ## Funcionalidades 24 | 25 | - **Edição interativa do currículo**: Permite adicionar, editar e remover seções do CV dinamicamente. 26 | - **Geração de PDF**:Converte o currículo para um documento PDF pronto para impressão. 27 | - **Interface responsiva**: Layout adaptável para diferentes dispositivos, garantindo uma boa experiência do usuário. 28 | 29 | ## Tecnologias Utilizadas 30 | 31 | - **HTML**: Estrutura básica do currículo. 32 | - **CSS**: Estilização da interface, garantindo um design responsivo e moderno. 33 | - **JavaScript**: Manipulação do DOM, interatividade e lógica para edição do CV. 34 | - **Biblioteca html2pdf**: Conversão do currículo para PDF diretamente pelo navegador. 35 | -------------------------------------------------------------------------------- /assets/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rochadevj/ClickCV/787ac2c6c2cf92489044ed4ae2268c79aec6fcbc/assets/favicon-32x32.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Click CV 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 23 | 24 |
25 |
26 |
27 |
28 | SEU NOME 29 |
SUA ATUAÇÃO
30 |
31 |
32 | (51) 994587458
33 | seuemail@gmail.com
34 | linkedin/username.com
35 | Rio Grande do Sul, Brasil  36 |
37 |
38 | 39 |
40 |
41 |
42 | EXPERIÊNCIA

43 |
44 |
45 |
46 | 47 | SEU CARGO 48 |
Nome da Empresa - Ano
49 |
50 |
51 | 52 |   53 | 54 |
55 |

HABILIDADES

56 |
Suas Skills - Nível
57 |
58 | 59 |   60 |
61 |

PROJETOS

62 |
Escreva seus Projetos
63 |
64 | 65 |   66 |
67 |

IDIOMAS

68 |
Seus Idiomas
69 |
70 | 71 |   72 |
73 |
74 | 75 |
76 |
77 | PERFIL PROFISSIONAL

78 |
79 | Aqui você pode escrever as informações básicas sobre sua carreira como seu forte, algo sobre você que deseja que seu entrevistador saiba. Tente ser breve e forneça apenas as informações necessárias. Não inclua informações que já estão escritas em seu currículo em alguma outra seção.
80 |

EDUCAÇÃO

81 |
82 |
83 | 84 | SEU DIPLOMA 85 |
Nome da Instituição - Ano
86 |
87 |
88 | 89 | 90 |   91 |
92 |

93 |
Qualificações Profissionais

94 |
95 | Nesta seção, detalhe suas qualificações profissionais, certificações e cursos relevantes.
96 |
97 |
98 | 99 |   100 | 101 |
102 |
103 |
104 |
105 | 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | 2 | function printpdf() { 3 | var content = document.getElementById("resume"); 4 | 5 | const allButtons = document.querySelectorAll("#print button"); 6 | allButtons.forEach(button => { 7 | button.style.display = "none"; 8 | }); 9 | 10 | let allInputCheckboxes = document.querySelectorAll(".input-checkbox"); 11 | allInputCheckboxes.forEach(input => { 12 | input.style.display = "none"; 13 | }); 14 | 15 | 16 | html2pdf(content, { 17 | html2canvas: { scale: 1, logging: true, dpi: 500 }, 18 | pagebreak: { mode: 'avoid-all' } 19 | }).then(() => { 20 | allButtons.forEach(button => { 21 | button.style.display = "inline-block"; 22 | }); 23 | allInputCheckboxes.forEach(input => { 24 | input.style.display = "inline-block"; 25 | }); 26 | }); 27 | } 28 | 29 | document.addEventListener("DOMContentLoaded", function () { 30 | const expContainer = document.getElementById("experience"); 31 | const addExpBtn = document.getElementById("expadd"); 32 | const remExpBtn = document.getElementById("exprem"); 33 | 34 | 35 | addExpBtn.addEventListener("click", function () { 36 | let newExp = document.createElement("div"); 37 | newExp.classList.add("expblock"); 38 | newExp.innerHTML = ` 39 | 40 | SEU CARGO 41 |
Nome da Empresa - Ano
42 | `; 43 | expContainer.appendChild(newExp); 44 | }); 45 | 46 | 47 | remExpBtn.addEventListener("click", function () { 48 | if (expContainer.children.length > 1) { 49 | expContainer.removeChild(expContainer.lastElementChild); 50 | } 51 | }); 52 | }); 53 | 54 | 55 | 56 | function addedu() { 57 | const head = document.createElement('div'); 58 | document.getElementById("education").appendChild(head); 59 | head.innerHTML = ('
SEU DIPLOMA
Nome da Instituição - Ano
'); 60 | saveresume(); 61 | } 62 | function remedu(event) { 63 | let val = 0; 64 | let empty = true; 65 | const allInputCheckboxes = event.target.parentElement.getElementsByClassName("input-checkbox"); 66 | const array = Array.from(allInputCheckboxes); 67 | if (array.length === 0) { 68 | alert("Não há nada para deletar!") 69 | } 70 | else { 71 | console.log(array); 72 | array.forEach(element => { 73 | if (element.checked === true) { 74 | val = 1; 75 | element.parentElement.parentElement.remove(); 76 | } 77 | }) 78 | if (val === 0) alert("Por favor, marque as caixas de seleção para excluir o campo obrigatório!") 79 | } 80 | saveresume(); 81 | } 82 | 83 | 84 | function addskill() { 85 | const head = document.createElement('div'); 86 | document.getElementById("skills").appendChild(head); 87 | head.innerHTML = ('
   Sua expêriencia aqui
'); 88 | saveresume(); 89 | } 90 | 91 | function remskill(event) { 92 | let val = 0; 93 | const allInputCheckboxes = event.target.parentElement.getElementsByClassName("input-checkbox"); 94 | const array = Array.from(allInputCheckboxes); 95 | if (array.length === 0) { 96 | alert("Não há nada para deletar!") 97 | } 98 | else { 99 | console.log(array); 100 | array.forEach(element => { 101 | if (element.checked === true) { 102 | val = 1; 103 | element.parentElement.parentElement.remove(); 104 | } 105 | }) 106 | if (val === 0) alert("Por favor, marque as caixas de seleção para excluir o campo obrigatório!") 107 | } 108 | saveresume(); 109 | } 110 | 111 | 112 | function addLang() { 113 | const head = document.createElement('div'); 114 | document.getElementById("languages").appendChild(head); 115 | head.innerHTML = ('
Suas Skills - Nível
'); 116 | saveresume(); 117 | } 118 | function remLang(event) { 119 | let val = 0; 120 | const allInputCheckboxes = event.target.parentElement.getElementsByClassName("input-checkbox"); 121 | const array = Array.from(allInputCheckboxes); 122 | if (array.length === 0) { 123 | alert("Não há nada para deletar!") 124 | } 125 | else { 126 | console.log(array); 127 | array.forEach(element => { 128 | if (element.checked === true) { 129 | val = 1; 130 | element.parentElement.parentElement.remove(); 131 | } 132 | }) 133 | if (val === 0) alert("Por favor, marque as caixas de seleção para excluir o campo obrigatório!") 134 | } 135 | saveresume(); 136 | } 137 | 138 | 139 | function addAch() { 140 | const head = document.createElement('div'); 141 | document.getElementById("achievement").appendChild(head); 142 | head.innerHTML = ('
Escreva seus Projetos
'); 143 | saveresume(); 144 | } 145 | function remAch(event) { 146 | let val = 0; 147 | const allInputCheckboxes = event.target.parentElement.getElementsByClassName("input-checkbox"); 148 | const array = Array.from(allInputCheckboxes); 149 | if (array.length === 0) { 150 | alert("Não há nada para deletar!") 151 | } 152 | else { 153 | console.log(array); 154 | array.forEach(element => { 155 | if (element.checked === true) { 156 | val = 1; 157 | element.parentElement.parentElement.remove(); 158 | } 159 | }) 160 | if (val === 0) alert("Por favor, marque as caixas de seleção para excluir o campo obrigatório!") 161 | } 162 | saveresume(); 163 | } 164 | 165 | 166 | function addInt() { 167 | const head = document.createElement('div'); 168 | document.getElementById("interest").appendChild(head); 169 | head.innerHTML = ('
Seus Idiomas
'); 170 | saveresume(); 171 | } 172 | function remInt(event) { 173 | let val = 0; 174 | const allInputCheckboxes = event.target.parentElement.getElementsByClassName("input-checkbox"); 175 | const array = Array.from(allInputCheckboxes); 176 | if (array.length === 0) { 177 | alert("Não há nada para deletar!") 178 | } 179 | else { 180 | array.forEach(element => { 181 | if (element.checked === true) { 182 | val = 1; 183 | element.parentElement.parentElement.remove(); 184 | } 185 | }) 186 | if (val === 0) alert("Por favor, marque as caixas de seleção para excluir o campo obrigatório!") 187 | } 188 | saveresume(); 189 | } 190 | 191 | let maxNewSection = 1; 192 | function addsec() { 193 | if (maxNewSection < 3) { 194 | const head = document.createElement('div'); 195 | document.getElementById("newsec").appendChild(head); 196 | if (maxNewSection === 1) { 197 | head.innerHTML = ('
Qualificações Profissionais

Nesta seção, detalhe suas qualificações profissionais, certificações e cursos relevantes.
'); 198 | } 199 | else { 200 | head.innerHTML = ('


Qualificações Profissionais

Nesta seção, detalhe suas qualificações profissionais, certificações e cursos relevantes.
'); 201 | } 202 | 203 | maxNewSection = maxNewSection + 1; 204 | } 205 | else { 206 | alert("Somente três novos tópicos podem ser adicionados!") 207 | 208 | } 209 | saveresume(); 210 | } 211 | function remsec(event) { 212 | let val = 0; 213 | const allInputCheckboxes = event.target.parentElement.getElementsByClassName("input-checkbox"); 214 | const array = Array.from(allInputCheckboxes); 215 | if (array.length === 0) { 216 | alert("Não há nada para deletar!") 217 | } 218 | else { 219 | console.log(array); 220 | array.forEach(element => { 221 | if (element.checked === true) { 222 | val = 1; 223 | maxNewSection = maxNewSection - 1; 224 | element.parentElement.parentElement.remove(); 225 | } 226 | }) 227 | if (val === 0) alert("Por favor, marque as caixas de seleção para excluir o campo obrigatório!") 228 | } 229 | saveresume(); 230 | } 231 | 232 | function saveresume() { 233 | var sec = document.getElementById("print"); 234 | value1 = sec.innerHTML; 235 | var info = document.getElementById("custinfo"); 236 | info.value = value1; 237 | } 238 | 239 | 240 | function isMobile() { 241 | return window.innerWidth <= 768; 242 | } 243 | 244 | function updateMobileView() { 245 | if (isMobile()) { 246 | document.querySelectorAll(".input-checkbox").forEach(input => { 247 | input.style.width = "20px"; 248 | input.style.height = "20px"; 249 | }); 250 | 251 | document.querySelectorAll("#print button").forEach(button => { 252 | button.style.fontSize = "14px"; 253 | button.style.padding = "8px"; 254 | }); 255 | 256 | document.getElementById("resume").style.fontSize = "14px"; 257 | } 258 | } 259 | 260 | window.addEventListener("load", updateMobileView); 261 | window.addEventListener("resize", updateMobileView); 262 | 263 | 264 | function adjustForPrint() { 265 | document.querySelectorAll("h2, h3").forEach(title => { 266 | let nextElement = title.nextElementSibling; 267 | 268 | if (nextElement && nextElement.getBoundingClientRect().top - title.getBoundingClientRect().bottom < 50) { 269 | title.classList.add("new-page"); 270 | } 271 | }); 272 | } 273 | window.addEventListener("load", adjustForPrint); 274 | -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Raleway&display=swap'); 2 | @import url('https://fonts.googleapis.com/css2?family=Barlow:wght@500&display=swap'); 3 | 4 | * { 5 | margin: 0; 6 | padding: 0; 7 | font-weight: 500; 8 | font-size: 14px; 9 | } 10 | 11 | body { 12 | background: linear-gradient(135deg, #E3E3E3 0%, #9a9a9a 100%); 13 | display: grid; 14 | place-items: center; 15 | font-weight: 450; 16 | opacity: 1; 17 | } 18 | 19 | .none { 20 | display: none; 21 | } 22 | 23 | .resume { 24 | margin-top: 20px; 25 | width: 800px; 26 | box-shadow: rgba(17, 17, 26, 0.1) 0px 4px 16px, rgba(17, 17, 26, 0.1) 0px 8px 24px, rgba(17, 17, 26, 0.1) 0px 16px 56px; 27 | } 28 | 29 | #print { 30 | background-color: #fff; 31 | padding: 30px 50px; 32 | height: 1120px; 33 | overflow: hidden; 34 | } 35 | 36 | .head { 37 | display: grid; 38 | grid-template-columns: 3fr 1.5fr; 39 | } 40 | 41 | .head .main .name { 42 | font-size: 55px; 43 | font-family: 'Raleway', sans-serif; 44 | } 45 | 46 | .head .main span:nth-child(2) { 47 | color: rgb(100, 100, 100); 48 | font-size: 55px; 49 | font-family: 'Raleway', sans-serif; 50 | margin-left: 5px; 51 | } 52 | 53 | .head .main .post { 54 | font-family: 'Barlow', sans-serif; 55 | } 56 | 57 | .head .contacts { 58 | text-align: right; 59 | padding-top: 7px; 60 | } 61 | 62 | .head .contacts .content { 63 | font-weight: 500; 64 | padding-right: 5px; 65 | } 66 | 67 | .head .contacts .symbol { 68 | margin-right: 5px; 69 | font-size: 15px; 70 | width: 17px; 71 | height: 17px; 72 | } 73 | 74 | .line { 75 | height: 0.5px; 76 | background-color: rgb(87, 87, 87); 77 | margin: 25px 0; 78 | margin-bottom: 50px; 79 | } 80 | 81 | .mainbody { 82 | display: grid; 83 | grid-template-columns: 10fr 1fr 17fr; 84 | height: 900px; 85 | } 86 | 87 | .mainbody .border { 88 | background-color: rgb(87, 87, 87); 89 | width: 3px; 90 | opacity: 2; 91 | } 92 | 93 | .mainbody .rightside { 94 | padding-left: 15px; 95 | } 96 | 97 | .title { 98 | font-weight: 700; 99 | font-size: 18px; 100 | border: none; 101 | padding-bottom: 3px; 102 | border-bottom: 2px greenyellow solid; 103 | } 104 | 105 | .skill { 106 | margin-bottom: 6px; 107 | } 108 | 109 | button { 110 | margin: 15px 0; 111 | } 112 | 113 | .language { 114 | margin-bottom: 6px; 115 | } 116 | 117 | .language span:nth-child(odd) { 118 | font-weight: 700; 119 | } 120 | 121 | .edublock { 122 | margin-bottom: 10px; 123 | } 124 | 125 | .edublock .head { 126 | font-weight: 700; 127 | font-size: 17px; 128 | } 129 | 130 | .navbtn { 131 | position: fixed; 132 | top: 40%; 133 | left: 4%; 134 | transform: translate(-40%, -4%); 135 | height: 60px; 136 | width: 60px; 137 | border-radius: 50%; 138 | border: #fff 2px solid; 139 | transition: 300ms ease-in-out; 140 | box-shadow: rgba(17, 17, 26, 0.1) 0px 4px 16px, rgba(17, 17, 26, 0.1) 0px 8px 24px, rgba(17, 17, 26, 0.1) 0px 16px 56px; 141 | } 142 | 143 | .navbtn:nth-child(2) { 144 | top: 50%; 145 | left: 4.4%; 146 | transform: translate(-50%, -4.4%); 147 | } 148 | 149 | .navbtn:nth-child(3) { 150 | top: 60%; 151 | left: 4.8%; 152 | transform: translate(-60%, -4.8%); 153 | } 154 | 155 | .navbtn:hover { 156 | background-color: black; 157 | color: #fff; 158 | border: #000 2px solid; 159 | height: 65px; 160 | width: 65px; 161 | } 162 | 163 | .input-checkbox { 164 | margin-right: 10px; 165 | } 166 | 167 | .education-head { 168 | font-weight: 700; 169 | font-size: 17px; 170 | } 171 | 172 | @media screen and (max-width: 480px) { 173 | .resume { 174 | width: 95%; 175 | margin-top: 10px; 176 | padding: 15px; 177 | } 178 | 179 | #print { 180 | padding: 10px; 181 | height: auto; 182 | } 183 | 184 | .head .main .name { 185 | font-size: 28px; 186 | } 187 | 188 | .head .main span:nth-child(2) { 189 | font-size: 28px; 190 | } 191 | 192 | .head .main .post { 193 | font-size: 13px; 194 | } 195 | 196 | .head .contacts { 197 | text-align: center; 198 | font-size: 11px; 199 | } 200 | 201 | .mainbody { 202 | display: flex; 203 | flex-direction: column; 204 | height: auto; 205 | } 206 | 207 | .mainbody .border { 208 | display: none; 209 | } 210 | 211 | .mainbody .rightside { 212 | padding-left: 0; 213 | } 214 | 215 | .title { 216 | font-size: 14px; 217 | } 218 | 219 | .experience, .skills, .projects { 220 | padding: 3px; 221 | margin-bottom: 4px; 222 | } 223 | 224 | 225 | .section-container { 226 | padding: 5px; 227 | } 228 | 229 | .section-container label { 230 | font-size: 12px; 231 | } 232 | 233 | .section-container input, 234 | .section-container button { 235 | width: 100%; 236 | font-size: 12px; 237 | margin-bottom: 5px; 238 | padding: 5px 8px; 239 | } 240 | 241 | .nav { 242 | position: fixed; 243 | bottom: 60px; 244 | left: 50%; 245 | transform: translateX(-50%); 246 | display: flex; 247 | justify-content: center; 248 | align-items: center; 249 | gap: 50px; 250 | width: auto; 251 | z-index: 1000; 252 | } 253 | 254 | .navbtn { 255 | position: relative; 256 | top: auto; 257 | left: auto; 258 | transform: none; 259 | height: 50px; 260 | width: 50px; 261 | border-radius: 50%; 262 | border: #fff 2px solid; 263 | transition: 300ms ease-in-out; 264 | box-shadow: rgba(17, 17, 26, 0.1) 0px 4px 16px, rgba(17, 17, 26, 0.1) 0px 8px 24px, rgba(17, 17, 26, 0.1) 0px 16px 56px; 265 | display: flex; 266 | justify-content: center; 267 | align-items: center; 268 | background-color: #000; 269 | color: white; 270 | } 271 | 272 | .navbtn:hover { 273 | height: 55px; 274 | width: 55px; 275 | } 276 | 277 | .footer-buttons { 278 | position: fixed; 279 | bottom: 10px; 280 | left: 50%; 281 | transform: translateX(-50%); 282 | display: flex; 283 | gap: 10px; 284 | } 285 | 286 | .footer-buttons .navbtn { 287 | height: 45px; 288 | width: 45px; 289 | background-color: gray; 290 | } 291 | 292 | 293 | .content { 294 | display: inline-block; 295 | word-break: break-all; 296 | overflow-wrap: break-word; 297 | max-width: 100%; 298 | font-size: 14px; 299 | } 300 | 301 | .symbol { 302 | display: inline-block; 303 | vertical-align: middle; 304 | margin-left: 5px; 305 | } 306 | 307 | .navbtn[href] { 308 | display: none; 309 | } 310 | 311 | .edublock, .skill, .language, .achieve { 312 | font-size: 14px; 313 | padding: 5px; 314 | } 315 | @media print { 316 | h1, h2, h3 { 317 | page-break-after: avoid; 318 | page-break-inside: avoid; 319 | } 320 | 321 | .section, .content-block { 322 | page-break-inside: avoid; 323 | } 324 | 325 | .new-page { 326 | break-before: page; 327 | } 328 | } 329 | 330 | } 331 | --------------------------------------------------------------------------------