Skip to content

Commit 36a7faf

Browse files
raisedadeadclaude
andauthored
feat: Implement curriculum database feature from issue (#44)
Co-authored-by: Claude <[email protected]>
1 parent 30a616f commit 36a7faf

File tree

4 files changed

+31
-0
lines changed

4 files changed

+31
-0
lines changed

packages/server/src/data/normalizer.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,20 @@ const BLOCK_LABEL_MAPPING: Record<RawBlockLabel, BlockLabel> = {
4848
learn: BlockLabel.LEARN,
4949
};
5050

51+
/**
52+
* Convert dashedName to human-readable title case name.
53+
* Examples:
54+
* "responsive-web-design" → "Responsive Web Design"
55+
* "javascript-algorithms-and-data-structures" → "JavaScript Algorithms and Data Structures"
56+
* "front-end-development-libraries" → "Front End Development Libraries"
57+
*/
58+
function dashedNameToTitle(dashedName: string): string {
59+
return dashedName
60+
.split('-')
61+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
62+
.join(' ');
63+
}
64+
5165
/**
5266
* Normalize block layout from kebab-case to SCREAMING_SNAKE_CASE enum
5367
* @param raw Raw block layout string
@@ -171,7 +185,11 @@ export function normalizeSuperblock(
171185
flattenedBlocks = [...raw.blocks];
172186
}
173187

188+
// Use the name from JSON if available, otherwise generate from dashedName
189+
const name = raw.name ?? dashedNameToTitle(dashedName);
190+
174191
return {
192+
name,
175193
dashedName,
176194
blocks: flattenedBlocks,
177195
chapters,

packages/server/src/data/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ export interface RawChapter {
108108
* Supports both legacy (flat blocks) and new (hierarchical chapters/modules) structures.
109109
*/
110110
export interface RawSuperblock {
111+
// Optional human-readable name (e.g., "Responsive Web Design")
112+
// If not present in JSON, will be generated from dashedName
113+
readonly name?: string;
114+
111115
// Legacy structure (flat)
112116
readonly blocks?: readonly string[];
113117

@@ -241,6 +245,7 @@ export interface ChapterData {
241245
* Supports both legacy (flat blocks) and new (hierarchical chapters/modules) structures.
242246
*/
243247
export interface SuperblockData {
248+
readonly name: string;
244249
readonly dashedName: string;
245250

246251
// Flattened view (all blocks from all chapters/modules)

packages/server/src/schema/schema.graphql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ Major curriculum area (e.g., Responsive Web Design)
100100
Supports both legacy (flat) and new v9 (hierarchical) curriculum structures
101101
"""
102102
type Superblock {
103+
"""
104+
Human-readable name (e.g., 'Responsive Web Design')
105+
"""
106+
name: String!
107+
103108
"""
104109
Unique identifier (e.g., 'responsive-web-design')
105110
"""

packages/server/src/schema/types.generated.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,8 @@ export type Superblock = {
501501
dashedName: Scalars['String']['output'];
502502
/** True if this superblock is certification-eligible */
503503
isCertification: Scalars['Boolean']['output'];
504+
/** Human-readable name (e.g., 'Responsive Web Design') */
505+
name: Scalars['String']['output'];
504506
};
505507

506508
/**
@@ -1010,6 +1012,7 @@ export type SuperblockResolvers<
10101012
ParentType,
10111013
ContextType
10121014
>;
1015+
name?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
10131016
};
10141017

10151018
export type TestResolvers<

0 commit comments

Comments
 (0)