Add PDF generation functionality and update layout styles

This commit is contained in:
yoosangwook 2025-05-28 14:03:38 +09:00
parent a97e6cc5e1
commit 9ca1d76fdf
5 changed files with 367 additions and 152 deletions

2
.gitignore vendored
View File

@ -39,3 +39,5 @@ yarn-error.log*
# typescript # typescript
*.tsbuildinfo *.tsbuildinfo
next-env.d.ts next-env.d.ts
/.idea

View File

@ -12,6 +12,7 @@
"next": "15.3.1", "next": "15.3.1",
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"react-to-pdf": "^2.0.0",
"sass": "^1.87.0", "sass": "^1.87.0",
"swiper": "^11.2.6" "swiper": "^11.2.6"
}, },

175
pnpm-lock.yaml generated
View File

@ -17,6 +17,9 @@ importers:
react-dom: react-dom:
specifier: ^19.0.0 specifier: ^19.0.0
version: 19.1.0(react@19.1.0) version: 19.1.0(react@19.1.0)
react-to-pdf:
specifier: ^2.0.0
version: 2.0.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
sass: sass:
specifier: ^1.87.0 specifier: ^1.87.0
version: 1.87.0 version: 1.87.0
@ -49,6 +52,10 @@ packages:
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
engines: {node: '>=10'} engines: {node: '>=10'}
'@babel/runtime@7.27.3':
resolution: {integrity: sha512-7EYtGezsdiDMyY80+65EzwiGmcJqpmcZCojSXaRgdrBaGtWTgDZKq69cPIVped6MkIM78cTQ2GOiEYjwOlG4xw==}
engines: {node: '>=6.9.0'}
'@emnapi/runtime@1.4.3': '@emnapi/runtime@1.4.3':
resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==}
@ -392,6 +399,9 @@ packages:
'@types/node@20.17.30': '@types/node@20.17.30':
resolution: {integrity: sha512-7zf4YyHA+jvBNfVrk2Gtvs6x7E8V+YDW05bNfG2XkWDJfYRXrTiP/DsB2zSYTaHX0bGIujTBQdMVAhb+j7mwpg==} resolution: {integrity: sha512-7zf4YyHA+jvBNfVrk2Gtvs6x7E8V+YDW05bNfG2XkWDJfYRXrTiP/DsB2zSYTaHX0bGIujTBQdMVAhb+j7mwpg==}
'@types/raf@3.4.3':
resolution: {integrity: sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==}
'@types/react-dom@19.1.2': '@types/react-dom@19.1.2':
resolution: {integrity: sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw==} resolution: {integrity: sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw==}
peerDependencies: peerDependencies:
@ -400,10 +410,27 @@ packages:
'@types/react@19.1.2': '@types/react@19.1.2':
resolution: {integrity: sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw==} resolution: {integrity: sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw==}
'@types/trusted-types@2.0.7':
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
atob@2.1.2:
resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==}
engines: {node: '>= 4.5.0'}
hasBin: true
base64-arraybuffer@1.0.2:
resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==}
engines: {node: '>= 0.6.0'}
braces@3.0.3: braces@3.0.3:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'} engines: {node: '>=8'}
btoa@1.2.1:
resolution: {integrity: sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==}
engines: {node: '>= 0.4.0'}
hasBin: true
busboy@1.6.0: busboy@1.6.0:
resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
engines: {node: '>=10.16.0'} engines: {node: '>=10.16.0'}
@ -411,6 +438,10 @@ packages:
caniuse-lite@1.0.30001715: caniuse-lite@1.0.30001715:
resolution: {integrity: sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==} resolution: {integrity: sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==}
canvg@3.0.11:
resolution: {integrity: sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==}
engines: {node: '>=10.0.0'}
chokidar@4.0.3: chokidar@4.0.3:
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
engines: {node: '>= 14.16.0'} engines: {node: '>= 14.16.0'}
@ -432,6 +463,12 @@ packages:
resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
engines: {node: '>=12.5.0'} engines: {node: '>=12.5.0'}
core-js@3.42.0:
resolution: {integrity: sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==}
css-line-break@2.1.0:
resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==}
csstype@3.1.3: csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
@ -444,10 +481,16 @@ packages:
resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
engines: {node: '>=8'} engines: {node: '>=8'}
dompurify@3.2.6:
resolution: {integrity: sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==}
enhanced-resolve@5.18.1: enhanced-resolve@5.18.1:
resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==}
engines: {node: '>=10.13.0'} engines: {node: '>=10.13.0'}
fflate@0.8.2:
resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
fill-range@7.1.1: fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -455,6 +498,10 @@ packages:
graceful-fs@4.2.11: graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
html2canvas@1.4.1:
resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==}
engines: {node: '>=8.0.0'}
immutable@5.1.1: immutable@5.1.1:
resolution: {integrity: sha512-3jatXi9ObIsPGr3N5hGw/vWWcTkq6hUYhpQz4k0wLC+owqWi/LiugIw9x0EdNZ2yGedKN/HzePiBvaJRXa0Ujg==} resolution: {integrity: sha512-3jatXi9ObIsPGr3N5hGw/vWWcTkq6hUYhpQz4k0wLC+owqWi/LiugIw9x0EdNZ2yGedKN/HzePiBvaJRXa0Ujg==}
@ -477,6 +524,9 @@ packages:
resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==}
hasBin: true hasBin: true
jspdf@3.0.1:
resolution: {integrity: sha512-qaGIxqxetdoNnFQQXxTKUD9/Z7AloLaw94fFsOiJMxbfYdBbrBuhWmbzI8TVjrw7s3jBY1PFHofBKMV/wZPapg==}
lightningcss-darwin-arm64@1.29.2: lightningcss-darwin-arm64@1.29.2:
resolution: {integrity: sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==} resolution: {integrity: sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
@ -574,6 +624,9 @@ packages:
node-addon-api@7.1.1: node-addon-api@7.1.1:
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
performance-now@2.1.0:
resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==}
picocolors@1.1.1: picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@ -589,11 +642,20 @@ packages:
resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==}
engines: {node: ^10 || ^12 || >=14} engines: {node: ^10 || ^12 || >=14}
raf@3.4.1:
resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==}
react-dom@19.1.0: react-dom@19.1.0:
resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==} resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==}
peerDependencies: peerDependencies:
react: ^19.1.0 react: ^19.1.0
react-to-pdf@2.0.0:
resolution: {integrity: sha512-QZTgOpVLtBUdYFOBnye9uZaGR3LYSF2t0ATfVmED3QJYIwsmRVNs6/W0mpcipde85b4cvZoqXUx9V3VBWg8EpQ==}
peerDependencies:
react: '>=16.8'
react-dom: '>=16.8'
react@19.1.0: react@19.1.0:
resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -602,6 +664,13 @@ packages:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'} engines: {node: '>= 14.18.0'}
regenerator-runtime@0.13.11:
resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
rgbcolor@1.0.1:
resolution: {integrity: sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==}
engines: {node: '>= 0.8.15'}
sass@1.87.0: sass@1.87.0:
resolution: {integrity: sha512-d0NoFH4v6SjEK7BoX810Jsrhj7IQSYHAHLi/iSpgqKc7LaIDshFRlSg5LOymf9FqQhxEHs2W5ZQXlvy0KD45Uw==} resolution: {integrity: sha512-d0NoFH4v6SjEK7BoX810Jsrhj7IQSYHAHLi/iSpgqKc7LaIDshFRlSg5LOymf9FqQhxEHs2W5ZQXlvy0KD45Uw==}
engines: {node: '>=14.0.0'} engines: {node: '>=14.0.0'}
@ -626,6 +695,10 @@ packages:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
stackblur-canvas@2.7.0:
resolution: {integrity: sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==}
engines: {node: '>=0.1.14'}
streamsearch@1.1.0: streamsearch@1.1.0:
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
engines: {node: '>=10.0.0'} engines: {node: '>=10.0.0'}
@ -643,6 +716,10 @@ packages:
babel-plugin-macros: babel-plugin-macros:
optional: true optional: true
svg-pathdata@6.0.3:
resolution: {integrity: sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==}
engines: {node: '>=12.0.0'}
swiper@11.2.6: swiper@11.2.6:
resolution: {integrity: sha512-8aXpYKtjy3DjcbzZfz+/OX/GhcU5h+looA6PbAzHMZT6ESSycSp9nAjPCenczgJyslV+rUGse64LMGpWE3PX9Q==} resolution: {integrity: sha512-8aXpYKtjy3DjcbzZfz+/OX/GhcU5h+looA6PbAzHMZT6ESSycSp9nAjPCenczgJyslV+rUGse64LMGpWE3PX9Q==}
engines: {node: '>= 4.7.0'} engines: {node: '>= 4.7.0'}
@ -654,6 +731,9 @@ packages:
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
engines: {node: '>=6'} engines: {node: '>=6'}
text-segmentation@1.0.3:
resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==}
to-regex-range@5.0.1: to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'} engines: {node: '>=8.0'}
@ -669,10 +749,15 @@ packages:
undici-types@6.19.8: undici-types@6.19.8:
resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
utrie@1.0.2:
resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==}
snapshots: snapshots:
'@alloc/quick-lru@5.2.0': {} '@alloc/quick-lru@5.2.0': {}
'@babel/runtime@7.27.3': {}
'@emnapi/runtime@1.4.3': '@emnapi/runtime@1.4.3':
dependencies: dependencies:
tslib: 2.8.1 tslib: 2.8.1
@ -919,6 +1004,9 @@ snapshots:
dependencies: dependencies:
undici-types: 6.19.8 undici-types: 6.19.8
'@types/raf@3.4.3':
optional: true
'@types/react-dom@19.1.2(@types/react@19.1.2)': '@types/react-dom@19.1.2(@types/react@19.1.2)':
dependencies: dependencies:
'@types/react': 19.1.2 '@types/react': 19.1.2
@ -927,17 +1015,38 @@ snapshots:
dependencies: dependencies:
csstype: 3.1.3 csstype: 3.1.3
'@types/trusted-types@2.0.7':
optional: true
atob@2.1.2: {}
base64-arraybuffer@1.0.2: {}
braces@3.0.3: braces@3.0.3:
dependencies: dependencies:
fill-range: 7.1.1 fill-range: 7.1.1
optional: true optional: true
btoa@1.2.1: {}
busboy@1.6.0: busboy@1.6.0:
dependencies: dependencies:
streamsearch: 1.1.0 streamsearch: 1.1.0
caniuse-lite@1.0.30001715: {} caniuse-lite@1.0.30001715: {}
canvg@3.0.11:
dependencies:
'@babel/runtime': 7.27.3
'@types/raf': 3.4.3
core-js: 3.42.0
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
chokidar@4.0.3: chokidar@4.0.3:
dependencies: dependencies:
readdirp: 4.1.2 readdirp: 4.1.2
@ -964,6 +1073,13 @@ snapshots:
color-string: 1.9.1 color-string: 1.9.1
optional: true optional: true
core-js@3.42.0:
optional: true
css-line-break@2.1.0:
dependencies:
utrie: 1.0.2
csstype@3.1.3: {} csstype@3.1.3: {}
detect-libc@1.0.3: detect-libc@1.0.3:
@ -971,11 +1087,18 @@ snapshots:
detect-libc@2.0.4: {} detect-libc@2.0.4: {}
dompurify@3.2.6:
optionalDependencies:
'@types/trusted-types': 2.0.7
optional: true
enhanced-resolve@5.18.1: enhanced-resolve@5.18.1:
dependencies: dependencies:
graceful-fs: 4.2.11 graceful-fs: 4.2.11
tapable: 2.2.1 tapable: 2.2.1
fflate@0.8.2: {}
fill-range@7.1.1: fill-range@7.1.1:
dependencies: dependencies:
to-regex-range: 5.0.1 to-regex-range: 5.0.1
@ -983,6 +1106,11 @@ snapshots:
graceful-fs@4.2.11: {} graceful-fs@4.2.11: {}
html2canvas@1.4.1:
dependencies:
css-line-break: 2.1.0
text-segmentation: 1.0.3
immutable@5.1.1: {} immutable@5.1.1: {}
is-arrayish@0.3.2: is-arrayish@0.3.2:
@ -1001,6 +1129,18 @@ snapshots:
jiti@2.4.2: {} jiti@2.4.2: {}
jspdf@3.0.1:
dependencies:
'@babel/runtime': 7.27.3
atob: 2.1.2
btoa: 1.2.1
fflate: 0.8.2
optionalDependencies:
canvg: 3.0.11
core-js: 3.42.0
dompurify: 3.2.6
html2canvas: 1.4.1
lightningcss-darwin-arm64@1.29.2: lightningcss-darwin-arm64@1.29.2:
optional: true optional: true
@ -1083,6 +1223,9 @@ snapshots:
node-addon-api@7.1.1: node-addon-api@7.1.1:
optional: true optional: true
performance-now@2.1.0:
optional: true
picocolors@1.1.1: {} picocolors@1.1.1: {}
picomatch@2.3.1: picomatch@2.3.1:
@ -1100,15 +1243,33 @@ snapshots:
picocolors: 1.1.1 picocolors: 1.1.1
source-map-js: 1.2.1 source-map-js: 1.2.1
raf@3.4.1:
dependencies:
performance-now: 2.1.0
optional: true
react-dom@19.1.0(react@19.1.0): react-dom@19.1.0(react@19.1.0):
dependencies: dependencies:
react: 19.1.0 react: 19.1.0
scheduler: 0.26.0 scheduler: 0.26.0
react-to-pdf@2.0.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
html2canvas: 1.4.1
jspdf: 3.0.1
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
react@19.1.0: {} react@19.1.0: {}
readdirp@4.1.2: {} readdirp@4.1.2: {}
regenerator-runtime@0.13.11:
optional: true
rgbcolor@1.0.1:
optional: true
sass@1.87.0: sass@1.87.0:
dependencies: dependencies:
chokidar: 4.0.3 chokidar: 4.0.3
@ -1157,6 +1318,9 @@ snapshots:
source-map-js@1.2.1: {} source-map-js@1.2.1: {}
stackblur-canvas@2.7.0:
optional: true
streamsearch@1.1.0: {} streamsearch@1.1.0: {}
styled-jsx@5.1.6(react@19.1.0): styled-jsx@5.1.6(react@19.1.0):
@ -1164,12 +1328,19 @@ snapshots:
client-only: 0.0.1 client-only: 0.0.1
react: 19.1.0 react: 19.1.0
svg-pathdata@6.0.3:
optional: true
swiper@11.2.6: {} swiper@11.2.6: {}
tailwindcss@4.1.4: {} tailwindcss@4.1.4: {}
tapable@2.2.1: {} tapable@2.2.1: {}
text-segmentation@1.0.3:
dependencies:
utrie: 1.0.2
to-regex-range@5.0.1: to-regex-range@5.0.1:
dependencies: dependencies:
is-number: 7.0.0 is-number: 7.0.0
@ -1180,3 +1351,7 @@ snapshots:
typescript@5.8.3: {} typescript@5.8.3: {}
undici-types@6.19.8: {} undici-types@6.19.8: {}
utrie@1.0.2:
dependencies:
base64-arraybuffer: 1.0.2

