Skip to content

Assessment: Show grade suggestion based on assessment results #608

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

rappm
Copy link
Contributor

@rappm rappm commented Jun 20, 2025

📝 Show grading suggestion based on assessment results

Warning

Depends on #607 due to db migrations

✨ What is the change?

  • Show grading suggestion based on assessment results
  • add tooltips to explain grade suggestion and platform recommendation

📌 Reason for the change / Link to issue

closes #605

🧪 How to Test

  1. Navigate to a student assessment
  2. checkout the new tooltips for the GradeSuggestionBadge and the StudentScoreBadge
  3. when adding a grading recommendation, you can now see the platform suggestion

🖼️ Screenshots (if UI changes are included)

Before After
image Bildschirmfoto 2025-06-20 um 13 22 44
Bildschirmfoto 2025-06-20 um 13 22 16 Bildschirmfoto 2025-06-20 um 13 19 29 Bildschirmfoto 2025-06-20 um 13 19 24

✅ PR Checklist

  • Tested locally or on the dev environment
  • Code is clean, readable, and documented
  • Tests added or updated (if needed)
  • Screenshots attached for UI changes (if any)
  • Documentation updated (if relevant)

Summary by CodeRabbit

  • New Features

    • Introduced a dedicated grade suggestion card with improved UI for selecting grades, including a dropdown and contextual recommendations.
    • Added tooltips to grade and score badges to provide explanatory information on hover.
  • Improvements

    • Simplified grade validation and centralized it in a utility for more consistent input handling.
    • Enhanced score and grade badges to display both numeric and level information, improving clarity.
  • Bug Fixes

    • Improved handling of missing or undefined grade and score values to avoid rendering issues.
  • Refactor

    • Streamlined component structures and updated export styles for consistency.
    • Updated JSON field naming for student scores to ensure consistent API responses.

@rappm rappm self-assigned this Jun 20, 2025
@rappm rappm linked an issue Jun 20, 2025 that may be closed by this pull request
@github-project-automation github-project-automation bot moved this to In Review in PROMPT Jun 20, 2025
Copy link
Contributor

coderabbitai bot commented Jun 20, 2025

Walkthrough

The changes introduce a dedicated GradeSuggestion component for grade selection, move grade validation logic into a utility function, and enhance badge components with tooltips and improved props. The AssessmentCompletion component is refactored to use these new utilities and components, and JSON serialization for student scores is updated for consistency.

Changes

File(s) Change Summary
.../AssessmentCompletion/AssessmentCompletion.tsx Refactored: uses new GradeSuggestion component, imports validateGrade, converts to arrow function, simplifies grade suggestion UI and logic.
.../AssessmentCompletion/components/GradeSuggestion.tsx Added: new GradeSuggestion component for grade selection UI.
.../AssessmentCompletion/utils/validateGrade.tsx Added: new validateGrade utility for validating grade input.
.../AssessmentProfile.tsx Updated: passes scoreNumeric prop to StudentScoreBadge, reordered imports.
.../AssessmentStatusBadge.tsx Changed: switched from default export to named export.
.../CategoryAssessment.tsx Updated: uses named import for AssessmentStatusBadge.
.../components/GradeSuggestionBadge.tsx Enhanced: optional gradeSuggestion prop, uses mapNumberToScoreLevel, adds tooltip to badge.
.../components/StudentScoreBadge.tsx Enhanced: both scoreLevel and scoreNumeric props optional, improved display and tooltip.
.../scoreLevelDTO/studentScore.go Changed: JSON tag for ScoreNumeric field from "numericScore" to "scoreNumeric".

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant AssessmentCompletion
    participant GradeSuggestion
    participant validateGrade

    User->>AssessmentCompletion: Interacts with grade suggestion UI
    AssessmentCompletion->>GradeSuggestion: Renders with props (gradeSuggestion, studentScore, etc.)
    User->>GradeSuggestion: Selects a grade
    GradeSuggestion->>AssessmentCompletion: Calls onGradeSuggestionChange(newGrade)
    AssessmentCompletion->>validateGrade: validateGrade(newGrade)
    validateGrade-->>AssessmentCompletion: Returns validation result
    AssessmentCompletion->>AssessmentCompletion: Updates state, triggers save if valid
