diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json index b666c884..730161bd 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json @@ -2835,6 +2835,14 @@ "DisplayName": "App.Classroom.RoomDetail", "IsEnabled": true, "MultiTenancySide": 2 + }, + { + "GroupName": "App.Classroom", + "Name": "App.Classroom.Planning", + "ParentName": "App.Classroom", + "DisplayName": "App.Classroom.Planning", + "IsEnabled": true, + "MultiTenancySide": 2 } ], "Menus": [ @@ -3941,6 +3949,13 @@ "componentPath": "@/views/classroom/RoomDetail", "routeType": "protected", "authority": ["App.Classroom.RoomDetail"] + }, + { + "key": "admin.classroom.planning", + "path": "/admin/classroom/planning/:id", + "componentPath": "@/views/classroom/PlanningPage", + "routeType": "protected", + "authority": ["App.Classroom.Planning"] } ], "Languages": [ @@ -14184,8 +14199,14 @@ { "resourceName": "Platform", "key": "App.Classroom.RoomDetail", - "tr": "Virtul Classroom", - "en": "Sanal Sınıf" + "tr": "Sanal Sınıf", + "en": "Virtul Classroom" + }, + { + "resourceName": "Platform", + "key": "App.Classroom.Planning", + "tr": "Sınıf Planlama", + "en": "Classroom Planning" } ], "Settings": [ diff --git a/ui/dev-dist/sw.js b/ui/dev-dist/sw.js index e2d0c7ec..1ebbd15e 100644 --- a/ui/dev-dist/sw.js +++ b/ui/dev-dist/sw.js @@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict'; "revision": "3ca0b8505b4bec776b69afdba2768812" }, { "url": "index.html", - "revision": "0.d148klvmpj8" + "revision": "0.7r1n6s5iulg" }], {}); workbox.cleanupOutdatedCaches(); workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), { diff --git a/ui/src/components/classroom/data/classroom.ts b/ui/src/components/classroom/data/classroom.ts new file mode 100644 index 00000000..6ceffc9e --- /dev/null +++ b/ui/src/components/classroom/data/classroom.ts @@ -0,0 +1,64 @@ +import { Classroom } from '@/proxy/classroom/planning' + +export const classrooms: Classroom[] = [ + { + id: '1', + name: 'Theater Sınıfı', + layoutType: 'Theater', + rows: 6, + columns: 8, + capacity: 48, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '2', + name: 'U-Shape Sınıfı', + layoutType: 'UShape', + rows: 5, + columns: 8, + capacity: 40, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '3', + name: 'Bus Sınıfı', + layoutType: 'Bus', + rows: 10, + columns: 5, + capacity: 50, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '4', + name: 'Lab Sınıfı', + layoutType: 'Lab', + rows: 8, + columns: 6, + capacity: 48, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '5', + name: 'Exam Sınıfı', + layoutType: 'Exam', + rows: 10, + columns: 10, + capacity: 100, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '6', + name: 'Grid Sınıfı', + layoutType: 'Grid', + rows: 8, + columns: 8, + capacity: 64, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, +] diff --git a/ui/src/components/classroom/data/layouts.ts b/ui/src/components/classroom/data/layouts.ts new file mode 100644 index 00000000..2321f465 --- /dev/null +++ b/ui/src/components/classroom/data/layouts.ts @@ -0,0 +1,44 @@ +import { + FaBookOpen, + FaBus, + FaCircle, + FaFlask, + FaLayerGroup, + FaSquare, + FaThLarge, +} from 'react-icons/fa' + +export const layouts = [ + { + value: 'Theater', + label: 'Theater', + icon: FaThLarge, + description: 'Tam grid düzen', + }, + { value: 'Bus', label: 'Bus', icon: FaBus, description: 'Ortada koridor' }, + { + value: 'UShape', + label: 'U-Shape', + icon: FaSquare, + description: 'U şekli düzen', + }, + { + value: 'Grid', + label: 'Grid', + icon: FaLayerGroup, + description: 'Basit tablo', + }, + { value: 'Lab', label: 'Lab', icon: FaFlask, description: 'Masa grupları' }, + { + value: 'Exam', + label: 'Exam', + icon: FaBookOpen, + description: 'Sınav düzeni', + }, + { + value: 'Circle', + label: 'Circle', + icon: FaCircle, + description: 'Yuvarlak düzen', + }, +] diff --git a/ui/src/components/classroom/data/students.ts b/ui/src/components/classroom/data/students.ts new file mode 100644 index 00000000..b0a1fb8b --- /dev/null +++ b/ui/src/components/classroom/data/students.ts @@ -0,0 +1,454 @@ +import { Student } from '@/proxy/classroom/planning' + +export const mockStudents: Student[] = [ + { + id: '1', + fullName: 'Ahmet Yılmaz', + photoUrl: 'https://images.pexels.com/photos/1239291/pexels-photo-1239291.jpeg', + tags: ['Matematik', 'Fizik'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '2', + fullName: 'Ayşe Demir', + photoUrl: 'https://images.pexels.com/photos/733872/pexels-photo-733872.jpeg', + tags: ['Edebiyat', 'Tarih'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '3', + fullName: 'Mehmet Kaya', + photoUrl: 'https://images.pexels.com/photos/220453/pexels-photo-220453.jpeg', + tags: ['Kimya', 'Biyoloji'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '4', + fullName: 'Fatma Özkan', + photoUrl: 'https://images.pexels.com/photos/1181519/pexels-photo-1181519.jpeg', + tags: ['Geometri', 'Sanat'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '5', + fullName: 'Ali Çelik', + photoUrl: 'https://images.pexels.com/photos/2379004/pexels-photo-2379004.jpeg', + tags: ['İngilizce', 'Müzik'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '6', + fullName: 'Zeynep Arslan', + photoUrl: 'https://images.pexels.com/photos/1181686/pexels-photo-1181686.jpeg', + tags: ['Matematik', 'İngilizce'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '7', + fullName: 'Murat Doğan', + photoUrl: 'https://images.pexels.com/photos/2182970/pexels-photo-2182970.jpeg', + tags: ['Tarih', 'Coğrafya'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '8', + fullName: 'Elif Yıldız', + photoUrl: 'https://images.pexels.com/photos/1858175/pexels-photo-1858175.jpeg', + tags: ['Biyoloji', 'Edebiyat'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '9', + fullName: 'Osman Güler', + photoUrl: 'https://images.pexels.com/photos/2613260/pexels-photo-2613260.jpeg', + tags: ['Fizik', 'Kimya'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '10', + fullName: 'Hatice Aydın', + photoUrl: 'https://images.pexels.com/photos/1587009/pexels-photo-1587009.jpeg', + tags: ['Sanat', 'Müzik'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '11', + fullName: 'Emre Şahin', + photoUrl: 'https://images.pexels.com/photos/1819483/pexels-photo-1819483.jpeg', + tags: ['Matematik', 'Geometri'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '12', + fullName: 'Büşra Öztürk', + photoUrl: 'https://images.pexels.com/photos/1674752/pexels-photo-1674752.jpeg', + tags: ['İngilizce', 'Edebiyat'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '13', + fullName: 'Kemal Polat', + photoUrl: 'https://images.pexels.com/photos/2218208/pexels-photo-2218208.jpeg', + tags: ['Coğrafya', 'Tarih'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '14', + fullName: 'Selin Karaca', + photoUrl: 'https://images.pexels.com/photos/1468379/pexels-photo-1468379.jpeg', + tags: ['Biyoloji', 'Kimya'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '15', + fullName: 'Can Yavaş', + photoUrl: 'https://images.pexels.com/photos/2379005/pexels-photo-2379005.jpeg', + tags: ['Fizik', 'Matematik'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '16', + fullName: 'Deniz Mutlu', + photoUrl: 'https://images.pexels.com/photos/1040880/pexels-photo-1040880.jpeg', + tags: ['Müzik', 'Sanat'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '17', + fullName: 'Berk Koç', + photoUrl: 'https://images.pexels.com/photos/1043471/pexels-photo-1043471.jpeg', + tags: ['Geometri', 'Fizik'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '18', + fullName: 'Naz Aktaş', + photoUrl: 'https://images.pexels.com/photos/1559486/pexels-photo-1559486.jpeg', + tags: ['Edebiyat', 'İngilizce'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '19', + fullName: 'Arda Bulut', + photoUrl: 'https://images.pexels.com/photos/2379004/pexels-photo-2379004.jpeg', + tags: ['Tarih', 'Matematik'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '20', + fullName: 'İrem Tosun', + photoUrl: 'https://images.pexels.com/photos/1858175/pexels-photo-1858175.jpeg', + tags: ['Biyoloji', 'Sanat'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '21', + fullName: 'Kaan Erdoğan', + photoUrl: 'https://images.pexels.com/photos/2182970/pexels-photo-2182970.jpeg', + tags: ['Kimya', 'Coğrafya'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '22', + fullName: 'Lale Gündüz', + photoUrl: 'https://images.pexels.com/photos/1587009/pexels-photo-1587009.jpeg', + tags: ['Müzik', 'Edebiyat'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '23', + fullName: 'Rıza Özer', + photoUrl: 'https://images.pexels.com/photos/1239291/pexels-photo-1239291.jpeg', + tags: ['Fizik', 'Geometri'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '24', + fullName: 'Mine Akın', + photoUrl: 'https://images.pexels.com/photos/1181519/pexels-photo-1181519.jpeg', + tags: ['İngilizce', 'Tarih'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '25', + fullName: 'Tolga Şen', + photoUrl: 'https://images.pexels.com/photos/220453/pexels-photo-220453.jpeg', + tags: ['Matematik', 'Biyoloji'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '26', + fullName: 'Pınar Yıldırım', + photoUrl: 'https://images.pexels.com/photos/733872/pexels-photo-733872.jpeg', + tags: ['Sanat', 'Kimya'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '27', + fullName: 'Serkan Bozkurt', + photoUrl: 'https://images.pexels.com/photos/2613260/pexels-photo-2613260.jpeg', + tags: ['Coğrafya', 'Müzik'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '28', + fullName: 'Cansu Güven', + photoUrl: 'https://images.pexels.com/photos/1468379/pexels-photo-1468379.jpeg', + tags: ['Edebiyat', 'Fizik'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '29', + fullName: 'Barış Tekin', + photoUrl: 'https://images.pexels.com/photos/1819483/pexels-photo-1819483.jpeg', + tags: ['Matematik', 'Tarih'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '30', + fullName: 'Gizem Aslan', + photoUrl: 'https://images.pexels.com/photos/1674752/pexels-photo-1674752.jpeg', + tags: ['Biyoloji', 'İngilizce'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '31', + fullName: 'Cem Yılmaz', + photoUrl: 'https://images.pexels.com/photos/2218208/pexels-photo-2218208.jpeg', + tags: ['Fizik', 'Matematik'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '32', + fullName: 'Seda Kaya', + photoUrl: 'https://images.pexels.com/photos/1040880/pexels-photo-1040880.jpeg', + tags: ['Kimya', 'Biyoloji'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '33', + fullName: 'Burak Özkan', + photoUrl: 'https://images.pexels.com/photos/1043471/pexels-photo-1043471.jpeg', + tags: ['Tarih', 'Coğrafya'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '34', + fullName: 'Esra Demir', + photoUrl: 'https://images.pexels.com/photos/1559486/pexels-photo-1559486.jpeg', + tags: ['Edebiyat', 'Sanat'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '35', + fullName: 'Onur Çelik', + photoUrl: 'https://images.pexels.com/photos/2379004/pexels-photo-2379004.jpeg', + tags: ['İngilizce', 'Müzik'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '36', + fullName: 'Merve Arslan', + photoUrl: 'https://images.pexels.com/photos/1181686/pexels-photo-1181686.jpeg', + tags: ['Matematik', 'Geometri'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '37', + fullName: 'Hakan Doğan', + photoUrl: 'https://images.pexels.com/photos/2182970/pexels-photo-2182970.jpeg', + tags: ['Fizik', 'Kimya'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '38', + fullName: 'Aylin Yıldız', + photoUrl: 'https://images.pexels.com/photos/1858175/pexels-photo-1858175.jpeg', + tags: ['Biyoloji', 'Tarih'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '39', + fullName: 'Volkan Güler', + photoUrl: 'https://images.pexels.com/photos/2613260/pexels-photo-2613260.jpeg', + tags: ['Coğrafya', 'Edebiyat'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '40', + fullName: 'Sibel Aydın', + photoUrl: 'https://images.pexels.com/photos/1587009/pexels-photo-1587009.jpeg', + tags: ['Sanat', 'İngilizce'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '41', + fullName: 'Taner Şahin', + photoUrl: 'https://images.pexels.com/photos/1819483/pexels-photo-1819483.jpeg', + tags: ['Matematik', 'Müzik'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '42', + fullName: 'Gamze Öztürk', + photoUrl: 'https://images.pexels.com/photos/1674752/pexels-photo-1674752.jpeg', + tags: ['Fizik', 'Sanat'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '43', + fullName: 'Erhan Polat', + photoUrl: 'https://images.pexels.com/photos/2218208/pexels-photo-2218208.jpeg', + tags: ['Kimya', 'Geometri'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '44', + fullName: 'Dilek Karaca', + photoUrl: 'https://images.pexels.com/photos/1468379/pexels-photo-1468379.jpeg', + tags: ['Biyoloji', 'Edebiyat'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '45', + fullName: 'Mert Yavaş', + photoUrl: 'https://images.pexels.com/photos/2379005/pexels-photo-2379005.jpeg', + tags: ['Tarih', 'İngilizce'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '46', + fullName: 'Özge Mutlu', + photoUrl: 'https://images.pexels.com/photos/1040880/pexels-photo-1040880.jpeg', + tags: ['Coğrafya', 'Müzik'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '47', + fullName: 'Koray Koç', + photoUrl: 'https://images.pexels.com/photos/1043471/pexels-photo-1043471.jpeg', + tags: ['Matematik', 'Fizik'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '48', + fullName: 'Yeliz Aktaş', + photoUrl: 'https://images.pexels.com/photos/1559486/pexels-photo-1559486.jpeg', + tags: ['Sanat', 'Biyoloji'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '49', + fullName: 'Serdar Bulut', + photoUrl: 'https://images.pexels.com/photos/2379004/pexels-photo-2379004.jpeg', + tags: ['Kimya', 'Tarih'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, + { + id: '50', + fullName: 'Nilüfer Tosun', + photoUrl: 'https://images.pexels.com/photos/1858175/pexels-photo-1858175.jpeg', + tags: ['Edebiyat', 'Geometri'], + isActive: true, + creationTime: '2023-01-01T00:00:00Z', + lastModificationTime: '2023-01-01T00:00:00Z', + }, +] diff --git a/ui/src/components/classroom/ChatPanel.tsx b/ui/src/components/classroom/panels/ChatPanel.tsx similarity index 100% rename from ui/src/components/classroom/ChatPanel.tsx rename to ui/src/components/classroom/panels/ChatPanel.tsx diff --git a/ui/src/components/classroom/DocumentsPanel.tsx b/ui/src/components/classroom/panels/DocumentsPanel.tsx similarity index 100% rename from ui/src/components/classroom/DocumentsPanel.tsx rename to ui/src/components/classroom/panels/DocumentsPanel.tsx diff --git a/ui/src/components/classroom/LayoutPanel.tsx b/ui/src/components/classroom/panels/LayoutPanel.tsx similarity index 100% rename from ui/src/components/classroom/LayoutPanel.tsx rename to ui/src/components/classroom/panels/LayoutPanel.tsx diff --git a/ui/src/components/classroom/ParticipantsPanel.tsx b/ui/src/components/classroom/panels/ParticipantsPanel.tsx similarity index 100% rename from ui/src/components/classroom/ParticipantsPanel.tsx rename to ui/src/components/classroom/panels/ParticipantsPanel.tsx diff --git a/ui/src/components/classroom/ScreenSharePanel.tsx b/ui/src/components/classroom/panels/ScreenSharePanel.tsx similarity index 100% rename from ui/src/components/classroom/ScreenSharePanel.tsx rename to ui/src/components/classroom/panels/ScreenSharePanel.tsx diff --git a/ui/src/components/classroom/SettingsPanel.tsx b/ui/src/components/classroom/panels/SettingsPanel.tsx similarity index 100% rename from ui/src/components/classroom/SettingsPanel.tsx rename to ui/src/components/classroom/panels/SettingsPanel.tsx diff --git a/ui/src/components/classroom/planning/ClassroomSelector.tsx b/ui/src/components/classroom/planning/ClassroomSelector.tsx new file mode 100644 index 00000000..cafcc89b --- /dev/null +++ b/ui/src/components/classroom/planning/ClassroomSelector.tsx @@ -0,0 +1,31 @@ +import { Classroom } from '@/proxy/classroom/planning' +import React from 'react' +import { classrooms } from '../data/classroom' + +interface ClassroomSelectorProps { + selectedClassroom: Classroom | null + onClassroomChange: (classroom: Classroom | null) => void +} + +export const ClassroomSelector: React.FC = ({ + selectedClassroom, + onClassroomChange, +}) => { + return ( +
+ +
+ ) +} diff --git a/ui/src/components/classroom/planning/QuickActions.tsx b/ui/src/components/classroom/planning/QuickActions.tsx new file mode 100644 index 00000000..1c7a4c8c --- /dev/null +++ b/ui/src/components/classroom/planning/QuickActions.tsx @@ -0,0 +1,145 @@ +import React from 'react' +import { Card } from '@/components/ui/Card' +import { Button } from '@/components/ui/Button' +import { Avatar } from '@/components/ui/Avatar' +import { FaPhone, FaEnvelope, FaRegCommentDots, FaUserTimes } from 'react-icons/fa' +import { Seat, Student } from '@/proxy/classroom/planning' + +interface QuickActionsProps { + selectedSeats: string[] + seats: Seat[] + students: Student[] + onRemoveSelectedStudents: () => void + onToggleSeatBlock: () => void +} + +export const QuickActions: React.FC = ({ + selectedSeats, + seats, + students, + onRemoveSelectedStudents, +}) => { + const selectedStudents = selectedSeats + .map((seatId) => { + const seat = seats.find((s) => s.id === seatId) + return seat?.studentId ? students.find((s) => s.id === seat.studentId) : null + }) + .filter(Boolean) as Student[] + + return ( +
+ {/* Statistics */} + İstatistikler} + headerClass="p-2" + > +
+
+ Toplam koltuk: + {seats.length} +
+
+ Dolu koltuk: + + {seats.filter((s) => s.studentId).length} + +
+
+ Boş koltuk: + + {seats.filter((s) => !s.studentId && !s.isBlocked).length} + +
+
+
+ Doluluk oranı: + + {Math.round((seats.filter((s) => s.studentId).length / seats.length) * 100)}% + +
+
+
+
+ + {/* Selection Info */} + Seçilen Koltuk ({selectedStudents.length})} + headerClass="p-2" + > +
+ {/* Quick Actions */} + {selectedStudents.length > 0 && ( + +
+ {selectedStudents.length > 0 && ( + <> + + + + + )} + + {selectedSeats.length > 0 && ( + <> + + + )} +
+
+ )} + + {/* Selected Students */} + {selectedStudents.length > 0 && ( + + + {selectedStudents.map((student) => ( +
+ +
+
{student.fullName}
+
+
+ ))} + +
+ )} +
+
+
+ ) +} diff --git a/ui/src/components/classroom/planning/SeatGrid.tsx b/ui/src/components/classroom/planning/SeatGrid.tsx new file mode 100644 index 00000000..01faac86 --- /dev/null +++ b/ui/src/components/classroom/planning/SeatGrid.tsx @@ -0,0 +1,186 @@ +import React from 'react' +import { useDroppable } from '@dnd-kit/core' +import { Avatar } from '@/components/ui/Avatar' +import { FaTimes } from 'react-icons/fa' +import { Seat, SeatGridProps, Student } from '@/proxy/classroom/planning' + +const DroppableSeat: React.FC<{ + seat: Seat + student?: Student + isSelected: boolean + onSelect: () => void + onRemoveStudent: () => void +}> = ({ seat, student, isSelected, onSelect, onRemoveStudent }) => { + const { isOver, setNodeRef } = useDroppable({ + id: seat.id, + }) + + const isEmpty = !student + const isBlocked = seat.isBlocked + const canDrop = !isBlocked // Bloke olmayan tüm koltuklar drop edilebilir + const canSelect = !isEmpty // Sadece dolu koltuklar seçilebilir + + return ( +
+
+ {student ? ( + + {student.fullName + .split(' ') + .map((n) => n[0]) + .join('')} + + ) : ( + + {seat.label} + + )} + + {/* Drop indicator */} + {isOver && canDrop && isEmpty && ( +
+ )} + + {/* Drop indicator for occupied seats */} + {isOver && canDrop && !isEmpty && ( +
+ )} + + {/* Invalid drop indicator */} + {isOver && !canDrop && ( +
+ )} +
+ + {/* Remove button - sadece dolu koltuklar için */} + {student && ( + + )} + + {/* Tooltip on hover */} + {student && ( +
+ {student.fullName} +
+ )} +
+ ) +} + +export const SeatGrid: React.FC = ({ + classroom, + seats, + students, + selectedSeats, + onSeatSelect, + onRemoveStudent, +}) => { + const handleSeatSelect = (seatId: string) => { + if (selectedSeats.includes(seatId)) { + onSeatSelect(selectedSeats.filter((id) => id !== seatId)) + } else { + onSeatSelect([...selectedSeats, seatId]) + } + } + + // Create grid layout + const grid = Array.from({ length: classroom.rows }, (_, row) => + Array.from({ length: classroom.columns }, (_, col) => { + const seat = seats.find((s) => s.row === row && s.col === col) + const student = seat?.studentId ? students.find((s) => s.id === seat.studentId) : undefined + return { seat, student } + }), + ) + + return ( +
+
+
TAHTA
+
+ + {/* Seat Grid */} +
+ {grid.flat().map(({ seat, student }, index) => { + if (!seat) return
+ + return ( + handleSeatSelect(seat.id)} + onRemoveStudent={() => onRemoveStudent(seat.id)} + /> + ) + })} +
+ + {/* Legend */} +
+
+
+ Boş +
+
+
+ Dolu +
+
+
+ ) +} diff --git a/ui/src/components/classroom/planning/StudentList.tsx b/ui/src/components/classroom/planning/StudentList.tsx new file mode 100644 index 00000000..69f47d9f --- /dev/null +++ b/ui/src/components/classroom/planning/StudentList.tsx @@ -0,0 +1,60 @@ +import React from 'react' +import { useDraggable } from '@dnd-kit/core' +import { Avatar } from '@/components/ui/Avatar' +import { Student, StudentListProps } from '@/proxy/classroom/planning' + +const DraggableStudent: React.FC<{ student: Student }> = ({ student }) => { + const { attributes, listeners, setNodeRef, transform, isDragging } = useDraggable({ + id: student.id, + }) + + const style = transform + ? { + transform: `translate3d(${transform.x}px, ${transform.y}px, 0)`, + } + : undefined + + return ( +
+
+ + {student.fullName + .split(' ') + .map((n) => n[0]) + .join('')} + + +
+
+ {student.fullName} +
+
+
+
+ ) +} + +export const StudentList: React.FC = ({ students }) => { + return ( +
+
+ {students.length === 0 ? ( +
+
Öğrenci bulunamadı
+
Arama kriterlerinizi değiştirin
+
+ ) : ( + students.map((student) => ) + )} +
+
+ ) +} diff --git a/ui/src/proxy/classroom/planning.ts b/ui/src/proxy/classroom/planning.ts new file mode 100644 index 00000000..4f977b02 --- /dev/null +++ b/ui/src/proxy/classroom/planning.ts @@ -0,0 +1,123 @@ +export interface Student { + id: string + fullName: string + photoUrl: string | null + tags: string[] + isActive: boolean + creationTime: string + lastModificationTime: string +} + +export interface SeatGridProps { + classroom: Classroom + seats: Seat[] + students: Student[] + selectedSeats: string[] + onSeatSelect: (seatIds: string[]) => void + onRemoveStudent: (seatId: string) => void +} + +export interface StudentListProps { + students: Student[] + searchQuery: string + selectedTags: string[] +} + +export interface Seat { + id: string + row: number + col: number + label: string + isBlocked: boolean + studentId?: string + seatType: SeatType + concurrencyStamp: string + creationTime: string + lastModificationTime: string +} + +export interface Classroom { + id: string + name: string + layoutType: string + rows: number + columns: number + capacity: number + creationTime: string + lastModificationTime: string +} + +export interface StudentQuery { + q?: string + tags?: string[] + page?: number + size?: number + isActive?: boolean +} + +// Classroom types +export type LayoutType = 'Theater' | 'Bus' | 'UShape' | 'Grid' | 'Lab' | 'Exam' | 'Circle' +export type SeatType = 'Standard' | 'Table' | 'Wheelchair' +export type AssignmentStrategy = 'FillByOrder' | 'MatchByIndex' + +export interface SeatAssignment { + id: string + classroomId: string + seatId: string + studentId: string + assignedAt: string + assignedBy: string +} + +export interface SeatMap { + classroom: Classroom + seats: Seat[] + assignments: SeatAssignment[] +} + +// Assignment operations +export interface AssignSingleDto { + seatId: string + studentId: string +} + +export interface AssignBulkDto { + seatIds: string[] + studentIds: string[] + strategy: AssignmentStrategy +} + +export interface AssignmentResult { + success: boolean + assignedCount: number + errors?: string[] +} + +// Real-time events +export interface SseEvent { + id: string + event: string + data: any + timestamp: string +} + +export interface SeatAssignedEvent { + classroomId: string + seatId: string + studentId: string + ts: string + id: string +} + +export interface SeatUnassignedEvent { + classroomId: string + seatId: string + ts: string + id: string +} + +export interface LayoutChangedEvent { + classroomId: string + ts: string + id: string +} diff --git a/ui/src/routes/route.constant.ts b/ui/src/routes/route.constant.ts index 57c201fa..f777dffd 100644 --- a/ui/src/routes/route.constant.ts +++ b/ui/src/routes/route.constant.ts @@ -80,6 +80,7 @@ export const ROUTES_ENUM = { dashboard: '/admin/classroom/dashboard', classes: '/admin/classroom/classes', roomDetail: '/admin/classroom/room/:id', + planning: '/admin/classroom/planning/:id', }, }, accessDenied: '/admin/access-denied', diff --git a/ui/src/views/classroom/ClassList.tsx b/ui/src/views/classroom/ClassList.tsx index 49c8eed2..f371044c 100644 --- a/ui/src/views/classroom/ClassList.tsx +++ b/ui/src/views/classroom/ClassList.tsx @@ -183,6 +183,12 @@ const ClassList: React.FC = () => { } } + const handlePlanningClass = (classSession: ClassroomDto) => { + if (classSession.id) { + navigate(ROUTES_ENUM.protected.admin.classroom.planning.replace(':id', classSession.id)) + } + } + // const canJoinClass = (actualStartTime: string) => { // const actualed = new Date(actualStartTime) // const now = new Date() @@ -260,7 +266,7 @@ const ClassList: React.FC = () => { <> @@ -448,6 +454,18 @@ const ClassList: React.FC = () => {
{user.role === 'teacher' && classSession.teacherId === user.id && ( <> + + + + + +
+
+ + + +
+ {/* Left Sidebar - Student List */} +
+
+
+

+ + Öğrenciler ({unassignedStudents.length}) +

+
+ +
+
+ + setSearchQuery(e.target.value)} + className="w-full p-1 pl-8 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary" + /> +
+
+
+ + +
+ + {/* Main Content - Seat Grid */} +
+
+
+

+ + Sınıflar +

+
+ +
+
+ +
+
+
+ + {/* Seat Grid */} +
+ {selectedClassroom && ( + + )} +
+
+ + {/* Right Sidebar - Quick Actions */} +
+ +
+
+ + + {draggedStudent && ( +
+ +
+ )} +
+
+ + + ) +} + +export default ClassroomPlannerPage diff --git a/ui/src/views/classroom/RoomDetail.tsx b/ui/src/views/classroom/RoomDetail.tsx index 4243e658..a0838c31 100644 --- a/ui/src/views/classroom/RoomDetail.tsx +++ b/ui/src/views/classroom/RoomDetail.tsx @@ -19,22 +19,13 @@ import { FaTimes, FaCompress, FaUserFriends, - FaClipboardList, FaLayerGroup, FaWrench, - FaUserTimes, - FaDownload, - FaTrash, - FaEye, FaFilePdf, FaFileWord, FaFileImage, FaFileAlt, - FaPaperPlane, - FaBullhorn, - FaUser, FaBars, - FaCheck, } from 'react-icons/fa' import { SignalRService } from '@/services/classroom/signalr' import { WebRTCService } from '@/services/classroom/webrtc' @@ -48,8 +39,6 @@ import { VideoLayoutDto, } from '@/proxy/classroom/models' import { useStoreState } from '@/store/store' -import { ParticipantGrid } from '@/components/classroom/ParticipantGrid' -import { ScreenSharePanel } from '@/components/classroom/ScreenSharePanel' import { KickParticipantModal } from '@/components/classroom/KickParticipantModal' import { useParams } from 'react-router-dom' import { @@ -63,11 +52,13 @@ import { endClassroom } from '@/services/classroom.service' import { ROUTES_ENUM } from '@/routes/route.constant' import { Helmet } from 'react-helmet' import { useLocalization } from '@/utils/hooks/useLocalization' -import ChatPanel from '@/components/classroom/ChatPanel' -import ParticipantsPanel from '@/components/classroom/ParticipantsPanel' -import DocumentsPanel from '@/components/classroom/DocumentsPanel' -import LayoutPanel from '@/components/classroom/LayoutPanel' -import SettingsPanel from '@/components/classroom/SettingsPanel' +import ChatPanel from '@/components/classroom/panels/ChatPanel' +import ParticipantsPanel from '@/components/classroom/panels/ParticipantsPanel' +import DocumentsPanel from '@/components/classroom/panels/DocumentsPanel' +import LayoutPanel from '@/components/classroom/panels/LayoutPanel' +import SettingsPanel from '@/components/classroom/panels/SettingsPanel' +import { ScreenSharePanel } from '@/components/classroom/panels/ScreenSharePanel' +import { ParticipantGrid } from '@/components/classroom/ParticipantGrid' type SidePanelType = | 'chat' @@ -740,7 +731,7 @@ const RoomDetail: React.FC = () => { <>