View File

@ -1,6 +1,6 @@
import type { Metadata } from "next"; import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google"; import { Geist, Geist_Mono } from "next/font/google";
import '@/styles/style.scss' import "@/styles/style.scss";
import Spinner from "@/components/layouts/Spinner"; import Spinner from "@/components/layouts/Spinner";
const geistSans = Geist({ const geistSans = Geist({

View File

@ -1,6 +1,42 @@
export default function PDFViewContents(){ "use client";
return(
<div className="pdf-contents"> import { useRef } from "react";
import generatePDF, { Margin, Resolution } from "react-to-pdf";
export default function PDFViewContents() {
const targetRef = useRef<HTMLDivElement>(null);
const handleDownPdf = () => {
const options = {
method: "open" as const,
resolution: Resolution.HIGH,
page: {
margin: Margin.SMALL,
format: "A4",
orientation: "portrait" as const, // 'portrait' 세로 | 'landscape' 가로
},
canvas: {
mimeType: "image/png" as const,
qualityRatio: 1,
},
overrides: {
pdf: {
compress: true,
},
canvas: {
useCORS: true,
},
},
};
generatePDF(targetRef, options);
// generatePDF(targetRef, { filename: 'page.pdf' })
};
return (
<>
<button className="btn-frame n-blue min" onClick={handleDownPdf}>
PDF Download
</button>
<div className="pdf-contents" ref={targetRef}>
<div className="pdf-cont-head"> <div className="pdf-cont-head">
<div className="pdf-cont-head-tit">HWJ 調1/2</div> <div className="pdf-cont-head-tit">HWJ 調1/2</div>
<div className="pdf-cont-head-data-wrap"> <div className="pdf-cont-head-data-wrap">
@ -18,7 +54,7 @@ export default function PDFViewContents(){
<div className="pdf-table"> <div className="pdf-table">
<table> <table>
<colgroup> <colgroup>
<col width={72}/> <col width={72} />
<col /> <col />
</colgroup> </colgroup>
<tbody> <tbody>
@ -37,7 +73,7 @@ export default function PDFViewContents(){
<div className="pdf-data-tit"></div> <div className="pdf-data-tit"></div>
<table> <table>
<colgroup> <colgroup>
<col width={110}/> <col width={110} />
<col /> <col />
</colgroup> </colgroup>
<tbody> <tbody>
@ -64,7 +100,7 @@ export default function PDFViewContents(){
<div className="pdf-data-tit"></div> <div className="pdf-data-tit"></div>
<table> <table>
<colgroup> <colgroup>
<col width={110}/> <col width={110} />
<col /> <col />
</colgroup> </colgroup>
<tbody> <tbody>
@ -134,7 +170,7 @@ export default function PDFViewContents(){
<div className="pdf-table"> <div className="pdf-table">
<table> <table>
<colgroup> <colgroup>
<col width={150}/> <col width={150} />
<col /> <col />
</colgroup> </colgroup>
<tbody> <tbody>
@ -151,5 +187,6 @@ export default function PDFViewContents(){
</div> </div>
</div> </div>
</div> </div>
) </>
);
} }