@codihaus/odp-app-hr 0.1.0

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 (192) hide show
  1. package/app/components/hr/contact/tab.vue +238 -0
  2. package/app/components/hr/department/card.vue +141 -0
  3. package/app/components/hr/department/form-modal.vue +90 -0
  4. package/app/components/hr/employees/assets/tab.vue +432 -0
  5. package/app/components/hr/employees/compensation.vue +136 -0
  6. package/app/components/hr/employees/contract.vue +77 -0
  7. package/app/components/hr/employees/insurance.vue +164 -0
  8. package/app/components/hr/employees/leave/tab.vue +180 -0
  9. package/app/components/hr/employees/provisioning/form-modal.vue +219 -0
  10. package/app/components/hr/employees/provisioning/tab.vue +187 -0
  11. package/app/components/hr/employees/tab.vue +38 -0
  12. package/app/components/hr/leave/calendar-tab.vue +649 -0
  13. package/app/components/hr/leave/override-modal.vue +62 -0
  14. package/app/components/hr/leave/request-modal.vue +185 -0
  15. package/app/components/hr/leave/requests-tab.vue +289 -0
  16. package/app/components/hr/leave/timeline-tab.vue +259 -0
  17. package/app/components/hr/offboarding/tab.vue +303 -0
  18. package/app/components/hr/person/activity/tab.vue +65 -0
  19. package/app/components/hr/person/activity/timeline.vue +119 -0
  20. package/app/components/hr/person/detail.vue +303 -0
  21. package/app/components/hr/person/document/tab-documents.vue +120 -0
  22. package/app/components/hr/person/document/template-edit-drawer.vue +215 -0
  23. package/app/components/hr/person/document/template-preview-card.vue +39 -0
  24. package/app/components/hr/person/document/trigger-modal.vue +121 -0
  25. package/app/components/hr/person/employee-form-modal.vue +78 -0
  26. package/app/components/hr/person/form-modal.vue +78 -0
  27. package/app/components/hr/person/list-row.vue +40 -0
  28. package/app/components/hr/person/profile/tab.vue +231 -0
  29. package/app/components/hr/settings/automation.vue +113 -0
  30. package/app/components/hr/settings/documents.vue +200 -0
  31. package/app/components/hr/settings/general.vue +87 -0
  32. package/app/components/hr/settings/holidays.vue +171 -0
  33. package/app/components/hr/settings/integrations.vue +185 -0
  34. package/app/components/hr/settings/policies.vue +83 -0
  35. package/app/components/hr/settings/policy/benefit-override-modal.vue +59 -0
  36. package/app/components/hr/settings/policy/editor-eligibility.vue +27 -0
  37. package/app/components/hr/settings/policy/editor-leave-base.vue +37 -0
  38. package/app/components/hr/settings/policy/editor-tenure-bonus.vue +61 -0
  39. package/app/components/hr/settings/recruitment.vue +128 -0
  40. package/app/components/hr/settings/taxonomies.vue +170 -0
  41. package/app/components/hr/shared/row.vue +21 -0
  42. package/app/components/hr/shared/section.vue +20 -0
  43. package/app/components/hr/shared/source-badge.vue +42 -0
  44. package/app/components/hr/shared/stage-badge.vue +24 -0
  45. package/app/components/hr/shared/workflow-timeline.vue +27 -0
  46. package/app/components/hr/talents/app-sidebar.vue +54 -0
  47. package/app/components/hr/talents/application-form-modal.vue +114 -0
  48. package/app/components/hr/talents/pipeline-picker.vue +56 -0
  49. package/app/components/hr/talents/step-detail.vue +133 -0
  50. package/app/components/hr/talents/step-stepper.vue +85 -0
  51. package/app/components/hr/talents/tab.vue +263 -0
  52. package/app/composables/use-departments.ts +59 -0
  53. package/app/composables/use-employee-detail.ts +24 -0
  54. package/app/composables/use-holidays.ts +48 -0
  55. package/app/composables/use-hr-api.ts +210 -0
  56. package/app/composables/use-hr-field-registry.ts +76 -0
  57. package/app/composables/use-hr-policies.ts +66 -0
  58. package/app/composables/use-hr-settings.ts +118 -0
  59. package/app/composables/use-leave.ts +71 -0
  60. package/app/composables/use-offboarding.ts +49 -0
  61. package/app/composables/use-people.ts +149 -0
  62. package/app/composables/use-providers.ts +44 -0
  63. package/app/composables/use-recruitment-workflow.ts +173 -0
  64. package/app/composables/use-templates.ts +44 -0
  65. package/app/composables/use-triggers.ts +26 -0
  66. package/app/config/column-renderers.ts +4 -0
  67. package/app/config/form-layouts.ts +193 -0
  68. package/app/data/hr-schema.ts +2608 -0
  69. package/app/lib/policy-engine.ts +116 -0
  70. package/app/pages/hr/departments.vue +114 -0
  71. package/app/pages/hr/employees/[id]/activity.vue +10 -0
  72. package/app/pages/hr/employees/[id]/assets.vue +14 -0
  73. package/app/pages/hr/employees/[id]/employment.vue +14 -0
  74. package/app/pages/hr/employees/[id]/index.vue +9 -0
  75. package/app/pages/hr/employees/[id]/offboarding.vue +7 -0
  76. package/app/pages/hr/employees/[id]/profile.vue +11 -0
  77. package/app/pages/hr/employees/[id]/provisioning.vue +17 -0
  78. package/app/pages/hr/employees/[id].vue +313 -0
  79. package/app/pages/hr/employees/index.vue +291 -0
  80. package/app/pages/hr/index.vue +3 -0
  81. package/app/pages/hr/leave.vue +79 -0
  82. package/app/pages/hr/settings.vue +43 -0
  83. package/app/pages/hr/setup.vue +3 -0
  84. package/app/pages/hr/talents/[id]/interview/[stepId].vue +231 -0
  85. package/app/pages/hr/talents/[id].vue +52 -0
  86. package/app/pages/hr/talents/index.vue +224 -0
  87. package/app/pages/hr.vue +129 -0
  88. package/app/plugins/hr-contacts-sync.client.ts +3 -0
  89. package/app/plugins/hr-extensions.ts +36 -0
  90. package/app/plugins/hr-setup.ts +5 -0
  91. package/app/plugins/navigations.ts +22 -0
  92. package/app/utils/hr-permissions.ts +27 -0
  93. package/app/utils/hr-policy-seed-step.ts +110 -0
  94. package/i18n/locales/en.json +726 -0
  95. package/i18n/locales/vi.json +688 -0
  96. package/nuxt.config.ts +19 -0
  97. package/package.json +27 -0
  98. package/server/api/hr/departments/[id].delete.ts +12 -0
  99. package/server/api/hr/departments/[id].patch.ts +14 -0
  100. package/server/api/hr/departments/index.get.ts +11 -0
  101. package/server/api/hr/departments/index.post.ts +13 -0
  102. package/server/api/hr/documents/templates/[id]/preview.post.ts +16 -0
  103. package/server/api/hr/documents/templates/[id].delete.ts +14 -0
  104. package/server/api/hr/documents/templates/[id].patch.ts +16 -0
  105. package/server/api/hr/documents/templates/index.get.ts +15 -0
  106. package/server/api/hr/documents/templates/index.post.ts +15 -0
  107. package/server/api/hr/documents/triggers/[id].patch.ts +16 -0
  108. package/server/api/hr/documents/triggers/index.get.ts +13 -0
  109. package/server/api/hr/fields/[collection].get.ts +14 -0
  110. package/server/api/hr/holidays/[id].delete.ts +14 -0
  111. package/server/api/hr/holidays/[id].patch.ts +16 -0
  112. package/server/api/hr/holidays/copy.post.ts +15 -0
  113. package/server/api/hr/holidays/index.get.ts +15 -0
  114. package/server/api/hr/holidays/index.post.ts +15 -0
  115. package/server/api/hr/leave/requests/[id].patch.ts +22 -0
  116. package/server/api/hr/leave/requests.get.ts +15 -0
  117. package/server/api/hr/leave/types.get.ts +13 -0
  118. package/server/api/hr/offboarding/[id]/cancel.post.ts +8 -0
  119. package/server/api/hr/offboarding/[id]/deprovision.post.ts +8 -0
  120. package/server/api/hr/offboarding/[id]/finalize.post.ts +8 -0
  121. package/server/api/hr/offboarding/[id]/return-assets.post.ts +8 -0
  122. package/server/api/hr/offboarding/[id]/settlement.get.ts +8 -0
  123. package/server/api/hr/offboarding/[id]/tasks/[taskId].patch.ts +10 -0
  124. package/server/api/hr/offboarding/[id].get.ts +8 -0
  125. package/server/api/hr/offboarding/[id].patch.ts +9 -0
  126. package/server/api/hr/offboarding/index.get.ts +7 -0
  127. package/server/api/hr/people/[id]/applications/[appId]/interviews/[iid].delete.ts +16 -0
  128. package/server/api/hr/people/[id]/applications/[appId]/interviews/[iid].patch.ts +18 -0
  129. package/server/api/hr/people/[id]/applications/[appId]/interviews/index.get.ts +15 -0
  130. package/server/api/hr/people/[id]/applications/[appId]/interviews/index.post.ts +17 -0
  131. package/server/api/hr/people/[id]/applications/[appId].patch.ts +17 -0
  132. package/server/api/hr/people/[id]/applications/index.get.ts +14 -0
  133. package/server/api/hr/people/[id]/applications/index.post.ts +16 -0
  134. package/server/api/hr/people/[id]/assets/[aid].delete.ts +13 -0
  135. package/server/api/hr/people/[id]/assets/[aid].patch.ts +15 -0
  136. package/server/api/hr/people/[id]/assets/index.get.ts +12 -0
  137. package/server/api/hr/people/[id]/assets/index.post.ts +14 -0
  138. package/server/api/hr/people/[id]/compensations.get.ts +14 -0
  139. package/server/api/hr/people/[id]/compensations.patch.ts +16 -0
  140. package/server/api/hr/people/[id]/contracts.get.ts +14 -0
  141. package/server/api/hr/people/[id]/contracts.patch.ts +16 -0
  142. package/server/api/hr/people/[id]/documents/[did].delete.ts +15 -0
  143. package/server/api/hr/people/[id]/documents/index.get.ts +14 -0
  144. package/server/api/hr/people/[id]/documents/index.post.ts +16 -0
  145. package/server/api/hr/people/[id]/insurances.get.ts +14 -0
  146. package/server/api/hr/people/[id]/insurances.patch.ts +16 -0
  147. package/server/api/hr/people/[id]/leave-balances/[bid].patch.ts +17 -0
  148. package/server/api/hr/people/[id]/leave-balances/index.get.ts +14 -0
  149. package/server/api/hr/people/[id]/leave-requests/index.get.ts +14 -0
  150. package/server/api/hr/people/[id]/leave-requests/index.post.ts +16 -0
  151. package/server/api/hr/people/[id]/link-user.post.ts +16 -0
  152. package/server/api/hr/people/[id]/notes/[nid].delete.ts +15 -0
  153. package/server/api/hr/people/[id]/notes/index.get.ts +14 -0
  154. package/server/api/hr/people/[id]/notes/index.post.ts +16 -0
  155. package/server/api/hr/people/[id]/offboarding/cases.get.ts +12 -0
  156. package/server/api/hr/people/[id]/offboarding.get.ts +12 -0
  157. package/server/api/hr/people/[id]/offboarding.post.ts +14 -0
  158. package/server/api/hr/people/[id]/provisioning/[logId]/retry.post.ts +7 -0
  159. package/server/api/hr/people/[id]/provisioning/index.get.ts +6 -0
  160. package/server/api/hr/people/[id]/provisioning/index.post.ts +7 -0
  161. package/server/api/hr/people/[id]/transition.post.ts +19 -0
  162. package/server/api/hr/people/[id]/transitions.get.ts +14 -0
  163. package/server/api/hr/people/[id].delete.ts +15 -0
  164. package/server/api/hr/people/[id].get.ts +14 -0
  165. package/server/api/hr/people/[id].patch.ts +17 -0
  166. package/server/api/hr/people/index.get.ts +15 -0
  167. package/server/api/hr/people/index.post.ts +19 -0
  168. package/server/api/hr/policies/[id].patch.ts +16 -0
  169. package/server/api/hr/policies/index.get.ts +13 -0
  170. package/server/api/hr/providers/[id]/test.post.ts +6 -0
  171. package/server/api/hr/providers/[id].delete.ts +6 -0
  172. package/server/api/hr/providers/[id].patch.ts +7 -0
  173. package/server/api/hr/providers/index.get.ts +5 -0
  174. package/server/api/hr/providers/index.post.ts +6 -0
  175. package/server/api/hr/settings/employment-types/[id].delete.ts +14 -0
  176. package/server/api/hr/settings/employment-types/[id].patch.ts +16 -0
  177. package/server/api/hr/settings/employment-types/index.get.ts +13 -0
  178. package/server/api/hr/settings/employment-types/index.post.ts +15 -0
  179. package/server/api/hr/settings/index.get.ts +13 -0
  180. package/server/api/hr/settings/index.patch.ts +15 -0
  181. package/server/api/hr/settings/leave-types/[id].delete.ts +14 -0
  182. package/server/api/hr/settings/leave-types/[id].patch.ts +16 -0
  183. package/server/api/hr/settings/leave-types/index.get.ts +13 -0
  184. package/server/api/hr/settings/leave-types/index.post.ts +15 -0
  185. package/shared/types/form-layout.ts +30 -0
  186. package/shared/types/index.ts +2 -0
  187. package/shared/types/integration.ts +41 -0
  188. package/shared/types/leave.ts +53 -0
  189. package/shared/types/offboarding.ts +46 -0
  190. package/shared/types/person.ts +54 -0
  191. package/shared/types/settings.ts +16 -0
  192. package/shared/utils/template-render.ts +155 -0
