UNPKG

@defikitdotnet/education-module-ai

Version:
236 lines (235 loc) 26.1 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.UserProfileComponent = void 0; var jsx_runtime_1 = require("react/jsx-runtime"); var react_1 = require("react"); var UserContext_1 = require("../context/UserContext"); var AgentContext_1 = require("../context/AgentContext"); // Define constants for available options var allSubjects = [ "mathematics", "science", "history", "language_arts", "computer_science", "physics", "chemistry", "biology", ]; var allLearningStyles = [ "visual", "auditory", "reading_writing", "kinesthetic", "social", "solitary", ]; var UserProfileComponent = function (_a) { var _b; var apiBaseUrl = _a.apiBaseUrl, _c = _a.showFullDetails, showFullDetails = _c === void 0 ? true : _c, onProfileUpdated = _a.onProfileUpdated; var _d = (0, UserContext_1.useUser)(), isAuthenticated = _d.isAuthenticated, userId = _d.userId, userProfile = _d.userProfile, updateProfile = _d.updateProfile, updateLearningStyles = _d.updateLearningStyles, addSubject = _d.addSubject, loading = _d.loading, error = _d.error; var _e = (0, AgentContext_1.useAgent)(), agent = _e.agent, isAgentAuthenticated = _e.isAgentAuthenticated; var _f = (0, react_1.useState)(false), isEditing = _f[0], setIsEditing = _f[1]; var _g = (0, react_1.useState)(""), name = _g[0], setName = _g[1]; var _h = (0, react_1.useState)(""), email = _h[0], setEmail = _h[1]; var _j = (0, react_1.useState)([]), selectedStyles = _j[0], setSelectedStyles = _j[1]; var _k = (0, react_1.useState)(""), newSubject = _k[0], setNewSubject = _k[1]; var _l = (0, react_1.useState)(1), subjectLevel = _l[0], setSubjectLevel = _l[1]; var _m = (0, react_1.useState)("profile"), activeTab = _m[0], setActiveTab = _m[1]; // Update form when profile changes (0, react_1.useEffect)(function () { if (userProfile) { setName(userProfile.name || ""); setEmail(userProfile.email || ""); setSelectedStyles(userProfile.learningStyles || []); } }, [userProfile]); // Determine if the current user is a teacher/admin based on agent authentication var isTeacher = isAgentAuthenticated && agent; // Determine if user can edit their profile var canEdit = isAuthenticated && !isTeacher && userId === (userProfile === null || userProfile === void 0 ? void 0 : userProfile.id); // Formatted learning style display names var formatLearningStyle = function (style) { return style .split("_") .map(function (word) { return word.charAt(0).toUpperCase() + word.slice(1); }) .join(" "); }; // Handle saving profile changes var handleSaveProfile = function () { return __awaiter(void 0, void 0, void 0, function () { var success; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!userProfile) return [2 /*return*/]; return [4 /*yield*/, updateProfile(__assign(__assign({}, userProfile), { name: name, email: email }))]; case 1: success = _a.sent(); if (success && onProfileUpdated) { onProfileUpdated(); } setIsEditing(false); return [2 /*return*/]; } }); }); }; // Toggle learning style selection var toggleLearningStyle = function (style) { if (selectedStyles.includes(style)) { setSelectedStyles(selectedStyles.filter(function (s) { return s !== style; })); } else { setSelectedStyles(__spreadArray(__spreadArray([], selectedStyles, true), [style], false)); } }; // Save learning styles var handleSaveLearningStyles = function () { return __awaiter(void 0, void 0, void 0, function () { var success; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, updateLearningStyles(selectedStyles)]; case 1: success = _a.sent(); if (success && onProfileUpdated) { onProfileUpdated(); } return [2 /*return*/]; } }); }); }; // Add new subject var handleAddSubject = function () { return __awaiter(void 0, void 0, void 0, function () { var success; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!newSubject) return [2 /*return*/]; return [4 /*yield*/, addSubject(newSubject, subjectLevel)]; case 1: success = _a.sent(); if (success) { setNewSubject(""); setSubjectLevel(1); if (onProfileUpdated) { onProfileUpdated(); } } return [2 /*return*/]; } }); }); }; // If using agent context (teacher), show nothing in this component as teacher profiles are displayed differently if (isTeacher) { return null; } if (!isAuthenticated) { return ((0, jsx_runtime_1.jsx)("div", { className: "bg-gray-100 p-6 rounded-lg", children: (0, jsx_runtime_1.jsx)("p", { className: "text-center text-gray-500", children: "Please log in to view your profile." }) })); } if (loading) { return ((0, jsx_runtime_1.jsx)("div", { className: "bg-white p-6 rounded-lg shadow-md", children: (0, jsx_runtime_1.jsx)("div", { className: "flex justify-center items-center h-40", children: (0, jsx_runtime_1.jsx)("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-indigo-600" }) }) })); } if (error) { return ((0, jsx_runtime_1.jsx)("div", { className: "bg-red-50 p-6 rounded-lg border border-red-200", children: (0, jsx_runtime_1.jsxs)("p", { className: "text-red-600", children: ["Error: ", error] }) })); } if (!userProfile) { return ((0, jsx_runtime_1.jsx)("div", { className: "bg-yellow-50 p-6 rounded-lg border border-yellow-200", children: (0, jsx_runtime_1.jsx)("p", { className: "text-yellow-600", children: "User profile not found." }) })); } return ((0, jsx_runtime_1.jsxs)("div", { className: "user-profile-container bg-white rounded-lg shadow-md overflow-hidden", children: [(0, jsx_runtime_1.jsx)("div", { className: "bg-gradient-to-r from-indigo-600 to-blue-500 px-6 py-4", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center", children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-white text-xl font-bold", children: "Student Profile" }), canEdit && !isEditing && ((0, jsx_runtime_1.jsx)("button", { onClick: function () { return setIsEditing(true); }, className: "bg-white text-indigo-600 px-4 py-1 rounded text-sm font-medium hover:bg-gray-100 transition-colors", "aria-label": "Edit profile", tabIndex: 0, onKeyDown: function (e) { return e.key === "Enter" && setIsEditing(true); }, children: "Edit" }))] }) }), (0, jsx_runtime_1.jsx)("div", { className: "border-b border-gray-200", children: (0, jsx_runtime_1.jsxs)("nav", { className: "flex -mb-px", children: [(0, jsx_runtime_1.jsx)("button", { className: "px-4 py-3 font-medium text-sm border-b-2 ".concat(activeTab === "profile" ? "border-indigo-500 text-indigo-600" : "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300"), onClick: function () { return setActiveTab("profile"); }, "aria-label": "View profile information", tabIndex: 0, onKeyDown: function (e) { return e.key === "Enter" && setActiveTab("profile"); }, children: "Profile" }), (0, jsx_runtime_1.jsx)("button", { className: "px-4 py-3 font-medium text-sm border-b-2 ".concat(activeTab === "progress" ? "border-indigo-500 text-indigo-600" : "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300"), onClick: function () { return setActiveTab("progress"); }, "aria-label": "View learning progress", tabIndex: 0, onKeyDown: function (e) { return e.key === "Enter" && setActiveTab("progress"); }, children: "Progress" }), (0, jsx_runtime_1.jsx)("button", { className: "px-4 py-3 font-medium text-sm border-b-2 ".concat(activeTab === "preferences" ? "border-indigo-500 text-indigo-600" : "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300"), onClick: function () { return setActiveTab("preferences"); }, "aria-label": "View learning preferences", tabIndex: 0, onKeyDown: function (e) { return e.key === "Enter" && setActiveTab("preferences"); }, children: "Preferences" })] }) }), (0, jsx_runtime_1.jsxs)("div", { className: "p-6", children: [activeTab === "profile" && ((0, jsx_runtime_1.jsx)("div", { className: "space-y-6", children: isEditing ? ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "name", className: "block text-sm font-medium text-gray-700 mb-1", children: "Name" }), (0, jsx_runtime_1.jsx)("input", { type: "text", id: "name", value: name, onChange: function (e) { return setName(e.target.value); }, className: "block w-full p-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500" })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "email", className: "block text-sm font-medium text-gray-700 mb-1", children: "Email" }), (0, jsx_runtime_1.jsx)("input", { type: "email", id: "email", value: email, onChange: function (e) { return setEmail(e.target.value); }, className: "block w-full p-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex space-x-2 pt-2", children: [(0, jsx_runtime_1.jsx)("button", { onClick: handleSaveProfile, className: "bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700 transition-colors", "aria-label": "Save profile changes", tabIndex: 0, onKeyDown: function (e) { return e.key === "Enter" && handleSaveProfile(); }, children: "Save Changes" }), (0, jsx_runtime_1.jsx)("button", { onClick: function () { setIsEditing(false); setName(userProfile.name || ""); setEmail(userProfile.email || ""); }, className: "border border-gray-300 text-gray-700 px-4 py-2 rounded-md hover:bg-gray-50 transition-colors", "aria-label": "Cancel editing", tabIndex: 0, onKeyDown: function (e) { if (e.key === "Enter") { setIsEditing(false); setName(userProfile.name || ""); setEmail(userProfile.email || ""); } }, children: "Cancel" })] })] })) : ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center", children: [(0, jsx_runtime_1.jsx)("div", { className: "h-16 w-16 rounded-full bg-indigo-100 flex items-center justify-center text-indigo-500 text-xl font-bold", children: ((_b = userProfile.name) === null || _b === void 0 ? void 0 : _b.charAt(0).toUpperCase()) || "?" }), (0, jsx_runtime_1.jsxs)("div", { className: "ml-4", children: [(0, jsx_runtime_1.jsx)("h3", { className: "text-lg font-medium", children: userProfile.name }), (0, jsx_runtime_1.jsx)("p", { className: "text-gray-500", children: userProfile.email || "No email provided" })] })] }), showFullDetails && ((0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-2 gap-4 mt-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "bg-gray-50 p-4 rounded-lg", children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-sm font-medium text-gray-500", children: "Account Type" }), (0, jsx_runtime_1.jsx)("p", { className: "mt-1 font-medium", children: "Student" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-gray-50 p-4 rounded-lg", children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-sm font-medium text-gray-500", children: "Member Since" }), (0, jsx_runtime_1.jsx)("p", { className: "mt-1 font-medium", children: new Date(userProfile.createdAt).toLocaleDateString() })] }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-gray-50 p-4 rounded-lg", children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-sm font-medium text-gray-500", children: "Learning Streak" }), (0, jsx_runtime_1.jsxs)("p", { className: "mt-1 font-medium", children: [userProfile.streak, " days"] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-gray-50 p-4 rounded-lg", children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-sm font-medium text-gray-500", children: "Total Learning Time" }), (0, jsx_runtime_1.jsxs)("p", { className: "mt-1 font-medium", children: [Math.floor(userProfile.totalLearningTime / 60), " hours", " ", userProfile.totalLearningTime % 60, " minutes"] })] })] }))] })) })), activeTab === "progress" && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-6", children: [(0, jsx_runtime_1.jsx)("h3", { className: "text-lg font-medium border-b pb-2", children: "Subject Progress" }), Object.keys(userProfile.subjectProgress).length > 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "space-y-4", children: Object.entries(userProfile.subjectProgress).map(function (_a) { var subject = _a[0], progress = _a[1]; return ((0, jsx_runtime_1.jsxs)("div", { className: "border rounded-lg p-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center mb-2", children: [(0, jsx_runtime_1.jsx)("h4", { className: "font-medium capitalize", children: subject.replace("_", " ") }), (0, jsx_runtime_1.jsxs)("span", { className: "text-sm bg-indigo-100 text-indigo-800 py-1 px-2 rounded-full", children: ["Level ", progress.level] })] }), (0, jsx_runtime_1.jsx)("div", { className: "w-full bg-gray-200 rounded-full h-2.5 mb-4", children: (0, jsx_runtime_1.jsx)("div", { className: "bg-indigo-600 h-2.5 rounded-full", style: { width: "".concat((progress.level / 10) * 100, "%") } }) }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-2 text-sm text-gray-500 gap-2", children: [(0, jsx_runtime_1.jsxs)("div", { children: ["Completed: ", progress.completedSessions, " sessions"] }), (0, jsx_runtime_1.jsxs)("div", { children: ["Last activity:", " ", progress.lastActivity ? new Date(progress.lastActivity).toLocaleDateString() : "Never"] })] }), Object.keys(progress.topics).length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-3 pt-3 border-t", children: [(0, jsx_runtime_1.jsx)("h5", { className: "text-sm font-medium mb-2", children: "Topics Mastery" }), (0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-2 gap-2", children: Object.entries(progress.topics).map(function (_a) { var topic = _a[0], mastery = _a[1]; return ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-full bg-gray-200 rounded-full h-1.5 mr-2", children: (0, jsx_runtime_1.jsx)("div", { className: "bg-green-500 h-1.5 rounded-full", style: { width: "".concat((mastery / 10) * 100, "%"), } }) }), (0, jsx_runtime_1.jsxs)("span", { className: "text-xs whitespace-nowrap", children: [topic.substring(0, 15), topic.length > 15 ? "..." : "", ": ", mastery, "/10"] })] }, topic)); }) })] }))] }, subject)); }) })) : ((0, jsx_runtime_1.jsx)("div", { className: "text-center py-8 text-gray-500", children: (0, jsx_runtime_1.jsx)("p", { children: "No subject progress available yet." }) })), canEdit && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-6 pt-4 border-t", children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-md font-medium mb-3", children: "Add New Subject" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex space-x-2", children: [(0, jsx_runtime_1.jsxs)("select", { value: newSubject, onChange: function (e) { return setNewSubject(e.target.value); }, className: "flex-grow p-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500", children: [(0, jsx_runtime_1.jsx)("option", { value: "", children: "Select Subject" }), allSubjects.map(function (subject) { return ((0, jsx_runtime_1.jsx)("option", { value: subject, children: subject.replace("_", " ").charAt(0).toUpperCase() + subject.replace("_", " ").slice(1) }, subject)); })] }), (0, jsx_runtime_1.jsx)("select", { value: subjectLevel, onChange: function (e) { return setSubjectLevel(parseInt(e.target.value)); }, className: "w-24 p-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500", children: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(function (level) { return ((0, jsx_runtime_1.jsxs)("option", { value: level, children: ["Level ", level] }, level)); }) }), (0, jsx_runtime_1.jsx)("button", { onClick: handleAddSubject, disabled: !newSubject, className: "bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700 transition-colors disabled:bg-gray-300 disabled:cursor-not-allowed", "aria-label": "Add subject", tabIndex: 0, onKeyDown: function (e) { return e.key === "Enter" && newSubject && handleAddSubject(); }, children: "Add" })] })] }))] })), activeTab === "preferences" && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-6", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { className: "text-lg font-medium border-b pb-2", children: "Learning Styles" }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-gray-500 mt-2 mb-4", children: "Select the learning styles that work best for you. This helps us personalize your learning experience." }), (0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-2 gap-3 md:grid-cols-3", children: allLearningStyles.map(function (style) { return ((0, jsx_runtime_1.jsxs)("div", { onClick: function () { return canEdit && toggleLearningStyle(style); }, onKeyDown: function (e) { return canEdit && e.key === "Enter" && toggleLearningStyle(style); }, className: "\n flex items-center p-3 border rounded-lg cursor-pointer transition-colors\n ".concat(selectedStyles.includes(style) ? "border-indigo-500 bg-indigo-50" : "border-gray-200 hover:bg-gray-50", "\n ").concat(canEdit ? "cursor-pointer" : "cursor-default opacity-80", "\n "), tabIndex: canEdit ? 0 : -1, "aria-label": "".concat(formatLearningStyle(style), " learning style"), children: [(0, jsx_runtime_1.jsx)("span", { className: "\n w-4 h-4 rounded-full mr-2 flex-shrink-0\n ".concat(selectedStyles.includes(style) ? "bg-indigo-500" : "bg-gray-200", "\n ") }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium text-sm", children: formatLearningStyle(style) })] }, style)); }) }), canEdit && ((0, jsx_runtime_1.jsx)("div", { className: "mt-4", children: (0, jsx_runtime_1.jsx)("button", { onClick: handleSaveLearningStyles, className: "bg-indigo-600 text-white px-4 py-2 rounded-md hover:bg-indigo-700 transition-colors", "aria-label": "Save learning styles", tabIndex: 0, onKeyDown: function (e) { return e.key === "Enter" && handleSaveLearningStyles(); }, children: "Save Preferences" }) }))] }), showFullDetails && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-8 pt-6 border-t", children: [(0, jsx_runtime_1.jsx)("h3", { className: "text-lg font-medium mb-4", children: "Recommended Content" }), userProfile.recommendations && userProfile.recommendations.length > 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "space-y-3", children: userProfile.recommendations.map(function (rec, index) { return ((0, jsx_runtime_1.jsxs)("div", { className: "border rounded-lg p-3 hover:bg-gray-50", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between", children: [(0, jsx_runtime_1.jsx)("h4", { className: "font-medium", children: rec.contentId }), (0, jsx_runtime_1.jsx)("span", { className: "text-sm text-gray-500", children: new Date(rec.timestamp).toLocaleDateString() })] }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-gray-600 mt-1", children: rec.reason }), (0, jsx_runtime_1.jsx)("div", { className: "mt-2", children: (0, jsx_runtime_1.jsxs)("span", { className: "inline-block bg-green-100 text-green-800 text-xs px-2 py-1 rounded-full", children: ["Relevance: ", rec.relevanceScore.toFixed(1)] }) })] }, index)); }) })) : ((0, jsx_runtime_1.jsxs)("div", { className: "text-center py-6 text-gray-500 bg-gray-50 rounded-lg", children: [(0, jsx_runtime_1.jsx)("p", { children: "No recommendations available yet." }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm mt-1", children: "Complete more learning sessions to receive personalized recommendations." })] }))] }))] }))] })] })); }; exports.UserProfileComponent = UserProfileComponent;