Download backend/static/assets/js/data.js from TalimBot/talimbot: direct link, hf CLI and curl.
- Browser
- Download file 7.3 kB
-
https://huggingface.co/spaces/TalimBot/talimbot/resolve/main/backend/static/assets/js/data.js
- Command line
-
hf download hf://spaces/TalimBot/talimbot/backend/static/assets/js/data.js
-
curl -L -o data.js https://huggingface.co/spaces/TalimBot/talimbot/resolve/main/backend/static/assets/js/data.js
7.3 kB
| // Student Grouping System - Data Management | |
| // This file handles all data operations using Backend API | |
| // Backend API Configuration | |
| // Auto-detects if running on Railway deployment or localhost | |
| function getApiBaseUrl() { | |
| // When deployed to Railway, it will use the same domain | |
| // Railway serves both frontend and backend from the same URL | |
| // So we use relative paths for API calls | |
| if (window.location.hostname !== 'localhost' && window.location.hostname !== '127.0.0.1') { | |
| // PRODUCTION: Running on Railway - use relative paths | |
| return '/api'; | |
| } | |
| // DEVELOPMENT: Running locally | |
| return 'http://localhost:8000/api'; | |
| } | |
| const API_BASE_URL = getApiBaseUrl(); | |
| // Utility function for API calls | |
| async function apiCall(endpoint, options = {}) { | |
| try { | |
| const response = await fetch(`${API_BASE_URL}${endpoint}`, { | |
| ...options, | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| ...options.headers | |
| } | |
| }); | |
| if (!response.ok) { | |
| const error = await response.json(); | |
| throw new Error(error.detail || 'API request failed'); | |
| } | |
| return await response.json(); | |
| } catch (error) { | |
| console.error('API Error:', error); | |
| throw error; | |
| } | |
| } | |
| // Get all data (for backward compatibility) | |
| async function getData() { | |
| const students = await getAllStudents(); | |
| const status = await getGroupingStats(); | |
| return { | |
| students: students, | |
| courseName: status.courseName, | |
| groupingComplete: status.groupingComplete, | |
| resultsVisible: status.resultsVisible, | |
| teacherPassword: 'teacher123' | |
| }; | |
| } | |
| // Get student by student number | |
| async function getStudent(studentNumber) { | |
| try { | |
| return await apiCall(`/student/${studentNumber}`); | |
| } catch (error) { | |
| return null; | |
| } | |
| } | |
| // Update student information | |
| async function updateStudent(studentNumber, updates) { | |
| try { | |
| const result = await apiCall(`/student/${studentNumber}`, { | |
| method: 'PUT', | |
| body: JSON.stringify(updates) | |
| }); | |
| return result.success; | |
| } catch (error) { | |
| return false; | |
| } | |
| } | |
| // Get all students | |
| async function getAllStudents() { | |
| const result = await apiCall('/students'); | |
| return result.students; | |
| } | |
| // Check if a student number exists in the system | |
| async function studentExists(studentNumber) { | |
| const student = await getStudent(studentNumber); | |
| return student !== null; | |
| } | |
| // Get students with complete information (REQUIRED fields only: MBTI and Learning Style) | |
| async function getStudentsWithCompleteInfo() { | |
| const students = await getAllStudents(); | |
| return students.filter(s => s.mbti && s.learningStyle); | |
| } | |
| // Check if a student has complete profile (all fields filled) | |
| async function hasCompleteProfile(studentNumber) { | |
| const student = await getStudent(studentNumber); | |
| if (!student) return false; | |
| return !!(student.mbti && student.learningStyle && | |
| student.ams !== null && student.cooperative !== null); | |
| } | |
| // Get completion percentage for a student | |
| async function getProfileCompletion(studentNumber) { | |
| const student = await getStudent(studentNumber); | |
| if (!student) return 0; | |
| let completed = 0; | |
| const total = 4; | |
| if (student.mbti) completed++; | |
| if (student.learningStyle) completed++; | |
| if (student.ams !== null) completed++; | |
| if (student.cooperative !== null) completed++; | |
| return Math.round((completed / total) * 100); | |
| } | |
| // Get grouping statistics | |
| async function getGroupingStats() { | |
| return await apiCall('/grouping/status'); | |
| } | |
| // Check if grouping is complete | |
| async function isGroupingComplete() { | |
| const stats = await getGroupingStats(); | |
| return stats.groupingComplete; | |
| } | |
| // Get course name | |
| async function getCourseName() { | |
| const stats = await getGroupingStats(); | |
| return stats.courseName; | |
| } | |
| // Check teacher password | |
| async function checkTeacherPassword(password) { | |
| try { | |
| const result = await apiCall('/auth/teacher', { | |
| method: 'POST', | |
| body: JSON.stringify({ password }) | |
| }); | |
| return result.valid; | |
| } catch (error) { | |
| return false; | |
| } | |
| } | |
| // Get student's group (only if results are visible) | |
| async function getStudentGroup(studentNumber) { | |
| try { | |
| return await apiCall(`/student/${studentNumber}/group`); | |
| } catch (error) { | |
| if (error.message.includes('not yet visible')) { | |
| return { error: 'results_not_visible', message: 'نتایج هنوز توسط معلم نمایش داده نشده است.' }; | |
| } | |
| if (error.message.includes('not assigned')) { | |
| return { error: 'not_assigned', message: 'شما هنوز به گروهی اختصاص داده نشدهاید.' }; | |
| } | |
| throw error; | |
| } | |
| } | |
| // Reset grouping only (keep student data) | |
| async function resetGrouping(password) { | |
| return await apiCall('/grouping/reset', { | |
| method: 'POST', | |
| body: JSON.stringify({ password }) | |
| }); | |
| } | |
| // Reset ALL data (student profiles + grouping) | |
| async function resetAllData(password) { | |
| return await apiCall('/data/reset-all', { | |
| method: 'POST', | |
| body: JSON.stringify({ password }) | |
| }); | |
| } | |
| // Toggle results visibility | |
| async function toggleResultsVisibility(password) { | |
| return await apiCall('/grouping/toggle-visibility', { | |
| method: 'POST', | |
| body: JSON.stringify({ password }) | |
| }); | |
| } | |
| // Legacy functions for backward compatibility (these are handled by backend now) | |
| function saveData(data) { | |
| console.warn('saveData is deprecated - data is automatically saved to backend'); | |
| } | |
| function initializeData() { | |
| console.log('Data is managed by backend'); | |
| return true; | |
| } | |
| function addNewStudent(studentNumber, name, grade = 15) { | |
| console.warn('addNewStudent should be done through admin panel'); | |
| return { success: false, message: 'Use backend API for adding students' }; | |
| } | |
| function saveStudents(students) { | |
| console.warn('saveStudents is deprecated - use backend API'); | |
| } | |
| function deleteStudent(studentNumber) { | |
| console.warn('deleteStudent should be done through admin panel'); | |
| return false; | |
| } | |
| function setGroupingComplete(status) { | |
| console.warn('setGroupingComplete is handled by backend'); | |
| } | |
| function setCourseName(name) { | |
| console.warn('setCourseName is handled by backend'); | |
| } | |
| function resetData() { | |
| console.warn('resetData should be done through teacher dashboard'); | |
| } | |
| // Export functions for use in other files | |
| if (typeof module !== 'undefined' && module.exports) { | |
| module.exports = { | |
| getData, | |
| getStudent, | |
| updateStudent, | |
| getAllStudents, | |
| studentExists, | |
| getStudentsWithCompleteInfo, | |
| hasCompleteProfile, | |
| getProfileCompletion, | |
| isGroupingComplete, | |
| getCourseName, | |
| checkTeacherPassword, | |
| getGroupingStats, | |
| getStudentGroup | |
| }; | |
| } | |