add qr-code install instructions
Main daploy / deploy (push) Successful in 47s

This commit is contained in:
2024-11-19 18:49:12 +02:00
parent 4dbf9825eb
commit 5d66a3c79a
16 changed files with 755 additions and 63 deletions
+2
View File
@@ -29,7 +29,9 @@ declare module 'vue' {
IconSupport: typeof import('./src/components/icons/IconSupport.vue')['default']
IconTooling: typeof import('./src/components/icons/IconTooling.vue')['default']
InputText: typeof import('primevue/inputtext')['default']
ManagePlacementInstructions: typeof import('./src/components/manage/ManagePlacementInstructions.vue')['default']
MessageSender: typeof import('./src/components/read/ReadMessageSender.vue')['default']
PlacementInstructions: typeof import('./src/components/manage/ManagePlacementInstructions.vue')['default']
QRCodeReadySection: typeof import('./src/components/create/CreateReadySection.vue')['default']
RadioButton: typeof import('primevue/radiobutton')['default']
ReadContactInfo: typeof import('./src/components/read/ReadContactInfo.vue')['default']
+447 -3
View File
@@ -8,8 +8,10 @@
"name": "hereconnect",
"version": "0.0.0",
"dependencies": {
"@f3ve/vue-markdown-it": "^0.2.3",
"@primevue/forms": "^4.2.1",
"@primevue/themes": "^4.2.1",
"@tanstack/vue-query": "^5.60.6",
"events": "^3.3.0",
"md5": "^2.3.0",
"pinia": "^2.2.6",
@@ -20,6 +22,7 @@
"svgo": "^3.3.2",
"tailwindcss-primeui": "^0.3.4",
"vue": "^3.5.12",
"vue-query": "^1.26.0",
"vue-router": "^4.4.5"
},
"devDependencies": {
@@ -530,6 +533,18 @@
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/runtime": {
"version": "7.26.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz",
"integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==",
"license": "MIT",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/template": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
@@ -1137,6 +1152,18 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@f3ve/vue-markdown-it": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/@f3ve/vue-markdown-it/-/vue-markdown-it-0.2.3.tgz",
"integrity": "sha512-v0VNd7wb55kwsUUy3n6DLI9+0FYSG0PrCTD3bWuSRo6WS3OHD5wghh/aHzebVdsVkSBXfVpiEUlMA3DrxLs7Lw==",
"license": "MIT",
"dependencies": {
"markdown-it": "^14.1.0"
},
"peerDependencies": {
"vue": "^3.3.4"
}
},
"node_modules/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -1755,6 +1782,83 @@
"win32"
]
},
"node_modules/@tanstack/match-sorter-utils": {
"version": "8.19.4",
"resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.19.4.tgz",
"integrity": "sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==",
"license": "MIT",
"dependencies": {
"remove-accents": "0.5.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/query-core": {
"version": "5.60.6",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.60.6.tgz",
"integrity": "sha512-tI+k0KyCo1EBJ54vxK1kY24LWj673ujTydCZmzEZKAew4NqZzTaVQJEuaG1qKj2M03kUHN46rchLRd+TxVq/zQ==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/vue-query": {
"version": "5.60.6",
"resolved": "https://registry.npmjs.org/@tanstack/vue-query/-/vue-query-5.60.6.tgz",
"integrity": "sha512-VW8eN0nXdmDCjhhZPoNQVN0EWgs5XA0D5OARN8xEhCcYB3NUda9csxIjW45hiWhhqIiUfjLJRDYPJ75nYWbUSw==",
"license": "MIT",
"dependencies": {
"@tanstack/match-sorter-utils": "^8.15.1",
"@tanstack/query-core": "5.60.6",
"@vue/devtools-api": "^6.6.3",
"vue-demi": "^0.14.10"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"@vue/composition-api": "^1.1.2",
"vue": "^2.6.0 || ^3.3.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@tanstack/vue-query/node_modules/vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"license": "MIT",
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@trysound/sax": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
@@ -2717,7 +2821,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true,
"license": "Python-2.0"
},
"node_modules/assertion-error": {
@@ -2781,6 +2884,15 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"license": "MIT"
},
"node_modules/big-integer": {
"version": "1.6.52",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz",
"integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==",
"license": "Unlicense",
"engines": {
"node": ">=0.6"
}
},
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
@@ -2830,6 +2942,22 @@
"node": ">=8"
}
},
"node_modules/broadcast-channel": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz",
"integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.7.2",
"detect-node": "^2.1.0",
"js-sha3": "0.8.0",
"microseconds": "0.2.0",
"nano-time": "1.0.0",
"oblivious-set": "1.0.0",
"rimraf": "3.0.2",
"unload": "2.2.0"
}
},
"node_modules/browserslist": {
"version": "4.24.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz",
@@ -3063,7 +3191,6 @@
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true,
"license": "MIT"
},
"node_modules/confbox": {
@@ -3351,6 +3478,12 @@
"node": ">=0.4.0"
}
},
"node_modules/detect-node": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
"license": "MIT"
},
"node_modules/didyoumean": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
@@ -4116,6 +4249,12 @@
"node": ">=14.14"
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"license": "ISC"
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
@@ -4374,6 +4513,23 @@
"node": ">=0.8.19"
}
},
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
"license": "ISC",
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
"node_modules/ini": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
@@ -4599,11 +4755,16 @@
"node": ">=14"
}
},
"node_modules/js-sha3": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
"integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==",
"license": "MIT"
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true,
"license": "MIT"
},
"node_modules/js-yaml": {
@@ -4786,6 +4947,15 @@
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"license": "MIT"
},
"node_modules/linkify-it": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
"license": "MIT",
"dependencies": {
"uc.micro": "^2.0.0"
}
},
"node_modules/local-pkg": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz",
@@ -4833,6 +5003,19 @@
"dev": true,
"license": "MIT"
},
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"license": "MIT",
"peer": true,
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
"bin": {
"loose-envify": "cli.js"
}
},
"node_modules/loupe": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz",
@@ -4855,6 +5038,33 @@
"@jridgewell/sourcemap-codec": "^1.5.0"
}
},
"node_modules/markdown-it": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
"integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1",
"entities": "^4.4.0",
"linkify-it": "^5.0.0",
"mdurl": "^2.0.0",
"punycode.js": "^2.3.1",
"uc.micro": "^2.1.0"
},
"bin": {
"markdown-it": "bin/markdown-it.mjs"
}
},
"node_modules/match-sorter": {
"version": "6.3.4",
"resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.4.tgz",
"integrity": "sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.23.8",
"remove-accents": "0.5.0"
}
},
"node_modules/md5": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
@@ -4872,6 +5082,12 @@
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
"license": "CC0-1.0"
},
"node_modules/mdurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
"integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
"license": "MIT"
},
"node_modules/memorystream": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
@@ -4910,6 +5126,12 @@
"node": ">=8.6"
}
},
"node_modules/microseconds": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz",
"integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==",
"license": "MIT"
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@@ -5025,6 +5247,15 @@
"thenify-all": "^1.0.0"
}
},
"node_modules/nano-time": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz",
"integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==",
"license": "ISC",
"dependencies": {
"big-integer": "^1.6.16"
}
},
"node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
@@ -5234,6 +5465,21 @@
"node": ">= 6"
}
},
"node_modules/oblivious-set": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz",
"integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==",
"license": "MIT"
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"license": "ISC",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/onetime": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
@@ -5368,6 +5614,15 @@
"node": ">=8"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -5811,6 +6066,15 @@
"node": ">=6"
}
},
"node_modules/punycode.js": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/qr-code-styling": {
"version": "1.8.4",
"resolved": "https://registry.npmjs.org/qr-code-styling/-/qr-code-styling-1.8.4.tgz",
@@ -5849,6 +6113,45 @@
],
"license": "MIT"
},
"node_modules/react": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-query": {
"version": "3.39.3",
"resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz",
"integrity": "sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.5.5",
"broadcast-channel": "^3.4.1",
"match-sorter": "^6.0.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
}
}
},
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@@ -5884,6 +6187,18 @@
"node": ">=8.10.0"
}
},
"node_modules/regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
"license": "MIT"
},
"node_modules/remove-accents": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz",
"integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==",
"license": "MIT"
},
"node_modules/resolve": {
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
@@ -5928,6 +6243,65 @@
"dev": true,
"license": "MIT"
},
"node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"deprecated": "Rimraf versions prior to v4 are no longer supported",
"license": "ISC",
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/rimraf/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/rimraf/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"license": "ISC",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/rimraf/node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/rollup": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.4.tgz",
@@ -6677,6 +7051,12 @@
}
}
},
"node_modules/uc.micro": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
"license": "MIT"
},
"node_modules/ufo": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz",
@@ -6701,6 +7081,16 @@
"node": ">= 10.0.0"
}
},
"node_modules/unload": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz",
"integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==",
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.6.2",
"detect-node": "^2.0.4"
}
},
"node_modules/unplugin": {
"version": "1.16.0",
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.16.0.tgz",
@@ -7170,6 +7560,54 @@
"url": "https://opencollective.com/eslint"
}
},
"node_modules/vue-query": {
"version": "1.26.0",
"resolved": "https://registry.npmjs.org/vue-query/-/vue-query-1.26.0.tgz",
"integrity": "sha512-78JbnLX/3tDll5kDr6PUasRWn05BeWm7yJNeUezA9INrn3AgTCLbsEctnlw6/wM6HiRqFj9F+mf+ruZusyiVOg==",
"license": "MIT",
"dependencies": {
"@vue/devtools-api": "^6.1.4",
"match-sorter": "^6.3.1",
"react-query": "^3.39.0",
"vue-demi": "0.10.1"
},
"peerDependencies": {
"@nuxtjs/composition-api": "^0.28.0",
"@vue/composition-api": "^1.1.2",
"vue": "^2.0.0 || >=3.0.0"
},
"peerDependenciesMeta": {
"@nuxtjs/composition-api": {
"optional": true
},
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/vue-query/node_modules/vue-demi": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.10.1.tgz",
"integrity": "sha512-L6Oi+BvmMv6YXvqv5rJNCFHEKSVu7llpWWJczqmAQYOdmPPw5PNYoz1KKS//Fxhi+4QP64dsPjtmvnYGo1jemA==",
"hasInstallScript": true,
"license": "MIT",
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^2.6.0 || >=3.0.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/vue-router": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.4.5.tgz",
@@ -7416,6 +7854,12 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
},
"node_modules/ws": {
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
+3
View File
@@ -19,8 +19,10 @@
"pnpm": ">=8.15.0"
},
"dependencies": {
"@f3ve/vue-markdown-it": "^0.2.3",
"@primevue/forms": "^4.2.1",
"@primevue/themes": "^4.2.1",
"@tanstack/vue-query": "^5.60.6",
"events": "^3.3.0",
"md5": "^2.3.0",
"pinia": "^2.2.6",
@@ -31,6 +33,7 @@
"svgo": "^3.3.2",
"tailwindcss-primeui": "^0.3.4",
"vue": "^3.5.12",
"vue-query": "^1.26.0",
"vue-router": "^4.4.5"
},
"devDependencies": {
@@ -0,0 +1,135 @@
<template>
<div class="max-w-3xl mx-auto py-6 px-4 md:px-6">
<div v-if="isLoading" class="text-gray-500">Загрузка инструкции...</div>
<div v-else-if="data" class="markdown">
<VueMarkdownIt :source="data" />
</div>
<p v-else-if="isError" class="text-red-500">Ошибка загрузки инструкции.</p>
<p v-else class="text-gray-500">Инструкция для этого типа размещения отсутствует.</p>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { VueMarkdownIt } from '@f3ve/vue-markdown-it'
import { useQuery } from '@tanstack/vue-query'
import { type QRCodeDocument } from '@/types/DBDocumentTypes'
// Импортируем все инструкции из директории
const importInstructions = import.meta.glob('/src/content/placementInstructions/*.md', {
as: 'raw',
}) as unknown as Record<string, () => Promise<string>>
const { placement } = defineProps<{ placement: QRCodeDocument['placement'] }>()
// Хук для загрузки инструкции
async function fetchInstructions(): Promise<string | undefined> {
return importInstructions[`/src/content/placementInstructions/${placement}.md`]?.()
}
// Используем vue-query для управления запросом
const { isLoading, isError, data } = useQuery({
queryKey: ['placementInstructions', computed(() => placement)],
queryFn: fetchInstructions,
})
</script>
<style scoped>
.markdown {
font-family: 'Inter', sans-serif;
line-height: 1.7;
color: #333;
}
.markdown ::v-deep(h1) {
font-size: 2rem;
margin-bottom: 1rem;
color: #111827;
font-weight: 700;
}
.markdown ::v-deep(h2) {
font-size: 1.75rem;
margin-top: 1.5rem;
margin-bottom: 1rem;
color: #1f2937;
font-weight: 600;
}
.markdown ::v-deep(h3) {
font-size: 1.5rem;
margin-top: 1.25rem;
margin-bottom: 0.75rem;
color: #374151;
font-weight: 500;
}
.markdown ::v-deep(p) {
margin-bottom: 1rem;
color: #4b5563;
}
.markdown ::v-deep(ul) {
list-style: disc;
margin-left: 1.5rem;
margin-bottom: 1rem;
}
.markdown ::v-deep(ol) {
list-style: decimal;
margin-left: 1.5rem;
margin-bottom: 1rem;
}
.markdown ::v-deep(li) {
margin-bottom: 0.5rem;
}
.markdown ::v-deep(a) {
color: #2563eb;
text-decoration: underline;
}
.markdown ::v-deep(blockquote) {
border-left: 4px solid #d1d5db;
padding-left: 1rem;
color: #6b7280;
margin: 1rem 0;
font-style: italic;
}
.markdown ::v-deep(code) {
background-color: #f3f4f6;
border-radius: 4px;
padding: 0.2rem 0.4rem;
font-family: 'Courier New', Courier, monospace;
color: #1f2937;
}
.markdown ::v-deep(pre) {
background-color: #f9fafb;
padding: 1rem;
border-radius: 8px;
overflow-x: auto;
color: #111827;
font-family: 'Courier New', Courier, monospace;
}
.markdown ::v-deep(table) {
width: 100%;
border-collapse: collapse;
margin-bottom: 1rem;
}
.markdown ::v-deep(th),
.markdown ::v-deep(td) {
border: 1px solid #d1d5db;
padding: 0.5rem;
}
.markdown ::v-deep(th) {
background-color: #f9fafb;
font-weight: 600;
text-align: left;
}
</style>
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<section class="max-w-lg w-full text-center">
<section class="max-w-prose w-full text-center">
<!-- Контактная информация -->
<div class="flex items-start bg-gray-100 border rounded-lg p-4">
<!-- Аватарка Gravatar -->
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<section class="max-w-lg w-full">
<section class="max-w-prose w-full">
<p class="text-gray-600 mb-4 text-center">Выберите сообщение из списка или напишите своё:</p>
<!-- Предустановленные сообщения -->
+22
View File
@@ -0,0 +1,22 @@
### Инструкции по размещению на автомобиль:
**Где размещать:**
- На боковом или заднем стекле автомобиля.
**Как разместить:**
1. Найдите видимое место на стекле, которое будет хорошо видно прохожим, например, в углу заднего или бокового окна.
2. Очистите поверхность стекла от пыли и грязи с помощью сухой или слегка влажной ткани.
3. Если вы используете наклейку:
- Убедитесь, что материал устойчив к влаге и выцветанию.
- Аккуратно приклейте наклейку на стекло, разглаживая её от центра к краям, чтобы избежать появления пузырьков воздуха.
4. Если вы используете пластину или рамку:
- Проверьте, что крепление не повредит стекло.
- Убедитесь, что QR-код надёжно зафиксирован и не шатается.
5. Если QR-код нанесён с помощью трафарета или гравировки:
- Проверьте, что код выполнен без дефектов и легко сканируется.
- Очистите стекло от остатков краски или мусора.
**Важно:**
- Убедитесь, что QR-код не блокирует обзор водителю.
- Проверьте, что код можно легко сканировать снаружи автомобиля в любое время суток.
- Если QR-код размещён внутри, убедитесь, что стекло чистое и не бликует.
+14
View File
@@ -0,0 +1,14 @@
### Инструкции по размещению на входную дверь дома или квартиры:
**Где размещать:**
- На входной двери или рядом с домофоном.
- На двери или рядом с дверным звонком.
**Как разместить:**
1. Найдите место рядом с дверным звонком или на самой двери, которое будет заметно для гостей.
2. Очистите поверхность от пыли и грязи, чтобы QR-код держался крепче.
3. Приклейте QR-код на дверь с помощью двустороннего скотча или водостойкого клея.
4. Если вы не хотите приклеивать код, используйте рамку или подставку и разместите её на полке или возле двери.
**Важно:**
- Проверьте, что QR-код не блокирует другие элементы двери.
- Убедитесь, что его легко заметить и сканировать при любом освещении.
@@ -0,0 +1,12 @@
### Инструкции по размещению:
**Где размещать:**
- В зависимости от ситуации, на любом удобном и видимом месте.
**Как разместить:**
1. Подберите место, где QR-код будет защищён от повреждений и виден окружающим.
2. Используйте подходящие материалы для крепления: двусторонний скотч, рамку, подставку или брелок.
3. Убедитесь, что QR-код хорошо заметен и его легко сканировать.
**Важно:**
- Адаптируйте место размещения под конкретную задачу.
- Проверьте, чтобы QR-код не был скрыт другими предметами.
+13
View File
@@ -0,0 +1,13 @@
### Инструкции по размещению на питомца:
**Где размещать:**
- На ошейнике питомца.
**Как разместить:**
1. Выберите удобный ошейник с креплением для QR-кода. Лучше всего подойдут ошейники с кольцом или специальным держателем.
2. Используйте прочный и водостойкий брелок или пластиковую подложку для QR-кода.
3. Закрепите QR-код на ошейнике так, чтобы он не мешал вашему питомцу, но был легко доступен для сканирования.
4. Проверьте, чтобы QR-код был хорошо зафиксирован и не потерялся во время прогулки.
**Важно:**
- Используйте материалы, которые не вызовут аллергии или раздражения у питомца.
- Проверьте, что QR-код можно легко сканировать в любом положении.
@@ -0,0 +1,18 @@
### Инструкции по размещению на стол в кафе или ресторане:
**Где размещать:**
- На столе, в меню или на подставке.
**Как разместить:**
1. Если QR-код размещается на столе:
- Используйте небольшой деревянный держатель или подставку.
- Поставьте подставку в центр стола или сбоку, чтобы гости могли легко заметить код.
2. Если QR-код размещается в меню:
- Вставьте QR-код на видное место, например, на первую или последнюю страницу меню.
- Используйте плотный ламинированный материал, чтобы код не повредился при использовании меню.
3. Если QR-код размещается на подставке:
- Поставьте подставку на уровне глаз сидящих гостей.
- Проверьте, чтобы подставка была устойчива и не падала.
**Важно:**
- Защищайте QR-код от влаги, например, от пролитых напитков.
- Проверьте, что его можно легко сканировать, сидя за столом.
@@ -0,0 +1,21 @@
### Инструкции по размещению в магазине
**Где размещать:**
- На витрине, входной двери, кассе или информационной стойке.
**Как разместить:**
1. **Если QR-код размещается на витрине или входной двери:**
- Найдите видное место на стекле, чтобы QR-код был хорошо заметен прохожим.
- Очистите стекло от пыли и загрязнений.
- Приклейте QR-код на внутреннюю сторону стекла, чтобы защитить его от погодных условий.
2. **Если QR-код размещается на кассе:**
- Используйте подставку или рамку, чтобы QR-код был на уровне глаз клиента.
- Убедитесь, что он не мешает работе кассира.
3. **Если QR-код размещается на информационной стойке:**
- Прикрепите QR-код к стойке с помощью двустороннего скотча.
- Либо используйте рамку, чтобы код выглядел аккуратно и профессионально.
**Важно:**
- Убедитесь, что QR-код можно легко сканировать, даже при ярком свете или бликах.
- Если QR-код находится на улице, используйте стойкие к погодным условиям материалы.
- Разместите код так, чтобы он не мешал и не мог быть случайно повреждён.
+4
View File
@@ -1,4 +1,5 @@
import { createApp } from 'vue'
import { VueQueryPlugin } from '@tanstack/vue-query'
import { createPinia } from 'pinia'
import PouchDB from 'pouchdb-browser'
@@ -31,6 +32,9 @@ import router from './router'
const app = createApp(App)
app.use(VueQueryPlugin, {
enableDevtoolsV6Plugin: import.meta.env.DEV,
})
app.use(createPinia())
app.use(router)
app.use(PrimeVue, {
+2 -2
View File
@@ -1,7 +1,7 @@
<template>
<div class="max-w-lg mx-auto py-6 px-4 md:px-6">
<div class="max-w-prose mx-auto py-6 px-4 md:px-6">
<section class="content">
<div class="max-w-lg mx-auto py-8">
<div class="max-w-prose mx-auto py-8">
<!-- Секция выбора размещения -->
<CreateSection :isActive="activeSteps.includes('placement')">
<CreatePlacementSection v-model="placement" />
+58 -54
View File
@@ -1,27 +1,31 @@
<template>
<div class="flex flex-col min-h-screen">
<main class="flex-grow flex items-center justify-center py-6 px-4 md:px-6">
<section class="max-w-lg w-full flex flex-col gap-1">
<section class="max-w-prose w-full flex flex-col gap-1">
<h2 class="text-xl font-semibold mb-4">Ваш QRкод готов</h2>
<p class="text-gray-600 mb-4">Сохраните его и ознакомьтесь с инструкциями по размещению.</p>
<!-- Рендер QRкода -->
<div v-if="!loading && svgUrl" class="border p-4 bg-white rounded-lg mb-6">
<img :src="svgUrl" alt="QR‑код" />
<div v-if="!svgQueryIsLoading && svgQueryData" class="border p-4 bg-white rounded-lg mb-6">
<img :src="svgQueryData" alt="QR‑код" />
</div>
<!-- Сообщение об ошибке -->
<p v-if="error" class="text-red-500 mt-4">{{ error }}</p>
<p v-if="loading" class="text-gray-500 mt-4">Загрузка...</p>
<p v-if="qrCodeQueryIsError" class="text-red-500 mt-4">
Ошибка загрузки данных QRкода: {{ qrCodeQueryError!.message }}
</p>
<p v-if="svgQueryIsLoading" class="text-gray-500 mt-4">Загрузка...</p>
<!-- Кнопки для скачивания -->
<div v-if="!loading && !error" class="flex flex-row gap-4 justify-center">
<div
v-if="!svgQueryIsLoading && !qrCodeQueryIsError && svgQueryData"
class="flex flex-row gap-4 justify-center"
>
<Button
v-if="svgUrl"
label="Скачать SVG"
icon="pi pi-download"
class="p-button-sm"
:href="svgUrl"
:href="svgQueryData"
:download="`${sanitizedFileName}.svg`"
as="a"
/>
@@ -32,6 +36,12 @@
@click="downloadPng"
/>
</div>
<!-- Инструкции по размещению -->
<ManagePlacementInstructions
:placement="qrCodeDoc?.placement"
v-if="qrCodeDoc?.placement"
/>
</section>
</main>
@@ -50,27 +60,23 @@
</template>
<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { computed } from 'vue'
import { useQuery } from '@tanstack/vue-query'
import QRCodeStyling from 'qr-code-styling'
import { getQrCodeDocument } from '@/api/qrCode'
import { optimize } from 'svgo'
import type { QRCodeDocument } from '@/types/DBDocumentTypes'
import { getQrCodeDocument } from '@/api/qrCode'
import { type QRCodeDocument } from '@/types/DBDocumentTypes'
const { qr_code_uri } = defineProps<{ qr_code_uri: QRCodeDocument['uri'] }>()
// Локальные состояния
const loading = ref(true)
const error = ref<string | null>(null)
const qrCodeData = ref<null | { name: string; url: string }>(null)
const svgUrl = ref<string | null>(null)
// Получение имени файла
const sanitizedFileName = computed(() => {
const sanitized = qrCodeData.value?.name
.replace(/[<>:"/\\|?*\x00-\x1F]/g, '') // Убираем запрещённые символы
.replace(/\s+/g, '_') // Заменяем пробелы на подчёркивания
.trim()
return sanitized ? `${sanitized}_QR-Code_HereConnect` : 'QR-Code_HereConnect'
// Хук для загрузки данных QR‑кода
const {
data: qrCodeDoc,
isError: qrCodeQueryIsError,
error: qrCodeQueryError,
} = useQuery({
queryKey: ['qrCode', computed(() => qr_code_uri)],
queryFn: () => getQrCodeDocument(qr_code_uri),
})
// Инициализация QRCodeStyling
@@ -84,10 +90,26 @@ const qrCode = new QRCodeStyling({
},
})
// Генерация и оптимизация SVG
async function generateOptimizedSvg(url: string) {
try {
qrCode.update({ data: url })
// Получение имени файла
const sanitizedFileName = computed(() => {
const sanitized = qrCodeDoc.value?.name
?.replace(/[<>:"/\\|?*\x00-\x1F]/g, '') // Убираем запрещённые символы
.replace(/\s+/g, '_') // Заменяем пробелы на подчёркивания
.trim()
return sanitized ? `${sanitized}_QR-Code_HereConnect` : 'QR-Code_HereConnect'
})
// Хук для генерации и оптимизации SVG
const {
isLoading: svgQueryIsLoading,
data: svgQueryData,
error: svgQueryError,
} = useQuery({
queryKey: ['svg', computed(() => qr_code_uri)],
enabled: computed(() => !!qrCodeDoc.value?.url),
queryFn: async () => {
qrCode.update({ data: qrCodeDoc.value!.url })
const blob = await qrCode.getRawData('svg')
if (blob && blob instanceof Blob) {
const text = await blob.text()
@@ -104,17 +126,20 @@ async function generateOptimizedSvg(url: string) {
})
if (optimizedSvg.data) {
svgUrl.value = URL.createObjectURL(new Blob([optimizedSvg.data], { type: 'image/svg+xml' }))
return URL.createObjectURL(new Blob([optimizedSvg.data], { type: 'image/svg+xml' }))
} else {
throw new Error('Ошибка оптимизации SVG')
}
} else {
throw new Error('Ошибка генерации QR‑кода')
}
} catch (err) {
error.value = (err as Error).message || 'Неизвестная ошибка'
}
},
onSettled(data) {
if (!data && svgQueryError) {
console.error('Ошибка загрузки SVG:', svgQueryError.message)
}
},
})
// Скачивание PNG
async function downloadPng() {
@@ -124,28 +149,7 @@ async function downloadPng() {
extension: 'png',
})
} catch (err) {
error.value = (err as Error).message || 'Ошибка при скачивании QR‑кода'
console.error('Ошибка скачивания PNG:', err)
}
}
// Монтирование
onMounted(async () => {
try {
// Загружаем данные QR‑кода
const doc = await getQrCodeDocument(qr_code_uri)
qrCodeData.value = { name: doc.name, url: doc.url }
await generateOptimizedSvg(doc.url)
} catch (err) {
error.value = (err as Error).message || 'Ошибка загрузки данных QR‑кода'
} finally {
loading.value = false
}
})
// Очистка ресурсов при размонтировании
onUnmounted(() => {
if (svgUrl.value) {
URL.revokeObjectURL(svgUrl.value)
}
})
</script>
+1 -1
View File
@@ -1,7 +1,7 @@
<template>
<div class="flex flex-col min-h-screen">
<main class="flex-grow flex items-center justify-center py-6 px-4 md:px-6">
<section class="max-w-lg w-full flex flex-col gap-10">
<section class="max-w-prose w-full flex flex-col gap-10">
<template v-for="action in actions">
<ReadContactInfo v-if="action === 'viewContactInfo'" :contactInfo="contactInfo" />
<ReadMessageSender