diff --git a/frontend_vue/package-lock.json b/frontend_vue/package-lock.json index e9d9a37e7..af56eae70 100644 --- a/frontend_vue/package-lock.json +++ b/frontend_vue/package-lock.json @@ -17,6 +17,7 @@ "@vue/test-utils": "^2.4.4", "@vueuse/core": "^10.9.0", "axios": "^1.6.7", + "canvas-confetti": "^1.9.3", "eslint-config-typescript": "^3.0.0", "floating-vue": "^5.2.2", "vee-validate": "^4.12.6", @@ -3682,6 +3683,15 @@ } ] }, + "node_modules/canvas-confetti": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.3.tgz", + "integrity": "sha512-rFfTURMvmVEX1gyXFgn5QMn81bYk70qa0HLzcIOSVEyl57n6o9ItHeBtUSWdvKAPY0xlvBHno4/v3QPrT83q9g==", + "funding": { + "type": "donate", + "url": "https://www.paypal.me/kirilvatev" + } + }, "node_modules/chai": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", diff --git a/frontend_vue/package.json b/frontend_vue/package.json index 0e727e2f9..2a2fb91c2 100644 --- a/frontend_vue/package.json +++ b/frontend_vue/package.json @@ -23,6 +23,7 @@ "@vue/test-utils": "^2.4.4", "@vueuse/core": "^10.9.0", "axios": "^1.6.7", + "canvas-confetti": "^1.9.3", "eslint-config-typescript": "^3.0.0", "floating-vue": "^5.2.2", "vee-validate": "^4.12.6", diff --git a/frontend_vue/src/components/ModalToken.vue b/frontend_vue/src/components/ModalToken.vue index d4c6f6423..181b7cc10 100644 --- a/frontend_vue/src/components/ModalToken.vue +++ b/frontend_vue/src/components/ModalToken.vue @@ -134,6 +134,7 @@ import ButtonHowToDeploy from '@/components/ui/ButtonHowToDeploy.vue'; import { generateToken } from '@/api/main'; import { TOKENS_TYPE } from './constants'; import { tokenServices } from '@/utils/tokenServices'; +import { launchConfetti } from '@/utils/confettiEffect'; enum ModalType { AddToken = 'addToken', @@ -262,6 +263,7 @@ async function handleGenerateToken(formValues: BaseFormValuesType) { modalType.value = ModalType.NewToken; // Keep track of loaded components componentStack.value.push(modalType.value); + launchConfetti(); } catch (err) { triggerSubmit.value = false; isGenerateTokenError.value = true; diff --git a/frontend_vue/src/utils/confettiEffect.ts b/frontend_vue/src/utils/confettiEffect.ts new file mode 100644 index 000000000..5fe2f2470 --- /dev/null +++ b/frontend_vue/src/utils/confettiEffect.ts @@ -0,0 +1,35 @@ +//@ts-ignore +import confetti from 'canvas-confetti'; + +export function launchConfetti() { + const confettiCanvas = document.createElement('canvas'); + const modal = document.querySelector('.vfm__content'); + modal?.appendChild(confettiCanvas); + + Object.assign(confettiCanvas.style, { + position: 'absolute', + top: '0', + left: '0', + width: '100%', + height: '100%', + pointerEvents: 'none', + }); + + Object.assign(confettiCanvas, { + with: window.innerWidth, + height: window.innerHeight, + }); + + const myConfetti = confetti.create(confettiCanvas, { resize: true }); + + myConfetti({ + particleCount: 100, + spread: 160, + origin: { y: 0.9 }, + colors: ['#F2059F', '#04D9B2', '#80C7F2'], + }); + + setTimeout(() => { + confettiCanvas.remove(); + }, 2000); +}