@@ -0,0 +1,187 @@
1
+ <template>
2
+ <div class="p-6 max-w-4xl space-y-4">
3
+ <div class="flex items-center justify-between">
4
+ <h2 class="text-base font-semibold text-default">
5
+ {{ $t('provisioning.linked_accounts') }}
6
+ </h2>
7
+ <UButton
8
+ icon="i-ph-arrow-clockwise-light"
9
+ variant="ghost"
10
+ size="sm"
11
+ :loading="pending"
12
+ @click="load"
13
+ />
14
+ </div>
15
+
16
+ <!-- No providers -->
17
+ <div
18
+ v-if="!pending && !statuses.length"
19
+ class="text-sm text-muted py-8 text-center border border-dashed border-default rounded-lg"
20
+ >
21
+ {{ $t('provisioning.no_providers_configured') }}
22
+ </div>
23
+
24
+ <!-- Status table -->
25
+ <div
26
+ v-else-if="statuses.length"
27
+ class="border border-default rounded-lg divide-y divide-default"
28
+ >
29
+ <div
30
+ v-for="s in statuses"
31
+ :key="s.provider_id"
32
+ class="p-4 flex items-center gap-4"
33
+ >
34
+ <div class="flex-1 min-w-0">
35
+ <div class="flex items-center gap-2 flex-wrap">
36
+ <span class="font-medium text-default text-sm">{{ s.provider_name }}</span>
37
+ <UBadge
38
+ :label="$t(`integrations.types.${s.provider_type}`)"
39
+ color="neutral"
40
+ variant="subtle"
41
+ size="xs"
42
+ />
43
+ <UBadge
44
+ :label="$t(`provisioning.status.${s.status}`)"
45
+ :color="statusColor(s.status)"
46
+ variant="subtle"
47
+ size="sm"
48
+ />
49
+ </div>
50
+ <div
51
+ v-if="s.username"
52
+ class="text-xs text-muted mt-1"
53
+ >
54
+ {{ $t('provisioning.username') }}: <span class="font-mono text-default">{{ s.username }}</span>
55
+ </div>
56
+ <div
57
+ v-if="s.last_action_date"
58
+ class="text-xs text-muted mt-0.5"
59
+ >
60
+ {{ $t('provisioning.last_action') }}: {{ s.last_action }} &middot; {{ formatDate(s.last_action_date) }}
61
+ </div>
62
+ <div
63
+ v-if="s.last_error"
64
+ class="text-xs text-error mt-1"
65
+ >
66
+ {{ s.last_error }}
67
+ </div>
68
+ </div>
69
+
70
+ <div class="flex items-center gap-2 shrink-0">
71
+ <!-- Retry on error -->
72
+ <UButton
73
+ v-if="s.status === 'error' && s.last_log_id"
74
+ icon="i-ph-arrow-clockwise-light"
75
+ label="Retry"
76
+ variant="outline"
77
+ color="error"
78
+ size="sm"
79
+ :loading="retryingId === s.last_log_id"
80
+ @click="retry(s)"
81
+ />
82
+ <!-- Manual create on not_created -->
83
+ <UButton
84
+ v-else-if="s.status === 'not_created'"
85
+ icon="i-ph-plus-light"
86
+ :label="$t('provisioning.create_account')"
87
+ variant="outline"
88
+ size="sm"
89
+ :loading="creatingId === s.provider_id"
90
+ @click="manualCreate(s)"
91
+ />
92
+ </div>
93
+ </div>
94
+ </div>
95
+
96
+ <!-- Loading -->
97
+ <div
98
+ v-else
99
+ class="flex justify-center py-8"
100
+ >
101
+ <UIcon
102
+ name="i-ph-spinner-light"
103
+ class="size-6 text-muted animate-spin"
104
+ />
105
+ </div>
106
+ </div>
107
+ </template>
108
+
109
+ <script lang="ts" setup>
110
+ const { $api } = useNuxtApp()
111
+ const props = defineProps<{
112
+ person: Person
113
+ readonly?: boolean
114
+ }>()
115
+
116
+ const toast = useToast()
117
+ const { t } = useI18n()
118
+
119
+ const statuses = useState<ProvisioningStatus[]>(`hr:provisioning:${props.person.id}`, () => [])
120
+ const pending = ref(false)
121
+ const retryingId = ref<string | null>(null)
122
+ const creatingId = ref<string | null>(null)
123
+
124
+ async function load() {
125
+ pending.value = true
126
+ try {
127
+ const res = await $api<any>(`/hr/people/${props.person.id}/provisioning`)
128
+ statuses.value = Array.isArray(res) ? res : (res?.data ?? [])
129
+ }
130
+ catch (err: any) {
131
+ toast.add({ title: err.message ?? t('hr.toast.error'), color: 'error' })
132
+ }
133
+ finally {
134
+ pending.value = false
135
+ }
136
+ }
137
+
138
+ async function retry(s: ProvisioningStatus) {
139
+ if (!s.last_log_id) return
140
+ retryingId.value = s.last_log_id
141
+ try {
142
+ await $api(`/hr/people/${props.person.id}/provisioning/${s.last_log_id}/retry`, { method: 'POST' })
143
+ toast.add({ title: 'Retry triggered', color: 'success' })
144
+ await load()
145
+ }
146
+ catch (err: any) {
147
+ toast.add({ title: err.message ?? t('hr.toast.error'), color: 'error' })
148
+ }
149
+ finally {
150
+ retryingId.value = null
151
+ }
152
+ }
153
+
154
+ async function manualCreate(s: ProvisioningStatus) {
155
+ creatingId.value = s.provider_id
156
+ try {
157
+ await $api(`/hr/people/${props.person.id}/provisioning`, {
158
+ method: 'POST',
159
+ body: { action: 'create' },
160
+ })
161
+ toast.add({ title: t('provisioning.create_account'), color: 'success' })
162
+ await load()
163
+ }
164
+ catch (err: any) {
165
+ toast.add({ title: err.message ?? t('hr.toast.error'), color: 'error' })
166
+ }
167
+ finally {
168
+ creatingId.value = null
169
+ }
170
+ }
171
+
172
+ function statusColor(status: ProvisioningStatus['status']) {
173
+ const map: Record<ProvisioningStatus['status'], string> = {
174
+ active: 'success',
175
+ disabled: 'warning',
176
+ not_created: 'neutral',
177
+ error: 'error',
178
+ }
179
+ return map[status] ?? 'neutral'
180
+ }
181
+
182
+ function formatDate(d: string) {
183
+ return new Date(d).toLocaleDateString()
184
+ }
185
+
186
+ onMounted(load)
187
+ </script>
@@ -0,0 +1,38 @@
1
+ <script lang="ts" setup>
2
+ import HrInfoSection from "../shared/section.vue"
3
+
4
+ defineProps<{ person: Person, readonly?: boolean }>()
5
+
6
+ const { can } = usePermissionRegistry()
7
+ const canViewSensitive = computed(() => can('hr', 'sensitive.read'))
8
+ const sensitiveReadonly = computed(() => !can('hr', 'sensitive.update'))
9
+ </script>
10
+
11
+ <template>
12
+ <div class="p-6 max-w-4xl space-y-6">
13
+ <HrEmployeesContract
14
+ :person="person"
15
+ :readonly="readonly"
16
+ />
17
+ <template v-if="canViewSensitive">
18
+ <HrEmployeesCompensation
19
+ :person="person"
20
+ :readonly="readonly || sensitiveReadonly"
21
+ />
22
+ <HrEmployeesInsurance
23
+ :person="person"
24
+ :readonly="readonly || sensitiveReadonly"
25
+ />
26
+ </template>
27
+ <HrInfoSection
28
+ v-else
29
+ :title="$t('hr.compensation.title')"
30
+ icon="i-ph-lock-light"
31
+ >
32
+ <div class="px-4 py-6 text-sm text-muted flex items-center gap-2">
33
+ <UIcon name="i-ph-lock-light" class="size-4" />
34
+ {{ $t('hr.permissions.sensitive_locked') }}
35
+ </div>
36
+ </HrInfoSection>
37
+ </div>
38
+ </template>