@zwayam/apply-experience-library 0.2.1 → 0.2.3
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/README.md +27 -456
- package/{packages/web/dist → dist}/index.d.ts +1 -0
- package/{packages/web/dist → dist}/index.js +9 -9
- package/package.json +10 -25
- package/packages/web/README.md +0 -57
- /package/{packages/web/dist → dist}/publicTypes.d.ts +0 -0
- /package/{packages/web/dist → dist}/styles.css +0 -0
package/README.md
CHANGED
|
@@ -1,28 +1,14 @@
|
|
|
1
1
|
# Apply Experience Library
|
|
2
2
|
|
|
3
|
-
`@zwayam/apply-experience-library
|
|
3
|
+
This package is the bundled web entrypoint for `@zwayam/apply-experience-library`.
|
|
4
4
|
|
|
5
|
-
It
|
|
5
|
+
It exposes framework-friendly mount helpers for launching **Add Profile** and **Edit Profile** popups from:
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
- dynamic field rendering from backend `applyFields`
|
|
13
|
-
- required validation, pattern validation, dependent field visibility
|
|
14
|
-
- country code + phone input handling
|
|
15
|
-
- source / source type / sub-source flow
|
|
16
|
-
- optional location autosuggestions
|
|
17
|
-
- final submit flow and success callbacks
|
|
18
|
-
|
|
19
|
-
## What the Host App Handles
|
|
20
|
-
|
|
21
|
-
- authentication and session
|
|
22
|
-
- current job and user context
|
|
23
|
-
- backend API calls
|
|
24
|
-
- route-level state management
|
|
25
|
-
- refresh / navigation after success
|
|
7
|
+
- Angular
|
|
8
|
+
- React
|
|
9
|
+
- Vue
|
|
10
|
+
- Vanilla JavaScript
|
|
11
|
+
- Custom elements
|
|
26
12
|
|
|
27
13
|
## Install
|
|
28
14
|
|
|
@@ -30,457 +16,42 @@ It is designed for hosts that already own authentication, API orchestration, and
|
|
|
30
16
|
npm install @zwayam/apply-experience-library
|
|
31
17
|
```
|
|
32
18
|
|
|
33
|
-
Import styles once
|
|
19
|
+
Import styles once:
|
|
34
20
|
|
|
35
21
|
```ts
|
|
36
22
|
import "@zwayam/apply-experience-library/styles.css";
|
|
37
23
|
```
|
|
38
24
|
|
|
39
|
-
##
|
|
40
|
-
|
|
41
|
-
The package exposes:
|
|
42
|
-
|
|
43
|
-
- `mountAddProfile(options)`
|
|
44
|
-
- `mountEditProfile(options)`
|
|
45
|
-
- `registerAddProfileElement(options)`
|
|
46
|
-
- `registerEditProfileElement(options)`
|
|
47
|
-
|
|
48
|
-
Use `mount*` for direct framework integration. Use `register*Element` if you prefer custom elements.
|
|
49
|
-
|
|
50
|
-
## How It Is Built
|
|
51
|
-
|
|
52
|
-
The SDK is made in two layers:
|
|
53
|
-
|
|
54
|
-
1. `packages/react`
|
|
55
|
-
- React implementation of Add Profile / Edit Profile
|
|
56
|
-
- field rendering, validations, workflow logic
|
|
57
|
-
|
|
58
|
-
2. `packages/web`
|
|
59
|
-
- bundled host-facing package
|
|
60
|
-
- exports mount helpers that work in Angular, React, Vue, and vanilla JS
|
|
61
|
-
|
|
62
|
-
This means host apps do not need to know the internal React implementation details. They only provide `context`, `api`, and a DOM `container`.
|
|
63
|
-
|
|
64
|
-
## Add Profile Context
|
|
65
|
-
|
|
66
|
-
```ts
|
|
67
|
-
type AddProfileHostContext = {
|
|
68
|
-
job: {
|
|
69
|
-
id: string;
|
|
70
|
-
companyId: number | string;
|
|
71
|
-
departmentId?: number | string;
|
|
72
|
-
jobTitle: string;
|
|
73
|
-
jobCode: string;
|
|
74
|
-
location?: string;
|
|
75
|
-
minYearOfExperience?: number;
|
|
76
|
-
maxYearOfExperience?: number;
|
|
77
|
-
departmentName?: string;
|
|
78
|
-
};
|
|
79
|
-
user: {
|
|
80
|
-
id: string | number;
|
|
81
|
-
email: string;
|
|
82
|
-
name: string;
|
|
83
|
-
uuid?: string;
|
|
84
|
-
};
|
|
85
|
-
session: {
|
|
86
|
-
sessionId: string;
|
|
87
|
-
};
|
|
88
|
-
environment?: Record<string, string>;
|
|
89
|
-
};
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### Example
|
|
25
|
+
## Main Exports
|
|
93
26
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
companyId: 16136,
|
|
99
|
-
departmentId: 12,
|
|
100
|
-
jobTitle: "Java Developer",
|
|
101
|
-
jobCode: "16667",
|
|
102
|
-
location: "Pune, Maharashtra, India",
|
|
103
|
-
minYearOfExperience: 2,
|
|
104
|
-
maxYearOfExperience: 5,
|
|
105
|
-
departmentName: "Engineering",
|
|
106
|
-
},
|
|
107
|
-
user: {
|
|
108
|
-
id: 286813,
|
|
109
|
-
email: "recruiter@example.com",
|
|
110
|
-
name: "Recruiter Name",
|
|
111
|
-
uuid: "host-user-uuid",
|
|
112
|
-
},
|
|
113
|
-
session: {
|
|
114
|
-
sessionId: "SESSION_ID",
|
|
115
|
-
},
|
|
116
|
-
environment: {
|
|
117
|
-
tenant: "prod",
|
|
118
|
-
},
|
|
119
|
-
};
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
## Edit Profile Context
|
|
27
|
+
- `mountAddProfile`
|
|
28
|
+
- `mountEditProfile`
|
|
29
|
+
- `registerAddProfileElement`
|
|
30
|
+
- `registerEditProfileElement`
|
|
123
31
|
|
|
124
|
-
|
|
32
|
+
## Quick Example
|
|
125
33
|
|
|
126
34
|
```ts
|
|
127
|
-
|
|
128
|
-
applyId: string | number;
|
|
129
|
-
application?: Record<string, unknown>;
|
|
130
|
-
};
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### Example
|
|
134
|
-
|
|
135
|
-
```ts
|
|
136
|
-
const editProfileContext = {
|
|
137
|
-
...addProfileContext,
|
|
138
|
-
applyId: 987654,
|
|
139
|
-
application: {
|
|
140
|
-
applyId: 987654,
|
|
141
|
-
candidateId: 12345,
|
|
142
|
-
},
|
|
143
|
-
};
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
## Add Profile API Contract
|
|
147
|
-
|
|
148
|
-
```ts
|
|
149
|
-
type AddProfileApi = {
|
|
150
|
-
loadInitialData(
|
|
151
|
-
context: AddProfileHostContext,
|
|
152
|
-
): Promise<{
|
|
153
|
-
applyFields: AddProfileFieldDefinition[];
|
|
154
|
-
supportedFiles: {
|
|
155
|
-
addProfile?: {
|
|
156
|
-
fileFormat: string[];
|
|
157
|
-
fileSize?: number;
|
|
158
|
-
};
|
|
159
|
-
};
|
|
160
|
-
profileSources: Array<{
|
|
161
|
-
sourceOfProfile?: string;
|
|
162
|
-
profileSource: string;
|
|
163
|
-
subSourceValues?: string | null;
|
|
164
|
-
}>;
|
|
165
|
-
phoneConfiguration: {
|
|
166
|
-
countryIsoCode: string | null;
|
|
167
|
-
whatsAppEnabled: boolean;
|
|
168
|
-
maxCount: number;
|
|
169
|
-
};
|
|
170
|
-
resumeOptional?: boolean;
|
|
171
|
-
}>;
|
|
172
|
-
|
|
173
|
-
parseResume(
|
|
174
|
-
file: File,
|
|
175
|
-
context: AddProfileHostContext,
|
|
176
|
-
): Promise<{
|
|
177
|
-
responseCode?: number;
|
|
178
|
-
reponseObject?: {
|
|
179
|
-
parsedObjectId?: string;
|
|
180
|
-
parsedResult?: {
|
|
181
|
-
profile?: Record<string, unknown>;
|
|
182
|
-
};
|
|
183
|
-
jobApplication?: Record<string, unknown>;
|
|
184
|
-
};
|
|
185
|
-
}>;
|
|
186
|
-
|
|
187
|
-
submitProfile(
|
|
188
|
-
payload: FormData,
|
|
189
|
-
context: AddProfileHostContext,
|
|
190
|
-
): Promise<{
|
|
191
|
-
code?: number;
|
|
192
|
-
message?: string;
|
|
193
|
-
[key: string]: unknown;
|
|
194
|
-
}>;
|
|
195
|
-
|
|
196
|
-
getLocationSuggestions?(
|
|
197
|
-
query: string,
|
|
198
|
-
context: AddProfileHostContext,
|
|
199
|
-
): Promise<string[]>;
|
|
200
|
-
};
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
## Edit Profile API Contract
|
|
204
|
-
|
|
205
|
-
```ts
|
|
206
|
-
type EditProfileApi = {
|
|
207
|
-
loadInitialData(
|
|
208
|
-
context: EditProfileHostContext,
|
|
209
|
-
): Promise<{
|
|
210
|
-
jobApplication: Record<string, unknown>;
|
|
211
|
-
applyFieldsObject: Record<string, unknown>;
|
|
212
|
-
applyFields: AddProfileFieldDefinition[];
|
|
213
|
-
phoneConfiguration: {
|
|
214
|
-
countryIsoCode: string | null;
|
|
215
|
-
whatsAppEnabled: boolean;
|
|
216
|
-
maxCount: number;
|
|
217
|
-
};
|
|
218
|
-
phoneNumbers?: Array<Record<string, unknown>>;
|
|
219
|
-
supportedFiles?: {
|
|
220
|
-
addProfile?: {
|
|
221
|
-
fileFormat: string[];
|
|
222
|
-
fileSize?: number;
|
|
223
|
-
};
|
|
224
|
-
};
|
|
225
|
-
}>;
|
|
226
|
-
|
|
227
|
-
submitProfile(
|
|
228
|
-
payload: Record<string, unknown>,
|
|
229
|
-
context: EditProfileHostContext,
|
|
230
|
-
): Promise<{
|
|
231
|
-
code?: number;
|
|
232
|
-
message?: string;
|
|
233
|
-
[key: string]: unknown;
|
|
234
|
-
}>;
|
|
235
|
-
|
|
236
|
-
getLocationSuggestions?(
|
|
237
|
-
query: string,
|
|
238
|
-
context: EditProfileHostContext,
|
|
239
|
-
): Promise<string[]>;
|
|
240
|
-
};
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
## Field Definitions
|
|
244
|
-
|
|
245
|
-
The SDK renders fields from backend `applyFields`.
|
|
246
|
-
|
|
247
|
-
Common field types include:
|
|
248
|
-
|
|
249
|
-
- `T` for text-like inputs
|
|
250
|
-
- `D` for searchable dropdowns
|
|
251
|
-
- `date`
|
|
252
|
-
- `phone`
|
|
253
|
-
- `checkbox`
|
|
254
|
-
- `location`
|
|
255
|
-
- `email`
|
|
256
|
-
- `consent`
|
|
257
|
-
|
|
258
|
-
Notes:
|
|
259
|
-
|
|
260
|
-
- `field.errorMessage` is used as first priority for validation messages when present.
|
|
261
|
-
- Generated SDK validation messages are used as fallback when API does not provide one.
|
|
262
|
-
- Currency formatting follows field metadata type such as `INRCURRENCY` / `CURRENCY`, matching host behavior.
|
|
263
|
-
|
|
264
|
-
## React Usage
|
|
265
|
-
|
|
266
|
-
```tsx
|
|
267
|
-
import { useEffect, useRef } from "react";
|
|
268
|
-
import {
|
|
269
|
-
mountAddProfile,
|
|
270
|
-
type MountedAddProfile,
|
|
271
|
-
type AddProfileApi,
|
|
272
|
-
type AddProfileHostContext,
|
|
273
|
-
} from "@zwayam/apply-experience-library";
|
|
274
|
-
import "@zwayam/apply-experience-library/styles.css";
|
|
35
|
+
import { mountAddProfile } from "@zwayam/apply-experience-library";
|
|
275
36
|
|
|
276
|
-
|
|
277
|
-
|
|
37
|
+
const mounted = mountAddProfile({
|
|
38
|
+
container: document.getElementById("add-profile-root"),
|
|
278
39
|
context,
|
|
279
40
|
api,
|
|
280
|
-
onClose,
|
|
281
|
-
|
|
282
|
-
open: boolean;
|
|
283
|
-
context: AddProfileHostContext;
|
|
284
|
-
api: AddProfileApi;
|
|
285
|
-
onClose(): void;
|
|
286
|
-
}) {
|
|
287
|
-
const rootRef = useRef<HTMLDivElement | null>(null);
|
|
288
|
-
const mountedRef = useRef<MountedAddProfile | null>(null);
|
|
289
|
-
|
|
290
|
-
useEffect(() => {
|
|
291
|
-
if (!open || !rootRef.current) return;
|
|
292
|
-
|
|
293
|
-
mountedRef.current = mountAddProfile({
|
|
294
|
-
container: rootRef.current,
|
|
295
|
-
context,
|
|
296
|
-
api,
|
|
297
|
-
title: "Add Profile",
|
|
298
|
-
onClose,
|
|
299
|
-
onSuccess: () => {
|
|
300
|
-
mountedRef.current?.unmount();
|
|
301
|
-
onClose();
|
|
302
|
-
},
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
return () => mountedRef.current?.unmount();
|
|
306
|
-
}, [open, context, api, onClose]);
|
|
307
|
-
|
|
308
|
-
return <div ref={rootRef} />;
|
|
309
|
-
}
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
## Angular Usage
|
|
313
|
-
|
|
314
|
-
Import styles once in a global stylesheet:
|
|
315
|
-
|
|
316
|
-
```scss
|
|
317
|
-
@import "@zwayam/apply-experience-library/styles.css";
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
Mount from a component or service:
|
|
321
|
-
|
|
322
|
-
```ts
|
|
323
|
-
import {
|
|
324
|
-
mountAddProfile,
|
|
325
|
-
type MountedAddProfile,
|
|
326
|
-
type AddProfileApi,
|
|
327
|
-
type AddProfileHostContext,
|
|
328
|
-
} from "@zwayam/apply-experience-library";
|
|
329
|
-
|
|
330
|
-
private mountedAddProfile?: MountedAddProfile;
|
|
331
|
-
|
|
332
|
-
openAddProfile(container: Element, context: AddProfileHostContext, api: AddProfileApi) {
|
|
333
|
-
this.mountedAddProfile = mountAddProfile({
|
|
334
|
-
container,
|
|
335
|
-
context,
|
|
336
|
-
api,
|
|
337
|
-
title: "Add Profile",
|
|
338
|
-
onClose: () => this.mountedAddProfile?.unmount(),
|
|
339
|
-
onSuccess: () => {
|
|
340
|
-
this.mountedAddProfile?.unmount();
|
|
341
|
-
// refresh host data here
|
|
342
|
-
},
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
## Vue Usage
|
|
348
|
-
|
|
349
|
-
```vue
|
|
350
|
-
<script setup lang="ts">
|
|
351
|
-
import { onBeforeUnmount, watch, ref } from "vue";
|
|
352
|
-
import { mountAddProfile } from "@zwayam/apply-experience-library";
|
|
353
|
-
import "@zwayam/apply-experience-library/styles.css";
|
|
354
|
-
|
|
355
|
-
const props = defineProps<{
|
|
356
|
-
open: boolean;
|
|
357
|
-
context: any;
|
|
358
|
-
api: any;
|
|
359
|
-
}>();
|
|
360
|
-
|
|
361
|
-
const root = ref<HTMLElement | null>(null);
|
|
362
|
-
let mounted: ReturnType<typeof mountAddProfile> | null = null;
|
|
363
|
-
|
|
364
|
-
watch(
|
|
365
|
-
() => props.open,
|
|
366
|
-
(open) => {
|
|
367
|
-
if (!open || !root.value) return;
|
|
368
|
-
|
|
369
|
-
mounted = mountAddProfile({
|
|
370
|
-
container: root.value,
|
|
371
|
-
context: props.context,
|
|
372
|
-
api: props.api,
|
|
373
|
-
onClose: () => mounted?.unmount(),
|
|
374
|
-
onSuccess: () => mounted?.unmount(),
|
|
375
|
-
});
|
|
376
|
-
},
|
|
377
|
-
);
|
|
378
|
-
|
|
379
|
-
onBeforeUnmount(() => mounted?.unmount());
|
|
380
|
-
</script>
|
|
381
|
-
|
|
382
|
-
<template>
|
|
383
|
-
<div ref="root"></div>
|
|
384
|
-
</template>
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
## Vanilla JavaScript Usage
|
|
388
|
-
|
|
389
|
-
```html
|
|
390
|
-
<button id="open-add-profile">Add Profile</button>
|
|
391
|
-
<div id="add-profile-root"></div>
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
```js
|
|
395
|
-
import { mountAddProfile } from "@zwayam/apply-experience-library";
|
|
396
|
-
import "@zwayam/apply-experience-library/styles.css";
|
|
397
|
-
|
|
398
|
-
document.getElementById("open-add-profile").addEventListener("click", () => {
|
|
399
|
-
const mounted = mountAddProfile({
|
|
400
|
-
container: document.getElementById("add-profile-root"),
|
|
401
|
-
context: addProfileContext,
|
|
402
|
-
api: addProfileApi,
|
|
403
|
-
onClose: () => mounted.unmount(),
|
|
404
|
-
onSuccess: () => mounted.unmount(),
|
|
405
|
-
});
|
|
41
|
+
onClose: () => mounted.unmount(),
|
|
42
|
+
onSuccess: () => mounted.unmount(),
|
|
406
43
|
});
|
|
407
44
|
```
|
|
408
45
|
|
|
409
|
-
##
|
|
46
|
+
## Context and API
|
|
410
47
|
|
|
411
|
-
|
|
412
|
-
import {
|
|
413
|
-
registerAddProfileElement,
|
|
414
|
-
registerEditProfileElement,
|
|
415
|
-
} from "@zwayam/apply-experience-library";
|
|
48
|
+
The host must provide:
|
|
416
49
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
50
|
+
- job context
|
|
51
|
+
- logged-in user context
|
|
52
|
+
- session context
|
|
53
|
+
- host-owned API functions for loading fields, parsing resume, submitting profile, and optionally fetching location suggestions
|
|
421
54
|
|
|
422
|
-
|
|
423
|
-
getApi: () => editProfileApi,
|
|
424
|
-
getContext: () => editProfileContext,
|
|
425
|
-
});
|
|
426
|
-
```
|
|
427
|
-
|
|
428
|
-
Then use:
|
|
429
|
-
|
|
430
|
-
```html
|
|
431
|
-
<apply-experience-add-profile></apply-experience-add-profile>
|
|
432
|
-
<apply-experience-edit-profile></apply-experience-edit-profile>
|
|
433
|
-
```
|
|
434
|
-
|
|
435
|
-
## Example API Object
|
|
55
|
+
For the full API contract and framework-specific examples, see:
|
|
436
56
|
|
|
437
|
-
|
|
438
|
-
const addProfileApi = {
|
|
439
|
-
loadInitialData: async (context) => {
|
|
440
|
-
const response = await fetch(`/api/apply-fields?jobId=${context.job.id}`);
|
|
441
|
-
return response.json();
|
|
442
|
-
},
|
|
443
|
-
|
|
444
|
-
parseResume: async (file, context) => {
|
|
445
|
-
const formData = new FormData();
|
|
446
|
-
formData.append("file", file);
|
|
447
|
-
formData.append("sessionId", context.session.sessionId);
|
|
448
|
-
const response = await fetch("/api/parse-resume", {
|
|
449
|
-
method: "POST",
|
|
450
|
-
body: formData,
|
|
451
|
-
});
|
|
452
|
-
return response.json();
|
|
453
|
-
},
|
|
454
|
-
|
|
455
|
-
submitProfile: async (payload, context) => {
|
|
456
|
-
payload.append("sessionId", context.session.sessionId);
|
|
457
|
-
const response = await fetch("/api/add-profile", {
|
|
458
|
-
method: "POST",
|
|
459
|
-
body: payload,
|
|
460
|
-
});
|
|
461
|
-
return response.json();
|
|
462
|
-
},
|
|
463
|
-
|
|
464
|
-
getLocationSuggestions: async (query) => {
|
|
465
|
-
if (!query.trim()) return [];
|
|
466
|
-
const response = await fetch(`/api/location-suggestions?q=${encodeURIComponent(query)}`);
|
|
467
|
-
const data = await response.json();
|
|
468
|
-
return data.suggestions || [];
|
|
469
|
-
},
|
|
470
|
-
};
|
|
471
|
-
```
|
|
472
|
-
|
|
473
|
-
## Development
|
|
474
|
-
|
|
475
|
-
```bash
|
|
476
|
-
npm install
|
|
477
|
-
npm run build
|
|
478
|
-
npm run playground
|
|
479
|
-
```
|
|
480
|
-
|
|
481
|
-
## Publish
|
|
482
|
-
|
|
483
|
-
```bash
|
|
484
|
-
npm run build
|
|
485
|
-
npm publish --access public
|
|
486
|
-
```
|
|
57
|
+
- [../../README.md](../../README.md)
|