From f3ff6fd6ac37b8bfce50604c95e05374d433937d Mon Sep 17 00:00:00 2001 From: Matthias Guillitte Date: Wed, 27 Aug 2025 14:54:51 +0200 Subject: [PATCH] Added printing + Resume name input --- app/Http/Controllers/ResumeController.php | 2 +- package.json | 1 + pnpm-lock.yaml | 167 ++++++++++++++++++ .../components/resume/PrintResumeButton.vue | 18 ++ .../js/components/resume/ResumeComponent.vue | 4 +- .../js/components/resume/ResumeNameInput.vue | 58 ++++++ .../components/resume/ResumePreviewPanel.vue | 12 +- .../resume/resumeComponents/email.vue | 3 +- resources/js/lib/pdfExport.ts | 13 ++ resources/js/pages/resumes/Edit.vue | 37 +++- resources/views/app.blade.php | 4 +- 11 files changed, 303 insertions(+), 16 deletions(-) create mode 100644 resources/js/components/resume/PrintResumeButton.vue create mode 100644 resources/js/components/resume/ResumeNameInput.vue create mode 100644 resources/js/lib/pdfExport.ts diff --git a/app/Http/Controllers/ResumeController.php b/app/Http/Controllers/ResumeController.php index 7290747..d78247f 100644 --- a/app/Http/Controllers/ResumeController.php +++ b/app/Http/Controllers/ResumeController.php @@ -72,7 +72,7 @@ class ResumeController extends Controller */ public function update(UpdateResumeRequest $request, Resume $resume) { - // + $resume->update($request->validated()); } /** diff --git a/package.json b/package.json index e9145d8..f710bc5 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "concurrently": "^9.0.1", + "jspdf": "^3.0.1", "laravel-vite-plugin": "^2.0.0", "lucide-vue-next": "^0.468.0", "reka-ui": "^2.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f34be1f..01f5f7e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ importers: concurrently: specifier: ^9.0.1 version: 9.2.0 + jspdf: + specifier: ^3.0.1 + version: 3.0.1 laravel-vite-plugin: specifier: ^2.0.0 version: 2.0.0(vite@7.1.2(@types/node@22.17.2)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)) @@ -241,6 +244,10 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/runtime@7.28.3': + resolution: {integrity: sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==} + engines: {node: '>=6.9.0'} + '@babel/template@7.27.2': resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} @@ -759,6 +766,12 @@ packages: '@types/qs@6.14.0': resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} + '@types/raf@3.4.3': + resolution: {integrity: sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==} + + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/web-bluetooth@0.0.21': resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==} @@ -962,12 +975,21 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + atob@2.1.2: + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} + hasBin: true + axios@1.11.0: resolution: {integrity: sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==} balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + base64-arraybuffer@1.0.2: + resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==} + engines: {node: '>= 0.6.0'} + birpc@2.5.0: resolution: {integrity: sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ==} @@ -989,6 +1011,11 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + btoa@1.2.1: + resolution: {integrity: sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==} + engines: {node: '>= 0.4.0'} + hasBin: true + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -1011,6 +1038,10 @@ packages: caniuse-lite@1.0.30001735: resolution: {integrity: sha512-EV/laoX7Wq2J9TQlyIXRxTJqIw4sxfXS4OYgudGxBYRuTv0q7AM6yMEpU/Vo1I94thg9U6EZ2NfZx9GJq83u7w==} + canvg@3.0.11: + resolution: {integrity: sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==} + engines: {node: '>=10.0.0'} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -1059,10 +1090,16 @@ packages: resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} engines: {node: '>=12.13'} + core-js@3.45.1: + resolution: {integrity: sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg==} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + css-line-break@2.1.0: + resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -1109,6 +1146,9 @@ packages: resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} engines: {node: '>=8'} + dompurify@3.2.6: + resolution: {integrity: sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==} + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -1256,6 +1296,9 @@ packages: picomatch: optional: true + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + figures@6.1.0: resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} engines: {node: '>=18'} @@ -1369,6 +1412,10 @@ packages: hookable@5.5.3: resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + html2canvas@1.4.1: + resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==} + engines: {node: '>=8.0.0'} + human-signals@8.0.1: resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==} engines: {node: '>=18.18.0'} @@ -1468,6 +1515,9 @@ packages: engines: {node: '>=6'} hasBin: true + jspdf@3.0.1: + resolution: {integrity: sha512-qaGIxqxetdoNnFQQXxTKUD9/Z7AloLaw94fFsOiJMxbfYdBbrBuhWmbzI8TVjrw7s3jBY1PFHofBKMV/wZPapg==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -1698,6 +1748,9 @@ packages: perfect-debounce@1.0.0: resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + performance-now@2.1.0: + resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1819,6 +1872,12 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + raf@3.4.1: + resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==} + + regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + reka-ui@2.4.1: resolution: {integrity: sha512-NB7DrCsODN8MH02BWtgiExygfFcuuZ5/PTn6fMgjppmFHqePvNhmSn1LEuF35nel6PFbA4v+gdj0IoGN1yZ+vw==} peerDependencies: @@ -1839,6 +1898,10 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + rgbcolor@1.0.1: + resolution: {integrity: sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==} + engines: {node: '>= 0.8.15'} + rollup@4.46.2: resolution: {integrity: sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -1914,6 +1977,10 @@ packages: resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} engines: {node: '>=0.10.0'} + stackblur-canvas@2.7.0: + resolution: {integrity: sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==} + engines: {node: '>=0.1.14'} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -1942,6 +2009,10 @@ packages: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} + svg-pathdata@6.0.3: + resolution: {integrity: sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==} + engines: {node: '>=12.0.0'} + tailwind-merge@3.3.1: resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==} @@ -1961,6 +2032,9 @@ packages: engines: {node: '>=10'} hasBin: true + text-segmentation@1.0.3: + resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==} + tinyglobby@0.2.14: resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} engines: {node: '>=12.0.0'} @@ -2032,6 +2106,9 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + utrie@1.0.2: + resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==} + vite-dev-rpc@1.1.0: resolution: {integrity: sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A==} peerDependencies: @@ -2372,6 +2449,8 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/runtime@7.28.3': {} + '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 @@ -2778,6 +2857,12 @@ snapshots: '@types/qs@6.14.0': {} + '@types/raf@3.4.3': + optional: true + + '@types/trusted-types@2.0.7': + optional: true + '@types/web-bluetooth@0.0.21': {} '@typescript-eslint/eslint-plugin@8.39.1(@typescript-eslint/parser@8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2)': @@ -3079,6 +3164,8 @@ snapshots: asynckit@0.4.0: {} + atob@2.1.2: {} + axios@1.11.0: dependencies: follow-redirects: 1.15.11 @@ -3089,6 +3176,9 @@ snapshots: balanced-match@1.0.2: {} + base64-arraybuffer@1.0.2: + optional: true + birpc@2.5.0: {} boolbase@1.0.0: {} @@ -3113,6 +3203,8 @@ snapshots: node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.25.2) + btoa@1.2.1: {} + buffer-from@1.1.2: optional: true @@ -3134,6 +3226,18 @@ snapshots: caniuse-lite@1.0.30001735: {} + canvg@3.0.11: + dependencies: + '@babel/runtime': 7.28.3 + '@types/raf': 3.4.3 + core-js: 3.45.1 + raf: 3.4.1 + regenerator-runtime: 0.13.11 + rgbcolor: 1.0.1 + stackblur-canvas: 2.7.0 + svg-pathdata: 6.0.3 + optional: true + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -3184,12 +3288,20 @@ snapshots: dependencies: is-what: 4.1.16 + core-js@3.45.1: + optional: true + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 + css-line-break@2.1.0: + dependencies: + utrie: 1.0.2 + optional: true + cssesc@3.0.0: {} csstype@3.1.3: {} @@ -3217,6 +3329,11 @@ snapshots: detect-libc@2.0.4: {} + dompurify@3.2.6: + optionalDependencies: + '@types/trusted-types': 2.0.7 + optional: true + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -3423,6 +3540,8 @@ snapshots: optionalDependencies: picomatch: 4.0.3 + fflate@0.8.2: {} + figures@6.1.0: dependencies: is-unicode-supported: 2.1.0 @@ -3525,6 +3644,12 @@ snapshots: hookable@5.5.3: {} + html2canvas@1.4.1: + dependencies: + css-line-break: 2.1.0 + text-segmentation: 1.0.3 + optional: true + human-signals@8.0.1: {} ignore@5.3.2: {} @@ -3586,6 +3711,18 @@ snapshots: json5@2.2.3: {} + jspdf@3.0.1: + dependencies: + '@babel/runtime': 7.28.3 + atob: 2.1.2 + btoa: 1.2.1 + fflate: 0.8.2 + optionalDependencies: + canvg: 3.0.11 + core-js: 3.45.1 + dompurify: 3.2.6 + html2canvas: 1.4.1 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -3770,6 +3907,9 @@ snapshots: perfect-debounce@1.0.0: {} + performance-now@2.1.0: + optional: true + picocolors@1.1.1: {} picomatch@2.3.1: {} @@ -3820,6 +3960,14 @@ snapshots: queue-microtask@1.2.3: {} + raf@3.4.1: + dependencies: + performance-now: 2.1.0 + optional: true + + regenerator-runtime@0.13.11: + optional: true + reka-ui@2.4.1(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2)): dependencies: '@floating-ui/dom': 1.7.3 @@ -3845,6 +3993,9 @@ snapshots: rfdc@1.4.1: {} + rgbcolor@1.0.1: + optional: true + rollup@4.46.2: dependencies: '@types/estree': 1.0.8 @@ -3942,6 +4093,9 @@ snapshots: speakingurl@14.0.1: {} + stackblur-canvas@2.7.0: + optional: true + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -3968,6 +4122,9 @@ snapshots: dependencies: has-flag: 4.0.0 + svg-pathdata@6.0.3: + optional: true + tailwind-merge@3.3.1: {} tailwindcss@4.1.12: {} @@ -3991,6 +4148,11 @@ snapshots: source-map-support: 0.5.21 optional: true + text-segmentation@1.0.3: + dependencies: + utrie: 1.0.2 + optional: true + tinyglobby@0.2.14: dependencies: fdir: 6.5.0(picomatch@4.0.3) @@ -4052,6 +4214,11 @@ snapshots: util-deprecate@1.0.2: {} + utrie@1.0.2: + dependencies: + base64-arraybuffer: 1.0.2 + optional: true + vite-dev-rpc@1.1.0(vite@7.1.2(@types/node@22.17.2)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)): dependencies: birpc: 2.5.0 diff --git a/resources/js/components/resume/PrintResumeButton.vue b/resources/js/components/resume/PrintResumeButton.vue new file mode 100644 index 0000000..cdec876 --- /dev/null +++ b/resources/js/components/resume/PrintResumeButton.vue @@ -0,0 +1,18 @@ + + + diff --git a/resources/js/components/resume/ResumeComponent.vue b/resources/js/components/resume/ResumeComponent.vue index 00d75b6..6e6754e 100644 --- a/resources/js/components/resume/ResumeComponent.vue +++ b/resources/js/components/resume/ResumeComponent.vue @@ -16,5 +16,7 @@ const componentFile = defineAsyncComponent( diff --git a/resources/js/components/resume/ResumeNameInput.vue b/resources/js/components/resume/ResumeNameInput.vue new file mode 100644 index 0000000..ff1bcd7 --- /dev/null +++ b/resources/js/components/resume/ResumeNameInput.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/resources/js/components/resume/ResumePreviewPanel.vue b/resources/js/components/resume/ResumePreviewPanel.vue index 4482965..3054921 100644 --- a/resources/js/components/resume/ResumePreviewPanel.vue +++ b/resources/js/components/resume/ResumePreviewPanel.vue @@ -1,19 +1,25 @@ diff --git a/resources/js/components/resume/resumeComponents/email.vue b/resources/js/components/resume/resumeComponents/email.vue index 6553c30..f3ee514 100644 --- a/resources/js/components/resume/resumeComponents/email.vue +++ b/resources/js/components/resume/resumeComponents/email.vue @@ -8,8 +8,9 @@ const props = defineProps<{ diff --git a/resources/js/lib/pdfExport.ts b/resources/js/lib/pdfExport.ts new file mode 100644 index 0000000..af071d3 --- /dev/null +++ b/resources/js/lib/pdfExport.ts @@ -0,0 +1,13 @@ +import { jsPDF } from "jspdf"; + +export function exportToPdf(element: HTMLElement, name: string) { + const pdf = new jsPDF(); + + pdf.html(element, { + callback: function (doc) { + doc.save(name); + }, + width: 210, + windowWidth: element.scrollWidth, + }); +} diff --git a/resources/js/pages/resumes/Edit.vue b/resources/js/pages/resumes/Edit.vue index 19b79bc..0070770 100644 --- a/resources/js/pages/resumes/Edit.vue +++ b/resources/js/pages/resumes/Edit.vue @@ -2,20 +2,24 @@ import AppLayout from '@/layouts/AppLayout.vue'; import { type BreadcrumbItem } from '@/types'; import { Head } from '@inertiajs/vue3'; -import { Resume, ResumeComponent, ResumeComponentPlacement } from '@/types/resume'; +import { Resume, ResumeComponentPlacement } from '@/types/resume'; import ResumeEditPanel from '@/components/resume/ResumeEditPanel.vue'; import ResumePreviewPanel from '@/components/resume/ResumePreviewPanel.vue'; -import { ref } from 'vue'; +import { computed, ref, watch } from 'vue'; const props = defineProps<{ resume: Resume }>(); +const localResume = ref({ ...props.resume }); + +const resumeTitle = computed(() => (localResume.value.name == '' ? 'Sans titre' : localResume.value.name) ?? 'Sans titre'); + const selectedComponent = ref(null); const breadcrumbs: BreadcrumbItem[] = [ { - title: props.resume?.name ?? 'Sans titre', + title: resumeTitle.value, href: '/resumes/edit', }, ]; @@ -23,22 +27,39 @@ const breadcrumbs: BreadcrumbItem[] = [ function changeSelectedComponent(newComponent: ResumeComponentPlacement) { selectedComponent.value = newComponent; // Update the resume - props.resume.components_placements! = props.resume.components_placements!.map(component => + localResume.value.components_placements! = localResume.value.components_placements!.map(component => component.id === newComponent.id ? newComponent : component ); } -console.log('Resume : ', props.resume); +function changeResumeTitle(newTitle: string) { + console.log('Changing resume title to ', newTitle); + localResume.value.name = newTitle; +} + +console.debug('Resume : ', localResume.value); + + diff --git a/resources/views/app.blade.php b/resources/views/app.blade.php index cd275d0..161324d 100644 --- a/resources/views/app.blade.php +++ b/resources/views/app.blade.php @@ -23,11 +23,11 @@ {{-- Inline style to set the HTML background color based on our theme in app.css --}}