Loading

Assessment against linked issues

Objective Addressed Explanation
Show grading suggestion generated based on the assessment input (#605)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Change of JSON tag from "numericScore" to "scoreNumeric" (servers/assessment/assessments/scoreLevel/scoreLevelDTO/studentScore.go) This change is not directly related to the UI grading suggestion feature in #605, but may be for backend consistency.

Suggested labels

enhancement, Component:: Assessment

Suggested reviewers

  • mathildeshagl
  • niclasheun
  • Mtze

Poem

A bunny brings a shiny grade,
With tooltips bright and dropdowns made.
Suggestions hop in, scores align,
Validation checks—oh, how fine!
Now students see, with clearer view,
What grade the platform thinks is true.
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
clients/assessment_component/src/assessment/pages/AssessmentPage/components/AssessmentCompletion/utils/validateGrade.tsx (1)

1-33: Well-structured grade validation utility.

The implementation correctly handles edge cases including empty inputs, invalid numbers, range validation, and floating-point precision issues. The use of tolerance (0.01) for floating-point comparison is a good practice.

Consider documenting the default value behavior (5.0 for empty input) more explicitly, as this might not be immediately obvious to users of this utility.

+// Returns default grade of 5.0 (fail) when input is empty or whitespace-only
 export const validateGrade = (
   gradeString: string,
 ): { isValid: boolean; value?: number; error?: string } => {
clients/assessment_component/src/assessment/pages/components/StudentScoreBadge.tsx (2)

23-29: Simplify the config determination logic.

The ternary chain can be simplified for better readability since you already have an early return when both props are undefined.

-  const config = getLevelConfig(
-    scoreLevel
-      ? scoreLevel
-      : scoreNumeric
-        ? mapNumberToScoreLevel(scoreNumeric)
-        : ScoreLevel.VeryBad,
-  )
+  const config = getLevelConfig(
+    scoreLevel ?? mapNumberToScoreLevel(scoreNumeric!)
+  )

Since you've already handled the case where both are undefined with an early return, the fallback to ScoreLevel.VeryBad is unreachable.


43-45: Simplify the badge content display logic.

The conditional logic for displaying badge content can be simplified for better readability.

-            {scoreLevel ? config.title : ''}
-            {scoreLevel && scoreNumeric ? ` (${scoreNumeric.toFixed(1)})` : ''}
-            {!scoreLevel && scoreNumeric ? `${scoreNumeric.toFixed(1)}` : ''}
+            {scoreLevel && config.title}
+            {scoreNumeric && (scoreLevel ? ` (${scoreNumeric.toFixed(1)})` : scoreNumeric.toFixed(1))}

This reduces duplication and makes the logic clearer.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f869424 and 8acf44a.

📒 Files selected for processing (9)
  • clients/assessment_component/src/assessment/pages/AssessmentPage/components/AssessmentCompletion/AssessmentCompletion.tsx (3 hunks)
  • clients/assessment_component/src/assessment/pages/AssessmentPage/components/AssessmentCompletion/components/GradeSuggestion.tsx (1 hunks)
  • clients/assessment_component/src/assessment/pages/AssessmentPage/components/AssessmentCompletion/utils/validateGrade.tsx (1 hunks)
  • clients/assessment_component/src/assessment/pages/AssessmentPage/components/AssessmentProfile.tsx (2 hunks)
  • clients/assessment_component/src/assessment/pages/AssessmentPage/components/AssessmentStatusBadge.tsx (1 hunks)
  • clients/assessment_component/src/assessment/pages/AssessmentPage/components/CategoryAssessment.tsx (1 hunks)
  • clients/assessment_component/src/assessment/pages/components/GradeSuggestionBadge.tsx (1 hunks)
  • clients/assessment_component/src/assessment/pages/components/StudentScoreBadge.tsx (1 hunks)
  • servers/assessment/assessments/scoreLevel/scoreLevelDTO/studentScore.go (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: test-servers / test (assessment)
  • GitHub Check: build-clients / clients-base / Build Docker Image for ghcr.io/ls1intum/prompt2/prompt-clients-base
  • GitHub Check: build-clients / clients-base / Build Docker Image for ghcr.io/ls1intum/prompt2/prompt-clients-base
  • GitHub Check: Analyze (go)
🔇 Additional comments (28)
clients/assessment_component/src/assessment/pages/AssessmentPage/components/AssessmentStatusBadge.tsx (1)

10-14: Export style updated to named export
The component has been changed from a default export to a named export, which improves consistency and tree-shaking. Ensure no leftover default imports for this component remain.

To verify, run:

#!/bin/bash
# Verify no default imports of AssessmentStatusBadge remain
rg -n "import\s+AssessmentStatusBadge\s+from"
clients/assessment_component/src/assessment/pages/AssessmentPage/components/CategoryAssessment.tsx (1)

8-8: Import adjusted to named export
The import of AssessmentStatusBadge has been updated to a named import to match the component’s export. This aligns usage and avoids unresolved imports.

servers/assessment/assessments/scoreLevel/scoreLevelDTO/studentScore.go (1)

9-9: LGTM: JSON field naming consistency improvement.

The change from "numericScore" to "scoreNumeric" aligns the backend JSON serialization with frontend component prop naming, ensuring consistent data contracts between backend and frontend layers.

clients/assessment_component/src/assessment/pages/AssessmentPage/components/AssessmentProfile.tsx (2)

3-12: Good import organization and component integration.

The import reordering follows TypeScript conventions by placing type imports first, and the addition of component imports is well-structured. The integration with the new GradeSuggestionBadge component is clean.


46-49: Correct prop addition for enhanced badge functionality.

The addition of the scoreNumeric prop to StudentScoreBadge correctly utilizes the updated data structure and enables the enhanced tooltip functionality described in the PR objectives.

clients/assessment_component/src/assessment/pages/AssessmentPage/components/AssessmentCompletion/components/GradeSuggestion.tsx (3)

17-29: Well-structured component interface.

The props interface is clean and the component signature follows React best practices with proper typing and default values.


34-42: Smart conditional rendering for platform recommendations.

The condition studentScore.scoreNumeric > 0 appropriately determines when to show platform recommendations, providing contextual guidance to users.


45-62: Verify grade values consistency with validation utility.

The dropdown options should match the valid grade values defined in the validation utility to ensure consistency across the application.

#!/bin/bash
# Verify that grade values in GradeSuggestion component match validateGrade utility
echo "Grade values in validateGrade utility:"
rg -A 1 "validGradeValues.*=" clients/assessment_component/src/assessment/pages/AssessmentPage/components/AssessmentCompletion/utils/validateGrade.tsx

echo -e "\nGrade values in GradeSuggestion SelectItems:"
rg "SelectItem value=" clients/assessment_component/src/assessment/pages/AssessmentPage/components/AssessmentCompletion/components/GradeSuggestion.tsx
clients/assessment_component/src/assessment/pages/components/GradeSuggestionBadge.tsx (3)

14-14: Good prop type simplification.

Changing from number | null to number? makes the interface cleaner and more idiomatic for optional props.


18-22: Clean logic simplification.

The early return pattern and use of mapNumberToScoreLevel utility improves code readability and maintainability compared to nested ternary operations.


26-40: Excellent tooltip implementation for better UX.

The tooltip provides clear context about the grade suggestion's purpose, and the cursor-help class gives users a visual cue that additional information is available. The 250ms delay duration provides a good balance between responsiveness and avoiding accidental triggers.

clients/assessment_component/src/assessment/pages/components/StudentScoreBadge.tsx (6)

14-16: Props interface looks good with optional typing.

The interface correctly makes both props optional, allowing for flexible usage patterns. The naming is consistent with the backend changes mentioned in the AI summary.


18-21: Early return prevents unnecessary rendering.

Good defensive programming practice to return undefined when no score data is provided, preventing empty badge rendering.


40-46: Badge content logic handles multiple display scenarios correctly.

The conditional rendering logic appropriately handles:

  • Score level with optional numeric value
  • Numeric-only display when no score level is provided

The formatting with .toFixed(1) ensures consistent numeric display.


40-40: Consider improving hover cursor semantics.

The cursor-help class correctly indicates that help information is available via tooltip, which is good for accessibility.


23-29: ```shell
#!/bin/bash

Display the ScoreLevel enum and mapNumberToScoreLevel implementation

sed -n '1,100p' clients/assessment_component/src/assessment/interfaces/scoreLevel.ts


---

`36-52`: **LGTM! Well-implemented tooltip functionality.**

The tooltip implementation follows React patterns correctly with appropriate delay, positioning, and accessible content. The styling enhancements with `cursor-help` provide good UX.

</details>
<details>
<summary>clients/assessment_component/src/assessment/pages/AssessmentPage/components/AssessmentCompletion/AssessmentCompletion.tsx (11)</summary>

`35-39`: **Function conversion and prop destructuring look good.**

The conversion to arrow function maintains the same functionality while following modern React patterns. Removing the default value for `deadline` is appropriate if it's handled elsewhere.

---

`75-79`: **Grade validation integration is well-implemented.**

The validation logic correctly:
- Uses the extracted utility function
- Handles validation errors appropriately
- Prevents proceeding with invalid grades

Good separation of concerns.

---

`104-108`: **Consistent validation pattern in save handler.**

The same validation pattern is correctly applied in the save handler, maintaining consistency across both code paths.

---

`110-117`: **Inline object creation simplifies the code.**

Removing the intermediate `completionData` variable reduces unnecessary complexity while maintaining readability.

---

`148-156`: **New GradeSuggestion component integration looks well-structured.**

The component receives appropriate props:
- `studentScore` for display context
- `gradeSuggestion` for current state
- `onGradeSuggestionChange` with proper state update and save logic
- `disabled` state for completion handling

The callback correctly triggers both state update and save operation.

---

`151-154`: ```shell
#!/bin/bash
# Inspect the GradeSuggestion component to verify its props interface
sed -n '1,200p' clients/assessment_component/src/assessment/pages/AssessmentPage/components/AssessmentCompletion/components/GradeSuggestion.tsx

27-27: LGTM! Good refactoring to use centralized validation.

Extracting grade validation into a utility function improves code organization and reusability.


21-21: LGTM! Component extraction improves modularity.

Using the GradeSuggestion component to encapsulate grade selection UI is a good architectural decision that improves code organization.


35-39: Function converted to arrow function.

The conversion from function declaration to arrow function is consistent, though note that the deadline prop no longer has a default value.


110-117: LGTM! Simplified mutation call.

Removing the intermediate completionData object and passing the data inline simplifies the code while maintaining the same functionality.


148-156: LGTM! Clean integration of GradeSuggestion component.

The integration passes the necessary props correctly and maintains the existing save behavior through the change handler.

@rappm rappm requested a review from Mtze June 20, 2025 11:37
@rappm rappm added the schau mi o Translation: Ready to review label Jun 20, 2025
@rappm rappm requested a review from mathildeshagl June 20, 2025 13:24
@mathildeshagl
Copy link
Contributor

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
schau mi o Translation: Ready to review
Projects
Status: In Review
Development

Successfully merging this pull request may close these issues.

Show grading suggestion based on assessment input Show grading suggestion generated based on the assessment input
2 participants