@happyvertical/smrt-human-resources 0.0.0-stage → 0.53.6
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/AGENTS.md +297 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +7 -0
- package/README.md +291 -2
- package/dist/__smrt-register__.d.ts +2 -0
- package/dist/__smrt-register__.d.ts.map +1 -0
- package/dist/dates.d.ts +25 -0
- package/dist/dates.d.ts.map +1 -0
- package/dist/employment/index.d.ts +3 -0
- package/dist/employment/index.d.ts.map +1 -0
- package/dist/employment/models.d.ts +73 -0
- package/dist/employment/models.d.ts.map +1 -0
- package/dist/employment/queries.d.ts +12 -0
- package/dist/employment/queries.d.ts.map +1 -0
- package/dist/employment/service.d.ts +277 -0
- package/dist/employment/service.d.ts.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2068 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.json +2424 -0
- package/dist/qualifications/index.d.ts +3 -0
- package/dist/qualifications/index.d.ts.map +1 -0
- package/dist/qualifications/internal.d.ts +24 -0
- package/dist/qualifications/internal.d.ts.map +1 -0
- package/dist/qualifications/models.d.ts +77 -0
- package/dist/qualifications/models.d.ts.map +1 -0
- package/dist/qualifications/service.d.ts +381 -0
- package/dist/qualifications/service.d.ts.map +1 -0
- package/dist/service-base.d.ts +47 -0
- package/dist/service-base.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +902 -0
- package/dist/svelte/components/EmployeeForm.svelte +369 -0
- package/dist/svelte/components/EmployeeForm.svelte.d.ts +28 -0
- package/dist/svelte/components/EmployeeForm.svelte.d.ts.map +1 -0
- package/dist/svelte/components/EmployeeList.svelte +158 -0
- package/dist/svelte/components/EmployeeList.svelte.d.ts +13 -0
- package/dist/svelte/components/EmployeeList.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ExpiringQualificationsList.svelte +126 -0
- package/dist/svelte/components/ExpiringQualificationsList.svelte.d.ts +13 -0
- package/dist/svelte/components/ExpiringQualificationsList.svelte.d.ts.map +1 -0
- package/dist/svelte/components/PersonQualifications.svelte +156 -0
- package/dist/svelte/components/PersonQualifications.svelte.d.ts +15 -0
- package/dist/svelte/components/PersonQualifications.svelte.d.ts.map +1 -0
- package/dist/svelte/i18n.d.ts +67 -0
- package/dist/svelte/i18n.d.ts.map +1 -0
- package/dist/svelte/i18n.js +67 -0
- package/dist/svelte/index.d.ts +23 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +25 -0
- package/dist/svelte/types.d.ts +225 -0
- package/dist/svelte/types.d.ts.map +1 -0
- package/dist/svelte/types.js +257 -0
- package/dist/types.d.ts +119 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +23 -0
- package/dist/types.js.map +1 -0
- package/dist/ui.d.ts +17 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +65 -0
- package/dist/ui.js.map +1 -0
- package/dist/write.d.ts +22 -0
- package/dist/write.d.ts.map +1 -0
- package/package.json +86 -3
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* ExpiringQualificationsList — qualifications about to expire, across people,
|
|
4
|
+
* soonest first. Presentational: the host calls
|
|
5
|
+
* `QualificationService.expiringWithin`, adds each holder's name (HR holds no
|
|
6
|
+
* identity data) and adapts rows with `toExpiringQualificationView`.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { Button } from '@happyvertical/smrt-ui';
|
|
10
|
+
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
11
|
+
import { M } from '../i18n.js';
|
|
12
|
+
import {
|
|
13
|
+
type ExpiringQualificationView,
|
|
14
|
+
expiryDistance,
|
|
15
|
+
sortBySoonestExpiry,
|
|
16
|
+
} from '../types.js';
|
|
17
|
+
|
|
18
|
+
const { t } = useI18n();
|
|
19
|
+
|
|
20
|
+
export interface ExpiringQualificationsListProps {
|
|
21
|
+
/** Qualifications close to expiry; the list sorts them soonest first. */
|
|
22
|
+
items: ExpiringQualificationView[];
|
|
23
|
+
/** Invoked with the held-qualification id when a row is activated. */
|
|
24
|
+
onselect?: (id: string) => void;
|
|
25
|
+
/** Message shown when nothing is expiring. */
|
|
26
|
+
emptyMessage?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const { items, onselect, emptyMessage }: ExpiringQualificationsListProps =
|
|
30
|
+
$props();
|
|
31
|
+
|
|
32
|
+
const sorted = $derived(sortBySoonestExpiry(items));
|
|
33
|
+
|
|
34
|
+
function distance(daysUntilExpiry: number): string {
|
|
35
|
+
const { key, days } = expiryDistance(daysUntilExpiry);
|
|
36
|
+
return t(key, { days });
|
|
37
|
+
}
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
{#if sorted.length === 0}
|
|
41
|
+
<p class="expiring-qualifications-empty">
|
|
42
|
+
{emptyMessage ?? t(M['human_resources.expiring_qualifications_list.empty'])}
|
|
43
|
+
</p>
|
|
44
|
+
{:else}
|
|
45
|
+
<ul class="expiring-qualifications">
|
|
46
|
+
{#each sorted as item (item.id)}
|
|
47
|
+
<li class="expiring-qualification">
|
|
48
|
+
<div class="expiring-qualification-main">
|
|
49
|
+
{#if onselect}
|
|
50
|
+
<Button
|
|
51
|
+
variant="ghost"
|
|
52
|
+
size="sm"
|
|
53
|
+
onclick={() => onselect(item.id)}
|
|
54
|
+
aria-label={t(M['human_resources.expiring_qualifications_list.select_aria'], { qualification: item.qualificationName, name: item.displayName })}
|
|
55
|
+
>
|
|
56
|
+
{item.qualificationName}
|
|
57
|
+
</Button>
|
|
58
|
+
{:else}
|
|
59
|
+
<span class="expiring-qualification-name">{item.qualificationName}</span>
|
|
60
|
+
{/if}
|
|
61
|
+
<span class="expiring-qualification-person">{item.displayName}</span>
|
|
62
|
+
</div>
|
|
63
|
+
<div class="expiring-qualification-when">
|
|
64
|
+
<span class="expiring-qualification-distance">{distance(item.daysUntilExpiry)}</span>
|
|
65
|
+
<span>{t(M['human_resources.expiring_qualifications_list.expires_on'], { date: item.expiresOn })}</span>
|
|
66
|
+
</div>
|
|
67
|
+
</li>
|
|
68
|
+
{/each}
|
|
69
|
+
</ul>
|
|
70
|
+
{/if}
|
|
71
|
+
|
|
72
|
+
<style>
|
|
73
|
+
.expiring-qualifications {
|
|
74
|
+
list-style: none;
|
|
75
|
+
margin: 0;
|
|
76
|
+
padding: 0;
|
|
77
|
+
display: flex;
|
|
78
|
+
flex-direction: column;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.expiring-qualification {
|
|
82
|
+
display: flex;
|
|
83
|
+
flex-wrap: wrap;
|
|
84
|
+
align-items: center;
|
|
85
|
+
justify-content: space-between;
|
|
86
|
+
gap: 0.75rem;
|
|
87
|
+
padding: 0.5rem 0.25rem;
|
|
88
|
+
border-bottom: 1px solid var(--smrt-color-outline-variant, transparent);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.expiring-qualification:last-child {
|
|
92
|
+
border-bottom: none;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.expiring-qualification-main {
|
|
96
|
+
display: flex;
|
|
97
|
+
flex-direction: column;
|
|
98
|
+
align-items: flex-start;
|
|
99
|
+
gap: 0.125rem;
|
|
100
|
+
min-width: 0;
|
|
101
|
+
flex: 1;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.expiring-qualification-name,
|
|
105
|
+
.expiring-qualification-distance {
|
|
106
|
+
font-weight: 500;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.expiring-qualification-person,
|
|
110
|
+
.expiring-qualification-when {
|
|
111
|
+
font-size: 0.75rem;
|
|
112
|
+
color: var(--smrt-color-on-surface-variant, inherit);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.expiring-qualification-when {
|
|
116
|
+
display: flex;
|
|
117
|
+
flex-direction: column;
|
|
118
|
+
align-items: flex-end;
|
|
119
|
+
gap: 0.125rem;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.expiring-qualifications-empty {
|
|
123
|
+
color: var(--smrt-color-on-surface-variant, inherit);
|
|
124
|
+
padding: 1rem 0;
|
|
125
|
+
}
|
|
126
|
+
</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ExpiringQualificationView } from '../types.js';
|
|
2
|
+
export interface ExpiringQualificationsListProps {
|
|
3
|
+
/** Qualifications close to expiry; the list sorts them soonest first. */
|
|
4
|
+
items: ExpiringQualificationView[];
|
|
5
|
+
/** Invoked with the held-qualification id when a row is activated. */
|
|
6
|
+
onselect?: (id: string) => void;
|
|
7
|
+
/** Message shown when nothing is expiring. */
|
|
8
|
+
emptyMessage?: string;
|
|
9
|
+
}
|
|
10
|
+
declare const ExpiringQualificationsList: import("svelte").Component<ExpiringQualificationsListProps, {}, "">;
|
|
11
|
+
type ExpiringQualificationsList = ReturnType<typeof ExpiringQualificationsList>;
|
|
12
|
+
export default ExpiringQualificationsList;
|
|
13
|
+
//# sourceMappingURL=ExpiringQualificationsList.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpiringQualificationsList.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ExpiringQualificationsList.svelte.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,KAAK,yBAAyB,EAG/B,MAAM,aAAa,CAAC;AAGrB,MAAM,WAAW,+BAA+B;IAC9C,yEAAyE;IACzE,KAAK,EAAE,yBAAyB,EAAE,CAAC;IACnC,sEAAsE;IACtE,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAsDD,QAAA,MAAM,0BAA0B,qEAAwC,CAAC;AACzE,KAAK,0BAA0B,GAAG,UAAU,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAChF,eAAe,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* PersonQualifications — what one person holds, each with its expiry state.
|
|
4
|
+
* Presentational: the host calls `QualificationService.listForProfile` and
|
|
5
|
+
* adapts rows with `toPersonQualificationView`. The state is always written
|
|
6
|
+
* out as text beside the badge, never shown by colour alone.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { Button, StatusBadge } from '@happyvertical/smrt-ui';
|
|
10
|
+
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
11
|
+
import { M } from '../i18n.js';
|
|
12
|
+
import {
|
|
13
|
+
DEFAULT_EXPIRING_SOON_DAYS,
|
|
14
|
+
expiryDistance,
|
|
15
|
+
type PersonQualificationView,
|
|
16
|
+
qualificationExpiryState,
|
|
17
|
+
qualificationKindLabelKey,
|
|
18
|
+
qualificationStateBadgeKey,
|
|
19
|
+
qualificationStateLabelKey,
|
|
20
|
+
} from '../types.js';
|
|
21
|
+
|
|
22
|
+
const { t } = useI18n();
|
|
23
|
+
|
|
24
|
+
export interface PersonQualificationsProps {
|
|
25
|
+
/** The person's qualifications, in the host's order. */
|
|
26
|
+
qualifications: PersonQualificationView[];
|
|
27
|
+
/** Valid qualifications expiring within this many days are flagged. */
|
|
28
|
+
expiringSoonDays?: number;
|
|
29
|
+
/** Invoked with the held-qualification id when a name is activated. */
|
|
30
|
+
onselect?: (id: string) => void;
|
|
31
|
+
/** Message shown when the person holds nothing. */
|
|
32
|
+
emptyMessage?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const {
|
|
36
|
+
qualifications,
|
|
37
|
+
expiringSoonDays = DEFAULT_EXPIRING_SOON_DAYS,
|
|
38
|
+
onselect,
|
|
39
|
+
emptyMessage,
|
|
40
|
+
}: PersonQualificationsProps = $props();
|
|
41
|
+
|
|
42
|
+
function distance(daysUntilExpiry: number): string {
|
|
43
|
+
const { key, days } = expiryDistance(daysUntilExpiry);
|
|
44
|
+
return t(key, { days });
|
|
45
|
+
}
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
{#if qualifications.length === 0}
|
|
49
|
+
<p class="person-qualifications-empty">
|
|
50
|
+
{emptyMessage ?? t(M['human_resources.person_qualifications.empty'])}
|
|
51
|
+
</p>
|
|
52
|
+
{:else}
|
|
53
|
+
<ul class="person-qualifications">
|
|
54
|
+
{#each qualifications as qualification (qualification.id)}
|
|
55
|
+
{@const state = qualificationExpiryState(qualification, expiringSoonDays)}
|
|
56
|
+
<li class="person-qualification" data-state={state}>
|
|
57
|
+
<div class="person-qualification-main">
|
|
58
|
+
{#if onselect}
|
|
59
|
+
<Button
|
|
60
|
+
variant="ghost"
|
|
61
|
+
size="sm"
|
|
62
|
+
onclick={() => onselect(qualification.id)}
|
|
63
|
+
aria-label={t(M['human_resources.person_qualifications.select_aria'], { name: qualification.name })}
|
|
64
|
+
>
|
|
65
|
+
{qualification.name}
|
|
66
|
+
</Button>
|
|
67
|
+
{:else}
|
|
68
|
+
<span class="person-qualification-name">{qualification.name}</span>
|
|
69
|
+
{/if}
|
|
70
|
+
<span class="person-qualification-detail">
|
|
71
|
+
<span>{t(qualificationKindLabelKey(qualification.kind))}</span>
|
|
72
|
+
{#if qualification.issuingBody}
|
|
73
|
+
<span>{qualification.issuingBody}</span>
|
|
74
|
+
{/if}
|
|
75
|
+
{#if qualification.certificateNumber}
|
|
76
|
+
<span>
|
|
77
|
+
{t(M['human_resources.person_qualifications.certificate'], { certificateNumber: qualification.certificateNumber })}
|
|
78
|
+
</span>
|
|
79
|
+
{/if}
|
|
80
|
+
</span>
|
|
81
|
+
</div>
|
|
82
|
+
<div class="person-qualification-dates">
|
|
83
|
+
<span>{t(M['human_resources.person_qualifications.issued_on'], { date: qualification.issuedOn })}</span>
|
|
84
|
+
{#if qualification.expiresOn === null}
|
|
85
|
+
<span>{t(M['human_resources.person_qualifications.no_expiry'])}</span>
|
|
86
|
+
{:else}
|
|
87
|
+
<span>{t(M['human_resources.person_qualifications.expires_on'], { date: qualification.expiresOn })}</span>
|
|
88
|
+
{#if qualification.daysUntilExpiry !== null && (state === 'valid' || state === 'expiring-soon' || state === 'expired')}
|
|
89
|
+
<span class="person-qualification-distance">{distance(qualification.daysUntilExpiry)}</span>
|
|
90
|
+
{/if}
|
|
91
|
+
{/if}
|
|
92
|
+
</div>
|
|
93
|
+
<StatusBadge
|
|
94
|
+
status={qualificationStateBadgeKey(state)}
|
|
95
|
+
label={t(qualificationStateLabelKey(state))}
|
|
96
|
+
size="sm"
|
|
97
|
+
/>
|
|
98
|
+
</li>
|
|
99
|
+
{/each}
|
|
100
|
+
</ul>
|
|
101
|
+
{/if}
|
|
102
|
+
|
|
103
|
+
<style>
|
|
104
|
+
.person-qualifications {
|
|
105
|
+
list-style: none;
|
|
106
|
+
margin: 0;
|
|
107
|
+
padding: 0;
|
|
108
|
+
display: flex;
|
|
109
|
+
flex-direction: column;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.person-qualification {
|
|
113
|
+
display: flex;
|
|
114
|
+
flex-wrap: wrap;
|
|
115
|
+
align-items: center;
|
|
116
|
+
justify-content: space-between;
|
|
117
|
+
gap: 0.75rem;
|
|
118
|
+
padding: 0.5rem 0.25rem;
|
|
119
|
+
border-bottom: 1px solid var(--smrt-color-outline-variant, transparent);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.person-qualification:last-child {
|
|
123
|
+
border-bottom: none;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.person-qualification-main {
|
|
127
|
+
display: flex;
|
|
128
|
+
flex-direction: column;
|
|
129
|
+
align-items: flex-start;
|
|
130
|
+
gap: 0.125rem;
|
|
131
|
+
min-width: 0;
|
|
132
|
+
flex: 1;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.person-qualification-name {
|
|
136
|
+
font-weight: 500;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.person-qualification-detail,
|
|
140
|
+
.person-qualification-dates {
|
|
141
|
+
display: flex;
|
|
142
|
+
flex-wrap: wrap;
|
|
143
|
+
gap: 0.5rem;
|
|
144
|
+
font-size: 0.75rem;
|
|
145
|
+
color: var(--smrt-color-on-surface-variant, inherit);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.person-qualification-distance {
|
|
149
|
+
font-weight: 500;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.person-qualifications-empty {
|
|
153
|
+
color: var(--smrt-color-on-surface-variant, inherit);
|
|
154
|
+
padding: 1rem 0;
|
|
155
|
+
}
|
|
156
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type PersonQualificationView } from '../types.js';
|
|
2
|
+
export interface PersonQualificationsProps {
|
|
3
|
+
/** The person's qualifications, in the host's order. */
|
|
4
|
+
qualifications: PersonQualificationView[];
|
|
5
|
+
/** Valid qualifications expiring within this many days are flagged. */
|
|
6
|
+
expiringSoonDays?: number;
|
|
7
|
+
/** Invoked with the held-qualification id when a name is activated. */
|
|
8
|
+
onselect?: (id: string) => void;
|
|
9
|
+
/** Message shown when the person holds nothing. */
|
|
10
|
+
emptyMessage?: string;
|
|
11
|
+
}
|
|
12
|
+
declare const PersonQualifications: import("svelte").Component<PersonQualificationsProps, {}, "">;
|
|
13
|
+
type PersonQualifications = ReturnType<typeof PersonQualifications>;
|
|
14
|
+
export default PersonQualifications;
|
|
15
|
+
//# sourceMappingURL=PersonQualifications.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PersonQualifications.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/PersonQualifications.svelte.ts"],"names":[],"mappings":"AAYA,OAAO,EAGL,KAAK,uBAAuB,EAK7B,MAAM,aAAa,CAAC;AAGrB,MAAM,WAAW,yBAAyB;IACxC,wDAAwD;IACxD,cAAc,EAAE,uBAAuB,EAAE,CAAC;IAC1C,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uEAAuE;IACvE,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA2ED,QAAA,MAAM,oBAAoB,+DAAwC,CAAC;AACnE,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACpE,eAAe,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message catalog for the HR components. Keys are
|
|
3
|
+
* `human_resources.<component>.<key>`; `human_resources.expiry.*` is shared by
|
|
4
|
+
* the two qualification lists.
|
|
5
|
+
*/
|
|
6
|
+
export declare const M: {
|
|
7
|
+
readonly 'human_resources.employee_list.caption': "human_resources.employee_list.caption";
|
|
8
|
+
readonly 'human_resources.employee_list.empty': "human_resources.employee_list.empty";
|
|
9
|
+
readonly 'human_resources.employee_list.name': "human_resources.employee_list.name";
|
|
10
|
+
readonly 'human_resources.employee_list.employee_number': "human_resources.employee_list.employee_number";
|
|
11
|
+
readonly 'human_resources.employee_list.position': "human_resources.employee_list.position";
|
|
12
|
+
readonly 'human_resources.employee_list.worker_type': "human_resources.employee_list.worker_type";
|
|
13
|
+
readonly 'human_resources.employee_list.status': "human_resources.employee_list.status";
|
|
14
|
+
readonly 'human_resources.employee_list.started_on': "human_resources.employee_list.started_on";
|
|
15
|
+
readonly 'human_resources.employee_list.status_active': "human_resources.employee_list.status_active";
|
|
16
|
+
readonly 'human_resources.employee_list.status_on_leave': "human_resources.employee_list.status_on_leave";
|
|
17
|
+
readonly 'human_resources.employee_list.status_ended': "human_resources.employee_list.status_ended";
|
|
18
|
+
readonly 'human_resources.employee_list.last_day': "human_resources.employee_list.last_day";
|
|
19
|
+
readonly 'human_resources.employee_list.none': "human_resources.employee_list.none";
|
|
20
|
+
readonly 'human_resources.employee_list.select_aria': "human_resources.employee_list.select_aria";
|
|
21
|
+
readonly 'human_resources.employee_form.employee_number': "human_resources.employee_form.employee_number";
|
|
22
|
+
readonly 'human_resources.employee_form.employee_number_edit_help': "human_resources.employee_form.employee_number_edit_help";
|
|
23
|
+
readonly 'human_resources.employee_form.worker_type': "human_resources.employee_form.worker_type";
|
|
24
|
+
readonly 'human_resources.employee_form.worker_type_help': "human_resources.employee_form.worker_type_help";
|
|
25
|
+
readonly 'human_resources.employee_form.position': "human_resources.employee_form.position";
|
|
26
|
+
readonly 'human_resources.employee_form.started_on': "human_resources.employee_form.started_on";
|
|
27
|
+
readonly 'human_resources.employee_form.effective_on': "human_resources.employee_form.effective_on";
|
|
28
|
+
readonly 'human_resources.employee_form.effective_on_help': "human_resources.employee_form.effective_on_help";
|
|
29
|
+
readonly 'human_resources.employee_form.login': "human_resources.employee_form.login";
|
|
30
|
+
readonly 'human_resources.employee_form.login_help': "human_resources.employee_form.login_help";
|
|
31
|
+
readonly 'human_resources.employee_form.login_none': "human_resources.employee_form.login_none";
|
|
32
|
+
readonly 'human_resources.employee_form.login_current': "human_resources.employee_form.login_current";
|
|
33
|
+
readonly 'human_resources.employee_form.submit_hire': "human_resources.employee_form.submit_hire";
|
|
34
|
+
readonly 'human_resources.employee_form.submit_edit': "human_resources.employee_form.submit_edit";
|
|
35
|
+
readonly 'human_resources.employee_form.saving': "human_resources.employee_form.saving";
|
|
36
|
+
readonly 'human_resources.employee_form.cancel': "human_resources.employee_form.cancel";
|
|
37
|
+
readonly 'human_resources.employee_form.error_employee_number': "human_resources.employee_form.error_employee_number";
|
|
38
|
+
readonly 'human_resources.employee_form.error_worker_type': "human_resources.employee_form.error_worker_type";
|
|
39
|
+
readonly 'human_resources.employee_form.error_started_on': "human_resources.employee_form.error_started_on";
|
|
40
|
+
readonly 'human_resources.employee_form.error_effective_on': "human_resources.employee_form.error_effective_on";
|
|
41
|
+
readonly 'human_resources.person_qualifications.empty': "human_resources.person_qualifications.empty";
|
|
42
|
+
readonly 'human_resources.person_qualifications.select_aria': "human_resources.person_qualifications.select_aria";
|
|
43
|
+
readonly 'human_resources.person_qualifications.certificate': "human_resources.person_qualifications.certificate";
|
|
44
|
+
readonly 'human_resources.person_qualifications.issued_on': "human_resources.person_qualifications.issued_on";
|
|
45
|
+
readonly 'human_resources.person_qualifications.expires_on': "human_resources.person_qualifications.expires_on";
|
|
46
|
+
readonly 'human_resources.person_qualifications.no_expiry': "human_resources.person_qualifications.no_expiry";
|
|
47
|
+
readonly 'human_resources.person_qualifications.state_valid': "human_resources.person_qualifications.state_valid";
|
|
48
|
+
readonly 'human_resources.person_qualifications.state_expiring_soon': "human_resources.person_qualifications.state_expiring_soon";
|
|
49
|
+
readonly 'human_resources.person_qualifications.state_expired': "human_resources.person_qualifications.state_expired";
|
|
50
|
+
readonly 'human_resources.person_qualifications.state_suspended': "human_resources.person_qualifications.state_suspended";
|
|
51
|
+
readonly 'human_resources.person_qualifications.state_revoked': "human_resources.person_qualifications.state_revoked";
|
|
52
|
+
readonly 'human_resources.person_qualifications.state_not_yet_issued': "human_resources.person_qualifications.state_not_yet_issued";
|
|
53
|
+
readonly 'human_resources.person_qualifications.kind_ticket': "human_resources.person_qualifications.kind_ticket";
|
|
54
|
+
readonly 'human_resources.person_qualifications.kind_certification': "human_resources.person_qualifications.kind_certification";
|
|
55
|
+
readonly 'human_resources.person_qualifications.kind_authorization': "human_resources.person_qualifications.kind_authorization";
|
|
56
|
+
readonly 'human_resources.person_qualifications.kind_training': "human_resources.person_qualifications.kind_training";
|
|
57
|
+
readonly 'human_resources.person_qualifications.kind_restriction': "human_resources.person_qualifications.kind_restriction";
|
|
58
|
+
readonly 'human_resources.expiring_qualifications_list.empty': "human_resources.expiring_qualifications_list.empty";
|
|
59
|
+
readonly 'human_resources.expiring_qualifications_list.select_aria': "human_resources.expiring_qualifications_list.select_aria";
|
|
60
|
+
readonly 'human_resources.expiring_qualifications_list.expires_on': "human_resources.expiring_qualifications_list.expires_on";
|
|
61
|
+
readonly 'human_resources.expiry.today': "human_resources.expiry.today";
|
|
62
|
+
readonly 'human_resources.expiry.in_one_day': "human_resources.expiry.in_one_day";
|
|
63
|
+
readonly 'human_resources.expiry.in_days': "human_resources.expiry.in_days";
|
|
64
|
+
readonly 'human_resources.expiry.one_day_ago': "human_resources.expiry.one_day_ago";
|
|
65
|
+
readonly 'human_resources.expiry.days_ago': "human_resources.expiry.days_ago";
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=i18n.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/svelte/i18n.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,eAAO,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4EZ,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { defineMessages } from '@happyvertical/smrt-ui/i18n';
|
|
2
|
+
/**
|
|
3
|
+
* Message catalog for the HR components. Keys are
|
|
4
|
+
* `human_resources.<component>.<key>`; `human_resources.expiry.*` is shared by
|
|
5
|
+
* the two qualification lists.
|
|
6
|
+
*/
|
|
7
|
+
export const M = defineMessages({
|
|
8
|
+
'human_resources.employee_list.caption': 'Employees',
|
|
9
|
+
'human_resources.employee_list.empty': 'No employees',
|
|
10
|
+
'human_resources.employee_list.name': 'Name',
|
|
11
|
+
'human_resources.employee_list.employee_number': 'Employee number',
|
|
12
|
+
'human_resources.employee_list.position': 'Position',
|
|
13
|
+
'human_resources.employee_list.worker_type': 'Worker type',
|
|
14
|
+
'human_resources.employee_list.status': 'Status',
|
|
15
|
+
'human_resources.employee_list.started_on': 'Start date',
|
|
16
|
+
'human_resources.employee_list.status_active': 'Active',
|
|
17
|
+
'human_resources.employee_list.status_on_leave': 'On leave',
|
|
18
|
+
'human_resources.employee_list.status_ended': 'Ended',
|
|
19
|
+
'human_resources.employee_list.last_day': 'Last day {date}',
|
|
20
|
+
'human_resources.employee_list.none': 'None',
|
|
21
|
+
'human_resources.employee_list.select_aria': 'Open employee: {name}',
|
|
22
|
+
'human_resources.employee_form.employee_number': 'Employee number',
|
|
23
|
+
'human_resources.employee_form.employee_number_edit_help': 'The employee number cannot be changed.',
|
|
24
|
+
'human_resources.employee_form.worker_type': 'Worker type',
|
|
25
|
+
'human_resources.employee_form.worker_type_help': 'Pick a suggestion or enter your own: lowercase words joined by hyphens.',
|
|
26
|
+
'human_resources.employee_form.position': 'Position',
|
|
27
|
+
'human_resources.employee_form.started_on': 'Start date',
|
|
28
|
+
'human_resources.employee_form.effective_on': 'Effective date',
|
|
29
|
+
'human_resources.employee_form.effective_on_help': 'The day these changes take effect.',
|
|
30
|
+
'human_resources.employee_form.login': 'Login',
|
|
31
|
+
'human_resources.employee_form.login_help': 'Optional. A worker who signs in on a shared device may have none.',
|
|
32
|
+
'human_resources.employee_form.login_none': 'No login',
|
|
33
|
+
'human_resources.employee_form.login_current': 'Current login ({id})',
|
|
34
|
+
'human_resources.employee_form.submit_hire': 'Hire employee',
|
|
35
|
+
'human_resources.employee_form.submit_edit': 'Save changes',
|
|
36
|
+
'human_resources.employee_form.saving': 'Saving...',
|
|
37
|
+
'human_resources.employee_form.cancel': 'Cancel',
|
|
38
|
+
'human_resources.employee_form.error_employee_number': 'Enter an employee number.',
|
|
39
|
+
'human_resources.employee_form.error_worker_type': 'Enter a worker type using lowercase words joined by hyphens.',
|
|
40
|
+
'human_resources.employee_form.error_started_on': 'Enter a start date.',
|
|
41
|
+
'human_resources.employee_form.error_effective_on': 'Enter an effective date.',
|
|
42
|
+
'human_resources.person_qualifications.empty': 'No qualifications',
|
|
43
|
+
'human_resources.person_qualifications.select_aria': 'Open qualification: {name}',
|
|
44
|
+
'human_resources.person_qualifications.certificate': 'Certificate {certificateNumber}',
|
|
45
|
+
'human_resources.person_qualifications.issued_on': 'Issued {date}',
|
|
46
|
+
'human_resources.person_qualifications.expires_on': 'Expires {date}',
|
|
47
|
+
'human_resources.person_qualifications.no_expiry': 'Does not expire',
|
|
48
|
+
'human_resources.person_qualifications.state_valid': 'Valid',
|
|
49
|
+
'human_resources.person_qualifications.state_expiring_soon': 'Expiring soon',
|
|
50
|
+
'human_resources.person_qualifications.state_expired': 'Expired',
|
|
51
|
+
'human_resources.person_qualifications.state_suspended': 'Suspended',
|
|
52
|
+
'human_resources.person_qualifications.state_revoked': 'Revoked',
|
|
53
|
+
'human_resources.person_qualifications.state_not_yet_issued': 'Not yet issued',
|
|
54
|
+
'human_resources.person_qualifications.kind_ticket': 'Ticket',
|
|
55
|
+
'human_resources.person_qualifications.kind_certification': 'Certification',
|
|
56
|
+
'human_resources.person_qualifications.kind_authorization': 'Authorization',
|
|
57
|
+
'human_resources.person_qualifications.kind_training': 'Training',
|
|
58
|
+
'human_resources.person_qualifications.kind_restriction': 'Restriction',
|
|
59
|
+
'human_resources.expiring_qualifications_list.empty': 'No qualifications expiring soon',
|
|
60
|
+
'human_resources.expiring_qualifications_list.select_aria': 'Open qualification: {qualification} held by {name}',
|
|
61
|
+
'human_resources.expiring_qualifications_list.expires_on': 'Expires {date}',
|
|
62
|
+
'human_resources.expiry.today': 'Today',
|
|
63
|
+
'human_resources.expiry.in_one_day': 'In 1 day',
|
|
64
|
+
'human_resources.expiry.in_days': 'In {days} days',
|
|
65
|
+
'human_resources.expiry.one_day_ago': '1 day ago',
|
|
66
|
+
'human_resources.expiry.days_ago': '{days} days ago',
|
|
67
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @happyvertical/smrt-human-resources/svelte
|
|
3
|
+
*
|
|
4
|
+
* Props-driven Svelte 5 surfaces for HR records: an employee list, an
|
|
5
|
+
* employee form, one person's qualifications with their expiry state, and an
|
|
6
|
+
* "expiring soon" list. Hosts load data
|
|
7
|
+
* through the package services and pass plain view objects.
|
|
8
|
+
* Auto-registers components with ModuleUIRegistry on import.
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
import type { ComponentProps } from 'svelte';
|
|
13
|
+
import EmployeeForm from './components/EmployeeForm.svelte';
|
|
14
|
+
import EmployeeList from './components/EmployeeList.svelte';
|
|
15
|
+
import ExpiringQualificationsList from './components/ExpiringQualificationsList.svelte';
|
|
16
|
+
import PersonQualifications from './components/PersonQualifications.svelte';
|
|
17
|
+
export { EmployeeForm, EmployeeList, ExpiringQualificationsList, PersonQualifications, };
|
|
18
|
+
export type EmployeeFormProps = ComponentProps<typeof EmployeeForm>;
|
|
19
|
+
export type EmployeeListProps = ComponentProps<typeof EmployeeList>;
|
|
20
|
+
export type ExpiringQualificationsListProps = ComponentProps<typeof ExpiringQualificationsList>;
|
|
21
|
+
export type PersonQualificationsProps = ComponentProps<typeof PersonQualifications>;
|
|
22
|
+
export { DEFAULT_EXPIRING_SOON_DAYS, daysUntil, type EmployeeFormDraft, type EmployeeFormField, type EmployeeFormInitial, type EmployeeFormValidation, type EmployeeFormValues, type EmployeeLoginOption, type EmployeeView, type EmploymentLike, type ExpiringQualificationView, employmentStatusBadgeKey, employmentStatusLabelKey, expiryDistance, type HeldQualificationLike, isCalendarDate, isWorkerType, type PersonQualificationView, type ProfileQualificationLike, type QualificationExpiryState, type QualificationLike, type QualificationStatusOn, qualificationExpiryState, qualificationKindLabelKey, qualificationStateBadgeKey, qualificationStateLabelKey, sortBySoonestExpiry, toEmployeeFormInitial, toEmployeeView, toExpiringQualificationView, toPersonQualificationView, validateEmployeeForm, } from './types.js';
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svelte/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAE7C,OAAO,YAAY,MAAM,kCAAkC,CAAC;AAC5D,OAAO,YAAY,MAAM,kCAAkC,CAAC;AAC5D,OAAO,0BAA0B,MAAM,gDAAgD,CAAC;AACxF,OAAO,oBAAoB,MAAM,0CAA0C,CAAC;AAE5E,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,0BAA0B,EAC1B,oBAAoB,GACrB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,YAAY,CAAC,CAAC;AACpE,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,YAAY,CAAC,CAAC;AACpE,MAAM,MAAM,+BAA+B,GAAG,cAAc,CAC1D,OAAO,0BAA0B,CAClC,CAAC;AACF,MAAM,MAAM,yBAAyB,GAAG,cAAc,CACpD,OAAO,oBAAoB,CAC5B,CAAC;AAEF,OAAO,EACL,0BAA0B,EAC1B,SAAS,EACT,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,yBAAyB,EAC9B,wBAAwB,EACxB,wBAAwB,EACxB,cAAc,EACd,KAAK,qBAAqB,EAC1B,cAAc,EACd,YAAY,EACZ,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,wBAAwB,EACxB,yBAAyB,EACzB,0BAA0B,EAC1B,0BAA0B,EAC1B,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,2BAA2B,EAC3B,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @happyvertical/smrt-human-resources/svelte
|
|
3
|
+
*
|
|
4
|
+
* Props-driven Svelte 5 surfaces for HR records: an employee list, an
|
|
5
|
+
* employee form, one person's qualifications with their expiry state, and an
|
|
6
|
+
* "expiring soon" list. Hosts load data
|
|
7
|
+
* through the package services and pass plain view objects.
|
|
8
|
+
* Auto-registers components with ModuleUIRegistry on import.
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
import { ModuleUIRegistry } from '@happyvertical/smrt-ui/registry';
|
|
13
|
+
import { HUMAN_RESOURCES_MODULE_META } from '../ui.js';
|
|
14
|
+
import EmployeeForm from './components/EmployeeForm.svelte';
|
|
15
|
+
import EmployeeList from './components/EmployeeList.svelte';
|
|
16
|
+
import ExpiringQualificationsList from './components/ExpiringQualificationsList.svelte';
|
|
17
|
+
import PersonQualifications from './components/PersonQualifications.svelte';
|
|
18
|
+
export { EmployeeForm, EmployeeList, ExpiringQualificationsList, PersonQualifications, };
|
|
19
|
+
export { DEFAULT_EXPIRING_SOON_DAYS, daysUntil, employmentStatusBadgeKey, employmentStatusLabelKey, expiryDistance, isCalendarDate, isWorkerType, qualificationExpiryState, qualificationKindLabelKey, qualificationStateBadgeKey, qualificationStateLabelKey, sortBySoonestExpiry, toEmployeeFormInitial, toEmployeeView, toExpiringQualificationView, toPersonQualificationView, validateEmployeeForm, } from './types.js';
|
|
20
|
+
// Auto-register with ModuleUIRegistry
|
|
21
|
+
ModuleUIRegistry.registerModule(HUMAN_RESOURCES_MODULE_META);
|
|
22
|
+
ModuleUIRegistry.register('@happyvertical/smrt-human-resources', 'employee-list', EmployeeList);
|
|
23
|
+
ModuleUIRegistry.register('@happyvertical/smrt-human-resources', 'employee-form', EmployeeForm);
|
|
24
|
+
ModuleUIRegistry.register('@happyvertical/smrt-human-resources', 'person-qualifications', PersonQualifications);
|
|
25
|
+
ModuleUIRegistry.register('@happyvertical/smrt-human-resources', 'expiring-qualifications-list', ExpiringQualificationsList);
|