touchstudy-core 0.1.177 → 0.1.179

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.
@@ -0,0 +1,12 @@
1
+ import { MouseEvent } from "react";
2
+ import { FC } from "react";
3
+ import { ExamSessionResponse } from "../../configs/types";
4
+ interface Props {
5
+ isSelected: boolean;
6
+ isPrintSelected?: (code: string) => boolean;
7
+ session: ExamSessionResponse;
8
+ onViewResult: (code: string) => void;
9
+ onSelectPrint?: (e: MouseEvent<any>, code: string) => void;
10
+ }
11
+ declare const ExamSessionItem: FC<Props>;
12
+ export default ExamSessionItem;
@@ -0,0 +1,9 @@
1
+ import { FC } from "react";
2
+ import { ExamSessionResponse } from "../../configs/types";
3
+ interface Props {
4
+ isSelected: boolean;
5
+ session: ExamSessionResponse;
6
+ onViewResult: (code: string) => void;
7
+ }
8
+ declare const GeneralExamItem: FC<Props>;
9
+ export default GeneralExamItem;
@@ -0,0 +1,19 @@
1
+ import { MouseEvent } from "react";
2
+ import { FC } from "react";
3
+ import { ExamSessionResponse } from "../../configs/types";
4
+ import { Role } from "../../../../utils";
5
+ interface Props {
6
+ role: Role;
7
+ activeCode?: string;
8
+ examSessions: ExamSessionResponse[];
9
+ date: string;
10
+ index: number;
11
+ open: boolean;
12
+ itemActive: boolean;
13
+ isPrintSelected?: (code: string) => boolean;
14
+ onSelectPrint?: (e: MouseEvent<any>, code: string) => void;
15
+ onToggle: (index: number) => void;
16
+ onViewResult: (code: string) => void;
17
+ }
18
+ declare const MonthGroupedExamSessionItem: FC<Props>;
19
+ export default MonthGroupedExamSessionItem;
@@ -0,0 +1,3 @@
1
+ import ExamSessionItem from "./ExamSessionItem";
2
+ import MonthGroupedExamSessionItem from "./MonthGroupedExamSessionItem";
3
+ export { ExamSessionItem, MonthGroupedExamSessionItem };
@@ -1,6 +1,6 @@
1
1
  import { FormikProps } from "formik";
2
2
  import React, { FC } from "react";
