academe-kit 0.9.6 → 0.9.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1282,6 +1282,68 @@ export interface paths {
1282
1282
  patch?: never;
1283
1283
  trace?: never;
1284
1284
  };
1285
+ "/certificates/{userId}/download-all": {
1286
+ parameters: {
1287
+ query?: never;
1288
+ header?: never;
1289
+ path?: never;
1290
+ cookie?: never;
1291
+ };
1292
+ /**
1293
+ * Download all certificates of a user as a single PDF
1294
+ * @description Downloads all certificates of the given user merged into a single PDF file.
1295
+ * Each certificate occupies one page in the resulting file.
1296
+ * PDFs are downloaded from S3 in parallel and merged using pdf-lib.
1297
+ */
1298
+ get: {
1299
+ parameters: {
1300
+ query?: never;
1301
+ header?: never;
1302
+ path: {
1303
+ /** @description ID of the user whose certificates will be downloaded */
1304
+ userId: string;
1305
+ };
1306
+ cookie?: never;
1307
+ };
1308
+ requestBody?: never;
1309
+ responses: {
1310
+ /** @description Merged PDF file containing all user certificates */
1311
+ 200: {
1312
+ headers: {
1313
+ /** @description attachment; filename="Meus-Certificados.pdf" */
1314
+ "Content-Disposition"?: string;
1315
+ [name: string]: unknown;
1316
+ };
1317
+ content: {
1318
+ "application/pdf": string;
1319
+ };
1320
+ };
1321
+ 401: components["responses"]["Unauthorized"];
1322
+ /** @description No certificates found for the user */
1323
+ 404: {
1324
+ headers: {
1325
+ [name: string]: unknown;
1326
+ };
1327
+ content: {
1328
+ "application/json": {
1329
+ /** @example error */
1330
+ status?: string;
1331
+ /** @example No certificates found for this user */
1332
+ message?: string;
1333
+ };
1334
+ };
1335
+ };
1336
+ 500: components["responses"]["ServerError"];
1337
+ };
1338
+ };
1339
+ put?: never;
1340
+ post?: never;
1341
+ delete?: never;
1342
+ options?: never;
1343
+ head?: never;
1344
+ patch?: never;
1345
+ trace?: never;
1346
+ };
1285
1347
  "/certificates": {
1286
1348
  parameters: {
1287
1349
  query?: never;
@@ -1291,13 +1353,24 @@ export interface paths {
1291
1353
  };
1292
1354
  /**
1293
1355
  * List all certificates
1294
- * @description Retrieve a list of all certificates in the system.
1356
+ * @description Retrieve a paginated list of all certificates in the system.
1295
1357
  * Each certificate includes course information (id, title, description) when available.
1296
1358
  * Course data is extracted from the related Quiz through QuizAttempt.
1297
1359
  */
1298
1360
  get: {
1299
1361
  parameters: {
1300
- query?: never;
1362
+ query?: {
1363
+ /** @description Filter certificates by user ID */
1364
+ userId?: string;
1365
+ /** @description Search term */
1366
+ search?: components["parameters"]["search"];
1367
+ /** @description Page number */
1368
+ page?: components["parameters"]["page"];
1369
+ /** @description Items per page */
1370
+ limit?: components["parameters"]["limit"];
1371
+ /** @description Whether to include course data in the response (default true). Pass false to skip course lookup. */
1372
+ includeCourse?: boolean;
1373
+ };
1301
1374
  header?: never;
1302
1375
  path?: never;
1303
1376
  cookie?: never;
@@ -1314,6 +1387,16 @@ export interface paths {
1314
1387
  /** @example success */
1315
1388
  status?: string;
1316
1389
  data?: components["schemas"]["Certificate"][];
1390
+ meta?: {
1391
+ /** @example 10 */
1392
+ total?: number;
1393
+ /** @example 1 */
1394
+ page?: number;
1395
+ /** @example 10 */
1396
+ limit?: number;
1397
+ /** @example 1 */
1398
+ totalPages?: number;
1399
+ };
1317
1400
  };
1318
1401
  };
1319
1402
  };
@@ -1349,8 +1432,6 @@ export interface paths {
1349
1432
  /** @example success */
1350
1433
  status?: string;
1351
1434
  data?: components["schemas"]["Certificate"];
1352
- /** @example Certificate created successfully */
1353
- message?: string;
1354
1435
  };
1355
1436
  };
1356
1437
  };
