Skip to content

Commit d4b4cfe

Browse files
committed
feat: add concept list and item components for track page
Implement the `ConceptList` and `ConceptListItem` components to display sorted concepts on the track page. Introduce a new SVG icon for visual representation. Update the card layout for better spacing and remove an unused SVG. These changes enhance the user interface and improve the organization of concept information.
1 parent 4a941e7 commit d4b4cfe

File tree

10 files changed

+156
-3
lines changed

10 files changed

+156
-3
lines changed

app/components/track-page/card.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
{{#if @isComplete}}
3232
{{svg-jar "check-circle" class="w-8 h-8 fill-current text-teal-500"}}
3333
{{else if (and @logoImageUrl @logoImageAltText)}}
34-
<img src={{@logoImageUrl}} alt={{@logoImageAltText}} class="w-8 md:w-12 transform scale-100 group-hover:scale-105 transition-all" />
34+
<img src={{@logoImageUrl}} alt={{@logoImageAltText}} class="w-8 transform scale-100 group-hover:scale-105 transition-all" />
3535
{{/if}}
3636
</div>
3737
</div>

app/components/track-page/course-card.hbs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
</:afterTitle>
1515

1616
<:default>
17-
<div class="leading-6 prose dark:prose-invert mb-6">
17+
<div class="leading-6 prose dark:prose-invert mb-4 pr-8">
1818
{{markdown-to-html this.introductionMarkdown}}
1919
</div>
2020

@@ -53,7 +53,7 @@
5353
</div>
5454
{{/if}}
5555

56-
<div class="leading-6 prose dark:prose-invert mb-6 pr-8 md:pr-12">
56+
<div class="leading-6 prose dark:prose-invert mb-4 pr-8">
5757
{{markdown-to-html this.introductionMarkdown}}
5858
</div>
5959

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<LinkTo
2+
@route="concept"
3+
@models={{array @concept.slug}}
4+
class="block hover:bg-gray-50 dark:hover:bg-gray-700/50 py-1.5 -mx-1.5 px-1.5 rounded"
5+
data-test-concept-list-item
6+
...attributes
7+
>
8+
<div class="flex items-center justify-between">
9+
<div class="flex items-center">
10+
<div class="w-2 h-2 {{if @isComplete 'bg-teal-500' 'bg-gray-200 dark:bg-gray-700'}} rounded-full mr-2"></div>
11+
12+
{{! TODO: Qualify all heroicons with solid/outline }}
13+
{{svg-jar "book-open-outline" class="w-6 mr-2 text-gray-400 dark:text-gray-600"}}
14+
15+
<div class="prose dark:prose-invert prose-sm">
16+
{{@concept.title}}
17+
</div>
18+
</div>
19+
20+
{{#if @isComplete}}
21+
{{svg-jar "check" class="ml-1 w-5 text-teal-500"}}
22+
{{else}}
23+
<div class="items-center gap-1 pl-4 hidden sm:flex flex-shrink-0">
24+
{{svg-jar "clock" class="w-4 fill-current text-gray-300 dark:text-gray-700"}}
25+
26+
<span class="text-xs text-gray-400 dark:text-gray-600">
27+
{{@concept.estimatedReadingTimeInMinutes}}
28+
mins
29+
</span>
30+
</div>
31+
{{/if}}
32+
</div>
33+
</LinkTo>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import Component from '@glimmer/component';
2+
import type AuthenticatorService from 'codecrafters-frontend/services/authenticator';
3+
import type ConceptModel from 'codecrafters-frontend/models/concept';
4+
import { service } from '@ember/service';
5+
6+
interface Signature {
7+
Element: HTMLAnchorElement;
8+
9+
Args: {
10+
isComplete: boolean;
11+
concept: ConceptModel;
12+
};
13+
}
14+
15+
export default class ConceptListItemComponent extends Component<Signature> {
16+
@service declare authenticator: AuthenticatorService;
17+
}
18+
19+
declare module '@glint/environment-ember-loose/registry' {
20+
export default interface Registry {
21+
'TrackPage::PrimerConceptGroupCard::ConceptListItem': typeof ConceptListItemComponent;
22+
}
23+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{{#each this.sortedConcepts as |concept|}}
2+
<TrackPage::PrimerConceptGroupCard::ConceptListItem @concept={{concept}} @isComplete={{false}} />
3+
{{/each}}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import Component from '@glimmer/component';
2+
import ConceptGroupModel from 'codecrafters-frontend/models/concept-group';
3+
import ConceptModel from 'codecrafters-frontend/models/concept';
4+
import Store from '@ember-data/store';
5+
import { inject as service } from '@ember/service';
6+
7+
interface Signature {
8+
Element: HTMLDivElement;
9+
10+
Args: {
11+
conceptGroup: ConceptGroupModel;
12+
};
13+
}
14+
15+
export default class TrackPagePrimerConceptGroupCardConceptListComponent extends Component<Signature> {
16+
@service declare store: Store;
17+
18+
get sortedConcepts() {
19+
return this.args.conceptGroup.conceptSlugs.reduce((acc, slug) => {
20+
const concept = this.store.peekAll('concept').find((concept) => concept.slug === slug);
21+
22+
if (concept) {
23+
acc.push(concept);
24+
}
25+
26+
return acc;
27+
}, [] as ConceptModel[]);
28+
}
29+
}
30+
31+
declare module '@glint/environment-ember-loose/registry' {
32+
export default interface Registry {
33+
'TrackPage::PrimerConceptGroupCard::ConceptList': typeof TrackPagePrimerConceptGroupCardConceptListComponent;
34+
}
35+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<TrackPage::Card
2+
@isComplete={{false}}
3+
@logoImageAltText={{@language.name}}
4+
@logoImageUrl={{@language.colorLogoUrl}}
5+
@title="Rust Primer"
6+
@recentParticipants={{array}}
7+
...attributes
8+
>
9+
<:afterTitle>
10+
<Pill @color="green">
11+
FREE
12+
</Pill>
13+
</:afterTitle>
14+
15+
<:default>
16+
<div class="leading-6 prose dark:prose-invert mb-4">
17+
New to Rust? Start with our interactive concepts that cover the basics.
18+
</div>
19+
20+
<TrackPage::PrimerConceptGroupCard::ConceptList @conceptGroup={{@conceptGroup}} />
21+
</:default>
22+
</TrackPage::Card>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import Component from '@glimmer/component';
2+
import ConceptGroupModel from 'codecrafters-frontend/models/concept-group';
3+
import LanguageModel from 'codecrafters-frontend/models/language';
4+
5+
interface Signature {
6+
Element: HTMLDivElement;
7+
8+
Args: {
9+
language: LanguageModel;
10+
conceptGroup: ConceptGroupModel;
11+
};
12+
}
13+
14+
export default class TrackPagePrimerConceptGroupCardComponent extends Component<Signature> {}
15+
16+
declare module '@glint/environment-ember-loose/registry' {
17+
export default interface Registry {
18+
'TrackPage::PrimerConceptGroupCard': typeof TrackPagePrimerConceptGroupCardComponent;
19+
}
20+
}

app/templates/track.hbs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,23 @@
1010
<div class="container mx-auto lg:max-w-screen-lg px-3 md:px-6 py-6 md:py-10">
1111
<div class="flex items-start">
1212
<div class="flex-grow">
13+
{{#if this.trackPrimerConceptGroup}}
14+
<TrackPage::PrimerConceptGroupCard @language={{@model.language}} @conceptGroup={{this.trackPrimerConceptGroup}} class="w-full mb-6" />
15+
16+
<div class="border-b pb-1 mb-4 flex">
17+
<div class="text-2xl font-semibold text-gray-800 dark:text-gray-200">
18+
{{@model.language.name}}
19+
Projects
20+
</div>
21+
</div>
22+
23+
<div class="prose dark:prose-invert mb-4">
24+
<p>
25+
Ready to get your hands dirty? Here are some projects you can build.
26+
</p>
27+
</div>
28+
{{/if}}
29+
1330
<TrackPage::CourseCardList @language={{@model.language}} @courses={{this.sortedCourses}} class="w-full mb-4" />
1431
</div>
1532

public/assets/images/heroicons/outline/book-open.svg renamed to public/assets/images/heroicons/outline/book-open-outline.svg

File renamed without changes.

0 commit comments

Comments
 (0)