pages_classroom.tsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. import React, { useState, useEffect } from 'react';
  2. import { useAuth } from './hooks.tsx';
  3. import { useNavigate } from 'react-router';
  4. import { Role, ClassStatus } from './components/Classroom/useClassroom.ts';
  5. // import { TeacherView } from './components/Classroom/TeacherView.tsx';
  6. // import { StudentView } from './components/Classroom/StudentView.tsx';
  7. import { ClassroomLayout } from './components/Classroom/ClassroomLayout.tsx';
  8. import { AuthLayout } from './components/Classroom/AuthLayout.tsx';
  9. import { ClassroomProvider, useClassroomContext } from "./components/Classroom/ClassroomProvider.tsx";
  10. import { ToastContainer } from 'react-toastify';
  11. const RoleSelection = () => {
  12. const { setRole, login } = useClassroomContext();
  13. const chooseRole = (role: Role) => {
  14. setRole(role);
  15. login(role);
  16. }
  17. return (
  18. <div className="flex flex-col items-center justify-center h-full">
  19. <h2 className="text-2xl font-bold mb-8">请选择您的角色</h2>
  20. <div className="flex space-x-4">
  21. <button
  22. type="button"
  23. onClick={() => chooseRole(Role.Teacher)}
  24. className="px-6 py-3 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors"
  25. >
  26. 我是老师
  27. </button>
  28. <button
  29. type="button"
  30. onClick={() => chooseRole(Role.Student)}
  31. className="px-6 py-3 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors"
  32. >
  33. 我是学生
  34. </button>
  35. </div>
  36. </div>
  37. );
  38. };
  39. const JoinClassSection = () => {
  40. const { joinClass } = useClassroomContext();
  41. const [classId, setClassId] = useState('');
  42. const handleJoinClass = async () => {
  43. if (!classId.trim()) return;
  44. await joinClass(classId);
  45. };
  46. return (
  47. <div className="bg-white p-4 rounded shadow mb-4">
  48. <h3 className="font-bold mb-2">加入课堂</h3>
  49. <div className="flex space-x-2">
  50. <input
  51. type="text"
  52. value={classId}
  53. onChange={(e) => setClassId(e.target.value)}
  54. placeholder="输入课堂ID"
  55. className="flex-1 px-3 py-2 border rounded"
  56. />
  57. <button
  58. type="button"
  59. onClick={handleJoinClass}
  60. className="px-4 py-2 bg-blue-500 text-white rounded"
  61. >
  62. 加入课堂
  63. </button>
  64. </div>
  65. </div>
  66. );
  67. };
  68. const CreateClassSection = () => {
  69. const { classStatus, createClass, className, setClassName, role } = useClassroomContext();
  70. const navigate = useNavigate();
  71. const handleCreateClass = async () => {
  72. if (!className.trim()) return;
  73. const classId = await createClass(className);
  74. if (classId) {
  75. navigate(`/mobile/classroom/${classId}/${role === Role.Teacher ? Role.Teacher : Role.Student}`, { replace: true });
  76. }
  77. };
  78. if (classStatus !== ClassStatus.NOT_STARTED) return null;
  79. return (
  80. <div className="bg-white p-4 rounded shadow mb-4">
  81. <h3 className="font-bold mb-2">创建新课堂</h3>
  82. <div className="flex space-x-2">
  83. <input
  84. type="text"
  85. value={className}
  86. onChange={(e) => setClassName(e.target.value)}
  87. placeholder="输入课堂名称"
  88. className="flex-1 px-3 py-2 border rounded"
  89. />
  90. <button
  91. type="button"
  92. onClick={handleCreateClass}
  93. className="px-4 py-2 bg-green-500 text-white rounded"
  94. >
  95. 创建课堂
  96. </button>
  97. </div>
  98. </div>
  99. );
  100. };
  101. const Classroom = () => {
  102. const context = useClassroomContext();
  103. const { role, classStatus, isLoggedIn, login, classId, joinClass } = context;
  104. useEffect(() => {
  105. if (!isLoggedIn && role && classId) {
  106. (async () => {
  107. await login(role);
  108. await joinClass(classId);
  109. })()
  110. }
  111. }, [isLoggedIn, role , classId]);
  112. if (!role) {
  113. return (
  114. <AuthLayout>
  115. <RoleSelection />
  116. </AuthLayout>
  117. );
  118. }
  119. if (!isLoggedIn) {
  120. return (
  121. <AuthLayout>
  122. <div className="flex items-center justify-center h-full">
  123. <p>正在自动登录中...</p>
  124. </div>
  125. </AuthLayout>
  126. );
  127. }
  128. if (role === Role.Teacher && !context.isJoinedClass && !classId) {
  129. return (
  130. <>
  131. <AuthLayout>
  132. <CreateClassSection />
  133. </AuthLayout>
  134. </>
  135. );
  136. }
  137. if (role === Role.Student && !context.isJoinedClass && !classId) {
  138. return (
  139. <>
  140. <AuthLayout>
  141. <JoinClassSection />
  142. </AuthLayout>
  143. </>
  144. );
  145. }
  146. if (classStatus === ClassStatus.ENDED) {
  147. return (
  148. <div className="text-center py-8">
  149. <h2 className="text-xl font-bold">课堂已结束</h2>
  150. <p>感谢参与本次课堂</p>
  151. </div>
  152. );
  153. }
  154. return (
  155. <ClassroomLayout role={role}>
  156. {/* {role === Role.Teacher ? <TeacherView /> : <StudentView />} */}
  157. <></>
  158. </ClassroomLayout>
  159. );
  160. };
  161. export const ClassroomPage = () => {
  162. const { user } = useAuth();
  163. return (
  164. <>
  165. <ClassroomProvider user={user!}>
  166. <Classroom />
  167. </ClassroomProvider>
  168. <ToastContainer
  169. position="top-right"
  170. autoClose={500}
  171. hideProgressBar={false}
  172. newestOnTop={false}
  173. closeOnClick
  174. rtl={false}
  175. pauseOnFocusLoss
  176. draggable
  177. pauseOnHover
  178. />
  179. </>
  180. )
  181. }