@hed-hog/lms 0.0.331 → 0.0.338

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.
Files changed (110) hide show
  1. package/dist/class-group/class-group.controller.d.ts +3 -3
  2. package/dist/class-group/class-group.service.d.ts +3 -3
  3. package/dist/course/course.service.d.ts.map +1 -1
  4. package/dist/course/course.service.js +12 -20
  5. package/dist/course/course.service.js.map +1 -1
  6. package/dist/enterprise/enterprise.controller.d.ts +72 -0
  7. package/dist/enterprise/enterprise.controller.d.ts.map +1 -1
  8. package/dist/enterprise/enterprise.controller.js +10 -0
  9. package/dist/enterprise/enterprise.controller.js.map +1 -1
  10. package/dist/enterprise/enterprise.service.d.ts +78 -0
  11. package/dist/enterprise/enterprise.service.d.ts.map +1 -1
  12. package/dist/enterprise/enterprise.service.js +413 -40
  13. package/dist/enterprise/enterprise.service.js.map +1 -1
  14. package/dist/enterprise/training/training-admin.controller.d.ts +6 -3
  15. package/dist/enterprise/training/training-admin.controller.d.ts.map +1 -1
  16. package/dist/enterprise/training/training-admin.controller.js +10 -6
  17. package/dist/enterprise/training/training-admin.controller.js.map +1 -1
  18. package/dist/enterprise/training/training-admin.service.d.ts +8 -2
  19. package/dist/enterprise/training/training-admin.service.d.ts.map +1 -1
  20. package/dist/enterprise/training/training-admin.service.js +108 -52
  21. package/dist/enterprise/training/training-admin.service.js.map +1 -1
  22. package/dist/enterprise/training/training-viewer.controller.d.ts +3 -0
  23. package/dist/enterprise/training/training-viewer.controller.d.ts.map +1 -1
  24. package/dist/evaluation/evaluation.controller.d.ts +4 -4
  25. package/dist/evaluation/evaluation.service.d.ts +4 -4
  26. package/dist/instructor/dto/create-instructor-skill.dto.d.ts +0 -4
  27. package/dist/instructor/dto/create-instructor-skill.dto.d.ts.map +1 -1
  28. package/dist/instructor/dto/create-instructor-skill.dto.js +0 -21
  29. package/dist/instructor/dto/create-instructor-skill.dto.js.map +1 -1
  30. package/dist/instructor/dto/update-instructor-skill.dto.d.ts +0 -4
  31. package/dist/instructor/dto/update-instructor-skill.dto.d.ts.map +1 -1
  32. package/dist/instructor/dto/update-instructor-skill.dto.js +0 -22
  33. package/dist/instructor/dto/update-instructor-skill.dto.js.map +1 -1
  34. package/dist/instructor/instructor-skill.controller.d.ts +4 -4
  35. package/dist/instructor/instructor-skill.service.d.ts +4 -7
  36. package/dist/instructor/instructor-skill.service.d.ts.map +1 -1
  37. package/dist/instructor/instructor-skill.service.js +2 -89
  38. package/dist/instructor/instructor-skill.service.js.map +1 -1
  39. package/dist/instructor/instructor.controller.d.ts +20 -0
  40. package/dist/instructor/instructor.controller.d.ts.map +1 -1
  41. package/dist/instructor/instructor.controller.js +19 -0
  42. package/dist/instructor/instructor.controller.js.map +1 -1
  43. package/dist/instructor/instructor.service.d.ts +25 -0
  44. package/dist/instructor/instructor.service.d.ts.map +1 -1
  45. package/dist/instructor/instructor.service.js +70 -18
  46. package/dist/instructor/instructor.service.js.map +1 -1
  47. package/dist/lms.module.d.ts.map +1 -1
  48. package/dist/lms.module.js.map +1 -1
  49. package/hedhog/data/route.yaml +23 -1
  50. package/hedhog/frontend/app/_components/class-form-sheet.tsx.ejs +42 -24
  51. package/hedhog/frontend/app/_components/course-form-sheet.tsx.ejs +3 -3
  52. package/hedhog/frontend/app/_components/create-lms-instructor-sheet.tsx.ejs +591 -0
  53. package/hedhog/frontend/app/certificates/issued/page.tsx.ejs +6 -1
  54. package/hedhog/frontend/app/certificates/models/page.tsx.ejs +6 -1
  55. package/hedhog/frontend/app/classes/page.tsx.ejs +6 -1
  56. package/hedhog/frontend/app/courses/[id]/_components/CourseClassificationCard.tsx.ejs +3 -33
  57. package/hedhog/frontend/app/courses/[id]/_components/CourseContentCard.tsx.ejs +9 -9
  58. package/hedhog/frontend/app/courses/[id]/_components/CourseMainInfoCard.tsx.ejs +109 -0
  59. package/hedhog/frontend/app/courses/[id]/_components/CourseMultiEntityPicker.tsx.ejs +40 -13
  60. package/hedhog/frontend/app/courses/[id]/_components/CourseRelationsCard.tsx.ejs +76 -81
  61. package/hedhog/frontend/app/courses/[id]/_components/CourseSummaryCard.tsx.ejs +60 -0
  62. package/hedhog/frontend/app/courses/[id]/structure/_components/course-scheduled-classes-tab.tsx.ejs +406 -0
  63. package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree.tsx.ejs +134 -0
  64. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-course.tsx.ejs +113 -0
  65. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson.tsx.ejs +314 -0
  66. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-session.tsx.ejs +174 -0
  67. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-course.tsx.ejs +242 -33
  68. package/hedhog/frontend/app/courses/[id]/structure/_components/mock-data.ts.ejs +185 -0
  69. package/hedhog/frontend/app/courses/page.tsx.ejs +6 -1
  70. package/hedhog/frontend/app/enterprise/_components/enterprise-activity-timeline.tsx.ejs +87 -0
  71. package/hedhog/frontend/app/enterprise/_components/enterprise-admin-create-sheet.tsx.ejs +4 -0
  72. package/hedhog/frontend/app/enterprise/_components/enterprise-administrators-tab.tsx.ejs +31 -5
  73. package/hedhog/frontend/app/enterprise/_components/enterprise-classes-tab.tsx.ejs +79 -20
  74. package/hedhog/frontend/app/enterprise/_components/enterprise-company-identity-card.tsx.ejs +11 -2
  75. package/hedhog/frontend/app/enterprise/_components/enterprise-course-edit-sheet.tsx.ejs +201 -0
  76. package/hedhog/frontend/app/enterprise/_components/enterprise-courses-tab.tsx.ejs +55 -24
  77. package/hedhog/frontend/app/enterprise/_components/enterprise-detail-sheet.tsx.ejs +430 -296
  78. package/hedhog/frontend/app/enterprise/_components/enterprise-mocks.ts.ejs +277 -0
  79. package/hedhog/frontend/app/enterprise/_components/enterprise-overview-analytics.tsx.ejs +205 -0
  80. package/hedhog/frontend/app/enterprise/_components/enterprise-person-edit-sheet.tsx.ejs +97 -0
  81. package/hedhog/frontend/app/enterprise/_components/enterprise-sheet.tsx.ejs +82 -57
  82. package/hedhog/frontend/app/enterprise/_components/enterprise-student-create-sheet.tsx.ejs +4 -0
  83. package/hedhog/frontend/app/enterprise/_components/enterprise-students-tab.tsx.ejs +60 -22
  84. package/hedhog/frontend/app/enterprise/_components/enterprise-types.ts.ejs +54 -0
  85. package/hedhog/frontend/app/enterprise/_components/enterprise-user-create-sheet.tsx.ejs +211 -0
  86. package/hedhog/frontend/app/enterprise/page.tsx.ejs +39 -7
  87. package/hedhog/frontend/app/exams/[id]/questions/page.tsx.ejs +6 -1
  88. package/hedhog/frontend/app/exams/page.tsx.ejs +6 -1
  89. package/hedhog/frontend/app/instructor-skills/page.tsx.ejs +51 -104
  90. package/hedhog/frontend/app/instructors/_components/instructor-form-sheet.tsx.ejs +625 -366
  91. package/hedhog/frontend/app/instructors/page.tsx.ejs +6 -1
  92. package/hedhog/frontend/app/paths/page.tsx.ejs +9 -4
  93. package/hedhog/frontend/app/reports/evaluations/page.tsx.ejs +6 -1
  94. package/hedhog/frontend/app/training/page.tsx.ejs +9 -4
  95. package/hedhog/frontend/messages/en.json +101 -10
  96. package/hedhog/frontend/messages/pt.json +101 -10
  97. package/hedhog/table/enterprise_student_license_event.yaml +30 -0
  98. package/hedhog/table/instructor_skill.yaml +0 -11
  99. package/package.json +7 -7
  100. package/src/course/course.service.ts +12 -24
  101. package/src/enterprise/enterprise.controller.ts +5 -0
  102. package/src/enterprise/enterprise.service.ts +507 -29
  103. package/src/enterprise/training/training-admin.controller.ts +4 -0
  104. package/src/enterprise/training/training-admin.service.ts +115 -51
  105. package/src/instructor/dto/create-instructor-skill.dto.ts +0 -17
  106. package/src/instructor/dto/update-instructor-skill.dto.ts +0 -18
  107. package/src/instructor/instructor-skill.service.ts +2 -97
  108. package/src/instructor/instructor.controller.ts +16 -0
  109. package/src/instructor/instructor.service.ts +85 -10
  110. package/src/lms.module.ts +1 -0
