From f3b953da4f2ad76a569aa86d915a13876f551661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96ZT=C3=9CRK?= <76204082+iamsedatozturk@users.noreply.github.com> Date: Fri, 29 Aug 2025 14:41:47 +0300 Subject: [PATCH] =?UTF-8?q?Chat=20ve=20Attandace=20=C3=B6zellikleri=20veri?= =?UTF-8?q?taban=C4=B1=C4=B1ndan=20y=C3=BCkleniyor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Classroom/ClassroomAppService.cs | 38 +++++++- .../components/classroom/Panels/ChatPanel.tsx | 1 + ui/src/proxy/classroom/models.ts | 3 +- ui/src/services/classroom.service.ts | 26 ++++- ui/src/views/classroom/Dashboard.tsx | 5 +- ui/src/views/classroom/RoomDetail.tsx | 95 ++++++++----------- 6 files changed, 104 insertions(+), 64 deletions(-) diff --git a/api/src/Kurs.Platform.Application/Classroom/ClassroomAppService.cs b/api/src/Kurs.Platform.Application/Classroom/ClassroomAppService.cs index 900a2e9b..6f9e6b55 100644 --- a/api/src/Kurs.Platform.Application/Classroom/ClassroomAppService.cs +++ b/api/src/Kurs.Platform.Application/Classroom/ClassroomAppService.cs @@ -17,15 +17,18 @@ public class ClassroomAppService : PlatformAppService, IClassroomAppService private readonly IRepository _classSessionRepository; private readonly IRepository _participantRepository; private readonly IRepository _attendanceRepository; + private readonly IRepository _chatRepository; public ClassroomAppService( IRepository classSessionRepository, IRepository participantRepository, - IRepository attendanceRepository) + IRepository attendanceRepository, + IRepository chatRepository) { _classSessionRepository = classSessionRepository; _participantRepository = participantRepository; _attendanceRepository = attendanceRepository; + _chatRepository = chatRepository; } public async Task GetAsync(Guid id) @@ -271,4 +274,37 @@ public class ClassroomAppService : PlatformAppService, IClassroomAppService return ObjectMapper.Map, List>(attendanceRecords); } + + public async Task> GetParticipantAsync(Guid sessionId) + { + var classSession = await _classSessionRepository.GetAsync(sessionId); + + if (classSession.TeacherId != CurrentUser.Id) + { + throw new UnauthorizedAccessException("Only the teacher can view participant"); + } + + var participantRecords = await _participantRepository.GetListAsync( + x => x.SessionId == sessionId + ); + + return ObjectMapper.Map, List>(participantRecords); + } + + public async Task> GetChatAsync(Guid sessionId) + { + var classSession = await _classSessionRepository.GetAsync(sessionId); + + if (classSession.TeacherId != CurrentUser.Id) + { + throw new UnauthorizedAccessException("Only the teacher can view chat"); + } + + var chatRecords = await _chatRepository.GetListAsync( + x => x.SessionId == sessionId + ); + + return ObjectMapper.Map, List>(chatRecords); + } + } \ No newline at end of file diff --git a/ui/src/components/classroom/Panels/ChatPanel.tsx b/ui/src/components/classroom/Panels/ChatPanel.tsx index a043d228..7926dfde 100644 --- a/ui/src/components/classroom/Panels/ChatPanel.tsx +++ b/ui/src/components/classroom/Panels/ChatPanel.tsx @@ -144,6 +144,7 @@ export const ChatPanel: React.FC = ({ )} + {/* Messages */}
{messages.length === 0 ? ( diff --git a/ui/src/proxy/classroom/models.ts b/ui/src/proxy/classroom/models.ts index c492c99c..c33fe7c7 100644 --- a/ui/src/proxy/classroom/models.ts +++ b/ui/src/proxy/classroom/models.ts @@ -66,12 +66,13 @@ export type messageType = 'public' | 'private' | 'announcement' export interface ClassroomChatDto { id: string + sessionId: string senderId: string senderName: string message: string timestamp: string isTeacher: boolean - recipientId?: string // Özel mesaj için + recipientId?: string recipientName?: string messageType: messageType } diff --git a/ui/src/services/classroom.service.ts b/ui/src/services/classroom.service.ts index b9cb7c9f..78c7295a 100644 --- a/ui/src/services/classroom.service.ts +++ b/ui/src/services/classroom.service.ts @@ -1,4 +1,10 @@ -import { ClassroomDto, ClassroomFilterInputDto } from '@/proxy/classroom/models' +import { + ClassroomAttendanceDto, + ClassroomChatDto, + ClassroomDto, + ClassroomFilterInputDto, + ClassroomParticipantDto, +} from '@/proxy/classroom/models' import apiService from './api.service' import { PagedAndSortedResultRequestDto, PagedResultDto } from '@/proxy' @@ -46,3 +52,21 @@ export const endClassroom = (id: string) => method: 'PUT', url: `/api/app/classroom/${id}/end-class`, }) + +export const getClassroomAttandances = (id: string) => + apiService.fetchData({ + method: 'GET', + url: `/api/app/classroom/attendance/${id}`, + }) + +export const getClassroomParticipants = (id: string) => + apiService.fetchData({ + method: 'GET', + url: `/api/app/classroom/participant/${id}`, + }) + +export const getClassroomChats = (id: string) => + apiService.fetchData({ + method: 'GET', + url: `/api/app/classroom/chat/${id}`, + }) diff --git a/ui/src/views/classroom/Dashboard.tsx b/ui/src/views/classroom/Dashboard.tsx index 85dc20f1..79ed5c3f 100644 --- a/ui/src/views/classroom/Dashboard.tsx +++ b/ui/src/views/classroom/Dashboard.tsx @@ -7,7 +7,6 @@ import { useNavigate } from 'react-router-dom' import { ROUTES_ENUM } from '@/routes/route.constant' import { Helmet } from 'react-helmet' import { useLocalization } from '@/utils/hooks/useLocalization' -import { Container } from '@/components/shared' const Dashboard: React.FC = () => { const navigate = useNavigate() @@ -31,7 +30,7 @@ const Dashboard: React.FC = () => { title={translate('::' + 'App.Classroom')} defaultTitle="Kurs Platform" > - +
{
-
+
) } diff --git a/ui/src/views/classroom/RoomDetail.tsx b/ui/src/views/classroom/RoomDetail.tsx index 6323920c..5c08eb94 100644 --- a/ui/src/views/classroom/RoomDetail.tsx +++ b/ui/src/views/classroom/RoomDetail.tsx @@ -53,7 +53,11 @@ import { ParticipantGrid } from '@/components/classroom/ParticipantGrid' import { ScreenSharePanel } from '@/components/classroom/Panels/ScreenSharePanel' import { KickParticipantModal } from '@/components/classroom/KickParticipantModal' import { useParams } from 'react-router-dom' -import { getClassroomById } from '@/services/classroom.service' +import { + getClassroomAttandances, + getClassroomById, + getClassroomChats, +} from '@/services/classroom.service' import { showDbDateAsIs } from '@/utils/dateUtils' import { useNavigate } from 'react-router-dom' import { endClassroom } from '@/services/classroom.service' @@ -162,6 +166,22 @@ const RoomDetail: React.FC = () => { }, ] + const fetchClassAttendances = async () => { + if (!params?.id) return + const attResult = await getClassroomAttandances(params.id) + if (attResult && attResult.data) { + setAttendanceRecords(attResult.data) + } + } + + const fetchClassChats = async () => { + if (!params?.id) return + const chatResult = await getClassroomChats(params.id) + if (chatResult && chatResult.data) { + setChatMessages(chatResult.data || []) + } + } + const fetchClassDetails = async () => { const classEntity = await getClassroomById(params?.id ?? '') if (classEntity) { @@ -172,6 +192,8 @@ const RoomDetail: React.FC = () => { useEffect(() => { fetchClassDetails() + fetchClassChats() + fetchClassAttendances() }, []) useEffect(() => { @@ -558,52 +580,6 @@ const RoomDetail: React.FC = () => { ) } - // // Demo: Simulate student joining - // const simulateStudentJoin = () => { - // const studentNames = ['Ahmet Yılmaz', 'Fatma Demir', 'Mehmet Kaya', 'Ayşe Özkan', 'Ali Çelik'] - // const availableNames = studentNames.filter((name) => !participants.some((p) => p.name === name)) - - // if (availableNames.length === 0) { - // alert('Tüm demo öğrenciler zaten sınıfta!') - // return - // } - - // const randomName = availableNames[Math.floor(Math.random() * availableNames.length)] - // const studentId = crypto.randomUUID() - - // setParticipants((prev) => { - // return [ - // ...prev, - // { - // id: studentId, - // name: randomName, - // isTeacher: false, - // isAudioMuted: classSettings.autoMuteNewParticipants, - // isVideoMuted: classSettings.defaultCameraState === 'off', - // }, - // ] - // }) - - // // Add attendance record - // setAttendanceRecords((prev: any) => { - // // Check if student already has an active attendance record - // const existingRecord = prev.find((r: any) => r.studentId === studentId && !r.leaveTime) - // if (existingRecord) return prev - - // return [ - // ...prev, - // { - // id: crypto.randomUUID(), - // sessionId: classSession.id, - // studentId, - // studentName: randomName, - // joinTime: new Date().toISOString(), - // totalDurationMinutes: 0, - // }, - // ] - // }) - // } - const handleSettingsChange = (newSettings: Partial) => { setClassSettings((prev) => ({ ...prev, ...newSettings })) } @@ -921,17 +897,20 @@ const RoomDetail: React.FC = () => { Katılımcılar - + + {user.role === 'teacher' && ( + + )}