Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions mobile-app/lib/models/learn/challenge_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ class Challenge {
final EnglishAudio? audio;
final Scene? scene;

// Nodules for interactive challenges
final List<Nodules>? nodules;

final List<Question>? questions;

// Challenge Type 15 - Odin
Expand All @@ -92,6 +95,7 @@ class Challenge {
required this.helpCategory,
this.explanation,
required this.transcript,
this.nodules,
this.questions,
this.assignments,
this.fillInTheBlank,
Expand Down Expand Up @@ -127,6 +131,9 @@ class Challenge {
files: (data['challengeFiles'] ?? [])
.map<ChallengeFile>((file) => ChallengeFile.fromJson(file))
.toList(),
nodules: (data['nodules'] ?? [])
.map<Nodules>((nodule) => Nodules.fromJson(nodule))
.toList(),
questions: (data['questions'] as List).isNotEmpty
? (data['questions'] as List)
.map<Question>((q) => Question.fromJson(q))
Expand Down Expand Up @@ -225,6 +232,96 @@ class Hooks {
}
}

sealed class StringOrList {}

enum NoduleType {
paragraph('paragraph'),
interactiveEditor('interactiveEditor');

final String type;

const NoduleType(this.type);
}

class NoduleTypeString extends StringOrList {
final String value;

NoduleTypeString(this.value);
}

class NoduleTypeList extends StringOrList {
final List<InterActiveFile> value;

NoduleTypeList(this.value);
}

class Nodules {
final NoduleType type;
final StringOrList data;

Nodules({
required this.type,
required this.data,
});

String asString() {
return (data as NoduleTypeString).value;
}

List<InterActiveFile> asList() {
return (data as NoduleTypeList).value;
}

factory Nodules.fromJson(Map<String, dynamic> data) {
final noduleType = NoduleType.values.firstWhere(
(type) => type.type == data['type'],
orElse: () => throw ArgumentError('Invalid nodule type: ${data['type']}'),
);

final noduleData = data['data'];
if (noduleData is String) {
return Nodules(
type: noduleType,
data: NoduleTypeString(noduleData),
);
} else if (noduleData is List) {
return Nodules(
type: noduleType,
data: NoduleTypeList(
noduleData
.map<InterActiveFile>(
(item) => InterActiveFile.fromJson(item),
)
.toList(),
),
);
} else {
throw ArgumentError(
'Invalid nodule data type: ${noduleData.runtimeType}');
}
}
}

class InterActiveFile {
final String name;
final String contents;
final String ext;

InterActiveFile({
required this.ext,
required this.name,
required this.contents,
});

factory InterActiveFile.fromJson(Map<String, dynamic> data) {
return InterActiveFile(
ext: data['ext'],
name: data['name'],
contents: data['contents'],
);
}
}

class Question {
final String text;
final List<Answer> answers;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'package:freecodecamp/ui/views/learn/widgets/quiz_widget.dart';
import 'package:freecodecamp/ui/views/learn/widgets/transcript_widget.dart';
import 'package:freecodecamp/ui/views/learn/widgets/youtube_player_widget.dart';
import 'package:freecodecamp/ui/views/news/html_handler/html_handler.dart';
import 'package:phone_ide/phone_ide.dart';
import 'package:stacked/stacked.dart';

class MultipleChoiceView extends StatelessWidget {
Expand Down Expand Up @@ -59,6 +60,35 @@ class MultipleChoiceView extends StatelessWidget {
),
),
),
if (challenge.nodules?.isNotEmpty ?? false)
ChallengeCard(
title: 'Lesson',
child: Column(
children: [
...(challenge.nodules ?? []).map(
(nodule) {
if (nodule.type == NoduleType.paragraph) {
return Column(
children: parser.parse(nodule.asString()),
);
} else if (nodule.type ==
NoduleType.interactiveEditor) {
return Editor(
options: EditorOptions(
takeFullHeight: false,
showLinebar: false,
),
defaultLanguage: nodule.asList()[0].ext,
defaultValue: nodule.asList()[0].contents,
path: '/');
} else {
return const SizedBox.shrink();
}
},
)
],
),
),
if (challenge.videoId != null) ...[
ChallengeCard(
title: 'Watch the Video',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,9 @@ class LearnLandingViewModel extends BaseViewModel {

List superBlocks = res.data['superblocks'];
for (int i = 0; i < superBlocks.length; i++) {
if (superBlocks[i]['dashedName'].toString().contains('full-stack')) {
continue;
}
// if (superBlocks[i]['dashedName'].toString().contains('full-stack')) {
// continue;
// }
Comment on lines +246 to +248
Copy link
Member

Choose a reason for hiding this comment

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

Do we have a way to enable FSD for dev only, without making it available in prod?

Copy link
Member Author

Choose a reason for hiding this comment

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

yep this is the way

Copy link
Member Author

Choose a reason for hiding this comment

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

I think this is mostly a relic from what we used to do with the new landing page for the full stack cert

layout.add(
SuperBlockButton(
button: SuperBlockButtonData(
Expand Down
Loading