@@ -449,30 +449,68 @@ const QuestionMarksManualUpdate: React.FC<QuestionMarksManualUpdateProps> = ({
449449 const max =
450450 content_details ?. sections ?. [ sectionIndex ] ?. questions ?. [ questionIndex ]
451451 ?. maxScore || 0 ;
452- const onlyDigits = ( textValue || '' ) . replace ( / [ ^ 0 - 9 ] / g, '' ) ;
453- if ( onlyDigits === '' ) {
452+
453+ // Allow only digits and single decimal point
454+ const filtered = ( textValue || '' ) . replace ( / [ ^ 0 - 9 . ] / g, '' ) ;
455+
456+ // Handle empty input
457+ if ( filtered === '' || filtered === '.' ) {
454458 set_marksTextBySection ( ( prev ) => {
455459 const arr = [ ...( prev [ String ( sectionIndex ) ] || [ ] ) ] ;
456- arr [ questionIndex ] = '' ;
460+ arr [ questionIndex ] = filtered ;
457461 return { ...prev , [ String ( sectionIndex ) ] : arr } ;
458462 } ) ;
463+ if ( filtered === '' ) {
464+ set_marksBySection ( ( prev ) => {
465+ const arr = [ ...( prev [ String ( sectionIndex ) ] || [ ] ) ] ;
466+ arr [ questionIndex ] = 0 ;
467+ return { ...prev , [ String ( sectionIndex ) ] : arr } ;
468+ } ) ;
469+ }
470+ return ;
471+ }
472+
473+ // Prevent multiple decimal points
474+ const decimalCount = ( filtered . match ( / \. / g) || [ ] ) . length ;
475+ if ( decimalCount > 1 ) return ;
476+
477+ // If input ends with a dot, allow it during typing
478+ if ( filtered . endsWith ( '.' ) ) {
479+ const beforeDot = filtered . slice ( 0 , - 1 ) ;
480+ const numBeforeDot = Number ( beforeDot ) ;
481+ // Don't allow if the number before dot already exceeds max
482+ if ( Number . isFinite ( numBeforeDot ) && numBeforeDot > max ) return ;
483+
484+ set_marksTextBySection ( ( prev ) => {
485+ const arr = [ ...( prev [ String ( sectionIndex ) ] || [ ] ) ] ;
486+ arr [ questionIndex ] = filtered ;
487+ return { ...prev , [ String ( sectionIndex ) ] : arr } ;
488+ } ) ;
489+ // Update numeric value to the integer part while user is typing decimal
459490 set_marksBySection ( ( prev ) => {
460491 const arr = [ ...( prev [ String ( sectionIndex ) ] || [ ] ) ] ;
461- arr [ questionIndex ] = 0 ;
492+ arr [ questionIndex ] = numBeforeDot ;
462493 return { ...prev , [ String ( sectionIndex ) ] : arr } ;
463494 } ) ;
464495 return ;
465496 }
466- // Normalize leading zeros: "000" -> "0", "0012" -> "12"
467- let normalized = onlyDigits . replace ( / ^ 0 + / , '' ) ;
468- if ( normalized === '' ) normalized = '0' ;
469- const parsed = Number ( normalized ) ;
497+
498+ const parsed = Number ( filtered ) ;
470499 if ( ! Number . isFinite ( parsed ) ) return ;
471- // Reject values above max: keep previous valid value unchanged
500+
501+ // Validation: Only allow whole numbers or numbers ending with .5
502+ const isValid =
503+ / ^ ( \d + \. 5 | \d + ) $ / . test ( filtered ) ||
504+ filtered === '0.5' ||
505+ filtered === '.5' ;
506+ if ( ! isValid ) return ; // Reject invalid decimals like 0.1, 0.2, 1.3, etc.
507+
508+ // Reject values above max
472509 if ( parsed > max ) return ;
510+
473511 set_marksTextBySection ( ( prev ) => {
474512 const arr = [ ...( prev [ String ( sectionIndex ) ] || [ ] ) ] ;
475- arr [ questionIndex ] = normalized ;
513+ arr [ questionIndex ] = filtered ;
476514 return { ...prev , [ String ( sectionIndex ) ] : arr } ;
477515 } ) ;
478516 set_marksBySection ( ( prev ) => {
@@ -486,19 +524,53 @@ const QuestionMarksManualUpdate: React.FC<QuestionMarksManualUpdateProps> = ({
486524 const max =
487525 content_details ?. sections ?. [ sectionIndex ] ?. questions ?. [ questionIndex ]
488526 ?. maxScore || 0 ;
489- const text =
490- marksTextBySection [ String ( sectionIndex ) ] ?. [ questionIndex ] ?? '' ;
491- if ( text === '' ) {
492- // keep UI empty but ensure numeric is 0
527+ let text = marksTextBySection [ String ( sectionIndex ) ] ?. [ questionIndex ] ?? '' ;
528+
529+ // Handle empty or just dot
530+ if ( text === '' || text === '.' ) {
493531 set_marksBySection ( ( prev ) => {
494532 const arr = [ ...( prev [ String ( sectionIndex ) ] || [ ] ) ] ;
495533 arr [ questionIndex ] = 0 ;
496534 return { ...prev , [ String ( sectionIndex ) ] : arr } ;
497535 } ) ;
536+ set_marksTextBySection ( ( prev ) => {
537+ const arr = [ ...( prev [ String ( sectionIndex ) ] || [ ] ) ] ;
538+ arr [ questionIndex ] = '' ;
539+ return { ...prev , [ String ( sectionIndex ) ] : arr } ;
540+ } ) ;
498541 return ;
499542 }
543+
544+ // Handle incomplete input like "2." - convert to whole number
545+ if ( text . endsWith ( '.' ) ) {
546+ text = text . slice ( 0 , - 1 ) ;
547+ }
548+
549+ // Normalize ".5" to "0.5"
550+ if ( text === '.5' ) {
551+ text = '0.5' ;
552+ }
553+
500554 const num = Number ( text ) ;
501- const safe = Number . isFinite ( num ) ? Math . max ( 0 , Math . min ( num , max ) ) : 0 ;
555+
556+ // Validate: must be finite, within range, and either whole number or .5 decimal
557+ const isValidFormat = / ^ ( \d + \. 5 | \d + ) $ / . test ( text ) ;
558+ if ( ! Number . isFinite ( num ) || ! isValidFormat ) {
559+ // Revert to previous valid value (0)
560+ set_marksBySection ( ( prev ) => {
561+ const arr = [ ...( prev [ String ( sectionIndex ) ] || [ ] ) ] ;
562+ arr [ questionIndex ] = 0 ;
563+ return { ...prev , [ String ( sectionIndex ) ] : arr } ;
564+ } ) ;
565+ set_marksTextBySection ( ( prev ) => {
566+ const arr = [ ...( prev [ String ( sectionIndex ) ] || [ ] ) ] ;
567+ arr [ questionIndex ] = '0' ;
568+ return { ...prev , [ String ( sectionIndex ) ] : arr } ;
569+ } ) ;
570+ return ;
571+ }
572+
573+ const safe = Math . max ( 0 , Math . min ( num , max ) ) ;
502574 set_marksBySection ( ( prev ) => {
503575 const arr = [ ...( prev [ String ( sectionIndex ) ] || [ ] ) ] ;
504576 arr [ questionIndex ] = safe ;
@@ -641,12 +713,11 @@ const QuestionMarksManualUpdate: React.FC<QuestionMarksManualUpdateProps> = ({
641713
642714 const result = await createContentTracking ( {
643715 userId : userId ,
644- contentId : do_id ,
716+ contentId : do_id ,
645717 courseId : parentId ,
646718 unitId : unitId ,
647- totalScore : totalScore
719+ totalScore : totalScore ,
648720 } ) ;
649-
650721 } catch ( error ) {
651722 console . error ( 'API error while creating assessment tracking:' , error ) ;
652723 set_isSubmitting ( false ) ;
@@ -941,8 +1012,7 @@ const QuestionMarksManualUpdate: React.FC<QuestionMarksManualUpdateProps> = ({
9411012 < label style = { { fontWeight : 500 } } > Marks:</ label >
9421013 < input
9431014 type = "text"
944- inputMode = "numeric"
945- pattern = "[0-9]*"
1015+ inputMode = "decimal"
9461016 min = { 0 }
9471017 max = { q . maxScore }
9481018 value = {
@@ -954,11 +1024,7 @@ const QuestionMarksManualUpdate: React.FC<QuestionMarksManualUpdateProps> = ({
9541024 marksBySection [ String ( si ) ] ?. [ qi ] ?? 0
9551025 ) }
9561026 onChange = { ( e ) => {
957- const onlyDigits = e . target . value . replace (
958- / [ ^ 0 - 9 ] / g,
959- ''
960- ) ;
961- handleMarksTextChange ( si , qi , onlyDigits ) ;
1027+ handleMarksTextChange ( si , qi , e . target . value ) ;
9621028 } }
9631029 onBlur = { ( ) => handleMarksBlur ( si , qi ) }
9641030 style = { { width : 80 } }
0 commit comments