Skip to content

[Feat/native/#227] 이어서 풀기 관련 로직 수정(DOING handling 추가)#229

Merged
sterdsterd merged 8 commits intodevelopfrom
feat/native/doing-handling-#227
Feb 20, 2026
Merged

[Feat/native/#227] 이어서 풀기 관련 로직 수정(DOING handling 추가)#229
sterdsterd merged 8 commits intodevelopfrom
feat/native/doing-handling-#227

Conversation

@sterdsterd
Copy link
Collaborator

📌 Related Issue Number


✅ Key Changes

이번 PR에서 작업한 내용을 간략히 설명해주세요

  1. DOING 핸들링 구현
  2. API 수정사항 반영(schema.d.ts 업데이트)
  3. attemptCount, lastProgressInfo 기반 마지막 상태에서 이어서 풀기 구현

@sterdsterd sterdsterd requested a review from Copilot February 20, 2026 19:26
@sterdsterd sterdsterd self-assigned this Feb 20, 2026
@sterdsterd sterdsterd added the 🐞 Fix 버그 수정 label Feb 20, 2026
@vercel
Copy link

vercel bot commented Feb 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
pointer-admin Ready Ready Preview, Comment Feb 20, 2026 7:32pm

Copy link

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 implements the "resume from where you left off" functionality for problem-solving sessions with proper handling of the DOING state. It adds support for tracking attempt counts and progress information, allowing students to continue their problem-solving session from the exact point where they stopped.

Changes:

  • Added API schema updates to support resume functionality (LastProgressInfo, attemptCount, publishId fields)
  • Implemented MAIN_PROBLEM_RETRY phase and resume state computation logic in problem session store
  • Updated all entry points (deep links, notifications, problem set) to use initWithResume instead of init

Reviewed changes

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

Show a summary per file
File Description
apps/native/src/types/api/schema.d.ts Added LastProgressInfo type, attemptCount fields, and optional publishId to PointingFeedbackRequest
apps/native/src/stores/problemSessionStore.ts Added MAIN_PROBLEM_RETRY phase, initWithResume action, and computeResumeState function to handle session resumption logic
apps/native/src/hooks/useDeepLinkHandler.ts Updated to use initWithResume and navigate to appropriate screen based on session phase
apps/native/src/features/student/problem/screens/ProblemScreen.tsx Added handling for MAIN_PROBLEM_RETRY phase and updated attempt count tracking
apps/native/src/features/student/problem/screens/PointingScreen.tsx Updated pointing feedback submission to include publishId and fixed CTA button labels for different paths
apps/native/src/features/student/home/screens/notifications/NotificationsScreen.tsx Updated to use initWithResume and phase-based navigation
apps/native/src/features/student/home/components/ProblemSet.tsx Updated to use initWithResume and phase-based navigation
apps/native/src/apis/controller/student/study/postPointing.ts Added optional publishId parameter to pointing feedback API

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

Comment on lines +80 to +89
};

const findNextPointingIndex = (
pointings: PointingWithFeedbackResp[],
lastAnsweredNo: number | undefined | null
): number => {
if (lastAnsweredNo == null) return 0;
const lastIdx = pointings.findIndex((p) => p.no === lastAnsweredNo);
if (lastIdx === -1) return 0;
return lastIdx + 1;
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

The findNextPointingIndex helper function is defined but never used in the code. Consider removing it if it's not needed, or use it if it was intended to be part of the resume logic.

Suggested change
};
const findNextPointingIndex = (
pointings: PointingWithFeedbackResp[],
lastAnsweredNo: number | undefined | null
): number => {
if (lastAnsweredNo == null) return 0;
const lastIdx = pointings.findIndex((p) => p.no === lastAnsweredNo);
if (lastIdx === -1) return 0;
return lastIdx + 1;

Copilot uses AI. Check for mistakes.
const totalChildPointingCount = children.reduce((s, c) => s + (c.pointings ?? []).length, 0);
const childPointingsDone = answeredChildPointingCount >= totalChildPointingCount;

if (!childPointingsDone) {
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

The condition mainPointings.every((p) => p.isUnderstood == null) is redundant because if all pointings are unanswered, mainNextPIdx would already be 0 (the first unanswered pointing). The check mainNextPIdx === 0 alone is sufficient for determining whether to go to MAIN_PROBLEM_RETRY phase.

Suggested change
if (!childPointingsDone) {
if (mainNextPIdx === 0) {

Copilot uses AI. Check for mistakes.
Comment on lines +243 to +262
if (mainNextPIdx !== -1 && mainNextPIdx > 0) {
return {
phase: 'MAIN_POINTINGS',
childIndex: INITIAL_INDEX,
pointingIndex: mainNextPIdx,
pointingTarget: 'MAIN',
mainCorrect: false,
};
}

if (mainNextPIdx === 0 || mainPointings.every((p) => p.isUnderstood == null)) {
return {
phase: 'MAIN_PROBLEM_RETRY',
childIndex: INITIAL_INDEX,
pointingIndex: INITIAL_INDEX,
pointingTarget: undefined,
mainCorrect: false,
};
}

Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

When the main problem is incorrect (isMainCorrect === false) and there are no child problems (totalChildren === 0), the logic falls through to line 245 which directs to MAIN_POINTINGS. However, according to the incorrect path flow, the student should retry the main problem first (MAIN_PROBLEM_RETRY) before doing main pointings. Consider adding a condition to handle the case when !isMainCorrect && totalChildren === 0 to direct to MAIN_PROBLEM_RETRY phase.

Suggested change
if (mainNextPIdx !== -1 && mainNextPIdx > 0) {
return {
phase: 'MAIN_POINTINGS',
childIndex: INITIAL_INDEX,
pointingIndex: mainNextPIdx,
pointingTarget: 'MAIN',
mainCorrect: false,
};
}
if (mainNextPIdx === 0 || mainPointings.every((p) => p.isUnderstood == null)) {
return {
phase: 'MAIN_PROBLEM_RETRY',
childIndex: INITIAL_INDEX,
pointingIndex: INITIAL_INDEX,
pointingTarget: undefined,
mainCorrect: false,
};
}
// ... some existing logic for when all children are solved ...
// (not shown in the snippet)
}
// When the main problem is incorrect and there are no child problems,
// the student should retry the main problem before doing main pointings.
if (!isMainCorrect && totalChildren === 0) {
return {
phase: 'MAIN_PROBLEM_RETRY',
childIndex: INITIAL_INDEX,
pointingIndex: INITIAL_INDEX,
pointingTarget: undefined,
mainCorrect: false,
};
}
const mainNextPIdx = mainPointings.findIndex((p) => p.isUnderstood == null);
if (mainNextPIdx !== -1) {
return {
phase: 'MAIN_POINTINGS',
childIndex: INITIAL_INDEX,
pointingIndex: mainNextPIdx,
pointingTarget: 'MAIN',
mainCorrect: false,
};
}
return {
phase: 'ANALYSIS',
childIndex: INITIAL_INDEX,
pointingIndex: INITIAL_INDEX,
pointingTarget: undefined,
mainCorrect: false,
};

Copilot uses AI. Check for mistakes.
Comment on lines 353 to 367
mainCorrect: true,
phase: 'MAIN_POINTINGS',
pointingTarget: 'MAIN',
pointingIndex: 0,
});
} else {
set({
mainCorrect: true,
phase: 'ANALYSIS',
pointingTarget: undefined,
pointingIndex: INITIAL_INDEX,
});
}
return;
}
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