3
- import { TextbookRequest } from "../configs/types";
3
+ import { TextbookDetailResponse, TextbookRequest } from "../configs/types";
4
4
  interface Props extends FormikProps<TextbookRequest> {
5
5
  isCreatedByAdmin?: boolean;
6
6
  isSuperAdminUser: boolean;
@@ -11,6 +11,8 @@ interface Props extends FormikProps<TextbookRequest> {
11
11
  coverImage?: string;
12
12
  disabled?: boolean;
13
13
  ownersDisabled?: boolean;
14
+ handleSaveData: (values: TextbookRequest) => Promise<void>;
15
+ selectedTextbook?: TextbookDetailResponse;
14
16
  onUploadImage: (event: React.ChangeEvent<HTMLInputElement>) => Promise<void>;
15
17
  onChangeTab: (_: React.SyntheticEvent, newValue: number) => void;
16
18
  }
@@ -93,3 +93,5 @@ export declare const CompareTypeOptions: {
93
93
  label: string;
94
94
  value: QuestionAnswerType;
95
95
  }[];
96
+ export declare const SAVE_TIME_INTERVAL_IN_MILLISECONDS: number;
97
+ export declare const SAVE_TIME_MAX_DIFF_IN_MILLISECONDS = 1000;
@@ -19,3 +19,8 @@ export declare enum TextbookEditorType {
19
19
  Korea = 1,
20
20
  Math = 2
21
21
  }
22
+ export declare enum PrintStatus {
23
+ Idle = 0,
24
+ Saving = 1,
25
+ Saved = 2
26
+ }
@@ -11,7 +11,7 @@ declare const useTextbookManagement: ({ textbookId, role, onNavigateList }: Prop
11
11
  isAdminSite: boolean;
12
12
  disabledTextbookOwners: boolean;
13
13
  isReadonly: boolean;
14
- isEditable: boolean;
14
+ isEditable: any;
15
15
  isAdmin: any;
16
16
  theme: import("@mui/material").Theme;
17
17
  history: History;
@@ -20,6 +20,7 @@ declare const useTextbookManagement: ({ textbookId, role, onNavigateList }: Prop
20
20
  isSuperAdminUser: any;
21
21
  openDialog: boolean;
22
22
  handleSubmit: (values: TextbookRequest, _formikHelpers: FormikHelpers<TextbookRequest>) => Promise<void>;
23
+ handleSaveData: (values: TextbookRequest) => Promise<void>;
23
24
  selectedTextbook: TextbookDetailResponse | undefined;
24
25
  handleOpenDialog: (item?: any) => void;
25
26
  handleCloseDialog: () => void;
package/dist/index.js CHANGED
@@ -70,6 +70,7 @@ var reactHookForm = require('react-hook-form');
70
70
  var yup$1 = require('@hookform/resolvers/yup');
71
71
  var pi = require('react-icons/pi');
72
72
  var Container = _interopDefault(require('@mui/material/Container'));
73
+ var ai = require('react-icons/ai');
73
74
  var bs = require('react-icons/bs');
74
75
  var Popover = _interopDefault(require('@mui/material/Popover'));
75
76
  var MenuItem = _interopDefault(require('@mui/material/MenuItem'));
@@ -1029,6 +1030,7 @@ var teacher_required = "선생님은 필수입니다";
1029
1030
  var total_users = "총 사용자";
1030
1031
  var added_date = "추가된 날짜";
1031
1032
  var sync_exam_results = "시험 결과 동기화";
1033
+ var sync_textbook_results = "교재 결과 동기화";
1032
1034
  var update_data_fail = "데이터 업데이트 실패";
1033
1035
  var add_students_to_class = "수업에 학생 추가";
1034
1036
  var add_teachers_to_class = "수업에 교사 추가";
@@ -1039,9 +1041,13 @@ var question_management = "질문 관리";
1039
1041
  var student_data = "학생 데이터";
1040
1042
  var problem_number_question_chart = "문제 {{number}}번";
1041
1043
  var are_you_sure_to_sync_exam_results_to_academy = "시험 결과를 아카데미 {{ academyName }}에 동기화하시겠습니까(백그라운드에서 실행되며 시간이 다소 소요됨)";
1044
+ var are_you_sure_to_sync_textbook_results_to_academy = "교재 학습 결과를 아카데미 {{ academyName }}에 동기화하시겠습니까? (백그라운드에서 실행되며 시간이 다소 소요됨)";
1042
1045
  var messages = {
1043
- exam_sessions_are_being_synchronized: "{{ total }} 개의 시험 세션이 동기화되고 있습니다"
1046
+ exam_sessions_are_being_synchronized: "{{ total }} 개의 시험 세션이 동기화되고 있습니다",
1047
+ textbook_sessions_are_being_synchronized: "{{ total }} 개의 교재 학습 세션이 동기화되고 있습니다"
1044
1048
  };
1049
+ var sync_exam = "시험 동기화";
1050
+ var sync_textbook = "교재 동기화";
1045
1051
  var submit = "제출하다";
1046
1052
  var must_select_a_teacher_first = "먼저 교사를 선택해야 합니다";
1047
1053
  var student_grade_is_invalid = "학생 등급은 1에서 12 사이여야 합니다";
@@ -1488,6 +1494,8 @@ var order_matters = "순서 상관 있음";
1488
1494
  var order_does_not_matter = "순서 상관 없음";
1489
1495
  var synonym_processing = "답 이음동의어 처리";
1490
1496
  var compare_type = "비교 유형";
1497
+ var all_changes_saved = "모든 변경 사항이 저장되었습니다";
1498
+ var saving = "절약";
1491
1499
  var textbook_name = "교재 이름";
1492
1500
  var korean_language = "국어";
1493
1501
  var answer_cannot_be_empty = "답변은 비워둘 수 없습니다";
@@ -1534,6 +1542,7 @@ var admin_to_teachers = "관리자에서 교사들에게";
1534
1542
  var teacher_to_teachers = "교사에서 교사들에게";
1535
1543
  var student_required = "학생은 필수입니다";
1536
1544
  var teachers_required = "교사가 필요합니다";
1545
+ var all_changes_are_not_saved_yet = "아직 모든 변경 사항이 저장되지 않았습니다";
1537
1546
  var lang_ko = {
1538
1547
  problem_solving: problem_solving,
1539
1548
  my_story: my_story,
@@ -2213,6 +2222,7 @@ var lang_ko = {
2213
2222
  total_users: total_users,
2214
2223
  added_date: added_date,
2215
2224
  sync_exam_results: sync_exam_results,
2225
+ sync_textbook_results: sync_textbook_results,
2216
2226
  update_data_fail: update_data_fail,
2217
2227
  add_students_to_class: add_students_to_class,
2218
2228
  add_teachers_to_class: add_teachers_to_class,
@@ -2223,7 +2233,10 @@ var lang_ko = {
2223
2233
  student_data: student_data,
2224
2234
  problem_number_question_chart: problem_number_question_chart,
2225
2235
  are_you_sure_to_sync_exam_results_to_academy: are_you_sure_to_sync_exam_results_to_academy,
2236
+ are_you_sure_to_sync_textbook_results_to_academy: are_you_sure_to_sync_textbook_results_to_academy,
2226
2237
  messages: messages,
2238
+ sync_exam: sync_exam,
2239
+ sync_textbook: sync_textbook,
2227
2240
  submit: submit,
2228
2241
  must_select_a_teacher_first: must_select_a_teacher_first,
2229
2242
  student_grade_is_invalid: student_grade_is_invalid,
@@ -2658,6 +2671,8 @@ var lang_ko = {
2658
2671
  order_does_not_matter: order_does_not_matter,
2659
2672
  synonym_processing: synonym_processing,
2660
2673
  compare_type: compare_type,
2674
+ all_changes_saved: all_changes_saved,
2675
+ saving: saving,
2661
2676
  textbook_name: textbook_name,
2662
2677
  korean_language: korean_language,
2663
2678
  answer_cannot_be_empty: answer_cannot_be_empty,
@@ -2703,7 +2718,8 @@ var lang_ko = {
2703
2718
  admin_to_teachers: admin_to_teachers,
2704
2719
  teacher_to_teachers: teacher_to_teachers,
2705
2720
  student_required: student_required,
2706
- teachers_required: teachers_required
2721
+ teachers_required: teachers_required,
2722
+ all_changes_are_not_saved_yet: all_changes_are_not_saved_yet
2707
2723
  };
2708
2724
 
2709
2725
  var problem_solving$1 = "Problem Solving";
@@ -3390,6 +3406,7 @@ var teacher_required$1 = "Teacher is required";
3390
3406
  var total_users$1 = "Total users";
3391
3407
  var added_date$1 = "Added date";
3392
3408
  var sync_exam_results$1 = "Sync exam results";
3409
+ var sync_textbook_results$1 = "Sync textbook results";
3393
3410
  var update_data_fail$1 = "Update data fail";
3394
3411
  var add_students_to_class$1 = "Add students to class";
3395
3412
  var add_teachers_to_class$1 = "Add teachers to class";
@@ -3400,9 +3417,13 @@ var question_management$1 = "Question Management";
3400
3417
  var student_data$1 = "Student Data";
3401
3418
  var problem_number_question_chart$1 = "Q. {{number}}";
3402
3419
  var are_you_sure_to_sync_exam_results_to_academy$1 = "Are you sure to sync exam results to academy \"{{ academyName }}\" (it will run in the background and take a while)";
3420
+ var are_you_sure_to_sync_textbook_results_to_academy$1 = "Are you sure to sync textbook results to academy \"{{ academyName }}\" (it will run in the background and take a while)";
3403
3421
  var messages$1 = {
3404
- exam_sessions_are_being_synchronized: "{{ total }} exam sessions are being synchronized"
3422
+ exam_sessions_are_being_synchronized: "{{ total }} exam sessions are being synchronized",
3423
+ textbook_sessions_are_being_synchronized: "{{ total }} textbook sessions are being synchronized"
3405
3424
  };
3425
+ var sync_exam$1 = "Sync Exam";
3426
+ var sync_textbook$1 = "Sync Textbook";
3406
3427
  var submit$1 = "Submit";
3407
3428
  var must_select_a_teacher_first$1 = "Must select a teacher first";
3408
3429
  var student_grade_is_invalid$1 = "Student grade must be from 1 to 12";
@@ -3850,6 +3871,8 @@ var order_matters$1 = "Order matters";
3850
3871
  var order_does_not_matter$1 = "Order doesn't matter";
3851
3872
  var synonym_processing$1 = "Answer Synonym processing";
3852
3873
  var compare_type$1 = "Compare Type";
3874
+ var all_changes_saved$1 = "All changes saved";
3875
+ var saving$1 = "Saving";
3853
3876
  var textbook_name$1 = "Textbook name";
3854
3877
  var korean_language$1 = "Korean";
3855
3878
  var answer_cannot_be_empty$1 = "Answer cannot be empty";
@@ -3896,6 +3919,7 @@ var admin_to_teachers$1 = "Admin to teachers";
3896
3919
  var teacher_to_teachers$1 = "Teacher to teachers";
3897
3920
  var student_required$1 = "Student is required";
3898
3921
  var teachers_required$1 = "Teachers are required";
3922
+ var all_changes_are_not_saved_yet$1 = "All changes are not saved yet";
3899
3923
  var lang_en = {
3900
3924
  problem_solving: problem_solving$1,
3901
3925
  my_story: my_story$1,
@@ -4576,6 +4600,7 @@ var lang_en = {
4576
4600
  total_users: total_users$1,
4577
4601
  added_date: added_date$1,
4578
4602
  sync_exam_results: sync_exam_results$1,
4603
+ sync_textbook_results: sync_textbook_results$1,
4579
4604
  update_data_fail: update_data_fail$1,
4580
4605
  add_students_to_class: add_students_to_class$1,
4581
4606
  add_teachers_to_class: add_teachers_to_class$1,
@@ -4586,7 +4611,10 @@ var lang_en = {
4586
4611
  student_data: student_data$1,
4587
4612
  problem_number_question_chart: problem_number_question_chart$1,
4588
4613
  are_you_sure_to_sync_exam_results_to_academy: are_you_sure_to_sync_exam_results_to_academy$1,
4614
+ are_you_sure_to_sync_textbook_results_to_academy: are_you_sure_to_sync_textbook_results_to_academy$1,
4589
4615
  messages: messages$1,
4616
+ sync_exam: sync_exam$1,
4617
+ sync_textbook: sync_textbook$1,
4590
4618
  submit: submit$1,
4591
4619
  must_select_a_teacher_first: must_select_a_teacher_first$1,
4592
4620
  student_grade_is_invalid: student_grade_is_invalid$1,
@@ -5022,6 +5050,8 @@ var lang_en = {
5022
5050
  order_does_not_matter: order_does_not_matter$1,
5023
5051
  synonym_processing: synonym_processing$1,
5024
5052
  compare_type: compare_type$1,
5053
+ all_changes_saved: all_changes_saved$1,
5054
+ saving: saving$1,
5025
5055
  textbook_name: textbook_name$1,
5026
5056
  korean_language: korean_language$1,
5027
5057
  answer_cannot_be_empty: answer_cannot_be_empty$1,
@@ -5067,7 +5097,8 @@ var lang_en = {
5067
5097
  admin_to_teachers: admin_to_teachers$1,
5068
5098
  teacher_to_teachers: teacher_to_teachers$1,
5069
5099
  student_required: student_required$1,
5070
- teachers_required: teachers_required$1
5100
+ teachers_required: teachers_required$1,
5101
+ all_changes_are_not_saved_yet: all_changes_are_not_saved_yet$1
5071
5102
  };
5072
5103
 
5073
5104
  i18n__default.use(reactI18next.initReactI18next).init({
@@ -6265,6 +6296,12 @@ var HighSchoolGrade;
6265
6296
  TextbookEditorType[TextbookEditorType["Korea"] = 1] = "Korea";
6266
6297
  TextbookEditorType[TextbookEditorType["Math"] = 2] = "Math";
6267
6298
  })(exports.TextbookEditorType || (exports.TextbookEditorType = {}));
6299
+ var PrintStatus;
6300
+ (function (PrintStatus) {
6301
+ PrintStatus[PrintStatus["Idle"] = 0] = "Idle";
6302
+ PrintStatus[PrintStatus["Saving"] = 1] = "Saving";
6303
+ PrintStatus[PrintStatus["Saved"] = 2] = "Saved";
6304
+ })(PrintStatus || (PrintStatus = {}));
6268
6305
 
6269
6306
  (function (SchoolType) {
6270
6307
  SchoolType[SchoolType["Default"] = 0] = "Default";
@@ -33911,11 +33948,11 @@ var TextbookRow = function TextbookRow(_ref) {
33911
33948
  });
33912
33949
  var _useTranslation = reactI18next.useTranslation(),
33913
33950
  t = _useTranslation.t;
33914
- var isEditable = (!onAcademy || isAdminSite || isSuperAdmin || isSuperAdminUser || !isAdmin && data.isShared && (((_data$createdBy = data.createdBy) === null || _data$createdBy === void 0 ? void 0 : _data$createdBy.id) === (infoUser === null || infoUser === void 0 ? void 0 : infoUser.id) || ((_data$textbookOwners = data.textbookOwners) === null || _data$textbookOwners === void 0 ? void 0 : _data$textbookOwners.some(function (i) {
33951
+ var isEditable = !onAcademy || isAdminSite || isSuperAdmin || isSuperAdminUser || !isAdmin && data.isShared && (((_data$createdBy = data.createdBy) === null || _data$createdBy === void 0 ? void 0 : _data$createdBy.id) === (infoUser === null || infoUser === void 0 ? void 0 : infoUser.id) || ((_data$textbookOwners = data.textbookOwners) === null || _data$textbookOwners === void 0 ? void 0 : _data$textbookOwners.some(function (i) {
33915
33952
  var _infoUser$email, _infoUser$email$trim;
33916
33953
  return (i === null || i === void 0 ? void 0 : i.email.trim().toUpperCase()) === (infoUser === null || infoUser === void 0 ? void 0 : (_infoUser$email = infoUser.email) === null || _infoUser$email === void 0 ? void 0 : (_infoUser$email$trim = _infoUser$email.trim()) === null || _infoUser$email$trim === void 0 ? void 0 : _infoUser$email$trim.toUpperCase()) && (i === null || i === void 0 ? void 0 : i.academyId) === (academy === null || academy === void 0 ? void 0 : academy.id);
33917
- })))) && data.totalUses <= 0;
33918
- var isDeleteAble = !onAcademy || isAdminSite || isSuperAdmin || isSuperAdminUser || !isAdmin && data.isShared && ((_data$createdBy2 = data.createdBy) === null || _data$createdBy2 === void 0 ? void 0 : _data$createdBy2.id) === (infoUser === null || infoUser === void 0 ? void 0 : infoUser.id) && data.totalUses <= 0;
33954
+ })));
33955
+ var isDeleteAble = !onAcademy || isAdminSite || isSuperAdmin || isSuperAdminUser || !isAdmin && data.isShared && ((_data$createdBy2 = data.createdBy) === null || _data$createdBy2 === void 0 ? void 0 : _data$createdBy2.id) === (infoUser === null || infoUser === void 0 ? void 0 : infoUser.id);
33919
33956
  var isSharable = !data.isPublic && data.isShared && onAcademy && (isAdminSite || isSuperAdminUser || !isAdmin && data.createdBy.id === infoUser.id);
33920
33957
  var handleUpdateTextbook = function handleUpdateTextbook() {
33921
33958
  onUpdateTextbook(data);
@@ -34936,10 +34973,10 @@ var useTextbookManagement = function useTextbookManagement(_ref) {
34936
34973
  var isAdminSite = role === exports.Role.Admin;
34937
34974
  var onAcademy = !!(user !== null && user !== void 0 && user.academyDomain);
34938
34975
  var isSuperAdminUser = !!user && user.isSuperAdmin;
34939
- var isEditable = !selectedTextbook || (!onAcademy || isAdminSite || isSuperAdmin || isSuperAdminUser || !isAdmin && selectedTextbook.isShared && (((_selectedTextbook$cre = selectedTextbook.createdBy) === null || _selectedTextbook$cre === void 0 ? void 0 : _selectedTextbook$cre.id) === (user === null || user === void 0 ? void 0 : user.id) || selectedTextbook.textbookOwners.some(function (i) {
34976
+ var isEditable = !selectedTextbook || !onAcademy || isAdminSite || isSuperAdmin || isSuperAdminUser || !isAdmin && selectedTextbook.isShared && (((_selectedTextbook$cre = selectedTextbook.createdBy) === null || _selectedTextbook$cre === void 0 ? void 0 : _selectedTextbook$cre.id) === (user === null || user === void 0 ? void 0 : user.id) || selectedTextbook.textbookOwners.some(function (i) {
34940
34977
  var _user$email, _user$email$trim;
34941
34978
  return i.email.trim().toUpperCase() === (user === null || user === void 0 ? void 0 : (_user$email = user.email) === null || _user$email === void 0 ? void 0 : (_user$email$trim = _user$email.trim()) === null || _user$email$trim === void 0 ? void 0 : _user$email$trim.toUpperCase()) && i.academyId === (academy === null || academy === void 0 ? void 0 : academy.id);
34942
- }))) && selectedTextbook.totalUses <= 0;
34979
+ }));
34943
34980
  var disabledTextbookOwners = !selectedTextbook && isAdmin || selectedTextbook && (!isEditable || isTeacher && ((_selectedTextbook$cre2 = selectedTextbook.createdBy) === null || _selectedTextbook$cre2 === void 0 ? void 0 : _selectedTextbook$cre2.id) !== (user === null || user === void 0 ? void 0 : user.id) || isAdmin && !isSuperAdminUser);
34944
34981
  var handleOpenConfirmDeleteChapterDialog = function handleOpenConfirmDeleteChapterDialog(chapter) {
34945
34982
  setSelectedChapter(chapter);
@@ -35041,6 +35078,24 @@ var useTextbookManagement = function useTextbookManagement(_ref) {
35041
35078
  return Promise.reject(e);
35042
35079
  }
35043
35080
  };
35081
+ var handleSaveData = React.useCallback(function (values) {
35082
+ try {
35083
+ if (!coverImage && !(values !== null && values !== void 0 && values.coverImage)) {
35084
+ return Promise.resolve();
35085
+ }
35086
+ return Promise.resolve(_catch(function () {
35087
+ var coverImg = coverImage || (values === null || values === void 0 ? void 0 : values.coverImage);
35088
+ return Promise.resolve(updateTextbookApi$1(_extends({}, values, {
35089
+ coverImage: coverImg
35090
+ }), (selectedTextbook === null || selectedTextbook === void 0 ? void 0 : selectedTextbook.id) || 0, isSuperAdmin)).then(function () {});
35091
+ }, function (error) {
35092
+ reactToastify.toast.error(getErrorMessage(t, error));
35093
+ throw error;
35094
+ }));
35095
+ } catch (e) {
35096
+ return Promise.reject(e);
35097
+ }
35098
+ }, [coverImage, isSuperAdmin, JSON.stringify(selectedTextbook)]);
35044
35099
  React.useEffect(function () {
35045
35100
  if (!textbookId) return;
35046
35101
  handleGetTextbookDetail();
@@ -35059,6 +35114,7 @@ var useTextbookManagement = function useTextbookManagement(_ref) {
35059
35114
  isSuperAdminUser: isSuperAdminUser,
35060
35115
  openDialog: openDialog,
35061
35116
  handleSubmit: handleSubmit,
35117
+ handleSaveData: handleSaveData,
35062
35118
  selectedTextbook: selectedTextbook,
35063
35119
  handleOpenDialog: handleOpenDialog,
35064
35120
  handleCloseDialog: handleCloseDialog,
@@ -35352,6 +35408,8 @@ var CompareTypeOptions = [{
35352
35408
  label: "synonym_processing",
35353
35409
  value: exports.QuestionAnswerType.SynonymProcessing
35354
35410
  }];
35411
+ var SAVE_TIME_INTERVAL_IN_MILLISECONDS = 60 * 1000;
35412
+ var SAVE_TIME_MAX_DIFF_IN_MILLISECONDS = 1000;
35355
35413
 
35356
35414
  var CustomTextbookTab = function CustomTextbookTab(props) {
35357
35415
  var children = props.children,
@@ -38527,8 +38585,9 @@ var TextbookOwnersTab = function TextbookOwnersTab(_ref) {
38527
38585
  }));
38528
38586
  };
38529
38587
 
38530
- var _excluded$n = ["isCreatedByAdmin", "isSuperAdminUser", "isSuperAdmin", "isAdmin", "textbookId", "selected", "coverImage", "disabled", "ownersDisabled", "onChangeTab", "onUploadImage"];
38588
+ var _excluded$n = ["isCreatedByAdmin", "isSuperAdminUser", "isSuperAdmin", "isAdmin", "textbookId", "selected", "coverImage", "disabled", "ownersDisabled", "selectedTextbook", "handleSaveData", "onChangeTab", "onUploadImage"];
38531
38589
  var PreparedTextbookForm = function PreparedTextbookForm(_ref) {
38590
+ var _valuesTextbook$curre;
38532
38591
  var isCreatedByAdmin = _ref.isCreatedByAdmin,
38533
38592
  isSuperAdminUser = _ref.isSuperAdminUser,
38534
38593
  isSuperAdmin = _ref.isSuperAdmin,
@@ -38538,6 +38597,8 @@ var PreparedTextbookForm = function PreparedTextbookForm(_ref) {
38538
38597
  coverImage = _ref.coverImage,
38539
38598
  disabled = _ref.disabled,
38540
38599
  ownersDisabled = _ref.ownersDisabled,
38600
+ selectedTextbook = _ref.selectedTextbook,
38601
+ handleSaveData = _ref.handleSaveData,
38541
38602
  onChangeTab = _ref.onChangeTab,
38542
38603
  onUploadImage = _ref.onUploadImage,
38543
38604
  formikProps = _objectWithoutPropertiesLoose(_ref, _excluded$n);
@@ -38546,6 +38607,20 @@ var PreparedTextbookForm = function PreparedTextbookForm(_ref) {
38546
38607
  dirty = formikProps.dirty,
38547
38608
  submitCount = formikProps.submitCount,
38548
38609
  setValues = formikProps.setValues;
38610
+ var theme = material.useTheme();
38611
+ var savedRunRef = React.useRef(Date.now());
38612
+ var runTimeRef = React.useRef(Date.now());
38613
+ var valuesTextbook = React.useRef(null);
38614
+ var isFirstLoadRef = React.useRef(true);
38615
+ var _React$useState = React__default.useState(PrintStatus.Idle),
38616
+ saveStatus = _React$useState[0],
38617
+ setSaveStatus = _React$useState[1];
38618
+ var timeoutRef = React.useRef(null);
38619
+ var isProcessingRef = React.useRef(false);
38620
+ var pendingValuesRef = React.useRef(null);
38621
+ var _useState = React.useState(),
38622
+ lastEdited = _useState[0],
38623
+ setLastEdited = _useState[1];
38549
38624
  React.useEffect(function () {
38550
38625
  var handleBeforeUnload = function handleBeforeUnload(event) {
38551
38626
  var message = i18n.t("are_you_sure_you_want_to_quit_yours_changes_may_not_be_saved");
@@ -38566,9 +38641,99 @@ var PreparedTextbookForm = function PreparedTextbookForm(_ref) {
38566
38641
  var newValues = _resetAllCategoriesAndQuestionTypesBySubject(values, val);
38567
38642
  setValues(newValues);
38568
38643
  };
38644
+ React.useEffect(function () {
38645
+ if (!valuesTextbook.current && isFirstLoadRef.current && !_$8.isEqual(values, DEFAULT_TEXTBOOK_REQUEST)) {
38646
+ valuesTextbook.current = _$8.cloneDeep(values);
38647
+ isFirstLoadRef.current = false;
38648
+ }
38649
+ }, [values]);
38650
+ var _handleSave = function handleSave(valuesProps) {
38651
+ try {
38652
+ var _temp = _finallyRethrows(function () {
38653
+ return _catch(function () {
38654
+ isProcessingRef.current = true;
38655
+ setSaveStatus(PrintStatus.Saving);
38656
+ var valuesToSave = valuesProps || values;
38657
+ return Promise.resolve(handleSaveData(valuesToSave)).then(function () {
38658
+ valuesTextbook.current = _$8.cloneDeep(valuesToSave);
38659
+ var now = Date.now();
38660
+ savedRunRef.current = now;
38661
+ runTimeRef.current = now;
38662
+ setSaveStatus(PrintStatus.Saved);
38663
+ });
38664
+ }, function (error) {
38665
+ setSaveStatus(PrintStatus.Idle);
38666
+ console.error(error);
38667
+ });
38668
+ }, function (_wasThrown, _result) {
38669
+ isProcessingRef.current = false;
38670
+ if (pendingValuesRef.current) {
38671
+ if (timeoutRef.current) {
38672
+ clearTimeout(timeoutRef.current);
38673
+ }
38674
+ timeoutRef.current = setTimeout(function () {
38675
+ timeoutRef.current = null;
38676
+ var pendingValues = pendingValuesRef.current;
38677
+ if (pendingValues) {
38678
+ _handleSave(pendingValues);
38679
+ pendingValuesRef.current = null;
38680
+ }
38681
+ }, SAVE_TIME_INTERVAL_IN_MILLISECONDS);
38682
+ }
38683
+ if (_wasThrown) throw _result;
38684
+ return _result;
38685
+ });
38686
+ return Promise.resolve(_temp && _temp.then ? _temp.then(function () {}) : void 0);
38687
+ } catch (e) {
38688
+ return Promise.reject(e);
38689
+ }
38690
+ };
38691
+ React.useEffect(function () {
38692
+ var now = Date.now();
38693
+ if (valuesTextbook.current && !_$8.isEqual(values, valuesTextbook.current)) setLastEdited(now);
38694
+ if (!_$8.isEmpty(errors) || !valuesTextbook.current || !(selectedTextbook !== null && selectedTextbook !== void 0 && selectedTextbook.id)) return;
38695
+ if (valuesTextbook.current && _$8.isEqual(values, valuesTextbook.current)) return;
38696
+ if (isProcessingRef.current) {
38697
+ pendingValuesRef.current = _$8.cloneDeep(values);
38698
+ return;
38699
+ }
38700
+ var timeSinceLastRun = now - runTimeRef.current;
38701
+ var maxTime = SAVE_TIME_INTERVAL_IN_MILLISECONDS + SAVE_TIME_MAX_DIFF_IN_MILLISECONDS;
38702
+ if (timeSinceLastRun > maxTime) {
38703
+ runTimeRef.current = now;
38704
+ timeSinceLastRun = 0;
38705
+ }
38706
+ if (timeSinceLastRun >= SAVE_TIME_INTERVAL_IN_MILLISECONDS) {
38707
+ if (timeoutRef.current) {
38708
+ clearTimeout(timeoutRef.current);
38709
+ timeoutRef.current = null;
38710
+ pendingValuesRef.current = null;
38711
+ }
38712
+ _handleSave();
38713
+ } else {
38714
+ pendingValuesRef.current = _$8.cloneDeep(values);
38715
+ var intevalTime = SAVE_TIME_INTERVAL_IN_MILLISECONDS - timeSinceLastRun;
38716
+ timeoutRef.current = setTimeout(function () {
38717
+ timeoutRef.current = null;
38718
+ var pendingValues = pendingValuesRef.current;
38719
+ if (pendingValues) {
38720
+ clearTimeout(timeoutRef.current);
38721
+ _handleSave(pendingValues);
38722
+ pendingValuesRef.current = null;
38723
+ }
38724
+ }, intevalTime);
38725
+ }
38726
+ return function () {
38727
+ if (timeoutRef.current) {
38728
+ clearTimeout(timeoutRef.current);
38729
+ }
38730
+ };
38731
+ }, [values, errors]);
38569
38732
  var inforErrors = errors.coverImage || errors.grade || errors.isbn || errors.preparedType || errors.publicationDate || errors.publisher;
38570
38733
  var contentsErrors = errors.chapters;
38571
38734
  var textbookOwnersErrors = errors.textbookOwners;
38735
+ var hasError = !_$8.isEmpty(errors);
38736
+ var isSaved = !lastEdited || _$8.isEqual(values, (_valuesTextbook$curre = valuesTextbook.current) != null ? _valuesTextbook$curre : {});
38572
38737
  return React__default.createElement(formik.Form, null, React__default.createElement(material.Stack, {
38573
38738
  direction: "column",
38574
38739
  gap: 3
@@ -38656,7 +38821,45 @@ var PreparedTextbookForm = function PreparedTextbookForm(_ref) {
38656
38821
  }), React__default.createElement(material.FormLabel, {
38657
38822
  htmlFor: "type",
38658
38823
  className: "text-center"
38659
- }, i18n.t("math"))))), React__default.createElement(material.Box, null, React__default.createElement(material.Button, {
38824
+ }, i18n.t("math"))))), React__default.createElement(material.Stack, {
38825
+ flexDirection: "row",
38826
+ gap: "8px"
38827
+ }, !!(selectedTextbook !== null && selectedTextbook !== void 0 && selectedTextbook.id) && React__default.createElement(material.Stack, {
38828
+ padding: "6px 12px",
38829
+ sx: {
38830
+ transition: "opacity 0.3s ease",
38831
+ opacity: saveStatus === PrintStatus.Idle && isSaved ? 0 : 1,
38832
+ pointerEvents: "none",
38833
+ gap: "8px",
38834
+ flexDirection: "row",
38835
+ justifyContent: "center",
38836
+ alignItems: "center"
38837
+ }
38838
+ }, saveStatus === PrintStatus.Saving && React__default.createElement(ai.AiOutlineLoading3Quarters, {
38839
+ style: {
38840
+ animation: "spin 1s linear infinite"
38841
+ }
38842
+ }), saveStatus === PrintStatus.Saved && isSaved && React__default.createElement(io5.IoCheckmark, null), saveStatus !== PrintStatus.Saving && !isSaved && React__default.createElement(React.Fragment, null, hasError ? React__default.createElement(md.MdError, {
38843
+ color: red[900]
38844
+ }) : React__default.createElement(fa6.FaClockRotateLeft, {
38845
+ size: "14px"
38846
+ })), React__default.createElement(material.Typography, {
38847
+ sx: {
38848
+ color: theme.palette.grey[700],
38849
+ fontSize: "14px",
38850
+ display: "flex",
38851
+ alignItems: "center",
38852
+ gap: 1,
38853
+ "@keyframes spin": {
38854
+ "0%": {
38855
+ transform: "rotate(0deg)"
38856
+ },
38857
+ "100%": {
38858
+ transform: "rotate(360deg)"
38859
+ }
38860
+ }
38861
+ }
38862
+ }, saveStatus === PrintStatus.Saving && i18n.t("saving"), saveStatus === PrintStatus.Saved && isSaved && i18n.t("all_changes_saved"), saveStatus !== PrintStatus.Saving && !isSaved && i18n.t("all_changes_are_not_saved_yet"))), React__default.createElement(material.Button, {
38660
38863
  type: "submit",
38661
38864
  sx: {
38662
38865
  width: "fit-content"
@@ -38763,6 +38966,7 @@ var PreparedTextbookView = function PreparedTextbookView(_ref) {
38763
38966
  isSuperAdminUser = _useTextbookManagemen.isSuperAdminUser,
38764
38967
  isAdmin = _useTextbookManagemen.isAdmin,
38765
38968
  coverImage = _useTextbookManagemen.coverImage,
38969
+ handleSaveData = _useTextbookManagemen.handleSaveData,
38766
38970
  selectedTextbook = _useTextbookManagemen.selectedTextbook,
38767
38971
  handleSubmit = _useTextbookManagemen.handleSubmit,
38768
38972
  handleUploadImage = _useTextbookManagemen.handleUploadImage;
@@ -38785,7 +38989,9 @@ var PreparedTextbookView = function PreparedTextbookView(_ref) {
38785
38989
  isAdmin: isAdmin,
38786
38990
  isSuperAdmin: isSuperAdmin,
38787
38991
  selected: selected,
38992
+ handleSaveData: handleSaveData,
38788
38993
  textbookId: textbookId,
38994
+ selectedTextbook: selectedTextbook,
38789
38995
  onChangeTab: handleChangeTab,
38790
38996
  onUploadImage: handleUploadImage,
38791
38997
  coverImage: coverImage,