@hed-hog/lms 0.0.328 → 0.0.330
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/instructor/instructor.service.d.ts.map +1 -1
- package/dist/instructor/instructor.service.js +22 -16
- package/dist/instructor/instructor.service.js.map +1 -1
- package/hedhog/frontend/app/_components/class-form-sheet.tsx.ejs +18 -8
- package/hedhog/frontend/app/_components/course-form-sheet.tsx.ejs +7 -5
- package/hedhog/frontend/app/_components/create-lms-person-sheet.tsx.ejs +5 -9
- package/hedhog/frontend/app/_components/create-lms-student-person-sheet.tsx.ejs +5 -9
- package/hedhog/frontend/app/certificates/models/LeftPanel.tsx.ejs +15 -14
- package/hedhog/frontend/app/certificates/models/RightPanel.tsx.ejs +66 -29
- package/hedhog/frontend/app/certificates/models/TemplateEditorPage.tsx.ejs +4 -2
- package/hedhog/frontend/app/certificates/models/TopBar.tsx.ejs +44 -34
- package/hedhog/frontend/app/classes/[id]/page.tsx.ejs +10 -10
- package/hedhog/frontend/app/classes/page.tsx.ejs +23 -15
- package/hedhog/frontend/app/courses/[id]/page.tsx.ejs +5 -3
- package/hedhog/frontend/app/courses/[id]/structure/_components/confirm-dialog.tsx.ejs +5 -3
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-panel.tsx.ejs +9 -7
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-skeleton.tsx.ejs +3 -1
- package/hedhog/frontend/app/courses/[id]/structure/_components/drag-handle.tsx.ejs +4 -2
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-bulk.tsx.ejs +24 -23
- package/hedhog/frontend/app/courses/[id]/structure/_components/multi-select-bar.tsx.ejs +21 -19
- package/hedhog/frontend/app/courses/[id]/structure/_components/shortcuts-help.tsx.ejs +7 -5
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-display-settings-popover.tsx.ejs +18 -16
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-lesson.tsx.ejs +13 -11
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-session.tsx.ejs +5 -3
- package/hedhog/frontend/app/courses/[id]/structure/_components/use-course-structure-shortcuts.ts.ejs +14 -9
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure-mutations.ts.ejs +42 -25
- package/hedhog/frontend/app/enterprise/_components/enterprise-admin-create-sheet.tsx.ejs +3 -1
- package/hedhog/frontend/app/enterprise/_components/enterprise-administrators-tab.tsx.ejs +10 -8
- package/hedhog/frontend/app/enterprise/_components/enterprise-classes-tab.tsx.ejs +22 -20
- package/hedhog/frontend/app/enterprise/_components/enterprise-course-create-sheet.tsx.ejs +3 -3
- package/hedhog/frontend/app/enterprise/_components/enterprise-courses-tab.tsx.ejs +21 -19
- package/hedhog/frontend/app/enterprise/_components/enterprise-sheet.tsx.ejs +34 -36
- package/hedhog/frontend/app/enterprise/_components/enterprise-student-create-sheet.tsx.ejs +3 -1
- package/hedhog/frontend/app/enterprise/_components/enterprise-students-tab.tsx.ejs +7 -5
- package/hedhog/frontend/app/enterprise/page.tsx.ejs +106 -54
- package/hedhog/frontend/app/instructor-skills/page.tsx.ejs +79 -59
- package/hedhog/frontend/app/instructors/_components/instructor-form-sheet.tsx.ejs +92 -26
- package/hedhog/frontend/app/instructors/page.tsx.ejs +4 -2
- package/hedhog/frontend/messages/en.json +619 -13
- package/hedhog/frontend/messages/pt.json +619 -13
- package/package.json +7 -7
- package/src/instructor/instructor.service.ts +22 -19
- package/hedhog/frontend/app/_components/create-lms-instructor-sheet.tsx.ejs +0 -591
- package/hedhog/frontend/app/courses/[id]/_components/CourseMainInfoCard.tsx.ejs +0 -109
- package/hedhog/frontend/app/courses/[id]/_components/CourseSummaryCard.tsx.ejs +0 -60
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree.tsx.ejs +0 -134
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-course.tsx.ejs +0 -113
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson.tsx.ejs +0 -314
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-session.tsx.ejs +0 -174
- package/hedhog/frontend/app/courses/[id]/structure/_components/mock-data.ts.ejs +0 -185
- package/hedhog/frontend/app/enterprise/_components/enterprise-mocks.ts.ejs +0 -277
- package/hedhog/frontend/app/enterprise/_components/enterprise-user-create-sheet.tsx.ejs +0 -207
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
SquareArrowOutUpRight,
|
|
45
45
|
Users,
|
|
46
46
|
} from 'lucide-react';
|
|
47
|
+
import { useTranslations } from 'next-intl';
|
|
47
48
|
import { useMemo, useState } from 'react';
|
|
48
49
|
import { EnterpriseDetailSheet } from './_components/enterprise-detail-sheet';
|
|
49
50
|
import { EnterpriseSheet } from './_components/enterprise-sheet';
|
|
@@ -69,16 +70,10 @@ const STATUS_VARIANT: Record<
|
|
|
69
70
|
suspended: 'destructive',
|
|
70
71
|
};
|
|
71
72
|
|
|
72
|
-
const STATUS_LABEL: Record<EnterpriseStatus, string> = {
|
|
73
|
-
active: 'Active',
|
|
74
|
-
trial: 'Trial',
|
|
75
|
-
inactive: 'Inactive',
|
|
76
|
-
suspended: 'Suspended',
|
|
77
|
-
};
|
|
78
|
-
|
|
79
73
|
// ── Page ──────────────────────────────────────────────────────────────────────
|
|
80
74
|
|
|
81
75
|
export default function EnterprisePage() {
|
|
76
|
+
const t = useTranslations('lms.EnterprisePage');
|
|
82
77
|
const [search, setSearch] = useState('');
|
|
83
78
|
const [statusFilter, setStatusFilter] = useState('all');
|
|
84
79
|
const [crmFilter, setCrmFilter] = useState('all');
|
|
@@ -205,42 +200,48 @@ export default function EnterprisePage() {
|
|
|
205
200
|
return [
|
|
206
201
|
{
|
|
207
202
|
key: 'total',
|
|
208
|
-
title: '
|
|
203
|
+
title: t('kpis.total.label'),
|
|
209
204
|
value: total,
|
|
210
|
-
description: '
|
|
205
|
+
description: t('kpis.total.description'),
|
|
211
206
|
icon: Building2,
|
|
212
207
|
accentClassName: 'from-slate-500/20 via-slate-400/10 to-transparent',
|
|
213
208
|
iconContainerClassName: 'bg-slate-100 text-slate-700',
|
|
214
209
|
},
|
|
215
210
|
{
|
|
216
211
|
key: 'active',
|
|
217
|
-
title: '
|
|
212
|
+
title: t('kpis.active.label'),
|
|
218
213
|
value: active,
|
|
219
|
-
description: '
|
|
214
|
+
description: t('kpis.active.description'),
|
|
220
215
|
icon: Users,
|
|
221
216
|
accentClassName: 'from-green-500/20 via-emerald-500/10 to-transparent',
|
|
222
217
|
iconContainerClassName: 'bg-green-50 text-green-600',
|
|
223
218
|
},
|
|
224
219
|
{
|
|
225
220
|
key: 'trial',
|
|
226
|
-
title: 'Trial',
|
|
221
|
+
title: t.has('kpis.trial.label') ? t('kpis.trial.label') : 'Trial',
|
|
227
222
|
value: trial,
|
|
228
|
-
description: '
|
|
223
|
+
description: t.has('kpis.trial.description')
|
|
224
|
+
? t('kpis.trial.description')
|
|
225
|
+
: 'In trial period',
|
|
229
226
|
icon: CalendarDays,
|
|
230
227
|
accentClassName: 'from-amber-500/20 via-orange-500/10 to-transparent',
|
|
231
228
|
iconContainerClassName: 'bg-amber-50 text-amber-600',
|
|
232
229
|
},
|
|
233
230
|
{
|
|
234
231
|
key: 'portal',
|
|
235
|
-
title: '
|
|
232
|
+
title: t.has('kpis.portal.label')
|
|
233
|
+
? t('kpis.portal.label')
|
|
234
|
+
: 'Portal Enabled',
|
|
236
235
|
value: withPortal,
|
|
237
|
-
description: '
|
|
236
|
+
description: t.has('kpis.portal.description')
|
|
237
|
+
? t('kpis.portal.description')
|
|
238
|
+
: 'Self-service portal access',
|
|
238
239
|
icon: Globe,
|
|
239
240
|
accentClassName: 'from-blue-500/20 via-cyan-500/10 to-transparent',
|
|
240
241
|
iconContainerClassName: 'bg-blue-50 text-blue-600',
|
|
241
242
|
},
|
|
242
243
|
];
|
|
243
|
-
}, [stats]);
|
|
244
|
+
}, [stats, t]);
|
|
244
245
|
|
|
245
246
|
const accounts = enterpriseList?.data ?? [];
|
|
246
247
|
const totalItems = enterpriseList?.total ?? 0;
|
|
@@ -271,11 +272,19 @@ export default function EnterprisePage() {
|
|
|
271
272
|
value: statusFilter,
|
|
272
273
|
onChange: handleStatusFilter,
|
|
273
274
|
options: [
|
|
274
|
-
{ value: 'all', label: '
|
|
275
|
-
{ value: 'active', label: '
|
|
276
|
-
{
|
|
277
|
-
|
|
278
|
-
|
|
275
|
+
{ value: 'all', label: t('filters.allStatuses') },
|
|
276
|
+
{ value: 'active', label: t('status.active') },
|
|
277
|
+
{
|
|
278
|
+
value: 'trial',
|
|
279
|
+
label: t.has('status.trial') ? t('status.trial') : 'Trial',
|
|
280
|
+
},
|
|
281
|
+
{ value: 'inactive', label: t('status.inactive') },
|
|
282
|
+
{
|
|
283
|
+
value: 'suspended',
|
|
284
|
+
label: t.has('status.suspended')
|
|
285
|
+
? t('status.suspended')
|
|
286
|
+
: 'Suspended',
|
|
287
|
+
},
|
|
279
288
|
],
|
|
280
289
|
},
|
|
281
290
|
{
|
|
@@ -283,7 +292,15 @@ export default function EnterprisePage() {
|
|
|
283
292
|
type: 'select',
|
|
284
293
|
value: crmFilter,
|
|
285
294
|
onChange: handleCrmFilter,
|
|
286
|
-
options: [
|
|
295
|
+
options: [
|
|
296
|
+
{
|
|
297
|
+
value: 'all',
|
|
298
|
+
label: t.has('filters.allCrmAccounts')
|
|
299
|
+
? t('filters.allCrmAccounts')
|
|
300
|
+
: 'All CRM accounts',
|
|
301
|
+
},
|
|
302
|
+
...crmOptions,
|
|
303
|
+
],
|
|
287
304
|
// options populated from API
|
|
288
305
|
},
|
|
289
306
|
];
|
|
@@ -291,14 +308,16 @@ export default function EnterprisePage() {
|
|
|
291
308
|
return (
|
|
292
309
|
<Page>
|
|
293
310
|
<PageHeader
|
|
311
|
+
title={t('title')}
|
|
312
|
+
description={t('description')}
|
|
294
313
|
breadcrumbs={[
|
|
295
|
-
{ label: '
|
|
296
|
-
{ label: '
|
|
297
|
-
{ label: '
|
|
314
|
+
{ label: t('breadcrumbs.home'), href: '/' },
|
|
315
|
+
{ label: t('breadcrumbs.lms'), href: '/lms' },
|
|
316
|
+
{ label: t('breadcrumbs.enterprise') },
|
|
298
317
|
]}
|
|
299
318
|
actions={[
|
|
300
319
|
{
|
|
301
|
-
label: '
|
|
320
|
+
label: t('actions.new'),
|
|
302
321
|
onClick: handleOpenCreate,
|
|
303
322
|
icon: <Plus className="h-4 w-4" />,
|
|
304
323
|
variant: 'default',
|
|
@@ -314,13 +333,13 @@ export default function EnterprisePage() {
|
|
|
314
333
|
searchQuery={search}
|
|
315
334
|
onSearchChange={handleSearch}
|
|
316
335
|
onSearch={() => {}}
|
|
317
|
-
placeholder=
|
|
336
|
+
placeholder={t('filters.searchPlaceholder')}
|
|
318
337
|
controls={controls}
|
|
319
338
|
/>
|
|
320
339
|
</div>
|
|
321
340
|
<div className="flex items-center gap-3">
|
|
322
341
|
<span className="text-xs font-medium text-muted-foreground">
|
|
323
|
-
View
|
|
342
|
+
{t.has('view.label') ? t('view.label') : 'View'}
|
|
324
343
|
</span>
|
|
325
344
|
<ToggleGroup
|
|
326
345
|
type="single"
|
|
@@ -328,15 +347,23 @@ export default function EnterprisePage() {
|
|
|
328
347
|
onValueChange={handleViewModeChange}
|
|
329
348
|
variant="outline"
|
|
330
349
|
size="sm"
|
|
331
|
-
aria-label=
|
|
350
|
+
aria-label={
|
|
351
|
+
t.has('view.modeAriaLabel')
|
|
352
|
+
? t('view.modeAriaLabel')
|
|
353
|
+
: 'View mode'
|
|
354
|
+
}
|
|
332
355
|
>
|
|
333
356
|
<ToggleGroupItem value="table" className="gap-1.5 px-2.5">
|
|
334
357
|
<List className="h-4 w-4" />
|
|
335
|
-
<span className="hidden sm:inline">
|
|
358
|
+
<span className="hidden sm:inline">
|
|
359
|
+
{t.has('view.table') ? t('view.table') : 'Table'}
|
|
360
|
+
</span>
|
|
336
361
|
</ToggleGroupItem>
|
|
337
362
|
<ToggleGroupItem value="cards" className="gap-1.5 px-2.5">
|
|
338
363
|
<LayoutGrid className="h-4 w-4" />
|
|
339
|
-
<span className="hidden sm:inline">
|
|
364
|
+
<span className="hidden sm:inline">
|
|
365
|
+
{t.has('view.cards') ? t('view.cards') : 'Cards'}
|
|
366
|
+
</span>
|
|
340
367
|
</ToggleGroupItem>
|
|
341
368
|
</ToggleGroup>
|
|
342
369
|
</div>
|
|
@@ -345,9 +372,9 @@ export default function EnterprisePage() {
|
|
|
345
372
|
{accounts.length === 0 && !isLoading ? (
|
|
346
373
|
<EmptyState
|
|
347
374
|
icon={<Building2 className="h-10 w-10" />}
|
|
348
|
-
title=
|
|
349
|
-
description=
|
|
350
|
-
actionLabel=
|
|
375
|
+
title={t('empty.title')}
|
|
376
|
+
description={t('empty.description')}
|
|
377
|
+
actionLabel={t('actions.new')}
|
|
351
378
|
onAction={handleOpenCreate}
|
|
352
379
|
actionIcon={<Plus className="h-4 w-4" />}
|
|
353
380
|
/>
|
|
@@ -356,13 +383,25 @@ export default function EnterprisePage() {
|
|
|
356
383
|
<Table>
|
|
357
384
|
<TableHeader>
|
|
358
385
|
<TableRow>
|
|
359
|
-
<TableHead>
|
|
360
|
-
<TableHead>
|
|
361
|
-
<TableHead>
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
386
|
+
<TableHead>{t('table.name')}</TableHead>
|
|
387
|
+
<TableHead>{t('table.status')}</TableHead>
|
|
388
|
+
<TableHead>
|
|
389
|
+
{t.has('table.crmAccount')
|
|
390
|
+
? t('table.crmAccount')
|
|
391
|
+
: 'CRM Account'}
|
|
392
|
+
</TableHead>
|
|
393
|
+
<TableHead className="text-center">
|
|
394
|
+
{t.has('table.classes') ? t('table.classes') : 'Classes'}
|
|
395
|
+
</TableHead>
|
|
396
|
+
<TableHead className="text-center">
|
|
397
|
+
{t('table.activeCourses')}
|
|
398
|
+
</TableHead>
|
|
399
|
+
<TableHead className="text-center">
|
|
400
|
+
{t.has('table.users') ? t('table.users') : 'Users'}
|
|
401
|
+
</TableHead>
|
|
402
|
+
<TableHead>
|
|
403
|
+
{t.has('table.updated') ? t('table.updated') : 'Updated'}
|
|
404
|
+
</TableHead>
|
|
366
405
|
<TableHead className="w-10" />
|
|
367
406
|
</TableRow>
|
|
368
407
|
</TableHeader>
|
|
@@ -381,14 +420,20 @@ export default function EnterprisePage() {
|
|
|
381
420
|
<>
|
|
382
421
|
<span className="opacity-30">·</span>
|
|
383
422
|
<Globe className="h-3 w-3 text-primary/60" />
|
|
384
|
-
<span className="text-primary/70">
|
|
423
|
+
<span className="text-primary/70">
|
|
424
|
+
{t.has('labels.portal')
|
|
425
|
+
? t('labels.portal')
|
|
426
|
+
: 'Portal'}
|
|
427
|
+
</span>
|
|
385
428
|
</>
|
|
386
429
|
)}
|
|
387
430
|
</p>
|
|
388
431
|
</TableCell>
|
|
389
432
|
<TableCell>
|
|
390
433
|
<Badge variant={STATUS_VARIANT[account.status]}>
|
|
391
|
-
{
|
|
434
|
+
{t.has(`status.${account.status}`)
|
|
435
|
+
? t(`status.${account.status}`)
|
|
436
|
+
: account.status}
|
|
392
437
|
</Badge>
|
|
393
438
|
</TableCell>
|
|
394
439
|
<TableCell className="text-sm text-muted-foreground">
|
|
@@ -422,14 +467,14 @@ export default function EnterprisePage() {
|
|
|
422
467
|
onClick={() => handleViewDetails(account)}
|
|
423
468
|
>
|
|
424
469
|
<SquareArrowOutUpRight className="mr-2 h-4 w-4" />
|
|
425
|
-
|
|
470
|
+
{t('actions.view')}
|
|
426
471
|
</DropdownMenuItem>
|
|
427
472
|
<DropdownMenuSeparator />
|
|
428
473
|
<DropdownMenuItem
|
|
429
474
|
onClick={() => handleOpenEdit(account)}
|
|
430
475
|
>
|
|
431
476
|
<Pencil className="mr-2 h-4 w-4" />
|
|
432
|
-
|
|
477
|
+
{t('actions.edit')}
|
|
433
478
|
</DropdownMenuItem>
|
|
434
479
|
</DropdownMenuContent>
|
|
435
480
|
</DropdownMenu>
|
|
@@ -453,7 +498,9 @@ export default function EnterprisePage() {
|
|
|
453
498
|
<div className="min-w-0 flex-1">
|
|
454
499
|
<div className="mb-1 flex flex-wrap items-center gap-1.5">
|
|
455
500
|
<Badge variant={STATUS_VARIANT[account.status]}>
|
|
456
|
-
{
|
|
501
|
+
{t.has(`status.${account.status}`)
|
|
502
|
+
? t(`status.${account.status}`)
|
|
503
|
+
: account.status}
|
|
457
504
|
</Badge>
|
|
458
505
|
{account.portalEnabled && (
|
|
459
506
|
<Badge
|
|
@@ -461,7 +508,9 @@ export default function EnterprisePage() {
|
|
|
461
508
|
className="border-blue-500/20 bg-blue-500/10 px-1.5 text-blue-600"
|
|
462
509
|
>
|
|
463
510
|
<Globe className="mr-1 h-3 w-3" />
|
|
464
|
-
|
|
511
|
+
{t.has('labels.portal')
|
|
512
|
+
? t('labels.portal')
|
|
513
|
+
: 'Portal'}
|
|
465
514
|
</Badge>
|
|
466
515
|
)}
|
|
467
516
|
</div>
|
|
@@ -491,14 +540,14 @@ export default function EnterprisePage() {
|
|
|
491
540
|
onClick={() => handleViewDetails(account)}
|
|
492
541
|
>
|
|
493
542
|
<SquareArrowOutUpRight className="mr-2 h-4 w-4" />
|
|
494
|
-
|
|
543
|
+
{t('actions.view')}
|
|
495
544
|
</DropdownMenuItem>
|
|
496
545
|
<DropdownMenuSeparator />
|
|
497
546
|
<DropdownMenuItem
|
|
498
547
|
onClick={() => handleOpenEdit(account)}
|
|
499
548
|
>
|
|
500
549
|
<Pencil className="mr-2 h-4 w-4" />
|
|
501
|
-
|
|
550
|
+
{t('actions.edit')}
|
|
502
551
|
</DropdownMenuItem>
|
|
503
552
|
</DropdownMenuContent>
|
|
504
553
|
</DropdownMenu>
|
|
@@ -508,7 +557,9 @@ export default function EnterprisePage() {
|
|
|
508
557
|
{/* CRM */}
|
|
509
558
|
{account.crmAccountName && (
|
|
510
559
|
<p className="truncate text-xs text-muted-foreground">
|
|
511
|
-
<span className="font-medium">
|
|
560
|
+
<span className="font-medium">
|
|
561
|
+
{t.has('labels.crm') ? t('labels.crm') : 'CRM'}:
|
|
562
|
+
</span>{' '}
|
|
512
563
|
{account.crmAccountName}
|
|
513
564
|
</p>
|
|
514
565
|
)}
|
|
@@ -521,7 +572,7 @@ export default function EnterprisePage() {
|
|
|
521
572
|
{account.classesCount}
|
|
522
573
|
</span>
|
|
523
574
|
<span className="text-[10px] text-muted-foreground">
|
|
524
|
-
Classes
|
|
575
|
+
{t.has('table.classes') ? t('table.classes') : 'Classes'}
|
|
525
576
|
</span>
|
|
526
577
|
</div>
|
|
527
578
|
<div className="flex flex-col py-2">
|
|
@@ -530,7 +581,7 @@ export default function EnterprisePage() {
|
|
|
530
581
|
{account.coursesCount}
|
|
531
582
|
</span>
|
|
532
583
|
<span className="text-[10px] text-muted-foreground">
|
|
533
|
-
|
|
584
|
+
{t('table.activeCourses')}
|
|
534
585
|
</span>
|
|
535
586
|
</div>
|
|
536
587
|
<div className="flex flex-col py-2">
|
|
@@ -539,14 +590,15 @@ export default function EnterprisePage() {
|
|
|
539
590
|
{account.usersCount}
|
|
540
591
|
</span>
|
|
541
592
|
<span className="text-[10px] text-muted-foreground">
|
|
542
|
-
Users
|
|
593
|
+
{t.has('table.users') ? t('table.users') : 'Users'}
|
|
543
594
|
</span>
|
|
544
595
|
</div>
|
|
545
596
|
</div>
|
|
546
597
|
|
|
547
598
|
{/* Footer */}
|
|
548
599
|
<p className="text-right text-[10px] text-muted-foreground/60">
|
|
549
|
-
|
|
600
|
+
{(t.has('labels.updated') ? t('labels.updated') : 'Updated') +
|
|
601
|
+
' '}
|
|
550
602
|
{formatDate(
|
|
551
603
|
account.updatedAt,
|
|
552
604
|
getSettingValue,
|