When the main problem is answered incorrectly on the first attempt and there are no child problems, the logic goes directly to MAIN_POINTINGS or ANALYSIS (lines 353-367). However, according to the new MAIN_PROBLEM_RETRY flow, the student should be directed to retry the main problem first. Consider changing this logic to direct to MAIN_PROBLEM_RETRY phase instead, or clarify if this path should skip the retry (which would be inconsistent with the incorrect path after child problems are completed).

Copilot uses AI. Check for mistakes.
Comment on lines +180 to +186

const lastChildIdx = findChildIndexByNo(children, lastChildNo);
if (lastChildIdx !== -1) {
const child = children[lastChildIdx];
const childAttempts = child.attemptCount ?? 0;
const childCorrect = child.progress === 'CORRECT' || child.progress === 'SEMI_CORRECT';
if (!childCorrect && childAttempts < MAX_RETRY_ATTEMPTS) {
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

lastChildIdx could be -1 when findChildIndexByNo returns -1 (child not found). Using it directly to compute nextChildIdx would result in nextChildIdx being 0, which could incorrectly navigate to the first child problem instead of handling the error case properly. Consider adding a check to handle the case when lastChildIdx === -1 before computing nextChildIdx.

Suggested change
const lastChildIdx = findChildIndexByNo(children, lastChildNo);
if (lastChildIdx !== -1) {
const child = children[lastChildIdx];
const childAttempts = child.attemptCount ?? 0;
const childCorrect = child.progress === 'CORRECT' || child.progress === 'SEMI_CORRECT';
if (!childCorrect && childAttempts < MAX_RETRY_ATTEMPTS) {
const nextChildIdx = lastChildIdx + 1;
if (nextChildIdx < children.length) {
return {
phase: 'CHILD_PROBLEM',
childIndex: nextChildIdx,
pointingIndex: INITIAL_INDEX,
pointingTarget: undefined,
mainCorrect: false,
};
}
} else {
// lastSolvedChildProblemNo did not correspond to any child; start from the first child.
return {
phase: 'CHILD_PROBLEM',
childIndex: 0,

Copilot uses AI. Check for mistakes.
Comment on lines 171 to 172
[isSubmittingUnderstanding, pointing?.id]
);
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

publishId is used inside the callback but is missing from the dependency array. This could cause the callback to capture a stale value of publishId. Add publishId to the dependency array.

Copilot uses AI. Check for mistakes.
@sterdsterd sterdsterd merged commit 33eba8c into develop Feb 20, 2026
2 checks passed
@sterdsterd sterdsterd deleted the feat/native/doing-handling-#227 branch February 20, 2026 19:35
@sterdsterd sterdsterd restored the feat/native/doing-handling-#227 branch February 21, 2026 06:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐞 Fix 버그 수정

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] 이어서 풀기 관련 로직 수정(DOING handling 추가)

2 participants