pages_classroom_new.tsx 5.2 KB

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