@thanh01.pmt/interactive-quiz-kit 1.0.44 → 1.0.45
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/dist/react-ui.cjs +275 -50
- package/dist/react-ui.d.cts +4 -1
- package/dist/react-ui.d.ts +4 -1
- package/dist/react-ui.mjs +274 -50
- package/package.json +1 -1
package/dist/react-ui.cjs
CHANGED
|
@@ -10,6 +10,7 @@ var default3 = require('process');
|
|
|
10
10
|
var url = require('url');
|
|
11
11
|
var JSZip = require('jszip');
|
|
12
12
|
var navigation = require('next/navigation');
|
|
13
|
+
var Link3 = require('next/link');
|
|
13
14
|
|
|
14
15
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
16
|
|
|
@@ -36,6 +37,7 @@ var ReactDOM4__namespace = /*#__PURE__*/_interopNamespace(ReactDOM4);
|
|
|
36
37
|
var default2__default = /*#__PURE__*/_interopDefault(default2);
|
|
37
38
|
var default3__default = /*#__PURE__*/_interopDefault(default3);
|
|
38
39
|
var JSZip__default = /*#__PURE__*/_interopDefault(JSZip);
|
|
40
|
+
var Link3__default = /*#__PURE__*/_interopDefault(Link3);
|
|
39
41
|
|
|
40
42
|
var __create = Object.create;
|
|
41
43
|
var __defProp = Object.defineProperty;
|
|
@@ -142549,7 +142551,7 @@ function z29(e3 = x) {
|
|
|
142549
142551
|
}
|
|
142550
142552
|
var B = { tooltip: "core-styles-module_tooltip__3vRRp", fixed: "core-styles-module_fixed__pcSol", arrow: "core-styles-module_arrow__cvMwQ", noArrow: "core-styles-module_noArrow__xock6", clickable: "core-styles-module_clickable__ZuTTB", show: "core-styles-module_show__Nt9eE", closing: "core-styles-module_closing__sGnxF" };
|
|
142551
142553
|
var D2 = { tooltip: "styles-module_tooltip__mnnfp", arrow: "styles-module_arrow__K0L3T", dark: "styles-module_dark__xNqje", light: "styles-module_light__Z6W-X", success: "styles-module_success__A2AKt", warning: "styles-module_warning__SCK0X", error: "styles-module_error__JvumD", info: "styles-module_info__BWdHW" };
|
|
142552
|
-
var q = ({ forwardRef: t4, id: l2, className: i2, classNameArrow: c4, variant: u2 = "dark", anchorId: d, anchorSelect: p2, place: v = "top", offset: m = 10, events: h3 = ["hover"], openOnClick: w2 = false, positionStrategy: b2 = "absolute", middlewares: S3, wrapper: g, delayShow: A3 = 0, delayHide: O2 = 0, float: T3 = false, hidden: x3 = false, noArrow: N2 = false, clickable: $3 = false, closeOnEsc: I = false, closeOnScroll: j = false, closeOnResize: q2 = false, openEvents: H2, closeEvents: M2, globalCloseEvents: W, imperativeModeOnly: P2, style: V, position: F, afterShow: K, afterHide: U2, disableTooltip:
|
|
142554
|
+
var q = ({ forwardRef: t4, id: l2, className: i2, classNameArrow: c4, variant: u2 = "dark", anchorId: d, anchorSelect: p2, place: v = "top", offset: m = 10, events: h3 = ["hover"], openOnClick: w2 = false, positionStrategy: b2 = "absolute", middlewares: S3, wrapper: g, delayShow: A3 = 0, delayHide: O2 = 0, float: T3 = false, hidden: x3 = false, noArrow: N2 = false, clickable: $3 = false, closeOnEsc: I = false, closeOnScroll: j = false, closeOnResize: q2 = false, openEvents: H2, closeEvents: M2, globalCloseEvents: W, imperativeModeOnly: P2, style: V, position: F, afterShow: K, afterHide: U2, disableTooltip: X3, content: Y, contentWrapperRef: G, isOpen: Z2, defaultIsOpen: J = false, setIsOpen: Q, activeAnchor: ee, setActiveAnchor: te, border: oe, opacity: le, arrowColor: re3, arrowSize: ne = 8, role: ie3 = "tooltip" }) => {
|
|
142553
142555
|
var ce;
|
|
142554
142556
|
const se = React163.useRef(null), ae = React163.useRef(null), ue = React163.useRef(null), de = React163.useRef(null), pe = React163.useRef(null), [ve, me] = React163.useState({ tooltipStyles: {}, tooltipArrowStyles: {}, place: v }), [fe, ye] = React163.useState(false), [he, we] = React163.useState(false), [be, Se] = React163.useState(null), ge = React163.useRef(false), Ee = React163.useRef(null), { anchorRefs: Ae, setActiveAnchor: _e } = z29(l2), Oe = React163.useRef(false), [ke, Te] = React163.useState([]), Le = React163.useRef(false), Ce = w2 || h3.includes("click"), Re = Ce || (null == H2 ? void 0 : H2.click) || (null == H2 ? void 0 : H2.dblclick) || (null == H2 ? void 0 : H2.mousedown), xe = H2 ? { ...H2 } : { mouseover: true, focus: true, mouseenter: false, click: false, dblclick: false, mousedown: false };
|
|
142555
142557
|
!H2 && Ce && Object.assign(xe, { mouseenter: false, focus: false, mouseover: false, click: true });
|
|
@@ -142637,10 +142639,10 @@ var q = ({ forwardRef: t4, id: l2, className: i2, classNameArrow: c4, variant: u
|
|
|
142637
142639
|
var e3, t5;
|
|
142638
142640
|
const o2 = new Set(Ae);
|
|
142639
142641
|
ke.forEach((e4) => {
|
|
142640
|
-
(null ==
|
|
142642
|
+
(null == X3 ? void 0 : X3(e4)) || o2.add({ current: e4 });
|
|
142641
142643
|
});
|
|
142642
142644
|
const l3 = document.querySelector(`[id='${d}']`);
|
|
142643
|
-
l3 && !(null ==
|
|
142645
|
+
l3 && !(null == X3 ? void 0 : X3(l3)) && o2.add({ current: l3 });
|
|
142644
142646
|
const r4 = () => {
|
|
142645
142647
|
Ie(false);
|
|
142646
142648
|
}, n2 = L2(ee), i3 = L2(se.current);
|
|
@@ -142756,7 +142758,7 @@ var q = ({ forwardRef: t4, id: l2, className: i2, classNameArrow: c4, variant: u
|
|
|
142756
142758
|
}, style: { ...V, ...ve.tooltipStyles, opacity: void 0 !== le && Ye ? le : void 0 }, ref: se }, Xe, React163__namespace.default.createElement(g, { className: (0, import_classnames.default)("react-tooltip-arrow", B.arrow, D2.arrow, c4, N2 && B.noArrow), style: { ...ve.tooltipArrowStyles, background: re3 ? `linear-gradient(to right bottom, transparent 50%, ${re3} 50%)` : void 0, "--rt-arrow-size": `${ne}px` }, ref: ae })) : null;
|
|
142757
142759
|
};
|
|
142758
142760
|
var H = ({ content: t4 }) => React163__namespace.default.createElement("span", { dangerouslySetInnerHTML: { __html: t4 } });
|
|
142759
|
-
var M = React163__namespace.default.forwardRef(({ id: t4, anchorId: l2, anchorSelect: n2, content: i2, html: c4, render: a4, className: u2, classNameArrow: d, variant: p2 = "dark", place: v = "top", offset: m = 10, wrapper: f = "div", children: h3 = null, events: w2 = ["hover"], openOnClick: b2 = false, positionStrategy: S3 = "absolute", middlewares: g, delayShow: E2 = 0, delayHide: _2 = 0, float: O2 = false, hidden: k3 = false, noArrow: T3 = false, clickable: L3 = false, closeOnEsc: C3 = false, closeOnScroll: R3 = false, closeOnResize: x3 = false, openEvents: N2, closeEvents: $3, globalCloseEvents: I, imperativeModeOnly: j = false, style: B2, position: D3, isOpen: M2, defaultIsOpen: W = false, disableStyleInjection: P2 = false, border: V, opacity: F, arrowColor: K, arrowSize: U2, setIsOpen:
|
|
142761
|
+
var M = React163__namespace.default.forwardRef(({ id: t4, anchorId: l2, anchorSelect: n2, content: i2, html: c4, render: a4, className: u2, classNameArrow: d, variant: p2 = "dark", place: v = "top", offset: m = 10, wrapper: f = "div", children: h3 = null, events: w2 = ["hover"], openOnClick: b2 = false, positionStrategy: S3 = "absolute", middlewares: g, delayShow: E2 = 0, delayHide: _2 = 0, float: O2 = false, hidden: k3 = false, noArrow: T3 = false, clickable: L3 = false, closeOnEsc: C3 = false, closeOnScroll: R3 = false, closeOnResize: x3 = false, openEvents: N2, closeEvents: $3, globalCloseEvents: I, imperativeModeOnly: j = false, style: B2, position: D3, isOpen: M2, defaultIsOpen: W = false, disableStyleInjection: P2 = false, border: V, opacity: F, arrowColor: K, arrowSize: U2, setIsOpen: X3, afterShow: Y, afterHide: G, disableTooltip: Z2, role: J = "tooltip" }, Q) => {
|
|
142760
142762
|
const [ee, te] = React163.useState(i2), [oe, le] = React163.useState(c4), [re3, ne] = React163.useState(v), [ie3, ce] = React163.useState(p2), [se, ae] = React163.useState(m), [ue, de] = React163.useState(E2), [pe, ve] = React163.useState(_2), [me, fe] = React163.useState(O2), [ye, he] = React163.useState(k3), [we, be] = React163.useState(f), [Se, ge] = React163.useState(w2), [Ee, Ae] = React163.useState(S3), [_e, Oe] = React163.useState(null), [ke, Te] = React163.useState(null), Le = React163.useRef(P2), { anchorRefs: Ce, activeAnchor: Re } = z29(t4), xe = (e3) => null == e3 ? void 0 : e3.getAttributeNames().reduce((t5, o2) => {
|
|
142761
142763
|
var l3;
|
|
142762
142764
|
if (o2.startsWith("data-tooltip-")) {
|
|
@@ -142863,7 +142865,7 @@ var M = React163__namespace.default.forwardRef(({ id: t4, anchorId: l2, anchorSe
|
|
|
142863
142865
|
$e = t5 ? React163__namespace.default.createElement("div", { ref: Ie, className: "react-tooltip-content-wrapper" }, t5) : null;
|
|
142864
142866
|
} else ee && ($e = ee);
|
|
142865
142867
|
oe && ($e = React163__namespace.default.createElement(H, { content: oe }));
|
|
142866
|
-
const ze = { forwardRef: Q, id: t4, anchorId: l2, anchorSelect: n2, className: (0, import_classnames.default)(u2, _e), classNameArrow: d, content: $e, contentWrapperRef: Ie, place: re3, variant: ie3, offset: se, wrapper: we, events: Se, openOnClick: b2, positionStrategy: Ee, middlewares: g, delayShow: ue, delayHide: pe, float: me, hidden: ye, noArrow: T3, clickable: L3, closeOnEsc: C3, closeOnScroll: R3, closeOnResize: x3, openEvents: N2, closeEvents: $3, globalCloseEvents: I, imperativeModeOnly: j, style: B2, position: D3, isOpen: M2, defaultIsOpen: W, border: V, opacity: F, arrowColor: K, arrowSize: U2, setIsOpen:
|
|
142868
|
+
const ze = { forwardRef: Q, id: t4, anchorId: l2, anchorSelect: n2, className: (0, import_classnames.default)(u2, _e), classNameArrow: d, content: $e, contentWrapperRef: Ie, place: re3, variant: ie3, offset: se, wrapper: we, events: Se, openOnClick: b2, positionStrategy: Ee, middlewares: g, delayShow: ue, delayHide: pe, float: me, hidden: ye, noArrow: T3, clickable: L3, closeOnEsc: C3, closeOnScroll: R3, closeOnResize: x3, openEvents: N2, closeEvents: $3, globalCloseEvents: I, imperativeModeOnly: j, style: B2, position: D3, isOpen: M2, defaultIsOpen: W, border: V, opacity: F, arrowColor: K, arrowSize: U2, setIsOpen: X3, afterShow: Y, afterHide: G, disableTooltip: Z2, activeAnchor: ke, setActiveAnchor: (e3) => Te(e3), role: J };
|
|
142867
142869
|
return React163__namespace.default.createElement(q, { ...ze });
|
|
142868
142870
|
});
|
|
142869
142871
|
"undefined" != typeof window && window.addEventListener("react-tooltip-inject-styles", (e3) => {
|
|
@@ -167223,7 +167225,7 @@ var ClientTranslation = ({ tKey, options, fallback: fallback2 }) => {
|
|
|
167223
167225
|
};
|
|
167224
167226
|
|
|
167225
167227
|
// src/react-ui/components/app/PersonalPracticeDashboard.tsx
|
|
167226
|
-
var PersonalPracticeDashboard = () => {
|
|
167228
|
+
var PersonalPracticeDashboard = ({ settingsPath }) => {
|
|
167227
167229
|
const router = navigation.useRouter();
|
|
167228
167230
|
const { toast: toast2 } = useToast();
|
|
167229
167231
|
const { t: t4, i18n } = useTranslation();
|
|
@@ -167240,7 +167242,10 @@ var PersonalPracticeDashboard = () => {
|
|
|
167240
167242
|
const [isChatbotOpen, setIsChatbotOpen] = React163.useState(false);
|
|
167241
167243
|
const [isUploadModalOpen, setIsUploadModalOpen] = React163.useState(false);
|
|
167242
167244
|
const [isEditMode, setIsEditMode] = React163.useState(false);
|
|
167243
|
-
const [dashboardLayout, setDashboardLayout] = React163.useState(
|
|
167245
|
+
const [dashboardLayout, setDashboardLayout] = React163.useState(
|
|
167246
|
+
DashboardLayoutService.getLayout()
|
|
167247
|
+
);
|
|
167248
|
+
const [isSettingsModalOpen, setIsSettingsModalOpen] = React163.useState(false);
|
|
167244
167249
|
const loadDashboardData = React163.useCallback(() => {
|
|
167245
167250
|
setIsLoading(true);
|
|
167246
167251
|
setDashboardLayout(DashboardLayoutService.getLayout());
|
|
@@ -167248,9 +167253,17 @@ var PersonalPracticeDashboard = () => {
|
|
|
167248
167253
|
const practiceStats = PracticeHistoryService.getPracticeStats();
|
|
167249
167254
|
const name3 = UserConfigService.getFullName();
|
|
167250
167255
|
if (practiceStats && practiceHistory.length > 0) {
|
|
167251
|
-
const newlyUnlocked = AchievementService.checkAndUnlockAchievements(
|
|
167256
|
+
const newlyUnlocked = AchievementService.checkAndUnlockAchievements(
|
|
167257
|
+
practiceHistory,
|
|
167258
|
+
practiceStats
|
|
167259
|
+
);
|
|
167252
167260
|
if (newlyUnlocked.length > 0) {
|
|
167253
|
-
newlyUnlocked.forEach(
|
|
167261
|
+
newlyUnlocked.forEach(
|
|
167262
|
+
(ach) => toast2({
|
|
167263
|
+
title: "\u{1F3C6} Th\xE0nh t\xEDch M\u1EDBi!",
|
|
167264
|
+
description: `B\u1EA1n \u0111\xE3 m\u1EDF kh\xF3a: ${t4(ach.nameKey)}`
|
|
167265
|
+
})
|
|
167266
|
+
);
|
|
167254
167267
|
}
|
|
167255
167268
|
}
|
|
167256
167269
|
const achievementsWithStatus = AchievementService.getAllAchievementsWithStatus();
|
|
@@ -167272,32 +167285,55 @@ var PersonalPracticeDashboard = () => {
|
|
|
167272
167285
|
const apiKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
|
|
167273
167286
|
if (!apiKey || !stats) return;
|
|
167274
167287
|
try {
|
|
167275
|
-
const weakestTopic = stats.performanceByTopic.sort(
|
|
167276
|
-
|
|
167277
|
-
|
|
167278
|
-
|
|
167279
|
-
|
|
167280
|
-
|
|
167281
|
-
|
|
167288
|
+
const weakestTopic = stats.performanceByTopic.sort(
|
|
167289
|
+
(a4, b2) => a4.averageScore - b2.averageScore
|
|
167290
|
+
)[0]?.name;
|
|
167291
|
+
const aiQuote = await generateMotivationalQuote(
|
|
167292
|
+
{
|
|
167293
|
+
language: i18n.language === "vi" ? "Vietnamese" : "English",
|
|
167294
|
+
userName: UserConfigService.getFullName() || void 0,
|
|
167295
|
+
currentStreak: stats.currentStreak,
|
|
167296
|
+
weakestTopic
|
|
167297
|
+
},
|
|
167298
|
+
apiKey
|
|
167299
|
+
);
|
|
167282
167300
|
if (aiQuote) setMotivationalQuote(aiQuote);
|
|
167283
167301
|
} catch (e3) {
|
|
167284
167302
|
console.warn("Could not fetch AI-powered quote.", e3);
|
|
167285
167303
|
}
|
|
167286
167304
|
};
|
|
167287
167305
|
if (stats) fetchAIQuote();
|
|
167288
|
-
const intervalId = setInterval(
|
|
167306
|
+
const intervalId = setInterval(
|
|
167307
|
+
() => setMotivationalQuote(QuoteService.getRandomQuote()),
|
|
167308
|
+
10 * 60 * 1e3
|
|
167309
|
+
);
|
|
167289
167310
|
return () => clearInterval(intervalId);
|
|
167290
167311
|
}, [stats, i18n.language]);
|
|
167291
167312
|
const historySummaryForTable = React163.useMemo(() => {
|
|
167292
|
-
return history2.map((session) => ({
|
|
167313
|
+
return history2.map((session) => ({
|
|
167314
|
+
...session.summary,
|
|
167315
|
+
id: session.id,
|
|
167316
|
+
timestamp: session.timestamp,
|
|
167317
|
+
quizTitle: session.quizConfig.title
|
|
167318
|
+
}));
|
|
167293
167319
|
}, [history2]);
|
|
167294
|
-
const handleStartPractice = React163.useCallback(
|
|
167320
|
+
const handleStartPractice = React163.useCallback(
|
|
167321
|
+
() => router.push("/practice"),
|
|
167322
|
+
[router]
|
|
167323
|
+
);
|
|
167295
167324
|
const handleGenerateRoadmap = React163.useCallback(async () => {
|
|
167296
167325
|
setIsGeneratingRoadmap(true);
|
|
167297
|
-
toast2({
|
|
167326
|
+
toast2({
|
|
167327
|
+
title: "AI Tutor \u0111ang suy ngh\u0129...",
|
|
167328
|
+
description: "\u0110ang t\u1EA1o l\u1ED9 tr\xECnh h\u1ECDc t\u1EADp \u0111\u01B0\u1EE3c c\xE1 nh\xE2n h\xF3a cho b\u1EA1n."
|
|
167329
|
+
});
|
|
167298
167330
|
const apiKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
|
|
167299
167331
|
if (!apiKey) {
|
|
167300
|
-
toast2({
|
|
167332
|
+
toast2({
|
|
167333
|
+
title: "API Key Missing",
|
|
167334
|
+
description: "Vui l\xF2ng c\u1EA5u h\xECnh Gemini API Key trong C\xE0i \u0111\u1EB7t.",
|
|
167335
|
+
variant: "destructive"
|
|
167336
|
+
});
|
|
167301
167337
|
setIsGeneratingRoadmap(false);
|
|
167302
167338
|
return;
|
|
167303
167339
|
}
|
|
@@ -167309,28 +167345,42 @@ var PersonalPracticeDashboard = () => {
|
|
|
167309
167345
|
topic: lo.topic
|
|
167310
167346
|
}));
|
|
167311
167347
|
if (allAvailableTopics.length === 0) {
|
|
167312
|
-
throw new Error(
|
|
167348
|
+
throw new Error(
|
|
167349
|
+
"No topic data found. Please import curriculum data in Settings first."
|
|
167350
|
+
);
|
|
167313
167351
|
}
|
|
167314
|
-
const result = await generateLearningAnalysis(
|
|
167315
|
-
|
|
167316
|
-
|
|
167317
|
-
|
|
167318
|
-
|
|
167319
|
-
|
|
167320
|
-
|
|
167321
|
-
|
|
167322
|
-
|
|
167323
|
-
|
|
167324
|
-
|
|
167352
|
+
const result = await generateLearningAnalysis(
|
|
167353
|
+
{
|
|
167354
|
+
language: i18n.language === "vi" ? "Vietnamese" : "English",
|
|
167355
|
+
userName: UserConfigService.getFullName() || void 0,
|
|
167356
|
+
weeklyGoal: UserConfigService.getWeeklyGoal() || void 0,
|
|
167357
|
+
unlockedAchievements: AchievementService.getAllAchievementsWithStatus().filter(
|
|
167358
|
+
(a4) => a4.unlockedAt
|
|
167359
|
+
),
|
|
167360
|
+
stats: PracticeHistoryService.getPracticeStats(),
|
|
167361
|
+
history: PracticeHistoryService.getPracticeHistory(),
|
|
167362
|
+
startDate: new Date(Date.now() - 7 * 24 * 60 * 60 * 1e3).toISOString().split("T")[0],
|
|
167363
|
+
endDate: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
|
|
167364
|
+
allAvailableTopics
|
|
167365
|
+
},
|
|
167366
|
+
apiKey
|
|
167367
|
+
);
|
|
167325
167368
|
if (result.weeklyRoadmap) {
|
|
167326
167369
|
RoadmapService.saveRoadmap(result.weeklyRoadmap);
|
|
167327
|
-
toast2({
|
|
167370
|
+
toast2({
|
|
167371
|
+
title: "L\u1ED9 tr\xECnh M\u1EDBi \u0111\xE3 S\u1EB5n s\xE0ng!",
|
|
167372
|
+
description: "L\u1ED9 tr\xECnh h\u1ECDc t\u1EADp cho tu\u1EA7n n\xE0y \u0111\xE3 \u0111\u01B0\u1EE3c c\u1EADp nh\u1EADt."
|
|
167373
|
+
});
|
|
167328
167374
|
} else {
|
|
167329
167375
|
throw new Error("AI \u0111\xE3 kh\xF4ng tr\u1EA3 v\u1EC1 m\u1ED9t l\u1ED9 tr\xECnh h\u1EE3p l\u1EC7.");
|
|
167330
167376
|
}
|
|
167331
167377
|
} catch (error) {
|
|
167332
167378
|
const msg = error instanceof Error ? error.message : "\u0110\xE3 x\u1EA3y ra l\u1ED7i kh\xF4ng x\xE1c \u0111\u1ECBnh.";
|
|
167333
|
-
toast2({
|
|
167379
|
+
toast2({
|
|
167380
|
+
title: "T\u1EA1o L\u1ED9 tr\xECnh Th\u1EA5t b\u1EA1i",
|
|
167381
|
+
description: msg,
|
|
167382
|
+
variant: "destructive"
|
|
167383
|
+
});
|
|
167334
167384
|
} finally {
|
|
167335
167385
|
setIsGeneratingRoadmap(false);
|
|
167336
167386
|
}
|
|
@@ -167354,14 +167404,26 @@ var PersonalPracticeDashboard = () => {
|
|
|
167354
167404
|
if (!over || active.id === over.id) return;
|
|
167355
167405
|
setDashboardLayout((prev) => {
|
|
167356
167406
|
const newLayout = JSON.parse(JSON.stringify(prev));
|
|
167357
|
-
const activeColKey = newLayout.column1.some(
|
|
167358
|
-
|
|
167407
|
+
const activeColKey = newLayout.column1.some(
|
|
167408
|
+
(c4) => c4.id === active.id
|
|
167409
|
+
) ? "column1" : "column2";
|
|
167410
|
+
const overColKey = newLayout.column1.some(
|
|
167411
|
+
(c4) => c4.id === over.id
|
|
167412
|
+
) ? "column1" : "column2";
|
|
167359
167413
|
const activeCol = newLayout[activeColKey];
|
|
167360
167414
|
const overCol = newLayout[overColKey];
|
|
167361
|
-
const activeIndex = activeCol.findIndex(
|
|
167362
|
-
|
|
167415
|
+
const activeIndex = activeCol.findIndex(
|
|
167416
|
+
(c4) => c4.id === active.id
|
|
167417
|
+
);
|
|
167418
|
+
const overIndex = overCol.findIndex(
|
|
167419
|
+
(c4) => c4.id === over.id
|
|
167420
|
+
);
|
|
167363
167421
|
if (activeColKey === overColKey) {
|
|
167364
|
-
newLayout[activeColKey] = arrayMove(
|
|
167422
|
+
newLayout[activeColKey] = arrayMove(
|
|
167423
|
+
activeCol,
|
|
167424
|
+
activeIndex,
|
|
167425
|
+
overIndex
|
|
167426
|
+
);
|
|
167365
167427
|
} else {
|
|
167366
167428
|
const [movedItem] = activeCol.splice(activeIndex, 1);
|
|
167367
167429
|
overCol.splice(overIndex, 0, movedItem);
|
|
@@ -167369,15 +167431,6 @@ var PersonalPracticeDashboard = () => {
|
|
|
167369
167431
|
return newLayout;
|
|
167370
167432
|
});
|
|
167371
167433
|
};
|
|
167372
|
-
const handleSaveLayout = () => {
|
|
167373
|
-
DashboardLayoutService.saveLayout(dashboardLayout);
|
|
167374
|
-
setIsEditMode(false);
|
|
167375
|
-
toast2({ title: "Layout \u0111\xE3 \u0111\u01B0\u1EE3c l\u01B0u", description: "Dashboard c\u1EE7a b\u1EA1n \u0111\xE3 \u0111\u01B0\u1EE3c c\u1EADp nh\u1EADt." });
|
|
167376
|
-
};
|
|
167377
|
-
const handleCancelEdit = () => {
|
|
167378
|
-
setDashboardLayout(DashboardLayoutService.getLayout());
|
|
167379
|
-
setIsEditMode(false);
|
|
167380
|
-
};
|
|
167381
167434
|
const cardComponents = {
|
|
167382
167435
|
roadmap: /* @__PURE__ */ React163__namespace.default.createElement(RoadmapChecklist, null),
|
|
167383
167436
|
activity: /* @__PURE__ */ React163__namespace.default.createElement(ActivityCalendar, { stats }),
|
|
@@ -167393,7 +167446,179 @@ var PersonalPracticeDashboard = () => {
|
|
|
167393
167446
|
const column2Items = dashboardLayout.column2.map((c4) => c4.id);
|
|
167394
167447
|
const quoteText = isMounted ? motivationalQuote ? `"${motivationalQuote.text}" \u2014 ${motivationalQuote.author}` : t4("dashboard.motivationalQuoteFallback") : '"The best way to predict the future is to create it." \u2014 Peter Drucker';
|
|
167395
167448
|
const welcomeMessage = isMounted ? userName ? t4("dashboard.welcomeMessage", { name: userName }) : t4("dashboard.welcomeMessageGuest") : userName ? `Welcome back, ${userName}!` : "Welcome to your Practice Dashboard";
|
|
167396
|
-
return /* @__PURE__ */ React163__namespace.default.createElement(
|
|
167449
|
+
return /* @__PURE__ */ React163__namespace.default.createElement(
|
|
167450
|
+
DndContext,
|
|
167451
|
+
{
|
|
167452
|
+
sensors,
|
|
167453
|
+
collisionDetection: closestCenter,
|
|
167454
|
+
onDragEnd: handleDragEnd
|
|
167455
|
+
},
|
|
167456
|
+
/* @__PURE__ */ React163__namespace.default.createElement("div", { className: "space-y-8" }, /* @__PURE__ */ React163__namespace.default.createElement(Card, { className: "text-center shadow-xl bg-gradient-to-br from-primary to-primary/80 text-primary-foreground border-none" }, /* @__PURE__ */ React163__namespace.default.createElement(CardHeader, { className: "p-8 relative" }, /* @__PURE__ */ React163__namespace.default.createElement("div", { className: "absolute top-4 right-4" }, settingsPath ? (
|
|
167457
|
+
// If settingsPath is provided, always render a Link regardless of edit mode
|
|
167458
|
+
/* @__PURE__ */ React163__namespace.default.createElement(Button, { asChild: true, variant: "secondary", size: "sm" }, /* @__PURE__ */ React163__namespace.default.createElement(Link3__default.default, { href: settingsPath }, /* @__PURE__ */ React163__namespace.default.createElement(Settings, { className: "mr-2 h-4 w-4" }), /* @__PURE__ */ React163__namespace.default.createElement(
|
|
167459
|
+
ClientTranslation,
|
|
167460
|
+
{
|
|
167461
|
+
tKey: "common.customize",
|
|
167462
|
+
fallback: "Customize"
|
|
167463
|
+
}
|
|
167464
|
+
)))
|
|
167465
|
+
) : (
|
|
167466
|
+
// If no settingsPath, always open the modal regardless of edit mode
|
|
167467
|
+
/* @__PURE__ */ React163__namespace.default.createElement(
|
|
167468
|
+
Button,
|
|
167469
|
+
{
|
|
167470
|
+
variant: "secondary",
|
|
167471
|
+
size: "sm",
|
|
167472
|
+
onClick: () => setIsSettingsModalOpen(true)
|
|
167473
|
+
},
|
|
167474
|
+
/* @__PURE__ */ React163__namespace.default.createElement(Settings, { className: "mr-2 h-4 w-4" }),
|
|
167475
|
+
/* @__PURE__ */ React163__namespace.default.createElement(
|
|
167476
|
+
ClientTranslation,
|
|
167477
|
+
{
|
|
167478
|
+
tKey: "common.customize",
|
|
167479
|
+
fallback: "Customize"
|
|
167480
|
+
}
|
|
167481
|
+
)
|
|
167482
|
+
)
|
|
167483
|
+
)), /* @__PURE__ */ React163__namespace.default.createElement(CardTitle, { className: "text-3xl md:text-4xl font-bold tracking-tight" }, welcomeMessage), /* @__PURE__ */ React163__namespace.default.createElement(CardDescription, { className: "text-lg md:text-xl text-primary-foreground/80 max-w-3xl mx-auto mt-2 h-14 flex items-center justify-center" }, quoteText)), /* @__PURE__ */ React163__namespace.default.createElement(CardContent, { className: "pb-8 flex flex-wrap justify-center items-center gap-4" }, /* @__PURE__ */ React163__namespace.default.createElement(
|
|
167484
|
+
Button,
|
|
167485
|
+
{
|
|
167486
|
+
size: "lg",
|
|
167487
|
+
onClick: () => setIsUploadModalOpen(true),
|
|
167488
|
+
className: "bg-indigo-600 hover:bg-indigo-700 text-white text-base font-semibold px-8 py-6"
|
|
167489
|
+
},
|
|
167490
|
+
/* @__PURE__ */ React163__namespace.default.createElement(FileUp, { className: "mr-2 h-5 w-5" }),
|
|
167491
|
+
/* @__PURE__ */ React163__namespace.default.createElement(
|
|
167492
|
+
ClientTranslation,
|
|
167493
|
+
{
|
|
167494
|
+
tKey: "dashboard.actions.createFromDoc",
|
|
167495
|
+
fallback: "Create Quiz from Document"
|
|
167496
|
+
}
|
|
167497
|
+
)
|
|
167498
|
+
), /* @__PURE__ */ React163__namespace.default.createElement(
|
|
167499
|
+
Button,
|
|
167500
|
+
{
|
|
167501
|
+
size: "lg",
|
|
167502
|
+
onClick: handleStartPractice,
|
|
167503
|
+
className: "bg-amber-400 hover:bg-amber-500 text-amber-950 text-base font-semibold px-8 py-6"
|
|
167504
|
+
},
|
|
167505
|
+
/* @__PURE__ */ React163__namespace.default.createElement(BrainCircuit, { className: "mr-2 h-5 w-5" }),
|
|
167506
|
+
/* @__PURE__ */ React163__namespace.default.createElement(
|
|
167507
|
+
ClientTranslation,
|
|
167508
|
+
{
|
|
167509
|
+
tKey: "dashboard.actions.freestyleTopic",
|
|
167510
|
+
fallback: "Freestyle Topic"
|
|
167511
|
+
}
|
|
167512
|
+
)
|
|
167513
|
+
), /* @__PURE__ */ React163__namespace.default.createElement(AlertDialog2, null, /* @__PURE__ */ React163__namespace.default.createElement(AlertDialogTrigger2, { asChild: true }, /* @__PURE__ */ React163__namespace.default.createElement(
|
|
167514
|
+
Button,
|
|
167515
|
+
{
|
|
167516
|
+
size: "lg",
|
|
167517
|
+
variant: "secondary",
|
|
167518
|
+
className: "px-8 py-6 text-base font-semibold",
|
|
167519
|
+
disabled: isGeneratingRoadmap
|
|
167520
|
+
},
|
|
167521
|
+
/* @__PURE__ */ React163__namespace.default.createElement(Lightbulb, { className: "mr-2 h-5 w-5" }),
|
|
167522
|
+
/* @__PURE__ */ React163__namespace.default.createElement(
|
|
167523
|
+
ClientTranslation,
|
|
167524
|
+
{
|
|
167525
|
+
tKey: "dashboard.actions.suggestRoadmap",
|
|
167526
|
+
fallback: "Suggest Next Week's Roadmap"
|
|
167527
|
+
}
|
|
167528
|
+
)
|
|
167529
|
+
)), /* @__PURE__ */ React163__namespace.default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React163__namespace.default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React163__namespace.default.createElement(AlertDialogTitle2, null, t4("dialogs.confirmRoadmap.title")), /* @__PURE__ */ React163__namespace.default.createElement(AlertDialogDescription2, null, t4(
|
|
167530
|
+
"dialogs.confirmRoadmap.description"
|
|
167531
|
+
))), /* @__PURE__ */ React163__namespace.default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React163__namespace.default.createElement(AlertDialogCancel2, null, t4("common.cancel")), /* @__PURE__ */ React163__namespace.default.createElement(
|
|
167532
|
+
AlertDialogAction2,
|
|
167533
|
+
{
|
|
167534
|
+
onClick: handleGenerateRoadmap
|
|
167535
|
+
},
|
|
167536
|
+
t4("dialogs.confirmRoadmap.action")
|
|
167537
|
+
)))), /* @__PURE__ */ React163__namespace.default.createElement(
|
|
167538
|
+
Button,
|
|
167539
|
+
{
|
|
167540
|
+
size: "lg",
|
|
167541
|
+
onClick: () => setIsAnalysisDialogOpen(true),
|
|
167542
|
+
className: "bg-blue-600 hover:bg-blue-700 text-white text-base font-semibold px-8 py-6"
|
|
167543
|
+
},
|
|
167544
|
+
/* @__PURE__ */ React163__namespace.default.createElement(BarChart4, { className: "mr-2 h-5 w-5" }),
|
|
167545
|
+
/* @__PURE__ */ React163__namespace.default.createElement(
|
|
167546
|
+
ClientTranslation,
|
|
167547
|
+
{
|
|
167548
|
+
tKey: "dashboard.actions.deepAnalysis",
|
|
167549
|
+
fallback: "Deep Analysis"
|
|
167550
|
+
}
|
|
167551
|
+
)
|
|
167552
|
+
))), /* @__PURE__ */ React163__namespace.default.createElement(PerformanceSnapshot, { stats, isLoading }), /* @__PURE__ */ React163__namespace.default.createElement("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-8 items-start" }, /* @__PURE__ */ React163__namespace.default.createElement(
|
|
167553
|
+
SortableContext,
|
|
167554
|
+
{
|
|
167555
|
+
items: column1Items,
|
|
167556
|
+
strategy: verticalListSortingStrategy
|
|
167557
|
+
},
|
|
167558
|
+
/* @__PURE__ */ React163__namespace.default.createElement("div", { className: "flex flex-col gap-8" }, dashboardLayout.column1.map((cardConfig) => /* @__PURE__ */ React163__namespace.default.createElement(
|
|
167559
|
+
DraggableDashboardCard,
|
|
167560
|
+
{
|
|
167561
|
+
key: cardConfig.id,
|
|
167562
|
+
id: cardConfig.id,
|
|
167563
|
+
visible: cardConfig.visible,
|
|
167564
|
+
isEditMode,
|
|
167565
|
+
onToggleVisibility: handleToggleVisibility
|
|
167566
|
+
},
|
|
167567
|
+
cardComponents[cardConfig.id]
|
|
167568
|
+
)))
|
|
167569
|
+
), /* @__PURE__ */ React163__namespace.default.createElement(
|
|
167570
|
+
SortableContext,
|
|
167571
|
+
{
|
|
167572
|
+
items: column2Items,
|
|
167573
|
+
strategy: verticalListSortingStrategy
|
|
167574
|
+
},
|
|
167575
|
+
/* @__PURE__ */ React163__namespace.default.createElement("div", { className: "flex flex-col gap-8" }, dashboardLayout.column2.map((cardConfig) => /* @__PURE__ */ React163__namespace.default.createElement(
|
|
167576
|
+
DraggableDashboardCard,
|
|
167577
|
+
{
|
|
167578
|
+
key: cardConfig.id,
|
|
167579
|
+
id: cardConfig.id,
|
|
167580
|
+
visible: cardConfig.visible,
|
|
167581
|
+
isEditMode,
|
|
167582
|
+
onToggleVisibility: handleToggleVisibility
|
|
167583
|
+
},
|
|
167584
|
+
cardComponents[cardConfig.id]
|
|
167585
|
+
)))
|
|
167586
|
+
)), /* @__PURE__ */ React163__namespace.default.createElement(
|
|
167587
|
+
AnalysisDialog,
|
|
167588
|
+
{
|
|
167589
|
+
isOpen: isAnalysisDialogOpen,
|
|
167590
|
+
onClose: () => setIsAnalysisDialogOpen(false)
|
|
167591
|
+
}
|
|
167592
|
+
), /* @__PURE__ */ React163__namespace.default.createElement("div", { className: "fixed bottom-6 right-6 z-50" }, /* @__PURE__ */ React163__namespace.default.createElement(
|
|
167593
|
+
Button,
|
|
167594
|
+
{
|
|
167595
|
+
size: "icon",
|
|
167596
|
+
className: "rounded-full h-14 w-14 shadow-lg bg-primary hover:bg-primary/90",
|
|
167597
|
+
onClick: () => setIsChatbotOpen(true),
|
|
167598
|
+
"aria-label": "Open AI Tutor Chat"
|
|
167599
|
+
},
|
|
167600
|
+
/* @__PURE__ */ React163__namespace.default.createElement(Bot, { className: "h-7 w-7" })
|
|
167601
|
+
)), /* @__PURE__ */ React163__namespace.default.createElement(
|
|
167602
|
+
ChatbotDialog,
|
|
167603
|
+
{
|
|
167604
|
+
isOpen: isChatbotOpen,
|
|
167605
|
+
onClose: () => setIsChatbotOpen(false)
|
|
167606
|
+
}
|
|
167607
|
+
), /* @__PURE__ */ React163__namespace.default.createElement(
|
|
167608
|
+
UploadResourceModal,
|
|
167609
|
+
{
|
|
167610
|
+
isOpen: isUploadModalOpen,
|
|
167611
|
+
onClose: () => setIsUploadModalOpen(false)
|
|
167612
|
+
}
|
|
167613
|
+
)),
|
|
167614
|
+
!settingsPath && /* @__PURE__ */ React163__namespace.default.createElement(
|
|
167615
|
+
SettingsModal,
|
|
167616
|
+
{
|
|
167617
|
+
isOpen: isSettingsModalOpen,
|
|
167618
|
+
onClose: () => setIsSettingsModalOpen(false)
|
|
167619
|
+
}
|
|
167620
|
+
)
|
|
167621
|
+
);
|
|
167397
167622
|
};
|
|
167398
167623
|
|
|
167399
167624
|
// src/react-ui/components/practice/PracticeModeController.tsx
|
package/dist/react-ui.d.cts
CHANGED
|
@@ -70,7 +70,10 @@ interface QuestionRendererProps {
|
|
|
70
70
|
type ProgrammingQuestionUIRef = BlocklyProgrammingQuestionUIRef | ScratchProgrammingQuestionUIRef;
|
|
71
71
|
declare const QuestionRenderer: React__default.ForwardRefExoticComponent<QuestionRendererProps & React__default.RefAttributes<ProgrammingQuestionUIRef>>;
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
interface PersonalPracticeDashboardProps {
|
|
74
|
+
settingsPath?: string;
|
|
75
|
+
}
|
|
76
|
+
declare const PersonalPracticeDashboard: React__default.FC<PersonalPracticeDashboardProps>;
|
|
74
77
|
|
|
75
78
|
type SettingsTab = 'personal' | 'topics' | 'imageContexts' | 'layout' | 'apiKeys';
|
|
76
79
|
interface SettingsModalProps {
|
package/dist/react-ui.d.ts
CHANGED
|
@@ -70,7 +70,10 @@ interface QuestionRendererProps {
|
|
|
70
70
|
type ProgrammingQuestionUIRef = BlocklyProgrammingQuestionUIRef | ScratchProgrammingQuestionUIRef;
|
|
71
71
|
declare const QuestionRenderer: React__default.ForwardRefExoticComponent<QuestionRendererProps & React__default.RefAttributes<ProgrammingQuestionUIRef>>;
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
interface PersonalPracticeDashboardProps {
|
|
74
|
+
settingsPath?: string;
|
|
75
|
+
}
|
|
76
|
+
declare const PersonalPracticeDashboard: React__default.FC<PersonalPracticeDashboardProps>;
|
|
74
77
|
|
|
75
78
|
type SettingsTab = 'personal' | 'topics' | 'imageContexts' | 'layout' | 'apiKeys';
|
|
76
79
|
interface SettingsModalProps {
|
package/dist/react-ui.mjs
CHANGED
|
@@ -10,6 +10,7 @@ import default3 from 'process';
|
|
|
10
10
|
import { fileURLToPath } from 'url';
|
|
11
11
|
import JSZip from 'jszip';
|
|
12
12
|
import { useRouter } from 'next/navigation';
|
|
13
|
+
import Link3 from 'next/link';
|
|
13
14
|
|
|
14
15
|
var __create = Object.create;
|
|
15
16
|
var __defProp = Object.defineProperty;
|
|
@@ -142523,7 +142524,7 @@ function z29(e3 = x) {
|
|
|
142523
142524
|
}
|
|
142524
142525
|
var B = { tooltip: "core-styles-module_tooltip__3vRRp", fixed: "core-styles-module_fixed__pcSol", arrow: "core-styles-module_arrow__cvMwQ", noArrow: "core-styles-module_noArrow__xock6", clickable: "core-styles-module_clickable__ZuTTB", show: "core-styles-module_show__Nt9eE", closing: "core-styles-module_closing__sGnxF" };
|
|
142525
142526
|
var D2 = { tooltip: "styles-module_tooltip__mnnfp", arrow: "styles-module_arrow__K0L3T", dark: "styles-module_dark__xNqje", light: "styles-module_light__Z6W-X", success: "styles-module_success__A2AKt", warning: "styles-module_warning__SCK0X", error: "styles-module_error__JvumD", info: "styles-module_info__BWdHW" };
|
|
142526
|
-
var q = ({ forwardRef: t4, id: l2, className: i2, classNameArrow: c4, variant: u2 = "dark", anchorId: d, anchorSelect: p2, place: v = "top", offset: m = 10, events: h3 = ["hover"], openOnClick: w2 = false, positionStrategy: b2 = "absolute", middlewares: S3, wrapper: g, delayShow: A3 = 0, delayHide: O2 = 0, float: T3 = false, hidden: x3 = false, noArrow: N2 = false, clickable: $3 = false, closeOnEsc: I = false, closeOnScroll: j = false, closeOnResize: q2 = false, openEvents: H2, closeEvents: M2, globalCloseEvents: W, imperativeModeOnly: P2, style: V, position: F, afterShow: K, afterHide: U2, disableTooltip:
|
|
142527
|
+
var q = ({ forwardRef: t4, id: l2, className: i2, classNameArrow: c4, variant: u2 = "dark", anchorId: d, anchorSelect: p2, place: v = "top", offset: m = 10, events: h3 = ["hover"], openOnClick: w2 = false, positionStrategy: b2 = "absolute", middlewares: S3, wrapper: g, delayShow: A3 = 0, delayHide: O2 = 0, float: T3 = false, hidden: x3 = false, noArrow: N2 = false, clickable: $3 = false, closeOnEsc: I = false, closeOnScroll: j = false, closeOnResize: q2 = false, openEvents: H2, closeEvents: M2, globalCloseEvents: W, imperativeModeOnly: P2, style: V, position: F, afterShow: K, afterHide: U2, disableTooltip: X3, content: Y, contentWrapperRef: G, isOpen: Z2, defaultIsOpen: J = false, setIsOpen: Q, activeAnchor: ee, setActiveAnchor: te, border: oe, opacity: le, arrowColor: re3, arrowSize: ne = 8, role: ie3 = "tooltip" }) => {
|
|
142527
142528
|
var ce;
|
|
142528
142529
|
const se = useRef(null), ae = useRef(null), ue = useRef(null), de = useRef(null), pe = useRef(null), [ve, me] = useState({ tooltipStyles: {}, tooltipArrowStyles: {}, place: v }), [fe, ye] = useState(false), [he, we] = useState(false), [be, Se] = useState(null), ge = useRef(false), Ee = useRef(null), { anchorRefs: Ae, setActiveAnchor: _e } = z29(l2), Oe = useRef(false), [ke, Te] = useState([]), Le = useRef(false), Ce = w2 || h3.includes("click"), Re = Ce || (null == H2 ? void 0 : H2.click) || (null == H2 ? void 0 : H2.dblclick) || (null == H2 ? void 0 : H2.mousedown), xe = H2 ? { ...H2 } : { mouseover: true, focus: true, mouseenter: false, click: false, dblclick: false, mousedown: false };
|
|
142529
142530
|
!H2 && Ce && Object.assign(xe, { mouseenter: false, focus: false, mouseover: false, click: true });
|
|
@@ -142611,10 +142612,10 @@ var q = ({ forwardRef: t4, id: l2, className: i2, classNameArrow: c4, variant: u
|
|
|
142611
142612
|
var e3, t5;
|
|
142612
142613
|
const o2 = new Set(Ae);
|
|
142613
142614
|
ke.forEach((e4) => {
|
|
142614
|
-
(null ==
|
|
142615
|
+
(null == X3 ? void 0 : X3(e4)) || o2.add({ current: e4 });
|
|
142615
142616
|
});
|
|
142616
142617
|
const l3 = document.querySelector(`[id='${d}']`);
|
|
142617
|
-
l3 && !(null ==
|
|
142618
|
+
l3 && !(null == X3 ? void 0 : X3(l3)) && o2.add({ current: l3 });
|
|
142618
142619
|
const r4 = () => {
|
|
142619
142620
|
Ie(false);
|
|
142620
142621
|
}, n2 = L2(ee), i3 = L2(se.current);
|
|
@@ -142730,7 +142731,7 @@ var q = ({ forwardRef: t4, id: l2, className: i2, classNameArrow: c4, variant: u
|
|
|
142730
142731
|
}, style: { ...V, ...ve.tooltipStyles, opacity: void 0 !== le && Ye ? le : void 0 }, ref: se }, Xe, React163__default.createElement(g, { className: (0, import_classnames.default)("react-tooltip-arrow", B.arrow, D2.arrow, c4, N2 && B.noArrow), style: { ...ve.tooltipArrowStyles, background: re3 ? `linear-gradient(to right bottom, transparent 50%, ${re3} 50%)` : void 0, "--rt-arrow-size": `${ne}px` }, ref: ae })) : null;
|
|
142731
142732
|
};
|
|
142732
142733
|
var H = ({ content: t4 }) => React163__default.createElement("span", { dangerouslySetInnerHTML: { __html: t4 } });
|
|
142733
|
-
var M = React163__default.forwardRef(({ id: t4, anchorId: l2, anchorSelect: n2, content: i2, html: c4, render: a4, className: u2, classNameArrow: d, variant: p2 = "dark", place: v = "top", offset: m = 10, wrapper: f = "div", children: h3 = null, events: w2 = ["hover"], openOnClick: b2 = false, positionStrategy: S3 = "absolute", middlewares: g, delayShow: E2 = 0, delayHide: _2 = 0, float: O2 = false, hidden: k3 = false, noArrow: T3 = false, clickable: L3 = false, closeOnEsc: C3 = false, closeOnScroll: R3 = false, closeOnResize: x3 = false, openEvents: N2, closeEvents: $3, globalCloseEvents: I, imperativeModeOnly: j = false, style: B2, position: D3, isOpen: M2, defaultIsOpen: W = false, disableStyleInjection: P2 = false, border: V, opacity: F, arrowColor: K, arrowSize: U2, setIsOpen:
|
|
142734
|
+
var M = React163__default.forwardRef(({ id: t4, anchorId: l2, anchorSelect: n2, content: i2, html: c4, render: a4, className: u2, classNameArrow: d, variant: p2 = "dark", place: v = "top", offset: m = 10, wrapper: f = "div", children: h3 = null, events: w2 = ["hover"], openOnClick: b2 = false, positionStrategy: S3 = "absolute", middlewares: g, delayShow: E2 = 0, delayHide: _2 = 0, float: O2 = false, hidden: k3 = false, noArrow: T3 = false, clickable: L3 = false, closeOnEsc: C3 = false, closeOnScroll: R3 = false, closeOnResize: x3 = false, openEvents: N2, closeEvents: $3, globalCloseEvents: I, imperativeModeOnly: j = false, style: B2, position: D3, isOpen: M2, defaultIsOpen: W = false, disableStyleInjection: P2 = false, border: V, opacity: F, arrowColor: K, arrowSize: U2, setIsOpen: X3, afterShow: Y, afterHide: G, disableTooltip: Z2, role: J = "tooltip" }, Q) => {
|
|
142734
142735
|
const [ee, te] = useState(i2), [oe, le] = useState(c4), [re3, ne] = useState(v), [ie3, ce] = useState(p2), [se, ae] = useState(m), [ue, de] = useState(E2), [pe, ve] = useState(_2), [me, fe] = useState(O2), [ye, he] = useState(k3), [we, be] = useState(f), [Se, ge] = useState(w2), [Ee, Ae] = useState(S3), [_e, Oe] = useState(null), [ke, Te] = useState(null), Le = useRef(P2), { anchorRefs: Ce, activeAnchor: Re } = z29(t4), xe = (e3) => null == e3 ? void 0 : e3.getAttributeNames().reduce((t5, o2) => {
|
|
142735
142736
|
var l3;
|
|
142736
142737
|
if (o2.startsWith("data-tooltip-")) {
|
|
@@ -142837,7 +142838,7 @@ var M = React163__default.forwardRef(({ id: t4, anchorId: l2, anchorSelect: n2,
|
|
|
142837
142838
|
$e = t5 ? React163__default.createElement("div", { ref: Ie, className: "react-tooltip-content-wrapper" }, t5) : null;
|
|
142838
142839
|
} else ee && ($e = ee);
|
|
142839
142840
|
oe && ($e = React163__default.createElement(H, { content: oe }));
|
|
142840
|
-
const ze = { forwardRef: Q, id: t4, anchorId: l2, anchorSelect: n2, className: (0, import_classnames.default)(u2, _e), classNameArrow: d, content: $e, contentWrapperRef: Ie, place: re3, variant: ie3, offset: se, wrapper: we, events: Se, openOnClick: b2, positionStrategy: Ee, middlewares: g, delayShow: ue, delayHide: pe, float: me, hidden: ye, noArrow: T3, clickable: L3, closeOnEsc: C3, closeOnScroll: R3, closeOnResize: x3, openEvents: N2, closeEvents: $3, globalCloseEvents: I, imperativeModeOnly: j, style: B2, position: D3, isOpen: M2, defaultIsOpen: W, border: V, opacity: F, arrowColor: K, arrowSize: U2, setIsOpen:
|
|
142841
|
+
const ze = { forwardRef: Q, id: t4, anchorId: l2, anchorSelect: n2, className: (0, import_classnames.default)(u2, _e), classNameArrow: d, content: $e, contentWrapperRef: Ie, place: re3, variant: ie3, offset: se, wrapper: we, events: Se, openOnClick: b2, positionStrategy: Ee, middlewares: g, delayShow: ue, delayHide: pe, float: me, hidden: ye, noArrow: T3, clickable: L3, closeOnEsc: C3, closeOnScroll: R3, closeOnResize: x3, openEvents: N2, closeEvents: $3, globalCloseEvents: I, imperativeModeOnly: j, style: B2, position: D3, isOpen: M2, defaultIsOpen: W, border: V, opacity: F, arrowColor: K, arrowSize: U2, setIsOpen: X3, afterShow: Y, afterHide: G, disableTooltip: Z2, activeAnchor: ke, setActiveAnchor: (e3) => Te(e3), role: J };
|
|
142841
142842
|
return React163__default.createElement(q, { ...ze });
|
|
142842
142843
|
});
|
|
142843
142844
|
"undefined" != typeof window && window.addEventListener("react-tooltip-inject-styles", (e3) => {
|
|
@@ -167197,7 +167198,7 @@ var ClientTranslation = ({ tKey, options, fallback: fallback2 }) => {
|
|
|
167197
167198
|
};
|
|
167198
167199
|
|
|
167199
167200
|
// src/react-ui/components/app/PersonalPracticeDashboard.tsx
|
|
167200
|
-
var PersonalPracticeDashboard = () => {
|
|
167201
|
+
var PersonalPracticeDashboard = ({ settingsPath }) => {
|
|
167201
167202
|
const router = useRouter();
|
|
167202
167203
|
const { toast: toast2 } = useToast();
|
|
167203
167204
|
const { t: t4, i18n } = useTranslation();
|
|
@@ -167214,7 +167215,10 @@ var PersonalPracticeDashboard = () => {
|
|
|
167214
167215
|
const [isChatbotOpen, setIsChatbotOpen] = useState(false);
|
|
167215
167216
|
const [isUploadModalOpen, setIsUploadModalOpen] = useState(false);
|
|
167216
167217
|
const [isEditMode, setIsEditMode] = useState(false);
|
|
167217
|
-
const [dashboardLayout, setDashboardLayout] = useState(
|
|
167218
|
+
const [dashboardLayout, setDashboardLayout] = useState(
|
|
167219
|
+
DashboardLayoutService.getLayout()
|
|
167220
|
+
);
|
|
167221
|
+
const [isSettingsModalOpen, setIsSettingsModalOpen] = useState(false);
|
|
167218
167222
|
const loadDashboardData = useCallback(() => {
|
|
167219
167223
|
setIsLoading(true);
|
|
167220
167224
|
setDashboardLayout(DashboardLayoutService.getLayout());
|
|
@@ -167222,9 +167226,17 @@ var PersonalPracticeDashboard = () => {
|
|
|
167222
167226
|
const practiceStats = PracticeHistoryService.getPracticeStats();
|
|
167223
167227
|
const name3 = UserConfigService.getFullName();
|
|
167224
167228
|
if (practiceStats && practiceHistory.length > 0) {
|
|
167225
|
-
const newlyUnlocked = AchievementService.checkAndUnlockAchievements(
|
|
167229
|
+
const newlyUnlocked = AchievementService.checkAndUnlockAchievements(
|
|
167230
|
+
practiceHistory,
|
|
167231
|
+
practiceStats
|
|
167232
|
+
);
|
|
167226
167233
|
if (newlyUnlocked.length > 0) {
|
|
167227
|
-
newlyUnlocked.forEach(
|
|
167234
|
+
newlyUnlocked.forEach(
|
|
167235
|
+
(ach) => toast2({
|
|
167236
|
+
title: "\u{1F3C6} Th\xE0nh t\xEDch M\u1EDBi!",
|
|
167237
|
+
description: `B\u1EA1n \u0111\xE3 m\u1EDF kh\xF3a: ${t4(ach.nameKey)}`
|
|
167238
|
+
})
|
|
167239
|
+
);
|
|
167228
167240
|
}
|
|
167229
167241
|
}
|
|
167230
167242
|
const achievementsWithStatus = AchievementService.getAllAchievementsWithStatus();
|
|
@@ -167246,32 +167258,55 @@ var PersonalPracticeDashboard = () => {
|
|
|
167246
167258
|
const apiKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
|
|
167247
167259
|
if (!apiKey || !stats) return;
|
|
167248
167260
|
try {
|
|
167249
|
-
const weakestTopic = stats.performanceByTopic.sort(
|
|
167250
|
-
|
|
167251
|
-
|
|
167252
|
-
|
|
167253
|
-
|
|
167254
|
-
|
|
167255
|
-
|
|
167261
|
+
const weakestTopic = stats.performanceByTopic.sort(
|
|
167262
|
+
(a4, b2) => a4.averageScore - b2.averageScore
|
|
167263
|
+
)[0]?.name;
|
|
167264
|
+
const aiQuote = await generateMotivationalQuote(
|
|
167265
|
+
{
|
|
167266
|
+
language: i18n.language === "vi" ? "Vietnamese" : "English",
|
|
167267
|
+
userName: UserConfigService.getFullName() || void 0,
|
|
167268
|
+
currentStreak: stats.currentStreak,
|
|
167269
|
+
weakestTopic
|
|
167270
|
+
},
|
|
167271
|
+
apiKey
|
|
167272
|
+
);
|
|
167256
167273
|
if (aiQuote) setMotivationalQuote(aiQuote);
|
|
167257
167274
|
} catch (e3) {
|
|
167258
167275
|
console.warn("Could not fetch AI-powered quote.", e3);
|
|
167259
167276
|
}
|
|
167260
167277
|
};
|
|
167261
167278
|
if (stats) fetchAIQuote();
|
|
167262
|
-
const intervalId = setInterval(
|
|
167279
|
+
const intervalId = setInterval(
|
|
167280
|
+
() => setMotivationalQuote(QuoteService.getRandomQuote()),
|
|
167281
|
+
10 * 60 * 1e3
|
|
167282
|
+
);
|
|
167263
167283
|
return () => clearInterval(intervalId);
|
|
167264
167284
|
}, [stats, i18n.language]);
|
|
167265
167285
|
const historySummaryForTable = useMemo(() => {
|
|
167266
|
-
return history2.map((session) => ({
|
|
167286
|
+
return history2.map((session) => ({
|
|
167287
|
+
...session.summary,
|
|
167288
|
+
id: session.id,
|
|
167289
|
+
timestamp: session.timestamp,
|
|
167290
|
+
quizTitle: session.quizConfig.title
|
|
167291
|
+
}));
|
|
167267
167292
|
}, [history2]);
|
|
167268
|
-
const handleStartPractice = useCallback(
|
|
167293
|
+
const handleStartPractice = useCallback(
|
|
167294
|
+
() => router.push("/practice"),
|
|
167295
|
+
[router]
|
|
167296
|
+
);
|
|
167269
167297
|
const handleGenerateRoadmap = useCallback(async () => {
|
|
167270
167298
|
setIsGeneratingRoadmap(true);
|
|
167271
|
-
toast2({
|
|
167299
|
+
toast2({
|
|
167300
|
+
title: "AI Tutor \u0111ang suy ngh\u0129...",
|
|
167301
|
+
description: "\u0110ang t\u1EA1o l\u1ED9 tr\xECnh h\u1ECDc t\u1EADp \u0111\u01B0\u1EE3c c\xE1 nh\xE2n h\xF3a cho b\u1EA1n."
|
|
167302
|
+
});
|
|
167272
167303
|
const apiKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
|
|
167273
167304
|
if (!apiKey) {
|
|
167274
|
-
toast2({
|
|
167305
|
+
toast2({
|
|
167306
|
+
title: "API Key Missing",
|
|
167307
|
+
description: "Vui l\xF2ng c\u1EA5u h\xECnh Gemini API Key trong C\xE0i \u0111\u1EB7t.",
|
|
167308
|
+
variant: "destructive"
|
|
167309
|
+
});
|
|
167275
167310
|
setIsGeneratingRoadmap(false);
|
|
167276
167311
|
return;
|
|
167277
167312
|
}
|
|
@@ -167283,28 +167318,42 @@ var PersonalPracticeDashboard = () => {
|
|
|
167283
167318
|
topic: lo.topic
|
|
167284
167319
|
}));
|
|
167285
167320
|
if (allAvailableTopics.length === 0) {
|
|
167286
|
-
throw new Error(
|
|
167321
|
+
throw new Error(
|
|
167322
|
+
"No topic data found. Please import curriculum data in Settings first."
|
|
167323
|
+
);
|
|
167287
167324
|
}
|
|
167288
|
-
const result = await generateLearningAnalysis(
|
|
167289
|
-
|
|
167290
|
-
|
|
167291
|
-
|
|
167292
|
-
|
|
167293
|
-
|
|
167294
|
-
|
|
167295
|
-
|
|
167296
|
-
|
|
167297
|
-
|
|
167298
|
-
|
|
167325
|
+
const result = await generateLearningAnalysis(
|
|
167326
|
+
{
|
|
167327
|
+
language: i18n.language === "vi" ? "Vietnamese" : "English",
|
|
167328
|
+
userName: UserConfigService.getFullName() || void 0,
|
|
167329
|
+
weeklyGoal: UserConfigService.getWeeklyGoal() || void 0,
|
|
167330
|
+
unlockedAchievements: AchievementService.getAllAchievementsWithStatus().filter(
|
|
167331
|
+
(a4) => a4.unlockedAt
|
|
167332
|
+
),
|
|
167333
|
+
stats: PracticeHistoryService.getPracticeStats(),
|
|
167334
|
+
history: PracticeHistoryService.getPracticeHistory(),
|
|
167335
|
+
startDate: new Date(Date.now() - 7 * 24 * 60 * 60 * 1e3).toISOString().split("T")[0],
|
|
167336
|
+
endDate: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
|
|
167337
|
+
allAvailableTopics
|
|
167338
|
+
},
|
|
167339
|
+
apiKey
|
|
167340
|
+
);
|
|
167299
167341
|
if (result.weeklyRoadmap) {
|
|
167300
167342
|
RoadmapService.saveRoadmap(result.weeklyRoadmap);
|
|
167301
|
-
toast2({
|
|
167343
|
+
toast2({
|
|
167344
|
+
title: "L\u1ED9 tr\xECnh M\u1EDBi \u0111\xE3 S\u1EB5n s\xE0ng!",
|
|
167345
|
+
description: "L\u1ED9 tr\xECnh h\u1ECDc t\u1EADp cho tu\u1EA7n n\xE0y \u0111\xE3 \u0111\u01B0\u1EE3c c\u1EADp nh\u1EADt."
|
|
167346
|
+
});
|
|
167302
167347
|
} else {
|
|
167303
167348
|
throw new Error("AI \u0111\xE3 kh\xF4ng tr\u1EA3 v\u1EC1 m\u1ED9t l\u1ED9 tr\xECnh h\u1EE3p l\u1EC7.");
|
|
167304
167349
|
}
|
|
167305
167350
|
} catch (error) {
|
|
167306
167351
|
const msg = error instanceof Error ? error.message : "\u0110\xE3 x\u1EA3y ra l\u1ED7i kh\xF4ng x\xE1c \u0111\u1ECBnh.";
|
|
167307
|
-
toast2({
|
|
167352
|
+
toast2({
|
|
167353
|
+
title: "T\u1EA1o L\u1ED9 tr\xECnh Th\u1EA5t b\u1EA1i",
|
|
167354
|
+
description: msg,
|
|
167355
|
+
variant: "destructive"
|
|
167356
|
+
});
|
|
167308
167357
|
} finally {
|
|
167309
167358
|
setIsGeneratingRoadmap(false);
|
|
167310
167359
|
}
|
|
@@ -167328,14 +167377,26 @@ var PersonalPracticeDashboard = () => {
|
|
|
167328
167377
|
if (!over || active.id === over.id) return;
|
|
167329
167378
|
setDashboardLayout((prev) => {
|
|
167330
167379
|
const newLayout = JSON.parse(JSON.stringify(prev));
|
|
167331
|
-
const activeColKey = newLayout.column1.some(
|
|
167332
|
-
|
|
167380
|
+
const activeColKey = newLayout.column1.some(
|
|
167381
|
+
(c4) => c4.id === active.id
|
|
167382
|
+
) ? "column1" : "column2";
|
|
167383
|
+
const overColKey = newLayout.column1.some(
|
|
167384
|
+
(c4) => c4.id === over.id
|
|
167385
|
+
) ? "column1" : "column2";
|
|
167333
167386
|
const activeCol = newLayout[activeColKey];
|
|
167334
167387
|
const overCol = newLayout[overColKey];
|
|
167335
|
-
const activeIndex = activeCol.findIndex(
|
|
167336
|
-
|
|
167388
|
+
const activeIndex = activeCol.findIndex(
|
|
167389
|
+
(c4) => c4.id === active.id
|
|
167390
|
+
);
|
|
167391
|
+
const overIndex = overCol.findIndex(
|
|
167392
|
+
(c4) => c4.id === over.id
|
|
167393
|
+
);
|
|
167337
167394
|
if (activeColKey === overColKey) {
|
|
167338
|
-
newLayout[activeColKey] = arrayMove(
|
|
167395
|
+
newLayout[activeColKey] = arrayMove(
|
|
167396
|
+
activeCol,
|
|
167397
|
+
activeIndex,
|
|
167398
|
+
overIndex
|
|
167399
|
+
);
|
|
167339
167400
|
} else {
|
|
167340
167401
|
const [movedItem] = activeCol.splice(activeIndex, 1);
|
|
167341
167402
|
overCol.splice(overIndex, 0, movedItem);
|
|
@@ -167343,15 +167404,6 @@ var PersonalPracticeDashboard = () => {
|
|
|
167343
167404
|
return newLayout;
|
|
167344
167405
|
});
|
|
167345
167406
|
};
|
|
167346
|
-
const handleSaveLayout = () => {
|
|
167347
|
-
DashboardLayoutService.saveLayout(dashboardLayout);
|
|
167348
|
-
setIsEditMode(false);
|
|
167349
|
-
toast2({ title: "Layout \u0111\xE3 \u0111\u01B0\u1EE3c l\u01B0u", description: "Dashboard c\u1EE7a b\u1EA1n \u0111\xE3 \u0111\u01B0\u1EE3c c\u1EADp nh\u1EADt." });
|
|
167350
|
-
};
|
|
167351
|
-
const handleCancelEdit = () => {
|
|
167352
|
-
setDashboardLayout(DashboardLayoutService.getLayout());
|
|
167353
|
-
setIsEditMode(false);
|
|
167354
|
-
};
|
|
167355
167407
|
const cardComponents = {
|
|
167356
167408
|
roadmap: /* @__PURE__ */ React163__default.createElement(RoadmapChecklist, null),
|
|
167357
167409
|
activity: /* @__PURE__ */ React163__default.createElement(ActivityCalendar, { stats }),
|
|
@@ -167367,7 +167419,179 @@ var PersonalPracticeDashboard = () => {
|
|
|
167367
167419
|
const column2Items = dashboardLayout.column2.map((c4) => c4.id);
|
|
167368
167420
|
const quoteText = isMounted ? motivationalQuote ? `"${motivationalQuote.text}" \u2014 ${motivationalQuote.author}` : t4("dashboard.motivationalQuoteFallback") : '"The best way to predict the future is to create it." \u2014 Peter Drucker';
|
|
167369
167421
|
const welcomeMessage = isMounted ? userName ? t4("dashboard.welcomeMessage", { name: userName }) : t4("dashboard.welcomeMessageGuest") : userName ? `Welcome back, ${userName}!` : "Welcome to your Practice Dashboard";
|
|
167370
|
-
return /* @__PURE__ */ React163__default.createElement(
|
|
167422
|
+
return /* @__PURE__ */ React163__default.createElement(
|
|
167423
|
+
DndContext,
|
|
167424
|
+
{
|
|
167425
|
+
sensors,
|
|
167426
|
+
collisionDetection: closestCenter,
|
|
167427
|
+
onDragEnd: handleDragEnd
|
|
167428
|
+
},
|
|
167429
|
+
/* @__PURE__ */ React163__default.createElement("div", { className: "space-y-8" }, /* @__PURE__ */ React163__default.createElement(Card, { className: "text-center shadow-xl bg-gradient-to-br from-primary to-primary/80 text-primary-foreground border-none" }, /* @__PURE__ */ React163__default.createElement(CardHeader, { className: "p-8 relative" }, /* @__PURE__ */ React163__default.createElement("div", { className: "absolute top-4 right-4" }, settingsPath ? (
|
|
167430
|
+
// If settingsPath is provided, always render a Link regardless of edit mode
|
|
167431
|
+
/* @__PURE__ */ React163__default.createElement(Button, { asChild: true, variant: "secondary", size: "sm" }, /* @__PURE__ */ React163__default.createElement(Link3, { href: settingsPath }, /* @__PURE__ */ React163__default.createElement(Settings, { className: "mr-2 h-4 w-4" }), /* @__PURE__ */ React163__default.createElement(
|
|
167432
|
+
ClientTranslation,
|
|
167433
|
+
{
|
|
167434
|
+
tKey: "common.customize",
|
|
167435
|
+
fallback: "Customize"
|
|
167436
|
+
}
|
|
167437
|
+
)))
|
|
167438
|
+
) : (
|
|
167439
|
+
// If no settingsPath, always open the modal regardless of edit mode
|
|
167440
|
+
/* @__PURE__ */ React163__default.createElement(
|
|
167441
|
+
Button,
|
|
167442
|
+
{
|
|
167443
|
+
variant: "secondary",
|
|
167444
|
+
size: "sm",
|
|
167445
|
+
onClick: () => setIsSettingsModalOpen(true)
|
|
167446
|
+
},
|
|
167447
|
+
/* @__PURE__ */ React163__default.createElement(Settings, { className: "mr-2 h-4 w-4" }),
|
|
167448
|
+
/* @__PURE__ */ React163__default.createElement(
|
|
167449
|
+
ClientTranslation,
|
|
167450
|
+
{
|
|
167451
|
+
tKey: "common.customize",
|
|
167452
|
+
fallback: "Customize"
|
|
167453
|
+
}
|
|
167454
|
+
)
|
|
167455
|
+
)
|
|
167456
|
+
)), /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "text-3xl md:text-4xl font-bold tracking-tight" }, welcomeMessage), /* @__PURE__ */ React163__default.createElement(CardDescription, { className: "text-lg md:text-xl text-primary-foreground/80 max-w-3xl mx-auto mt-2 h-14 flex items-center justify-center" }, quoteText)), /* @__PURE__ */ React163__default.createElement(CardContent, { className: "pb-8 flex flex-wrap justify-center items-center gap-4" }, /* @__PURE__ */ React163__default.createElement(
|
|
167457
|
+
Button,
|
|
167458
|
+
{
|
|
167459
|
+
size: "lg",
|
|
167460
|
+
onClick: () => setIsUploadModalOpen(true),
|
|
167461
|
+
className: "bg-indigo-600 hover:bg-indigo-700 text-white text-base font-semibold px-8 py-6"
|
|
167462
|
+
},
|
|
167463
|
+
/* @__PURE__ */ React163__default.createElement(FileUp, { className: "mr-2 h-5 w-5" }),
|
|
167464
|
+
/* @__PURE__ */ React163__default.createElement(
|
|
167465
|
+
ClientTranslation,
|
|
167466
|
+
{
|
|
167467
|
+
tKey: "dashboard.actions.createFromDoc",
|
|
167468
|
+
fallback: "Create Quiz from Document"
|
|
167469
|
+
}
|
|
167470
|
+
)
|
|
167471
|
+
), /* @__PURE__ */ React163__default.createElement(
|
|
167472
|
+
Button,
|
|
167473
|
+
{
|
|
167474
|
+
size: "lg",
|
|
167475
|
+
onClick: handleStartPractice,
|
|
167476
|
+
className: "bg-amber-400 hover:bg-amber-500 text-amber-950 text-base font-semibold px-8 py-6"
|
|
167477
|
+
},
|
|
167478
|
+
/* @__PURE__ */ React163__default.createElement(BrainCircuit, { className: "mr-2 h-5 w-5" }),
|
|
167479
|
+
/* @__PURE__ */ React163__default.createElement(
|
|
167480
|
+
ClientTranslation,
|
|
167481
|
+
{
|
|
167482
|
+
tKey: "dashboard.actions.freestyleTopic",
|
|
167483
|
+
fallback: "Freestyle Topic"
|
|
167484
|
+
}
|
|
167485
|
+
)
|
|
167486
|
+
), /* @__PURE__ */ React163__default.createElement(AlertDialog2, null, /* @__PURE__ */ React163__default.createElement(AlertDialogTrigger2, { asChild: true }, /* @__PURE__ */ React163__default.createElement(
|
|
167487
|
+
Button,
|
|
167488
|
+
{
|
|
167489
|
+
size: "lg",
|
|
167490
|
+
variant: "secondary",
|
|
167491
|
+
className: "px-8 py-6 text-base font-semibold",
|
|
167492
|
+
disabled: isGeneratingRoadmap
|
|
167493
|
+
},
|
|
167494
|
+
/* @__PURE__ */ React163__default.createElement(Lightbulb, { className: "mr-2 h-5 w-5" }),
|
|
167495
|
+
/* @__PURE__ */ React163__default.createElement(
|
|
167496
|
+
ClientTranslation,
|
|
167497
|
+
{
|
|
167498
|
+
tKey: "dashboard.actions.suggestRoadmap",
|
|
167499
|
+
fallback: "Suggest Next Week's Roadmap"
|
|
167500
|
+
}
|
|
167501
|
+
)
|
|
167502
|
+
)), /* @__PURE__ */ React163__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React163__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React163__default.createElement(AlertDialogTitle2, null, t4("dialogs.confirmRoadmap.title")), /* @__PURE__ */ React163__default.createElement(AlertDialogDescription2, null, t4(
|
|
167503
|
+
"dialogs.confirmRoadmap.description"
|
|
167504
|
+
))), /* @__PURE__ */ React163__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React163__default.createElement(AlertDialogCancel2, null, t4("common.cancel")), /* @__PURE__ */ React163__default.createElement(
|
|
167505
|
+
AlertDialogAction2,
|
|
167506
|
+
{
|
|
167507
|
+
onClick: handleGenerateRoadmap
|
|
167508
|
+
},
|
|
167509
|
+
t4("dialogs.confirmRoadmap.action")
|
|
167510
|
+
)))), /* @__PURE__ */ React163__default.createElement(
|
|
167511
|
+
Button,
|
|
167512
|
+
{
|
|
167513
|
+
size: "lg",
|
|
167514
|
+
onClick: () => setIsAnalysisDialogOpen(true),
|
|
167515
|
+
className: "bg-blue-600 hover:bg-blue-700 text-white text-base font-semibold px-8 py-6"
|
|
167516
|
+
},
|
|
167517
|
+
/* @__PURE__ */ React163__default.createElement(BarChart4, { className: "mr-2 h-5 w-5" }),
|
|
167518
|
+
/* @__PURE__ */ React163__default.createElement(
|
|
167519
|
+
ClientTranslation,
|
|
167520
|
+
{
|
|
167521
|
+
tKey: "dashboard.actions.deepAnalysis",
|
|
167522
|
+
fallback: "Deep Analysis"
|
|
167523
|
+
}
|
|
167524
|
+
)
|
|
167525
|
+
))), /* @__PURE__ */ React163__default.createElement(PerformanceSnapshot, { stats, isLoading }), /* @__PURE__ */ React163__default.createElement("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-8 items-start" }, /* @__PURE__ */ React163__default.createElement(
|
|
167526
|
+
SortableContext,
|
|
167527
|
+
{
|
|
167528
|
+
items: column1Items,
|
|
167529
|
+
strategy: verticalListSortingStrategy
|
|
167530
|
+
},
|
|
167531
|
+
/* @__PURE__ */ React163__default.createElement("div", { className: "flex flex-col gap-8" }, dashboardLayout.column1.map((cardConfig) => /* @__PURE__ */ React163__default.createElement(
|
|
167532
|
+
DraggableDashboardCard,
|
|
167533
|
+
{
|
|
167534
|
+
key: cardConfig.id,
|
|
167535
|
+
id: cardConfig.id,
|
|
167536
|
+
visible: cardConfig.visible,
|
|
167537
|
+
isEditMode,
|
|
167538
|
+
onToggleVisibility: handleToggleVisibility
|
|
167539
|
+
},
|
|
167540
|
+
cardComponents[cardConfig.id]
|
|
167541
|
+
)))
|
|
167542
|
+
), /* @__PURE__ */ React163__default.createElement(
|
|
167543
|
+
SortableContext,
|
|
167544
|
+
{
|
|
167545
|
+
items: column2Items,
|
|
167546
|
+
strategy: verticalListSortingStrategy
|
|
167547
|
+
},
|
|
167548
|
+
/* @__PURE__ */ React163__default.createElement("div", { className: "flex flex-col gap-8" }, dashboardLayout.column2.map((cardConfig) => /* @__PURE__ */ React163__default.createElement(
|
|
167549
|
+
DraggableDashboardCard,
|
|
167550
|
+
{
|
|
167551
|
+
key: cardConfig.id,
|
|
167552
|
+
id: cardConfig.id,
|
|
167553
|
+
visible: cardConfig.visible,
|
|
167554
|
+
isEditMode,
|
|
167555
|
+
onToggleVisibility: handleToggleVisibility
|
|
167556
|
+
},
|
|
167557
|
+
cardComponents[cardConfig.id]
|
|
167558
|
+
)))
|
|
167559
|
+
)), /* @__PURE__ */ React163__default.createElement(
|
|
167560
|
+
AnalysisDialog,
|
|
167561
|
+
{
|
|
167562
|
+
isOpen: isAnalysisDialogOpen,
|
|
167563
|
+
onClose: () => setIsAnalysisDialogOpen(false)
|
|
167564
|
+
}
|
|
167565
|
+
), /* @__PURE__ */ React163__default.createElement("div", { className: "fixed bottom-6 right-6 z-50" }, /* @__PURE__ */ React163__default.createElement(
|
|
167566
|
+
Button,
|
|
167567
|
+
{
|
|
167568
|
+
size: "icon",
|
|
167569
|
+
className: "rounded-full h-14 w-14 shadow-lg bg-primary hover:bg-primary/90",
|
|
167570
|
+
onClick: () => setIsChatbotOpen(true),
|
|
167571
|
+
"aria-label": "Open AI Tutor Chat"
|
|
167572
|
+
},
|
|
167573
|
+
/* @__PURE__ */ React163__default.createElement(Bot, { className: "h-7 w-7" })
|
|
167574
|
+
)), /* @__PURE__ */ React163__default.createElement(
|
|
167575
|
+
ChatbotDialog,
|
|
167576
|
+
{
|
|
167577
|
+
isOpen: isChatbotOpen,
|
|
167578
|
+
onClose: () => setIsChatbotOpen(false)
|
|
167579
|
+
}
|
|
167580
|
+
), /* @__PURE__ */ React163__default.createElement(
|
|
167581
|
+
UploadResourceModal,
|
|
167582
|
+
{
|
|
167583
|
+
isOpen: isUploadModalOpen,
|
|
167584
|
+
onClose: () => setIsUploadModalOpen(false)
|
|
167585
|
+
}
|
|
167586
|
+
)),
|
|
167587
|
+
!settingsPath && /* @__PURE__ */ React163__default.createElement(
|
|
167588
|
+
SettingsModal,
|
|
167589
|
+
{
|
|
167590
|
+
isOpen: isSettingsModalOpen,
|
|
167591
|
+
onClose: () => setIsSettingsModalOpen(false)
|
|
167592
|
+
}
|
|
167593
|
+
)
|
|
167594
|
+
);
|
|
167371
167595
|
};
|
|
167372
167596
|
|
|
167373
167597
|
// src/react-ui/components/practice/PracticeModeController.tsx
|
package/package.json
CHANGED