@nualang/nualang-ui-components 0.1.1395 → 0.1.1397

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.
@@ -27,6 +27,7 @@ import Add from "@mui/icons-material/Add";
27
27
  import ArrowBack from "@mui/icons-material/ArrowBack";
28
28
  import Close from "@mui/icons-material/Close";
29
29
  import UpgradeSubscription from "../../Dialogs/UpgradeSubscription/UpgradeSubscription";
30
+ import QuickCreateClassroomDialog from "../../Dialogs/QuickCreateClassroomDialog/QuickCreateClassroomDialog";
30
31
 
31
32
  // nav config
32
33
  import navigationImport from "../../Navigation/_nav";
@@ -214,7 +215,13 @@ function App({
214
215
  gameAward,
215
216
  isCollapsed,
216
217
  setIsCollapsed,
217
- isUserInternal
218
+ isUserInternal,
219
+ handleQuickCreateClassroom,
220
+ learnLang,
221
+ forLang,
222
+ fileSizeLimit,
223
+ languages,
224
+ forLanguages
218
225
  }) {
219
226
  const theme = useTheme();
220
227
  const isLgScreen = useMediaQuery(theme.breakpoints.up("md"));
@@ -222,6 +229,7 @@ function App({
222
229
  const [searchText, setSearchText] = useState("");
223
230
  const [isAppContainerLoading, setIsAppContainerLoading] = useState(true);
224
231
  const [anchorEl, setAnchorEl] = useState(null);
232
+ const [isCreateClassroomOpen, setIsCreateClassroomOpen] = useState(false);
225
233
  const [isUpgradeSubscriptionOpen, setIsUpgradeSubscriptionOpen] = useState(false);
226
234
  const [isMobileSearchExpanded, setIsMobileSearchExpanded] = useState(false);
227
235
  const handleOpenUpgradeSubscriptionModal = () => {
@@ -262,7 +270,7 @@ function App({
262
270
  };
263
271
  const handleCreateClassroom = () => {
264
272
  if (subscription.isPaidUser) {
265
- navigate("/classrooms/create");
273
+ setIsCreateClassroomOpen(true);
266
274
  } else {
267
275
  handleOpenUpgradeSubscriptionModal();
268
276
  }
@@ -418,6 +426,20 @@ function App({
418
426
  children: t("assignment")
419
427
  })]
420
428
  })]
429
+ }), /*#__PURE__*/_jsx(QuickCreateClassroomDialog, {
430
+ open: isCreateClassroomOpen,
431
+ handleClose: () => setIsCreateClassroomOpen(false),
432
+ handleCreate: async values => {
433
+ await handleQuickCreateClassroom(values);
434
+ },
435
+ t: t,
436
+ fileSizeLimit: fileSizeLimit,
437
+ verificationStatus: verificationStatus,
438
+ learnLang: learnLang,
439
+ forLang: forLang,
440
+ languages: languages,
441
+ forLanguages: forLanguages,
442
+ userImage: user ? user.picture : null
421
443
  }), /*#__PURE__*/_jsx(LanguageSelector, {
422
444
  t: t,
423
445
  currentLanguage: currentLanguage,
@@ -0,0 +1,200 @@
1
+ import { useState, useEffect } from "react";
2
+ import TextField from "@mui/material/TextField";
3
+ import Box from "@mui/material/Box";
4
+ import Button from "@mui/material/Button";
5
+ import Dialog from "@mui/material/Dialog";
6
+ import DialogTitle from "@mui/material/DialogTitle";
7
+ import DialogContent from "@mui/material/DialogContent";
8
+ import DialogActions from "@mui/material/DialogActions";
9
+ import Grid from "@mui/material/Grid";
10
+ import ImageSelector from "../../Forms/ImageSelector/ImageSelector";
11
+ import PlaceholderImages from "../../utils/placeholder-images/index";
12
+ import LanguageSelector from "../../Forms/LanguageSelector/LanguageSelector";
13
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
+ export default function QuickCreateClassroomDialog({
15
+ open,
16
+ handleClose,
17
+ handleCreate,
18
+ onCreated,
19
+ t = text => text,
20
+ fileSizeLimit,
21
+ verificationStatus,
22
+ learnLang,
23
+ userImage,
24
+ forLang,
25
+ languages,
26
+ forLanguages
27
+ }) {
28
+ const [name, setName] = useState("");
29
+ const [isLoading, setIsLoading] = useState(false);
30
+ const defaultSelectedImage = {
31
+ image: PlaceholderImages.classroom,
32
+ imageSelectionMethod: "default_image"
33
+ };
34
+ const [selectedImage, setSelectedImage] = useState(defaultSelectedImage);
35
+ const [picture, setPicture] = useState("");
36
+ const [classroomLearnLang, setClassroomLearnLang] = useState("");
37
+ const [classroomForLang, setClassroomForLang] = useState("");
38
+ useEffect(() => {
39
+ if (learnLang && classroomLearnLang === "") {
40
+ setClassroomLearnLang(learnLang);
41
+ }
42
+ }, [learnLang]);
43
+ useEffect(() => {
44
+ if (forLang && classroomForLang === "") {
45
+ setClassroomForLang(forLang);
46
+ }
47
+ }, [forLang]);
48
+ const handleImageSelection = event => {
49
+ const {
50
+ name,
51
+ value
52
+ } = event.target;
53
+ setSelectedImage(prev => ({
54
+ ...prev,
55
+ [name]: value
56
+ }));
57
+ setPicture(value);
58
+ };
59
+ const removeImage = () => {
60
+ setSelectedImage(defaultSelectedImage);
61
+ setPicture("");
62
+ };
63
+ const generateRandomEnrolmentKey = () => {
64
+ return String(Math.floor(Math.random() * 90000) + 10000);
65
+ };
66
+ const handleSubmit = async () => {
67
+ if (!name.trim()) return;
68
+ setIsLoading(true);
69
+ try {
70
+ const createdClassroom = await handleCreate({
71
+ classroomName: name.trim(),
72
+ description: `${t("first_classroom_description", {
73
+ learnLang: t(classroomLearnLang)
74
+ })}`,
75
+ learnLang: classroomLearnLang,
76
+ forLang: classroomForLang,
77
+ visibility: "private",
78
+ vchatEnabled: true,
79
+ vchatEnabledInSettings: true,
80
+ isDynamicResponsesEnabled: "enabled",
81
+ enrolmentKey: generateRandomEnrolmentKey(),
82
+ allowedDomains: [],
83
+ collaborators: [],
84
+ tags: [],
85
+ picture: picture || PlaceholderImages.classroom,
86
+ userImage: userImage
87
+ });
88
+ resetAndClose();
89
+ if (onCreated && createdClassroom) {
90
+ onCreated(createdClassroom, selectedImage.image || null);
91
+ }
92
+ } catch (error) {
93
+ console.error("Failed to create classroom:", error);
94
+ } finally {
95
+ setIsLoading(false);
96
+ }
97
+ };
98
+ const resetAndClose = () => {
99
+ setName("");
100
+ setSelectedImage(defaultSelectedImage);
101
+ setPicture("");
102
+ setClassroomLearnLang(learnLang || "");
103
+ setClassroomForLang(forLang || "");
104
+ handleClose();
105
+ };
106
+ return /*#__PURE__*/_jsxs(Dialog, {
107
+ open: open,
108
+ onClose: isLoading ? undefined : resetAndClose,
109
+ maxWidth: "sm",
110
+ fullWidth: true,
111
+ children: [/*#__PURE__*/_jsx(DialogTitle, {
112
+ children: t("create_classroom") || "Create Classroom"
113
+ }), /*#__PURE__*/_jsx(DialogContent, {
114
+ children: /*#__PURE__*/_jsxs(Box, {
115
+ display: "flex",
116
+ flexDirection: "column",
117
+ gap: 2,
118
+ pt: 1,
119
+ children: [/*#__PURE__*/_jsx(TextField, {
120
+ label: t("classroom_name") || "Classroom Name",
121
+ value: name,
122
+ onChange: e => setName(e.target.value),
123
+ fullWidth: true,
124
+ autoFocus: true,
125
+ required: true,
126
+ disabled: isLoading,
127
+ inputProps: {
128
+ maxLength: 100
129
+ },
130
+ onKeyDown: e => e.key === "Enter" && handleSubmit()
131
+ }), /*#__PURE__*/_jsx(Grid, {
132
+ size: 12,
133
+ children: /*#__PURE__*/_jsx(LanguageSelector, {
134
+ id: "learnLang",
135
+ name: "learnLang",
136
+ "data-cy": "learnLang",
137
+ label: t("the_language_classroom_teach"),
138
+ margin: "normal",
139
+ variant: "outlined",
140
+ fullWidth: true,
141
+ required: true,
142
+ t: t,
143
+ languages: languages,
144
+ value: classroomLearnLang,
145
+ disabled: isLoading,
146
+ onChange: e => {
147
+ setClassroomLearnLang(e.target.value);
148
+ }
149
+ })
150
+ }), /*#__PURE__*/_jsx(Grid, {
151
+ size: 12,
152
+ children: /*#__PURE__*/_jsx(LanguageSelector, {
153
+ id: "forLang",
154
+ name: "forLang",
155
+ "data-cy": "forLang",
156
+ label: t("the_language_students_classroom_speak"),
157
+ margin: "normal",
158
+ variant: "outlined",
159
+ fullWidth: true,
160
+ required: true,
161
+ t: t,
162
+ languages: forLanguages,
163
+ value: classroomForLang,
164
+ disabled: isLoading,
165
+ onChange: e => {
166
+ setClassroomForLang(e.target.value);
167
+ }
168
+ })
169
+ }), /*#__PURE__*/_jsx(Grid, {
170
+ size: 12,
171
+ children: /*#__PURE__*/_jsx(ImageSelector, {
172
+ t: t,
173
+ name: "image",
174
+ value: selectedImage.image,
175
+ handleChange: handleImageSelection,
176
+ fileSizeLimit: fileSizeLimit,
177
+ removeImage: removeImage,
178
+ autoCrop: true,
179
+ autoSuggest: false,
180
+ selectedImage: selectedImage,
181
+ verificationStatus: verificationStatus
182
+ })
183
+ })]
184
+ })
185
+ }), /*#__PURE__*/_jsxs(DialogActions, {
186
+ children: [/*#__PURE__*/_jsx(Button, {
187
+ onClick: resetAndClose,
188
+ color: "primary",
189
+ disabled: isLoading,
190
+ children: t("cancel") || "Cancel"
191
+ }), /*#__PURE__*/_jsx(Button, {
192
+ onClick: handleSubmit,
193
+ color: "primary",
194
+ variant: "contained",
195
+ disabled: !name.trim() || isLoading,
196
+ children: t("create") || "Create"
197
+ })]
198
+ })]
199
+ });
200
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nualang/nualang-ui-components",
3
- "version": "0.1.1395",
3
+ "version": "0.1.1397",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "files": [
@@ -174,7 +174,7 @@
174
174
  "postinstall": "patch-package",
175
175
  "start": "pnpm run storybook",
176
176
  "vitest": "vitest",
177
- "vitest:cicd": "cross-env CI=true vitest run",
177
+ "vitest:cicd": "cross-env CI=true vitest -- run --slient --threads 4",
178
178
  "test:coverage": "vitest run --coverage",
179
179
  "storybook": "storybook dev -p 9009",
180
180
  "build-storybook": "storybook build",