Skip to content

Commit b94f3c9

Browse files
authored
Merge pull request #3154 from codecrafters-io/refactor-first-stage-task-cards
feat(course-stage): refactor first stage task cards and simplify UI
2 parents c9662a8 + 08b8408 commit b94f3c9

File tree

15 files changed

+145
-291
lines changed

15 files changed

+145
-291
lines changed

app/components/course-page/course-stage-step/first-stage-tutorial-card/index.hbs

Lines changed: 0 additions & 46 deletions
This file was deleted.

app/components/course-page/course-stage-step/first-stage-tutorial-card/navigate-to-file-step.hbs

Lines changed: 0 additions & 55 deletions
This file was deleted.

app/components/course-page/course-stage-step/first-stage-tutorial-card/navigate-to-file-step.ts

Lines changed: 0 additions & 29 deletions
This file was deleted.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<CoursePage::InstructionsCard
2+
@contentIdentifier={{@currentStep.courseStage.id}}
3+
{{! TODO: See if we still need this id marker?}}
4+
id="your-task-card"
5+
class="group/your-task-card"
6+
data-test-your-task-card
7+
data-test-first-stage-your-task-card
8+
...attributes
9+
>
10+
<:header>
11+
<CoursePage::CourseStageStep::YourTaskCard::Header @currentStep={{this.coursePageState.currentStepAsCourseStageStep}} class="mb-5 w-full" />
12+
</:header>
13+
14+
<:content>
15+
<div class="prose dark:prose-invert has-prism-highlighting" data-test-stage-instructions {{highlight-code-blocks this.instructionsMarkdown}}>
16+
{{markdown-to-html this.instructionsMarkdown}}
17+
18+
<h4 id="first-stage-tutorial-heading">
19+
How to pass this stage
20+
</h4>
21+
22+
<p>
23+
Since this is the first stage, we've included some commented code to help you get started. To pass this stage, simply uncomment the code and
24+
submit your changes.
25+
</p>
26+
</div>
27+
28+
<ExpandableStepList @steps={{this.steps}} @onManualStepComplete={{this.handleStepCompletedManually}} class="scroll-mt-32 mt-5" as |stepList|>
29+
{{#if (eq stepList.expandedStep.id "uncomment-code")}}
30+
<CoursePage::CourseStageStep::FirstStageYourTaskCard::UncommentCodeStep
31+
@repository={{@currentStep.repository}}
32+
@courseStage={{@currentStep.courseStage}}
33+
@isComplete={{this.uncommentCodeStepIsComplete}}
34+
/>
35+
{{else if (eq stepList.expandedStep.id "submit-code")}}
36+
<CoursePage::CourseStageStep::FirstStageYourTaskCard::SubmitCodeStep
37+
@courseStage={{@currentStep.courseStage}}
38+
@filename={{this.filename}}
39+
@isComplete={{this.submitCodeStepIsComplete}}
40+
/>
41+
{{/if}}
42+
</ExpandableStepList>
43+
44+
{{#if (eq this.coursePageState.nextStep this.coursePageState.activeStep)}}
45+
<div class="mt-4 flex">
46+
<PrimaryLinkButton
47+
@route={{this.coursePageState.activeStep.routeParams.route}}
48+
@models={{this.coursePageState.activeStep.routeParams.models}}
49+
data-test-continue-button
50+
>
51+
{{#if (eq this.coursePageState.activeStep.type "CourseStageStep")}}
52+
View Next Stage →
53+
{{else}}
54+
View Next Step →
55+
{{/if}}
56+
</PrimaryLinkButton>
57+
</div>
58+
{{/if}}
59+
</:content>
60+
</CoursePage::InstructionsCard>
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
import AnalyticsEventTrackerService from 'codecrafters-frontend/services/analytics-event-tracker';
22
import Component from '@glimmer/component';
33
import CoursePageStateService from 'codecrafters-frontend/services/course-page-state';
4-
import FeatureFlagsService from 'codecrafters-frontend/services/feature-flags';
4+
import RepositoryModel from 'codecrafters-frontend/models/repository';
55
import Store from '@ember-data/store';
6-
import type CourseStageModel from 'codecrafters-frontend/models/course-stage';
7-
import type RepositoryModel from 'codecrafters-frontend/models/repository';
86
import type { StepDefinition } from 'codecrafters-frontend/components/expandable-step-list';
9-
import type CourseStageStep from 'codecrafters-frontend/utils/course-page-step-list/course-stage-step';
10-
import { action } from '@ember/object';
117
import { inject as service } from '@ember/service';
8+
import { action } from '@ember/object';
9+
import type CourseStageStep from 'codecrafters-frontend/utils/course-page-step-list/course-stage-step';
1210

1311
interface Signature {
1412
Element: HTMLDivElement;
1513

1614
Args: {
17-
repository: RepositoryModel;
18-
courseStage: CourseStageModel;
1915
currentStep: CourseStageStep;
2016
};
2117
}
@@ -30,51 +26,37 @@ class BaseStep {
3026
}
3127
}
3228

33-
class NavigateToFileStep extends BaseStep implements StepDefinition {
34-
id = 'navigate-to-file';
29+
class UncommentCodeStep extends BaseStep implements StepDefinition {
30+
id = 'uncomment-code';
3531
canBeCompletedManually = true;
3632

3733
get titleMarkdown() {
38-
if (!this.repository.firstStageSolution) {
39-
return 'Navigate to README.md';
40-
}
41-
42-
const filename = this.repository.firstStageSolution.changedFiles[0]!.filename;
34+
const filename = this.repository.firstStageSolution?.changedFiles[0]?.filename;
4335

4436
if (filename) {
45-
return `Navigate to ${filename}`;
37+
return `Uncomment code in ${filename}`;
4638
} else {
47-
return 'Navigate to file';
39+
return 'Uncomment code';
4840
}
4941
}
5042
}
5143

52-
class UncommentCodeStep extends BaseStep implements StepDefinition {
53-
id = 'uncomment-code';
54-
canBeCompletedManually = true;
55-
56-
get titleMarkdown() {
57-
return 'Uncomment code';
58-
}
59-
}
60-
6144
class SubmitCodeStep extends BaseStep implements StepDefinition {
6245
id = 'submit-code';
6346
canBeCompletedManually = false;
6447

6548
get titleMarkdown() {
66-
return 'Submit changes';
49+
return 'Git push to submit your changes';
6750
}
6851
}
6952

70-
export default class FirstStageTutorialCard extends Component<Signature> {
53+
export default class FirstStageYourTaskCard extends Component<Signature> {
7154
@service declare analyticsEventTracker: AnalyticsEventTrackerService;
7255
@service declare coursePageState: CoursePageStateService;
73-
@service declare featureFlags: FeatureFlagsService;
7456
@service declare store: Store;
7557

7658
get filename() {
77-
const solution = this.args.courseStage.solutions.find((solution) => solution.language === this.args.repository.language);
59+
const solution = this.args.currentStep.courseStage.solutions.find((solution) => solution.language === this.args.currentStep.repository.language);
7860

7961
return solution?.changedFiles[0]?.filename;
8062
}
@@ -83,24 +65,22 @@ export default class FirstStageTutorialCard extends Component<Signature> {
8365
return this.args.currentStep.testsStatus === 'passed' || this.args.currentStep.status === 'complete';
8466
}
8567

86-
get navigateToFileStepIsComplete() {
87-
return this.navigateToFileStepWasMarkedAsComplete || this.uncommentCodeStepIsComplete;
88-
}
89-
90-
get navigateToFileStepWasMarkedAsComplete() {
91-
return this.coursePageState.manuallyCompletedStepIdsInFirstStageInstructions.includes('navigate-to-file');
68+
get instructionsMarkdown() {
69+
return this.args.currentStep.courseStage.buildInstructionsMarkdownFor(this.args.currentStep.repository);
9270
}
9371

9472
get steps() {
9573
return [
96-
new NavigateToFileStep(this.args.repository, this.navigateToFileStepIsComplete),
97-
new UncommentCodeStep(this.args.repository, this.uncommentCodeStepIsComplete),
98-
new SubmitCodeStep(this.args.repository, this.submitCodeStepIsComplete),
74+
new UncommentCodeStep(this.args.currentStep.repository, this.uncommentCodeStepIsComplete),
75+
new SubmitCodeStep(this.args.currentStep.repository, this.submitCodeStepIsComplete),
9976
];
10077
}
10178

10279
get submitCodeStepIsComplete() {
103-
return this.args.repository.lastSubmissionHasSuccessStatus || this.args.repository.stageIsComplete(this.args.courseStage);
80+
return (
81+
this.args.currentStep.repository.lastSubmissionHasSuccessStatus ||
82+
this.args.currentStep.repository.stageIsComplete(this.args.currentStep.courseStage)
83+
);
10484
}
10585

10686
get uncommentCodeStepIsComplete() {
@@ -113,24 +93,13 @@ export default class FirstStageTutorialCard extends Component<Signature> {
11393

11494
@action
11595
handleStepCompletedManually(step: StepDefinition) {
116-
if (step.id === 'navigate-to-file') {
117-
this.coursePageState.recordManuallyCompletedStepInFirstStageInstructions('navigate-to-file');
118-
119-
this.analyticsEventTracker.track('completed_first_stage_tutorial_step', {
120-
step_number: 1,
121-
step_id: 'navigate-to-file',
122-
repository_id: this.args.repository.id,
123-
});
124-
}
125-
12696
if (step.id === 'uncomment-code') {
12797
this.coursePageState.recordManuallyCompletedStepInFirstStageInstructions('uncomment-code');
128-
this.coursePageState.recordManuallyCompletedStepInFirstStageInstructions('navigate-to-file');
12998

13099
this.analyticsEventTracker.track('completed_first_stage_tutorial_step', {
131-
step_number: 2,
100+
step_number: 1,
132101
step_id: 'uncomment-code',
133-
repository_id: this.args.repository.id,
102+
repository_id: this.args.currentStep.repository.id,
134103
});
135104
}
136105
}
@@ -143,6 +112,6 @@ export default class FirstStageTutorialCard extends Component<Signature> {
143112

144113
declare module '@glint/environment-ember-loose/registry' {
145114
export default interface Registry {
146-
'CoursePage::CourseStageStep::FirstStageTutorialCard': typeof FirstStageTutorialCard;
115+
'CoursePage::CourseStageStep::FirstStageYourTaskCard': typeof FirstStageYourTaskCard;
147116
}
148117
}

0 commit comments

Comments
 (0)