diff --git a/api/src/Kurs.Platform.Application.Contracts/Classroom/ClassroomFilterInputDto.cs b/api/src/Kurs.Platform.Application.Contracts/Classroom/ClassroomFilterInputDto.cs new file mode 100644 index 00000000..17ee9458 --- /dev/null +++ b/api/src/Kurs.Platform.Application.Contracts/Classroom/ClassroomFilterInputDto.cs @@ -0,0 +1,7 @@ +using Volo.Abp.Application.Dtos; + +public class ClassroomFilterInputDto : PagedAndSortedResultRequestDto +{ + public string Search { get; set; } + public string Status { get; set; } +} \ No newline at end of file diff --git a/api/src/Kurs.Platform.Application.Contracts/Classroom/IClassroomAppService.cs b/api/src/Kurs.Platform.Application.Contracts/Classroom/IClassroomAppService.cs index c37f39de..010a6bdf 100644 --- a/api/src/Kurs.Platform.Application.Contracts/Classroom/IClassroomAppService.cs +++ b/api/src/Kurs.Platform.Application.Contracts/Classroom/IClassroomAppService.cs @@ -9,7 +9,7 @@ namespace Kurs.Platform.Classrooms; public interface IClassroomAppService : IApplicationService { Task GetAsync(Guid id); - Task> GetListAsync(PagedAndSortedResultRequestDto input); + Task> GetListAsync(ClassroomFilterInputDto input); Task CreateAsync(ClassroomDto input); Task UpdateAsync(Guid id, ClassroomDto input); Task DeleteAsync(Guid id); diff --git a/api/src/Kurs.Platform.Application/Classroom/ClassroomAppService.cs b/api/src/Kurs.Platform.Application/Classroom/ClassroomAppService.cs index 03a2097d..af493eaa 100644 --- a/api/src/Kurs.Platform.Application/Classroom/ClassroomAppService.cs +++ b/api/src/Kurs.Platform.Application/Classroom/ClassroomAppService.cs @@ -34,9 +34,39 @@ public class ClassroomAppService : PlatformAppService, IClassroomAppService return ObjectMapper.Map(classSession); } - public async Task> GetListAsync(PagedAndSortedResultRequestDto input) + public async Task> GetListAsync(ClassroomFilterInputDto input) { var query = await _classSessionRepository.GetQueryableAsync(); + + if (!string.IsNullOrWhiteSpace(input.Search)) + { + query = query.Where(x => + x.Name.Contains(input.Search) || + x.Description.Contains(input.Search) || + x.Subject.Contains(input.Search) || + x.TeacherName.Contains(input.Search) + ); + } + + if (!string.IsNullOrWhiteSpace(input.Status)) + { + switch (input.Status) + { + case "Active": + query = query.Where(x => x.ActualStartTime == null && x.ActualEndTime == null); + break; + + case "Open": + query = query.Where(x => x.ActualStartTime != null && x.ActualEndTime == null); + break; + + case "Passive": + query = query.Where(x => x.ActualEndTime != null); + break; + } + } + + var totalCount = query.Count(); var items = query .OrderBy(x => x.ScheduledStartTime) diff --git a/ui/src/proxy/classroom/models.ts b/ui/src/proxy/classroom/models.ts index 46631718..b79784c8 100644 --- a/ui/src/proxy/classroom/models.ts +++ b/ui/src/proxy/classroom/models.ts @@ -1,3 +1,5 @@ +import { PagedAndSortedResultRequestDto } from '../abp' + export type RoleState = 'role-selection' | 'dashboard' | 'classroom' export type Role = 'teacher' | 'student' | 'observer' @@ -131,3 +133,8 @@ export interface ScreenShareRequestDto { userName: string isActive: boolean } + +export interface ClassroomFilterInputDto extends PagedAndSortedResultRequestDto { + search: string + status: string +} diff --git a/ui/src/services/classroom.service.ts b/ui/src/services/classroom.service.ts index 873c8934..b9cb7c9f 100644 --- a/ui/src/services/classroom.service.ts +++ b/ui/src/services/classroom.service.ts @@ -1,4 +1,4 @@ -import { ClassroomDto } from '@/proxy/classroom/models' +import { ClassroomDto, ClassroomFilterInputDto } from '@/proxy/classroom/models' import apiService from './api.service' import { PagedAndSortedResultRequestDto, PagedResultDto } from '@/proxy' @@ -8,7 +8,7 @@ export const getClassroomById = (id: string) => url: `/api/app/classroom/${id}`, }) -export const getClassrooms = (input: PagedAndSortedResultRequestDto) => +export const getClassrooms = (input: ClassroomFilterInputDto) => apiService.fetchData>({ method: 'GET', url: `/api/app/classroom`, diff --git a/ui/src/views/classroom/ClassList.tsx b/ui/src/views/classroom/ClassList.tsx index b3b4040d..8a6cc98a 100644 --- a/ui/src/views/classroom/ClassList.tsx +++ b/ui/src/views/classroom/ClassList.tsx @@ -13,6 +13,8 @@ import { FaEye, FaHourglassEnd, FaDoorOpen, + FaSearch, + FaFilter, } from 'react-icons/fa' import { ClassroomDto } from '@/proxy/classroom/models' @@ -70,12 +72,24 @@ const ClassList: React.FC = () => { const [showEditModal, setShowEditModal] = useState(false) const [showDeleteModal, setShowDeleteModal] = useState(false) - const getClassroomList = async (skipCount = 0, maxResultCount = 1000, sorting = '') => { + // Filter/search state + const [searchTerm, setSearchTerm] = useState('') + const [statusFilter, setStatusFilter] = useState('') + + const getClassroomList = async ( + skipCount = 0, + maxResultCount = 1000, + sorting = '', + search = '', + status = '', + ) => { try { const result = await getClassrooms({ sorting, skipCount, maxResultCount, + search, + status, }) const items = (result.data.items || []).map((item) => ({ @@ -93,8 +107,8 @@ const ClassList: React.FC = () => { } useEffect(() => { - getClassroomList() - }, []) + getClassroomList(0, 1000, '', searchTerm, statusFilter) + }, [searchTerm, statusFilter]) const handleCreateClass = async (e: React.FormEvent) => { e.preventDefault() @@ -166,13 +180,13 @@ const ClassList: React.FC = () => { } } - const canJoinClass = (actualStartTime: string) => { - const actualed = new Date(actualStartTime) - const now = new Date() - const tenMinutesBefore = new Date(actualed.getTime() - 10 * 60 * 1000) //10 dakika öncesine kadar - const twoHoursAfter = new Date(actualed.getTime() + 2 * 60 * 60 * 1000) // 2 saat sonrasına kadar - return now >= tenMinutesBefore && now <= twoHoursAfter - } + // const canJoinClass = (actualStartTime: string) => { + // const actualed = new Date(actualStartTime) + // const now = new Date() + // const tenMinutesBefore = new Date(actualed.getTime() - 10 * 60 * 1000) //10 dakika öncesine kadar + // const twoHoursAfter = new Date(actualed.getTime() + 2 * 60 * 60 * 1000) // 2 saat sonrasına kadar + // return now >= tenMinutesBefore && now <= twoHoursAfter + // } const widgets = () => { return { @@ -342,6 +356,36 @@ const ClassList: React.FC = () => { + {/* Filter Bar */} +
+
+
+ + setSearchTerm(e.target.value)} + /> +
+
+ + +
+
+
+ {/* Scheduled Classes */}