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.
package/dist/index.d.ts CHANGED
@@ -1372,6 +1372,68 @@ interface paths {
1372
1372
  patch?: never;
1373
1373
  trace?: never;
1374
1374
  };
1375
+ "/certificates/{userId}/download-all": {
1376
+ parameters: {
1377
+ query?: never;
1378
+ header?: never;
1379
+ path?: never;
1380
+ cookie?: never;
1381
+ };
1382
+ /**
1383
+ * Download all certificates of a user as a single PDF
1384
+ * @description Downloads all certificates of the given user merged into a single PDF file.
1385
+ * Each certificate occupies one page in the resulting file.
1386
+ * PDFs are downloaded from S3 in parallel and merged using pdf-lib.
1387
+ */
1388
+ get: {
1389
+ parameters: {
1390
+ query?: never;
1391
+ header?: never;
1392
+ path: {
1393
+ /** @description ID of the user whose certificates will be downloaded */
1394
+ userId: string;
1395
+ };
1396
+ cookie?: never;
1397
+ };
1398
+ requestBody?: never;
1399
+ responses: {
1400
+ /** @description Merged PDF file containing all user certificates */
1401
+ 200: {
1402
+ headers: {
1403
+ /** @description attachment; filename="Meus-Certificados.pdf" */
1404
+ "Content-Disposition"?: string;
1405
+ [name: string]: unknown;
1406
+ };
1407
+ content: {
1408
+ "application/pdf": string;
1409
+ };
1410
+ };
1411
+ 401: components["responses"]["Unauthorized"];
1412
+ /** @description No certificates found for the user */
1413
+ 404: {
1414
+ headers: {
1415
+ [name: string]: unknown;
1416
+ };
1417
+ content: {
1418
+ "application/json": {
1419
+ /** @example error */
1420
+ status?: string;
1421
+ /** @example No certificates found for this user */
1422
+ message?: string;
1423
+ };
1424
+ };
1425
+ };
1426
+ 500: components["responses"]["ServerError"];
1427
+ };
1428
+ };
1429
+ put?: never;
1430
+ post?: never;
1431
+ delete?: never;
1432
+ options?: never;
1433
+ head?: never;
1434
+ patch?: never;
1435
+ trace?: never;
1436
+ };
1375
1437
  "/certificates": {
1376
1438
  parameters: {
1377
1439
  query?: never;
@@ -1381,13 +1443,24 @@ interface paths {
1381
1443
  };
1382
1444
  /**
1383
1445
  * List all certificates
1384
- * @description Retrieve a list of all certificates in the system.
1446
+ * @description Retrieve a paginated list of all certificates in the system.
1385
1447
  * Each certificate includes course information (id, title, description) when available.
1386
1448
  * Course data is extracted from the related Quiz through QuizAttempt.
1387
1449
  */
1388
1450
  get: {
1389
1451
  parameters: {
1390
- query?: never;
1452
+ query?: {
1453
+ /** @description Filter certificates by user ID */
1454
+ userId?: string;
1455
+ /** @description Search term */
1456
+ search?: components["parameters"]["search"];
1457
+ /** @description Page number */
1458
+ page?: components["parameters"]["page"];
1459
+ /** @description Items per page */
1460
+ limit?: components["parameters"]["limit"];
1461
+ /** @description Whether to include course data in the response (default true). Pass false to skip course lookup. */
1462
+ includeCourse?: boolean;
1463
+ };
1391
1464
  header?: never;
1392
1465
  path?: never;
1393
1466
  cookie?: never;
@@ -1404,6 +1477,16 @@ interface paths {
1404
1477
  /** @example success */
1405
1478
  status?: string;
1406
1479
  data?: components["schemas"]["Certificate"][];
1480
+ meta?: {
1481
+ /** @example 10 */
1482
+ total?: number;
1483
+ /** @example 1 */
1484
+ page?: number;
1485
+ /** @example 10 */
1486
+ limit?: number;
1487
+ /** @example 1 */
1488
+ totalPages?: number;
1489
+ };
1407
1490
  };
1408
1491
  };
1409
1492
  };
@@ -1439,8 +1522,6 @@ interface paths {
1439
1522
  /** @example success */
1440
1523
  status?: string;
1441
1524
  data?: components["schemas"]["Certificate"];
1442
- /** @example Certificate created successfully */
1443
- message?: string;
1444
1525
  };
1445
1526
  };
1446
1527
  };
@@ -1518,18 +1599,11 @@ interface paths {
1518
1599
  requestBody?: never;
1519
1600
  responses: {
1520
1601
  /** @description Certificate deleted successfully */
1521
- 200: {
1602
+ 204: {
1522
1603
  headers: {
1523
1604
  [name: string]: unknown;
1524
1605
  };
1525
- content: {
1526
- "application/json": {
1527
- /** @example success */
1528
- status?: string;
1529
- /** @example Certificate deleted successfully */
1530
- message?: string;
1531
- };
1532
- };
1606
+ content?: never;
1533
1607
  };
1534
1608
  400: components["responses"]["BadRequest"];
1535
1609
  401: components["responses"]["Unauthorized"];
@@ -1569,8 +1643,6 @@ interface paths {
1569
1643
  /** @example success */
1570
1644
  status?: string;
1571
1645
  data?: components["schemas"]["Certificate"];
1572
- /** @example Certificate updated successfully */
1573
- message?: string;
1574
1646
  };
1575
1647
  };
1576
1648
  };
@@ -1582,6 +1654,123 @@ interface paths {
1582
1654
  };
1583
1655
  trace?: never;
1584
1656
  };
