Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
E
Easy Quest - Smart Recruitment Tool with AI
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
22_23 - J 36
Easy Quest - Smart Recruitment Tool with AI
Commits
ab94d701
Commit
ab94d701
authored
May 10, 2023
by
H.M.C. Nadunithara Wijerathne
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Organization profile update
parent
e903b102
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
264 additions
and
10 deletions
+264
-10
src/common/actions/index.ts
src/common/actions/index.ts
+3
-0
src/common/actions/user.ts
src/common/actions/user.ts
+13
-1
src/common/apis/user.ts
src/common/apis/user.ts
+4
-1
src/common/saga/user.ts
src/common/saga/user.ts
+39
-1
src/common/types.ts
src/common/types.ts
+1
-1
src/components/CandidateProfile.tsx
src/components/CandidateProfile.tsx
+2
-1
src/components/Login.tsx
src/components/Login.tsx
+0
-2
src/components/Modals/ProfilePicCrop.tsx
src/components/Modals/ProfilePicCrop.tsx
+4
-1
src/components/OrganizationProfile.tsx
src/components/OrganizationProfile.tsx
+194
-0
src/views/Settings.view.tsx
src/views/Settings.view.tsx
+4
-2
No files found.
src/common/actions/index.ts
View file @
ab94d701
...
...
@@ -9,6 +9,9 @@ export enum ACTIONS {
UPDATE_CANDIDATE
=
"
UPDATE_CANDIDATE
"
,
APPLY_FOR_JOB
=
"
APPLY_FOR_JOB
"
,
UPDATE_ORG
=
"
UPDATE_ORG
"
,
SET_APP_STATE
=
"
SET_APP_STATE
"
,
SET_JOBS
=
"
SET_JOBS
"
,
...
...
src/common/actions/user.ts
View file @
ab94d701
import
{
ACTIONS
}
from
"
.
"
;
import
{
CandidateType
}
from
"
../types
"
;
import
{
CandidateType
,
OrganizationType
}
from
"
../types
"
;
export
const
updateCandidate
=
(
payload
:
Partial
<
CandidateType
>
,
...
...
@@ -10,7 +10,19 @@ export const updateCandidate = (
success
,
});
export
const
updateOrganization
=
(
payload
:
Partial
<
OrganizationType
>
,
success
?:
(
organization
:
OrganizationType
)
=>
void
)
=>
({
type
:
ACTIONS
.
UPDATE_ORG
,
payload
,
success
,
});
export
const
applyForJob
=
(
payload
:
string
)
=>
({
type
:
ACTIONS
.
APPLY_FOR_JOB
,
payload
,
});
\ No newline at end of file
src/common/apis/user.ts
View file @
ab94d701
import
{
request
}
from
"
../lib/api
"
;
import
{
CandidateType
}
from
"
../types
"
;
import
{
CandidateType
,
OrganizationType
}
from
"
../types
"
;
export
default
class
UserAPI
{
static
updateCandidate
=
(
payload
:
Partial
<
CandidateType
>
)
=>
request
(
"
<BASE_URL>/user/candidate
"
,
"
POST
"
,
payload
);
static
updateOrganization
=
(
payload
:
Partial
<
OrganizationType
>
)
=>
request
(
"
<BASE_URL>/user/organization
"
,
"
POST
"
,
payload
);
}
src/common/saga/user.ts
View file @
ab94d701
...
...
@@ -3,7 +3,7 @@ import { ACTIONS } from "../actions";
import
CommonAPI
from
"
../apis/common
"
;
import
UserAPI
from
"
../apis/user
"
;
import
{
getProfile
}
from
"
../lib/util
"
;
import
{
APP_STATE
,
CandidateType
,
JobType
,
Reducers
}
from
"
../types
"
;
import
{
APP_STATE
,
CandidateType
,
JobType
,
OrganizationType
,
Reducers
}
from
"
../types
"
;
function
*
updateCandidate
({
payload
,
...
...
@@ -40,6 +40,41 @@ function* updateCandidate({
}
}
function
*
updateOrganization
({
payload
,
success
,
}:
{
type
:
typeof
ACTIONS
.
UPDATE_ORG
;
payload
:
Partial
<
OrganizationType
>
;
success
?:
(
organization
?:
OrganizationType
|
null
)
=>
void
;
})
{
try
{
yield
put
({
type
:
ACTIONS
.
SET_APP_STATE
,
payload
:
{
state
:
APP_STATE
.
LOADING
},
});
yield
call
(
UserAPI
.
updateOrganization
,
payload
);
const
org
:
OrganizationType
=
yield
select
(
getProfile
);
const
newOrg
=
{
...
org
,
...
payload
};
yield
put
({
type
:
ACTIONS
.
SET_AUTH
,
payload
:
{
organization
:
newOrg
},
});
yield
put
({
type
:
ACTIONS
.
SET_APP_STATE
,
payload
:
{
state
:
APP_STATE
.
SUCCESS
},
});
success
?.(
newOrg
);
}
catch
(
error
)
{
yield
put
({
type
:
ACTIONS
.
SET_APP_STATE
,
payload
:
{
state
:
APP_STATE
.
FAILED
},
});
success
?.(
null
);
}
}
function
*
applyForJob
({
payload
,
}:
{
...
...
@@ -103,7 +138,10 @@ function* applyForJob({
}
}
export
default
function
*
authSaga
()
{
yield
takeLeading
(
ACTIONS
.
UPDATE_CANDIDATE
,
updateCandidate
);
yield
takeLeading
(
ACTIONS
.
UPDATE_ORG
,
updateOrganization
);
yield
takeLeading
(
ACTIONS
.
APPLY_FOR_JOB
,
applyForJob
);
}
src/common/types.ts
View file @
ab94d701
...
...
@@ -110,7 +110,7 @@ export type OrganizationType = {
description
:
string
;
contacts
:
{
email
:
string
;
phone
:
string
[]
;
phone
:
string
;
address
:
AddressType
;
website
:
string
;
};
...
...
src/components/CandidateProfile.tsx
View file @
ab94d701
...
...
@@ -5,7 +5,7 @@ import { ACTIONS } from "../common/actions";
import
{
updateCandidate
}
from
"
../common/actions/user
"
;
import
{
fileStorage
}
from
"
../common/config
"
;
import
{
getProfile
}
from
"
../common/lib/util
"
;
import
{
APP_STATE
,
CandidateType
,
OnboardSteps
}
from
"
../common/types
"
;
import
{
APP_STATE
,
CandidateType
,
OnboardSteps
,
USER_TYPE
}
from
"
../common/types
"
;
import
Avatar
from
"
./Avatar
"
;
import
Progress
from
"
./Progress
"
;
import
Onboarder
from
"
./Onboarder
"
;
...
...
@@ -402,6 +402,7 @@ const CandidateProfile = () => {
profilePicPrev=
{
profilePicPrev
}
userId=
{
profile
.
_id
}
onUpdateCandidate=
{
onUpdateCandidate
}
userType=
{
USER_TYPE
.
CANDIDATE
}
/>
</
div
>
);
...
...
src/components/Login.tsx
View file @
ab94d701
...
...
@@ -46,8 +46,6 @@ const Login = ({ userType, setAlert }: OwnProps) => {
signIn
(
data
,
(
state
)
=>
{
if
(
state
===
"
failed
"
)
{
setAlert
(
"
Attempt failed! Try again
"
);
}
else
if
(
state
===
"
INTIAL
"
)
{
navigate
(
"
/settings
"
);
}
else
{
navigate
(
"
/home
"
);
}
...
...
src/components/Modals/ProfilePicCrop.tsx
View file @
ab94d701
...
...
@@ -3,12 +3,14 @@ import { getDownloadURL, ref, uploadBytesResumable } from "firebase/storage";
import
Cropper
,
{
Area
}
from
"
react-easy-crop
"
;
import
getCroppedImg
from
"
../../common/lib/crop
"
;
import
{
fileStorage
}
from
"
../../common/config
"
;
import
{
USER_TYPE
}
from
"
../../common/types
"
;
type
OwnProps
=
{
onRequestClose
:
()
=>
void
;
profilePicPrev
:
string
|
null
;
userId
?:
string
;
onUpdateCandidate
:
(
update
:
any
)
=>
void
;
userType
:
USER_TYPE
};
const
ProfilePicCrop
=
({
...
...
@@ -16,6 +18,7 @@ const ProfilePicCrop = ({
profilePicPrev
,
userId
,
onUpdateCandidate
,
userType
}:
OwnProps
)
=>
{
const
[
progress
,
setprogress
]
=
useState
(
0
);
const
[
crop
,
setCrop
]
=
useState
({
x
:
0
,
y
:
0
});
...
...
@@ -40,7 +43,7 @@ const ProfilePicCrop = ({
const
extension
=
file
.
name
.
split
(
"
.
"
)[
1
];
const
uploadRef
=
ref
(
fileStorage
,
`/
resumes
/
${
userId
}
.
${
extension
}
`
);
const
uploadRef
=
ref
(
fileStorage
,
`/
${
userType
}
/
${
userId
}
.
${
extension
}
`
);
const
uploadTask
=
uploadBytesResumable
(
uploadRef
,
file
);
uploadTask
.
on
(
...
...
src/components/OrganizationProfile.tsx
0 → 100644
View file @
ab94d701
import
React
,
{
useState
,
useEffect
,
ChangeEvent
,
useRef
}
from
"
react
"
;
import
{
useDispatch
,
useSelector
}
from
"
react-redux
"
;
import
{
ACTIONS
}
from
"
../common/actions
"
;
import
{
updateOrganization
}
from
"
../common/actions/user
"
;
import
{
getProfile
}
from
"
../common/lib/util
"
;
import
{
APP_STATE
,
OrganizationType
,
USER_TYPE
}
from
"
../common/types
"
;
import
Avatar
from
"
./Avatar
"
;
import
ProfilePicCrop
from
"
./Modals/ProfilePicCrop
"
;
const
OrganizationProfile
=
()
=>
{
const
dispath
=
useDispatch
();
const
org
=
useSelector
(
getProfile
)
as
OrganizationType
;
const
[
profile
,
setProfile
]
=
useState
<
OrganizationType
>
(
org
);
const
[
profilePicPrev
,
setprofilePicPrev
]
=
useState
<
string
|
null
>
(
null
);
const
_profilePicInput
=
useRef
<
HTMLInputElement
>
(
null
);
useEffect
(()
=>
{
if
(
org
)
{
setProfile
(
org
);
}
},
[
org
]);
const
onChange
=
(
e
:
ChangeEvent
<
HTMLInputElement
>
)
=>
{
if
(
e
.
target
.
name
===
"
phone
"
)
{
setProfile
({
...
profile
,
contacts
:
{
...
profile
.
contacts
,
phone
:
e
.
target
.
value
},
});
}
else
{
setProfile
({
...
profile
,
[
e
.
target
.
name
]:
e
.
target
.
value
,
});
}
};
const
onChangeAddress
=
(
e
:
ChangeEvent
<
HTMLInputElement
>
)
=>
{
setProfile
({
...
profile
,
contacts
:
{
...
profile
.
contacts
,
address
:
{
...
profile
.
contacts
.
address
,
[
e
.
target
.
name
]:
e
.
target
.
value
,
},
},
});
};
const
onUpdateOrg
=
(
payload
:
Partial
<
OrganizationType
>
,
)
=>
{
dispath
(
updateOrganization
(
payload
));
};
const
onSubmit
=
async
()
=>
{
const
{
_id
,
...
rest
}
=
profile
;
dispath
({
type
:
ACTIONS
.
SET_APP_STATE
,
payload
:
{
state
:
APP_STATE
.
LOADING
},
});
onUpdateOrg
(
rest
);
};
const
onSelectProfilePic
=
(
e
:
ChangeEvent
<
HTMLInputElement
>
)
=>
{
if
(
e
.
target
.
files
)
{
setprofilePicPrev
(
URL
.
createObjectURL
(
e
.
target
.
files
[
0
]));
}
};
const
onPressUploadProfilePic
=
()
=>
{
_profilePicInput
?.
current
?.
click
();
};
const
onRequestCloseProfilePic
=
()
=>
{
setprofilePicPrev
(
null
);
};
return
(
<
div
className=
"card p-4 mb-3"
>
<
h5
>
Edit/Update profile
</
h5
>
<
div
className=
"mb-3 row"
>
<
label
className=
"col-sm-3 col-form-label"
>
Org Name
</
label
>
<
div
className=
"col-sm-9"
>
<
input
type=
"text"
className=
"form-control"
name=
"name"
value=
{
profile
.
name
}
onChange=
{
onChange
}
/>
</
div
>
</
div
>
<
div
className=
"mb-3 row"
>
<
label
className=
"col-sm-3 col-form-label"
>
Address
</
label
>
<
div
className=
"col-sm-9"
>
<
input
type=
"text"
name=
"addressLine"
className=
"form-control mb-2"
placeholder=
"Address line"
value=
{
profile
.
contacts
?.
address
?.
addressLine
}
onChange=
{
onChangeAddress
}
/>
<
input
type=
"text"
className=
"form-control mb-2"
placeholder=
"City"
name=
"city"
value=
{
profile
.
contacts
?.
address
?.
city
}
onChange=
{
onChangeAddress
}
/>
<
input
type=
"text"
className=
"form-control mb-2"
placeholder=
"Country"
name=
"country"
value=
{
profile
.
contacts
?.
address
?.
country
}
onChange=
{
onChangeAddress
}
/>
</
div
>
</
div
>
<
div
className=
"mb-3 row"
>
<
div
className=
"col-sm-6"
>
<
div
className=
"row"
>
<
label
className=
"col-sm-3 col-form-label"
>
Phone
</
label
>
<
div
className=
"col-sm-9"
>
<
input
type=
"text"
className=
"form-control"
name=
"phone"
value=
{
profile
.
contacts
?.
phone
}
onChange=
{
onChange
}
/>
</
div
>
</
div
>
</
div
>
<
div
className=
"col-sm-6"
>
<
div
className=
"row"
>
<
label
className=
"col-sm-4 col-form-label"
>
Profile picuture
</
label
>
<
div
className=
"col-sm-8"
>
<
Avatar
name=
{
profile
?.
name
}
url=
{
profile
?.
profilePicture
}
size=
"lg"
/>
<
button
type=
"button"
className=
"btn btn-link"
style=
{
{
padding
:
"
0
"
}
}
onClick=
{
onPressUploadProfilePic
}
>
Upload picture
</
button
>
</
div
>
</
div
>
</
div
>
</
div
>
<
button
type=
"button"
className=
"btn btn-primary"
style=
{
{
width
:
"
300px
"
}
}
onClick=
{
onSubmit
}
>
Update Profile
</
button
>
<
input
type=
"file"
className=
"form-control hidden-input"
accept=
"image/*"
onChange=
{
onSelectProfilePic
}
ref=
{
_profilePicInput
}
/>
<
ProfilePicCrop
onRequestClose=
{
onRequestCloseProfilePic
}
profilePicPrev=
{
profilePicPrev
}
userId=
{
profile
.
_id
}
onUpdateCandidate=
{
onUpdateOrg
}
userType=
{
USER_TYPE
.
ORGANIZATION
}
/>
</
div
>
);
};
export
default
OrganizationProfile
;
src/views/Settings.view.tsx
View file @
ab94d701
...
...
@@ -2,15 +2,17 @@ import React, { ChangeEvent, useState } from "react";
import
{
useDispatch
,
useSelector
}
from
"
react-redux
"
;
import
{
updateKeystrokeSettings
}
from
"
../common/actions/auth
"
;
import
{
DEFAULT_CONTROLS
}
from
"
../common/config
"
;
import
{
ControlsType
,
Reducers
}
from
"
../common/types
"
;
import
{
ControlsType
,
Reducers
,
USER_TYPE
}
from
"
../common/types
"
;
import
ChangePassword
from
"
../components/ChangePassword
"
;
import
Charts
from
"
../components/Charts
"
;
import
Layout
from
"
../Layouts/Layout
"
;
import
CandidateProfile
from
"
../components/CandidateProfile
"
;
import
OrganizationProfile
from
"
../components/OrganizationProfile
"
;
import
ResultTable
from
"
../components/ResultTable
"
;
const
Settings
=
()
=>
{
const
dispatch
=
useDispatch
();
const
userType
=
useSelector
((
state
:
Reducers
)
=>
state
.
auth
.
userType
)
const
keystrokeResult
=
useSelector
(
(
state
:
Reducers
)
=>
state
.
auth
.
keystrokeResult
);
...
...
@@ -54,7 +56,7 @@ const Settings = () => {
<
Layout
title=
"Profile and Settings"
>
<
div
className=
"row"
>
<
div
className=
"col-8"
>
<
CandidateProfile
/>
{
userType
===
USER_TYPE
.
CANDIDATE
?
<
CandidateProfile
/>
:
<
OrganizationProfile
/>
}
<
ChangePassword
/>
</
div
>
<
div
className=
"col-4"
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment