Skip to content

Commit 7503401

Browse files
authored
Merge pull request #396 from singnet/development
Development
2 parents 6f3cb4f + 2282c84 commit 7503401

5 files changed

Lines changed: 95 additions & 8 deletions

File tree

.vitepress/theme/captchaFetch.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { Plugin } from "vue";
2+
import { createCaptchaFetchHandler } from "waf-captcha-frontend";
3+
4+
declare module '@vue/runtime-core' {
5+
interface ComponentCustomProperties {
6+
$captcha: {
7+
fetch: ReturnType<typeof createCaptchaFetchHandler> | null;
8+
isReady: boolean;
9+
};
10+
}
11+
}
12+
13+
let captchaInstance: ((path: RequestInfo | URL, init: RequestInit) => Promise<Response>) | null = null;
14+
15+
const initCaptcha = () => {
16+
if (typeof window === "undefined") {
17+
captchaInstance = fetch;
18+
return
19+
}
20+
if (captchaInstance) return captchaInstance;
21+
22+
const { VITE_JSAPI_URL, VITE_CAPTCHA_TOKEN } = import.meta.env;
23+
24+
if (!VITE_CAPTCHA_TOKEN || !VITE_JSAPI_URL) {
25+
console.warn('Captcha configuration missing');
26+
return fetch;
27+
}
28+
29+
captchaInstance = createCaptchaFetchHandler({
30+
API_KEY: VITE_CAPTCHA_TOKEN,
31+
JSAPI_URL: VITE_JSAPI_URL,
32+
captchaContainerId: "captcha-modal-container"
33+
});
34+
35+
return captchaInstance;
36+
};
37+
38+
const captchaFetch = initCaptcha();
39+
40+
const captchaPlugin: Plugin = {
41+
install(app: any) {
42+
app.config.globalProperties.$captchaFetch = captchaFetch;
43+
app.config.globalProperties.$captcha = {
44+
fetch: captchaFetch,
45+
isReady: !!captchaFetch
46+
};
47+
48+
app.provide('captchaFetch', captchaFetch);
49+
app.provide('captcha', {
50+
fetch: captchaFetch,
51+
isReady: !!captchaFetch
52+
});
53+
}
54+
};
55+
56+
export { captchaPlugin };

.vitepress/theme/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import DefaultTheme from "vitepress/theme";
2+
import { captchaPlugin } from "./captchaFetch";
23
import Home from "../../components/Home/Home.vue";
34
import Video from "../../components/Common/Video.vue";
45
import Footer from "../../components/Footer/Footer.vue";
@@ -33,5 +34,6 @@ export default {
3334
app.component("ImageViewer", ImageViewer);
3435
app.component("AccordionItem", AccordionItem);
3536
app.config.globalProperties.$daemonVersion = DAEMON_VERSION;
37+
app.use(captchaPlugin);
3638
},
3739
} satisfies Theme;

components/Common/FeedBackForm.vue

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<template>
2+
<div id="captcha-modal-container"></div>
23
<div class="feedback-form-holder">
34
<div class="feedback-form" :class="{ 'gradient-border': !isMobile, 'hidden': !isFormDisplayed }">
45
<div class="form-header">
@@ -45,8 +46,13 @@
4546
</div>
4647
</form>
4748
</div>
48-
<div class="ready-alert" :class="{ 'hidden': !isRequestSent }">Thank you!
49-
Our technical support will get in touch with you soon!</div>
49+
<div class="ready-alert" :class="{ 'hidden': !isRequestSent }">
50+
Thank you!
51+
Our technical support will get in touch with you soon!
52+
</div>
53+
<div class="error-alert" :class="{ 'hidden': !isRequestErrored }">
54+
Something went wrong! Please, try again later
55+
</div>
5056
<div class="feedback-form-launcher" :class="{ 'hidden': isFormDisplayed }">
5157
<button @click="toggleFormVisibility">
5258
<img src="/assets/images/common/feedback.webp" alt="feedback" />
@@ -75,8 +81,10 @@ const EMAIL_VALIDATION_REGEX: RegExp = new RegExp(
7581
export default {
7682
data() {
7783
return {
84+
isCaptchaReady: false,
7885
isRequestHandling: false as boolean,
7986
isRequestSent: false as boolean,
87+
isRequestErrored: false as boolean,
8088
isFormDisplayed: false as boolean,
8189
name: '' as string,
8290
email: '' as string,
@@ -125,9 +133,14 @@ export default {
125133
},
126134
async showAlert(): Promise<void> {
127135
this.isRequestSent = true;
128-
await new Promise(r => setTimeout(r, 2000));
136+
await new Promise(r => setTimeout(r, 5000));
129137
this.isRequestSent = false;
130138
},
139+
async showError(): Promise<void> {
140+
this.isRequestErrored = true;
141+
await new Promise(r => setTimeout(r, 5000));
142+
this.isRequestErrored = false;
143+
},
131144
async sendFeedback(): Promise<void> {
132145
try {
133146
const options: RequestInit = {
@@ -149,15 +162,16 @@ export default {
149162
attachment_details: {},
150163
})
151164
};
152-
if (!this.isRequestHandling) {
165+
if (!this.isRequestHandling && this.$captcha.isReady) {
153166
this.isRequestHandling = true;
154-
await fetch(endpoints.FEEDBACK, options);
167+
await this.$captcha?.fetch?.(endpoints.FEEDBACK, options);
155168
}
156169
this.isFormDisplayed = false;
157170
await this.showAlert();
158171
} catch (error) {
159172
this.isFormDisplayed = false;
160173
console.log("error on feedback request: ", error);
174+
this.showError();
161175
} finally {
162176
this.resetForm();
163177
this.isRequestHandling = false;
@@ -202,6 +216,7 @@ export default {
202216
background: var(--feedback-form-background);
203217
}
204218
219+
.error-alert.hidden,
205220
.ready-alert.hidden,
206221
.feedback-form.hidden,
207222
.feedback-form-launcher.hidden {
@@ -335,16 +350,26 @@ form {
335350
transform: scale(1.1);
336351
}
337352
353+
.error-alert,
338354
.ready-alert {
339355
width: 200px;
340356
position: absolute;
341357
right: 100px;
342358
bottom: 30px;
343359
padding: 10px;
344360
border-radius: 8px;
361+
backdrop-filter: blur(5px);
362+
transition: var(--feedback-form-transition) all;
363+
}
364+
365+
.error-alert {
366+
color: var(--vp-c-caution-3);
367+
background-color: var(--vp-c-danger-soft);
368+
}
369+
370+
.ready-alert {
345371
color: var(--vp-c-green-1);
346372
background-color: var(--vp-c-green-soft);
347-
transition: var(--feedback-form-transition) all;
348373
}
349374
350375
@media (max-width: 450px) {

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
},
88
"dependencies": {
99
"markdown-it-container": "^4.0.0",
10-
"swiper": "^11.1.12"
10+
"swiper": "^11.1.12",
11+
"waf-captcha-frontend": "^0.0.7"
1112
},
1213
"devDependencies": {
1314
"@types/node": "^24.10.1",

utils/constants/endpoints.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11

2+
/// <reference types="vite/client" />
3+
24
interface ImportMetaEnv {
35
readonly VITE_FEEDBACK_FORM_URL: string;
6+
readonly VITE_JSAPI_URL: string;
7+
readonly VITE_CAPTCHA_TOKEN: string;
48
}
59

610
interface ImportMeta {
711
readonly env: ImportMetaEnv;
812
}
913

10-
// @ts-ignore
1114
const { VITE_FEEDBACK_FORM_URL } = import.meta.env;
1215

1316
interface APIEndpoints {

0 commit comments

Comments
 (0)