1657
+ "/certificates/{id}/download": {
1658
+ parameters: {
1659
+ query?: never;
1660
+ header?: never;
1661
+ path?: never;
1662
+ cookie?: never;
1663
+ };
1664
+ /**
1665
+ * Download certificate PDF
1666
+ * @description Download the PDF of a specific certificate.
1667
+ * Acts as a proxy to download from S3, avoiding CORS issues.
1668
+ * Only the certificate owner can download their certificate.
1669
+ */
1670
+ get: {
1671
+ parameters: {
1672
+ query?: never;
1673
+ header?: never;
1674
+ path: {
1675
+ /** @description Resource ID */
1676
+ id: components["parameters"]["id"];
1677
+ };
1678
+ cookie?: never;
1679
+ };
1680
+ requestBody?: never;
1681
+ responses: {
1682
+ /** @description Certificate PDF file */
1683
+ 200: {
1684
+ headers: {
1685
+ [name: string]: unknown;
1686
+ };
1687
+ content: {
1688
+ "application/pdf": string;
1689
+ };
1690
+ };
1691
+ 401: components["responses"]["Unauthorized"];
1692
+ 403: components["responses"]["Forbidden"];
1693
+ 404: components["responses"]["NotFound"];
1694
+ 500: components["responses"]["ServerError"];
1695
+ };
1696
+ };
1697
+ put?: never;
1698
+ post?: never;
1699
+ delete?: never;
1700
+ options?: never;
1701
+ head?: never;
1702
+ patch?: never;
1703
+ trace?: never;
1704
+ };
1705
+ "/certificates/generate": {
1706
+ parameters: {
1707
+ query?: never;
1708
+ header?: never;
1709
+ path?: never;
1710
+ cookie?: never;
1711
+ };
1712
+ get?: never;
1713
+ put?: never;
1714
+ /**
1715
+ * Generate a certificate PDF server-side
1716
+ * @description Generates a certificate PDF on the server and creates the certificate record.
1717
+ * This eliminates CORS issues by downloading the template image on the server.
1718
+ *
1719
+ * If the user is currently on a journey "course" step whose `courseModuleId`
1720
+ * matches the quiz's course module, that step is auto-completed as part of
1721
+ * this call (best-effort; failures here are silent and do not affect the cert).
1722
+ */
1723
+ post: {
1724
+ parameters: {
1725
+ query?: never;
1726
+ header?: never;
1727
+ path?: never;
1728
+ cookie?: never;
1729
+ };
1730
+ requestBody: {
1731
+ content: {
1732
+ "application/json": components["schemas"]["GenerateCertificateDto"];
1733
+ };
1734
+ };
1735
+ responses: {
1736
+ /** @description Certificate generated and created successfully */
1737
+ 201: {
1738
+ headers: {
1739
+ [name: string]: unknown;
1740
+ };
1741
+ content: {
1742
+ "application/json": {
1743
+ /** @example success */
1744
+ status?: string;
1745
+ data?: {
1746
+ certificate?: components["schemas"]["Certificate"];
1747
+ /** @example https://s3.amazonaws.com/bucket/certificate.pdf */
1748
+ pdfUrl?: string;
1749
+ /**
1750
+ * @description True when this generation also concluded the user's current journey "course" step
1751
+ * @example true
1752
+ */
1753
+ stepCompleted?: boolean;
1754
+ /**
1755
+ * Format: uuid
1756
+ * @description ID of the challenge_step that was auto-completed, or null when no step was matched
1757
+ */
1758
+ challengeStepId?: string | null;
1759
+ };
1760
+ };
1761
+ };
1762
+ };
1763
+ 400: components["responses"]["BadRequest"];
1764
+ 401: components["responses"]["Unauthorized"];
1765
+ 500: components["responses"]["ServerError"];
1766
+ };
1767
+ };
1768
+ delete?: never;
1769
+ options?: never;
1770
+ head?: never;
1771
+ patch?: never;
1772
+ trace?: never;
1773
+ };
1585
1774
  "/challenge-groups": {
1586
1775
  parameters: {
1587
1776
  query?: never;
@@ -1920,6 +2109,12 @@ interface paths {
1920
2109
  templatesOnly?: boolean;
1921
2110
  /** @description Search by title */
1922
2111
  search?: string;
2112
+ /**
2113
+ * @description Comma-separated list of extra relations to load. Currently supported:
2114
+ * `steps` — embeds each challenge's `steps` (with their catalog `step`).
2115
+ * Opt-in to avoid penalizing list views that don't need them.
2116
+ */
2117
+ include?: "steps";
1923
2118
  /** @description Page number */
1924
2119
  page?: components["parameters"]["page"];
1925
2120
  /** @description Items per page */
@@ -1974,6 +2169,11 @@ interface paths {
1974
2169
  maxGroupMembers?: number;
1975
2170
  /** @default false */
1976
2171
  isInviteOnly?: boolean;
2172
+ /**
2173
+ * Format: uuid
2174
+ * @description Curso ao qual o desafio está associado (agrupa a jornada no dashboard)
2175
+ */
2176
+ courseId: string;
1977
2177
  /** Format: uuid */
1978
2178
  institutionId?: string | null;
1979
2179
  /** Format: uuid */
@@ -2116,6 +2316,8 @@ interface paths {
2116
2316
  maxGroupMembers?: number;
2117
2317
  isInviteOnly?: boolean;
2118
2318
  /** Format: uuid */
2319
+ courseId?: string;
2320
+ /** Format: uuid */
2119
2321
  serieId?: string;
2120
2322
  index?: number;
2121
2323
  /** @enum {string} */
@@ -2222,9 +2424,10 @@ interface paths {
2222
2424
  /**
2223
2425
  * Add a step to the challenge
2224
2426
  * @description Polymorphic validation:
2225
- * - When step.type=course, courseId is required
2226
2427
  * - When step.type=tutorial, tutorialVideoUrl is required
2227
- * - Other types must not have these specialized fields
2428
+ * - The course of a step is determined by the parent challenge's courseId.
2429
+ * Optionally, courseModuleId pinpoints a specific module within that course.
2430
+ * - tutorial fields are optional on any step type.
2228
2431
  */
2229
2432
  post: {
2230
2433
  parameters: {
@@ -2248,8 +2451,6 @@ interface paths {
2248
2451
  description?: string;
2249
2452
  index: number;
2250
2453
  /** Format: uuid */
2251
- courseId?: string;
2252
- /** Format: uuid */
2253
2454
  courseModuleId?: string;
2254
2455
  tutorialTitle?: string;
2255
2456
  tutorialDescription?: string;
@@ -9377,6 +9578,8 @@ interface paths {
9377
9578
  page?: number;
9378
9579
  /** @description Items per page */
9379
9580
  limit?: number;
9581
+ /** @description When true, returns questions in random order with shuffled answer alternatives. Each request reshuffles independently. */
9582
+ randomize?: boolean;
9380
9583
  };
9381
9584
  header?: never;
9382
9585
  path?: never;
@@ -10430,6 +10633,76 @@ interface paths {
10430
10633
  patch?: never;
10431
10634
  trace?: never;
10432
10635
  };
10636
+ "/reports/encourage-dashboard/{id}": {
10637
+ parameters: {
10638
+ query?: never;
10639
+ header?: never;
10640
+ path?: never;
10641
+ cookie?: never;
10642
+ };
10643
+ /**
10644
+ * Payload completo da nova tela /new-dashboard
10645
+ * @description Retorna o dashboard agregado por instituição: overview, KPIs,
10646
+ * licenças (apenas tipo aluno), jornada (cursos deduplicados),
10647
+ * submissões, desempenho por turma, top 10 alunos (por certificados,
10648
+ * desempate por nota) e top 10 professores (por avaliações).
10649
+ */
10650
+ get: {
10651
+ parameters: {
10652
+ query?: never;
10653
+ header?: never;
10654
+ path: {
10655
+ /** @description ID da instituição */
10656
+ id: string;
10657
+ };
10658
+ cookie?: never;
10659
+ };
10660
+ requestBody?: never;
10661
+ responses: {
10662
+ /** @description Payload completo do encourage dashboard */
10663
+ 200: {
10664
+ headers: {
10665
+ [name: string]: unknown;
10666
+ };
10667
+ content: {
10668
+ "application/json": {
10669
+ /** @example success */
10670
+ status?: string;
10671
+ data?: components["schemas"]["EncourageDashboardResponse"];
10672
+ };
10673
+ };
10674
+ };
10675
+ /** @description institutionId inválido */
10676
+ 400: {
10677
+ headers: {
10678
+ [name: string]: unknown;
10679
+ };
10680
+ content?: never;
10681
+ };
10682
+ /** @description Não autenticado */
10683
+ 401: {
10684
+ headers: {
10685
+ [name: string]: unknown;
10686
+ };
10687
+ content?: never;
10688
+ };
10689
+ /** @description Erro interno */
10690
+ 500: {
10691
+ headers: {
10692
+ [name: string]: unknown;
10693
+ };
10694
+ content?: never;
10695
+ };
10696
+ };
10697
+ };
10698
+ put?: never;
10699
+ post?: never;
10700
+ delete?: never;
10701
+ options?: never;
10702
+ head?: never;
10703
+ patch?: never;
10704
+ trace?: never;
10705
+ };
10433
10706
  "/roles": {
10434
10707
  parameters: {
10435
10708
  query?: never;
@@ -11447,7 +11720,7 @@ interface paths {
11447
11720
  /**
11448
11721
  * Create new submission attempt
11449
11722
  * @description Creates a submission with status=submitted. Validations:
11450
- * - Cannot submit to a global template (clone first)
11723
+ * - institutionId is sent by the client (user's institution_registration), not derived from the challenge
11451
11724
  * - For group challenges: groupId is required and user must be a member
11452
11725
  * - For individual challenges: groupId must be omitted
11453
11726
  * - Cannot create when there is already an active submission (submitted/ai_evaluated)
@@ -11467,6 +11740,11 @@ interface paths {
11467
11740
  "application/json": {
11468
11741
  /** Format: uuid */
11469
11742
  challengeId: string;
11743
+ /**
11744
+ * Format: uuid
11745
+ * @description Institution the user is submitting under (from institution_registration)
11746
+ */
11747
+ institutionId: string;
11470
11748
  /**
11471
11749
  * Format: uuid
11472
11750
  * @description Required when challenge.isGroup=true
@@ -12093,7 +12371,7 @@ interface paths {
12093
12371
  patch?: never;
12094
12372
  trace?: never;
12095
12373
  };
12096
- "/user-challenge-progress/steps/{stepId}/start": {
12374
+ "/user-challenge-progress/challenges/{id}/advance": {
12097
12375
  parameters: {
12098
12376
  query?: never;
12099
12377
  header?: never;
@@ -12103,24 +12381,107 @@ interface paths {
12103
12381
  get?: never;
12104
12382
  put?: never;
12105
12383
  /**
12106
- * Start a challenge step (idempotent)
12107
- * @description Creates a user_challenge_progress row. If one already exists for this user/step,
12108
- * returns the existing row (idempotent).
12384
+ * Advance one tick in the user's journey on a challenge
12385
+ * @description Unified journey advancement, agnostic of step type. Each call performs ONE action:
12386
+ *
12387
+ * 1. Resolves the current step = first active step (by index) not yet completed by the user.
12388
+ * 2. If no progress row exists for that step → creates one (action='started').
12389
+ * 3. If progress row exists with completed_at IS NULL → sets completed_at (action='completed').
12390
+ * 4. If all steps are completed → no-op (action='finished').
12391
+ *
12392
+ * Web and mobile clients must use this endpoint regardless of the step type
12393
+ * (challenge, course, tutorial, publication, evaluation, certificate).
12109
12394
  */
12110
12395
  post: {
12111
12396
  parameters: {
12112
12397
  query?: never;
12113
12398
  header?: never;
12114
12399
  path: {
12115
- /** @description ID of the challenge_step to start */
12116
- stepId: string;
12400
+ /** @description Resource ID */
12401
+ id: components["parameters"]["id"];
12117
12402
  };
12118
12403
  cookie?: never;
12119
12404
  };
12120
12405
  requestBody?: never;
12121
12406
  responses: {
12122
- /** @description Progress started */
12123
- 201: {
12407
+ /** @description Tick result */
12408
+ 200: {
12409
+ headers: {
12410
+ [name: string]: unknown;
12411
+ };
12412
+ content: {
12413
+ "application/json": {
12414
+ /** @example success */
12415
+ status?: string;
12416
+ data?: {
12417
+ /** @enum {string} */
12418
+ action?: "started" | "completed" | "finished";
12419
+ /** Format: uuid */
12420
+ challengeId?: string;
12421
+ currentStep?: {
12422
+ /** Format: uuid */
12423
+ id?: string;
12424
+ index?: number;
12425
+ name?: string;
12426
+ /** Format: date-time */
12427
+ startedAt?: string | null;
12428
+ /** Format: date-time */
12429
+ completedAt?: string | null;
12430
+ } | null;
12431
+ /** @description Next step in the journey. When action='completed', this step is also auto-started on the same call (startedAt populated). */
12432
+ nextStep?: {
12433
+ /** Format: uuid */
12434
+ id?: string;
12435
+ index?: number;
12436
+ name?: string;
12437
+ /** Format: date-time */
12438
+ startedAt?: string | null;
12439
+ } | null;
12440
+ };
12441
+ };
12442
+ };
12443
+ };
12444
+ 401: components["responses"]["Unauthorized"];
12445
+ 404: components["responses"]["NotFound"];
12446
+ };
12447
+ };
12448
+ delete?: never;
12449
+ options?: never;
12450
+ head?: never;
12451
+ patch?: never;
12452
+ trace?: never;
12453
+ };
12454
+ "/user-challenge-progress/steps/{stepId}/start": {
12455
+ parameters: {
12456
+ query?: never;
12457
+ header?: never;
12458
+ path?: never;
12459
+ cookie?: never;
12460
+ };
12461
+ get?: never;
12462
+ put?: never;
12463
+ /**
12464
+ * [Internal/Admin] Force-start a specific challenge step (idempotent)
12465
+ * @description Creates a user_challenge_progress row for the given step. If one already exists,
12466
+ * returns the existing row (idempotent).
12467
+ *
12468
+ * Client apps (web/mobile) should use POST /user-challenge-progress/challenges/{id}/advance
12469
+ * instead. This endpoint is retained for internal/admin tooling that needs to force a state.
12470
+ */
12471
+ post: {
12472
+ parameters: {
12473
+ query?: never;
12474
+ header?: never;
12475
+ path: {
12476
+ /** @description ID of the challenge_step to start */
12477
+ stepId: string;
12478
+ };
12479
+ cookie?: never;
12480
+ };
12481
+ requestBody?: never;
12482
+ responses: {
12483
+ /** @description Progress started */
12484
+ 201: {
12124
12485
  headers: {
12125
12486
  [name: string]: unknown;
12126
12487
  };
@@ -12152,8 +12513,12 @@ interface paths {
12152
12513
  get?: never;
12153
12514
  put?: never;
12154
12515
  /**
12155
- * Mark step as completed
12156
- * @description Sets completed_at on the user's progress row. Idempotent (no-op if already completed)
12516
+ * [Internal/Admin] Force-complete a specific challenge step
12517
+ * @description Sets completed_at on the user's progress row for the given step. Idempotent
12518
+ * (no-op if already completed).
12519
+ *
12520
+ * Client apps (web/mobile) should use POST /user-challenge-progress/challenges/{id}/advance
12521
+ * instead. This endpoint is retained for internal/admin tooling that needs to force a state.
12157
12522
  */
12158
12523
  post: {
12159
12524
  parameters: {
@@ -12463,6 +12828,103 @@ interface paths {
12463
12828
  patch?: never;
12464
12829
  trace?: never;
12465
12830
  };
12831
+ "/users-course-log/me/courses/{courseId}/progress": {
12832
+ parameters: {
12833
+ query?: never;
12834
+ header?: never;
12835
+ path?: never;
12836
+ cookie?: never;
12837
+ };
12838
+ /**
12839
+ * Get authenticated user's progress in a course
12840
+ * @description Returns completed/total active lessons (across every active module of the course)
12841
+ * and a percentage based on `users_course_log` completion events.
12842
+ */
12843
+ get: {
12844
+ parameters: {
12845
+ query?: never;
12846
+ header?: never;
12847
+ path: {
12848
+ courseId: string;
12849
+ };
12850
+ cookie?: never;
12851
+ };
12852
+ requestBody?: never;
12853
+ responses: {
12854
+ /** @description Course progress snapshot */
12855
+ 200: {
12856
+ headers: {
12857
+ [name: string]: unknown;
12858
+ };
12859
+ content: {
12860
+ "application/json": {
12861
+ /** @example success */
12862
+ status?: string;
12863
+ data?: components["schemas"]["UsersCourseLogProgress"];
12864
+ };
12865
+ };
12866
+ };
12867
+ 401: components["responses"]["Unauthorized"];
12868
+ 404: components["responses"]["NotFound"];
12869
+ };
12870
+ };
12871
+ put?: never;
12872
+ post?: never;
12873
+ delete?: never;
12874
+ options?: never;
12875
+ head?: never;
12876
+ patch?: never;
12877
+ trace?: never;
12878
+ };
12879
+ "/users-course-log/me/courses/{courseId}/modules/{moduleId}/progress": {
12880
+ parameters: {
12881
+ query?: never;
12882
+ header?: never;
12883
+ path?: never;
12884
+ cookie?: never;
12885
+ };
12886
+ /**
12887
+ * Get authenticated user's progress in a module
12888
+ * @description Returns completed/total active lessons of the module and a percentage based on
12889
+ * `users_course_log` completion events. Used by the Journey "curso" step.
12890
+ */
12891
+ get: {
12892
+ parameters: {
12893
+ query?: never;
12894
+ header?: never;
12895
+ path: {
12896
+ courseId: string;
12897
+ moduleId: string;
12898
+ };
12899
+ cookie?: never;
12900
+ };
12901
+ requestBody?: never;
12902
+ responses: {
12903
+ /** @description Module progress snapshot */
12904
+ 200: {
12905
+ headers: {
12906
+ [name: string]: unknown;
12907
+ };
12908
+ content: {
12909
+ "application/json": {
12910
+ /** @example success */
12911
+ status?: string;
12912
+ data?: components["schemas"]["UsersCourseLogProgress"];
12913
+ };
12914
+ };
12915
+ };
12916
+ 401: components["responses"]["Unauthorized"];
12917
+ 404: components["responses"]["NotFound"];
12918
+ };
12919
+ };
12920
+ put?: never;
12921
+ post?: never;
12922
+ delete?: never;
12923
+ options?: never;
12924
+ head?: never;
12925
+ patch?: never;
12926
+ trace?: never;
12927
+ };
12466
12928
  "/users/me": {
12467
12929
  parameters: {
12468
12930
  query?: never;
@@ -12936,7 +13398,19 @@ interface paths {
12936
13398
  head?: never;
12937
13399
  /**
12938
13400
  * Update user
12939
- * @description Update user information
13401
+ * @description Update user information.
13402
+ *
13403
+ * **Profile and seat code behavior:**
13404
+ * - Send `groupId` to change the user's profile/group.
13405
+ * - When `groupId` changes, the system will:
13406
+ * 1. Release the previous seat code used by the user (`isReserved = false`)
13407
+ * 2. Allocate a seat code for the new group in the same institution registration
13408
+ * 3. Create a new seat code automatically if none is available for that group
13409
+ *
13410
+ * **Important:**
13411
+ * - The target group must exist.
13412
+ * - The institution must have a seat configured for the target group.
13413
+ * - If any institution registration cannot be migrated to the new group, the operation fails.
12940
13414
  */
12941
13415
  patch: {
12942
13416
  parameters: {
@@ -14606,6 +15080,11 @@ interface components {
14606
15080
  maxGroupMembers?: number;
14607
15081
  /** @example false */
14608
15082
  isInviteOnly?: boolean;
15083
+ /**
15084
+ * Format: uuid
15085
+ * @description Curso ao qual o desafio está associado (agrupa a jornada no dashboard)
15086
+ */
15087
+ courseId?: string;
14609
15088
  /**
14610
15089
  * Format: uuid
14611
15090
  * @description Null para template global
@@ -14641,6 +15120,8 @@ interface components {
14641
15120
  createdAt?: string;
14642
15121
  /** Format: date-time */
14643
15122
  updatedAt?: string;
15123
+ /** @description Populado quando `include=steps` é informado no GET /challenges, ou via GET /challenges/{id} */
15124
+ steps?: components["schemas"]["ChallengeStep"][];
14644
15125
  };
14645
15126
  ChallengeMedia: {
14646
15127
  /** Format: uuid */
@@ -14669,10 +15150,8 @@ interface components {
14669
15150
  index?: number;
14670
15151
  /**
14671
15152
  * Format: uuid
14672
- * @description Obrigatório quando step type=course
15153
+ * @description Opcional. Quando step type=course, aponta para o módulo específico do curso do challenge.
14673
15154
  */
14674
- courseId?: string | null;
14675
- /** Format: uuid */
14676
15155
  courseModuleId?: string | null;
14677
15156
  tutorialTitle?: string | null;
14678
15157
  tutorialDescription?: string | null;
@@ -14683,6 +15162,8 @@ interface components {
14683
15162
  createdAt?: string;
14684
15163
  /** Format: date-time */
14685
15164
  updatedAt?: string;
15165
+ /** @description Catálogo do step (cor, ícone, tipo). Populado junto com o relation `steps.step`. */
15166
+ step?: components["schemas"]["Step"];
14686
15167
  };
14687
15168
  /** @description Item do checklist descritivo de entrega */
14688
15169
  ChallengeDeliveryStep: {
@@ -14754,6 +15235,29 @@ interface components {
14754
15235
  /** Format: date-time */
14755
15236
  updatedAt?: string;
14756
15237
  };
15238
+ /** @description Aggregated progress of a user on a course or module, derived from users_course_log completion events */
15239
+ UsersCourseLogProgress: {
15240
+ /**
15241
+ * @description Number of active lessons completed by the user
15242
+ * @example 3
15243
+ */
15244
+ completedLessons?: number;
15245
+ /**
15246
+ * @description Total number of active lessons in scope
15247
+ * @example 5
15248
+ */
15249
+ totalLessons?: number;
15250
+ /**
15251
+ * @description Completion percentage rounded to nearest integer
15252
+ * @example 60
15253
+ */
15254
+ percent?: number;
15255
+ /**
15256
+ * @description True when totalLessons > 0 and completedLessons >= totalLessons
15257
+ * @example false
15258
+ */
15259
+ isCompleted?: boolean;
15260
+ };
14757
15261
  Submission: {
14758
15262
  /** Format: uuid */
14759
15263
  id?: string;
@@ -15669,6 +16173,121 @@ interface components {
15669
16173
  totalStudents?: number;
15670
16174
  year?: number;
15671
16175
  };
16176
+ EncourageActivePeriod: {
16177
+ /** Format: uuid */
16178
+ id?: string;
16179
+ /** Format: date-time */
16180
+ start?: string;
16181
+ /** Format: date-time */
16182
+ end?: string;
16183
+ /** @example Bimestre */
16184
+ label?: string;
16185
+ /** @example 4 */
16186
+ periodsPerYear?: number;
16187
+ };
16188
+ EncourageOverview: {
16189
+ userFirstName?: string;
16190
+ institutionName?: string;
16191
+ activePeriod?: components["schemas"]["EncourageActivePeriod"];
16192
+ /** Format: float */
16193
+ globalProgressPct?: number;
16194
+ };
16195
+ EncourageKpis: {
16196
+ totalStudents?: number;
16197
+ /** Format: float */
16198
+ totalStudentsDeltaPct?: number;
16199
+ completedProjects?: number;
16200
+ /** Format: float */
16201
+ completedProjectsDeltaPct?: number;
16202
+ /** Format: float */
16203
+ engagementRatePct?: number;
16204
+ /** Format: float */
16205
+ engagementRateDeltaPct?: number;
16206
+ neverLoggedIn?: number;
16207
+ neverLoggedInDelta?: number;
16208
+ };
16209
+ /** @description Licenças do tipo aluno (seats.group_id → group.type = 'student') */
16210
+ EncourageLicenses: {
16211
+ used?: number;
16212
+ total?: number;
16213
+ /** Format: float */
16214
+ pct?: number;
16215
+ available?: number;
16216
+ };
16217
+ EncourageJourneyCourse: {
16218
+ /** Format: uuid */
16219
+ courseId?: string;
16220
+ title?: string;
16221
+ /** Format: date-time */
16222
+ dueDate?: string;
16223
+ /** Format: float */
16224
+ progressPct?: number;
16225
+ challengesCount?: number;
16226
+ color?: string;
16227
+ };
16228
+ EncourageJourney: {
16229
+ totalCourses?: number;
16230
+ /** Format: float */
16231
+ averageProgressPct?: number;
16232
+ /** @enum {string} */
16233
+ periodKind?: "semester" | "trimester" | "bimester";
16234
+ courses?: components["schemas"]["EncourageJourneyCourse"][];
16235
+ };
16236
+ EncourageSubmissions: {
16237
+ total?: number;
16238
+ evaluated?: number;
16239
+ awaitingTeacher?: number;
16240
+ awaitingAi?: number;
16241
+ };
16242
+ EncourageClassPerformance: {
16243
+ /** Format: uuid */
16244
+ classroomId?: string;
16245
+ /** @example 2º A — Médio */
16246
+ name?: string;
16247
+ /** @example Manhã */
16248
+ meta?: string;
16249
+ /** @description Total de alunos cadastrados na turma */
16250
+ studentsCount?: number;
16251
+ /** @description Alunos que submeteram pelo menos 1 challenge do período ativo */
16252
+ submittedCount?: number;
16253
+ /** Format: float */
16254
+ progressPct?: number;
16255
+ /** @enum {string} */
16256
+ level?: "high" | "medium" | "low";
16257
+ };
16258
+ EncourageTopStudent: {
16259
+ /** Format: uuid */
16260
+ userId?: string;
16261
+ rank?: number;
16262
+ name?: string;
16263
+ initials?: string;
16264
+ avatarColor?: string;
16265
+ certificates?: number;
16266
+ /** Format: float */
16267
+ averageScore?: number;
16268
+ };
16269
+ EncourageTopTeacher: {
16270
+ /** Format: uuid */
16271
+ userId?: string;
16272
+ rank?: number;
16273
+ name?: string;
16274
+ initials?: string;
16275
+ avatarColor?: string;
16276
+ evaluationsCount?: number;
16277
+ averageEvaluationSeconds?: number;
16278
+ /** Format: float */
16279
+ averageScore?: number;
16280
+ };
16281
+ EncourageDashboardResponse: {
16282
+ overview?: components["schemas"]["EncourageOverview"];
16283
+ kpis?: components["schemas"]["EncourageKpis"];
16284
+ licenses?: components["schemas"]["EncourageLicenses"];
16285
+ journey?: components["schemas"]["EncourageJourney"];
16286
+ submissions?: components["schemas"]["EncourageSubmissions"];
16287
+ classes?: components["schemas"]["EncourageClassPerformance"][];
16288
+ topStudents?: components["schemas"]["EncourageTopStudent"][];
16289
+ topTeachers?: components["schemas"]["EncourageTopTeacher"][];
16290
+ };
15672
16291
  UserCreationRequest: {
15673
16292
  /**
15674
16293
  * Format: uuid
@@ -15861,6 +16480,27 @@ interface components {
15861
16480
  /** Format: uri */
15862
16481
  url?: string;
15863
16482
  };
16483
+ GenerateCertificateDto: {
16484
+ /** Format: uuid */
16485
+ userId: string;
16486
+ /** Format: uuid */
16487
+ quizAttemptId?: string;
16488
+ /** Format: uuid */
16489
+ certificateTemplateId: string;
16490
+ /** @example João Silva */
16491
+ studentName: string;
16492
+ /** @example Introdução ao JavaScript */
16493
+ quizTitle: string;
16494
+ /** @example 85 */
16495
+ score?: number;
16496
+ /** @example CERT-2024-000001 */
16497
+ certificateNumber?: string;
16498
+ /**
16499
+ * Format: date-time
16500
+ * @example 2024-01-01T00:00:00.000Z
16501
+ */
16502
+ issuedAt?: string;
16503
+ };
15864
16504
  CreateGuardianDto: {
15865
16505
  /**
15866
16506
  * Format: email
@@ -21373,6 +22013,7 @@ declare function createQuizService(apiClient: AcademeApiClient): {
21373
22013
  search?: string;
21374
22014
  page?: number;
21375
22015
  limit?: number;
22016
+ randomize?: boolean;
21376
22017
  };
21377
22018
  header?: never;
21378
22019
  path?: never;
@@ -21403,6 +22044,7 @@ declare function createQuizService(apiClient: AcademeApiClient): {
21403
22044
  search?: string;
21404
22045
  page?: number;
21405
22046
  limit?: number;
22047
+ randomize?: boolean;
21406
22048
  } | undefined;
21407
22049
  };
21408
22050
  }, `${string}/${string}`>>;
@@ -22244,7 +22886,6 @@ declare function createCertificateService(apiClient: AcademeApiClient): {
22244
22886
  "application/json": {
22245
22887
  status?: string;
22246
22888
  data?: components["schemas"]["Certificate"];
22247
- message?: string;
22248
22889
  };
22249
22890
  };
22250
22891
  };
@@ -22291,7 +22932,6 @@ declare function createCertificateService(apiClient: AcademeApiClient): {
22291
22932
  "application/json": {
22292
22933
  status?: string;
22293
22934
  data?: components["schemas"]["Certificate"];
22294
- message?: string;
22295
22935
  };
22296
22936
  };
22297
22937
  };
@@ -22327,16 +22967,11 @@ declare function createCertificateService(apiClient: AcademeApiClient): {
22327
22967
  };
22328
22968
  requestBody?: never;
22329
22969
  responses: {
22330
- 200: {
22970
+ 204: {
22331
22971
  headers: {
22332
22972
  [name: string]: unknown;
22333
22973
  };
22334
- content: {
22335
- "application/json": {
22336
- status?: string;
22337
- message?: string;
22338
- };
22339
- };
22974
+ content?: never;
22340
22975
  };
22341
22976
  400: components["responses"]["BadRequest"];
22342
22977
  401: components["responses"]["Unauthorized"];
@@ -24160,7 +24795,6 @@ interface UpdateChallengeStepBody {
24160
24795
  name?: string;
24161
24796
  description?: string;
24162
24797
  index?: number;
24163
- courseId?: string;
24164
24798
  courseModuleId?: string;
24165
24799
  tutorialTitle?: string;
24166
24800
  tutorialDescription?: string;
@@ -24192,6 +24826,7 @@ declare function createChallengeService(apiClient: AcademeApiClient): {
24192
24826
  isActive?: boolean;
24193
24827
  templatesOnly?: boolean;
24194
24828
  search?: string;
24829
+ include?: "steps";
24195
24830
  page?: components["parameters"]["page"];
24196
24831
  limit?: components["parameters"]["limit"];
24197
24832
  };
@@ -24224,6 +24859,7 @@ declare function createChallengeService(apiClient: AcademeApiClient): {
24224
24859
  isActive?: boolean;
24225
24860
  templatesOnly?: boolean;
24226
24861
  search?: string;
24862
+ include?: "steps";
24227
24863
  page?: components["parameters"]["page"];
24228
24864
  limit?: components["parameters"]["limit"];
24229
24865
  } | undefined;
@@ -24288,6 +24924,7 @@ declare function createChallengeService(apiClient: AcademeApiClient): {
24288
24924
  isGroup?: boolean;
24289
24925
  maxGroupMembers?: number;
24290
24926
  isInviteOnly?: boolean;
24927
+ courseId: string;
24291
24928
  institutionId?: string | null;
24292
24929
  serieId?: string;
24293
24930
  index?: number;
@@ -24326,6 +24963,7 @@ declare function createChallengeService(apiClient: AcademeApiClient): {
24326
24963
  isGroup?: boolean;
24327
24964
  maxGroupMembers?: number;
24328
24965
  isInviteOnly?: boolean;
24966
+ courseId: string;
24329
24967
  institutionId?: string | null;
24330
24968
  serieId?: string;
24331
24969
  index?: number;
@@ -24359,6 +24997,7 @@ declare function createChallengeService(apiClient: AcademeApiClient): {
24359
24997
  isGroup?: boolean;
24360
24998
  maxGroupMembers?: number;
24361
24999
  isInviteOnly?: boolean;
25000
+ courseId?: string;
24362
25001
  serieId?: string;
24363
25002
  index?: number;
24364
25003
  submissionType?: "images" | "videos" | "audio" | "files" | "links";
@@ -24399,6 +25038,7 @@ declare function createChallengeService(apiClient: AcademeApiClient): {
24399
25038
  isGroup?: boolean;
24400
25039
  maxGroupMembers?: number;
24401
25040
  isInviteOnly?: boolean;
25041
+ courseId?: string;
24402
25042
  serieId?: string;
24403
25043
  index?: number;
24404
25044
  submissionType?: "images" | "videos" | "audio" | "files" | "links";
@@ -24504,7 +25144,6 @@ declare function createChallengeService(apiClient: AcademeApiClient): {
24504
25144
  name: string;
24505
25145
  description?: string;
24506
25146
  index: number;
24507
- courseId?: string;
24508
25147
  courseModuleId?: string;
24509
25148
  tutorialTitle?: string;
24510
25149
  tutorialDescription?: string;
@@ -24539,7 +25178,6 @@ declare function createChallengeService(apiClient: AcademeApiClient): {
24539
25178
  name: string;
24540
25179
  description?: string;
24541
25180
  index: number;
24542
- courseId?: string;
24543
25181
  courseModuleId?: string;
24544
25182
  tutorialTitle?: string;
24545
25183
  tutorialDescription?: string;
@@ -25110,6 +25748,353 @@ declare function createStepService(apiClient: AcademeApiClient): {
25110
25748
  };
25111
25749
  type StepService = ReturnType<typeof createStepService>;
25112
25750
 
25751
+ type GetSubmissionsParams = paths["/submissions"]["get"]["parameters"]["query"];
25752
+ type CreateSubmissionBody = paths["/submissions"]["post"]["requestBody"]["content"]["application/json"] & {
25753
+ /** Institution under which the user is submitting (from institution_registration) */
25754
+ institutionId: string;
25755
+ };
25756
+ type AttachFilesBody = paths["/submissions/{id}/files"]["post"]["requestBody"]["content"]["application/json"];
25757
+ type AiEvaluationBody = paths["/submissions/{id}/ai-evaluation"]["post"]["requestBody"]["content"]["application/json"];
25758
+ type TeacherEvaluationBody = paths["/submissions/{id}/teacher-evaluation"]["patch"]["requestBody"]["content"]["application/json"];
25759
+ declare function createSubmissionService(apiClient: AcademeApiClient): {
25760
+ /**
25761
+ * List submissions with filters and pagination
25762
+ */
25763
+ getAll(params?: GetSubmissionsParams): Promise<openapi_fetch.FetchResponse<{
25764
+ parameters: {
25765
+ query?: {
25766
+ challengeId?: string;
25767
+ userId?: string;
25768
+ groupId?: string;
25769
+ institutionId?: string;
25770
+ status?: "submitted" | "ai_evaluated" | "approved" | "rejected";
25771
+ page?: components["parameters"]["page"];
25772
+ limit?: components["parameters"]["limit"];
25773
+ };
25774
+ header?: never;
25775
+ path?: never;
25776
+ cookie?: never;
25777
+ };
25778
+ requestBody?: never;
25779
+ responses: {
25780
+ 200: {
25781
+ headers: {
25782
+ [name: string]: unknown;
25783
+ };
25784
+ content: {
25785
+ "application/json": {
25786
+ status?: string;
25787
+ data?: components["schemas"]["Submission"][];
25788
+ meta?: components["schemas"]["PaginationMeta"];
25789
+ };
25790
+ };
25791
+ };
25792
+ 401: components["responses"]["Unauthorized"];
25793
+ };
25794
+ }, {
25795
+ params: {
25796
+ query: {
25797
+ challengeId?: string;
25798
+ userId?: string;
25799
+ groupId?: string;
25800
+ institutionId?: string;
25801
+ status?: "submitted" | "ai_evaluated" | "approved" | "rejected";
25802
+ page?: components["parameters"]["page"];
25803
+ limit?: components["parameters"]["limit"];
25804
+ } | undefined;
25805
+ };
25806
+ }, `${string}/${string}`>>;
25807
+ /**
25808
+ * Get submission with files and per-criterion scores
25809
+ */
25810
+ getById(id: string): Promise<openapi_fetch.FetchResponse<{
25811
+ parameters: {
25812
+ query?: never;
25813
+ header?: never;
25814
+ path: {
25815
+ id: components["parameters"]["id"];
25816
+ };
25817
+ cookie?: never;
25818
+ };
25819
+ requestBody?: never;
25820
+ responses: {
25821
+ 200: {
25822
+ headers: {
25823
+ [name: string]: unknown;
25824
+ };
25825
+ content: {
25826
+ "application/json": {
25827
+ status?: string;
25828
+ data?: components["schemas"]["Submission"] & {
25829
+ files?: components["schemas"]["SubmissionFile"][];
25830
+ criterionScores?: components["schemas"]["SubmissionCriterionScore"][];
25831
+ };
25832
+ };
25833
+ };
25834
+ };
25835
+ 401: components["responses"]["Unauthorized"];
25836
+ 404: components["responses"]["NotFound"];
25837
+ };
25838
+ }, {
25839
+ params: {
25840
+ path: {
25841
+ id: string;
25842
+ };
25843
+ };
25844
+ }, `${string}/${string}`>>;
25845
+ /**
25846
+ * Create a new submission attempt (status=submitted)
25847
+ * - Cannot submit to a global template (clone first)
25848
+ * - For group challenges: groupId is required and user must be a member
25849
+ * - For individual challenges: groupId must be omitted
25850
+ * - Cannot create when there is already an active submission
25851
+ * - attempt_number is computed server-side
25852
+ */
25853
+ create(data: CreateSubmissionBody): Promise<openapi_fetch.FetchResponse<{
25854
+ parameters: {
25855
+ query?: never;
25856
+ header?: never;
25857
+ path?: never;
25858
+ cookie?: never;
25859
+ };
25860
+ requestBody: {
25861
+ content: {
25862
+ "application/json": {
25863
+ challengeId: string;
25864
+ institutionId: string;
25865
+ groupId?: string;
25866
+ description?: string;
25867
+ };
25868
+ };
25869
+ };
25870
+ responses: {
25871
+ 201: {
25872
+ headers: {
25873
+ [name: string]: unknown;
25874
+ };
25875
+ content: {
25876
+ "application/json": {
25877
+ status?: string;
25878
+ data?: components["schemas"]["Submission"];
25879
+ };
25880
+ };
25881
+ };
25882
+ 400: components["responses"]["BadRequest"];
25883
+ 403: components["responses"]["Forbidden"];
25884
+ 404: components["responses"]["NotFound"];
25885
+ 409: components["responses"]["Conflict"];
25886
+ };
25887
+ }, {
25888
+ body: never;
25889
+ }, `${string}/${string}`>>;
25890
+ /**
25891
+ * Attach files or links to a submission (batch)
25892
+ * Each item must have exactly ONE of fileId or url (XOR).
25893
+ * - submissionType in [images, videos, audio, files] → items must have fileId
25894
+ * - submissionType === 'links' → items must have url
25895
+ */
25896
+ attachFiles(submissionId: string, data: AttachFilesBody): Promise<openapi_fetch.FetchResponse<{
25897
+ parameters: {
25898
+ query?: never;
25899
+ header?: never;
25900
+ path: {
25901
+ id: components["parameters"]["id"];
25902
+ };
25903
+ cookie?: never;
25904
+ };
25905
+ requestBody: {
25906
+ content: {
25907
+ "application/json": {
25908
+ items: {
25909
+ fileId?: string | null;
25910
+ url?: string | null;
25911
+ index?: number;
25912
+ }[];
25913
+ };
25914
+ };
25915
+ };
25916
+ responses: {
25917
+ 201: {
25918
+ headers: {
25919
+ [name: string]: unknown;
25920
+ };
25921
+ content: {
25922
+ "application/json": {
25923
+ status?: string;
25924
+ data?: components["schemas"]["SubmissionFile"][];
25925
+ };
25926
+ };
25927
+ };
25928
+ 400: components["responses"]["BadRequest"];
25929
+ 404: components["responses"]["NotFound"];
25930
+ 409: components["responses"]["Conflict"];
25931
+ };
25932
+ }, {
25933
+ params: {
25934
+ path: {
25935
+ id: string;
25936
+ };
25937
+ };
25938
+ body: {
25939
+ items: {
25940
+ fileId?: string | null;
25941
+ url?: string | null;
25942
+ index?: number;
25943
+ }[];
25944
+ };
25945
+ }, `${string}/${string}`>>;
25946
+ /**
25947
+ * Remove a file or link from a submission
25948
+ * Only allowed when submission is in status submitted or ai_evaluated
25949
+ */
25950
+ removeFile(submissionId: string, fileRowId: string): Promise<openapi_fetch.FetchResponse<{
25951
+ parameters: {
25952
+ query?: never;
25953
+ header?: never;
25954
+ path: {
25955
+ id: components["parameters"]["id"];
25956
+ fileRowId: string;
25957
+ };
25958
+ cookie?: never;
25959
+ };
25960
+ requestBody?: never;
25961
+ responses: {
25962
+ 204: {
25963
+ headers: {
25964
+ [name: string]: unknown;
25965
+ };
25966
+ content?: never;
25967
+ };
25968
+ 400: components["responses"]["BadRequest"];
25969
+ 404: components["responses"]["NotFound"];
25970
+ };
25971
+ }, {
25972
+ params: {
25973
+ path: {
25974
+ id: string;
25975
+ fileRowId: string;
25976
+ };
25977
+ };
25978
+ }, `${string}/${string}`>>;
25979
+ /**
25980
+ * Register AI evaluation (called by the AI service callback).
25981
+ * Moves status from submitted → ai_evaluated.
25982
+ */
25983
+ aiEvaluate(submissionId: string, data: AiEvaluationBody): Promise<openapi_fetch.FetchResponse<{
25984
+ parameters: {
25985
+ query?: never;
25986
+ header?: never;
25987
+ path: {
25988
+ id: components["parameters"]["id"];
25989
+ };
25990
+ cookie?: never;
25991
+ };
25992
+ requestBody: {
25993
+ content: {
25994
+ "application/json": {
25995
+ aiScore: number;
25996
+ aiFeedback?: string;
25997
+ aiExtractedContent?: Record<string, never>;
25998
+ criterionScores?: {
25999
+ challengeEvaluationCriterionId: string;
26000
+ score: number;
26001
+ comment?: string;
26002
+ }[];
26003
+ };
26004
+ };
26005
+ };
26006
+ responses: {
26007
+ 200: {
26008
+ headers: {
26009
+ [name: string]: unknown;
26010
+ };
26011
+ content: {
26012
+ "application/json": {
26013
+ status?: string;
26014
+ data?: components["schemas"]["Submission"];
26015
+ };
26016
+ };
26017
+ };
26018
+ 400: {
26019
+ headers: {
26020
+ [name: string]: unknown;
26021
+ };
26022
+ content: {
26023
+ "application/json": components["schemas"]["Error"];
26024
+ };
26025
+ };
26026
+ 404: components["responses"]["NotFound"];
26027
+ 409: components["responses"]["Conflict"];
26028
+ };
26029
+ }, {
26030
+ params: {
26031
+ path: {
26032
+ id: string;
26033
+ };
26034
+ };
26035
+ body: {
26036
+ aiScore: number;
26037
+ aiFeedback?: string;
26038
+ aiExtractedContent?: Record<string, never>;
26039
+ criterionScores?: {
26040
+ challengeEvaluationCriterionId: string;
26041
+ score: number;
26042
+ comment?: string;
26043
+ }[];
26044
+ };
26045
+ }, `${string}/${string}`>>;
26046
+ /**
26047
+ * Teacher approves or rejects a submission.
26048
+ * Only allowed when status is submitted or ai_evaluated.
26049
+ */
26050
+ teacherEvaluate(submissionId: string, data: TeacherEvaluationBody): Promise<openapi_fetch.FetchResponse<{
26051
+ parameters: {
26052
+ query?: never;
26053
+ header?: never;
26054
+ path: {
26055
+ id: components["parameters"]["id"];
26056
+ };
26057
+ cookie?: never;
26058
+ };
26059
+ requestBody: {
26060
+ content: {
26061
+ "application/json": {
26062
+ status: "approved" | "rejected";
26063
+ teacherScore?: number;
26064
+ teacherFeedback?: string;
26065
+ };
26066
+ };
26067
+ };
26068
+ responses: {
26069
+ 200: {
26070
+ headers: {
26071
+ [name: string]: unknown;
26072
+ };
26073
+ content: {
26074
+ "application/json": {
26075
+ status?: string;
26076
+ data?: components["schemas"]["Submission"];
26077
+ };
26078
+ };
26079
+ };
26080
+ 400: components["responses"]["BadRequest"];
26081
+ 404: components["responses"]["NotFound"];
26082
+ };
26083
+ }, {
26084
+ params: {
26085
+ path: {
26086
+ id: string;
26087
+ };
26088
+ };
26089
+ body: {
26090
+ status: "approved" | "rejected";
26091
+ teacherScore?: number;
26092
+ teacherFeedback?: string;
26093
+ };
26094
+ }, `${string}/${string}`>>;
26095
+ };
26096
+ type SubmissionService = ReturnType<typeof createSubmissionService>;
26097
+
25113
26098
  type AcademeApiClient = ReturnType<typeof openapi_fetch__default<paths>>;
25114
26099
  declare function createAcademeApiClient(baseUrl: string): AcademeApiClient;
25115
26100
  interface AcademeServices {
@@ -25133,6 +26118,7 @@ interface AcademeServices {
25133
26118
  storageFile: StorageFileService;
25134
26119
  challenge: ChallengeService;
25135
26120
  step: StepService;
26121
+ submission: SubmissionService;
25136
26122
  }
25137
26123
 
25138
26124
  type AcademeKeycloakContextProps = {