Skip to content

Learner Activity Views#165

Merged
ji-mmyliu merged 3 commits intomainfrom
jimmy/activity-learner-views
Dec 23, 2025
Merged

Learner Activity Views#165
ji-mmyliu merged 3 commits intomainfrom
jimmy/activity-learner-views

Conversation

@ji-mmyliu
Copy link
Collaborator

Notion ticket link

Ticket Name

Implementation description

Steps to test

What should reviewers focus on?

Checklist

  • My PR name is descriptive and in imperative tense
  • My commit messages are descriptive and in imperative tense. My commits are atomic and trivial commits are squashed or fixup'd into non-trivial commits
  • I have run the appropriate linter(s)
  • I have requested a review from the PL, as well as other devs who have background knowledge on this PR or who will be building on top of this PR

@github-actions
Copy link

github-actions bot commented Dec 8, 2025

Visit the preview URL for this PR (updated for commit ede8166):

https://extendafamily-7613e--pr165-jimmy-activity-learn-f4837rtu.web.app

(expires Mon, 15 Dec 2025 03:11:19 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: f8bb7b5cd838ab636347dc54fd0ab08ab3715d31

@ji-mmyliu ji-mmyliu marked this pull request as ready for review December 23, 2025 00:25
@ji-mmyliu ji-mmyliu requested a review from Copilot December 23, 2025 00:25
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds interactive learner view functionality for activity pages, enabling learners to complete activities with answer checking and feedback, while providing administrators with preview capabilities.

  • Implements viewer components for three activity types: multiple-choice, table, and matching activities
  • Adds answer validation with feedback modals for incorrect answers
  • Introduces preview modal for administrators to view activities from learner perspective

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
frontend/src/types/CourseTypes.ts Updates type guard functions to accept optional parameters for safer null checking
frontend/src/theme/theme.ts Fixes Pressed state color from black to proper theme color
frontend/src/components/pages/ViewModulePage.tsx Integrates viewer components with role-based rendering and adds interactive buttons for learners and admins
frontend/src/components/course_viewing/table/TableViewer.tsx New component implementing interactive table activity with answer checking
frontend/src/components/course_viewing/multiple-choice/MultipleChoiceViewer.tsx Refactored to forwardRef pattern with answer validation logic
frontend/src/components/course_viewing/multiple-choice/MultipleChoiceViewOption.tsx Adds visual feedback for correct answers and selected states
frontend/src/components/course_viewing/modals/WrongAnswerModal.tsx New modal displaying hints when learners answer incorrectly
frontend/src/components/course_viewing/matching/MatchingViewer.tsx New component implementing drag-and-connect matching activity with visual feedback
frontend/src/components/course_viewing/matching/MatchingBox.tsx New component rendering individual matching boxes with selection states
frontend/src/components/course_authoring/matching/MatchingRow.tsx Removes redundant label text from arrow component
frontend/src/components/course_authoring/editorComponents/PreviewLearnerModal.tsx New modal allowing administrators to preview activities as learners

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +15 to +18
export type ActivityViewerHandle = {
checkAnswer: () => void;
onRetry?: () => void;
};
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The ActivityViewerHandle type is duplicated here. It's also defined in TableViewer.tsx and MatchingViewer.tsx. This type should be defined once in a shared location and imported where needed to maintain consistency.

Copilot uses AI. Check for mistakes.
<TableCell
align="center"
key={colIndex}
sx={{ backgroundColor: displayCorrect ? "#F5FFDF" : "transparent" }}
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The magic color value "#F5FFDF" (light green) is duplicated across multiple files (TableViewer.tsx line 94, MultipleChoiceViewOption.tsx line 42, and MatchingBox.tsx line 30). This should be defined as a constant in the theme or a shared constants file to ensure consistency and make it easier to update.

Copilot uses AI. Check for mistakes.

let backgroundColor: string | null = null;
if (displayCorrect) {
backgroundColor = "#F5FFDF"; // light green
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The magic color value "#F5FFDF" (light green) is hardcoded here. This same value appears in other files (TableViewer.tsx, MatchingBox.tsx). It should be defined as a constant in the theme or a shared constants file to ensure consistency.

Copilot uses AI. Check for mistakes.
Comment on lines +13 to +23
import { TableActivity } from "../../../types/CourseTypes";

type TableViewerProps = {
activity: TableActivity;
onWrongAnswer: () => void;
};

export type ActivityViewerHandle = {
checkAnswer: () => void;
};

Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The ActivityViewerHandle type is duplicated across multiple files (TableViewer.tsx, MultipleChoiceViewer.tsx, and MatchingViewer.tsx). This type should be defined once in a shared location (e.g., in CourseTypes.ts or a dedicated types file) and imported where needed to avoid duplication and potential inconsistencies.

Suggested change
import { TableActivity } from "../../../types/CourseTypes";
type TableViewerProps = {
activity: TableActivity;
onWrongAnswer: () => void;
};
export type ActivityViewerHandle = {
checkAnswer: () => void;
};
import { ActivityViewerHandle, TableActivity } from "../../../types/CourseTypes";
type TableViewerProps = {
activity: TableActivity;
onWrongAnswer: () => void;
};

Copilot uses AI. Check for mistakes.
Comment on lines +6 to +16

type MatchingViewerProps = {
activity: MatchingActivity;
onWrongAnswer: () => void;
};

export type ActivityViewerHandle = {
checkAnswer: () => void;
onRetry?: () => void;
};

Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The ActivityViewerHandle type is duplicated here. It's also defined in TableViewer.tsx and MultipleChoiceViewer.tsx. This type should be defined once in a shared location and imported where needed to maintain consistency.

Suggested change
type MatchingViewerProps = {
activity: MatchingActivity;
onWrongAnswer: () => void;
};
export type ActivityViewerHandle = {
checkAnswer: () => void;
onRetry?: () => void;
};
import type { ActivityViewerHandle } from "../table/TableViewer";
type MatchingViewerProps = {
activity: MatchingActivity;
onWrongAnswer: () => void;
};

Copilot uses AI. Check for mistakes.
Comment on lines +77 to +79
<Typography variant="bodySmall">
<Typography variant="bodySmall">{rowLabel}</Typography>
</Typography>
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

There's a redundant Typography wrapper. The rowLabel is wrapped in a Typography variant="bodySmall" component which itself is inside another Typography variant="bodySmall" component. The outer wrapper should be removed.

Suggested change
<Typography variant="bodySmall">
<Typography variant="bodySmall">{rowLabel}</Typography>
</Typography>
<Typography variant="bodySmall">{rowLabel}</Typography>

Copilot uses AI. Check for mistakes.
Comment on lines +636 to +653
<Button
sx={{
height: "48px",
paddingLeft: "16px",
paddingRight: "24px",
paddingY: "10px",
gap: "8px",
border: "1px solid",
borderColor: theme.palette.Error.Light.Default,
borderRadius: "4px",
backgroundColor: theme.palette.Error.Light.Default,
color: theme.palette.Error.Dark.Default,
}}
onClick={() => {}}
>
<DeleteOutline />
<Typography variant="labelLarge">Delete Page</Typography>
</Button>
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The Delete Page button has an onClick handler that does nothing (empty function). This creates a non-functional button in the UI. Either implement the delete functionality or remove the button until it's ready to be implemented.

Suggested change
<Button
sx={{
height: "48px",
paddingLeft: "16px",
paddingRight: "24px",
paddingY: "10px",
gap: "8px",
border: "1px solid",
borderColor: theme.palette.Error.Light.Default,
borderRadius: "4px",
backgroundColor: theme.palette.Error.Light.Default,
color: theme.palette.Error.Dark.Default,
}}
onClick={() => {}}
>
<DeleteOutline />
<Typography variant="labelLarge">Delete Page</Typography>
</Button>

Copilot uses AI. Check for mistakes.
border: `1px solid ${theme.palette.Neutral[400]}`,
borderRadius: "4px",
cursor: item ? "pointer" : "default",
// transition: "border-color 120ms ease, box-shadow 120ms ease",
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

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

The commented-out transition property suggests it was intentionally disabled. If this is temporary, a TODO comment should explain why. If it's permanent, the commented code should be removed to keep the codebase clean.

Suggested change
// transition: "border-color 120ms ease, box-shadow 120ms ease",

Copilot uses AI. Check for mistakes.
@ji-mmyliu ji-mmyliu merged commit ee7f294 into main Dec 23, 2025
9 checks passed
@ji-mmyliu ji-mmyliu deleted the jimmy/activity-learner-views branch December 23, 2025 00:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant