@recruitnepal/shared-packages 1.1.0 → 1.3.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.
- package/dist/api-client.d.ts +7 -0
- package/dist/api-client.d.ts.map +1 -1
- package/dist/api-client.js +7 -0
- package/dist/hooks/useEasyApplyFormHook.d.ts +180 -0
- package/dist/hooks/useEasyApplyFormHook.d.ts.map +1 -0
- package/dist/hooks/useEasyApplyFormHook.js +173 -0
- package/dist/hooks/useEasyApplyMutations.d.ts +13 -0
- package/dist/hooks/useEasyApplyMutations.d.ts.map +1 -0
- package/dist/hooks/useEasyApplyMutations.js +59 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/types/easy-apply.d.ts +36 -0
- package/dist/types/easy-apply.d.ts.map +1 -0
- package/dist/types/easy-apply.js +1 -0
- package/package.json +45 -39
package/dist/api-client.d.ts
CHANGED
|
@@ -23,5 +23,12 @@ export declare const API: {
|
|
|
23
23
|
questions: {
|
|
24
24
|
byVacancyId: (vacancyId: string) => string;
|
|
25
25
|
};
|
|
26
|
+
easyApplicants: {
|
|
27
|
+
create: () => string;
|
|
28
|
+
};
|
|
29
|
+
applicantAnswers: {
|
|
30
|
+
byApplicantId: (applicantId: string) => string;
|
|
31
|
+
byPersonalDetailId: (personalDetailId: string) => string;
|
|
32
|
+
};
|
|
26
33
|
};
|
|
27
34
|
//# sourceMappingURL=api-client.d.ts.map
|
package/dist/api-client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAEA,wBAAgB,OAAO,CAAC,MAAM,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,QAElD;AAED,wBAAgB,UAAU,WAKzB;AAED,eAAO,MAAM,GAAG;;;mBAGD,MAAM;;;;sBAIH,MAAM;;qBAEP,MAAM;;;sBAGL,MAAM;;qBAEP,MAAM;qBACN,MAAM;;;;iCAIM,MAAM;;
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAEA,wBAAgB,OAAO,CAAC,MAAM,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,QAElD;AAED,wBAAgB,UAAU,WAKzB;AAED,eAAO,MAAM,GAAG;;;mBAGD,MAAM;;;;sBAIH,MAAM;;qBAEP,MAAM;;;sBAGL,MAAM;;qBAEP,MAAM;qBACN,MAAM;;;;iCAIM,MAAM;;;;;;qCAMF,MAAM;+CACI,MAAM;;CAEhD,CAAC"}
|
package/dist/api-client.js
CHANGED
|
@@ -29,4 +29,11 @@ export const API = {
|
|
|
29
29
|
questions: {
|
|
30
30
|
byVacancyId: (vacancyId) => `${getBaseURL()}/application/questions/?vacancyId=${vacancyId}`,
|
|
31
31
|
},
|
|
32
|
+
easyApplicants: {
|
|
33
|
+
create: () => `${getBaseURL()}/easy/applicants`,
|
|
34
|
+
},
|
|
35
|
+
applicantAnswers: {
|
|
36
|
+
byApplicantId: (applicantId) => `${getBaseURL()}/applicant/answers?applicantId=${applicantId}`,
|
|
37
|
+
byPersonalDetailId: (personalDetailId) => `${getBaseURL()}/applicant/answers?personalDetailId=${personalDetailId}`,
|
|
38
|
+
},
|
|
32
39
|
};
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const screeningAnswerSchema: z.ZodObject<{
|
|
3
|
+
question_id: z.ZodString;
|
|
4
|
+
answer: z.ZodString;
|
|
5
|
+
}, "strip", z.ZodTypeAny, {
|
|
6
|
+
question_id: string;
|
|
7
|
+
answer: string;
|
|
8
|
+
}, {
|
|
9
|
+
question_id: string;
|
|
10
|
+
answer: string;
|
|
11
|
+
}>;
|
|
12
|
+
export declare const screeningAnswersSchema: z.ZodArray<z.ZodObject<{
|
|
13
|
+
question_id: z.ZodString;
|
|
14
|
+
answer: z.ZodString;
|
|
15
|
+
}, "strip", z.ZodTypeAny, {
|
|
16
|
+
question_id: string;
|
|
17
|
+
answer: string;
|
|
18
|
+
}, {
|
|
19
|
+
question_id: string;
|
|
20
|
+
answer: string;
|
|
21
|
+
}>, "many">;
|
|
22
|
+
export declare const easyApplyUserSchema: z.ZodObject<{
|
|
23
|
+
cv: z.ZodEffects<z.ZodType<File, z.ZodTypeDef, File>, File, File>;
|
|
24
|
+
first_name: z.ZodString;
|
|
25
|
+
last_name: z.ZodString;
|
|
26
|
+
email: z.ZodString;
|
|
27
|
+
phone_no: z.ZodString;
|
|
28
|
+
current_address: z.ZodString;
|
|
29
|
+
current_status: z.ZodString;
|
|
30
|
+
two_wheeler: z.ZodDefault<z.ZodBoolean>;
|
|
31
|
+
driving_license: z.ZodDefault<z.ZodBoolean>;
|
|
32
|
+
salary_expectation: z.ZodEffects<z.ZodObject<{
|
|
33
|
+
min: z.ZodNumber;
|
|
34
|
+
max: z.ZodNumber;
|
|
35
|
+
}, "strip", z.ZodTypeAny, {
|
|
36
|
+
min: number;
|
|
37
|
+
max: number;
|
|
38
|
+
}, {
|
|
39
|
+
min: number;
|
|
40
|
+
max: number;
|
|
41
|
+
}>, {
|
|
42
|
+
min: number;
|
|
43
|
+
max: number;
|
|
44
|
+
}, {
|
|
45
|
+
min: number;
|
|
46
|
+
max: number;
|
|
47
|
+
}>;
|
|
48
|
+
screening_answers: z.ZodArray<z.ZodObject<{
|
|
49
|
+
question_id: z.ZodString;
|
|
50
|
+
answer: z.ZodString;
|
|
51
|
+
}, "strip", z.ZodTypeAny, {
|
|
52
|
+
question_id: string;
|
|
53
|
+
answer: string;
|
|
54
|
+
}, {
|
|
55
|
+
question_id: string;
|
|
56
|
+
answer: string;
|
|
57
|
+
}>, "many">;
|
|
58
|
+
}, "strip", z.ZodTypeAny, {
|
|
59
|
+
cv: File;
|
|
60
|
+
first_name: string;
|
|
61
|
+
last_name: string;
|
|
62
|
+
email: string;
|
|
63
|
+
phone_no: string;
|
|
64
|
+
current_address: string;
|
|
65
|
+
current_status: string;
|
|
66
|
+
two_wheeler: boolean;
|
|
67
|
+
driving_license: boolean;
|
|
68
|
+
salary_expectation: {
|
|
69
|
+
min: number;
|
|
70
|
+
max: number;
|
|
71
|
+
};
|
|
72
|
+
screening_answers: {
|
|
73
|
+
question_id: string;
|
|
74
|
+
answer: string;
|
|
75
|
+
}[];
|
|
76
|
+
}, {
|
|
77
|
+
cv: File;
|
|
78
|
+
first_name: string;
|
|
79
|
+
last_name: string;
|
|
80
|
+
email: string;
|
|
81
|
+
phone_no: string;
|
|
82
|
+
current_address: string;
|
|
83
|
+
current_status: string;
|
|
84
|
+
salary_expectation: {
|
|
85
|
+
min: number;
|
|
86
|
+
max: number;
|
|
87
|
+
};
|
|
88
|
+
screening_answers: {
|
|
89
|
+
question_id: string;
|
|
90
|
+
answer: string;
|
|
91
|
+
}[];
|
|
92
|
+
two_wheeler?: boolean | undefined;
|
|
93
|
+
driving_license?: boolean | undefined;
|
|
94
|
+
}>;
|
|
95
|
+
export type EasyApplyFormValues = z.infer<typeof easyApplyUserSchema>;
|
|
96
|
+
export type EasyApplyScreeningAnswer = z.infer<typeof screeningAnswerSchema>;
|
|
97
|
+
export type EasyApplyScreeningAnswers = z.infer<typeof screeningAnswersSchema>;
|
|
98
|
+
export type UseEasyApplyFormHookParams = {
|
|
99
|
+
vacancyId: string;
|
|
100
|
+
/** When true, appends is_intern: 'true' to the easy apply POST (e.g. for Intern Nepal). Default false (Recruit Nepal). */
|
|
101
|
+
isIntern?: boolean;
|
|
102
|
+
token?: string;
|
|
103
|
+
onSuccess?: (message: string, data?: unknown) => void;
|
|
104
|
+
onError?: (message: string) => void;
|
|
105
|
+
};
|
|
106
|
+
export declare const useEasyApplyFormHook: ({ vacancyId, isIntern, token, onSuccess, onError, }: UseEasyApplyFormHookParams) => {
|
|
107
|
+
form: import("react-hook-form").UseFormReturn<{
|
|
108
|
+
cv: File;
|
|
109
|
+
first_name: string;
|
|
110
|
+
last_name: string;
|
|
111
|
+
email: string;
|
|
112
|
+
phone_no: string;
|
|
113
|
+
current_address: string;
|
|
114
|
+
current_status: string;
|
|
115
|
+
two_wheeler: boolean;
|
|
116
|
+
driving_license: boolean;
|
|
117
|
+
salary_expectation: {
|
|
118
|
+
min: number;
|
|
119
|
+
max: number;
|
|
120
|
+
};
|
|
121
|
+
screening_answers: {
|
|
122
|
+
question_id: string;
|
|
123
|
+
answer: string;
|
|
124
|
+
}[];
|
|
125
|
+
}, any, {
|
|
126
|
+
cv: File;
|
|
127
|
+
first_name: string;
|
|
128
|
+
last_name: string;
|
|
129
|
+
email: string;
|
|
130
|
+
phone_no: string;
|
|
131
|
+
current_address: string;
|
|
132
|
+
current_status: string;
|
|
133
|
+
two_wheeler: boolean;
|
|
134
|
+
driving_license: boolean;
|
|
135
|
+
salary_expectation: {
|
|
136
|
+
min: number;
|
|
137
|
+
max: number;
|
|
138
|
+
};
|
|
139
|
+
screening_answers: {
|
|
140
|
+
question_id: string;
|
|
141
|
+
answer: string;
|
|
142
|
+
}[];
|
|
143
|
+
}>;
|
|
144
|
+
questions: import("..").QuestionsAPIRes | undefined;
|
|
145
|
+
questionsLoading: boolean;
|
|
146
|
+
onSubmit: (values: EasyApplyFormValues) => Promise<any>;
|
|
147
|
+
step: number;
|
|
148
|
+
steps: readonly [{
|
|
149
|
+
readonly title: "About Yourself";
|
|
150
|
+
readonly stepNumber: 1;
|
|
151
|
+
readonly fields: readonly ["cv", "first_name", "last_name", "email", "phone_no", "current_address", "current_status", "two_wheeler", "driving_license", "salary_expectation"];
|
|
152
|
+
}, {
|
|
153
|
+
readonly title: "Screening Questions";
|
|
154
|
+
readonly stepNumber: 2;
|
|
155
|
+
readonly fields: readonly ["screening_answers"];
|
|
156
|
+
}, {
|
|
157
|
+
readonly title: "Review";
|
|
158
|
+
readonly stepNumber: 3;
|
|
159
|
+
readonly fields: readonly [];
|
|
160
|
+
}];
|
|
161
|
+
currentStep: {
|
|
162
|
+
readonly title: "About Yourself";
|
|
163
|
+
readonly stepNumber: 1;
|
|
164
|
+
readonly fields: readonly ["cv", "first_name", "last_name", "email", "phone_no", "current_address", "current_status", "two_wheeler", "driving_license", "salary_expectation"];
|
|
165
|
+
} | {
|
|
166
|
+
readonly title: "Screening Questions";
|
|
167
|
+
readonly stepNumber: 2;
|
|
168
|
+
readonly fields: readonly ["screening_answers"];
|
|
169
|
+
} | {
|
|
170
|
+
readonly title: "Review";
|
|
171
|
+
readonly stepNumber: 3;
|
|
172
|
+
readonly fields: readonly [];
|
|
173
|
+
} | undefined;
|
|
174
|
+
goForward: () => Promise<void>;
|
|
175
|
+
goBack: () => void;
|
|
176
|
+
isSubmitting: boolean;
|
|
177
|
+
validateCurrentStep: () => Promise<boolean>;
|
|
178
|
+
};
|
|
179
|
+
export default useEasyApplyFormHook;
|
|
180
|
+
//# sourceMappingURL=useEasyApplyFormHook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEasyApplyFormHook.d.ts","sourceRoot":"","sources":["../../src/hooks/useEasyApplyFormHook.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAcxB,eAAO,MAAM,qBAAqB;;;;;;;;;EAGhC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;WAAiC,CAAC;AAErE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsB9B,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AACtE,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAC7E,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AA+B/E,MAAM,MAAM,0BAA0B,GAAG;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,0HAA0H;IAC1H,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACtD,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,qDAMlC,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAqDV,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoErC,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useForm } from 'react-hook-form';
|
|
4
|
+
import { zodResolver } from '@hookform/resolvers/zod';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { useEasyApplyMutations } from './useEasyApplyMutations';
|
|
7
|
+
// Schemas
|
|
8
|
+
const salaryExpectationSchema = z
|
|
9
|
+
.object({
|
|
10
|
+
min: z.coerce.number().min(0, 'Minimum must be positive'),
|
|
11
|
+
max: z.coerce.number().min(0, 'Maximum must be positive'),
|
|
12
|
+
})
|
|
13
|
+
.refine((data) => data.max >= data.min, {
|
|
14
|
+
message: 'Maximum salary must be greater than or equal to minimum',
|
|
15
|
+
path: ['max'],
|
|
16
|
+
});
|
|
17
|
+
export const screeningAnswerSchema = z.object({
|
|
18
|
+
question_id: z.string().min(1, 'Question ID is required'),
|
|
19
|
+
answer: z.string().min(1, 'Answer is required'),
|
|
20
|
+
});
|
|
21
|
+
export const screeningAnswersSchema = z.array(screeningAnswerSchema);
|
|
22
|
+
export const easyApplyUserSchema = z.object({
|
|
23
|
+
cv: z
|
|
24
|
+
.instanceof(File, { message: 'Resume is required' })
|
|
25
|
+
.refine((file) => file.size <= 5 * 1024 * 1024, {
|
|
26
|
+
message: 'File size must be less than 5MB',
|
|
27
|
+
}),
|
|
28
|
+
first_name: z.string().min(1, { message: 'First name is required' }),
|
|
29
|
+
last_name: z.string().min(1, { message: 'Last name is required' }),
|
|
30
|
+
email: z.string().email({ message: 'Valid email is required' }),
|
|
31
|
+
phone_no: z
|
|
32
|
+
.string()
|
|
33
|
+
.min(10, { message: 'Phone number must be at least 10 digits' })
|
|
34
|
+
.max(15, { message: 'Phone number too long' })
|
|
35
|
+
.regex(/^[0-9]+$/, { message: 'Only numbers allowed' }),
|
|
36
|
+
current_address: z
|
|
37
|
+
.string()
|
|
38
|
+
.min(1, { message: 'Current address is required' }),
|
|
39
|
+
current_status: z.string().min(1, { message: 'Current status is required' }),
|
|
40
|
+
two_wheeler: z.boolean().default(false),
|
|
41
|
+
driving_license: z.boolean().default(false),
|
|
42
|
+
salary_expectation: salaryExpectationSchema,
|
|
43
|
+
screening_answers: screeningAnswersSchema,
|
|
44
|
+
});
|
|
45
|
+
const STEPS = [
|
|
46
|
+
{
|
|
47
|
+
title: 'About Yourself',
|
|
48
|
+
stepNumber: 1,
|
|
49
|
+
fields: [
|
|
50
|
+
'cv',
|
|
51
|
+
'first_name',
|
|
52
|
+
'last_name',
|
|
53
|
+
'email',
|
|
54
|
+
'phone_no',
|
|
55
|
+
'current_address',
|
|
56
|
+
'current_status',
|
|
57
|
+
'two_wheeler',
|
|
58
|
+
'driving_license',
|
|
59
|
+
'salary_expectation',
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
title: 'Screening Questions',
|
|
64
|
+
stepNumber: 2,
|
|
65
|
+
fields: ['screening_answers'],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
title: 'Review',
|
|
69
|
+
stepNumber: 3,
|
|
70
|
+
fields: [],
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
export const useEasyApplyFormHook = ({ vacancyId, isIntern = false, token, onSuccess, onError, }) => {
|
|
74
|
+
const [step, setStep] = React.useState(1);
|
|
75
|
+
const [isSubmitting, setIsSubmitting] = React.useState(false);
|
|
76
|
+
const form = useForm({
|
|
77
|
+
resolver: zodResolver(easyApplyUserSchema),
|
|
78
|
+
defaultValues: {
|
|
79
|
+
cv: undefined,
|
|
80
|
+
first_name: '',
|
|
81
|
+
last_name: '',
|
|
82
|
+
email: '',
|
|
83
|
+
phone_no: '',
|
|
84
|
+
current_address: '',
|
|
85
|
+
current_status: '',
|
|
86
|
+
two_wheeler: false,
|
|
87
|
+
driving_license: false,
|
|
88
|
+
salary_expectation: { min: 10000, max: 20000 },
|
|
89
|
+
screening_answers: [],
|
|
90
|
+
},
|
|
91
|
+
mode: 'onChange',
|
|
92
|
+
});
|
|
93
|
+
const { createEasyApply, getVacancyQuestion } = useEasyApplyMutations({
|
|
94
|
+
id: vacancyId,
|
|
95
|
+
token,
|
|
96
|
+
});
|
|
97
|
+
const { data: questions, isLoading: questionsLoading } = getVacancyQuestion;
|
|
98
|
+
const currentStep = React.useMemo(() => STEPS.find((s) => s.stepNumber === step), [step]);
|
|
99
|
+
const validateCurrentStep = React.useCallback(async () => {
|
|
100
|
+
if (!currentStep)
|
|
101
|
+
return false;
|
|
102
|
+
const fields = [...currentStep.fields];
|
|
103
|
+
return await form.trigger(fields);
|
|
104
|
+
}, [currentStep, form]);
|
|
105
|
+
const goForward = React.useCallback(async () => {
|
|
106
|
+
const isValid = await validateCurrentStep();
|
|
107
|
+
if (!isValid) {
|
|
108
|
+
onError?.('Please fill all required fields');
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
setStep((prev) => Math.min(prev + 1, STEPS.length));
|
|
112
|
+
}, [validateCurrentStep, onError]);
|
|
113
|
+
const goBack = React.useCallback(() => {
|
|
114
|
+
setStep((prev) => Math.max(prev - 1, 1));
|
|
115
|
+
}, []);
|
|
116
|
+
const onSubmit = React.useCallback(async (values) => {
|
|
117
|
+
try {
|
|
118
|
+
setIsSubmitting(true);
|
|
119
|
+
const formData = new FormData();
|
|
120
|
+
formData.append('vacancy_id', vacancyId);
|
|
121
|
+
formData.append('cv', values.cv);
|
|
122
|
+
formData.append('first_name', values.first_name);
|
|
123
|
+
formData.append('last_name', values.last_name);
|
|
124
|
+
formData.append('email', values.email);
|
|
125
|
+
formData.append('phone_no', values.phone_no);
|
|
126
|
+
formData.append('current_address', values.current_address);
|
|
127
|
+
formData.append('current_status', values.current_status);
|
|
128
|
+
formData.append('two_wheeler', String(values.two_wheeler));
|
|
129
|
+
formData.append('driving_license', String(values.driving_license));
|
|
130
|
+
formData.append('salary_expectation', JSON.stringify(values.salary_expectation));
|
|
131
|
+
if (isIntern) {
|
|
132
|
+
formData.append('is_intern', 'true');
|
|
133
|
+
}
|
|
134
|
+
// Send applicant_answers as a single JSON string so backend receives one field to parse as array of objects (avoids "expected object, received string" when sending applicant_answers[0], applicant_answers[1] as strings)
|
|
135
|
+
formData.append('applicant_answers', JSON.stringify(values.screening_answers));
|
|
136
|
+
const personalDetailData = await createEasyApply.mutateAsync(formData);
|
|
137
|
+
if (personalDetailData?.jobId) {
|
|
138
|
+
if (typeof sessionStorage !== 'undefined') {
|
|
139
|
+
sessionStorage.setItem('easyApplyCvJobId', personalDetailData.jobId);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const successMessage = personalDetailData?.applicant?.isUser
|
|
143
|
+
? 'Application submitted successfully, Please login with your account linked with this cv email to track status'
|
|
144
|
+
: 'Application submitted successfully!';
|
|
145
|
+
onSuccess?.(successMessage, personalDetailData);
|
|
146
|
+
form.reset();
|
|
147
|
+
return personalDetailData;
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
const message = 'Failed to submit application';
|
|
151
|
+
onError?.(message);
|
|
152
|
+
console.error('Submission error:', error);
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
setIsSubmitting(false);
|
|
157
|
+
}
|
|
158
|
+
}, [createEasyApply, form, vacancyId, isIntern, onSuccess, onError]);
|
|
159
|
+
return {
|
|
160
|
+
form,
|
|
161
|
+
questions,
|
|
162
|
+
questionsLoading,
|
|
163
|
+
onSubmit,
|
|
164
|
+
step,
|
|
165
|
+
steps: STEPS,
|
|
166
|
+
currentStep,
|
|
167
|
+
goForward,
|
|
168
|
+
goBack,
|
|
169
|
+
isSubmitting,
|
|
170
|
+
validateCurrentStep,
|
|
171
|
+
};
|
|
172
|
+
};
|
|
173
|
+
export default useEasyApplyFormHook;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { QuestionsAPIRes, ScreeningAnswersApiResNew } from '../types/easy-apply';
|
|
2
|
+
export type UseEasyApplyMutationsParams = {
|
|
3
|
+
id?: string;
|
|
4
|
+
applicant_id?: string;
|
|
5
|
+
type?: 'applicantId' | 'personalDetailId';
|
|
6
|
+
token?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare const useEasyApplyMutations: ({ id, applicant_id, type, token, }: UseEasyApplyMutationsParams) => {
|
|
9
|
+
createEasyApply: import("@tanstack/react-query").UseMutationResult<any, Error, FormData, unknown>;
|
|
10
|
+
getVacancyQuestion: import("@tanstack/react-query").UseQueryResult<QuestionsAPIRes, Error>;
|
|
11
|
+
getVacancyAnswers: import("@tanstack/react-query").UseQueryResult<ScreeningAnswersApiResNew, Error>;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=useEasyApplyMutations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEasyApplyMutations.d.ts","sourceRoot":"","sources":["../../src/hooks/useEasyApplyMutations.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAEtF,MAAM,MAAM,2BAA2B,GAAG;IACxC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,aAAa,GAAG,kBAAkB,CAAC;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,oCAKnC,2BAA2B;;;;CAqD7B,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useMutation, useQuery } from '@tanstack/react-query';
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
import { apiRequest } from '../utils/api-request';
|
|
5
|
+
import { API } from '../api-client';
|
|
6
|
+
export const useEasyApplyMutations = ({ id, applicant_id, type, token, }) => {
|
|
7
|
+
const getVacancyQuestion = useQuery({
|
|
8
|
+
queryKey: ['vacancy_question', id],
|
|
9
|
+
queryFn: async () => {
|
|
10
|
+
if (!id)
|
|
11
|
+
throw new Error('vacancy id required');
|
|
12
|
+
const response = await apiRequest({
|
|
13
|
+
endpoint: API.questions.byVacancyId(id),
|
|
14
|
+
method: 'GET',
|
|
15
|
+
token,
|
|
16
|
+
});
|
|
17
|
+
if (!response.data)
|
|
18
|
+
throw new Error('No data received');
|
|
19
|
+
return response.data;
|
|
20
|
+
},
|
|
21
|
+
enabled: !!id,
|
|
22
|
+
});
|
|
23
|
+
const getVacancyAnswers = useQuery({
|
|
24
|
+
queryKey: ['vacancy_answers', applicant_id],
|
|
25
|
+
queryFn: async () => {
|
|
26
|
+
if (!applicant_id || !type)
|
|
27
|
+
throw new Error('applicant_id and type required');
|
|
28
|
+
const endpoint = type === 'applicantId'
|
|
29
|
+
? API.applicantAnswers.byApplicantId(applicant_id)
|
|
30
|
+
: API.applicantAnswers.byPersonalDetailId(applicant_id);
|
|
31
|
+
const response = await apiRequest({
|
|
32
|
+
endpoint,
|
|
33
|
+
method: 'GET',
|
|
34
|
+
token,
|
|
35
|
+
});
|
|
36
|
+
if (!response.data)
|
|
37
|
+
throw new Error('No data received');
|
|
38
|
+
return response.data;
|
|
39
|
+
},
|
|
40
|
+
enabled: !!token && !!applicant_id && !!type,
|
|
41
|
+
retry: false,
|
|
42
|
+
});
|
|
43
|
+
const createEasyApply = useMutation({
|
|
44
|
+
mutationFn: async (data) => {
|
|
45
|
+
const url = API.easyApplicants.create();
|
|
46
|
+
const res = await axios.post(url, data, {
|
|
47
|
+
headers: {
|
|
48
|
+
'Content-Type': 'multipart/form-data',
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
return res.data;
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
createEasyApply,
|
|
56
|
+
getVacancyQuestion,
|
|
57
|
+
getVacancyAnswers,
|
|
58
|
+
};
|
|
59
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export type { SingleVacancyRes, VacancyApiRes, Pagination, ExperienceLevel, } fr
|
|
|
3
3
|
export type { ApplicantItem, ApplicantApiResponse, ApplicantPayload, } from './types/applicant';
|
|
4
4
|
export type { SavedVacancyItem, SavedVacancyApiResponse, SavedVacancyPayload, } from './types/saved-vacancy';
|
|
5
5
|
export type { Question, AnswerOption, VacancyQuestionsResponse, } from './types/questions';
|
|
6
|
+
export type { QuestionsAPIRes, ScreeningAnswersApiResNew, } from './types/easy-apply';
|
|
6
7
|
export { apiRequest } from './utils/api-request';
|
|
7
8
|
export type { ApiResponse } from './utils/api-request';
|
|
8
9
|
export { useGetAllVacancy } from './hooks/useGetAllVacancy';
|
|
@@ -13,6 +14,10 @@ export { useApplicantMutations } from './hooks/useApplicantMutations';
|
|
|
13
14
|
export { useApplicantList } from './hooks/useApplicantList';
|
|
14
15
|
export { useVacancyQuestions } from './hooks/useVacancyQuestions';
|
|
15
16
|
export { useShareJob } from './hooks/useShareJob';
|
|
17
|
+
export { useEasyApplyMutations } from './hooks/useEasyApplyMutations';
|
|
18
|
+
export type { UseEasyApplyMutationsParams } from './hooks/useEasyApplyMutations';
|
|
19
|
+
export { useEasyApplyFormHook, easyApplyUserSchema, screeningAnswerSchema, screeningAnswersSchema, } from './hooks/useEasyApplyFormHook';
|
|
20
|
+
export type { EasyApplyFormValues, EasyApplyScreeningAnswer, EasyApplyScreeningAnswers, UseEasyApplyFormHookParams, } from './hooks/useEasyApplyFormHook';
|
|
16
21
|
export { default as JobsClient } from './components/JobsClient';
|
|
17
22
|
export type { JobsClientProps } from './components/JobsClient';
|
|
18
23
|
export { default as JobDescriptionClient } from './components/JobDescriptionClient';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAGxD,YAAY,EACV,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,eAAe,GAChB,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,QAAQ,EACR,YAAY,EACZ,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAGxD,YAAY,EACV,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,eAAe,GAChB,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,QAAQ,EACR,YAAY,EACZ,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,eAAe,EACf,yBAAyB,GAC1B,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAC9E,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,YAAY,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACjF,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAChE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACpF,YAAY,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,8 @@ export { useApplicantMutations } from './hooks/useApplicantMutations';
|
|
|
11
11
|
export { useApplicantList } from './hooks/useApplicantList';
|
|
12
12
|
export { useVacancyQuestions } from './hooks/useVacancyQuestions';
|
|
13
13
|
export { useShareJob } from './hooks/useShareJob';
|
|
14
|
+
export { useEasyApplyMutations } from './hooks/useEasyApplyMutations';
|
|
15
|
+
export { useEasyApplyFormHook, easyApplyUserSchema, screeningAnswerSchema, screeningAnswersSchema, } from './hooks/useEasyApplyFormHook';
|
|
14
16
|
// Components
|
|
15
17
|
export { default as JobsClient } from './components/JobsClient';
|
|
16
18
|
export { default as JobDescriptionClient } from './components/JobDescriptionClient';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** API response for application questions (used by easy apply) */
|
|
2
|
+
export interface QuestionsAPIRes {
|
|
3
|
+
data: Array<{
|
|
4
|
+
id: string;
|
|
5
|
+
question: string;
|
|
6
|
+
type: string;
|
|
7
|
+
vacancy_id: string;
|
|
8
|
+
application_answers?: Array<{
|
|
9
|
+
id: string;
|
|
10
|
+
answer: string;
|
|
11
|
+
is_right: boolean | null;
|
|
12
|
+
}>;
|
|
13
|
+
answers?: Array<{
|
|
14
|
+
id: string;
|
|
15
|
+
answer: string;
|
|
16
|
+
is_right: boolean | null;
|
|
17
|
+
}>;
|
|
18
|
+
}>;
|
|
19
|
+
pagination?: {
|
|
20
|
+
total: number;
|
|
21
|
+
page: number;
|
|
22
|
+
pages: number;
|
|
23
|
+
nextPage: number | null;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/** API response for applicant screening answers */
|
|
27
|
+
export interface ScreeningAnswersApiResNew {
|
|
28
|
+
data: Array<{
|
|
29
|
+
id: string;
|
|
30
|
+
question_id: string;
|
|
31
|
+
answer: string;
|
|
32
|
+
is_right: boolean | null;
|
|
33
|
+
[key: string]: unknown;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=easy-apply.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"easy-apply.d.ts","sourceRoot":"","sources":["../../src/types/easy-apply.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,KAAK,CAAC;QACV,EAAE,EAAE,MAAM,CAAC;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,mBAAmB,CAAC,EAAE,KAAK,CAAC;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAA;SAAE,CAAC,CAAC;QACtF,OAAO,CAAC,EAAE,KAAK,CAAC;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAA;SAAE,CAAC,CAAC;KAC3E,CAAC,CAAC;IACH,UAAU,CAAC,EAAE;QACX,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACzB,CAAC;CACH;AAED,mDAAmD;AACnD,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,KAAK,CAAC;QACV,EAAE,EAAE,MAAM,CAAC;QACX,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;QACzB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC,CAAC;CACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,39 +1,45 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@recruitnepal/shared-packages",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Shared UI components and hooks for Recruit Nepal projects",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"build": "tsc",
|
|
9
|
-
"dev": "tsc --watch",
|
|
10
|
-
"prepublishOnly": "npm run build"
|
|
11
|
-
},
|
|
12
|
-
"keywords": [
|
|
13
|
-
"react",
|
|
14
|
-
"nextjs",
|
|
15
|
-
"recruit-nepal",
|
|
16
|
-
"shared-components"
|
|
17
|
-
],
|
|
18
|
-
"author": "",
|
|
19
|
-
"license": "MIT",
|
|
20
|
-
"peerDependencies": {
|
|
21
|
-
"react": "^18.2.0",
|
|
22
|
-
"react-dom": "^18.2.0",
|
|
23
|
-
"next": "^14.0.0",
|
|
24
|
-
"@tanstack/react-query": "^5.50.0"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
},
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@recruitnepal/shared-packages",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "Shared UI components and hooks for Recruit Nepal projects",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"dev": "tsc --watch",
|
|
10
|
+
"prepublishOnly": "npm run build"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"react",
|
|
14
|
+
"nextjs",
|
|
15
|
+
"recruit-nepal",
|
|
16
|
+
"shared-components"
|
|
17
|
+
],
|
|
18
|
+
"author": "",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"react": "^18.2.0",
|
|
22
|
+
"react-dom": "^18.2.0",
|
|
23
|
+
"next": "^14.0.0",
|
|
24
|
+
"@tanstack/react-query": "^5.50.0",
|
|
25
|
+
"zod": "^3.22.0",
|
|
26
|
+
"react-hook-form": "^7.49.0",
|
|
27
|
+
"@hookform/resolvers": "^3.3.0"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"axios": "^1.7.8"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^20.11.17",
|
|
34
|
+
"@types/react": "^18.2.55",
|
|
35
|
+
"@types/react-dom": "^18.2.19",
|
|
36
|
+
"typescript": "^5.3.3",
|
|
37
|
+
"zod": "^3.22.0",
|
|
38
|
+
"react-hook-form": "^7.49.0",
|
|
39
|
+
"@hookform/resolvers": "^3.3.0"
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"dist",
|
|
43
|
+
"README.md"
|
|
44
|
+
]
|
|
45
|
+
}
|