@@ -56,6 +56,7 @@ import {
56
56
  } from 'lucide-react';
57
57
  import { useTranslations } from 'next-intl';
58
58
  import { useEffect, useState } from 'react';
59
+ import { usePersistedPageSize } from '@/hooks/use-persisted-page-size';
59
60
  import { toast } from 'sonner';
60
61
  import { InstructorFormSheet } from './_components/instructor-form-sheet';
61
62
  import type {
@@ -102,7 +103,11 @@ export default function InstructorsPage() {
102
103
  const t = useTranslations('lms.InstructorsPage');
103
104
 
104
105
  const [page, setPage] = useState(1);
105
- const [pageSize, setPageSize] = useState(12);
106
+ const [pageSize, setPageSize] = usePersistedPageSize({
107
+ storageKey: 'pagination:global:pageSize',
108
+ defaultValue: 12,
109
+ allowedValues: [6, 12, 24, 48],
110
+ });
106
111
  const [searchInput, setSearchInput] = useState('');
107
112
  const [debouncedSearch, setDebouncedSearch] = useState('');
108
113
  const [statusFilter, setStatusFilter] = useState('all');
@@ -103,6 +103,7 @@ import {
103
103
  import { useTranslations } from 'next-intl';
104
104
  import { useRouter } from 'next/navigation';
105
105
  import { useEffect, useMemo, useRef, useState } from 'react';
106
+ import { usePersistedPageSize } from '@/hooks/use-persisted-page-size';
106
107
  import { Controller, useForm, useWatch } from 'react-hook-form';
107
108
  import { toast } from 'sonner';
108
109
  import { z } from 'zod';
@@ -565,7 +566,11 @@ export default function TrainingPage() {
565
566
 
566
567
  // Pagination
567
568
  const [currentPage, setCurrentPage] = useState(1);
568
- const [pageSize, setPageSize] = useState(12);
569
+ const [pageSize, setPageSize] = usePersistedPageSize({
570
+ storageKey: 'pagination:global:pageSize',
571
+ defaultValue: 12,
572
+ allowedValues: PAGE_SIZES,
573
+ });
569
574
 
570
575
  // Double-click tracking
571
576
  const clickTimers = useRef<Map<number, ReturnType<typeof setTimeout>>>(
@@ -1893,15 +1898,15 @@ export default function TrainingPage() {
1893
1898
  <FieldError>{form.formState.errors.nome?.message}</FieldError>
1894
1899
  </Field>
1895
1900
  <Field>
1896
- <FieldLabel htmlFor="descricao">
1901
+ <FieldLabel htmlFor="descricao">
1897
1902
  {t('form.fields.description.label')}{' '}
1898
1903
  <span className="text-destructive">*</span>
1899
1904
  </FieldLabel>
1900
1905
  <Textarea
1901
- id="descricao"
1906
+ id="descricao"
1902
1907
  rows={3}
1903
1908
  placeholder={t('form.fields.description.placeholder')}
1904
- {...form.register('descricao')}
1909
+ {...form.register('descricao')}
1905
1910
  />
1906
1911
  <FieldError>
1907
1912
  {form.formState.errors.descricao?.message}
@@ -61,6 +61,7 @@ import {
61
61
  import { useTranslations } from 'next-intl';
62
62
  import { useRouter } from 'next/navigation';
63
63
  import { useEffect, useMemo, useRef, useState, type ReactNode } from 'react';
64
+ import { usePersistedPageSize } from '@/hooks/use-persisted-page-size';
64
65
  import type { DateRange } from 'react-day-picker';
65
66
 
66
67
  // ── Types ─────────────────────────────────────────────────────────────────────
@@ -360,7 +361,11 @@ export default function EvaluationsReportPage() {
360
361
 
361
362
  // Pagination
362
363
  const [currentPage, setCurrentPage] = useState(1);
363
- const [pageSize, setPageSize] = useState(12);
364
+ const [pageSize, setPageSize] = usePersistedPageSize({
365
+ storageKey: 'pagination:global:pageSize',
366
+ defaultValue: 12,
367
+ allowedValues: PAGE_SIZES,
368
+ });
364
369
 
365
370
  // Reset page when filters change
366
371
  useEffect(() => {
@@ -102,6 +102,7 @@ import {
102
102
  import { useTranslations } from 'next-intl';
103
103
  import { useRouter } from 'next/navigation';
104
104
  import { useEffect, useMemo, useRef, useState } from 'react';
105
+ import { usePersistedPageSize } from '@/hooks/use-persisted-page-size';
105
106
  import { Controller, useForm, useWatch } from 'react-hook-form';
106
107
  import { toast } from 'sonner';
107
108
  import { z } from 'zod';
@@ -560,7 +561,11 @@ export default function TrainingPage() {
560
561
 
561
562
  // Pagination
562
563
  const [currentPage, setCurrentPage] = useState(1);
563
- const [pageSize, setPageSize] = useState(12);
564
+ const [pageSize, setPageSize] = usePersistedPageSize({
565
+ storageKey: 'pagination:global:pageSize',
566
+ defaultValue: 12,
567
+ allowedValues: PAGE_SIZES,
568
+ });
564
569
 
565
570
  // Double-click tracking
566
571
  const clickTimers = useRef<Map<number, ReturnType<typeof setTimeout>>>(
@@ -1886,15 +1891,15 @@ export default function TrainingPage() {
1886
1891
  <FieldError>{form.formState.errors.nome?.message}</FieldError>
1887
1892
  </Field>
1888
1893
  <Field>
1889
- <FieldLabel htmlFor="descricao">
1894
+ <FieldLabel htmlFor="descricao">
1890
1895
  {t('form.fields.description.label')}{' '}
1891
1896
  <span className="text-destructive">*</span>
1892
1897
  </FieldLabel>
1893
1898
  <Textarea
1894
- id="descricao"
1899
+ id="descricao"
1895
1900
  rows={3}
1896
1901
  placeholder={t('form.fields.description.placeholder')}
1897
- {...form.register('descricao')}
1902
+ {...form.register('descricao')}
1898
1903
  />
1899
1904
  <FieldError>
1900
1905
  {form.formState.errors.descricao?.message}
@@ -2907,6 +2907,11 @@
2907
2907
  "subFree": "{count} spots available",
2908
2908
  "subFull": "Full"
2909
2909
  },
2910
+ "nextClass": "Next Class",
2911
+ "noClass": "No class",
2912
+ "createNext": "Create next class",
2913
+ "calendar": "Calendar",
2914
+ "completed": "{count} completed",
2910
2915
  "avgAttendance": {
2911
2916
  "label": "Average Attendance",
2912
2917
  "sub": "overall attendance"
@@ -3538,10 +3543,92 @@
3538
3543
  "studentRemoveError": "Failed to remove student."
3539
3544
  },
3540
3545
  "form": {
3546
+ "title": {
3547
+ "create": "Create New Course",
3548
+ "edit": "Edit Course"
3549
+ },
3550
+ "description": {
3551
+ "create": "Fill in the details to create a new course. After creating, you will be redirected to the course page.",
3552
+ "edit": "Update the course information below."
3553
+ },
3554
+ "fields": {
3555
+ "internalName": {
3556
+ "label": "Internal Name",
3557
+ "placeholder": "Ex: Advanced React",
3558
+ "description": "Internal course name for administrative use"
3559
+ },
3560
+ "slug": {
3561
+ "label": "Slug",
3562
+ "placeholder": "Ex: advanced-react",
3563
+ "description": "Unique URL identifier (lowercase letters, numbers, and hyphens)"
3564
+ },
3565
+ "commercialTitle": {
3566
+ "label": "Commercial Title",
3567
+ "placeholder": "Ex: Advanced React"
3568
+ },
3569
+ "description": {
3570
+ "label": "Description",
3571
+ "placeholder": "Describe the course content and objectives..."
3572
+ },
3573
+ "level": {
3574
+ "label": "Level",
3575
+ "placeholder": "Select"
3576
+ },
3577
+ "status": {
3578
+ "label": "Status",
3579
+ "placeholder": "Select"
3580
+ },
3581
+ "categories": {
3582
+ "label": "Categories",
3583
+ "description": "Select one or more categories",
3584
+ "createAction": "Create category",
3585
+ "selectPlaceholder": "Select a category",
3586
+ "removeAction": "Remove category",
3587
+ "searchPlaceholder": "Type to search category...",
3588
+ "noResults": "No categories found",
3589
+ "selectedCount": "selected category(ies)"
3590
+ },
3591
+ "primaryColor": {
3592
+ "label": "Primary Color",
3593
+ "placeholder": "#1D4ED8"
3594
+ },
3595
+ "secondaryColor": {
3596
+ "label": "Secondary Color",
3597
+ "placeholder": "#111827"
3598
+ },
3599
+ "logo": {
3600
+ "label": "Course Logo",
3601
+ "alt": "Course logo",
3602
+ "upload": "Upload logo",
3603
+ "replace": "Replace logo",
3604
+ "remove": "Remove",
3605
+ "description": "Optional image to identify the course"
3606
+ }
3607
+ },
3608
+ "validation": {
3609
+ "internalNameMinLength": "Internal name must have at least 3 characters",
3610
+ "slugPattern": "Slug must contain only lowercase letters, numbers and hyphens"
3611
+ },
3612
+ "actions": {
3613
+ "cancel": "Cancel",
3614
+ "save": "Save Changes",
3615
+ "create": "Create Course"
3616
+ },
3541
3617
  "toasts": {
3542
3618
  "courseCreated": "Course created successfully! Redirecting...",
3543
3619
  "courseCreateError": "Failed to create the course."
3544
3620
  }
3621
+ },
3622
+ "levels": {
3623
+ "beginner": "Beginner",
3624
+ "intermediate": "Intermediate",
3625
+ "advanced": "Advanced"
3626
+ },
3627
+ "status": {
3628
+ "active": "Active",
3629
+ "inactive": "Inactive",
3630
+ "draft": "Draft",
3631
+ "archived": "Archived"
3545
3632
  }
3546
3633
  },
3547
3634
  "InstructorsPage": {
@@ -3652,9 +3739,17 @@
3652
3739
  "classes": {
3653
3740
  "emptyTitle": "No classes found",
3654
3741
  "emptyDescription": "This instructor is not linked to any classes yet.",
3742
+ "searchPlaceholder": "Search class by name, code or course...",
3743
+ "statusFilterPlaceholder": "Filter by status",
3744
+ "allStatuses": "All statuses",
3655
3745
  "start": "Start:",
3656
3746
  "end": "End:",
3657
- "students": "{count} student(s)"
3747
+ "students": "{count} student(s)",
3748
+ "studentsOfCapacity": "{count} / {total} student(s)",
3749
+ "actions": {
3750
+ "editAriaLabel": "Edit class",
3751
+ "openAriaLabel": "Open class page"
3752
+ }
3658
3753
  },
3659
3754
  "evaluations": {
3660
3755
  "comingSoonTitle": "Evaluations — feature coming soon",
@@ -3704,23 +3799,17 @@
3704
3799
  "current": "Instructor Skills"
3705
3800
  },
3706
3801
  "filters": {
3707
- "searchPlaceholder": "Search by slug or name..."
3802
+ "searchPlaceholder": "Search by slug..."
3708
3803
  },
3709
3804
  "table": {
3710
3805
  "slug": "Slug",
3711
- "namePt": "Name (PT)",
3712
- "nameEn": "Name (EN)",
3713
3806
  "status": "Status"
3714
3807
  },
3715
3808
  "form": {
3716
3809
  "slug": "Slug",
3717
3810
  "slugPlaceholder": "e.g. javascript, react-js",
3718
- "namePt": "Name (PT)",
3719
- "namePtPlaceholder": "Portuguese name",
3720
- "nameEn": "Name (EN)",
3721
- "nameEnPlaceholder": "Name in English (optional)",
3722
3811
  "status": "Status",
3723
- "statusPlaceholder": "Select status",
3812
+ "statusPlaceholder": "Select a status",
3724
3813
  "validation": {
3725
3814
  "required": "Required",
3726
3815
  "max100": "Maximum 100 characters",
@@ -3933,7 +4022,8 @@
3933
4022
  },
3934
4023
  "actions": {
3935
4024
  "create": "Create new class",
3936
- "add": "Add"
4025
+ "add": "Add",
4026
+ "edit": "Edit"
3937
4027
  },
3938
4028
  "empty": {
3939
4029
  "title": "No classes found.",
@@ -3941,6 +4031,7 @@
3941
4031
  },
3942
4032
  "table": {
3943
4033
  "class": "Class",
4034
+ "instructor": "Instructor",
3944
4035
  "status": "Status",
3945
4036
  "period": "Period",
3946
4037
  "capacity": "Capacity"
@@ -2916,6 +2916,11 @@
2916
2916
  "subFree": "{count} vagas livres",
2917
2917
  "subFull": "Lotada"
2918
2918
  },
2919
+ "nextClass": "Próxima Aula",
2920
+ "noClass": "Sem aula",
2921
+ "createNext": "Crie a próxima aula",
2922
+ "calendar": "Calendário",
2923
+ "completed": "{count} concluída(s)",
2919
2924
  "avgAttendance": {
2920
2925
  "label": "Presença Média",
2921
2926
  "sub": "frequência geral"
@@ -3547,10 +3552,92 @@
3547
3552
  "studentRemoveError": "Falha ao remover aluno."
3548
3553
  },
3549
3554
  "form": {
3555
+ "title": {
3556
+ "create": "Criar Novo Curso",
3557
+ "edit": "Editar Curso"
3558
+ },
3559
+ "description": {
3560
+ "create": "Preencha os dados para criar um novo curso. Após criar, você será redirecionado para a página do curso.",
3561
+ "edit": "Atualize as informações do curso abaixo."
3562
+ },
3563
+ "fields": {
3564
+ "internalName": {
3565
+ "label": "Nome Interno",
3566
+ "placeholder": "Ex: React Avançado",
3567
+ "description": "Nome interno do curso para uso administrativo"
3568
+ },
3569
+ "slug": {
3570
+ "label": "Slug",
3571
+ "placeholder": "Ex: react-avancado",
3572
+ "description": "Identificador único na URL (letras minúsculas, números e hífens)"
3573
+ },
3574
+ "commercialTitle": {
3575
+ "label": "Título Comercial",
3576
+ "placeholder": "Ex: React Avançado"
3577
+ },
3578
+ "description": {
3579
+ "label": "Descrição",
3580
+ "placeholder": "Descreva o conteúdo e objetivos do curso..."
3581
+ },
3582
+ "level": {
3583
+ "label": "Nível",
3584
+ "placeholder": "Selecione"
3585
+ },
3586
+ "status": {
3587
+ "label": "Status",
3588
+ "placeholder": "Selecione"
3589
+ },
3590
+ "categories": {
3591
+ "label": "Categorias",
3592
+ "description": "Selecione uma ou mais categorias",
3593
+ "createAction": "Criar categoria",
3594
+ "selectPlaceholder": "Selecione uma categoria",
3595
+ "removeAction": "Remover categoria",
3596
+ "searchPlaceholder": "Digite para buscar categoria...",
3597
+ "noResults": "Nenhuma categoria encontrada",
3598
+ "selectedCount": "categoria(s) selecionada(s)"
3599
+ },
3600
+ "primaryColor": {
3601
+ "label": "Cor Primária",
3602
+ "placeholder": "#1D4ED8"
3603
+ },
3604
+ "secondaryColor": {
3605
+ "label": "Cor Secundária",
3606
+ "placeholder": "#111827"
3607
+ },
3608
+ "logo": {
3609
+ "label": "Logo do Curso",
3610
+ "alt": "Logo do curso",
3611
+ "upload": "Carregar logo",
3612
+ "replace": "Substituir logo",
3613
+ "remove": "Remover",
3614
+ "description": "Imagem opcional para identificar o curso"
3615
+ }
3616
+ },
3617
+ "validation": {
3618
+ "internalNameMinLength": "Nome interno deve ter pelo menos 3 caracteres",
3619
+ "slugPattern": "Slug deve conter apenas letras minúsculas, números e hífens"
3620
+ },
3621
+ "actions": {
3622
+ "cancel": "Cancelar",
3623
+ "save": "Salvar Alterações",
3624
+ "create": "Criar Curso"
3625
+ },
3550
3626
  "toasts": {
3551
3627
  "courseCreated": "Curso criado com sucesso! Redirecionando...",
3552
3628
  "courseCreateError": "Não foi possível criar o curso."
3553
3629
  }
3630
+ },
3631
+ "levels": {
3632
+ "beginner": "Iniciante",
3633
+ "intermediate": "Intermediário",
3634
+ "advanced": "Avançado"
3635
+ },
3636
+ "status": {
3637
+ "active": "Ativo",
3638
+ "inactive": "Inativo",
3639
+ "draft": "Rascunho",
3640
+ "archived": "Arquivado"
3554
3641
  }
3555
3642
  },
3556
3643
  "InstructorsPage": {
@@ -3661,9 +3748,17 @@
3661
3748
  "classes": {
3662
3749
  "emptyTitle": "Nenhuma turma encontrada",
3663
3750
  "emptyDescription": "Este instrutor ainda não está vinculado a nenhuma turma.",
3751
+ "searchPlaceholder": "Buscar turma por nome, código ou curso...",
3752
+ "statusFilterPlaceholder": "Filtrar por status",
3753
+ "allStatuses": "Todos os status",
3664
3754
  "start": "Início:",
3665
3755
  "end": "Fim:",
3666
- "students": "{count} aluno(s)"
3756
+ "students": "{count} aluno(s)",
3757
+ "studentsOfCapacity": "{count} / {total} aluno(s)",
3758
+ "actions": {
3759
+ "editAriaLabel": "Editar turma",
3760
+ "openAriaLabel": "Abrir página da turma"
3761
+ }
3667
3762
  },
3668
3763
  "evaluations": {
3669
3764
  "comingSoonTitle": "Avaliações — funcionalidade em breve",
@@ -3713,23 +3808,17 @@
3713
3808
  "current": "Skills de Instrutor"
3714
3809
  },
3715
3810
  "filters": {
3716
- "searchPlaceholder": "Buscar por slug ou nome..."
3811
+ "searchPlaceholder": "Buscar por slug..."
3717
3812
  },
3718
3813
  "table": {
3719
3814
  "slug": "Slug",
3720
- "namePt": "Nome (PT)",
3721
- "nameEn": "Nome (EN)",
3722
3815
  "status": "Status"
3723
3816
  },
3724
3817
  "form": {
3725
3818
  "slug": "Slug",
3726
3819
  "slugPlaceholder": "ex.: javascript, react-js",
3727
- "namePt": "Nome (PT)",
3728
- "namePtPlaceholder": "Nome em português",
3729
- "nameEn": "Nome (EN)",
3730
- "nameEnPlaceholder": "Nome em inglês (opcional)",
3731
3820
  "status": "Status",
3732
- "statusPlaceholder": "Selecione o status",
3821
+ "statusPlaceholder": "Selecione um status",
3733
3822
  "validation": {
3734
3823
  "required": "Obrigatório",
3735
3824
  "max100": "Máximo 100 caracteres",
@@ -3942,7 +4031,8 @@
3942
4031
  },
3943
4032
  "actions": {
3944
4033
  "create": "Criar nova turma",
3945
- "add": "Adicionar"
4034
+ "add": "Adicionar",
4035
+ "edit": "Editar"
3946
4036
  },
3947
4037
  "empty": {
3948
4038
  "title": "Nenhuma turma encontrada.",
@@ -3950,6 +4040,7 @@
3950
4040
  },
3951
4041
  "table": {
3952
4042
  "class": "Turma",
4043
+ "instructor": "Instrutor",
3953
4044
  "status": "Status",
3954
4045
  "period": "Período",
3955
4046
  "capacity": "Capacidade"
@@ -0,0 +1,30 @@
1
+ columns:
2
+ - type: pk
3
+ - name: enterprise_id
4
+ type: fk
5
+ references:
6
+ table: enterprise
7
+ column: id
8
+ onDelete: CASCADE
9
+ - name: person_id
10
+ type: fk
11
+ references:
12
+ table: person
13
+ column: id
14
+ onDelete: CASCADE
15
+ - name: event_type
16
+ type: enum
17
+ values: [assigned, revoked, status_changed]
18
+ - name: previous_status
19
+ type: varchar
20
+ length: 32
21
+ isNullable: true
22
+ - name: next_status
23
+ type: varchar
24
+ length: 32
25
+ isNullable: true
26
+ - type: created_at
27
+
28
+ indices:
29
+ - columns: [enterprise_id, created_at]
30
+ - columns: [person_id, created_at]
@@ -2,17 +2,6 @@ columns:
2
2
  - type: pk
3
3
  - name: slug
4
4
  isUnique: true
5
- - name: name
6
- type: locale_varchar
7
- locale:
8
- pt: Nome
9
- en: Name
10
- - name: description
11
- type: locale_text
12
- isNullable: true
13
- locale:
14
- pt: Descrição
15
- en: Description
16
5
  - name: status
17
6
  type: enum
18
7
  values: [active, inactive]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hed-hog/lms",
3
- "version": "0.0.331",
3
+ "version": "0.0.338",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "dependencies": {
@@ -9,15 +9,15 @@
9
9
  "@nestjs/core": "^11",
10
10
  "@nestjs/jwt": "^11",
11
11
  "@nestjs/mapped-types": "*",
12
+ "@hed-hog/api-prisma": "0.0.6",
12
13
  "@hed-hog/api-types": "0.0.1",
13
- "@hed-hog/api-locale": "0.0.14",
14
14
  "@hed-hog/api": "0.0.8",
15
- "@hed-hog/api-prisma": "0.0.6",
16
- "@hed-hog/contact": "0.0.331",
17
15
  "@hed-hog/api-pagination": "0.0.7",
18
- "@hed-hog/category": "0.0.331",
19
- "@hed-hog/finance": "0.0.331",
20
- "@hed-hog/core": "0.0.331"
16
+ "@hed-hog/api-locale": "0.0.14",
17
+ "@hed-hog/contact": "0.0.338",
18
+ "@hed-hog/category": "0.0.338",
19
+ "@hed-hog/core": "0.0.338",
20
+ "@hed-hog/finance": "0.0.338"
21
21
  },
22
22
  "exports": {
23
23
  ".": {
@@ -808,51 +808,39 @@ export class CourseService {
808
808
  id: number,
809
809
  data: PersistCourseExtrasInput,
810
810
  ) {
811
- const sets: string[] = [];
812
- const params: Array<string | boolean | number> = [];
811
+ const updateData: Record<string, string | boolean> = {};
813
812
 
814
813
  if (data.name !== undefined) {
815
- params.push(data.name);
816
- sets.push(`name = $${params.length}`);
814
+ updateData.name = data.name;
817
815
  }
818
816
 
819
817
  if (data.isFeatured !== undefined) {
820
- params.push(data.isFeatured);
821
- sets.push(`is_featured = $${params.length}`);
818
+ updateData.is_featured = data.isFeatured;
822
819
  }
823
820
 
824
821
  if (data.hasCertificate !== undefined) {
825
- params.push(data.hasCertificate);
826
- sets.push(`has_certificate = $${params.length}`);
822
+ updateData.has_certificate = data.hasCertificate;
827
823
  }
828
824
 
829
825
  if (data.isListed !== undefined) {
830
- params.push(data.isListed);
831
- sets.push(`is_listed = $${params.length}`);
826
+ updateData.is_listed = data.isListed;
832
827
  }
833
828
 
834
829
  if (data.offeringType !== undefined) {
835
- params.push(data.offeringType);
836
- sets.push(`offering_type = $${params.length}`);
830
+ updateData.offering_type = data.offeringType;
837
831
  }
838
832
 
839
- if (sets.length === 0) {
833
+ if (Object.keys(updateData).length === 0) {
840
834
  return;
841
835
  }
842
836
 
843
- params.push(id);
844
-
845
837
  try {
846
- await this.prisma.$executeRawUnsafe(
847
- `
848
- UPDATE course
849
- SET ${sets.join(', ')}, updated_at = NOW()
850
- WHERE id = $${params.length}
851
- `,
852
- ...params,
853
- );
838
+ await this.prisma.course.update({
839
+ where: { id },
840
+ data: updateData as any,
841
+ });
854
842
  } catch {
855
- // Columns may not exist yet in environments with outdated schema.
843
+ // Some environments may still be behind the current course schema.
856
844
  }
857
845
  }
858
846
 
@@ -126,6 +126,11 @@ export class EnterpriseController {
126
126
  return { profiles };
127
127
  }
128
128
 
129
+ @Get(':id/overview')
130
+ getOverview(@Param('id', ParseIntPipe) id: number) {
131
+ return this.enterpriseService.getOverview(id);
132
+ }
133
+
129
134
  @Get(':id')
130
135
  getById(@Param('id', ParseIntPipe) id: number) {
131
136
  return this.enterpriseService.getById(id);