feat: separate trails and formations in cms
This commit is contained in:
8
server/migrations/010_learning_path_kind.sql
Normal file
8
server/migrations/010_learning_path_kind.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
-- Both content types are intentionally composed from existing courses. The
|
||||
-- distinction is editorial: a "trilha" is a guided sequence and a
|
||||
-- "formação" is a broader curriculum collection.
|
||||
alter table learning_paths
|
||||
add column kind text not null default 'trail'
|
||||
check (kind in ('trail', 'formation'));
|
||||
|
||||
create index learning_paths_kind_index on learning_paths (kind, published_at desc);
|
||||
@@ -33,6 +33,7 @@ const learningPathSchema = z.object({
|
||||
coverImagePositionX: z.number().min(0).max(100).default(50),
|
||||
coverImagePositionY: z.number().min(0).max(100).default(50),
|
||||
status: z.enum(['draft', 'published']).default('draft'),
|
||||
kind: z.enum(['trail', 'formation']).default('trail'),
|
||||
courseIds: z.array(z.string().uuid()).min(1).max(100),
|
||||
});
|
||||
|
||||
@@ -45,7 +46,7 @@ const getLearningPaths = async () => {
|
||||
p.cover_image_zoom as "coverImageZoom",
|
||||
p.cover_image_position_x as "coverImagePositionX",
|
||||
p.cover_image_position_y as "coverImagePositionY",
|
||||
p.status, p.published_at as "publishedAt", p.created_at as "createdAt",
|
||||
p.status, p.kind, p.published_at as "publishedAt", p.created_at as "createdAt",
|
||||
coalesce(jsonb_agg(jsonb_build_object(
|
||||
'id', c.id, 'title', c.title, 'status', c.status,
|
||||
'coverImageUrl', c.cover_image_url, 'position', pc.position
|
||||
@@ -126,10 +127,10 @@ export const adminRoutes: FastifyPluginAsync = async (app) => {
|
||||
const courseIds = await validatePathCourses(client, input);
|
||||
const path = await client.query<{ id: string }>(
|
||||
`insert into learning_paths (
|
||||
title, description, cover_image_url, cover_image_zoom, cover_image_position_x, cover_image_position_y, status, published_at
|
||||
) values ($1, $2, $3, $4, $5, $6, $7::course_status, case when $7 = 'published' then now() else null end)
|
||||
title, description, cover_image_url, cover_image_zoom, cover_image_position_x, cover_image_position_y, status, kind, published_at
|
||||
) values ($1, $2, $3, $4, $5, $6, $7::course_status, $8, case when $7 = 'published' then now() else null end)
|
||||
returning id`,
|
||||
[input.title, input.description, input.coverImageUrl, input.coverImageZoom, input.coverImagePositionX, input.coverImagePositionY, input.status],
|
||||
[input.title, input.description, input.coverImageUrl, input.coverImageZoom, input.coverImagePositionX, input.coverImagePositionY, input.status, input.kind],
|
||||
);
|
||||
await writePathCourses(client, path.rows[0].id, courseIds);
|
||||
await client.query('commit');
|
||||
@@ -155,11 +156,11 @@ export const adminRoutes: FastifyPluginAsync = async (app) => {
|
||||
const path = await client.query<{ id: string }>(
|
||||
`update learning_paths set
|
||||
title = $2, description = $3, cover_image_url = $4, cover_image_zoom = $5,
|
||||
cover_image_position_x = $6, cover_image_position_y = $7, status = $8::course_status,
|
||||
cover_image_position_x = $6, cover_image_position_y = $7, status = $8::course_status, kind = $9,
|
||||
published_at = case when $8 = 'published' then coalesce(published_at, now()) else null end
|
||||
where id = $1
|
||||
returning id`,
|
||||
[pathId, input.title, input.description, input.coverImageUrl, input.coverImageZoom, input.coverImagePositionX, input.coverImagePositionY, input.status],
|
||||
[pathId, input.title, input.description, input.coverImageUrl, input.coverImageZoom, input.coverImagePositionX, input.coverImagePositionY, input.status, input.kind],
|
||||
);
|
||||
if (!path.rows[0]) {
|
||||
await client.query('rollback');
|
||||
|
||||
@@ -153,7 +153,7 @@ export const courseRoutes: FastifyPluginAsync = async (app) => {
|
||||
app.get('/paths', async () => {
|
||||
const result = await pool.query(
|
||||
`select
|
||||
p.id, p.title, p.description,
|
||||
p.id, p.title, p.description, p.kind,
|
||||
coalesce(p.cover_image_url, (
|
||||
select value #>> '{}' from platform_settings where key = 'media.defaultCoverImageUrl'
|
||||
)) as "coverImageUrl",
|
||||
|
||||
Reference in New Issue
Block a user