Organization profile update

parent e903b102
......@@ -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",
......
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
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);
}
......@@ -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);
}
......@@ -110,7 +110,7 @@ export type OrganizationType = {
description: string;
contacts: {
email: string;
phone: string[];
phone: string;
address: AddressType;
website: string;
};
......
......@@ -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>
);
......
......@@ -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");
}
......
......@@ -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(
......
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;
......@@ -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">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment