interview-widget 0.0.8 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +187 -101
- package/dist/components/interview/interview-controller.d.ts +8 -0
- package/dist/components/interview/interview-header.d.ts +1 -0
- package/dist/components/interview/question-display.d.ts +3 -2
- package/dist/components/modals/exit-confirmation-modal.d.ts +7 -0
- package/dist/components/timer/timer-display.d.ts +13 -0
- package/dist/components/ui/dialog.d.ts +13 -0
- package/dist/context/interview-widget-context.d.ts +34 -0
- package/dist/hooks/use-api.d.ts +26 -0
- package/dist/hooks/use-dialog.d.ts +6 -0
- package/dist/hooks/use-interview-api.d.ts +5 -0
- package/dist/hooks/use-stt.d.ts +20 -0
- package/dist/hooks/use-timer.d.ts +12 -0
- package/dist/hooks/use-tts.d.ts +15 -0
- package/dist/index.d.ts +3 -2
- package/dist/services/api/index.d.ts +2 -0
- package/dist/services/api/interview-api.d.ts +23 -0
- package/dist/services/stt/index.d.ts +1 -0
- package/dist/services/stt/stt-service.d.ts +78 -0
- package/dist/services/timer/index.d.ts +6 -0
- package/dist/services/timer/timer-service.d.ts +81 -0
- package/dist/services/tts/index.d.ts +1 -0
- package/dist/services/tts/tts-service.d.ts +43 -0
- package/dist/types.d.ts +55 -29
- package/dist/utils/constants.d.ts +3 -0
- package/dist/utils/helper.d.ts +6 -0
- package/dist/widget.css +1 -1
- package/dist/widget.es.js +1594 -432
- package/dist/widget.umd.js +2 -2
- package/package.json +5 -4
- package/dist/examples/APIUsageExample.d.ts +0 -5
- package/dist/hooks/useAPI.d.ts +0 -12
- package/dist/services/index.d.ts +0 -2
- package/dist/services/interview-api.d.ts +0 -47
- /package/dist/components/{onboarding-modal.d.ts → modals/onboarding-modal.d.ts} +0 -0
package/dist/widget.es.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import {
|
|
5
|
-
|
|
1
|
+
var me = Object.defineProperty;
|
|
2
|
+
var ge = (i, t, e) => t in i ? me(i, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[t] = e;
|
|
3
|
+
var I = (i, t, e) => ge(i, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
+
import { createContext as he, useContext as fe, useEffect as A, useState as y, useRef as D, useCallback as v, useMemo as xe } from "react";
|
|
5
|
+
import { createPortal as pe } from "react-dom";
|
|
6
|
+
var X = { exports: {} }, U = {};
|
|
6
7
|
/**
|
|
7
8
|
* @license React
|
|
8
9
|
* react-jsx-runtime.production.js
|
|
@@ -12,56 +13,281 @@ var M = { exports: {} }, N = {};
|
|
|
12
13
|
* This source code is licensed under the MIT license found in the
|
|
13
14
|
* LICENSE file in the root directory of this source tree.
|
|
14
15
|
*/
|
|
15
|
-
var
|
|
16
|
-
function
|
|
17
|
-
var
|
|
18
|
-
if (
|
|
19
|
-
|
|
20
|
-
for (var
|
|
21
|
-
|
|
22
|
-
} else
|
|
23
|
-
return
|
|
24
|
-
$$typeof:
|
|
16
|
+
var be = Symbol.for("react.transitional.element"), ye = Symbol.for("react.fragment");
|
|
17
|
+
function Z(i, t, e) {
|
|
18
|
+
var a = null;
|
|
19
|
+
if (e !== void 0 && (a = "" + e), t.key !== void 0 && (a = "" + t.key), "key" in t) {
|
|
20
|
+
e = {};
|
|
21
|
+
for (var s in t)
|
|
22
|
+
s !== "key" && (e[s] = t[s]);
|
|
23
|
+
} else e = t;
|
|
24
|
+
return t = e.ref, {
|
|
25
|
+
$$typeof: be,
|
|
25
26
|
type: i,
|
|
26
|
-
key:
|
|
27
|
-
ref:
|
|
28
|
-
props:
|
|
27
|
+
key: a,
|
|
28
|
+
ref: t !== void 0 ? t : null,
|
|
29
|
+
props: e
|
|
29
30
|
};
|
|
30
31
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
var
|
|
36
|
-
const
|
|
32
|
+
U.Fragment = ye;
|
|
33
|
+
U.jsx = Z;
|
|
34
|
+
U.jsxs = Z;
|
|
35
|
+
X.exports = U;
|
|
36
|
+
var r = X.exports;
|
|
37
|
+
const C = {
|
|
38
|
+
api: {
|
|
39
|
+
baseUrl: "/api",
|
|
40
|
+
retryConfig: {
|
|
41
|
+
attempts: 3,
|
|
42
|
+
backoff: "exponential",
|
|
43
|
+
baseDelay: 1e3
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
ui: {
|
|
47
|
+
baseColor: "#3B82F6",
|
|
48
|
+
borderRadius: "8px"
|
|
49
|
+
},
|
|
50
|
+
interview: {
|
|
51
|
+
timers: {
|
|
52
|
+
thinkingDuration: 30,
|
|
53
|
+
answeringDuration: 120,
|
|
54
|
+
editingDuration: 30
|
|
55
|
+
},
|
|
56
|
+
stt: {
|
|
57
|
+
provider: "groq",
|
|
58
|
+
model: "whisper-large-v3-turbo",
|
|
59
|
+
language: "en"
|
|
60
|
+
},
|
|
61
|
+
tts: {
|
|
62
|
+
provider: "piper"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}, ee = he(
|
|
66
|
+
null
|
|
67
|
+
);
|
|
68
|
+
function Ne({
|
|
69
|
+
config: i = {},
|
|
70
|
+
children: t
|
|
71
|
+
}) {
|
|
72
|
+
var a, s, c, n;
|
|
73
|
+
const e = {
|
|
74
|
+
api: {
|
|
75
|
+
...C.api,
|
|
76
|
+
...i.api,
|
|
77
|
+
retryConfig: {
|
|
78
|
+
...C.api.retryConfig,
|
|
79
|
+
...(a = i.api) == null ? void 0 : a.retryConfig
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
ui: {
|
|
83
|
+
...C.ui,
|
|
84
|
+
...i.ui
|
|
85
|
+
},
|
|
86
|
+
interview: {
|
|
87
|
+
...C.interview,
|
|
88
|
+
...i.interview,
|
|
89
|
+
timers: {
|
|
90
|
+
...C.interview.timers,
|
|
91
|
+
...(s = i.interview) == null ? void 0 : s.timers
|
|
92
|
+
},
|
|
93
|
+
stt: {
|
|
94
|
+
...C.interview.stt,
|
|
95
|
+
...(c = i.interview) == null ? void 0 : c.stt
|
|
96
|
+
},
|
|
97
|
+
tts: {
|
|
98
|
+
...C.interview.tts,
|
|
99
|
+
...(n = i.interview) == null ? void 0 : n.tts
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
return /* @__PURE__ */ r.jsx(ee.Provider, { value: e, children: t });
|
|
104
|
+
}
|
|
105
|
+
function q() {
|
|
106
|
+
const i = fe(ee);
|
|
107
|
+
if (!i)
|
|
108
|
+
throw new Error(
|
|
109
|
+
"useInterviewConfig must be used within an InterviewWidgetProvider. Wrap your component tree with <InterviewWidgetProvider config={...}>"
|
|
110
|
+
);
|
|
111
|
+
return i;
|
|
112
|
+
}
|
|
113
|
+
function Te() {
|
|
114
|
+
return q().api || C.api;
|
|
115
|
+
}
|
|
116
|
+
function F() {
|
|
117
|
+
return q().ui || C.ui;
|
|
118
|
+
}
|
|
119
|
+
function Ie() {
|
|
120
|
+
return q().interview || C.interview;
|
|
121
|
+
}
|
|
122
|
+
const ve = ({
|
|
123
|
+
isOpen: i,
|
|
124
|
+
onClose: t,
|
|
125
|
+
children: e,
|
|
126
|
+
title: a,
|
|
127
|
+
showCloseButton: s = !0,
|
|
128
|
+
closeOnOverlayClick: c = !0,
|
|
129
|
+
closeOnEscape: n = !0,
|
|
130
|
+
className: o = ""
|
|
131
|
+
}) => {
|
|
132
|
+
if (A(() => {
|
|
133
|
+
if (!i || !n) return;
|
|
134
|
+
const d = (u) => {
|
|
135
|
+
u.key === "Escape" && t();
|
|
136
|
+
};
|
|
137
|
+
return document.addEventListener("keydown", d), () => document.removeEventListener("keydown", d);
|
|
138
|
+
}, [i, n, t]), A(() => (i ? (document.body.style.overflow = "hidden", document.body.classList.add("interview-widget-container")) : (document.body.style.overflow = "unset", document.body.classList.remove("interview-widget-container")), () => {
|
|
139
|
+
document.body.style.overflow = "unset";
|
|
140
|
+
}), [i]), !i) return null;
|
|
141
|
+
const m = (d) => {
|
|
142
|
+
c && d.target === d.currentTarget && t();
|
|
143
|
+
}, g = /* @__PURE__ */ r.jsxs("div", { className: "iw-fixed iw-inset-0 iw-z-50 iw-flex iw-items-center iw-justify-center", children: [
|
|
144
|
+
/* @__PURE__ */ r.jsx(
|
|
145
|
+
"div",
|
|
146
|
+
{
|
|
147
|
+
className: "iw-fixed iw-inset-0 iw-bg-black iw-bg-opacity-50 iw-transition-opacity",
|
|
148
|
+
onClick: m
|
|
149
|
+
}
|
|
150
|
+
),
|
|
151
|
+
/* @__PURE__ */ r.jsxs(
|
|
152
|
+
"div",
|
|
153
|
+
{
|
|
154
|
+
className: `iw-relative iw-bg-white iw-rounded-lg iw-shadow-xl iw-max-w-md iw-w-full iw-mx-4 iw-max-h-[90vh] iw-overflow-hidden ${o}`,
|
|
155
|
+
role: "dialog",
|
|
156
|
+
"aria-modal": "true",
|
|
157
|
+
"aria-labelledby": a ? "dialog-title" : void 0,
|
|
158
|
+
children: [
|
|
159
|
+
(a || s) && /* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-justify-between iw-p-4 iw-border-b iw-border-gray-200", children: [
|
|
160
|
+
a && /* @__PURE__ */ r.jsx(
|
|
161
|
+
"h2",
|
|
162
|
+
{
|
|
163
|
+
id: "dialog-title",
|
|
164
|
+
className: "iw-text-lg iw-font-semibold iw-text-gray-900",
|
|
165
|
+
children: a
|
|
166
|
+
}
|
|
167
|
+
),
|
|
168
|
+
s && /* @__PURE__ */ r.jsx(
|
|
169
|
+
"button",
|
|
170
|
+
{
|
|
171
|
+
onClick: t,
|
|
172
|
+
className: "iw-p-1 iw-text-gray-400 iw-hover:text-gray-600 iw-transition-colors iw-rounded iw-hover:bg-gray-100",
|
|
173
|
+
"aria-label": "Close dialog",
|
|
174
|
+
children: /* @__PURE__ */ r.jsx(
|
|
175
|
+
"svg",
|
|
176
|
+
{
|
|
177
|
+
className: "iw-w-5 iw-h-5",
|
|
178
|
+
fill: "none",
|
|
179
|
+
stroke: "currentColor",
|
|
180
|
+
viewBox: "0 0 24 24",
|
|
181
|
+
children: /* @__PURE__ */ r.jsx(
|
|
182
|
+
"path",
|
|
183
|
+
{
|
|
184
|
+
strokeLinecap: "round",
|
|
185
|
+
strokeLinejoin: "round",
|
|
186
|
+
strokeWidth: 2,
|
|
187
|
+
d: "M6 18L18 6M6 6l12 12"
|
|
188
|
+
}
|
|
189
|
+
)
|
|
190
|
+
}
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
)
|
|
194
|
+
] }),
|
|
195
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-p-4 iw-overflow-y-auto", children: e })
|
|
196
|
+
]
|
|
197
|
+
}
|
|
198
|
+
)
|
|
199
|
+
] });
|
|
200
|
+
return pe(g, document.body);
|
|
201
|
+
}, Ee = ({
|
|
202
|
+
confirmExitInterview: i,
|
|
203
|
+
isOpen: t,
|
|
204
|
+
onClose: e
|
|
205
|
+
}) => /* @__PURE__ */ r.jsx(ve, { isOpen: t, onClose: e, title: "Exit Interview", children: /* @__PURE__ */ r.jsxs("div", { className: "iw-space-y-4", children: [
|
|
206
|
+
/* @__PURE__ */ r.jsx("p", { className: "iw-text-base iw-text-gray-700", children: "Are you sure you want to exit the interview? All progress will be lost and you will not be able to resume." }),
|
|
207
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-justify-end iw-space-x-2", children: [
|
|
208
|
+
/* @__PURE__ */ r.jsx(
|
|
209
|
+
"button",
|
|
210
|
+
{
|
|
211
|
+
className: "iw-px-4 iw-py-2 iw-bg-gray-200 iw-rounded iw-text-gray-700 iw-font-medium",
|
|
212
|
+
onClick: e,
|
|
213
|
+
children: "Cancel"
|
|
214
|
+
}
|
|
215
|
+
),
|
|
216
|
+
/* @__PURE__ */ r.jsx(
|
|
217
|
+
"button",
|
|
218
|
+
{
|
|
219
|
+
className: "iw-px-4 iw-py-2 iw-bg-red-600 iw-text-white iw-rounded iw-font-medium",
|
|
220
|
+
onClick: i,
|
|
221
|
+
children: "Confirm Exit"
|
|
222
|
+
}
|
|
223
|
+
)
|
|
224
|
+
] })
|
|
225
|
+
] }) }), je = ({ title: i, onExit: t }) => {
|
|
226
|
+
const { baseColor: e } = F(), [a, s] = y(!1);
|
|
227
|
+
return /* @__PURE__ */ r.jsxs("header", { className: "iw-w-full iw-text-gray-900", children: [
|
|
228
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-mx-auto iw-flex iw-items-center iw-justify-between iw-px-4 iw-py-3", children: [
|
|
229
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-2", children: [
|
|
230
|
+
/* @__PURE__ */ r.jsx(
|
|
231
|
+
"div",
|
|
232
|
+
{
|
|
233
|
+
className: "iw-h-7 iw-w-7 iw-rounded-md iw-flex iw-items-center iw-justify-center iw-text-white iw-font-semibold",
|
|
234
|
+
style: { backgroundColor: e },
|
|
235
|
+
children: "N"
|
|
236
|
+
}
|
|
237
|
+
),
|
|
238
|
+
/* @__PURE__ */ r.jsx("p", { className: "iw-text-sm iw-font-medium", children: "Novara" })
|
|
239
|
+
] }),
|
|
240
|
+
/* @__PURE__ */ r.jsx("h1", { className: "iw-text-base iw-font-medium", children: i }),
|
|
241
|
+
/* @__PURE__ */ r.jsx(
|
|
242
|
+
"button",
|
|
243
|
+
{
|
|
244
|
+
className: "iw-text-sm iw-text-gray-500 hover:iw-text-gray-700",
|
|
245
|
+
onClick: () => s(!0),
|
|
246
|
+
children: "Exit Interview"
|
|
247
|
+
}
|
|
248
|
+
)
|
|
249
|
+
] }),
|
|
250
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-h-px iw-bg-gray-200" }),
|
|
251
|
+
/* @__PURE__ */ r.jsx(
|
|
252
|
+
Ee,
|
|
253
|
+
{
|
|
254
|
+
isOpen: a,
|
|
255
|
+
confirmExitInterview: () => {
|
|
256
|
+
t(), s(!1);
|
|
257
|
+
},
|
|
258
|
+
onClose: () => s(!1)
|
|
259
|
+
}
|
|
260
|
+
)
|
|
261
|
+
] });
|
|
262
|
+
}, $ = ({
|
|
37
263
|
children: i,
|
|
38
|
-
variant:
|
|
39
|
-
size:
|
|
40
|
-
fullWidth:
|
|
41
|
-
isLoading:
|
|
42
|
-
disabled:
|
|
43
|
-
className:
|
|
44
|
-
...
|
|
264
|
+
variant: t = "primary",
|
|
265
|
+
size: e = "md",
|
|
266
|
+
fullWidth: a = !1,
|
|
267
|
+
isLoading: s = !1,
|
|
268
|
+
disabled: c,
|
|
269
|
+
className: n = "",
|
|
270
|
+
...o
|
|
45
271
|
}) => {
|
|
46
|
-
const
|
|
272
|
+
const m = "iw-inline-flex iw-items-center iw-justify-center iw-rounded-md iw-font-medium iw-transition-colors iw-focus:outline-none iw-focus:ring-2 iw-focus:ring-primary-500 iw-focus:ring-offset-2", g = {
|
|
47
273
|
primary: "iw-bg-primary-600 iw-text-white iw-hover:bg-primary-700 iw-border iw-border-transparent",
|
|
48
274
|
secondary: "iw-bg-primary-100 iw-text-primary-700 iw-hover:bg-primary-200 iw-border iw-border-transparent",
|
|
49
275
|
outline: "iw-bg-transparent iw-text-primary-700 iw-border iw-border-primary-500 iw-hover:bg-primary-50",
|
|
50
276
|
text: "iw-bg-transparent iw-text-primary-600 iw-hover:bg-primary-50 iw-border iw-border-transparent",
|
|
51
277
|
gradient: "iw-text-white iw-border iw-border-transparent iw-bg-gradient-to-r iw-from-purple-500 iw-to-indigo-500 hover:iw-from-purple-600 hover:iw-to-indigo-600"
|
|
52
|
-
},
|
|
278
|
+
}, d = {
|
|
53
279
|
sm: "iw-px-3 iw-py-1.5 iw-text-sm",
|
|
54
280
|
md: "iw-px-4 iw-py-2 iw-text-sm",
|
|
55
281
|
lg: "iw-px-5 iw-py-2.5 iw-text-base"
|
|
56
|
-
},
|
|
57
|
-
return /* @__PURE__ */
|
|
282
|
+
}, u = "iw-disabled:opacity-50 iw-disabled:cursor-not-allowed iw-disabled:pointer-events-none", h = a ? "iw-w-full" : "";
|
|
283
|
+
return /* @__PURE__ */ r.jsxs(
|
|
58
284
|
"button",
|
|
59
285
|
{
|
|
60
|
-
className: `${
|
|
61
|
-
disabled:
|
|
62
|
-
...
|
|
286
|
+
className: `${m} ${g[t]} ${d[e]} ${h} ${u} ${n}`,
|
|
287
|
+
disabled: c || s,
|
|
288
|
+
...o,
|
|
63
289
|
children: [
|
|
64
|
-
|
|
290
|
+
s && /* @__PURE__ */ r.jsxs(
|
|
65
291
|
"svg",
|
|
66
292
|
{
|
|
67
293
|
className: "iw-animate-spin iw-mr-2 iw-h-4 iw-w-4 iw-text-white",
|
|
@@ -69,7 +295,7 @@ const E = ({
|
|
|
69
295
|
fill: "none",
|
|
70
296
|
viewBox: "0 0 24 24",
|
|
71
297
|
children: [
|
|
72
|
-
/* @__PURE__ */
|
|
298
|
+
/* @__PURE__ */ r.jsx(
|
|
73
299
|
"circle",
|
|
74
300
|
{
|
|
75
301
|
className: "iw-opacity-25",
|
|
@@ -80,7 +306,7 @@ const E = ({
|
|
|
80
306
|
strokeWidth: "4"
|
|
81
307
|
}
|
|
82
308
|
),
|
|
83
|
-
/* @__PURE__ */
|
|
309
|
+
/* @__PURE__ */ r.jsx(
|
|
84
310
|
"path",
|
|
85
311
|
{
|
|
86
312
|
className: "iw-opacity-75",
|
|
@@ -95,165 +321,321 @@ const E = ({
|
|
|
95
321
|
]
|
|
96
322
|
}
|
|
97
323
|
);
|
|
98
|
-
},
|
|
324
|
+
}, Se = ({
|
|
99
325
|
isOpen: i,
|
|
100
|
-
onStart:
|
|
101
|
-
onClose:
|
|
326
|
+
onStart: t,
|
|
327
|
+
onClose: e
|
|
102
328
|
}) => {
|
|
103
|
-
var
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
},
|
|
107
|
-
|
|
329
|
+
var N;
|
|
330
|
+
const a = D(null), s = D(null), { baseColor: c, borderRadius: n } = F(), [o, m] = y(!1), [g, d] = y(null), [u, h] = y(!1), x = () => {
|
|
331
|
+
s.current && (s.current.getTracks().forEach((w) => w.stop()), s.current = null);
|
|
332
|
+
}, k = async () => {
|
|
333
|
+
h(!0), d(null);
|
|
108
334
|
try {
|
|
109
|
-
const
|
|
335
|
+
const w = await navigator.mediaDevices.getUserMedia({
|
|
110
336
|
video: { width: { ideal: 1280 }, height: { ideal: 720 } },
|
|
111
337
|
audio: !0
|
|
112
338
|
});
|
|
113
|
-
|
|
114
|
-
} catch (
|
|
115
|
-
console.error("Media permission error:",
|
|
116
|
-
let
|
|
117
|
-
(
|
|
339
|
+
s.current = w, a.current && (a.current.srcObject = w), m(!0);
|
|
340
|
+
} catch (w) {
|
|
341
|
+
console.error("Media permission error:", w);
|
|
342
|
+
let p = "Unable to access camera or microphone.";
|
|
343
|
+
(w == null ? void 0 : w.name) === "NotAllowedError" ? p = "Permissions denied. Please allow access to camera and microphone." : (w == null ? void 0 : w.name) === "NotFoundError" ? p = "No camera/microphone found. Please connect a device and retry." : w != null && w.message && (p = w.message), m(!1), d(p);
|
|
118
344
|
} finally {
|
|
119
|
-
|
|
345
|
+
h(!1);
|
|
120
346
|
}
|
|
121
347
|
};
|
|
122
|
-
if (
|
|
348
|
+
if (A(() => {
|
|
123
349
|
if (!i) {
|
|
124
|
-
|
|
350
|
+
x();
|
|
125
351
|
return;
|
|
126
352
|
}
|
|
127
|
-
return
|
|
128
|
-
|
|
353
|
+
return k(), () => {
|
|
354
|
+
x();
|
|
129
355
|
};
|
|
130
356
|
}, [i]), !i) return null;
|
|
131
|
-
const
|
|
132
|
-
|
|
357
|
+
const j = () => {
|
|
358
|
+
t(), x();
|
|
133
359
|
};
|
|
134
|
-
return /* @__PURE__ */
|
|
135
|
-
/* @__PURE__ */
|
|
136
|
-
/* @__PURE__ */
|
|
137
|
-
|
|
360
|
+
return /* @__PURE__ */ r.jsx("div", { className: "iw-fixed iw-inset-0 iw-z-50 iw-flex iw-items-center iw-justify-center iw-bg-black/50 iw-backdrop-blur-sm", children: /* @__PURE__ */ r.jsxs("div", { className: "iw-bg-white iw-rounded-xl iw-shadow-2xl iw-w-full iw-max-w-3xl iw-mx-4", children: [
|
|
361
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-px-5 iw-py-4 iw-border-b iw-border-gray-200 iw-flex iw-items-center iw-justify-between", children: [
|
|
362
|
+
/* @__PURE__ */ r.jsx("h2", { className: "iw-text-base iw-font-semibold", children: "Camera & Microphone Check" }),
|
|
363
|
+
e && /* @__PURE__ */ r.jsx(
|
|
138
364
|
"button",
|
|
139
365
|
{
|
|
140
366
|
"aria-label": "Close",
|
|
141
367
|
className: "iw-text-gray-500 hover:iw-text-gray-700",
|
|
142
368
|
onClick: () => {
|
|
143
|
-
|
|
369
|
+
x(), e == null || e();
|
|
144
370
|
},
|
|
145
371
|
children: "✕"
|
|
146
372
|
}
|
|
147
373
|
)
|
|
148
374
|
] }),
|
|
149
|
-
/* @__PURE__ */
|
|
150
|
-
/* @__PURE__ */
|
|
375
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-p-4 iw-grid iw-grid-cols-2 iw-gap-4", children: [
|
|
376
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-border iw-border-gray-200 iw-rounded-lg iw-overflow-hidden iw-bg-gray-900", children: /* @__PURE__ */ r.jsx(
|
|
151
377
|
"video",
|
|
152
378
|
{
|
|
153
|
-
ref:
|
|
379
|
+
ref: a,
|
|
154
380
|
autoPlay: !0,
|
|
155
381
|
playsInline: !0,
|
|
156
382
|
muted: !0,
|
|
157
383
|
className: "iw-w-full iw-h-64 iw-object-cover"
|
|
158
384
|
}
|
|
159
385
|
) }),
|
|
160
|
-
/* @__PURE__ */
|
|
161
|
-
/* @__PURE__ */
|
|
162
|
-
!((
|
|
163
|
-
|
|
164
|
-
/* @__PURE__ */
|
|
165
|
-
/* @__PURE__ */
|
|
166
|
-
|
|
386
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-flex-col iw-gap-3", children: [
|
|
387
|
+
/* @__PURE__ */ r.jsx("p", { className: "iw-text-sm iw-text-gray-700", children: "We will need access to your camera and microphone. Grant permission to preview your setup and to enable the Start Interview button." }),
|
|
388
|
+
!((N = navigator.mediaDevices) != null && N.getUserMedia) && /* @__PURE__ */ r.jsx("div", { className: "iw-text-xs iw-text-red-600", children: "Your browser does not support media devices. Please use a modern browser like Chrome, Edge, or Firefox." }),
|
|
389
|
+
g && /* @__PURE__ */ r.jsx("div", { className: "iw-text-xs iw-text-red-600", children: g }),
|
|
390
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-gap-2", children: [
|
|
391
|
+
/* @__PURE__ */ r.jsx(
|
|
392
|
+
$,
|
|
167
393
|
{
|
|
168
|
-
onClick:
|
|
169
|
-
isLoading:
|
|
394
|
+
onClick: k,
|
|
395
|
+
isLoading: u,
|
|
170
396
|
variant: "outline",
|
|
171
397
|
size: "sm",
|
|
172
|
-
|
|
398
|
+
style: {
|
|
399
|
+
borderColor: c,
|
|
400
|
+
borderRadius: n,
|
|
401
|
+
color: c
|
|
402
|
+
},
|
|
403
|
+
children: o ? "Recheck Permissions" : "Enable Camera & Mic"
|
|
173
404
|
}
|
|
174
405
|
),
|
|
175
|
-
/* @__PURE__ */
|
|
176
|
-
|
|
406
|
+
/* @__PURE__ */ r.jsx(
|
|
407
|
+
$,
|
|
177
408
|
{
|
|
178
|
-
onClick:
|
|
179
|
-
disabled: !
|
|
409
|
+
onClick: j,
|
|
410
|
+
disabled: !o,
|
|
180
411
|
size: "sm",
|
|
181
|
-
|
|
412
|
+
style: { backgroundColor: c, borderRadius: n },
|
|
413
|
+
children: "Proceed"
|
|
182
414
|
}
|
|
183
415
|
)
|
|
184
416
|
] }),
|
|
185
|
-
/* @__PURE__ */
|
|
186
|
-
/* @__PURE__ */
|
|
187
|
-
/* @__PURE__ */
|
|
417
|
+
/* @__PURE__ */ r.jsxs("ul", { className: "iw-text-xs iw-text-gray-500 iw-pt-2 iw-list-disc iw-pl-4", children: [
|
|
418
|
+
/* @__PURE__ */ r.jsx("li", { children: "Your preview is muted to avoid echo." }),
|
|
419
|
+
/* @__PURE__ */ r.jsx("li", { children: "You can change devices from your browser’s site settings." })
|
|
188
420
|
] })
|
|
189
421
|
] })
|
|
190
422
|
] })
|
|
191
423
|
] }) });
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}
|
|
213
|
-
|
|
424
|
+
};
|
|
425
|
+
var l = /* @__PURE__ */ ((i) => (i.IDLE = "idle", i.FETCHING_QUESTION = "fetching_question", i.READING_QUESTION = "reading_question", i.THINKING = "thinking", i.ANSWERING = "answering", i.TRANSCRIBING = "transcribing", i.EDITING = "editing", i.SUBMITTING = "submitting", i.COMPLETED = "completed", i))(l || {});
|
|
426
|
+
const Re = {
|
|
427
|
+
thinkingDuration: 30,
|
|
428
|
+
answeringDuration: 120,
|
|
429
|
+
editingDuration: 30,
|
|
430
|
+
totalInterviewDuration: 600,
|
|
431
|
+
minimumTimeForNextQuestion: 120
|
|
432
|
+
}, Ce = {
|
|
433
|
+
idle: {
|
|
434
|
+
next: "fetching_question"
|
|
435
|
+
/* FETCHING_QUESTION */
|
|
436
|
+
},
|
|
437
|
+
fetching_question: {
|
|
438
|
+
next: "reading_question"
|
|
439
|
+
/* READING_QUESTION */
|
|
440
|
+
},
|
|
441
|
+
reading_question: {
|
|
442
|
+
next: "thinking"
|
|
443
|
+
/* THINKING */
|
|
444
|
+
},
|
|
445
|
+
thinking: { next: "answering", duration: 30 },
|
|
446
|
+
answering: { next: "transcribing", duration: 120 },
|
|
447
|
+
transcribing: {
|
|
448
|
+
next: "editing"
|
|
449
|
+
/* EDITING */
|
|
450
|
+
},
|
|
451
|
+
editing: { next: "submitting", duration: 30 },
|
|
452
|
+
submitting: {
|
|
453
|
+
next: "completed"
|
|
454
|
+
/* COMPLETED */
|
|
455
|
+
},
|
|
456
|
+
completed: {
|
|
457
|
+
next: "completed"
|
|
458
|
+
/* COMPLETED */
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
class ke {
|
|
462
|
+
constructor(t = {}, e = {}) {
|
|
463
|
+
I(this, "config");
|
|
464
|
+
I(this, "state");
|
|
465
|
+
I(this, "phaseIntervalId", null);
|
|
466
|
+
I(this, "globalIntervalId", null);
|
|
467
|
+
I(this, "callbacks");
|
|
468
|
+
this.config = { ...Re, ...t }, this.callbacks = e, this.state = {
|
|
469
|
+
phase: "idle",
|
|
470
|
+
currentPhaseTimeRemaining: 0,
|
|
471
|
+
totalTimeRemaining: this.config.totalInterviewDuration,
|
|
472
|
+
totalTimeElapsed: 0,
|
|
473
|
+
currentQuestionNumber: 0
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Get current state
|
|
478
|
+
*/
|
|
479
|
+
getState() {
|
|
480
|
+
return { ...this.state };
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Start a new question cycle
|
|
484
|
+
*/
|
|
485
|
+
startQuestion() {
|
|
486
|
+
var t, e;
|
|
487
|
+
if (this.state.totalTimeRemaining < this.config.minimumTimeForNextQuestion) {
|
|
488
|
+
this.state.phase = "completed", this.stopGlobalTimer(), this.stopPhaseTimer(), (e = (t = this.callbacks).onInterviewEnd) == null || e.call(t), this.notifyChange();
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
this.state.currentQuestionNumber === 0 && this.startGlobalTimer(), this.state.currentQuestionNumber = this.state.currentQuestionNumber + 1, this.state.phase = "fetching_question", this.notifyChange();
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Move to next phase
|
|
495
|
+
*/
|
|
496
|
+
nextPhase() {
|
|
497
|
+
const t = this.state.phase, e = Ce[t];
|
|
498
|
+
if (!e) return;
|
|
499
|
+
this.stopPhaseTimer(), this.state.phase = e.next;
|
|
500
|
+
const a = this.getDurationForPhase(e.next);
|
|
501
|
+
a > 0 ? (this.state.currentPhaseTimeRemaining = a, this.startPhaseTimer()) : this.state.currentPhaseTimeRemaining = 0, this.notifyChange();
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Cleanup
|
|
505
|
+
*/
|
|
506
|
+
destroy() {
|
|
507
|
+
this.stopPhaseTimer(), this.stopGlobalTimer();
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Get duration for a phase
|
|
511
|
+
*/
|
|
512
|
+
getDurationForPhase(t) {
|
|
513
|
+
switch (t) {
|
|
514
|
+
case "thinking":
|
|
515
|
+
return this.config.thinkingDuration;
|
|
516
|
+
case "answering":
|
|
517
|
+
return this.config.answeringDuration;
|
|
518
|
+
case "editing":
|
|
519
|
+
return this.config.editingDuration;
|
|
520
|
+
default:
|
|
521
|
+
return 0;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* Start global timer (runs continuously during entire interview)
|
|
526
|
+
*/
|
|
527
|
+
startGlobalTimer() {
|
|
528
|
+
this.globalIntervalId = setInterval(() => {
|
|
529
|
+
var t, e, a, s;
|
|
530
|
+
this.state.totalTimeRemaining--, this.state.totalTimeElapsed++, (e = (t = this.callbacks).onTick) == null || e.call(t, this.getState()), this.state.totalTimeRemaining <= 0 && (this.stopGlobalTimer(), this.stopPhaseTimer(), this.state.phase = "completed", (s = (a = this.callbacks).onInterviewEnd) == null || s.call(a), this.notifyChange());
|
|
531
|
+
}, 1e3);
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Stop global timer
|
|
535
|
+
*/
|
|
536
|
+
stopGlobalTimer() {
|
|
537
|
+
this.globalIntervalId && (clearInterval(this.globalIntervalId), this.globalIntervalId = null);
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Start phase timer (only for timed phases)
|
|
541
|
+
*/
|
|
542
|
+
startPhaseTimer() {
|
|
543
|
+
this.phaseIntervalId = setInterval(() => {
|
|
544
|
+
this.state.currentPhaseTimeRemaining--, this.state.currentPhaseTimeRemaining <= 0 && this.nextPhase();
|
|
545
|
+
}, 1e3);
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Stop phase timer
|
|
549
|
+
*/
|
|
550
|
+
stopPhaseTimer() {
|
|
551
|
+
this.phaseIntervalId && (clearInterval(this.phaseIntervalId), this.phaseIntervalId = null);
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Notify phase change
|
|
555
|
+
*/
|
|
556
|
+
notifyChange() {
|
|
557
|
+
var t, e;
|
|
558
|
+
(e = (t = this.callbacks).onPhaseChange) == null || e.call(t, this.state.phase, this.getState());
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
function De(i = {}) {
|
|
562
|
+
const { config: t = {}, callbacks: e = {} } = i, a = D(null);
|
|
563
|
+
a.current || (a.current = new ke(t, {}));
|
|
564
|
+
const s = a.current, [c, n] = y(s.getState()), o = v(() => {
|
|
565
|
+
n(s.getState());
|
|
566
|
+
}, [s]);
|
|
567
|
+
A(() => {
|
|
568
|
+
const d = {
|
|
569
|
+
onPhaseChange: (u, h) => {
|
|
570
|
+
var x;
|
|
571
|
+
o(), (x = e.onPhaseChange) == null || x.call(e, u, h);
|
|
572
|
+
},
|
|
573
|
+
onTick: (u) => {
|
|
574
|
+
var h;
|
|
575
|
+
o(), (h = e.onTick) == null || h.call(e, u);
|
|
576
|
+
},
|
|
577
|
+
onInterviewEnd: () => {
|
|
578
|
+
var u;
|
|
579
|
+
o(), (u = e.onInterviewEnd) == null || u.call(e);
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
s.callbacks = d;
|
|
583
|
+
}, [s, e, o]), A(() => () => {
|
|
584
|
+
s.destroy();
|
|
585
|
+
}, [s]);
|
|
586
|
+
const m = v(() => {
|
|
587
|
+
s.startQuestion(), o();
|
|
588
|
+
}, [s, o]), g = v(() => {
|
|
589
|
+
s.nextPhase(), o();
|
|
590
|
+
}, [s, o]);
|
|
591
|
+
return {
|
|
592
|
+
state: c,
|
|
593
|
+
startQuestion: m,
|
|
594
|
+
nextPhase: g,
|
|
595
|
+
timerService: s
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
function Pe(i, t = {}) {
|
|
599
|
+
const [e, a] = y({
|
|
214
600
|
data: null,
|
|
215
601
|
loading: !1,
|
|
216
602
|
error: null
|
|
217
|
-
}),
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
603
|
+
}), s = v(
|
|
604
|
+
async (...c) => {
|
|
605
|
+
var n, o, m, g;
|
|
606
|
+
a((d) => ({ ...d, loading: !0, error: null }));
|
|
221
607
|
try {
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
...
|
|
225
|
-
data:
|
|
608
|
+
const d = await i(...c);
|
|
609
|
+
a((u) => ({
|
|
610
|
+
...u,
|
|
611
|
+
data: d,
|
|
226
612
|
loading: !1,
|
|
227
613
|
error: null
|
|
228
|
-
})), (
|
|
229
|
-
} catch (
|
|
230
|
-
const
|
|
614
|
+
})), (n = t.onSuccess) == null || n.call(t, d), (o = t.onSettled) == null || o.call(t, d, null);
|
|
615
|
+
} catch (d) {
|
|
616
|
+
const u = d.type ? d : {
|
|
231
617
|
type: "unknown",
|
|
232
|
-
message:
|
|
618
|
+
message: d.message || "Unknown error",
|
|
233
619
|
retryable: !0,
|
|
234
620
|
userMessage: "Something went wrong. Please try again.",
|
|
235
|
-
originalError:
|
|
621
|
+
originalError: d
|
|
236
622
|
};
|
|
237
|
-
|
|
238
|
-
...
|
|
623
|
+
a((h) => ({
|
|
624
|
+
...h,
|
|
239
625
|
loading: !1,
|
|
240
|
-
error:
|
|
241
|
-
})), (
|
|
626
|
+
error: u
|
|
627
|
+
})), (m = t.onError) == null || m.call(t, u), (g = t.onSettled) == null || g.call(t, null, u);
|
|
242
628
|
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}, [e.immediate, e.enabled]), {
|
|
250
|
-
...s,
|
|
251
|
-
execute: r,
|
|
252
|
-
retry: a
|
|
629
|
+
},
|
|
630
|
+
[i, t]
|
|
631
|
+
);
|
|
632
|
+
return {
|
|
633
|
+
...e,
|
|
634
|
+
execute: s
|
|
253
635
|
};
|
|
254
636
|
}
|
|
255
|
-
function
|
|
256
|
-
var
|
|
637
|
+
function Ae(i) {
|
|
638
|
+
var t;
|
|
257
639
|
if (!navigator.onLine)
|
|
258
640
|
return {
|
|
259
641
|
type: "network",
|
|
@@ -261,7 +643,7 @@ function _(i) {
|
|
|
261
643
|
retryable: !0,
|
|
262
644
|
userMessage: "Please check your internet connection and try again."
|
|
263
645
|
};
|
|
264
|
-
if (i.name === "AbortError" || (
|
|
646
|
+
if (i.name === "AbortError" || (t = i.message) != null && t.includes("timeout"))
|
|
265
647
|
return {
|
|
266
648
|
type: "timeout",
|
|
267
649
|
message: "Request timed out",
|
|
@@ -269,36 +651,36 @@ function _(i) {
|
|
|
269
651
|
userMessage: "The request is taking longer than expected. Please try again."
|
|
270
652
|
};
|
|
271
653
|
if (i.status) {
|
|
272
|
-
const { status:
|
|
273
|
-
if (
|
|
654
|
+
const { status: e } = i;
|
|
655
|
+
if (e === 401 || e === 403)
|
|
274
656
|
return {
|
|
275
657
|
type: "auth",
|
|
276
|
-
status:
|
|
658
|
+
status: e,
|
|
277
659
|
message: "Authentication failed",
|
|
278
660
|
retryable: !1,
|
|
279
661
|
userMessage: "Your session has expired. Please refresh the page."
|
|
280
662
|
};
|
|
281
|
-
if (
|
|
663
|
+
if (e === 429)
|
|
282
664
|
return {
|
|
283
665
|
type: "rate-limit",
|
|
284
|
-
status:
|
|
666
|
+
status: e,
|
|
285
667
|
message: "Too many requests",
|
|
286
668
|
retryable: !0,
|
|
287
669
|
userMessage: "Please wait a moment before trying again."
|
|
288
670
|
};
|
|
289
|
-
if (
|
|
671
|
+
if (e >= 500)
|
|
290
672
|
return {
|
|
291
673
|
type: "server",
|
|
292
|
-
status:
|
|
293
|
-
message: `Server error: ${
|
|
674
|
+
status: e,
|
|
675
|
+
message: `Server error: ${e}`,
|
|
294
676
|
retryable: !0,
|
|
295
677
|
userMessage: "Our servers are experiencing issues. Please try again in a few moments."
|
|
296
678
|
};
|
|
297
|
-
if (
|
|
679
|
+
if (e >= 400)
|
|
298
680
|
return {
|
|
299
681
|
type: "client",
|
|
300
|
-
status:
|
|
301
|
-
message: `Client error: ${
|
|
682
|
+
status: e,
|
|
683
|
+
message: `Client error: ${e}`,
|
|
302
684
|
retryable: !1,
|
|
303
685
|
userMessage: "There was an issue with your request. Please check your input."
|
|
304
686
|
};
|
|
@@ -311,329 +693,798 @@ function _(i) {
|
|
|
311
693
|
originalError: i
|
|
312
694
|
};
|
|
313
695
|
}
|
|
314
|
-
async function
|
|
696
|
+
async function H(i, t = {}, e = {
|
|
315
697
|
attempts: 3,
|
|
316
698
|
backoff: "exponential",
|
|
317
699
|
baseDelay: 1e3,
|
|
318
700
|
maxDelay: 1e4,
|
|
319
701
|
jitter: !0
|
|
320
702
|
}) {
|
|
321
|
-
let
|
|
322
|
-
for (let
|
|
703
|
+
let a;
|
|
704
|
+
for (let s = 1; s <= e.attempts; s++)
|
|
323
705
|
try {
|
|
324
|
-
const
|
|
325
|
-
...
|
|
326
|
-
signal:
|
|
706
|
+
const c = new AbortController(), n = setTimeout(() => c.abort(), 6e4), o = await fetch(i, {
|
|
707
|
+
...t,
|
|
708
|
+
signal: c.signal
|
|
327
709
|
});
|
|
328
|
-
if (clearTimeout(
|
|
329
|
-
return
|
|
330
|
-
if (!
|
|
331
|
-
throw new Error(`HTTP ${
|
|
332
|
-
return
|
|
333
|
-
} catch (
|
|
334
|
-
|
|
335
|
-
const
|
|
336
|
-
if (!
|
|
337
|
-
throw
|
|
338
|
-
const
|
|
710
|
+
if (clearTimeout(n), o.status >= 400 && o.status < 500 && o.status !== 429)
|
|
711
|
+
return o;
|
|
712
|
+
if (!o.ok)
|
|
713
|
+
throw new Error(`HTTP ${o.status}: ${o.statusText}`);
|
|
714
|
+
return o;
|
|
715
|
+
} catch (c) {
|
|
716
|
+
a = c;
|
|
717
|
+
const n = Ae(c);
|
|
718
|
+
if (!n.retryable || s === e.attempts)
|
|
719
|
+
throw n;
|
|
720
|
+
const o = Ge(s, e);
|
|
339
721
|
console.warn(
|
|
340
|
-
`API request failed (attempt ${
|
|
341
|
-
|
|
342
|
-
), await new Promise((
|
|
722
|
+
`API request failed (attempt ${s}/${e.attempts}), retrying in ${o}ms:`,
|
|
723
|
+
n.message
|
|
724
|
+
), await new Promise((m) => setTimeout(m, o));
|
|
343
725
|
}
|
|
344
|
-
throw
|
|
726
|
+
throw a;
|
|
345
727
|
}
|
|
346
|
-
function
|
|
347
|
-
let
|
|
348
|
-
return
|
|
728
|
+
function Ge(i, t) {
|
|
729
|
+
let e;
|
|
730
|
+
return t.backoff === "exponential" ? e = t.baseDelay * Math.pow(2, i - 1) : e = t.baseDelay, e = Math.min(e, t.maxDelay), t.jitter && (e = e * (0.5 + Math.random() * 0.5)), Math.round(e);
|
|
349
731
|
}
|
|
350
|
-
class
|
|
351
|
-
constructor(
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
this.baseURL = e, this.authToken = s;
|
|
732
|
+
class Me {
|
|
733
|
+
constructor(t = {}) {
|
|
734
|
+
I(this, "config");
|
|
735
|
+
this.config = t;
|
|
355
736
|
}
|
|
356
737
|
/**
|
|
357
|
-
*
|
|
738
|
+
* Update configuration
|
|
358
739
|
*/
|
|
359
|
-
|
|
360
|
-
this.
|
|
740
|
+
updateConfig(t) {
|
|
741
|
+
this.config = { ...this.config, ...t };
|
|
361
742
|
}
|
|
362
743
|
/**
|
|
363
744
|
* Get default headers for API requests
|
|
364
745
|
*/
|
|
365
746
|
getHeaders() {
|
|
366
|
-
|
|
367
|
-
|
|
747
|
+
var e;
|
|
748
|
+
const t = {
|
|
749
|
+
"Content-Type": "application/json",
|
|
750
|
+
"X-Auth-Token": "appkey"
|
|
368
751
|
};
|
|
369
|
-
return this.authToken && (
|
|
752
|
+
return (e = this.config) != null && e.authToken && (t.Authorization = `Bearer ${this.config.authToken}`), t;
|
|
370
753
|
}
|
|
371
754
|
/**
|
|
372
|
-
*
|
|
755
|
+
* Get base URL from config with fallback
|
|
373
756
|
*/
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
headers: this.getHeaders(),
|
|
378
|
-
body: JSON.stringify({ candidateId: e })
|
|
379
|
-
});
|
|
380
|
-
if (!s.ok)
|
|
381
|
-
throw new Error(`Failed to start interview: ${s.status}`);
|
|
382
|
-
return s.json();
|
|
757
|
+
getBaseUrl() {
|
|
758
|
+
var t;
|
|
759
|
+
return ((t = this.config) == null ? void 0 : t.baseUrl) || "/api";
|
|
383
760
|
}
|
|
384
761
|
/**
|
|
385
762
|
* Get questions for an interview
|
|
386
763
|
*/
|
|
387
|
-
async
|
|
388
|
-
|
|
389
|
-
|
|
764
|
+
async generateQuestion({
|
|
765
|
+
interviewId: t,
|
|
766
|
+
isInterviewDone: e = !1,
|
|
767
|
+
qnaId: a,
|
|
768
|
+
question: s,
|
|
769
|
+
answer: c,
|
|
770
|
+
answerDuration: n
|
|
771
|
+
}) {
|
|
772
|
+
const o = await H(
|
|
773
|
+
`${this.getBaseUrl()}/interview/generate-question`,
|
|
390
774
|
{
|
|
391
|
-
method: "
|
|
392
|
-
headers: this.getHeaders()
|
|
775
|
+
method: "POST",
|
|
776
|
+
headers: this.getHeaders(),
|
|
777
|
+
body: JSON.stringify({
|
|
778
|
+
interview_id: t,
|
|
779
|
+
is_interview_done: e,
|
|
780
|
+
qna_id: a,
|
|
781
|
+
question: s,
|
|
782
|
+
answer: c,
|
|
783
|
+
// TODO: Hardcoded for now, will be dynamic later
|
|
784
|
+
answer_duration: n ?? "00:00:30"
|
|
785
|
+
})
|
|
393
786
|
}
|
|
394
787
|
);
|
|
395
|
-
if (!
|
|
396
|
-
throw new Error(`Failed to get questions: ${
|
|
397
|
-
|
|
398
|
-
|
|
788
|
+
if (!o.ok)
|
|
789
|
+
throw new Error(`Failed to get questions: ${o.status}`);
|
|
790
|
+
return await o.json();
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
function Oe() {
|
|
794
|
+
const i = q();
|
|
795
|
+
return xe(() => {
|
|
796
|
+
const e = i.api || {};
|
|
797
|
+
return new Me(e);
|
|
798
|
+
}, [i.api]);
|
|
799
|
+
}
|
|
800
|
+
class b extends Error {
|
|
801
|
+
constructor(t, e, a = !1) {
|
|
802
|
+
super(t), this.code = e, this.recoverable = a, this.name = "STTError";
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
class $e {
|
|
806
|
+
constructor(t = {}) {
|
|
807
|
+
I(this, "config");
|
|
808
|
+
I(this, "mediaRecorder", null);
|
|
809
|
+
I(this, "audioChunks", []);
|
|
810
|
+
I(this, "recordingStream", null);
|
|
811
|
+
I(this, "autoStopTimeoutId", null);
|
|
812
|
+
this.config = {
|
|
813
|
+
baseUrl: "http://localhost:8000",
|
|
814
|
+
provider: "groq",
|
|
815
|
+
model: "whisper-large-v3-turbo",
|
|
816
|
+
language: "en",
|
|
817
|
+
includeTimestamps: !1,
|
|
818
|
+
temperature: 0,
|
|
819
|
+
...t
|
|
820
|
+
};
|
|
399
821
|
}
|
|
400
822
|
/**
|
|
401
|
-
*
|
|
823
|
+
* Update STT configuration
|
|
402
824
|
*/
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
method: "POST",
|
|
406
|
-
headers: this.getHeaders(),
|
|
407
|
-
body: JSON.stringify(e)
|
|
408
|
-
});
|
|
409
|
-
if (!s.ok)
|
|
410
|
-
throw new Error(`Failed to submit answer: ${s.status}`);
|
|
825
|
+
updateConfig(t) {
|
|
826
|
+
this.config = { ...this.config, ...t };
|
|
411
827
|
}
|
|
412
828
|
/**
|
|
413
|
-
*
|
|
829
|
+
* Check if browser supports audio recording
|
|
414
830
|
*/
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
831
|
+
isRecordingSupported() {
|
|
832
|
+
return !!(navigator.mediaDevices && typeof navigator.mediaDevices.getUserMedia == "function" && window.MediaRecorder);
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* Start recording audio from user's microphone
|
|
836
|
+
*/
|
|
837
|
+
async startRecording(t, e) {
|
|
838
|
+
var a;
|
|
839
|
+
if (!this.isRecordingSupported())
|
|
840
|
+
throw new b(
|
|
841
|
+
"Audio recording is not supported in this browser",
|
|
842
|
+
"RECORDING_NOT_SUPPORTED",
|
|
843
|
+
!1
|
|
844
|
+
);
|
|
845
|
+
if (this.isRecording())
|
|
846
|
+
throw new b(
|
|
847
|
+
"Recording is already in progress",
|
|
848
|
+
"ALREADY_RECORDING",
|
|
849
|
+
!0
|
|
850
|
+
);
|
|
851
|
+
try {
|
|
852
|
+
this.recordingStream = await navigator.mediaDevices.getUserMedia({
|
|
853
|
+
audio: {
|
|
854
|
+
echoCancellation: !0,
|
|
855
|
+
noiseSuppression: !0,
|
|
856
|
+
sampleRate: 44100
|
|
857
|
+
}
|
|
858
|
+
}), this.audioChunks = [];
|
|
859
|
+
const s = this.getSupportedMimeType();
|
|
860
|
+
this.mediaRecorder = new MediaRecorder(this.recordingStream, {
|
|
861
|
+
mimeType: s
|
|
862
|
+
}), this.mediaRecorder.ondataavailable = (c) => {
|
|
863
|
+
var n;
|
|
864
|
+
c.data.size > 0 && (this.audioChunks.push(c.data), (n = e == null ? void 0 : e.onDataAvailable) == null || n.call(e, c.data));
|
|
865
|
+
}, this.mediaRecorder.onstop = () => {
|
|
866
|
+
var c;
|
|
867
|
+
(c = e == null ? void 0 : e.onStop) == null || c.call(e);
|
|
868
|
+
}, this.mediaRecorder.onerror = (c) => {
|
|
869
|
+
var o;
|
|
870
|
+
const n = new b(
|
|
871
|
+
`Recording failed: ${c.error}`,
|
|
872
|
+
"RECORDING_ERROR",
|
|
873
|
+
!0
|
|
874
|
+
);
|
|
875
|
+
(o = e == null ? void 0 : e.onError) == null || o.call(e, n), this.cleanup();
|
|
876
|
+
}, this.mediaRecorder.start(100), (a = e == null ? void 0 : e.onStart) == null || a.call(e), t && t > 0 && (this.autoStopTimeoutId = setTimeout(() => {
|
|
877
|
+
this.isRecording() && this.stopRecording();
|
|
878
|
+
}, t * 1e3));
|
|
879
|
+
} catch (s) {
|
|
880
|
+
if (this.cleanup(), s instanceof Error) {
|
|
881
|
+
if (s.name === "NotAllowedError" || s.name === "PermissionDeniedError")
|
|
882
|
+
throw new b(
|
|
883
|
+
"Microphone permission was denied",
|
|
884
|
+
"PERMISSION_DENIED",
|
|
885
|
+
!1
|
|
886
|
+
);
|
|
887
|
+
if (s.name === "NotFoundError")
|
|
888
|
+
throw new b("No microphone found", "NO_MICROPHONE", !1);
|
|
421
889
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
890
|
+
throw new b(
|
|
891
|
+
`Failed to start recording: ${s instanceof Error ? s.message : String(s)}`,
|
|
892
|
+
"START_RECORDING_FAILED",
|
|
893
|
+
!0
|
|
894
|
+
);
|
|
895
|
+
}
|
|
426
896
|
}
|
|
427
897
|
/**
|
|
428
|
-
*
|
|
898
|
+
* Stop recording and return the audio blob
|
|
429
899
|
*/
|
|
430
|
-
async
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
900
|
+
async stopRecording() {
|
|
901
|
+
if (this.autoStopTimeoutId && (clearTimeout(this.autoStopTimeoutId), this.autoStopTimeoutId = null), !this.mediaRecorder || !this.isRecording())
|
|
902
|
+
throw new b(
|
|
903
|
+
"No active recording to stop",
|
|
904
|
+
"NO_ACTIVE_RECORDING",
|
|
905
|
+
!1
|
|
906
|
+
);
|
|
907
|
+
return new Promise((t, e) => {
|
|
908
|
+
if (!this.mediaRecorder) {
|
|
909
|
+
e(
|
|
910
|
+
new b("MediaRecorder is null", "MEDIARECORDER_NULL", !1)
|
|
911
|
+
);
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
const a = this.mediaRecorder, s = () => {
|
|
915
|
+
try {
|
|
916
|
+
const c = a.mimeType || "audio/webm", n = new Blob(this.audioChunks, { type: c });
|
|
917
|
+
this.cleanup(), t(n);
|
|
918
|
+
} catch (c) {
|
|
919
|
+
e(
|
|
920
|
+
new b(
|
|
921
|
+
`Failed to create audio blob: ${c instanceof Error ? c.message : String(c)}`,
|
|
922
|
+
"BLOB_CREATION_FAILED",
|
|
923
|
+
!1
|
|
924
|
+
)
|
|
925
|
+
);
|
|
926
|
+
}
|
|
927
|
+
};
|
|
928
|
+
a.addEventListener("stop", s, { once: !0 }), a.stop();
|
|
434
929
|
});
|
|
435
|
-
if (!e.ok)
|
|
436
|
-
throw new Error(`Failed to get stats: ${e.status}`);
|
|
437
|
-
return e.json();
|
|
438
930
|
}
|
|
439
931
|
/**
|
|
440
|
-
*
|
|
932
|
+
* Transcribe audio blob using the STT API
|
|
441
933
|
*/
|
|
442
|
-
async
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
934
|
+
async transcribe(t) {
|
|
935
|
+
const {
|
|
936
|
+
audioBlob: e,
|
|
937
|
+
model: a = this.config.model,
|
|
938
|
+
language: s = this.config.language,
|
|
939
|
+
includeTimestamps: c = this.config.includeTimestamps,
|
|
940
|
+
temperature: n = this.config.temperature
|
|
941
|
+
} = t;
|
|
942
|
+
if (!e || e.size === 0)
|
|
943
|
+
throw new b(
|
|
944
|
+
"Audio blob is empty or invalid",
|
|
945
|
+
"INVALID_AUDIO",
|
|
946
|
+
!1
|
|
947
|
+
);
|
|
948
|
+
try {
|
|
949
|
+
const o = new FormData(), m = new File([e], "recording.wav", {
|
|
950
|
+
type: e.type || "audio/wav"
|
|
951
|
+
});
|
|
952
|
+
o.append("file", m), o.append("model", a || "whisper-large-v3-turbo"), o.append("language", s || "en"), o.append("include_timestamps", String(c || !1)), o.append("temperature", String(n || 0));
|
|
953
|
+
const g = await H(
|
|
954
|
+
`${this.config.baseUrl}/speech/transcribe`,
|
|
955
|
+
{
|
|
956
|
+
method: "POST",
|
|
957
|
+
headers: {
|
|
958
|
+
accept: "application/json",
|
|
959
|
+
"X-STT-Provider": this.config.provider || "groq"
|
|
960
|
+
},
|
|
961
|
+
body: o
|
|
962
|
+
},
|
|
963
|
+
{
|
|
964
|
+
attempts: 1,
|
|
965
|
+
backoff: "exponential",
|
|
966
|
+
baseDelay: 1e3,
|
|
967
|
+
maxDelay: 3e3,
|
|
968
|
+
jitter: !0
|
|
969
|
+
}
|
|
970
|
+
);
|
|
971
|
+
if (!g.ok) {
|
|
972
|
+
const u = await g.text();
|
|
973
|
+
let h = `STT request failed: ${g.status} ${g.statusText}`;
|
|
974
|
+
try {
|
|
975
|
+
const x = JSON.parse(u);
|
|
976
|
+
h = x.message || x.error || h;
|
|
977
|
+
} catch {
|
|
978
|
+
h = u || h;
|
|
979
|
+
}
|
|
980
|
+
throw new b(
|
|
981
|
+
h,
|
|
982
|
+
`HTTP_${g.status}`,
|
|
983
|
+
g.status >= 500
|
|
984
|
+
);
|
|
448
985
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
986
|
+
return {
|
|
987
|
+
transcript: (await g.json()).data.text ?? ""
|
|
988
|
+
};
|
|
989
|
+
} catch (o) {
|
|
990
|
+
throw o instanceof b ? o : new b(
|
|
991
|
+
`Transcription failed: ${o instanceof Error ? o.message : String(o)}`,
|
|
992
|
+
"TRANSCRIPTION_FAILED",
|
|
993
|
+
!0
|
|
994
|
+
);
|
|
995
|
+
}
|
|
453
996
|
}
|
|
454
997
|
/**
|
|
455
|
-
*
|
|
456
|
-
* Fake API example
|
|
457
|
-
* This API endpoint retrieves a list of products from the fake store API.
|
|
998
|
+
* Cancel current recording without processing
|
|
458
999
|
*/
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
return
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
1000
|
+
cancelRecording() {
|
|
1001
|
+
this.autoStopTimeoutId && (clearTimeout(this.autoStopTimeoutId), this.autoStopTimeoutId = null), this.mediaRecorder && this.isRecording() && this.mediaRecorder.stop(), this.cleanup();
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Check if currently recording
|
|
1005
|
+
*/
|
|
1006
|
+
isRecording() {
|
|
1007
|
+
return this.mediaRecorder !== null && this.mediaRecorder.state === "recording";
|
|
1008
|
+
}
|
|
1009
|
+
/**
|
|
1010
|
+
* Get supported MIME type for recording
|
|
1011
|
+
*/
|
|
1012
|
+
getSupportedMimeType() {
|
|
1013
|
+
const t = [
|
|
1014
|
+
"audio/webm",
|
|
1015
|
+
"audio/webm;codecs=opus",
|
|
1016
|
+
"audio/ogg;codecs=opus",
|
|
1017
|
+
"audio/mp4",
|
|
1018
|
+
"audio/wav"
|
|
1019
|
+
];
|
|
1020
|
+
for (const e of t)
|
|
1021
|
+
if (MediaRecorder.isTypeSupported(e))
|
|
1022
|
+
return e;
|
|
1023
|
+
return "audio/webm";
|
|
1024
|
+
}
|
|
1025
|
+
/**
|
|
1026
|
+
* Clean up recording resources
|
|
1027
|
+
*/
|
|
1028
|
+
cleanup() {
|
|
1029
|
+
this.recordingStream && (this.recordingStream.getTracks().forEach((t) => t.stop()), this.recordingStream = null), this.mediaRecorder = null, this.audioChunks = [], this.autoStopTimeoutId && (clearTimeout(this.autoStopTimeoutId), this.autoStopTimeoutId = null);
|
|
479
1030
|
}
|
|
480
1031
|
}
|
|
481
|
-
const
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
1032
|
+
const O = new $e(), _e = (i = {}) => {
|
|
1033
|
+
const [t, e] = y(!1), [a, s] = y(!1), [c, n] = y(null), [o, m] = y(null), [g, d] = y(null);
|
|
1034
|
+
i.config && O.updateConfig(i.config);
|
|
1035
|
+
const u = v(async (j) => {
|
|
1036
|
+
var N;
|
|
1037
|
+
try {
|
|
1038
|
+
m(null), n(null), d(null), await O.startRecording(j, {
|
|
1039
|
+
onStart: () => {
|
|
1040
|
+
var w;
|
|
1041
|
+
e(!0), (w = i.onStart) == null || w.call(i);
|
|
1042
|
+
},
|
|
1043
|
+
onStop: () => {
|
|
1044
|
+
var w;
|
|
1045
|
+
e(!1), (w = i.onStop) == null || w.call(i);
|
|
1046
|
+
},
|
|
1047
|
+
onError: (w) => {
|
|
1048
|
+
var T;
|
|
1049
|
+
const p = w instanceof b ? w : new b(w.message, "RECORDING_ERROR", !0);
|
|
1050
|
+
m(p), e(!1), (T = i.onError) == null || T.call(i, p);
|
|
1051
|
+
}
|
|
1052
|
+
});
|
|
1053
|
+
} catch (w) {
|
|
1054
|
+
const p = w instanceof b ? w : new b(
|
|
1055
|
+
w instanceof Error ? w.message : String(w),
|
|
1056
|
+
"START_FAILED",
|
|
1057
|
+
!1
|
|
1058
|
+
);
|
|
1059
|
+
throw m(p), e(!1), (N = i.onError) == null || N.call(i, p), p;
|
|
1060
|
+
}
|
|
1061
|
+
}, []), h = v(async () => {
|
|
1062
|
+
var j, N;
|
|
1063
|
+
try {
|
|
1064
|
+
const w = await O.stopRecording();
|
|
1065
|
+
return d(w), e(!1), (j = i.onStop) == null || j.call(i), w;
|
|
1066
|
+
} catch (w) {
|
|
1067
|
+
const p = w instanceof b ? w : new b(
|
|
1068
|
+
w instanceof Error ? w.message : String(w),
|
|
1069
|
+
"STOP_FAILED",
|
|
1070
|
+
!1
|
|
1071
|
+
);
|
|
1072
|
+
throw m(p), e(!1), (N = i.onError) == null || N.call(i, p), p;
|
|
1073
|
+
}
|
|
1074
|
+
}, []), x = v(
|
|
1075
|
+
async (j, N = {}) => {
|
|
1076
|
+
var w, p;
|
|
1077
|
+
try {
|
|
1078
|
+
m(null), s(!0);
|
|
1079
|
+
const T = {
|
|
1080
|
+
audioBlob: j,
|
|
1081
|
+
...N
|
|
1082
|
+
}, S = await O.transcribe(T);
|
|
1083
|
+
return n(S.transcript), s(!1), (w = i.onTranscriptionComplete) == null || w.call(i, S), S;
|
|
1084
|
+
} catch (T) {
|
|
1085
|
+
const S = T instanceof b ? T : new b(
|
|
1086
|
+
T instanceof Error ? T.message : String(T),
|
|
1087
|
+
"TRANSCRIPTION_FAILED",
|
|
1088
|
+
!0
|
|
1089
|
+
);
|
|
1090
|
+
throw m(S), s(!1), (p = i.onError) == null || p.call(i, S), S;
|
|
1091
|
+
}
|
|
491
1092
|
},
|
|
492
|
-
|
|
493
|
-
|
|
1093
|
+
[]
|
|
1094
|
+
), k = v(() => {
|
|
1095
|
+
O.cancelRecording(), e(!1), d(null);
|
|
1096
|
+
}, []);
|
|
1097
|
+
return {
|
|
1098
|
+
startRecording: u,
|
|
1099
|
+
stopRecording: h,
|
|
1100
|
+
transcribe: x,
|
|
1101
|
+
cancelRecording: k,
|
|
1102
|
+
isRecording: t,
|
|
1103
|
+
isTranscribing: a,
|
|
1104
|
+
transcript: c,
|
|
1105
|
+
error: o,
|
|
1106
|
+
audioBlob: g
|
|
1107
|
+
};
|
|
1108
|
+
};
|
|
1109
|
+
class Le {
|
|
1110
|
+
constructor(t = {}) {
|
|
1111
|
+
I(this, "config");
|
|
1112
|
+
I(this, "currentAudio", null);
|
|
1113
|
+
this.config = {
|
|
1114
|
+
baseUrl: "http://localhost:8000",
|
|
1115
|
+
provider: "piper",
|
|
1116
|
+
voice: "string",
|
|
1117
|
+
speed: 1,
|
|
1118
|
+
...t
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
/**
|
|
1122
|
+
* Update TTS configuration
|
|
1123
|
+
*/
|
|
1124
|
+
updateConfig(t) {
|
|
1125
|
+
this.config = { ...this.config, ...t };
|
|
1126
|
+
}
|
|
1127
|
+
/**
|
|
1128
|
+
* Get TTS audio from the API and return as blob
|
|
1129
|
+
*/
|
|
1130
|
+
async synthesizeSpeech(t) {
|
|
1131
|
+
const {
|
|
1132
|
+
text: e,
|
|
1133
|
+
voice: a = this.config.voice,
|
|
1134
|
+
speed: s = this.config.speed
|
|
1135
|
+
} = t, c = new URLSearchParams();
|
|
1136
|
+
c.append("text", e), c.append("voice", a || "string"), c.append("speed", (s == null ? void 0 : s.toString()) || "1");
|
|
1137
|
+
const n = await H(
|
|
1138
|
+
`${this.config.baseUrl}/speech/synthesize`,
|
|
1139
|
+
{
|
|
1140
|
+
method: "POST",
|
|
1141
|
+
headers: {
|
|
1142
|
+
accept: "application/json",
|
|
1143
|
+
"X-TTS-Provider": this.config.provider || "piper",
|
|
1144
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
1145
|
+
},
|
|
1146
|
+
body: c
|
|
1147
|
+
},
|
|
1148
|
+
{
|
|
1149
|
+
attempts: 1,
|
|
1150
|
+
backoff: "fixed",
|
|
1151
|
+
baseDelay: 1e3,
|
|
1152
|
+
maxDelay: 1e3,
|
|
1153
|
+
jitter: !1
|
|
1154
|
+
}
|
|
1155
|
+
);
|
|
1156
|
+
if (!n.ok)
|
|
1157
|
+
throw new Error(
|
|
1158
|
+
`TTS request failed: ${n.status} ${n.statusText}`
|
|
1159
|
+
);
|
|
1160
|
+
const o = n.headers.get("content-type");
|
|
1161
|
+
if (o && o.includes("audio/"))
|
|
1162
|
+
return n.blob();
|
|
1163
|
+
try {
|
|
1164
|
+
const m = await n.json();
|
|
1165
|
+
throw new Error(`TTS Error: ${JSON.stringify(m)}`);
|
|
1166
|
+
} catch {
|
|
1167
|
+
throw new Error("TTS request failed with unknown error");
|
|
494
1168
|
}
|
|
495
|
-
}
|
|
1169
|
+
}
|
|
1170
|
+
/**
|
|
1171
|
+
* Speak text and return a promise that resolves when playback completes
|
|
1172
|
+
*/
|
|
1173
|
+
async speak(t, e) {
|
|
1174
|
+
var a, s;
|
|
496
1175
|
try {
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
1176
|
+
this.stop(), (a = e == null ? void 0 : e.onStart) == null || a.call(e);
|
|
1177
|
+
const c = await this.synthesizeSpeech(t), n = URL.createObjectURL(c);
|
|
1178
|
+
return this.currentAudio = new Audio(n), new Promise((o, m) => {
|
|
1179
|
+
if (!this.currentAudio) {
|
|
1180
|
+
m(new Error("Audio element not created"));
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1183
|
+
const g = this.currentAudio;
|
|
1184
|
+
g.onended = () => {
|
|
1185
|
+
var d;
|
|
1186
|
+
URL.revokeObjectURL(n), this.currentAudio = null, (d = e == null ? void 0 : e.onEnd) == null || d.call(e), o();
|
|
1187
|
+
}, g.onerror = (d) => {
|
|
1188
|
+
var h;
|
|
1189
|
+
URL.revokeObjectURL(n), this.currentAudio = null;
|
|
1190
|
+
const u = new Error(`Audio playback failed: ${d}`);
|
|
1191
|
+
(h = e == null ? void 0 : e.onError) == null || h.call(e, u), m(u);
|
|
1192
|
+
}, g.play().catch((d) => {
|
|
1193
|
+
var h;
|
|
1194
|
+
URL.revokeObjectURL(n), this.currentAudio = null;
|
|
1195
|
+
const u = new Error(`Failed to play audio: ${d.message}`);
|
|
1196
|
+
(h = e == null ? void 0 : e.onError) == null || h.call(e, u), m(u);
|
|
1197
|
+
});
|
|
1198
|
+
});
|
|
1199
|
+
} catch (c) {
|
|
1200
|
+
const n = c instanceof Error ? c : new Error(`TTS Error: ${String(c)}`);
|
|
1201
|
+
throw (s = e == null ? void 0 : e.onError) == null || s.call(e, n), n;
|
|
500
1202
|
}
|
|
1203
|
+
}
|
|
1204
|
+
/**
|
|
1205
|
+
* Stop current audio playback
|
|
1206
|
+
*/
|
|
1207
|
+
stop() {
|
|
1208
|
+
this.currentAudio && (this.currentAudio.pause(), this.currentAudio.currentTime = 0, this.currentAudio = null);
|
|
1209
|
+
}
|
|
1210
|
+
/**
|
|
1211
|
+
* Check if audio is currently playing
|
|
1212
|
+
*/
|
|
1213
|
+
isPlaying() {
|
|
1214
|
+
return this.currentAudio !== null && !this.currentAudio.paused;
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
const B = new Le(), Ue = (i = {}) => {
|
|
1218
|
+
const [t, e] = y(!1), [a, s] = y(!1), [c, n] = y(null);
|
|
1219
|
+
i.config && B.updateConfig(i.config);
|
|
1220
|
+
const o = v(
|
|
1221
|
+
async (g, d = {}) => {
|
|
1222
|
+
var u;
|
|
1223
|
+
try {
|
|
1224
|
+
n(null), s(!0);
|
|
1225
|
+
const h = {
|
|
1226
|
+
text: g,
|
|
1227
|
+
...d
|
|
1228
|
+
};
|
|
1229
|
+
await B.speak(h, {
|
|
1230
|
+
onStart: () => {
|
|
1231
|
+
var x;
|
|
1232
|
+
s(!1), e(!0), (x = i.onStart) == null || x.call(i);
|
|
1233
|
+
},
|
|
1234
|
+
onEnd: () => {
|
|
1235
|
+
var x;
|
|
1236
|
+
e(!1), (x = i.onEnd) == null || x.call(i);
|
|
1237
|
+
},
|
|
1238
|
+
onError: (x) => {
|
|
1239
|
+
var k;
|
|
1240
|
+
e(!1), s(!1), n(x), (k = i.onError) == null || k.call(i, x);
|
|
1241
|
+
}
|
|
1242
|
+
});
|
|
1243
|
+
} catch (h) {
|
|
1244
|
+
const x = h instanceof Error ? h : new Error(String(h));
|
|
1245
|
+
throw n(x), e(!1), s(!1), (u = i.onError) == null || u.call(i, x), x;
|
|
1246
|
+
}
|
|
1247
|
+
},
|
|
1248
|
+
[i]
|
|
1249
|
+
), m = v(() => {
|
|
1250
|
+
B.stop(), e(!1), s(!1);
|
|
1251
|
+
}, []);
|
|
1252
|
+
return {
|
|
1253
|
+
speak: o,
|
|
1254
|
+
stop: m,
|
|
1255
|
+
isPlaying: t,
|
|
1256
|
+
isLoading: a,
|
|
1257
|
+
error: c
|
|
1258
|
+
};
|
|
1259
|
+
};
|
|
1260
|
+
function qe(i) {
|
|
1261
|
+
const t = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(i);
|
|
1262
|
+
return t ? {
|
|
1263
|
+
r: parseInt(t[1], 16),
|
|
1264
|
+
g: parseInt(t[2], 16),
|
|
1265
|
+
b: parseInt(t[3], 16)
|
|
1266
|
+
} : null;
|
|
1267
|
+
}
|
|
1268
|
+
function Fe(i, t, e) {
|
|
1269
|
+
return "#" + [i, t, e].map((a) => {
|
|
1270
|
+
const s = Math.round(a).toString(16);
|
|
1271
|
+
return s.length === 1 ? "0" + s : s;
|
|
1272
|
+
}).join("");
|
|
1273
|
+
}
|
|
1274
|
+
function V(i, t) {
|
|
1275
|
+
const e = qe(i);
|
|
1276
|
+
if (!e) return i;
|
|
1277
|
+
const a = e.r + (255 - e.r) * t, s = e.g + (255 - e.g) * t, c = e.b + (255 - e.b) * t;
|
|
1278
|
+
return Fe(a, s, c);
|
|
1279
|
+
}
|
|
1280
|
+
function Qe(i, t = 0.8) {
|
|
1281
|
+
const e = V(i, t), a = V(i, 0.7);
|
|
1282
|
+
return {
|
|
1283
|
+
background: `linear-gradient(to bottom, ${e}, #ffffff)`,
|
|
1284
|
+
border: `1px solid ${a}`,
|
|
1285
|
+
color: "#1f2937"
|
|
501
1286
|
};
|
|
502
|
-
|
|
1287
|
+
}
|
|
1288
|
+
function Be(i) {
|
|
1289
|
+
return new Promise((t) => setTimeout(t, i));
|
|
1290
|
+
}
|
|
1291
|
+
const He = ({
|
|
1292
|
+
state: i,
|
|
1293
|
+
className: t = "",
|
|
1294
|
+
defaultTimers: e = { thinking: 30, answering: 120, editing: 30 }
|
|
1295
|
+
}) => {
|
|
1296
|
+
const a = (d) => {
|
|
1297
|
+
const u = Math.floor(d / 60), h = d % 60;
|
|
1298
|
+
return `${u.toString().padStart(2, "0")}:${h.toString().padStart(2, "0")}`;
|
|
1299
|
+
}, s = (d) => ({
|
|
1300
|
+
[l.IDLE]: "Ready",
|
|
1301
|
+
[l.FETCHING_QUESTION]: "Loading Question...",
|
|
1302
|
+
[l.READING_QUESTION]: "Reading Question...",
|
|
1303
|
+
[l.THINKING]: "Preparation Time",
|
|
1304
|
+
[l.ANSWERING]: "Recording Answer",
|
|
1305
|
+
[l.TRANSCRIBING]: "Processing Speech...",
|
|
1306
|
+
[l.EDITING]: "Edit Your Answer",
|
|
1307
|
+
[l.SUBMITTING]: "Submitting...",
|
|
1308
|
+
[l.COMPLETED]: "Interview Complete"
|
|
1309
|
+
})[d] || d, c = (d) => ({
|
|
1310
|
+
[l.IDLE]: "iw-bg-gray-500",
|
|
1311
|
+
[l.FETCHING_QUESTION]: "iw-bg-blue-500",
|
|
1312
|
+
[l.READING_QUESTION]: "iw-bg-indigo-500",
|
|
1313
|
+
[l.THINKING]: "iw-bg-yellow-500",
|
|
1314
|
+
[l.ANSWERING]: "iw-bg-red-500",
|
|
1315
|
+
[l.TRANSCRIBING]: "iw-bg-purple-500",
|
|
1316
|
+
[l.EDITING]: "iw-bg-orange-500",
|
|
1317
|
+
[l.SUBMITTING]: "iw-bg-green-500",
|
|
1318
|
+
[l.COMPLETED]: "iw-bg-green-600"
|
|
1319
|
+
})[d] || "iw-bg-gray-500", n = (d) => ({
|
|
1320
|
+
[l.IDLE]: "iw-bg-gray-100 iw-text-gray-800",
|
|
1321
|
+
[l.FETCHING_QUESTION]: "iw-bg-blue-100 iw-text-blue-800",
|
|
1322
|
+
[l.READING_QUESTION]: "iw-bg-indigo-100 iw-text-indigo-800",
|
|
1323
|
+
[l.THINKING]: "iw-bg-yellow-100 iw-text-yellow-800",
|
|
1324
|
+
[l.ANSWERING]: "iw-bg-red-100 iw-text-red-800",
|
|
1325
|
+
[l.TRANSCRIBING]: "iw-bg-purple-100 iw-text-purple-800",
|
|
1326
|
+
[l.EDITING]: "iw-bg-orange-100 iw-text-orange-800",
|
|
1327
|
+
[l.SUBMITTING]: "iw-bg-green-100 iw-text-green-800",
|
|
1328
|
+
[l.COMPLETED]: "iw-bg-green-200 iw-text-green-900"
|
|
1329
|
+
})[d] || "iw-bg-gray-100 iw-text-gray-800", o = (d) => ({
|
|
1330
|
+
[l.IDLE]: "Ready to start next question.",
|
|
1331
|
+
[l.FETCHING_QUESTION]: "Please wait while we load the next question...",
|
|
1332
|
+
[l.READING_QUESTION]: "Listening to the question...",
|
|
1333
|
+
[l.THINKING]: "Take time to think about your answer.",
|
|
1334
|
+
[l.ANSWERING]: "Speak clearly into your microphone.",
|
|
1335
|
+
[l.TRANSCRIBING]: "Converting your speech to text...",
|
|
1336
|
+
[l.EDITING]: "Review and edit your answer.",
|
|
1337
|
+
[l.SUBMITTING]: "Submitting your answer...",
|
|
1338
|
+
[l.COMPLETED]: "Thank you for completing the interview!"
|
|
1339
|
+
})[d] || "";
|
|
1340
|
+
function m(d) {
|
|
1341
|
+
return {
|
|
1342
|
+
[l.THINKING]: e.thinking || 30,
|
|
1343
|
+
[l.ANSWERING]: e.answering || 120,
|
|
1344
|
+
[l.EDITING]: e.editing || 30
|
|
1345
|
+
}[d] || 1;
|
|
1346
|
+
}
|
|
1347
|
+
const g = i.currentPhaseTimeRemaining > 0;
|
|
1348
|
+
return /* @__PURE__ */ r.jsxs(
|
|
503
1349
|
"div",
|
|
504
1350
|
{
|
|
505
|
-
className:
|
|
506
|
-
style: {
|
|
507
|
-
// Fallback styles in case CSS classes don't load properly
|
|
508
|
-
background: "linear-gradient(to bottom, #eef2ff, #ffffff)",
|
|
509
|
-
border: "1px solid #e0e7ff",
|
|
510
|
-
color: "#1f2937"
|
|
511
|
-
},
|
|
1351
|
+
className: `iw-iw-bg-white iw-rounded-lg iw-shadow-md iw-p-4 iw-border iw-border-gray-200 ${t}`,
|
|
512
1352
|
children: [
|
|
513
|
-
/* @__PURE__ */
|
|
514
|
-
/* @__PURE__ */
|
|
1353
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-justify-between iw-items-center iw-mb-4", children: [
|
|
1354
|
+
/* @__PURE__ */ r.jsxs("div", { children: [
|
|
1355
|
+
/* @__PURE__ */ r.jsx("h3", { className: "iw-text-sm iw-font-semibold iw-text-gray-700", children: "Interview Timer" }),
|
|
1356
|
+
/* @__PURE__ */ r.jsxs("p", { className: "iw-text-xs iw-text-gray-700 iw-my-3 iw-font-mono", children: [
|
|
1357
|
+
"Phase",
|
|
1358
|
+
" ",
|
|
1359
|
+
/* @__PURE__ */ r.jsx(
|
|
1360
|
+
"span",
|
|
1361
|
+
{
|
|
1362
|
+
className: `iw-px-3 iw-py-1.5 iw-rounded-md iw-font-medium ${n(
|
|
1363
|
+
i.phase
|
|
1364
|
+
)}`,
|
|
1365
|
+
children: i.phase
|
|
1366
|
+
}
|
|
1367
|
+
)
|
|
1368
|
+
] }),
|
|
1369
|
+
/* @__PURE__ */ r.jsxs("p", { className: "iw-text-xs iw-text-gray-700 iw-font-mono", children: [
|
|
1370
|
+
"Question ",
|
|
1371
|
+
i.currentQuestionNumber
|
|
1372
|
+
] })
|
|
1373
|
+
] }),
|
|
1374
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-text-right", children: [
|
|
1375
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-text-2xl iw-font-bold iw-text-gray-900", children: a(i.totalTimeRemaining) }),
|
|
1376
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-text-xs iw-text-gray-500", children: "Total Time Left" })
|
|
1377
|
+
] })
|
|
1378
|
+
] }),
|
|
1379
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-mb-4", children: /* @__PURE__ */ r.jsx("div", { className: "iw-w-full iw-h-2 iw-iw-bg-gray-200 iw-rounded-full iw-overflow-hidden", children: /* @__PURE__ */ r.jsx(
|
|
1380
|
+
"div",
|
|
1381
|
+
{
|
|
1382
|
+
className: "iw-h-full iw-iw-bg-gradient-to-r iw-from-blue-500 iw-to-purple-500 iw-transition-all iw-duration-300",
|
|
1383
|
+
style: {
|
|
1384
|
+
width: `${i.totalTimeElapsed / (i.totalTimeElapsed + i.totalTimeRemaining) * 100}%`
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
) }) }),
|
|
1388
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-mb-4", children: [
|
|
1389
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-justify-between iw-mb-2", children: [
|
|
1390
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-2", children: [
|
|
1391
|
+
/* @__PURE__ */ r.jsx(
|
|
1392
|
+
"div",
|
|
1393
|
+
{
|
|
1394
|
+
className: `iw-w-3 iw-h-3 iw-rounded-full ${c(
|
|
1395
|
+
i.phase
|
|
1396
|
+
)} ${g ? "iw-animate-pulse" : ""}`
|
|
1397
|
+
}
|
|
1398
|
+
),
|
|
1399
|
+
/* @__PURE__ */ r.jsx("span", { className: "iw-text-sm iw-font-medium iw-text-gray-700", children: s(i.phase) })
|
|
1400
|
+
] }),
|
|
1401
|
+
g && /* @__PURE__ */ r.jsx("span", { className: "iw-text-lg iw-font-bold iw-text-gray-900", children: a(i.currentPhaseTimeRemaining) })
|
|
1402
|
+
] }),
|
|
1403
|
+
g && /* @__PURE__ */ r.jsx("div", { className: "iw-w-full iw-h-1.5 iw-iw-bg-gray-200 iw-rounded-full iw-overflow-hidden", children: /* @__PURE__ */ r.jsx(
|
|
515
1404
|
"div",
|
|
516
1405
|
{
|
|
517
|
-
className:
|
|
518
|
-
|
|
1406
|
+
className: `iw-h-full ${c(
|
|
1407
|
+
i.phase
|
|
1408
|
+
)} iw-transition-all iw-duration-300`,
|
|
1409
|
+
style: {
|
|
1410
|
+
width: `${i.currentPhaseTimeRemaining / m(i.phase) * 100}%`
|
|
1411
|
+
}
|
|
519
1412
|
}
|
|
520
|
-
)
|
|
521
|
-
/* @__PURE__ */ t.jsxs("div", { children: [
|
|
522
|
-
/* @__PURE__ */ t.jsx("div", { className: "iw-text-sm iw-font-semibold", children: "Novara" }),
|
|
523
|
-
/* @__PURE__ */ t.jsx("div", { className: "iw-text-xs iw-text-gray-500", children: "Assistant" })
|
|
524
|
-
] })
|
|
1413
|
+
) })
|
|
525
1414
|
] }),
|
|
526
|
-
|
|
527
|
-
"li",
|
|
528
|
-
{
|
|
529
|
-
className: "iw-cursor-pointer",
|
|
530
|
-
onClick: () => r(a.id),
|
|
531
|
-
children: [
|
|
532
|
-
/* @__PURE__ */ t.jsx("span", { className: "iw-font-medium", children: a.title }),
|
|
533
|
-
" - $",
|
|
534
|
-
a.price
|
|
535
|
-
]
|
|
536
|
-
},
|
|
537
|
-
a.id
|
|
538
|
-
)) })
|
|
1415
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-mt-3 iw-pt-3 iw-border-t iw-border-gray-200", children: /* @__PURE__ */ r.jsx("p", { className: "iw-text-xs iw-text-gray-600", children: o(i.phase) }) })
|
|
539
1416
|
]
|
|
540
1417
|
}
|
|
541
1418
|
);
|
|
542
|
-
},
|
|
543
|
-
const e = j(null);
|
|
544
|
-
return P(() => {
|
|
545
|
-
let s = null;
|
|
546
|
-
return (async () => {
|
|
547
|
-
try {
|
|
548
|
-
s = await navigator.mediaDevices.getUserMedia({
|
|
549
|
-
video: !0,
|
|
550
|
-
audio: !1
|
|
551
|
-
}), e.current && (e.current.srcObject = s);
|
|
552
|
-
} catch (r) {
|
|
553
|
-
console.error("Error accessing camera:", r);
|
|
554
|
-
}
|
|
555
|
-
})(), () => {
|
|
556
|
-
s && s.getTracks().forEach((r) => r.stop());
|
|
557
|
-
};
|
|
558
|
-
}, []), /* @__PURE__ */ t.jsx("div", { className: `iw-relative ${i}`, children: /* @__PURE__ */ t.jsx(
|
|
559
|
-
"video",
|
|
560
|
-
{
|
|
561
|
-
ref: e,
|
|
562
|
-
autoPlay: !0,
|
|
563
|
-
playsInline: !0,
|
|
564
|
-
muted: !0,
|
|
565
|
-
className: "iw-w-full iw-h-full iw-object-cover iw-rounded-md"
|
|
566
|
-
}
|
|
567
|
-
) });
|
|
568
|
-
}, X = ({
|
|
1419
|
+
}, We = ({
|
|
569
1420
|
label: i,
|
|
570
|
-
error:
|
|
571
|
-
fullWidth:
|
|
572
|
-
className:
|
|
573
|
-
id:
|
|
574
|
-
...
|
|
1421
|
+
error: t,
|
|
1422
|
+
fullWidth: e = !1,
|
|
1423
|
+
className: a = "",
|
|
1424
|
+
id: s,
|
|
1425
|
+
...c
|
|
575
1426
|
}) => {
|
|
576
|
-
const
|
|
577
|
-
return /* @__PURE__ */
|
|
1427
|
+
const n = s || `textarea-${Math.random().toString(36).substring(2, 9)}`, o = "iw-block iw-rounded-md iw-border iw-border-gray-300 iw-shadow-sm iw-px-4 iw-py-2 iw-text-sm iw-focus:border-primary-500 iw-focus:ring-primary-500 iw-focus:outline-none iw-transition-all", m = t ? "iw-border-red-500 iw-focus:border-red-500 iw-focus:ring-red-500" : "", g = e ? "iw-w-full" : "", d = a.includes("iw-h-full") ? "iw-h-full" : "";
|
|
1428
|
+
return /* @__PURE__ */ r.jsxs(
|
|
578
1429
|
"div",
|
|
579
1430
|
{
|
|
580
|
-
className: `${
|
|
1431
|
+
className: `${e ? "iw-w-full iw-h-full" : ""} ${d ? "iw-flex iw-flex-col" : ""}`,
|
|
581
1432
|
children: [
|
|
582
|
-
i && /* @__PURE__ */
|
|
1433
|
+
i && /* @__PURE__ */ r.jsx(
|
|
583
1434
|
"label",
|
|
584
1435
|
{
|
|
585
|
-
htmlFor:
|
|
1436
|
+
htmlFor: n,
|
|
586
1437
|
className: "iw-block iw-text-sm iw-font-medium iw-text-gray-700 iw-mb-1",
|
|
587
1438
|
children: i
|
|
588
1439
|
}
|
|
589
1440
|
),
|
|
590
|
-
/* @__PURE__ */
|
|
1441
|
+
/* @__PURE__ */ r.jsx(
|
|
591
1442
|
"textarea",
|
|
592
1443
|
{
|
|
593
|
-
id:
|
|
594
|
-
className: `${
|
|
595
|
-
"aria-invalid":
|
|
596
|
-
...
|
|
1444
|
+
id: n,
|
|
1445
|
+
className: `${o} ${m} ${g} ${d} ${a}`,
|
|
1446
|
+
"aria-invalid": t ? "true" : "false",
|
|
1447
|
+
...c
|
|
597
1448
|
}
|
|
598
1449
|
),
|
|
599
|
-
|
|
1450
|
+
t && /* @__PURE__ */ r.jsx("p", { className: "iw-mt-1 iw-text-sm iw-text-red-600", children: t })
|
|
600
1451
|
]
|
|
601
1452
|
}
|
|
602
1453
|
);
|
|
603
|
-
},
|
|
1454
|
+
}, ze = ({
|
|
604
1455
|
value: i,
|
|
605
|
-
onChange:
|
|
606
|
-
onSubmit:
|
|
607
|
-
isSubmitDisabled:
|
|
608
|
-
remainingTimeText:
|
|
1456
|
+
onChange: t,
|
|
1457
|
+
onSubmit: e,
|
|
1458
|
+
isSubmitDisabled: a,
|
|
1459
|
+
remainingTimeText: s
|
|
609
1460
|
}) => {
|
|
610
|
-
const
|
|
611
|
-
|
|
1461
|
+
const c = (n) => {
|
|
1462
|
+
n.key === "Enter" && (n.ctrlKey || n.metaKey) && !a && (n.preventDefault(), e());
|
|
612
1463
|
};
|
|
613
|
-
return /* @__PURE__ */
|
|
614
|
-
/* @__PURE__ */
|
|
615
|
-
/* @__PURE__ */
|
|
616
|
-
|
|
1464
|
+
return /* @__PURE__ */ r.jsx("div", { className: "iw-mt-auto", children: /* @__PURE__ */ r.jsxs("div", { className: "iw-rounded-xl iw-overflow-hidden iw-border iw-border-gray-200", children: [
|
|
1465
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-justify-between iw-px-3 iw-py-2 iw-bg-gray-50 iw-border-b iw-border-gray-200", children: [
|
|
1466
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-text-sm iw-font-medium", children: "Your answer" }),
|
|
1467
|
+
s && /* @__PURE__ */ r.jsx("div", { className: "iw-text-xs iw-text-gray-500", children: s })
|
|
617
1468
|
] }),
|
|
618
|
-
/* @__PURE__ */
|
|
619
|
-
|
|
1469
|
+
/* @__PURE__ */ r.jsx(
|
|
1470
|
+
We,
|
|
620
1471
|
{
|
|
621
1472
|
value: i,
|
|
622
|
-
onChange:
|
|
623
|
-
onKeyDown:
|
|
1473
|
+
onChange: t,
|
|
1474
|
+
onKeyDown: c,
|
|
624
1475
|
placeholder: "Type your answer here...",
|
|
625
1476
|
className: "iw-bg-gray-50 iw-w-full iw-resize-none iw-focus:outline-none iw-bg-transparent iw-min-h-[112px]",
|
|
626
1477
|
rows: 5,
|
|
627
1478
|
fullWidth: !0
|
|
628
1479
|
}
|
|
629
1480
|
),
|
|
630
|
-
/* @__PURE__ */
|
|
631
|
-
/* @__PURE__ */
|
|
632
|
-
/* @__PURE__ */
|
|
633
|
-
|
|
1481
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-p-2 iw-flex iw-justify-between iw-items-center iw-bg-gray-50", children: [
|
|
1482
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-text-xs iw-text-gray-500", children: /* @__PURE__ */ r.jsx("kbd", { children: " Press Ctrl+Enter to submit" }) }),
|
|
1483
|
+
/* @__PURE__ */ r.jsx(
|
|
1484
|
+
$,
|
|
634
1485
|
{
|
|
635
|
-
onClick:
|
|
636
|
-
disabled:
|
|
1486
|
+
onClick: e,
|
|
1487
|
+
disabled: a,
|
|
637
1488
|
size: "sm",
|
|
638
1489
|
variant: "gradient",
|
|
639
1490
|
children: "Submit Answer"
|
|
@@ -641,72 +1492,383 @@ const S = new B("https://fakestoreapi.com"), J = ({ question: i }) => {
|
|
|
641
1492
|
)
|
|
642
1493
|
] })
|
|
643
1494
|
] }) });
|
|
644
|
-
},
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
onComplete: s,
|
|
648
|
-
onAnswerSubmit: n,
|
|
649
|
-
className: r = ""
|
|
1495
|
+
}, Ye = ({
|
|
1496
|
+
question: i,
|
|
1497
|
+
isLoading: t = !1
|
|
650
1498
|
}) => {
|
|
651
|
-
const
|
|
652
|
-
|
|
653
|
-
questionId: (p == null ? void 0 : p.id) || "",
|
|
654
|
-
answerText: d,
|
|
655
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
656
|
-
};
|
|
657
|
-
w([...l, b]), n && n(b), a < e.length - 1 ? (o((v) => v + 1), u("")) : (f(!0), s && s(l));
|
|
658
|
-
}, D = H(() => {
|
|
659
|
-
const v = 60 - Math.floor(Date.now() / 1e3 % 60), F = Math.floor(v / 60).toString().padStart(2, "0"), U = (v % 60).toString().padStart(2, "0");
|
|
660
|
-
return `Time to Talk: ${F}:${U} min`;
|
|
661
|
-
}, [a]);
|
|
662
|
-
return c ? /* @__PURE__ */ t.jsx("div", { className: "interview-widget-container", children: /* @__PURE__ */ t.jsx(
|
|
1499
|
+
const { baseColor: e } = F();
|
|
1500
|
+
return t ? /* @__PURE__ */ r.jsxs(
|
|
663
1501
|
"div",
|
|
664
1502
|
{
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
/* @__PURE__ */
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
"
|
|
677
|
-
{
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
/* @__PURE__ */
|
|
683
|
-
|
|
684
|
-
{
|
|
685
|
-
value: d,
|
|
686
|
-
onChange: (b) => u(b.target.value),
|
|
687
|
-
onSubmit: A,
|
|
688
|
-
isSubmitDisabled: !d.trim() || !c,
|
|
689
|
-
remainingTimeText: D
|
|
690
|
-
}
|
|
691
|
-
)
|
|
1503
|
+
className: "iw-rounded-xl iw-mb-4 iw-p-5",
|
|
1504
|
+
style: {
|
|
1505
|
+
background: "linear-gradient(to bottom, #eef2ff, #ffffff)",
|
|
1506
|
+
border: "1px solid #e0e7ff",
|
|
1507
|
+
color: "#1f2937"
|
|
1508
|
+
},
|
|
1509
|
+
children: [
|
|
1510
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-3 iw-mb-3", children: [
|
|
1511
|
+
/* @__PURE__ */ r.jsx(
|
|
1512
|
+
"div",
|
|
1513
|
+
{
|
|
1514
|
+
className: "iw-h-12 iw-w-12 iw-rounded-lg iw-flex iw-items-center iw-justify-center iw-text-white iw-font-semibold iw-animate-pulse",
|
|
1515
|
+
style: { backgroundColor: e },
|
|
1516
|
+
children: "N"
|
|
1517
|
+
}
|
|
1518
|
+
),
|
|
1519
|
+
/* @__PURE__ */ r.jsxs("div", { children: [
|
|
1520
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-text-sm iw-font-semibold", children: "Novara" }),
|
|
1521
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-text-xs iw-text-gray-500", children: "Assistant" })
|
|
692
1522
|
] })
|
|
693
|
-
] })
|
|
694
|
-
|
|
1523
|
+
] }),
|
|
1524
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-animate-pulse", children: [
|
|
1525
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-h-4 iw-bg-gray-200 iw-rounded iw-w-3/4 iw-mb-2" }),
|
|
1526
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-h-4 iw-bg-gray-200 iw-rounded iw-w-full" })
|
|
1527
|
+
] })
|
|
1528
|
+
]
|
|
1529
|
+
}
|
|
1530
|
+
) : i ? /* @__PURE__ */ r.jsxs(
|
|
1531
|
+
"div",
|
|
1532
|
+
{
|
|
1533
|
+
className: "iw-rounded-xl iw-mb-4 message-animation iw-text-gray-800 iw-border iw-border-indigo-100 iw-p-5",
|
|
1534
|
+
style: Qe(e ?? "#8C75FB", 0.85),
|
|
1535
|
+
children: [
|
|
1536
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-3 iw-mb-3", children: [
|
|
1537
|
+
/* @__PURE__ */ r.jsx(
|
|
1538
|
+
"div",
|
|
1539
|
+
{
|
|
1540
|
+
className: "iw-h-12 iw-w-12 iw-rounded-lg iw-flex iw-items-center iw-justify-center iw-text-white iw-font-semibold",
|
|
1541
|
+
style: { backgroundColor: e },
|
|
1542
|
+
children: "N"
|
|
1543
|
+
}
|
|
1544
|
+
),
|
|
1545
|
+
/* @__PURE__ */ r.jsxs("div", { children: [
|
|
1546
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-text-sm iw-font-semibold", children: "Novara" }),
|
|
1547
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-text-xs iw-text-gray-500", children: "Assistant" })
|
|
1548
|
+
] })
|
|
1549
|
+
] }),
|
|
1550
|
+
/* @__PURE__ */ r.jsx("p", { className: "iw-text-[15px] iw-leading-6", children: i.question })
|
|
1551
|
+
]
|
|
1552
|
+
}
|
|
1553
|
+
) : /* @__PURE__ */ r.jsx(
|
|
1554
|
+
"div",
|
|
1555
|
+
{
|
|
1556
|
+
className: "iw-rounded-xl iw-mb-4 iw-bg-gray-50 iw-text-gray-500 iw-border iw-border-gray-200 iw-p-5 iw-text-center",
|
|
1557
|
+
children: /* @__PURE__ */ r.jsx("p", { className: "iw-text-sm", children: "No question available" })
|
|
1558
|
+
}
|
|
1559
|
+
);
|
|
1560
|
+
}, Ke = ({
|
|
1561
|
+
interviewId: i,
|
|
1562
|
+
onComplete: t,
|
|
1563
|
+
className: e = ""
|
|
1564
|
+
}) => {
|
|
1565
|
+
const a = Oe(), { baseColor: s } = F(), { baseUrl: c } = Te(), { timers: n, stt: o, tts: m } = Ie(), [g, d] = y(null), [u, h] = y(""), [x, k] = y(!1), j = D(""), N = D(null), w = {
|
|
1566
|
+
thinkingTime: (n == null ? void 0 : n.thinkingDuration) || 30,
|
|
1567
|
+
answeringTime: (n == null ? void 0 : n.answeringDuration) || 120,
|
|
1568
|
+
editingTime: (n == null ? void 0 : n.editingDuration) || 30,
|
|
1569
|
+
totalTime: (n == null ? void 0 : n.totalInterviewDuration) || 600,
|
|
1570
|
+
minimumBufferTime: (n == null ? void 0 : n.minimumTimeForNextQuestion) || 120
|
|
1571
|
+
}, {
|
|
1572
|
+
thinkingTime: p,
|
|
1573
|
+
answeringTime: T,
|
|
1574
|
+
editingTime: S,
|
|
1575
|
+
totalTime: ie,
|
|
1576
|
+
minimumBufferTime: re
|
|
1577
|
+
} = w;
|
|
1578
|
+
A(() => {
|
|
1579
|
+
j.current = u;
|
|
1580
|
+
}, [u]);
|
|
1581
|
+
const _ = D(!1), {
|
|
1582
|
+
speak: te,
|
|
1583
|
+
isPlaying: se,
|
|
1584
|
+
error: W
|
|
1585
|
+
} = Ue({
|
|
1586
|
+
config: {
|
|
1587
|
+
baseUrl: c,
|
|
1588
|
+
provider: m == null ? void 0 : m.provider
|
|
1589
|
+
},
|
|
1590
|
+
onEnd: () => {
|
|
1591
|
+
console.log("TTS playback completed"), _.current = !1, E();
|
|
1592
|
+
},
|
|
1593
|
+
onError: (f) => {
|
|
1594
|
+
console.error("TTS Error:", f), _.current || (_.current = !0, E());
|
|
1595
|
+
}
|
|
1596
|
+
}), G = D(!1), L = D(!1), {
|
|
1597
|
+
startRecording: z,
|
|
1598
|
+
stopRecording: Y,
|
|
1599
|
+
transcribe: K,
|
|
1600
|
+
isRecording: ne,
|
|
1601
|
+
isTranscribing: ae,
|
|
1602
|
+
error: M
|
|
1603
|
+
} = _e({
|
|
1604
|
+
config: {
|
|
1605
|
+
baseUrl: c,
|
|
1606
|
+
provider: o == null ? void 0 : o.provider,
|
|
1607
|
+
model: o == null ? void 0 : o.model,
|
|
1608
|
+
language: o == null ? void 0 : o.language
|
|
1609
|
+
},
|
|
1610
|
+
onStart: () => {
|
|
1611
|
+
console.log("STT recording started"), G.current = !1, L.current = !1;
|
|
1612
|
+
},
|
|
1613
|
+
onStop: () => {
|
|
1614
|
+
console.log("STT recording stopped");
|
|
1615
|
+
},
|
|
1616
|
+
onTranscriptionComplete: (f) => {
|
|
1617
|
+
console.log("Transcription completed:", f), h(f.transcript), L.current || (L.current = !0, E());
|
|
1618
|
+
},
|
|
1619
|
+
onError: (f) => {
|
|
1620
|
+
console.error("STT Error:", f), G.current || (G.current = !0, E());
|
|
1621
|
+
}
|
|
1622
|
+
}), { state: R, startQuestion: Q, nextPhase: E } = De({
|
|
1623
|
+
config: {
|
|
1624
|
+
thinkingDuration: p,
|
|
1625
|
+
answeringDuration: T,
|
|
1626
|
+
editingDuration: S,
|
|
1627
|
+
totalInterviewDuration: ie,
|
|
1628
|
+
minimumTimeForNextQuestion: re
|
|
1629
|
+
},
|
|
1630
|
+
callbacks: {
|
|
1631
|
+
onPhaseChange: (f) => {
|
|
1632
|
+
switch (console.log("Phase changed:", f), f) {
|
|
1633
|
+
case l.FETCHING_QUESTION:
|
|
1634
|
+
oe();
|
|
1635
|
+
break;
|
|
1636
|
+
case l.READING_QUESTION:
|
|
1637
|
+
le();
|
|
1638
|
+
break;
|
|
1639
|
+
case l.ANSWERING:
|
|
1640
|
+
de();
|
|
1641
|
+
break;
|
|
1642
|
+
case l.TRANSCRIBING:
|
|
1643
|
+
we();
|
|
1644
|
+
break;
|
|
1645
|
+
case l.SUBMITTING:
|
|
1646
|
+
ce();
|
|
1647
|
+
break;
|
|
1648
|
+
}
|
|
1649
|
+
},
|
|
1650
|
+
onInterviewEnd: () => {
|
|
1651
|
+
t == null || t();
|
|
1652
|
+
}
|
|
695
1653
|
}
|
|
696
|
-
|
|
697
|
-
|
|
1654
|
+
}), { execute: oe } = Pe(
|
|
1655
|
+
async () => {
|
|
1656
|
+
var P, J;
|
|
1657
|
+
const f = await a.generateQuestion({
|
|
1658
|
+
interviewId: i,
|
|
1659
|
+
isInterviewDone: R.totalTimeRemaining < 120,
|
|
1660
|
+
question: ((P = N.current) == null ? void 0 : P.question) || "",
|
|
1661
|
+
qnaId: ((J = N.current) == null ? void 0 : J.qna_id) || "",
|
|
1662
|
+
answer: j.current
|
|
1663
|
+
});
|
|
1664
|
+
return N.current = f.data, f;
|
|
1665
|
+
},
|
|
698
1666
|
{
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
1667
|
+
onSuccess: async (f) => {
|
|
1668
|
+
console.log("Questions fetched successfully", f), f && f.data && (h(""), d(f.data), E());
|
|
1669
|
+
},
|
|
1670
|
+
onError: (f) => {
|
|
1671
|
+
console.error("Failed to fetch questions:", f);
|
|
702
1672
|
}
|
|
703
1673
|
}
|
|
1674
|
+
), ce = v(async () => {
|
|
1675
|
+
console.log("Answer submitted successfully"), await Be(1500), Q();
|
|
1676
|
+
}, [Q]), le = v(async () => {
|
|
1677
|
+
var f;
|
|
1678
|
+
if ((f = N.current) != null && f.question)
|
|
1679
|
+
try {
|
|
1680
|
+
_.current = !1, console.log("Starting TTS for question"), await te(N.current.question);
|
|
1681
|
+
} catch (P) {
|
|
1682
|
+
console.error("Failed to speak question:", P);
|
|
1683
|
+
}
|
|
1684
|
+
else
|
|
1685
|
+
E();
|
|
1686
|
+
}, []), de = v(async () => {
|
|
1687
|
+
console.log("Starting recording...");
|
|
1688
|
+
try {
|
|
1689
|
+
const f = T;
|
|
1690
|
+
console.log("🚀 ~ maxDuration:", f), await z(f);
|
|
1691
|
+
} catch (f) {
|
|
1692
|
+
console.error("Failed to start recording:", f), E();
|
|
1693
|
+
}
|
|
1694
|
+
}, [z, E]), we = v(async () => {
|
|
1695
|
+
console.log("Stopping recording and processing STT...");
|
|
1696
|
+
try {
|
|
1697
|
+
const f = await Y();
|
|
1698
|
+
console.log("Recording stopped, audio blob size:", f.size), await K(f);
|
|
1699
|
+
} catch (f) {
|
|
1700
|
+
console.error("STT processing failed:", f), !G.current && !L.current && (G.current = !0, E());
|
|
1701
|
+
}
|
|
1702
|
+
}, [Y, K, E]), ue = () => {
|
|
1703
|
+
const { phase: f } = R;
|
|
1704
|
+
switch (f) {
|
|
1705
|
+
case l.IDLE:
|
|
1706
|
+
return /* @__PURE__ */ r.jsx("div", { className: "iw-text-center iw-py-8", children: /* @__PURE__ */ r.jsx("p", { className: "iw-text-gray-600", children: "Ready to start..." }) });
|
|
1707
|
+
case l.FETCHING_QUESTION:
|
|
1708
|
+
return /* @__PURE__ */ r.jsx("div", { className: "iw-space-y-4" });
|
|
1709
|
+
case l.READING_QUESTION:
|
|
1710
|
+
return /* @__PURE__ */ r.jsx("div", { className: "iw-space-y-4", children: /* @__PURE__ */ r.jsxs("div", { className: "iw-p-4 iw-bg-indigo-50 iw-border iw-border-indigo-200 iw-rounded-lg", children: [
|
|
1711
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-2", children: [
|
|
1712
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-w-3 iw-h-3 iw-bg-indigo-500 iw-rounded-full iw-animate-pulse" }),
|
|
1713
|
+
/* @__PURE__ */ r.jsx("span", { className: "iw-text-sm iw-font-medium iw-text-indigo-700", children: se ? "Playing question audio..." : "Reading the question..." })
|
|
1714
|
+
] }),
|
|
1715
|
+
W && /* @__PURE__ */ r.jsxs("div", { className: "iw-mt-2 iw-text-xs iw-text-red-600", children: [
|
|
1716
|
+
"Audio playback failed: ",
|
|
1717
|
+
W.message
|
|
1718
|
+
] })
|
|
1719
|
+
] }) });
|
|
1720
|
+
case l.THINKING:
|
|
1721
|
+
case l.ANSWERING:
|
|
1722
|
+
return /* @__PURE__ */ r.jsx("div", { className: "iw-space-y-4", children: f === l.ANSWERING && /* @__PURE__ */ r.jsxs("div", { className: "iw-p-4 iw-bg-red-50 iw-border iw-border-red-200 iw-rounded-lg", children: [
|
|
1723
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-2", children: [
|
|
1724
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-w-3 iw-h-3 iw-bg-red-500 iw-rounded-full iw-animate-pulse" }),
|
|
1725
|
+
/* @__PURE__ */ r.jsx("span", { className: "iw-text-sm iw-font-medium iw-text-red-700", children: ne ? "Recording in progress..." : "Preparing to record..." })
|
|
1726
|
+
] }),
|
|
1727
|
+
M && /* @__PURE__ */ r.jsxs("div", { className: "iw-mt-2 iw-text-xs iw-text-red-600", children: [
|
|
1728
|
+
"Recording error: ",
|
|
1729
|
+
M.message
|
|
1730
|
+
] })
|
|
1731
|
+
] }) });
|
|
1732
|
+
case l.TRANSCRIBING:
|
|
1733
|
+
return /* @__PURE__ */ r.jsx("div", { className: "iw-space-y-4", children: /* @__PURE__ */ r.jsxs("div", { className: "iw-p-4 iw-bg-purple-50 iw-border iw-border-purple-200 iw-rounded-lg", children: [
|
|
1734
|
+
/* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-2", children: [
|
|
1735
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-animate-spin iw-h-4 iw-w-4 iw-border-2 iw-border-purple-500 iw-border-t-transparent iw-rounded-full" }),
|
|
1736
|
+
/* @__PURE__ */ r.jsx("span", { className: "iw-text-sm iw-font-medium iw-text-purple-700", children: ae ? "Transcribing your speech..." : "Processing audio..." })
|
|
1737
|
+
] }),
|
|
1738
|
+
M && /* @__PURE__ */ r.jsxs("div", { className: "iw-mt-2 iw-text-xs iw-text-red-600", children: [
|
|
1739
|
+
"Transcription error: ",
|
|
1740
|
+
M.message,
|
|
1741
|
+
M.recoverable && " (attempting to continue)"
|
|
1742
|
+
] })
|
|
1743
|
+
] }) });
|
|
1744
|
+
case l.EDITING:
|
|
1745
|
+
return /* @__PURE__ */ r.jsx("div", { className: "iw-space-y-4", children: /* @__PURE__ */ r.jsx(
|
|
1746
|
+
ze,
|
|
1747
|
+
{
|
|
1748
|
+
value: u,
|
|
1749
|
+
onChange: (P) => h(P.target.value),
|
|
1750
|
+
onSubmit: () => E(),
|
|
1751
|
+
isSubmitDisabled: !u.trim(),
|
|
1752
|
+
remainingTimeText: `${R.currentPhaseTimeRemaining}s remaining`
|
|
1753
|
+
}
|
|
1754
|
+
) });
|
|
1755
|
+
case l.SUBMITTING:
|
|
1756
|
+
return /* @__PURE__ */ r.jsx("div", { className: "iw-space-y-4", children: /* @__PURE__ */ r.jsx("div", { className: "iw-p-4 iw-bg-green-50 iw-border iw-border-green-200 iw-rounded-lg", children: /* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-2", children: [
|
|
1757
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-animate-spin iw-h-4 iw-w-4 iw-border-2 iw-border-green-500 iw-border-t-transparent iw-rounded-full" }),
|
|
1758
|
+
/* @__PURE__ */ r.jsx("span", { className: "iw-text-sm iw-font-medium iw-text-green-700", children: "Submitting your answer..." })
|
|
1759
|
+
] }) }) });
|
|
1760
|
+
case l.COMPLETED:
|
|
1761
|
+
return /* @__PURE__ */ r.jsxs("div", { className: "iw-text-center iw-py-8", children: [
|
|
1762
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-mb-4", children: /* @__PURE__ */ r.jsx(
|
|
1763
|
+
"svg",
|
|
1764
|
+
{
|
|
1765
|
+
className: "iw-w-16 iw-h-16 iw-mx-auto iw-text-green-500",
|
|
1766
|
+
fill: "none",
|
|
1767
|
+
stroke: "currentColor",
|
|
1768
|
+
viewBox: "0 0 24 24",
|
|
1769
|
+
children: /* @__PURE__ */ r.jsx(
|
|
1770
|
+
"path",
|
|
1771
|
+
{
|
|
1772
|
+
strokeLinecap: "round",
|
|
1773
|
+
strokeLinejoin: "round",
|
|
1774
|
+
strokeWidth: 2,
|
|
1775
|
+
d: "M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
1776
|
+
}
|
|
1777
|
+
)
|
|
1778
|
+
}
|
|
1779
|
+
) }),
|
|
1780
|
+
/* @__PURE__ */ r.jsx("h3", { className: "iw-text-xl iw-font-bold iw-text-gray-900 iw-mb-2", children: "Interview Complete!" }),
|
|
1781
|
+
/* @__PURE__ */ r.jsx("p", { className: "iw-text-gray-600", children: "Thank you for your time. Your answers have been recorded." })
|
|
1782
|
+
] });
|
|
1783
|
+
default:
|
|
1784
|
+
return null;
|
|
1785
|
+
}
|
|
1786
|
+
};
|
|
1787
|
+
return /* @__PURE__ */ r.jsx("div", { className: "interview-widget-container", children: /* @__PURE__ */ r.jsxs(
|
|
1788
|
+
"div",
|
|
1789
|
+
{
|
|
1790
|
+
className: ` iw-max-w-3xl iw-mx-auto iw-space-y-4 iw-py-8 ${e}`,
|
|
1791
|
+
children: [
|
|
1792
|
+
R.phase !== l.IDLE && R.phase !== l.COMPLETED && /* @__PURE__ */ r.jsx(
|
|
1793
|
+
Ye,
|
|
1794
|
+
{
|
|
1795
|
+
question: g,
|
|
1796
|
+
isLoading: R.phase === l.FETCHING_QUESTION
|
|
1797
|
+
}
|
|
1798
|
+
),
|
|
1799
|
+
/* @__PURE__ */ r.jsx("div", { className: "iw-bg-white iw-rounded-lg iw-shadow-md iw-p-6", children: ue() }),
|
|
1800
|
+
/* @__PURE__ */ r.jsx(
|
|
1801
|
+
He,
|
|
1802
|
+
{
|
|
1803
|
+
state: R,
|
|
1804
|
+
defaultTimers: {
|
|
1805
|
+
thinking: p,
|
|
1806
|
+
answering: T,
|
|
1807
|
+
editing: S
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
),
|
|
1811
|
+
x && (R.phase === l.THINKING || R.phase === l.ANSWERING || R.phase === l.EDITING) && /* @__PURE__ */ r.jsx($, { onClick: E, children: "Next Phase" }),
|
|
1812
|
+
!x && /* @__PURE__ */ r.jsx("div", { className: "iw-text-center iw-py-12 w-full", children: /* @__PURE__ */ r.jsx(
|
|
1813
|
+
$,
|
|
1814
|
+
{
|
|
1815
|
+
className: "w-full",
|
|
1816
|
+
style: { backgroundColor: s },
|
|
1817
|
+
onClick: () => {
|
|
1818
|
+
Q(), k(!0);
|
|
1819
|
+
},
|
|
1820
|
+
children: "Start Interview"
|
|
1821
|
+
}
|
|
1822
|
+
) })
|
|
1823
|
+
]
|
|
1824
|
+
}
|
|
1825
|
+
) });
|
|
1826
|
+
}, Je = ({
|
|
1827
|
+
interviewId: i,
|
|
1828
|
+
title: t = "Interview",
|
|
1829
|
+
onInterviewEnd: e,
|
|
1830
|
+
className: a = ""
|
|
1831
|
+
}) => {
|
|
1832
|
+
const [s, c] = y(!1), [n, o] = y(!0), m = D(null);
|
|
1833
|
+
if (!s)
|
|
1834
|
+
return /* @__PURE__ */ r.jsx("div", { className: "interview-widget-container", children: /* @__PURE__ */ r.jsx(
|
|
1835
|
+
Se,
|
|
1836
|
+
{
|
|
1837
|
+
isOpen: n,
|
|
1838
|
+
onStart: () => {
|
|
1839
|
+
console.log("Permissions granted, starting interview"), c(!0), o(!1);
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
) });
|
|
1843
|
+
const g = () => {
|
|
1844
|
+
e == null || e();
|
|
1845
|
+
};
|
|
1846
|
+
return /* @__PURE__ */ r.jsx("div", { className: "interview-widget-container", children: /* @__PURE__ */ r.jsx(
|
|
1847
|
+
"div",
|
|
1848
|
+
{
|
|
1849
|
+
ref: m,
|
|
1850
|
+
className: `iw-flex iw-flex-col iw-rounded-xl iw-shadow-lg iw-overflow-hidden iw-h-[calc(100vh-1rem)] ${a}`,
|
|
1851
|
+
children: /* @__PURE__ */ r.jsxs("div", { className: " iw-h-full iw-flex iw-flex-col", children: [
|
|
1852
|
+
/* @__PURE__ */ r.jsx(je, { title: t, onExit: g }),
|
|
1853
|
+
/* @__PURE__ */ r.jsx(
|
|
1854
|
+
Ke,
|
|
1855
|
+
{
|
|
1856
|
+
interviewId: i,
|
|
1857
|
+
className: a,
|
|
1858
|
+
onComplete: e || (() => {
|
|
1859
|
+
})
|
|
1860
|
+
}
|
|
1861
|
+
)
|
|
1862
|
+
] })
|
|
1863
|
+
}
|
|
704
1864
|
) });
|
|
705
1865
|
};
|
|
706
1866
|
typeof window < "u" && (window.InterviewWidget = {
|
|
707
|
-
InterviewWidget:
|
|
1867
|
+
InterviewWidget: Je,
|
|
1868
|
+
InterviewWidgetProvider: Ne
|
|
708
1869
|
});
|
|
709
1870
|
export {
|
|
710
|
-
|
|
711
|
-
|
|
1871
|
+
Je as InterviewWidget,
|
|
1872
|
+
Ne as InterviewWidgetProvider,
|
|
1873
|
+
Je as default
|
|
712
1874
|
};
|