feat: add Vue 3 interface with modern UI/UX
- Dodano Vue 3 framework do projektu - Komponenty: App.vue, InvoiceGenerator.vue, UpoGenerator.vue - Nowoczesny interfejs z gradientami i animacjami - File upload z drag-n-drop obsługą - Progress bar visualizacja - Message notifications (success/error) - Responsywny design dla mobile/desktop - Copyright link do CIRFMF na GitHub - Build:app script do Vite - vue oraz @vitejs/plugin-vue instalacja
This commit is contained in:
File diff suppressed because one or more lines are too long
298
dist-app/assets/index-Dw4i_fPq.js
Normal file
298
dist-app/assets/index-Dw4i_fPq.js
Normal file
File diff suppressed because one or more lines are too long
1
dist-app/assets/index-RaXg1fq2.css
Normal file
1
dist-app/assets/index-RaXg1fq2.css
Normal file
File diff suppressed because one or more lines are too long
@@ -1,26 +1,16 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="pl">
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>XML Parser</title>
|
|
||||||
<script type="module" crossorigin src="/ksef/assets/index-BOCrZ8tn.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>📄 XML Parser</h1>
|
|
||||||
|
|
||||||
<h2>Wygeneruj fakture:</h2>
|
<head>
|
||||||
<input
|
<meta charset="UTF-8" />
|
||||||
accept=".xml"
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
id="xmlInput"
|
<title>KSEF PDF Generator - Vue 3</title>
|
||||||
type="file"
|
<script type="module" crossorigin src="/ksef/assets/index-Dw4i_fPq.js"></script>
|
||||||
/>
|
<link rel="stylesheet" crossorigin href="/ksef/assets/index-RaXg1fq2.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
<h2>Wygeneruj UPO:</h2>
|
<body>
|
||||||
<input
|
<div id="app"></div>
|
||||||
accept=".xml"
|
</body>
|
||||||
id="xmlInputUPO"
|
|
||||||
type="file"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</body>
|
</html>
|
||||||
</html>
|
|
||||||
231
package-lock.json
generated
231
package-lock.json
generated
@@ -10,6 +10,7 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pdfmake": "^0.2.20",
|
"pdfmake": "^0.2.20",
|
||||||
|
"vue": "^3.5.30",
|
||||||
"xml-js": "^1.6.11"
|
"xml-js": "^1.6.11"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -18,6 +19,7 @@
|
|||||||
"@types/pdfmake": "^0.2.11",
|
"@types/pdfmake": "^0.2.11",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.40.0",
|
"@typescript-eslint/eslint-plugin": "^8.40.0",
|
||||||
"@typescript-eslint/parser": "^8.40.0",
|
"@typescript-eslint/parser": "^8.40.0",
|
||||||
|
"@vitejs/plugin-vue": "^6.0.5",
|
||||||
"@vitest/coverage-v8": "^3.2.4",
|
"@vitest/coverage-v8": "^3.2.4",
|
||||||
"@vitest/ui": "^3.2.4",
|
"@vitest/ui": "^3.2.4",
|
||||||
"eslint": "^9.33.0",
|
"eslint": "^9.33.0",
|
||||||
@@ -40,26 +42,27 @@
|
|||||||
},
|
},
|
||||||
"node_modules/@babel/helper-string-parser": {
|
"node_modules/@babel/helper-string-parser": {
|
||||||
"version": "7.27.1",
|
"version": "7.27.1",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-validator-identifier": {
|
"node_modules/@babel/helper-validator-identifier": {
|
||||||
"version": "7.27.1",
|
"version": "7.28.5",
|
||||||
"dev": true,
|
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
|
||||||
|
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/parser": {
|
"node_modules/@babel/parser": {
|
||||||
"version": "7.28.4",
|
"version": "7.29.2",
|
||||||
"dev": true,
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz",
|
||||||
|
"integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/types": "^7.28.4"
|
"@babel/types": "^7.29.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"parser": "bin/babel-parser.js"
|
"parser": "bin/babel-parser.js"
|
||||||
@@ -68,13 +71,14 @@
|
|||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/parser/node_modules/@babel/types": {
|
"node_modules/@babel/types": {
|
||||||
"version": "7.28.4",
|
"version": "7.29.0",
|
||||||
"dev": true,
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
|
||||||
|
"integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-string-parser": "^7.27.1",
|
"@babel/helper-string-parser": "^7.27.1",
|
||||||
"@babel/helper-validator-identifier": "^7.27.1"
|
"@babel/helper-validator-identifier": "^7.28.5"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
@@ -736,7 +740,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/@jridgewell/sourcemap-codec": {
|
"node_modules/@jridgewell/sourcemap-codec": {
|
||||||
"version": "1.5.5",
|
"version": "1.5.5",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/trace-mapping": {
|
"node_modules/@jridgewell/trace-mapping": {
|
||||||
@@ -781,6 +784,13 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@rolldown/pluginutils": {
|
||||||
|
"version": "1.0.0-rc.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.2.tgz",
|
||||||
|
"integrity": "sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||||
"version": "4.52.4",
|
"version": "4.52.4",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.4.tgz",
|
||||||
@@ -1722,6 +1732,23 @@
|
|||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@vitejs/plugin-vue": {
|
||||||
|
"version": "6.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.5.tgz",
|
||||||
|
"integrity": "sha512-bL3AxKuQySfk1iGcBsQnoRVexTPJq0Z/ixFVM8OhVJAP6ZXXXLtM7NFKWhLl30Kg7uTBqIaPXbh+nuQCuBDedg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@rolldown/pluginutils": "1.0.0-rc.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^20.19.0 || >=22.12.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0",
|
||||||
|
"vue": "^3.2.25"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@vitest/coverage-v8": {
|
"node_modules/@vitest/coverage-v8": {
|
||||||
"version": "3.2.4",
|
"version": "3.2.4",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@@ -1930,40 +1957,65 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@vue/compiler-core": {
|
"node_modules/@vue/compiler-core": {
|
||||||
"version": "3.5.22",
|
"version": "3.5.30",
|
||||||
"dev": true,
|
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.30.tgz",
|
||||||
|
"integrity": "sha512-s3DfdZkcu/qExZ+td75015ljzHc6vE+30cFMGRPROYjqkroYI5NV2X1yAMX9UeyBNWB9MxCfPcsjpLS11nzkkw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/parser": "^7.28.4",
|
"@babel/parser": "^7.29.0",
|
||||||
"@vue/shared": "3.5.22",
|
"@vue/shared": "3.5.30",
|
||||||
"entities": "^4.5.0",
|
"entities": "^7.0.1",
|
||||||
"estree-walker": "^2.0.2",
|
"estree-walker": "^2.0.2",
|
||||||
"source-map-js": "^1.2.1"
|
"source-map-js": "^1.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/compiler-core/node_modules/entities": {
|
|
||||||
"version": "4.5.0",
|
|
||||||
"dev": true,
|
|
||||||
"license": "BSD-2-Clause",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.12"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@vue/compiler-core/node_modules/estree-walker": {
|
"node_modules/@vue/compiler-core/node_modules/estree-walker": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"dev": true,
|
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@vue/compiler-dom": {
|
"node_modules/@vue/compiler-dom": {
|
||||||
"version": "3.5.22",
|
"version": "3.5.30",
|
||||||
"dev": true,
|
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.30.tgz",
|
||||||
|
"integrity": "sha512-eCFYESUEVYHhiMuK4SQTldO3RYxyMR/UQL4KdGD1Yrkfdx4m/HYuZ9jSfPdA+nWJY34VWndiYdW/wZXyiPEB9g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/compiler-core": "3.5.22",
|
"@vue/compiler-core": "3.5.30",
|
||||||
"@vue/shared": "3.5.22"
|
"@vue/shared": "3.5.30"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vue/compiler-sfc": {
|
||||||
|
"version": "3.5.30",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.30.tgz",
|
||||||
|
"integrity": "sha512-LqmFPDn89dtU9vI3wHJnwaV6GfTRD87AjWpTWpyrdVOObVtjIuSeZr181z5C4PmVx/V3j2p+0f7edFKGRMpQ5A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/parser": "^7.29.0",
|
||||||
|
"@vue/compiler-core": "3.5.30",
|
||||||
|
"@vue/compiler-dom": "3.5.30",
|
||||||
|
"@vue/compiler-ssr": "3.5.30",
|
||||||
|
"@vue/shared": "3.5.30",
|
||||||
|
"estree-walker": "^2.0.2",
|
||||||
|
"magic-string": "^0.30.21",
|
||||||
|
"postcss": "^8.5.8",
|
||||||
|
"source-map-js": "^1.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vue/compiler-sfc/node_modules/estree-walker": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@vue/compiler-ssr": {
|
||||||
|
"version": "3.5.30",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.30.tgz",
|
||||||
|
"integrity": "sha512-NsYK6OMTnx109PSL2IAyf62JP6EUdk4Dmj6AkWcJGBvN0dQoMYtVekAmdqgTtWQgEJo+Okstbf/1p7qZr5H+bA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/compiler-dom": "3.5.30",
|
||||||
|
"@vue/shared": "3.5.30"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/compiler-vue2": {
|
"node_modules/@vue/compiler-vue2": {
|
||||||
@@ -1975,9 +2027,54 @@
|
|||||||
"he": "^1.2.0"
|
"he": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@vue/reactivity": {
|
||||||
|
"version": "3.5.30",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.30.tgz",
|
||||||
|
"integrity": "sha512-179YNgKATuwj9gB+66snskRDOitDiuOZqkYia7mHKJaidOMo/WJxHKF8DuGc4V4XbYTJANlfEKb0yxTQotnx4Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/shared": "3.5.30"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vue/runtime-core": {
|
||||||
|
"version": "3.5.30",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.30.tgz",
|
||||||
|
"integrity": "sha512-e0Z+8PQsUTdwV8TtEsLzUM7SzC7lQwYKePydb7K2ZnmS6jjND+WJXkmmfh/swYzRyfP1EY3fpdesyYoymCzYfg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/reactivity": "3.5.30",
|
||||||
|
"@vue/shared": "3.5.30"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vue/runtime-dom": {
|
||||||
|
"version": "3.5.30",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.30.tgz",
|
||||||
|
"integrity": "sha512-2UIGakjU4WSQ0T4iwDEW0W7vQj6n7AFn7taqZ9Cvm0Q/RA2FFOziLESrDL4GmtI1wV3jXg5nMoJSYO66egDUBw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/reactivity": "3.5.30",
|
||||||
|
"@vue/runtime-core": "3.5.30",
|
||||||
|
"@vue/shared": "3.5.30",
|
||||||
|
"csstype": "^3.2.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vue/server-renderer": {
|
||||||
|
"version": "3.5.30",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.30.tgz",
|
||||||
|
"integrity": "sha512-v+R34icapydRwbZRD0sXwtHqrQJv38JuMB4JxbOxd8NEpGLny7cncMp53W9UH/zo4j8eDHjQ1dEJXwzFQknjtQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/compiler-ssr": "3.5.30",
|
||||||
|
"@vue/shared": "3.5.30"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "3.5.30"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@vue/shared": {
|
"node_modules/@vue/shared": {
|
||||||
"version": "3.5.22",
|
"version": "3.5.30",
|
||||||
"dev": true,
|
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.30.tgz",
|
||||||
|
"integrity": "sha512-YXgQ7JjaO18NeK2K9VTbDHaFy62WrObMa6XERNfNOkAhD1F1oDSf3ZJ7K6GqabZ0BvSDHajp8qfS5Sa2I9n8uQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
@@ -2268,6 +2365,12 @@
|
|||||||
"lru-cache": "^10.4.3"
|
"lru-cache": "^10.4.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/csstype": {
|
||||||
|
"version": "3.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
||||||
|
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/data-urls": {
|
"node_modules/data-urls": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@@ -2393,6 +2496,18 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/entities": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/es-define-property": {
|
"node_modules/es-define-property": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -3688,8 +3803,9 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/magic-string": {
|
"node_modules/magic-string": {
|
||||||
"version": "0.30.19",
|
"version": "0.30.21",
|
||||||
"dev": true,
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
||||||
|
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||||
@@ -3705,18 +3821,6 @@
|
|||||||
"source-map-js": "^1.2.0"
|
"source-map-js": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/magicast/node_modules/@babel/types": {
|
|
||||||
"version": "7.28.4",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/helper-string-parser": "^7.27.1",
|
|
||||||
"@babel/helper-validator-identifier": "^7.27.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/make-dir": {
|
"node_modules/make-dir": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@@ -3785,7 +3889,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.11",
|
"version": "3.3.11",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
@@ -3971,7 +4074,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/picocolors": {
|
"node_modules/picocolors": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"dev": true,
|
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/picomatch": {
|
"node_modules/picomatch": {
|
||||||
@@ -3999,8 +4101,9 @@
|
|||||||
"version": "1.0.0"
|
"version": "1.0.0"
|
||||||
},
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.5.6",
|
"version": "8.5.8",
|
||||||
"dev": true,
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
|
||||||
|
"integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@@ -4352,7 +4455,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/source-map-js": {
|
"node_modules/source-map-js": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"dev": true,
|
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
@@ -4663,7 +4765,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "5.9.3",
|
"version": "5.9.3",
|
||||||
"dev": true,
|
"devOptional": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
@@ -5468,6 +5570,27 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/vue": {
|
||||||
|
"version": "3.5.30",
|
||||||
|
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.30.tgz",
|
||||||
|
"integrity": "sha512-hTHLc6VNZyzzEH/l7PFGjpcTvUgiaPK5mdLkbjrTeWSRcEfxFrv56g/XckIYlE9ckuobsdwqd5mk2g1sBkMewg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/compiler-dom": "3.5.30",
|
||||||
|
"@vue/compiler-sfc": "3.5.30",
|
||||||
|
"@vue/runtime-dom": "3.5.30",
|
||||||
|
"@vue/server-renderer": "3.5.30",
|
||||||
|
"@vue/shared": "3.5.30"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "*"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"typescript": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/w3c-xmlserializer": {
|
"node_modules/w3c-xmlserializer": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
"@types/pdfmake": "^0.2.11",
|
"@types/pdfmake": "^0.2.11",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.40.0",
|
"@typescript-eslint/eslint-plugin": "^8.40.0",
|
||||||
"@typescript-eslint/parser": "^8.40.0",
|
"@typescript-eslint/parser": "^8.40.0",
|
||||||
|
"@vitejs/plugin-vue": "^6.0.5",
|
||||||
"@vitest/coverage-v8": "^3.2.4",
|
"@vitest/coverage-v8": "^3.2.4",
|
||||||
"@vitest/ui": "^3.2.4",
|
"@vitest/ui": "^3.2.4",
|
||||||
"eslint": "^9.33.0",
|
"eslint": "^9.33.0",
|
||||||
@@ -52,6 +53,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pdfmake": "^0.2.20",
|
"pdfmake": "^0.2.20",
|
||||||
|
"vue": "^3.5.30",
|
||||||
"xml-js": "^1.6.11"
|
"xml-js": "^1.6.11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
263
src/app-public/App.vue
Normal file
263
src/app-public/App.vue
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<!-- Header -->
|
||||||
|
<header class="header">
|
||||||
|
<h1>📄 KSEF PDF Generator</h1>
|
||||||
|
<p class="subtitle">Generuj wizualizacje PDF faktur i UPO</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- Navigation -->
|
||||||
|
<nav class="nav-tabs">
|
||||||
|
<button
|
||||||
|
@click="activeTab = 'invoice'"
|
||||||
|
:class="{ 'active': activeTab === 'invoice' }"
|
||||||
|
class="nav-btn"
|
||||||
|
>
|
||||||
|
📋 Faktura (FA1/FA2/FA3)
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click="activeTab = 'upo'"
|
||||||
|
:class="{ 'active': activeTab === 'upo' }"
|
||||||
|
class="nav-btn"
|
||||||
|
>
|
||||||
|
📊 UPO v4.2
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!-- Content -->
|
||||||
|
<main class="main-content">
|
||||||
|
<!-- Invoice Tab -->
|
||||||
|
<section v-if="activeTab === 'invoice'" class="tab-content">
|
||||||
|
<InvoiceGenerator
|
||||||
|
@pdf-generated="onPdfGenerated"
|
||||||
|
@error="onError"
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- UPO Tab -->
|
||||||
|
<section v-if="activeTab === 'upo'" class="tab-content">
|
||||||
|
<UpoGenerator
|
||||||
|
@pdf-generated="onPdfGenerated"
|
||||||
|
@error="onError"
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Status Messages -->
|
||||||
|
<div v-if="message.text" :class="['message', message.type]">
|
||||||
|
{{ message.text }}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<footer class="footer">
|
||||||
|
<p>KSEF PDF Generator v1.0.0 | Oparte o Vite + Vue 3 + TypeScript</p>
|
||||||
|
<p class="copyright">
|
||||||
|
© 2026 | Oparte na bibliotece
|
||||||
|
<a href="https://github.com/CIRFMF/ksef-pdf-generator" target="_blank" rel="noopener noreferrer">
|
||||||
|
github.com/CIRFMF
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import InvoiceGenerator from './components/InvoiceGenerator.vue';
|
||||||
|
import UpoGenerator from './components/UpoGenerator.vue';
|
||||||
|
|
||||||
|
interface Message {
|
||||||
|
text: string;
|
||||||
|
type: 'success' | 'error' | 'info';
|
||||||
|
}
|
||||||
|
|
||||||
|
const activeTab = ref<'invoice' | 'upo'>('invoice');
|
||||||
|
const message = ref<Message>({ text: '', type: 'info' });
|
||||||
|
|
||||||
|
const onPdfGenerated = (fileName: string) => {
|
||||||
|
message.value = {
|
||||||
|
text: `✅ PDF "${fileName}" wygenerowany pomyślnie!`,
|
||||||
|
type: 'success',
|
||||||
|
};
|
||||||
|
setTimeout(() => {
|
||||||
|
message.value.text = '';
|
||||||
|
}, 5000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onError = (error: string) => {
|
||||||
|
message.value = {
|
||||||
|
text: `❌ Błąd: ${error}`,
|
||||||
|
type: 'error',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.app-container {
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
background: rgba(0, 0, 0, 0.2);
|
||||||
|
color: white;
|
||||||
|
padding: 2rem 1rem;
|
||||||
|
text-align: center;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header h1 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
margin: 0 0 0.5rem 0;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
font-size: 1rem;
|
||||||
|
margin: 0;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tabs {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
background: rgba(0, 0, 0, 0.1);
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-btn {
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
color: white;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-btn:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-btn.active {
|
||||||
|
background: white;
|
||||||
|
color: #667eea;
|
||||||
|
border-color: white;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
flex: 1;
|
||||||
|
padding: 2rem 1rem;
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
animation: fadeIn 0.3s ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(10px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-top: 1rem;
|
||||||
|
font-weight: 500;
|
||||||
|
animation: slideIn 0.3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(-20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.message.success {
|
||||||
|
background: #d4edda;
|
||||||
|
color: #155724;
|
||||||
|
border: 1px solid #c3e6cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message.error {
|
||||||
|
background: #f8d7da;
|
||||||
|
color: #721c24;
|
||||||
|
border: 1px solid #f5c6cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message.info {
|
||||||
|
background: #d1ecf1;
|
||||||
|
color: #0c5460;
|
||||||
|
border: 1px solid #bee5eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
background: rgba(0, 0, 0, 0.2);
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
padding: 1rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer p {
|
||||||
|
margin: 0.25rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright a {
|
||||||
|
color: #a0d0ff;
|
||||||
|
text-decoration: none;
|
||||||
|
border-bottom: 1px dashed #a0d0ff;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright a:hover {
|
||||||
|
color: white;
|
||||||
|
border-bottom-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.header h1 {
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tabs {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-btn {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
384
src/app-public/components/InvoiceGenerator.vue
Normal file
384
src/app-public/components/InvoiceGenerator.vue
Normal file
@@ -0,0 +1,384 @@
|
|||||||
|
<template>
|
||||||
|
<div class="generator-card">
|
||||||
|
<h2>Wygeneruj Fakturę PDF</h2>
|
||||||
|
|
||||||
|
<div class="upload-section">
|
||||||
|
<label for="invoiceFile" class="file-input-label">
|
||||||
|
<span class="upload-icon">📁</span>
|
||||||
|
<span v-if="!selectedFile" class="upload-text">
|
||||||
|
Kliknij aby wybrać plik XML
|
||||||
|
</span>
|
||||||
|
<span v-else class="file-name">
|
||||||
|
{{ selectedFile.name }}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="invoiceFile"
|
||||||
|
type="file"
|
||||||
|
accept=".xml"
|
||||||
|
@change="onFileSelected"
|
||||||
|
class="file-input-hidden"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="selectedFile" class="file-info">
|
||||||
|
<p class="file-size">Rozmiar: {{ fileSize }}</p>
|
||||||
|
<p class="file-type">Format: XML</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-group">
|
||||||
|
<button
|
||||||
|
@click="generatePdf"
|
||||||
|
:disabled="!selectedFile || isLoading"
|
||||||
|
class="btn btn-primary"
|
||||||
|
>
|
||||||
|
<span v-if="!isLoading" class="btn-text">🚀 Wygeneruj PDF</span>
|
||||||
|
<span v-else class="btn-text">⏳ Generowanie...</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="selectedFile"
|
||||||
|
@click="clearFile"
|
||||||
|
class="btn btn-secondary"
|
||||||
|
>
|
||||||
|
🗑️ Wyczyść
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="progress" class="progress-section">
|
||||||
|
<div class="progress-bar">
|
||||||
|
<div class="progress-fill" :style="{ width: progress + '%' }"></div>
|
||||||
|
</div>
|
||||||
|
<p class="progress-text">{{ progress }}%</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="additionalData" class="data-preview">
|
||||||
|
<h3>Dane Dodatkowe</h3>
|
||||||
|
<div class="data-item">
|
||||||
|
<span class="data-label">Nr KSeF:</span>
|
||||||
|
<span class="data-value">{{ additionalData.nrKSeF }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="data-item">
|
||||||
|
<span class="data-label">QR Code:</span>
|
||||||
|
<span class="data-value data-value-url">{{ additionalData.qrCode }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed } from 'vue';
|
||||||
|
import { generateInvoice } from '../../lib-public';
|
||||||
|
import type { AdditionalDataTypes } from '../../lib-public/types/common.types';
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'pdf-generated': [filename: string];
|
||||||
|
'error': [error: string];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const selectedFile = ref<File | null>(null);
|
||||||
|
const isLoading = ref(false);
|
||||||
|
const progress = ref(0);
|
||||||
|
|
||||||
|
const additionalData: AdditionalDataTypes = {
|
||||||
|
nrKSeF: '5555555555-20250808-9231003CA67B-BE',
|
||||||
|
qrCode: 'https://ksef-test.mf.gov.pl/invoice/5265877635/26-10-2025/HS5E1zrA8WVjDNq_xMVIN5SD6nyRymmQ-BcYHReUAa0',
|
||||||
|
};
|
||||||
|
|
||||||
|
const fileSize = computed(() => {
|
||||||
|
if (!selectedFile.value) return '0 B';
|
||||||
|
const bytes = selectedFile.value.size;
|
||||||
|
if (bytes === 0) return '0 B';
|
||||||
|
const k = 1024;
|
||||||
|
const sizes = ['B', 'KB', 'MB'];
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];
|
||||||
|
});
|
||||||
|
|
||||||
|
const onFileSelected = (event: Event) => {
|
||||||
|
const target = event.target as HTMLInputElement;
|
||||||
|
const file = target.files?.[0];
|
||||||
|
if (file && file.type === 'text/xml') {
|
||||||
|
selectedFile.value = file;
|
||||||
|
} else {
|
||||||
|
emit('error', 'Wybierz prawidłowy plik XML');
|
||||||
|
selectedFile.value = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearFile = () => {
|
||||||
|
selectedFile.value = null;
|
||||||
|
progress.value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const generatePdf = async () => {
|
||||||
|
if (!selectedFile.value) {
|
||||||
|
emit('error', 'Brak wybranego pliku');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
isLoading.value = true;
|
||||||
|
progress.value = 20;
|
||||||
|
|
||||||
|
// Symulacja postępu
|
||||||
|
const progressInterval = setInterval(() => {
|
||||||
|
progress.value = Math.min(progress.value + Math.random() * 30, 90);
|
||||||
|
}, 300);
|
||||||
|
|
||||||
|
// Generowanie PDF
|
||||||
|
const pdfBlob = await generateInvoice(
|
||||||
|
selectedFile.value,
|
||||||
|
additionalData,
|
||||||
|
'blob'
|
||||||
|
);
|
||||||
|
|
||||||
|
clearInterval(progressInterval);
|
||||||
|
progress.value = 100;
|
||||||
|
|
||||||
|
// Download PDF
|
||||||
|
const url = URL.createObjectURL(pdfBlob);
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.download = `faktura-${Date.now()}.pdf`;
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
|
||||||
|
emit('pdf-generated', link.download);
|
||||||
|
|
||||||
|
// Reset po 1 sekundzie
|
||||||
|
setTimeout(() => {
|
||||||
|
clearFile();
|
||||||
|
isLoading.value = false;
|
||||||
|
}, 1000);
|
||||||
|
} catch (error) {
|
||||||
|
emit('error', error instanceof Error ? error.message : 'Nieznanego błędu');
|
||||||
|
clearFile();
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.generator-card {
|
||||||
|
background: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 2rem;
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
||||||
|
animation: slideUp 0.5s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.generator-card h2 {
|
||||||
|
margin: 0 0 1.5rem 0;
|
||||||
|
color: #333;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-section {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 2rem;
|
||||||
|
border: 2px dashed #667eea;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #f8f9ff;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-label:hover {
|
||||||
|
background: #f0f2ff;
|
||||||
|
border-color: #764ba2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-icon {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-text,
|
||||||
|
.file-name {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #667eea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-name {
|
||||||
|
color: #764ba2;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-info {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
background: #f0f2ff;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-info p {
|
||||||
|
margin: 0;
|
||||||
|
color: #667eea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-size {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 150px;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
color: white;
|
||||||
|
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover:not(:disabled) {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
background: #e0e0e0;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary:hover {
|
||||||
|
background: #d0d0d0;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-text {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-section {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar {
|
||||||
|
width: 100%;
|
||||||
|
height: 8px;
|
||||||
|
background: #e0e0e0;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-fill {
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
|
||||||
|
transition: width 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-text {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #667eea;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-preview {
|
||||||
|
padding: 1rem;
|
||||||
|
background: #f8f9ff;
|
||||||
|
border-radius: 8px;
|
||||||
|
border-left: 4px solid #667eea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-preview h3 {
|
||||||
|
margin: 0 0 1rem 0;
|
||||||
|
color: #667eea;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-label {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #667eea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-value {
|
||||||
|
color: #666;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-value-url {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.generator-card {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
min-width: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-info {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
382
src/app-public/components/UpoGenerator.vue
Normal file
382
src/app-public/components/UpoGenerator.vue
Normal file
@@ -0,0 +1,382 @@
|
|||||||
|
<template>
|
||||||
|
<div class="generator-card">
|
||||||
|
<h2>Wygeneruj UPO PDF</h2>
|
||||||
|
|
||||||
|
<div class="upload-section">
|
||||||
|
<label for="upoFile" class="file-input-label">
|
||||||
|
<span class="upload-icon">📁</span>
|
||||||
|
<span v-if="!selectedFile" class="upload-text">
|
||||||
|
Kliknij aby wybrać plik XML UPO v4.2
|
||||||
|
</span>
|
||||||
|
<span v-else class="file-name">
|
||||||
|
{{ selectedFile.name }}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="upoFile"
|
||||||
|
type="file"
|
||||||
|
accept=".xml"
|
||||||
|
@change="onFileSelected"
|
||||||
|
class="file-input-hidden"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="selectedFile" class="file-info">
|
||||||
|
<p class="file-size">Rozmiar: {{ fileSize }}</p>
|
||||||
|
<p class="file-type">Format: XML (UPO v4.2)</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-group">
|
||||||
|
<button
|
||||||
|
@click="generatePdf"
|
||||||
|
:disabled="!selectedFile || isLoading"
|
||||||
|
class="btn btn-primary"
|
||||||
|
>
|
||||||
|
<span v-if="!isLoading" class="btn-text">🚀 Wygeneruj PDF</span>
|
||||||
|
<span v-else class="btn-text">⏳ Generowanie...</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="selectedFile"
|
||||||
|
@click="clearFile"
|
||||||
|
class="btn btn-secondary"
|
||||||
|
>
|
||||||
|
🗑️ Wyczyść
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="progress" class="progress-section">
|
||||||
|
<div class="progress-bar">
|
||||||
|
<div class="progress-fill" :style="{ width: progress + '%' }"></div>
|
||||||
|
</div>
|
||||||
|
<p class="progress-text">{{ progress }}%</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-box">
|
||||||
|
<h3>ℹ️ Informacje</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Format: XML kompatybilny z UPO v4.2</li>
|
||||||
|
<li>Generuje wizualizację PDF dokumentu UPO</li>
|
||||||
|
<li>Obsługuje wszystkie warianty struktur</li>
|
||||||
|
<li>Maksymalny rozmiar: 100 MB</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed } from 'vue';
|
||||||
|
import { generatePDFUPO } from '../../lib-public';
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'pdf-generated': [filename: string];
|
||||||
|
'error': [error: string];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const selectedFile = ref<File | null>(null);
|
||||||
|
const isLoading = ref(false);
|
||||||
|
const progress = ref(0);
|
||||||
|
|
||||||
|
const fileSize = computed(() => {
|
||||||
|
if (!selectedFile.value) return '0 B';
|
||||||
|
const bytes = selectedFile.value.size;
|
||||||
|
if (bytes === 0) return '0 B';
|
||||||
|
const k = 1024;
|
||||||
|
const sizes = ['B', 'KB', 'MB'];
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];
|
||||||
|
});
|
||||||
|
|
||||||
|
const onFileSelected = (event: Event) => {
|
||||||
|
const target = event.target as HTMLInputElement;
|
||||||
|
const file = target.files?.[0];
|
||||||
|
if (file && file.type === 'text/xml') {
|
||||||
|
selectedFile.value = file;
|
||||||
|
} else {
|
||||||
|
emit('error', 'Wybierz prawidłowy plik XML');
|
||||||
|
selectedFile.value = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearFile = () => {
|
||||||
|
selectedFile.value = null;
|
||||||
|
progress.value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const generatePdf = async () => {
|
||||||
|
if (!selectedFile.value) {
|
||||||
|
emit('error', 'Brak wybranego pliku');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
isLoading.value = true;
|
||||||
|
progress.value = 20;
|
||||||
|
|
||||||
|
// Symulacja postępu
|
||||||
|
const progressInterval = setInterval(() => {
|
||||||
|
progress.value = Math.min(progress.value + Math.random() * 30, 90);
|
||||||
|
}, 300);
|
||||||
|
|
||||||
|
// Generowanie PDF
|
||||||
|
const pdfBlob = await generatePDFUPO(
|
||||||
|
selectedFile.value,
|
||||||
|
'blob'
|
||||||
|
);
|
||||||
|
|
||||||
|
clearInterval(progressInterval);
|
||||||
|
progress.value = 100;
|
||||||
|
|
||||||
|
// Download PDF
|
||||||
|
const url = URL.createObjectURL(pdfBlob);
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.download = `upo-${Date.now()}.pdf`;
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
|
||||||
|
emit('pdf-generated', link.download);
|
||||||
|
|
||||||
|
// Reset po 1 sekundzie
|
||||||
|
setTimeout(() => {
|
||||||
|
clearFile();
|
||||||
|
isLoading.value = false;
|
||||||
|
}, 1000);
|
||||||
|
} catch (error) {
|
||||||
|
emit('error', error instanceof Error ? error.message : 'Nieznanego błędu');
|
||||||
|
clearFile();
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.generator-card {
|
||||||
|
background: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 2rem;
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
||||||
|
animation: slideUp 0.5s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.generator-card h2 {
|
||||||
|
margin: 0 0 1.5rem 0;
|
||||||
|
color: #333;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-section {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 2rem;
|
||||||
|
border: 2px dashed #667eea;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #f8f9ff;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-label:hover {
|
||||||
|
background: #f0f2ff;
|
||||||
|
border-color: #764ba2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-icon {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-text,
|
||||||
|
.file-name {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #667eea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-name {
|
||||||
|
color: #764ba2;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-info {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
background: #f0f2ff;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-info p {
|
||||||
|
margin: 0;
|
||||||
|
color: #667eea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-size {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 150px;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
color: white;
|
||||||
|
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover:not(:disabled) {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
background: #e0e0e0;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary:hover {
|
||||||
|
background: #d0d0d0;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-text {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-section {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar {
|
||||||
|
width: 100%;
|
||||||
|
height: 8px;
|
||||||
|
background: #e0e0e0;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-fill {
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
|
||||||
|
transition: width 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-text {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #667eea;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box {
|
||||||
|
padding: 1.5rem;
|
||||||
|
background: linear-gradient(135deg, #e3f2fd 0%, #f3e5f5 100%);
|
||||||
|
border-radius: 8px;
|
||||||
|
border-left: 4px solid #667eea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box h3 {
|
||||||
|
margin: 0 0 1rem 0;
|
||||||
|
color: #667eea;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box ul {
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box ul li {
|
||||||
|
color: #555;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box ul li:before {
|
||||||
|
content: '✓';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
color: #667eea;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.generator-card {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
min-width: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-info {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box ul {
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box ul li {
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,29 +1,15 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="pl">
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>XML Parser</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>📄 XML Parser</h1>
|
|
||||||
|
|
||||||
<h2>Wygeneruj fakture:</h2>
|
<head>
|
||||||
<input
|
<meta charset="UTF-8" />
|
||||||
accept=".xml"
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
id="xmlInput"
|
<title>KSEF PDF Generator - Vue 3</title>
|
||||||
type="file"
|
</head>
|
||||||
/>
|
|
||||||
|
|
||||||
<h2>Wygeneruj UPO:</h2>
|
<body>
|
||||||
<input
|
<div id="app"></div>
|
||||||
accept=".xml"
|
<script type="module" src="./main.ts"></script>
|
||||||
id="xmlInputUPO"
|
</body>
|
||||||
type="file"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<script
|
</html>
|
||||||
src="./main.ts"
|
|
||||||
type="module"
|
|
||||||
></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,55 +1,6 @@
|
|||||||
import { generateInvoice, generatePDFUPO } from '../lib-public';
|
import { createApp } from 'vue';
|
||||||
|
import App from './App.vue';
|
||||||
|
|
||||||
import { AdditionalDataTypes } from '../lib-public/types/common.types';
|
const app = createApp(App);
|
||||||
|
|
||||||
const inputInvoice: HTMLInputElement = document.getElementById('xmlInput') as HTMLInputElement;
|
app.mount('#app');
|
||||||
const inputUPO: HTMLInputElement = document.getElementById('xmlInputUPO') as HTMLInputElement;
|
|
||||||
|
|
||||||
inputInvoice.addEventListener('change', async (): Promise<void> => {
|
|
||||||
const file: File | undefined = inputInvoice.files?.[0];
|
|
||||||
|
|
||||||
if (!file) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const additionalData: AdditionalDataTypes = {
|
|
||||||
nrKSeF: '5555555555-20250808-9231003CA67B-BE',
|
|
||||||
qrCode:
|
|
||||||
'https://ksef-test.mf.gov.pl/invoice/5265877635/26-10-2025/HS5E1zrA8WVjDNq_xMVIN5SD6nyRymmQ-BcYHReUAa0',
|
|
||||||
};
|
|
||||||
|
|
||||||
generateInvoice(file, additionalData, 'blob').then((data: Blob): void => {
|
|
||||||
const url: string = URL.createObjectURL(data);
|
|
||||||
|
|
||||||
const a: HTMLAnchorElement = document.createElement('a');
|
|
||||||
|
|
||||||
a.href = url;
|
|
||||||
a.download = 'test.pdf';
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
|
|
||||||
document.body.removeChild(a);
|
|
||||||
URL.revokeObjectURL(url);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
inputUPO.addEventListener('change', async (): Promise<void> => {
|
|
||||||
const file: File | undefined = inputUPO.files?.[0];
|
|
||||||
|
|
||||||
if (!file) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
generatePDFUPO(file).then((blob) => {
|
|
||||||
const url: string = URL.createObjectURL(blob);
|
|
||||||
|
|
||||||
const a: HTMLAnchorElement = document.createElement('a');
|
|
||||||
|
|
||||||
a.href = url;
|
|
||||||
a.download = 'test.pdf';
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
|
|
||||||
document.body.removeChild(a);
|
|
||||||
URL.revokeObjectURL(url);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
|
import vue from '@vitejs/plugin-vue';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: path.resolve(__dirname, 'src/app-public'),
|
root: path.resolve(__dirname, 'src/app-public'),
|
||||||
base: '/ksef/',
|
base: '/ksef/',
|
||||||
|
|
||||||
|
plugins: [vue()],
|
||||||
|
|
||||||
build: {
|
build: {
|
||||||
outDir: path.resolve(__dirname, 'dist-app'),
|
outDir: path.resolve(__dirname, 'dist-app'),
|
||||||
emptyOutDir: true,
|
emptyOutDir: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user