diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 2bb4c92b..27794b6f 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -147,7 +147,9 @@ "PRE_TEST": "Pre Test", "ENGLISH": "English", "MATH": "Math", - "TEST": "Test" + "TEST": "Test", + "ENTER_NAME": "Please Enter Full Name", + "AT_REQUIRED_LETTER":"At least one letter or underscore is required" }, "FIELDS": { diff --git a/public/locales/hi/common.json b/public/locales/hi/common.json index 18b3ca92..921dd3ad 100644 --- a/public/locales/hi/common.json +++ b/public/locales/hi/common.json @@ -146,7 +146,9 @@ "PRE_TEST": "प्री टेस्ट", "ENGLISH": "अंग्रेजी", "MATH": "गणित", - "TEST": "परीक्षण" + "TEST": "परीक्षण", + "ENTER_NAME": "कृपया पूरा नाम दर्ज करें", + "AT_REQUIRED_LETTER": "कम से कम एक अक्षर या अंडरस्कोर आवश्यक है" }, "FIELDS": { diff --git a/public/locales/mr/common.json b/public/locales/mr/common.json index c0c8e871..bfd180f9 100644 --- a/public/locales/mr/common.json +++ b/public/locales/mr/common.json @@ -147,7 +147,9 @@ "PRE_TEST": "पूर्व चाचणी", "ENGLISH": "इंग्रजी", "MATH": "गणित", - "TEST": "चाचणी" + "TEST": "चाचणी", + "ENTER_NAME": "कृपया पूर्ण नाव प्रविष्ट करा", + "AT_REQUIRED_LETTER": "किमान एक अक्षर किंवा अंडरस्कोर आवश्यक आहे" }, "FIELDS": { "DESIGNATION": "पद", diff --git a/src/components/MarksObtainedCard.tsx b/src/components/MarksObtainedCard.tsx index 0c76c343..01ac5729 100644 --- a/src/components/MarksObtainedCard.tsx +++ b/src/components/MarksObtainedCard.tsx @@ -25,12 +25,18 @@ const SmallCard: React.FC = ({ item }) => { return ( - + {item.question} 0 @@ -45,7 +51,6 @@ const SmallCard: React.FC = ({ item }) => { const MarksObtainedCard: React.FC = ({ data }) => { const [showAllData, setShowAllData] = useState(false); const { t } = useTranslation(); - const limitedData = showAllData ? data : data?.slice(0, 12); diff --git a/src/pages/attendance-history.tsx b/src/pages/attendance-history.tsx index 73db040a..ad7cd185 100644 --- a/src/pages/attendance-history.tsx +++ b/src/pages/attendance-history.tsx @@ -100,6 +100,8 @@ const UserAttendanceHistory = () => { if (typeof window !== 'undefined' && window.localStorage) { const token = localStorage.getItem('token'); setClassId(localStorage.getItem('classId') || ''); + const classId = localStorage.getItem('classId') || ''; + localStorage.setItem('cohortId', classId); setLoading(false); if (token) { push('/attendance-history'); diff --git a/src/pages/attendance-overview.tsx b/src/pages/attendance-overview.tsx index ff904dd3..81da7072 100644 --- a/src/pages/attendance-overview.tsx +++ b/src/pages/attendance-overview.tsx @@ -109,6 +109,9 @@ const AttendanceOverview: React.FC = () => { if (typeof window !== 'undefined' && window.localStorage) { const token = localStorage.getItem('token'); setClassId(localStorage.getItem('classId') || ''); + const class_Id = localStorage.getItem('classId') || ''; + localStorage.setItem('cohortId', class_Id); + setLoading(false); if (token) { push('/attendance-overview'); @@ -194,12 +197,12 @@ const AttendanceOverview: React.FC = () => { state: stateName, }; }); + setCohortsData(filteredData); if (filteredData.length > 0) { // setClassId(filteredData[0].cohortId); - localStorage.setItem('cohortId', filteredData[0]?.cohortId); // add state name to localstorage if ( diff --git a/src/pages/dashboard.tsx b/src/pages/dashboard.tsx index afd2d187..d4aa0883 100644 --- a/src/pages/dashboard.tsx +++ b/src/pages/dashboard.tsx @@ -170,8 +170,15 @@ const Dashboard: React.FC = () => { ?.filter(Boolean); setCohortsData(filteredData); if (filteredData.length > 0) { - // setClassId(filteredData?.[0]?.cohortId); - // localStorage.setItem('classId', filteredData?.[0]?.cohortId); + if (typeof window !== 'undefined' && window.localStorage) { + const cohort = localStorage.getItem('classId') || ''; + if (cohort !== '') { + setClassId(localStorage.getItem('classId') || ''); + } else { + localStorage.setItem('classId', filteredData?.[0]?.cohortId); + setClassId(filteredData?.[0]?.cohortId); + } + } setManipulatedCohortData( filteredData.concat({ cohortId: 'all', name: 'All Centers' }) ); diff --git a/src/pages/learner/[userId].tsx b/src/pages/learner/[userId].tsx index aafdbd8a..f907ee19 100644 --- a/src/pages/learner/[userId].tsx +++ b/src/pages/learner/[userId].tsx @@ -111,6 +111,8 @@ const LearnerProfile: React.FC = () => { t('COMMON.AS_OF_TODAY') ); const open = Boolean(anchorEl); + const [totalMaxScore, setTotalMaxScore] = useState(''); + const [totalScore, setTotalScore] = useState(''); const [unitName, setUnitName] = useState(''); const [blockName, setBlockName] = useState(''); @@ -377,7 +379,8 @@ const LearnerProfile: React.FC = () => { const result = response.result; if (result) { setSubmitedOn(result[0]?.createdOn); - + setTotalMaxScore(result[0]?.totalMaxScore); + setTotalScore(result[0]?.totalScore); const questionValues = getQuestionValues(result); setAssesmentData(questionValues?.questions); // Use the parsed questions setLoading(false); @@ -559,6 +562,23 @@ const LearnerProfile: React.FC = () => { })); }; + const [hasErrors, setHasErrors] = useState(false); + + const handleInputChange = (e: React.ChangeEvent) => { + const { value } = e.target; + const sanitizedValue = value.replace(/[^a-zA-Z_ ]/g, ''); + + setFormData((prevData) => ({ + ...prevData, + userData: { + ...prevData.userData, + name: sanitizedValue, + }, + })); + + setHasErrors(!sanitizedValue.trim()); + }; + const handleSubmit = async ( e: React.MouseEvent ) => { @@ -867,7 +887,7 @@ const LearnerProfile: React.FC = () => { flex: '1', border: '2px solid', borderColor: '#FFECB3', - padding: '10px', + padding: '15px', }} minWidth={'100%'} borderRadius={'12px'} @@ -991,8 +1011,7 @@ const LearnerProfile: React.FC = () => { {uniqueDoId ? ( @@ -1009,7 +1028,8 @@ const LearnerProfile: React.FC = () => { {t('PROFILE.MARK_OBTAINED')} - {/* 60/70 */} + {totalScore ? totalScore : '0'}/ + {totalMaxScore ? totalMaxScore : '0'} @@ -1140,24 +1160,50 @@ const LearnerProfile: React.FC = () => { label={t('PROFILE.FULL_NAME')} variant="outlined" value={formData.userData.name} - onChange={(e) => - setFormData({ - ...formData, - userData: { - name: e.target.value, - district: '', - state: '', - mobile: '', - }, - }) + inputProps={{ + pattern: '^[A-Za-z_ ]+$', // Only allow letters, underscores, and spaces + title: t('PROFILE.AT_REQUIRED_LETTER'), + required: true, + }} + error={!formData.userData.name.trim()} // Show error if the input is empty + helperText={ + !formData.userData.name.trim() && t('PROFILE.ENTER_NAME') } + onChange={handleInputChange} /> {filteredSortedForEdit ?.filter((field) => field.isEditable) ?.map((field) => ( - {field.type === 'text' || field.type === 'numeric' ? ( + {field.type === 'text' ? ( + f.fieldId === field.fieldId + )?.value[0] || '' + } + onChange={(e) => { + handleFieldChange(field.fieldId, e.target.value); + }} + /> + ) : field.type === 'numeric' ? ( { }} onClick={handleSubmit} variant="contained" + disabled={hasErrors} > {t('COMMON.SAVE')} diff --git a/src/pages/login.tsx b/src/pages/login.tsx index 0cd4e925..d67069ec 100644 --- a/src/pages/login.tsx +++ b/src/pages/login.tsx @@ -307,7 +307,7 @@ const LoginPage = () => { /> - + {/* { > {t('LOGIN_PAGE.FORGOT_PASSWORD')} - + */} setRememberMe(e.target.checked)} diff --git a/src/pages/logout.tsx b/src/pages/logout.tsx index 1bf8f952..0a67cb6f 100644 --- a/src/pages/logout.tsx +++ b/src/pages/logout.tsx @@ -21,6 +21,7 @@ function Logout() { localStorage.removeItem('userId'); localStorage.removeItem('parentCohortId'); localStorage.removeItem('learnerId'); + localStorage.removeItem('classId'); router.replace('/login'); }, []); diff --git a/src/pages/profile.tsx b/src/pages/profile.tsx index 76a8247d..142902e8 100644 --- a/src/pages/profile.tsx +++ b/src/pages/profile.tsx @@ -268,6 +268,23 @@ const TeacherProfile = () => { }); }, [userData, customFieldsData]); + const [hasErrors, setHasErrors] = useState(false); + + const handleInputChange = (e: React.ChangeEvent) => { + const { value } = e.target; + const sanitizedValue = value.replace(/[^a-zA-Z_ ]/g, ''); + + setFormData((prevData) => ({ + ...prevData, + userData: { + ...prevData.userData, + name: sanitizedValue, + }, + })); + + setHasErrors(!sanitizedValue.trim()); + }; + const handleFieldChange = (fieldId: string, value: string) => { setFormData((prevState) => ({ ...prevState, @@ -752,22 +769,22 @@ const TeacherProfile = () => { - setFormData({ - ...formData, - userData: { - name: e.target.value, - district: '', - state: '', - mobile: '', - }, - }) + inputProps={{ + pattern: '^[A-Za-z_ ]+$', // Only allow letters, underscores, and spaces + title: t('PROFILE.AT_REQUIRED_LETTER'), + required: true, + }} + error={!formData.userData.name.trim()} // Show error if the input is empty + helperText={ + !formData.userData.name.trim() && t('PROFILE.ENTER_NAME') } + onChange={handleInputChange} /> {customFieldsData @@ -775,7 +792,33 @@ const TeacherProfile = () => { ?.sort((a, b) => a.order - b.order) ?.map((field) => ( - {field.type === 'text' || field.type === 'numeric' ? ( + {field.type === 'text' ? ( + f.fieldId === field.fieldId + )?.value[0] || '' + } + onChange={(e) => { + handleFieldChange(field.fieldId, e.target.value); + }} + /> + ) : field.type === 'numeric' ? ( { }} onClick={handleSubmit} variant="contained" + disabled={hasErrors} > {t('COMMON.SAVE')} diff --git a/src/utils/Interfaces.ts b/src/utils/Interfaces.ts index 1e08868c..a4db5926 100644 --- a/src/utils/Interfaces.ts +++ b/src/utils/Interfaces.ts @@ -208,7 +208,7 @@ export interface CustomField { label: string; value: string; options: Record; - type: string; + type: any; order: number; name: string; isEditable: boolean;