@@ -1428,18 +1509,11 @@ export interface paths {
1428
1509
  requestBody?: never;
1429
1510
  responses: {
1430
1511
  /** @description Certificate deleted successfully */
1431
- 200: {
1512
+ 204: {
1432
1513
  headers: {
1433
1514
  [name: string]: unknown;
1434
1515
  };
1435
- content: {
1436
- "application/json": {
1437
- /** @example success */
1438
- status?: string;
1439
- /** @example Certificate deleted successfully */
1440
- message?: string;
1441
- };
1442
- };
1516
+ content?: never;
1443
1517
  };
1444
1518
  400: components["responses"]["BadRequest"];
1445
1519
  401: components["responses"]["Unauthorized"];
@@ -1479,8 +1553,6 @@ export interface paths {
1479
1553
  /** @example success */
1480
1554
  status?: string;
1481
1555
  data?: components["schemas"]["Certificate"];
1482
- /** @example Certificate updated successfully */
1483
- message?: string;
1484
1556
  };
1485
1557
  };
1486
1558
  };
@@ -1492,6 +1564,123 @@ export interface paths {
1492
1564
  };
1493
1565
  trace?: never;
1494
1566
  };
1567
+ "/certificates/{id}/download": {
1568
+ parameters: {
1569
+ query?: never;
1570
+ header?: never;
1571
+ path?: never;
1572
+ cookie?: never;
1573
+ };
1574
+ /**
1575
+ * Download certificate PDF
1576
+ * @description Download the PDF of a specific certificate.
1577
+ * Acts as a proxy to download from S3, avoiding CORS issues.
1578
+ * Only the certificate owner can download their certificate.
1579
+ */
1580
+ get: {
1581
+ parameters: {
1582
+ query?: never;
1583
+ header?: never;
1584
+ path: {
1585
+ /** @description Resource ID */
1586
+ id: components["parameters"]["id"];
1587
+ };
1588
+ cookie?: never;
1589
+ };
1590
+ requestBody?: never;
1591
+ responses: {
1592
+ /** @description Certificate PDF file */
1593
+ 200: {
1594
+ headers: {
1595
+ [name: string]: unknown;
1596
+ };
1597
+ content: {
1598
+ "application/pdf": string;
1599
+ };
1600
+ };
1601
+ 401: components["responses"]["Unauthorized"];
1602
+ 403: components["responses"]["Forbidden"];
1603
+ 404: components["responses"]["NotFound"];
1604
+ 500: components["responses"]["ServerError"];
1605
+ };
1606
+ };
1607
+ put?: never;
1608
+ post?: never;
1609
+ delete?: never;
1610
+ options?: never;
1611
+ head?: never;
1612
+ patch?: never;
1613
+ trace?: never;
1614
+ };
1615
+ "/certificates/generate": {
1616
+ parameters: {
1617
+ query?: never;
1618
+ header?: never;
1619
+ path?: never;
1620
+ cookie?: never;
1621
+ };
1622
+ get?: never;
1623
+ put?: never;
1624
+ /**
1625
+ * Generate a certificate PDF server-side
1626
+ * @description Generates a certificate PDF on the server and creates the certificate record.
1627
+ * This eliminates CORS issues by downloading the template image on the server.
1628
+ *
1629
+ * If the user is currently on a journey "course" step whose `courseModuleId`
1630
+ * matches the quiz's course module, that step is auto-completed as part of
1631
+ * this call (best-effort; failures here are silent and do not affect the cert).
1632
+ */
1633
+ post: {
1634
+ parameters: {
1635
+ query?: never;
1636
+ header?: never;
1637
+ path?: never;
1638
+ cookie?: never;
1639
+ };
1640
+ requestBody: {
1641
+ content: {
1642
+ "application/json": components["schemas"]["GenerateCertificateDto"];
1643
+ };
1644
+ };
1645
+ responses: {
1646
+ /** @description Certificate generated and created successfully */
1647
+ 201: {
1648
+ headers: {
1649
+ [name: string]: unknown;
1650
+ };
1651
+ content: {
1652
+ "application/json": {
1653
+ /** @example success */
1654
+ status?: string;
1655
+ data?: {
1656
+ certificate?: components["schemas"]["Certificate"];
1657
+ /** @example https://s3.amazonaws.com/bucket/certificate.pdf */
1658
+ pdfUrl?: string;
1659
+ /**
1660
+ * @description True when this generation also concluded the user's current journey "course" step
1661
+ * @example true
1662
+ */
1663
+ stepCompleted?: boolean;
1664
+ /**
1665
+ * Format: uuid
1666
+ * @description ID of the challenge_step that was auto-completed, or null when no step was matched
1667
+ */
1668
+ challengeStepId?: string | null;
1669
+ };
1670
+ };
1671
+ };
1672
+ };
1673
+ 400: components["responses"]["BadRequest"];
1674
+ 401: components["responses"]["Unauthorized"];
1675
+ 500: components["responses"]["ServerError"];
1676
+ };
1677
+ };
1678
+ delete?: never;
1679
+ options?: never;
1680
+ head?: never;
1681
+ patch?: never;
1682
+ trace?: never;
1683
+ };
1495
1684
  "/challenge-groups": {
1496
1685
  parameters: {
1497
1686
  query?: never;
@@ -1830,6 +2019,12 @@ export interface paths {
1830
2019
  templatesOnly?: boolean;
1831
2020
  /** @description Search by title */
1832
2021
  search?: string;
2022
+ /**
2023
+ * @description Comma-separated list of extra relations to load. Currently supported:
2024
+ * `steps` — embeds each challenge's `steps` (with their catalog `step`).
2025
+ * Opt-in to avoid penalizing list views that don't need them.
2026
+ */
2027
+ include?: "steps";
1833
2028
  /** @description Page number */
1834
2029
  page?: components["parameters"]["page"];
1835
2030
  /** @description Items per page */
@@ -1884,6 +2079,11 @@ export interface paths {
1884
2079
  maxGroupMembers?: number;
1885
2080
  /** @default false */
1886
2081
  isInviteOnly?: boolean;
2082
+ /**
2083
+ * Format: uuid
2084
+ * @description Curso ao qual o desafio está associado (agrupa a jornada no dashboard)
2085
+ */
2086
+ courseId: string;
1887
2087
  /** Format: uuid */
1888
2088
  institutionId?: string | null;
1889
2089
  /** Format: uuid */
@@ -2026,6 +2226,8 @@ export interface paths {
2026
2226
  maxGroupMembers?: number;
2027
2227
  isInviteOnly?: boolean;
2028
2228
  /** Format: uuid */
2229
+ courseId?: string;
2230
+ /** Format: uuid */
2029
2231
  serieId?: string;
2030
2232
  index?: number;
2031
2233
  /** @enum {string} */
@@ -2132,9 +2334,10 @@ export interface paths {
2132
2334
  /**
2133
2335
  * Add a step to the challenge
2134
2336
  * @description Polymorphic validation:
2135
- * - When step.type=course, courseId is required
2136
2337
  * - When step.type=tutorial, tutorialVideoUrl is required
2137
- * - Other types must not have these specialized fields
2338
+ * - The course of a step is determined by the parent challenge's courseId.
2339
+ * Optionally, courseModuleId pinpoints a specific module within that course.
2340
+ * - tutorial fields are optional on any step type.
2138
2341
  */
2139
2342
  post: {
2140
2343
  parameters: {
@@ -2158,8 +2361,6 @@ export interface paths {
2158
2361
  description?: string;
2159
2362
  index: number;
2160
2363
  /** Format: uuid */
2161
- courseId?: string;
2162
- /** Format: uuid */
2163
2364
  courseModuleId?: string;
2164
2365
  tutorialTitle?: string;
2165
2366
  tutorialDescription?: string;
@@ -9287,6 +9488,8 @@ export interface paths {
9287
9488
  page?: number;
9288
9489
  /** @description Items per page */
9289
9490
  limit?: number;
9491
+ /** @description When true, returns questions in random order with shuffled answer alternatives. Each request reshuffles independently. */
9492
+ randomize?: boolean;
9290
9493
  };
9291
9494
  header?: never;
9292
9495
  path?: never;
@@ -10340,6 +10543,76 @@ export interface paths {
10340
10543
  patch?: never;
10341
10544
  trace?: never;
10342
10545
  };
10546
+ "/reports/encourage-dashboard/{id}": {
10547
+ parameters: {
10548
+ query?: never;
10549
+ header?: never;
10550
+ path?: never;
10551
+ cookie?: never;
10552
+ };
10553
+ /**
10554
+ * Payload completo da nova tela /new-dashboard
10555
+ * @description Retorna o dashboard agregado por instituição: overview, KPIs,
10556
+ * licenças (apenas tipo aluno), jornada (cursos deduplicados),
10557
+ * submissões, desempenho por turma, top 10 alunos (por certificados,
10558
+ * desempate por nota) e top 10 professores (por avaliações).
10559
+ */
10560
+ get: {
10561
+ parameters: {
10562
+ query?: never;
10563
+ header?: never;
10564
+ path: {
10565
+ /** @description ID da instituição */
10566
+ id: string;
10567
+ };
10568
+ cookie?: never;
10569
+ };
10570
+ requestBody?: never;
10571
+ responses: {
10572
+ /** @description Payload completo do encourage dashboard */
10573
+ 200: {
10574
+ headers: {
10575
+ [name: string]: unknown;
10576
+ };
10577
+ content: {
10578
+ "application/json": {
10579
+ /** @example success */
10580
+ status?: string;
10581
+ data?: components["schemas"]["EncourageDashboardResponse"];
10582
+ };
10583
+ };
10584
+ };
10585
+ /** @description institutionId inválido */
10586
+ 400: {
10587
+ headers: {
10588
+ [name: string]: unknown;
10589
+ };
10590
+ content?: never;
10591
+ };
10592
+ /** @description Não autenticado */
10593
+ 401: {
10594
+ headers: {
10595
+ [name: string]: unknown;
10596
+ };
10597
+ content?: never;
10598
+ };
10599
+ /** @description Erro interno */
10600
+ 500: {
10601
+ headers: {
10602
+ [name: string]: unknown;
10603
+ };
10604
+ content?: never;
10605
+ };
10606
+ };
10607
+ };
10608
+ put?: never;
10609
+ post?: never;
10610
+ delete?: never;
10611
+ options?: never;
10612
+ head?: never;
10613
+ patch?: never;
10614
+ trace?: never;
10615
+ };
10343
10616
  "/roles": {
10344
10617
  parameters: {
10345
10618
  query?: never;
@@ -11357,7 +11630,7 @@ export interface paths {
11357
11630
  /**
11358
11631
  * Create new submission attempt
11359
11632
  * @description Creates a submission with status=submitted. Validations:
11360
- * - Cannot submit to a global template (clone first)
11633
+ * - institutionId is sent by the client (user's institution_registration), not derived from the challenge
11361
11634
  * - For group challenges: groupId is required and user must be a member
11362
11635
  * - For individual challenges: groupId must be omitted
11363
11636
  * - Cannot create when there is already an active submission (submitted/ai_evaluated)
@@ -11377,6 +11650,11 @@ export interface paths {
11377
11650
  "application/json": {
11378
11651
  /** Format: uuid */
11379
11652
  challengeId: string;
11653
+ /**
11654
+ * Format: uuid
11655
+ * @description Institution the user is submitting under (from institution_registration)
11656
+ */
11657
+ institutionId: string;
11380
11658
  /**
11381
11659
  * Format: uuid
11382
11660
  * @description Required when challenge.isGroup=true
@@ -12003,6 +12281,86 @@ export interface paths {
12003
12281
  patch?: never;
12004
12282
  trace?: never;
12005
12283
  };
12284
+ "/user-challenge-progress/challenges/{id}/advance": {
12285
+ parameters: {
12286
+ query?: never;
12287
+ header?: never;
12288
+ path?: never;
12289
+ cookie?: never;
12290
+ };
12291
+ get?: never;
12292
+ put?: never;
12293
+ /**
12294
+ * Advance one tick in the user's journey on a challenge
12295
+ * @description Unified journey advancement, agnostic of step type. Each call performs ONE action:
12296
+ *
12297
+ * 1. Resolves the current step = first active step (by index) not yet completed by the user.
12298
+ * 2. If no progress row exists for that step → creates one (action='started').
12299
+ * 3. If progress row exists with completed_at IS NULL → sets completed_at (action='completed').
12300
+ * 4. If all steps are completed → no-op (action='finished').
12301
+ *
12302
+ * Web and mobile clients must use this endpoint regardless of the step type
12303
+ * (challenge, course, tutorial, publication, evaluation, certificate).
12304
+ */
12305
+ post: {
12306
+ parameters: {
12307
+ query?: never;
12308
+ header?: never;
12309
+ path: {
12310
+ /** @description Resource ID */
12311
+ id: components["parameters"]["id"];
12312
+ };
12313
+ cookie?: never;
12314
+ };
12315
+ requestBody?: never;
12316
+ responses: {
12317
+ /** @description Tick result */
12318
+ 200: {
12319
+ headers: {
12320
+ [name: string]: unknown;
12321
+ };
12322
+ content: {
12323
+ "application/json": {
12324
+ /** @example success */
12325
+ status?: string;
12326
+ data?: {
12327
+ /** @enum {string} */
12328
+ action?: "started" | "completed" | "finished";
12329
+ /** Format: uuid */
12330
+ challengeId?: string;
12331
+ currentStep?: {
12332
+ /** Format: uuid */
12333
+ id?: string;
12334
+ index?: number;
12335
+ name?: string;
12336
+ /** Format: date-time */
12337
+ startedAt?: string | null;
12338
+ /** Format: date-time */
12339
+ completedAt?: string | null;
12340
+ } | null;
12341
+ /** @description Next step in the journey. When action='completed', this step is also auto-started on the same call (startedAt populated). */
12342
+ nextStep?: {
12343
+ /** Format: uuid */
12344
+ id?: string;
12345
+ index?: number;
12346
+ name?: string;
12347
+ /** Format: date-time */
12348
+ startedAt?: string | null;
12349
+ } | null;
12350
+ };
12351
+ };
12352
+ };
12353
+ };
12354
+ 401: components["responses"]["Unauthorized"];
12355
+ 404: components["responses"]["NotFound"];
12356
+ };
12357
+ };
12358
+ delete?: never;
12359
+ options?: never;
12360
+ head?: never;
12361
+ patch?: never;
12362
+ trace?: never;
12363
+ };
12006
12364
  "/user-challenge-progress/steps/{stepId}/start": {
12007
12365
  parameters: {
12008
12366
  query?: never;
@@ -12013,9 +12371,12 @@ export interface paths {
12013
12371
  get?: never;
12014
12372
  put?: never;
12015
12373
  /**
12016
- * Start a challenge step (idempotent)
12017
- * @description Creates a user_challenge_progress row. If one already exists for this user/step,
12374
+ * [Internal/Admin] Force-start a specific challenge step (idempotent)
12375
+ * @description Creates a user_challenge_progress row for the given step. If one already exists,
12018
12376
  * returns the existing row (idempotent).
12377
+ *
12378
+ * Client apps (web/mobile) should use POST /user-challenge-progress/challenges/{id}/advance
12379
+ * instead. This endpoint is retained for internal/admin tooling that needs to force a state.
12019
12380
  */
12020
12381
  post: {
12021
12382
  parameters: {
@@ -12062,8 +12423,12 @@ export interface paths {
12062
12423
  get?: never;
12063
12424
  put?: never;
12064
12425
  /**
12065
- * Mark step as completed
12066
- * @description Sets completed_at on the user's progress row. Idempotent (no-op if already completed)
12426
+ * [Internal/Admin] Force-complete a specific challenge step
12427
+ * @description Sets completed_at on the user's progress row for the given step. Idempotent
12428
+ * (no-op if already completed).
12429
+ *
12430
+ * Client apps (web/mobile) should use POST /user-challenge-progress/challenges/{id}/advance
12431
+ * instead. This endpoint is retained for internal/admin tooling that needs to force a state.
12067
12432
  */
12068
12433
  post: {
12069
12434
  parameters: {
@@ -12373,6 +12738,103 @@ export interface paths {
12373
12738
  patch?: never;
12374
12739
  trace?: never;
12375
12740
  };
12741
+ "/users-course-log/me/courses/{courseId}/progress": {
12742
+ parameters: {
12743
+ query?: never;
12744
+ header?: never;
12745
+ path?: never;
12746
+ cookie?: never;
12747
+ };
12748
+ /**
12749
+ * Get authenticated user's progress in a course
12750
+ * @description Returns completed/total active lessons (across every active module of the course)
12751
+ * and a percentage based on `users_course_log` completion events.
12752
+ */
12753
+ get: {
12754
+ parameters: {
12755
+ query?: never;
12756
+ header?: never;
12757
+ path: {
12758
+ courseId: string;
12759
+ };
12760
+ cookie?: never;
12761
+ };
12762
+ requestBody?: never;
12763
+ responses: {
12764
+ /** @description Course progress snapshot */
12765
+ 200: {
12766
+ headers: {
12767
+ [name: string]: unknown;
12768
+ };
12769
+ content: {
12770
+ "application/json": {
12771
+ /** @example success */
12772
+ status?: string;
12773
+ data?: components["schemas"]["UsersCourseLogProgress"];
12774
+ };
12775
+ };
12776
+ };
12777
+ 401: components["responses"]["Unauthorized"];
12778
+ 404: components["responses"]["NotFound"];
12779
+ };
12780
+ };
12781
+ put?: never;
12782
+ post?: never;
12783
+ delete?: never;
12784
+ options?: never;
12785
+ head?: never;
12786
+ patch?: never;
12787
+ trace?: never;
12788
+ };
12789
+ "/users-course-log/me/courses/{courseId}/modules/{moduleId}/progress": {
12790
+ parameters: {
12791
+ query?: never;
12792
+ header?: never;
12793
+ path?: never;
12794
+ cookie?: never;
12795
+ };
12796
+ /**
12797
+ * Get authenticated user's progress in a module
12798
+ * @description Returns completed/total active lessons of the module and a percentage based on
12799
+ * `users_course_log` completion events. Used by the Journey "curso" step.
12800
+ */
12801
+ get: {
12802
+ parameters: {
12803
+ query?: never;
12804
+ header?: never;
12805
+ path: {
12806
+ courseId: string;
12807
+ moduleId: string;
12808
+ };
12809
+ cookie?: never;
12810
+ };
12811
+ requestBody?: never;
12812
+ responses: {
12813
+ /** @description Module progress snapshot */
12814
+ 200: {
12815
+ headers: {
12816
+ [name: string]: unknown;
12817
+ };
12818
+ content: {
12819
+ "application/json": {
12820
+ /** @example success */
12821
+ status?: string;
12822
+ data?: components["schemas"]["UsersCourseLogProgress"];
12823
+ };
12824
+ };
12825
+ };
12826
+ 401: components["responses"]["Unauthorized"];
12827
+ 404: components["responses"]["NotFound"];
12828
+ };
12829
+ };
12830
+ put?: never;
12831
+ post?: never;
12832
+ delete?: never;
12833
+ options?: never;
12834
+ head?: never;
12835
+ patch?: never;
12836
+ trace?: never;
12837
+ };
12376
12838
  "/users/me": {
12377
12839
  parameters: {
12378
12840
  query?: never;
@@ -12846,7 +13308,19 @@ export interface paths {
12846
13308
  head?: never;
12847
13309
  /**
12848
13310
  * Update user
12849
- * @description Update user information
13311
+ * @description Update user information.
13312
+ *
13313
+ * **Profile and seat code behavior:**
13314
+ * - Send `groupId` to change the user's profile/group.
13315
+ * - When `groupId` changes, the system will:
13316
+ * 1. Release the previous seat code used by the user (`isReserved = false`)
13317
+ * 2. Allocate a seat code for the new group in the same institution registration
13318
+ * 3. Create a new seat code automatically if none is available for that group
13319
+ *
13320
+ * **Important:**
13321
+ * - The target group must exist.
13322
+ * - The institution must have a seat configured for the target group.
13323
+ * - If any institution registration cannot be migrated to the new group, the operation fails.
12850
13324
  */
12851
13325
  patch: {
12852
13326
  parameters: {
@@ -14516,6 +14990,11 @@ export interface components {
14516
14990
  maxGroupMembers?: number;
14517
14991
  /** @example false */
14518
14992
  isInviteOnly?: boolean;
14993
+ /**
14994
+ * Format: uuid
14995
+ * @description Curso ao qual o desafio está associado (agrupa a jornada no dashboard)
14996
+ */
14997
+ courseId?: string;
14519
14998
  /**
14520
14999
  * Format: uuid
14521
15000
  * @description Null para template global
@@ -14551,6 +15030,8 @@ export interface components {
14551
15030
  createdAt?: string;
14552
15031
  /** Format: date-time */
14553
15032
  updatedAt?: string;
15033
+ /** @description Populado quando `include=steps` é informado no GET /challenges, ou via GET /challenges/{id} */
15034
+ steps?: components["schemas"]["ChallengeStep"][];
14554
15035
  };
14555
15036
  ChallengeMedia: {
14556
15037
  /** Format: uuid */
@@ -14579,10 +15060,8 @@ export interface components {
14579
15060
  index?: number;
14580
15061
  /**
14581
15062
  * Format: uuid
14582
- * @description Obrigatório quando step type=course
15063
+ * @description Opcional. Quando step type=course, aponta para o módulo específico do curso do challenge.
14583
15064
  */
14584
- courseId?: string | null;
14585
- /** Format: uuid */
14586
15065
  courseModuleId?: string | null;
14587
15066
  tutorialTitle?: string | null;
14588
15067
  tutorialDescription?: string | null;
@@ -14593,6 +15072,8 @@ export interface components {
14593
15072
  createdAt?: string;
14594
15073
  /** Format: date-time */
14595
15074
  updatedAt?: string;
15075
+ /** @description Catálogo do step (cor, ícone, tipo). Populado junto com o relation `steps.step`. */
15076
+ step?: components["schemas"]["Step"];
14596
15077
  };
14597
15078
  /** @description Item do checklist descritivo de entrega */
14598
15079
  ChallengeDeliveryStep: {
@@ -14664,6 +15145,29 @@ export interface components {
14664
15145
  /** Format: date-time */
14665
15146
  updatedAt?: string;
14666
15147
  };
15148
+ /** @description Aggregated progress of a user on a course or module, derived from users_course_log completion events */
15149
+ UsersCourseLogProgress: {
15150
+ /**
15151
+ * @description Number of active lessons completed by the user
15152
+ * @example 3
15153
+ */
15154
+ completedLessons?: number;
15155
+ /**
15156
+ * @description Total number of active lessons in scope
15157
+ * @example 5
15158
+ */
15159
+ totalLessons?: number;
15160
+ /**
15161
+ * @description Completion percentage rounded to nearest integer
15162
+ * @example 60
15163
+ */
15164
+ percent?: number;
15165
+ /**
15166
+ * @description True when totalLessons > 0 and completedLessons >= totalLessons
15167
+ * @example false
15168
+ */
15169
+ isCompleted?: boolean;
15170
+ };
14667
15171
  Submission: {
14668
15172
  /** Format: uuid */
14669
15173
  id?: string;
@@ -15579,6 +16083,121 @@ export interface components {
15579
16083
  totalStudents?: number;
15580
16084
  year?: number;
15581
16085
  };
16086
+ EncourageActivePeriod: {
16087
+ /** Format: uuid */
16088
+ id?: string;
16089
+ /** Format: date-time */
16090
+ start?: string;
16091
+ /** Format: date-time */
16092
+ end?: string;
16093
+ /** @example Bimestre */
16094
+ label?: string;
16095
+ /** @example 4 */
16096
+ periodsPerYear?: number;
16097
+ };
16098
+ EncourageOverview: {
16099
+ userFirstName?: string;
16100
+ institutionName?: string;
16101
+ activePeriod?: components["schemas"]["EncourageActivePeriod"];
16102
+ /** Format: float */
16103
+ globalProgressPct?: number;
16104
+ };
16105
+ EncourageKpis: {
16106
+ totalStudents?: number;
16107
+ /** Format: float */
16108
+ totalStudentsDeltaPct?: number;
16109
+ completedProjects?: number;
16110
+ /** Format: float */
16111
+ completedProjectsDeltaPct?: number;
16112
+ /** Format: float */
16113
+ engagementRatePct?: number;
16114
+ /** Format: float */
16115
+ engagementRateDeltaPct?: number;
16116
+ neverLoggedIn?: number;
16117
+ neverLoggedInDelta?: number;
16118
+ };
16119
+ /** @description Licenças do tipo aluno (seats.group_id → group.type = 'student') */
16120
+ EncourageLicenses: {
16121
+ used?: number;
16122
+ total?: number;
16123
+ /** Format: float */
16124
+ pct?: number;
16125
+ available?: number;
16126
+ };
16127
+ EncourageJourneyCourse: {
16128
+ /** Format: uuid */
16129
+ courseId?: string;
16130
+ title?: string;
16131
+ /** Format: date-time */
16132
+ dueDate?: string;
16133
+ /** Format: float */
16134
+ progressPct?: number;
16135
+ challengesCount?: number;
16136
+ color?: string;
16137
+ };
16138
+ EncourageJourney: {
16139
+ totalCourses?: number;
16140
+ /** Format: float */
16141
+ averageProgressPct?: number;
16142
+ /** @enum {string} */
16143
+ periodKind?: "semester" | "trimester" | "bimester";
16144
+ courses?: components["schemas"]["EncourageJourneyCourse"][];
16145
+ };
16146
+ EncourageSubmissions: {
16147
+ total?: number;
16148
+ evaluated?: number;
16149
+ awaitingTeacher?: number;
16150
+ awaitingAi?: number;
16151
+ };
16152
+ EncourageClassPerformance: {
16153
+ /** Format: uuid */
16154
+ classroomId?: string;
16155
+ /** @example 2º A — Médio */
16156
+ name?: string;
16157
+ /** @example Manhã */
16158
+ meta?: string;
16159
+ /** @description Total de alunos cadastrados na turma */
16160
+ studentsCount?: number;
16161
+ /** @description Alunos que submeteram pelo menos 1 challenge do período ativo */
16162
+ submittedCount?: number;
16163
+ /** Format: float */
16164
+ progressPct?: number;
16165
+ /** @enum {string} */
16166
+ level?: "high" | "medium" | "low";
16167
+ };
16168
+ EncourageTopStudent: {
16169
+ /** Format: uuid */
16170
+ userId?: string;
16171
+ rank?: number;
16172
+ name?: string;
16173
+ initials?: string;
16174
+ avatarColor?: string;
16175
+ certificates?: number;
16176
+ /** Format: float */
16177
+ averageScore?: number;
16178
+ };
16179
+ EncourageTopTeacher: {
16180
+ /** Format: uuid */
16181
+ userId?: string;
16182
+ rank?: number;
16183
+ name?: string;
16184
+ initials?: string;
16185
+ avatarColor?: string;
16186
+ evaluationsCount?: number;
16187
+ averageEvaluationSeconds?: number;
16188
+ /** Format: float */
16189
+ averageScore?: number;
16190
+ };
16191
+ EncourageDashboardResponse: {
16192
+ overview?: components["schemas"]["EncourageOverview"];
16193
+ kpis?: components["schemas"]["EncourageKpis"];
16194
+ licenses?: components["schemas"]["EncourageLicenses"];
16195
+ journey?: components["schemas"]["EncourageJourney"];
16196
+ submissions?: components["schemas"]["EncourageSubmissions"];
16197
+ classes?: components["schemas"]["EncourageClassPerformance"][];
16198
+ topStudents?: components["schemas"]["EncourageTopStudent"][];
16199
+ topTeachers?: components["schemas"]["EncourageTopTeacher"][];
16200
+ };
15582
16201
  UserCreationRequest: {
15583
16202
  /**
15584
16203
  * Format: uuid
@@ -15771,6 +16390,27 @@ export interface components {
15771
16390
  /** Format: uri */
15772
16391
  url?: string;
15773
16392
  };
16393
+ GenerateCertificateDto: {
16394
+ /** Format: uuid */
16395
+ userId: string;
16396
+ /** Format: uuid */
16397
+ quizAttemptId?: string;
16398
+ /** Format: uuid */
16399
+ certificateTemplateId: string;
16400
+ /** @example João Silva */
16401
+ studentName: string;
16402
+ /** @example Introdução ao JavaScript */
16403
+ quizTitle: string;
16404
+ /** @example 85 */
16405
+ score?: number;
16406
+ /** @example CERT-2024-000001 */
16407
+ certificateNumber?: string;
16408
+ /**
16409
+ * Format: date-time
16410
+ * @example 2024-01-01T00:00:00.000Z
16411
+ */
16412
+ issuedAt?: string;
16413
+ };
15774
16414
  CreateGuardianDto: {
15775
16415
  /**
15776
16416
  * Format: email