-
-
-
- Password
-
-
-
-
-
+ {isCalledFromSettings && (
+
+
+
+
+
+ Password
+
+
+
+
+
+
-
+ )}
);
diff --git a/app/javascript/src/components/Profile/UserDetail/UserDetailsView/index.tsx b/app/javascript/src/components/Profile/Personal/User/index.tsx
similarity index 64%
rename from app/javascript/src/components/Profile/UserDetail/UserDetailsView/index.tsx
rename to app/javascript/src/components/Profile/Personal/User/index.tsx
index add5b182fe..ef1f91a768 100644
--- a/app/javascript/src/components/Profile/UserDetail/UserDetailsView/index.tsx
+++ b/app/javascript/src/components/Profile/Personal/User/index.tsx
@@ -1,15 +1,12 @@
-/* eslint-disable @typescript-eslint/no-var-requires */
-
import React, { Fragment, useEffect, useState } from "react";
-import { Outlet, useNavigate } from "react-router-dom";
+import { Outlet, useNavigate, useParams } from "react-router-dom";
-import profileApi from "apis/profile";
import teamsApi from "apis/teams";
import Loader from "common/Loader/index";
import { MobileEditHeader } from "common/Mobile/MobileEditHeader";
-import { useProfile } from "components/Profile/context/EntryContext";
-import DetailsHeader from "components/Profile/DetailsHeader";
+import DetailsHeader from "components/Profile/Common/DetailsHeader";
+import { useProfileContext } from "context/Profile/ProfileContext";
import { useUserContext } from "context/UserContext";
import { employmentMapper, teamsMapper } from "mapper/teams.mapper";
import { sendGAPageView } from "utils/googleAnalytics";
@@ -18,32 +15,35 @@ import MobilePersonalDetails from "./MobilePersonalDetails";
import StaticPage from "./StaticPage";
const UserDetailsView = () => {
- const { setUserState, profileSettings } = useProfile();
+ const { updateDetails, personalDetails, isCalledFromSettings } =
+ useProfileContext();
const [isLoading, setIsLoading] = useState(false);
- const { isDesktop, companyRole } = useUserContext();
+ const { user, isDesktop, companyRole } = useUserContext();
+ const { memberId } = useParams();
+ const UserId = window.location.pathname.startsWith("/settings")
+ ? user.id
+ : memberId;
const getData = async () => {
setIsLoading(true);
- const res = await profileApi.index();
+ const res = await teamsApi.get(UserId);
if (res.status && res.status == 200) {
- const addressData = await profileApi.getAddress(res.data.user.id);
- const userObj = teamsMapper(res.data.user, addressData.data.addresses[0]);
+ const addressData = await teamsApi.getAddress(UserId);
+ const userObj = teamsMapper(res.data, addressData.data.addresses[0]);
- setUserState("profileSettings", userObj);
+ updateDetails("personalDetails", userObj);
if (companyRole !== "client") {
- const employmentData: any = await teamsApi.getEmploymentDetails(
- res?.data?.user.id
- );
+ const employmentData: any = await teamsApi.getEmploymentDetails(UserId);
const previousEmploymentData: any =
- await teamsApi.getPreviousEmployments(res?.data?.user.id);
+ await teamsApi.getPreviousEmployments(UserId);
if (employmentData.status && employmentData.status == 200) {
const employmentObj = employmentMapper(
employmentData.data.employment,
previousEmploymentData.data.previous_employments
);
- setUserState("employmentDetails", employmentObj);
+ updateDetails("employmentDetails", employmentObj);
}
}
setIsLoading(false);
@@ -60,7 +60,7 @@ const UserDetailsView = () => {
const navigate = useNavigate();
const handleEditClick = () => {
- navigate(`/settings/profile/edit`, { replace: true });
+ navigate(`edit`, { replace: true });
};
return (
@@ -79,7 +79,8 @@ const UserDetailsView = () => {
) : (
)}
@@ -87,16 +88,19 @@ const UserDetailsView = () => {
{!isDesktop && (
{isLoading ? (
) : (
)}
diff --git a/app/javascript/src/components/Profile/RouteConfig.tsx b/app/javascript/src/components/Profile/RouteConfig.tsx
deleted file mode 100644
index 1982b5f5ec..0000000000
--- a/app/javascript/src/components/Profile/RouteConfig.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-import React, { useEffect } from "react";
-
-import { Routes, Route, Navigate } from "react-router-dom";
-
-import profileApi from "apis/profile";
-import ErrorPage from "common/Error";
-import { useUserContext } from "context/UserContext";
-import { teamsMapper } from "mapper/teams.mapper";
-
-import { useProfile } from "./context/EntryContext";
-import { SETTINGS_ROUTES } from "./routes";
-
-const ProtectedRoute = ({ role, authorisedRoles, children }) => {
- if (authorisedRoles.includes(role)) {
- return children;
- }
-
- return
;
-};
-
-const RouteConfig = () => {
- const { companyRole } = useUserContext();
- const {
- setUserState,
- profileSettings: { first_name, last_name },
- } = useProfile();
-
- const getData = async () => {
- if (!first_name && !last_name) {
- const res = await profileApi.index();
- if (res.status && res.status == 200) {
- const addressData = await profileApi.getAddress(res.data.user.id);
- const userObj = teamsMapper(
- res.data.user,
- addressData.data.addresses[0]
- );
- setUserState("profileSettings", userObj);
- }
- }
- };
-
- useEffect(() => {
- getData();
- }, []);
-
- return (
-
- {SETTINGS_ROUTES.map(({ path, authorisedRoles, Component }) => (
-
-
-
- }
- />
- ))}
- } path="*" />
-
- );
-};
-
-export default RouteConfig;
diff --git a/app/javascript/src/components/Team/Details/EmploymentDetails/Edit/validationSchema.ts b/app/javascript/src/components/Profile/Schema/employmentSchema.ts
similarity index 100%
rename from app/javascript/src/components/Team/Details/EmploymentDetails/Edit/validationSchema.ts
rename to app/javascript/src/components/Profile/Schema/employmentSchema.ts
diff --git a/app/javascript/src/components/Profile/SubNav.tsx b/app/javascript/src/components/Profile/SubNav.tsx
deleted file mode 100644
index 76150998b1..0000000000
--- a/app/javascript/src/components/Profile/SubNav.tsx
+++ /dev/null
@@ -1,152 +0,0 @@
-/* eslint-disable @typescript-eslint/no-var-requires */
-import React, { useState } from "react";
-
-import { MinusIcon, PlusIcon } from "miruIcons";
-import { NavLink } from "react-router-dom";
-
-import { useUserContext } from "context/UserContext";
-
-import UserInformation from "./CommonComponents/UserInformation";
-import { companySettingsList, personalSettingsList } from "./constants";
-
-const SubNav = ({ isAdmin, firstName, company, lastName, designation }) => {
- const { companyRole } = useUserContext();
-
- const getActiveClassName = isActive => {
- if (isActive) {
- return "pl-4 py-5 border-l-8 border-miru-han-purple-600 bg-miru-gray-200 text-miru-han-purple-600 block w-full flex items-center";
- }
-
- return "pl-6 py-5 border-b-1 border-miru-gray-400 block w-full flex items-center";
- };
-
- const [openedSubNav, setOpenedSubNav] = useState({
- personal: true,
- company: false,
- });
-
- const getAdminLinks = () => (
-
-
- setOpenedSubNav({
- ...openedSubNav,
- personal: !openedSubNav.personal,
- })
- }
- >
-
Personal
-
-
- {openedSubNav.personal && (
-
- {personalSettingsList.map((setting, index) => {
- if (setting.authorisedRoles.includes(companyRole)) {
- return (
- -
-
-
- );
- }
- })}
-
- )}
-
- setOpenedSubNav({ ...openedSubNav, company: !openedSubNav.company })
- }
- >
-
{company.name}
-
-
- {openedSubNav.company && (
-
- {companySettingsList.map((setting, index) => {
- if (setting.authorisedRoles.includes(companyRole)) {
- return (
- -
-
-
- );
- }
- })}
-
- )}
-
- );
-
- const getEmployeeLinks = () => (
-
- {personalSettingsList.map((setting, index) => {
- if (setting.authorisedRoles.includes(companyRole)) {
- return (
- -
-
-
- );
- }
- })}
-
- );
-
- const SideBarNavItem = ({ label, link, icon }) => (
-
getActiveClassName(isActive)}
- to={link}
- >
- {icon}
- {label}
-
- );
-
- return (
-
-
-
- {isAdmin ? getAdminLinks() : getEmployeeLinks()}
-
-
- );
-};
-
-export default SubNav;
diff --git a/app/javascript/src/components/Profile/UserDetail/index.tsx b/app/javascript/src/components/Profile/UserDetail/index.tsx
deleted file mode 100644
index 12aff71ab5..0000000000
--- a/app/javascript/src/components/Profile/UserDetail/index.tsx
+++ /dev/null
@@ -1,456 +0,0 @@
-/* eslint-disable @typescript-eslint/no-var-requires */
-
-import React, { useEffect, useState } from "react";
-
-import {
- DeleteIconSVG,
- EditImageButtonSVG,
- PasswordIconSVG,
- PasswordIconTextSVG,
- PlusIconSVG,
-} from "miruIcons";
-import { Toastr } from "StyledComponents";
-import * as Yup from "yup";
-
-import profileApi from "apis/profile";
-import { Divider } from "common/Divider";
-import Loader from "common/Loader/index";
-import { sendGAPageView } from "utils/googleAnalytics";
-
-import { useProfile } from "../context/EntryContext";
-import Header from "../Header";
-
-const userProfileSchema = Yup.object().shape({
- firstName: Yup.string().required("First Name cannot be blank"),
- lastName: Yup.string().required("Last Name cannot be blank"),
- changePassword: Yup.boolean(),
- password: Yup.string().when("changePassword", {
- is: true,
- then: Yup.string().required("Please enter password"),
- }),
- currentPassword: Yup.string().when("changePassword", {
- is: true,
- then: Yup.string().required("Please enter current password"),
- }),
-
- confirmPassword: Yup.string().when("changePassword", {
- is: true,
- then: Yup.string().oneOf(
- [Yup.ref("password"), null],
- "Passwords don't match"
- ),
- }),
-});
-
-const UserDetails = () => {
- const initialErrState = {
- firstNameErr: "",
- lastNameErr: "",
- passwordErr: "",
- currentPasswordErr: "",
- confirmPasswordErr: "",
- };
-
- const { setUserState } = useProfile();
- const [profileImage, setProfileImage] = useState("");
- const [imageFile, setImageFile] = useState(null);
- const [firstName, setFirstName] = useState("");
- const [lastName, setLastName] = useState("");
- const [email, setEmail] = useState("");
- const [currentPassword, setCurrentPassword] = useState("");
- const [password, setPassword] = useState("");
- const [confirmPassword, setConfirmPassword] = useState("");
- const [changePassword, setChangePassword] = useState
(false);
- const [showPassword, setShowPassword] = useState(false);
- const [showCurrentPassword, setShowCurrentPassword] =
- useState(false);
-
- const [showConfirmPassword, setShowConfirmPassword] =
- useState(false);
- const [isDetailUpdated, setIsDetailUpdated] = useState(false);
- const [errDetails, setErrDetails] = useState(initialErrState);
- const [isLoading, setIsLoading] = useState(false);
-
- const handleProfileImageChange = e => {
- const imageFile = e.target.files[0];
- setProfileImage(URL.createObjectURL(imageFile));
- setImageFile(imageFile);
- setIsDetailUpdated(true);
- };
-
- const handleUpdateProfile = async () => {
- try {
- await userProfileSchema.validate(
- {
- firstName,
- lastName,
- changePassword,
- password,
- confirmPassword,
- currentPassword,
- },
- { abortEarly: false }
- );
- await updateProfile();
- } catch (err) {
- setIsLoading(false);
- const errObj = initialErrState;
- err.inner.map(item => {
- errObj[`${item.path}Err`] = item.message;
- });
- setErrDetails(errObj);
- }
- };
-
- const updateProfile = async () => {
- try {
- setIsLoading(true);
- const formD = new FormData();
- formD.append("user[first_name]", firstName);
- formD.append("user[last_name]", lastName);
- if (changePassword) {
- formD.append("user[current_password]", currentPassword);
- formD.append("user[password]", password);
- formD.append("user[password_confirmation]", confirmPassword);
- }
-
- if (imageFile) {
- formD.append("user[avatar]", imageFile);
- }
- await profileApi.update(formD);
- setIsDetailUpdated(false);
- setErrDetails(initialErrState);
- setUserState("profileSettings", {
- firstName,
- lastName,
- });
- setIsLoading(false);
- } catch {
- setIsLoading(false);
- Toastr.error("Error in Updating user Details");
- }
- };
-
- const handleFirstNameChange = event => {
- setFirstName(event.target.value);
- setIsDetailUpdated(true);
- setErrDetails({ ...errDetails, firstNameErr: "" });
- };
-
- const handleLastNameChange = event => {
- setLastName(event.target.value);
- setIsDetailUpdated(true);
- setErrDetails({ ...errDetails, lastNameErr: "" });
- };
-
- const handleCurrentPasswordChange = event => {
- setCurrentPassword(event.target.value);
- setIsDetailUpdated(true);
- setErrDetails({ ...errDetails, currentPasswordErr: "" });
- };
-
- const handlePasswordChange = event => {
- setPassword(event.target.value);
- setIsDetailUpdated(true);
- setErrDetails({ ...errDetails, passwordErr: "" });
- };
-
- const handleConfirmPasswordChange = event => {
- setConfirmPassword(event.target.value);
- setIsDetailUpdated(true);
- };
-
- const getData = async () => {
- setIsLoading(true);
- const data = await profileApi.index();
- if (data.status && data.status == 200) {
- setFirstName(data.data.user.first_name);
- setLastName(data.data.user.last_name);
- setProfileImage(data.data.user.avatar_url);
- setEmail(data.data.user.email);
- setUserState("profileSettings", {
- firstName: data.data.user.first_name,
- lastName: data.data.user.last_name,
- email: data.data.user.email,
- });
- setIsLoading(false);
- } else {
- setFirstName("");
- setLastName("");
- setProfileImage("");
- setEmail("");
- setIsLoading(false);
- }
- };
-
- useEffect(() => {
- sendGAPageView();
- getData();
- }, []);
-
- const handleCancelAction = () => {
- getData();
- setIsDetailUpdated(false);
- setErrDetails(initialErrState);
- setChangePassword(false);
- setCurrentPassword("");
- setPassword("");
- setConfirmPassword("");
- };
-
- const handleDeleteLogo = async () => {
- const removeProfile = await profileApi.removeAvatar();
- if (removeProfile.status === 200) {
- setImageFile(null);
- setProfileImage("");
- }
- };
-
- const getErr = errMsg => {errMsg}
;
-
- return (
-
-
- {isLoading ? (
-
-
-
- ) : (
-
-
-
Basic Details
-
- Profile Picture
- {profileImage ? (
-
- ) : (
- <>
-
-
-
-
- >
- )}
-
-
-
- setEmail(event.target.value)}
- />
-
-
-
-
-
-
Password
-
-
- {!changePassword && (
-
-
setChangePassword(true)}
- >
- CHANGE PASSWORD
-
-
- )}
- {changePassword && (
-
-
-
-
-
-
-
-
- {errDetails.currentPasswordErr &&
- getErr(errDetails.currentPasswordErr)}
-
-
-
-
-
-
-
-
- {errDetails.passwordErr &&
- getErr(errDetails.passwordErr)}
-
-
-
-
-
-
-
- {errDetails.confirmPasswordErr &&
- getErr(errDetails.confirmPasswordErr)}
-
-
-
{
- setChangePassword(false);
- setErrDetails(initialErrState);
- }}
- >
- CANCEL
-
-
-
- )}
-
-
-
-
- )}
-
- );
-};
-
-export default UserDetails;
diff --git a/app/javascript/src/components/Profile/constants.js b/app/javascript/src/components/Profile/constants.js
deleted file mode 100644
index 317fb0f3d7..0000000000
--- a/app/javascript/src/components/Profile/constants.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import React from "react";
-
-import {
- ClientsIcon as BuildingsIcon,
- CalendarIcon,
- CakeIcon,
- PaymentsIcon,
- UserIcon,
- MobileIcon,
- ProjectsIcon,
-} from "miruIcons";
-
-import { Roles } from "constants/index";
-
-const { ADMIN, OWNER, BOOK_KEEPER, EMPLOYEE, CLIENT } = Roles;
-
-export const personalSettingsList = [
- {
- label: "PROFILE SETTINGS",
- link: "/settings/profile",
- icon: ,
- authorisedRoles: [ADMIN, OWNER, BOOK_KEEPER, EMPLOYEE, CLIENT],
- },
- {
- label: "EMPLOYMENT DETAILS",
- link: "/settings/employment",
- icon: ,
- authorisedRoles: [ADMIN, OWNER, BOOK_KEEPER, EMPLOYEE],
- },
- {
- label: "ALLOCATED DEVICES",
- link: "/settings/devices",
- icon: ,
- authorisedRoles: [ADMIN, OWNER, BOOK_KEEPER, EMPLOYEE],
- },
- //TODO: Uncomment when Integrating with API
- // {
- // label: "COMPENSATION",
- // link: "/settings/compensation",
- // icon: ,
- // authorisedRoles: [ADMIN, OWNER, BOOK_KEEPER, EMPLOYEE],
- // },
-];
-
-export const companySettingsList = [
- {
- label: "ORG. SETTINGS",
- link: "/settings/organization",
- icon: ,
- authorisedRoles: [ADMIN, OWNER],
- },
- {
- label: "PAYMENT SETTINGS",
- link: "/settings/payment",
- icon: ,
- authorisedRoles: [ADMIN, OWNER],
- },
- {
- label: "LEAVES",
- link: "/settings/leaves",
- icon: ,
- authorisedRoles: [ADMIN, OWNER],
- },
- {
- label: "HOLIDAYS",
- link: "/settings/holidays",
- icon: ,
- authorisedRoles: [ADMIN, OWNER],
- },
- // {
- // label: "Integration",
- // link: "/settings/integrations",
- // icon: ,
- // authorisedRoles: [ADMIN, OWNER],
- // },
-];
diff --git a/app/javascript/src/components/Profile/context/EntryContext.tsx b/app/javascript/src/components/Profile/context/EntryContext.tsx
deleted file mode 100644
index 8fa61bc78b..0000000000
--- a/app/javascript/src/components/Profile/context/EntryContext.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import { createContext, useContext } from "react";
-
-import { CompensationDetailsState } from "./CompensationDetailsState";
-import { EmploymentDetailsState } from "./EmploymentDetailsState";
-import { PersonalDetailsState } from "./PersonalDetailsState";
-
-const EntryContext = createContext({
- profileSettings: PersonalDetailsState,
- employmentDetails: EmploymentDetailsState,
- compensationDetails: CompensationDetailsState,
- organizationSettings: {},
- bankAccDetails: {},
- paymentSettings: {},
- billing: {},
- setUserState: (key, value) => {}, //eslint-disable-line
-});
-
-export const useProfile = () => useContext(EntryContext);
-
-export default EntryContext;
diff --git a/app/javascript/src/components/Profile/index.tsx b/app/javascript/src/components/Profile/index.tsx
new file mode 100644
index 0000000000..3ad5076614
--- /dev/null
+++ b/app/javascript/src/components/Profile/index.tsx
@@ -0,0 +1,98 @@
+import React, { Fragment, useState, useEffect } from "react";
+
+import { useLocation, useParams } from "react-router-dom";
+
+import { ProfileContext } from "context/Profile/ProfileContext";
+import { useUserContext } from "context/UserContext";
+
+import { CompensationDetailsState } from "./Context/CompensationDetailsState";
+import { EmploymentDetailsState } from "./Context/EmploymentDetailsState";
+import { PersonalDetailsState } from "./Context/PersonalDetailsState";
+import Header from "./Layout/Header";
+import SideNav from "./Layout/Navigation";
+import MobileNav from "./Layout/Navigation/MobileNav";
+import OutletWrapper from "./Layout/OutletWrapper";
+
+const Layout = () => {
+ const { isDesktop } = useUserContext();
+ const location = useLocation();
+ const { memberId } = useParams();
+ const [settingsStates, setSettingsStates] = useState({
+ personalDetails: PersonalDetailsState,
+ employmentDetails: EmploymentDetailsState,
+ documentDetails: {},
+ deviceDetails: {},
+ compensationDetails: CompensationDetailsState,
+ reimburstmentDetails: {},
+ });
+
+ const [isCalledFromSettings, setIsCalledFromSettings] = useState(false);
+ const [isCalledFromTeam, setIsCalledFromTeam] = useState(false);
+ const [showMobileNav, setShowMobileNav] = useState(false);
+
+ useEffect(() => {
+ if (location.pathname.startsWith("/settings")) {
+ setIsCalledFromSettings(true);
+ } else {
+ setIsCalledFromSettings(false);
+ }
+
+ if (location.pathname.startsWith("/team")) {
+ setIsCalledFromTeam(true);
+ } else {
+ setIsCalledFromTeam(false);
+ }
+
+ const mobileNavVisibility =
+ location.pathname === "/settings" ||
+ location.pathname === "/settings/" ||
+ location.pathname === `/team/${memberId}` ||
+ location.pathname === `/team/${memberId}/`;
+
+ setShowMobileNav(mobileNavVisibility);
+ }, [location]);
+
+ const updateDetails = (key, value) => {
+ setSettingsStates(previousSettings => ({
+ ...previousSettings,
+ ...{ [key]: { ...previousSettings[key], ...value } },
+ }));
+ };
+
+ return (
+
+ {isDesktop && (
+
+
+
+
+
+
+ )}
+ {!isDesktop && (
+
+ {showMobileNav && }
+
+
+ )}
+
+ );
+};
+
+export default Layout;
diff --git a/app/javascript/src/components/Profile/routes.ts b/app/javascript/src/components/Profile/routes.ts
deleted file mode 100644
index 7ff1b29e98..0000000000
--- a/app/javascript/src/components/Profile/routes.ts
+++ /dev/null
@@ -1,106 +0,0 @@
-import { Roles } from "constants/index";
-
-import MobileNav from "./Layout/MobileNav";
-import OrgDetails from "./Organization/Details";
-import OrgEdit from "./Organization/Edit";
-import Holidays from "./Organization/Holidays";
-import Leaves from "./Organization/Leaves";
-import PaymentSettings from "./Organization/Payment";
-import AllocatedDevicesDetails from "./UserDetail/AllocatedDevicesDetails";
-import AllocatedDevicesEdit from "./UserDetail/AllocatedDevicesDetails/Edit";
-import CompensationDetails from "./UserDetail/CompensationDetails";
-import CompensationDetailsEdit from "./UserDetail/CompensationDetails/Edit";
-import UserDetailsEdit from "./UserDetail/Edit";
-import EmploymentDetails from "./UserDetail/EmploymentDetails";
-import EmploymentDetailsEdit from "./UserDetail/EmploymentDetails/Edit";
-import UserDetailsView from "./UserDetail/UserDetailsView";
-
-const { ADMIN, OWNER, BOOK_KEEPER, EMPLOYEE, CLIENT } = Roles;
-
-export const SETTINGS_ROUTES = [
- {
- path: "/profile",
- Component: UserDetailsView,
- authorisedRoles: [ADMIN, OWNER, BOOK_KEEPER, EMPLOYEE, CLIENT],
- },
- {
- path: "/profile/edit",
- Component: UserDetailsEdit,
- authorisedRoles: [ADMIN, OWNER, BOOK_KEEPER, EMPLOYEE, CLIENT],
- },
- {
- path: "/employment",
- Component: EmploymentDetails,
- authorisedRoles: [ADMIN, OWNER, BOOK_KEEPER, EMPLOYEE],
- },
- {
- path: "/employment/edit",
- Component: EmploymentDetailsEdit,
- authorisedRoles: [ADMIN, OWNER, BOOK_KEEPER, EMPLOYEE],
- },
- {
- path: "/devices",
- Component: AllocatedDevicesDetails,
- authorisedRoles: [ADMIN, OWNER, BOOK_KEEPER, EMPLOYEE],
- },
- {
- path: "/devices/edit",
- Component: AllocatedDevicesEdit,
- authorisedRoles: [ADMIN, OWNER, BOOK_KEEPER, EMPLOYEE],
- },
- {
- path: "/compensation",
- Component: CompensationDetails,
- authorisedRoles: [ADMIN, OWNER, BOOK_KEEPER, EMPLOYEE],
- },
- {
- path: "/compensation/edit",
- Component: CompensationDetailsEdit,
- authorisedRoles: [ADMIN, OWNER, BOOK_KEEPER, EMPLOYEE],
- },
- {
- path: "/",
- Component: MobileNav,
- authorisedRoles: [ADMIN, OWNER, BOOK_KEEPER, EMPLOYEE, CLIENT],
- },
- {
- path: "/organization",
- Component: OrgDetails,
- authorisedRoles: [ADMIN, OWNER],
- },
- {
- path: "/organization/edit",
- Component: OrgEdit,
- authorisedRoles: [ADMIN, OWNER],
- },
- {
- path: "/payment",
- Component: PaymentSettings,
- authorisedRoles: [ADMIN, OWNER],
- },
- // {
- // path: "/import",
- // Component: OrganizationImport,
- // authorisedRoles: [ADMIN, OWNER],
- // },
- // {
- // path: "/billing",
- // Component: Billing,
- // authorisedRoles: [ADMIN, OWNER],
- // },
- {
- path: "/leaves",
- Component: Leaves,
- authorisedRoles: [ADMIN, OWNER],
- },
- {
- path: "/holidays",
- Component: Holidays,
- authorisedRoles: [ADMIN, OWNER],
- },
- // {
- // path: "/integrations",
- // Component: GoogleCalendar,
- // authorisedRoles: [ADMIN, OWNER],
- // },
-];
diff --git a/app/javascript/src/components/Team/Details/CompensationDetails/CompensationDetailsState.tsx b/app/javascript/src/components/Team/Details/CompensationDetails/CompensationDetailsState.tsx
deleted file mode 100644
index f993aa7b2d..0000000000
--- a/app/javascript/src/components/Team/Details/CompensationDetails/CompensationDetailsState.tsx
+++ /dev/null
@@ -1,7 +0,0 @@
-export const CompensationDetailsState = {
- earnings: [],
- deductions: [],
- total: {
- amount: 0,
- },
-};
diff --git a/app/javascript/src/components/Team/Details/CompensationDetails/Edit/EditPage.tsx b/app/javascript/src/components/Team/Details/CompensationDetails/Edit/EditPage.tsx
deleted file mode 100644
index 235addf5ad..0000000000
--- a/app/javascript/src/components/Team/Details/CompensationDetails/Edit/EditPage.tsx
+++ /dev/null
@@ -1,170 +0,0 @@
-import React from "react";
-
-import { currencyFormat } from "helpers";
-import {
- DeleteIcon,
- CoinsIcon,
- EarningsIconSVG,
- DeductionIconSVG,
-} from "miruIcons";
-import "react-phone-number-input/style.css";
-import { Button } from "StyledComponents";
-
-import { CustomInputText } from "common/CustomInputText";
-
-const EditPage = ({
- handleAddEarning,
- handleAddDeduction,
- updateDeductionValues,
- updateEarningsValues,
- handleDeleteEarning,
- handleDeleteDeduction,
- earnings,
- deductions,
- total,
- currency,
-}) => (
-
-
-
-
-
- Earnings
-
-
-
- {earnings.length > 0 &&
- earnings.map((earning, index) => (
-
-
-
- {
- updateEarningsValues(earning, e);
- }}
- />
-
-
- {
- updateEarningsValues(earning, e);
- }}
- />
-
-
-
-
- ))}
-
-
-
-
-
-
-
- Deductions
-
-
-
- {deductions.length > 0 &&
- deductions.map((deduction, index) => (
-
-
-
- {
- updateDeductionValues(deduction, e);
- }}
- />
-
-
- {
- updateDeductionValues(deduction, e);
- }}
- />
-
-
-
-
- ))}
-
-
-
-
-
-
-
-
-
-
- Total
-
-
-
-
- {currencyFormat(currency, total)}
-
-
-
-
-);
-
-export default EditPage;
diff --git a/app/javascript/src/components/Team/Details/CompensationDetails/Edit/MobileEditPage.tsx b/app/javascript/src/components/Team/Details/CompensationDetails/Edit/MobileEditPage.tsx
deleted file mode 100644
index e700055902..0000000000
--- a/app/javascript/src/components/Team/Details/CompensationDetails/Edit/MobileEditPage.tsx
+++ /dev/null
@@ -1,192 +0,0 @@
-import React from "react";
-
-import { currencyFormat } from "helpers";
-import {
- CoinsIcon,
- DeductionIconSVG,
- DeleteIcon,
- EarningsIconSVG,
-} from "miruIcons";
-import "react-phone-number-input/style.css";
-import { Button } from "StyledComponents";
-
-import { CustomInputText } from "common/CustomInputText";
-
-const MobileEditPage = ({
- handleAddEarning,
- handleAddDeduction,
- updateDeductionValues,
- updateEarningsValues,
- handleDeleteEarning,
- handleDeleteDeduction,
- handleCancelDetails,
- handleUpdateDetails,
- earnings,
- deductions,
- total,
- currency,
-}) => (
-
-
-
-
-
- Earnings
-
-
-
- {earnings.length > 0 ? (
- earnings.map((earning, index) => (
-
-
-
- {
- updateEarningsValues(earning, e);
- }}
- />
-
-
-
-
- {
- updateEarningsValues(earning, e);
- }}
- />
-
-
- ))
- ) : (
-
No Earnings found
- )}
-
-
-
-
-
-
-
-
-
- Deductions
-
-
-
- {deductions.length > 0 ? (
- deductions.map((deduction, index) => (
-
-
-
- {
- updateDeductionValues(deduction, e);
- }}
- />
-
-
-
-
- {
- updateDeductionValues(deduction, e);
- }}
- />
-
-
- ))
- ) : (
-
No deductions found
- )}
-
-
-
-
-
-
-
-
-
- Total
-
-
-
-
- {currencyFormat(currency, total)}
-
-
-
-
-
-
-
-
-
-
-
-
-);
-
-export default MobileEditPage;
diff --git a/app/javascript/src/components/Team/Details/CompensationDetails/Edit/index.tsx b/app/javascript/src/components/Team/Details/CompensationDetails/Edit/index.tsx
deleted file mode 100644
index 214ef161e9..0000000000
--- a/app/javascript/src/components/Team/Details/CompensationDetails/Edit/index.tsx
+++ /dev/null
@@ -1,153 +0,0 @@
-/* eslint-disable no-unused-vars */
-import React, { Fragment, useEffect, useState } from "react";
-
-import { useNavigate } from "react-router-dom";
-
-import Loader from "common/Loader/index";
-import { CompensationDetailsState } from "components/Profile/context/CompensationDetailsState";
-import Header from "components/Profile/Header";
-import { useUserContext } from "context/UserContext";
-
-import EditPage from "./EditPage";
-import MobileEditPage from "./MobileEditPage";
-
-const CompensationEditPage = () => {
- //TODO: add state for errDetails after API integration
- // const initialErrState = {
- // earning_type_err: "",
- // earning_amount_err: "",
- // deduction_type_err: "",
- // deduction_amount_err: "",
- // };
- const navigate = useNavigate();
- const { isDesktop, company } = useUserContext();
-
- const [isLoading, setIsLoading] = useState(false);
- const [earnings, setEarnings] = useState>(
- CompensationDetailsState.earnings
- );
-
- const [deductions, setDeductions] = useState>(
- CompensationDetailsState.deductions
- );
-
- const [total, setTotal] = useState(
- CompensationDetailsState.total.amount
- );
-
- useEffect(() => {
- setIsLoading(true);
- getDevicesDetail();
- }, []);
-
- useEffect(() => {
- const totalEarnings = earnings.reduce(
- (accumulator, currentValue) => accumulator + currentValue["amount"],
- 0
- );
-
- const totalDeductions = deductions.reduce(
- (accumulator, currentValue) => accumulator + currentValue["amount"],
- 0
- );
- setTotal(totalEarnings - totalDeductions);
- }, [deductions, earnings]);
-
- const getDevicesDetail = async () => {
- setIsLoading(false);
- };
-
- const handleAddDeduction = () => {
- const newDeduction = [...deductions, { deduction_type: "", amount: "" }];
- setDeductions(newDeduction);
- };
-
- const handleAddEarning = () => {
- const newEarning = [...earnings, { earning_type: "", amount: "" }];
- setEarnings(newEarning);
- };
-
- const handleDeleteDeduction = deduction => {
- setDeductions(deductions.filter(d => d !== deduction));
- };
-
- const handleDeleteEarning = earning => {
- setEarnings(earnings.filter(e => e !== earning));
- };
-
- const updateEarningsValues = (earning, event) => {
- const { name, value } = event.target;
- const updatedEarnings = earnings.map(e =>
- e == earning ? { ...e, [name]: value } : e
- );
- setEarnings(updatedEarnings);
- };
-
- const updateDeductionValues = (deduction, event) => {
- const { name, value } = event.target;
- const updatedDeductions = deductions.map(d =>
- d == deduction ? { ...d, [name]: value } : d
- );
- setDeductions(updatedDeductions);
- };
-
- const handleUpdateDetails = () => {
- //Todo: API integration for update details
- };
-
- const handleCancelDetails = () => {
- setIsLoading(true);
- navigate(`/settings/compensation`, { replace: true });
- };
-
- return (
-
-
- {isLoading ? (
-
- ) : (
-
- {isDesktop && (
-
- )}
- {!isDesktop && (
-
- )}
-
- )}
-
- );
-};
-
-export default CompensationEditPage;
diff --git a/app/javascript/src/components/Team/Details/CompensationDetails/StaticPage.tsx b/app/javascript/src/components/Team/Details/CompensationDetails/StaticPage.tsx
deleted file mode 100644
index 42c702af43..0000000000
--- a/app/javascript/src/components/Team/Details/CompensationDetails/StaticPage.tsx
+++ /dev/null
@@ -1,100 +0,0 @@
-import React from "react";
-
-import { currencyFormat } from "helpers";
-import { EarningsIconSVG, DeductionIconSVG, CoinsIcon } from "miruIcons";
-
-const StaticPage = ({ compensationDetails, currency }) => {
- const { earnings, deductions, total } = compensationDetails;
-
- return (
-
-
-
-
-
- Earnings
-
-
-
- {earnings ? (
- earnings.map((earning, index) => (
-
-
-
- Earning Type
-
-
- {earning.type || "-"}
-
-
-
-
- Amount
-
-
- {currencyFormat(currency, earning.amount) || "-"}
-
-
-
- ))
- ) : (
-
No earning(s) found
- )}
-
-
-
-
-
-
- Deductions
-
-
-
- {deductions ? (
- deductions.map((deduction, index) => (
-
-
-
- Deduction Type
-
-
- {deduction.type}
-
-
-
-
- Amount
-
-
- {currencyFormat(currency, deduction.amount) || "-"}
-
-
-
- ))
- ) : (
-
No deduction(s) found
- )}
-
-
-
-
-
-
- Total
-
-
-
-
- {currencyFormat(currency, total.amount)}
-
-
-
-
- );
-};
-
-export default StaticPage;
diff --git a/app/javascript/src/components/Team/Details/CompensationDetails/index.tsx b/app/javascript/src/components/Team/Details/CompensationDetails/index.tsx
deleted file mode 100644
index b7e3eb9ae0..0000000000
--- a/app/javascript/src/components/Team/Details/CompensationDetails/index.tsx
+++ /dev/null
@@ -1,71 +0,0 @@
-import React, { Fragment, useEffect, useState } from "react";
-
-import { useNavigate } from "react-router-dom";
-
-import Loader from "common/Loader/index";
-import { MobileEditHeader } from "common/Mobile/MobileEditHeader";
-import { useProfile } from "components/Profile/context/EntryContext";
-import DetailsHeader from "components/Profile/DetailsHeader";
-import { useUserContext } from "context/UserContext";
-
-import StaticPage from "./StaticPage";
-
-const CompensationDetails = () => {
- const { isDesktop, company } = useUserContext();
- const { setUserState, compensationDetails } = useProfile();
- const navigate = useNavigate();
- const [isLoading, setIsLoading] = useState(false);
-
- const getDetails = async () => {
- //fetch compensation details from backend and store it in compensationData
- const compensationData = {
- earnings: [
- { type: "Monthly Salary", amount: "125000" },
- { type: "SGST (9%)", amount: "11250" },
- { type: "CGST (9%)", amount: "11250" },
- ],
- deductions: [{ type: "TDS", amount: "12500" }],
- total: {
- amount: "147500",
- },
- };
- setUserState("compensationDetails", compensationData);
- setIsLoading(false);
- };
-
- useEffect(() => {
- setIsLoading(true);
- getDetails();
- }, []);
-
- return (
-
- {isDesktop ? (
-
- navigate(`/settings/compensation/edit`, { replace: true })
- }
- />
- ) : (
-
- )}
- {isLoading ? (
-
- ) : (
-
- )}
-
- );
-};
-export default CompensationDetails;
diff --git a/app/javascript/src/components/Team/Details/DeviceDetails/StaticPage.tsx b/app/javascript/src/components/Team/Details/DeviceDetails/StaticPage.tsx
deleted file mode 100644
index 3b548b116d..0000000000
--- a/app/javascript/src/components/Team/Details/DeviceDetails/StaticPage.tsx
+++ /dev/null
@@ -1,59 +0,0 @@
-import React from "react";
-
-const StaticPage = () => (
-
-
-
-
- Devices
-
-
-
-
-
-
- Device Type
-
-
Laptop
-
-
-
Model
-
- Macbook Pro 13-inch, 2020, Four Thunderbolt 3 ports
-
-
-
-
-
-
- Serial Number
-
-
cf4c6be4c742
-
-
-
Memory
-
16 GB 3733 MHz LPDDR4X
-
-
-
-
-
Graphics
-
- Intel Iris Plus Graphics 1536 MB
-
-
-
-
- Processor
-
-
- 2 GHz Quad-Core Intel Core i5
-
-
-
-
-
-
-);
-
-export default StaticPage;
diff --git a/app/javascript/src/components/Team/Details/DeviceDetails/index.tsx b/app/javascript/src/components/Team/Details/DeviceDetails/index.tsx
deleted file mode 100644
index 033f11f9a0..0000000000
--- a/app/javascript/src/components/Team/Details/DeviceDetails/index.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import React, { Fragment } from "react";
-
-import StaticPage from "./StaticPage";
-
-const DeviceDetails = () => (
-
-
-
Device Details
-
-
-
-);
-
-export default DeviceDetails;
diff --git a/app/javascript/src/components/Team/Details/DocumentDetails/index.tsx b/app/javascript/src/components/Team/Details/DocumentDetails/index.tsx
deleted file mode 100644
index d0ae3ca09b..0000000000
--- a/app/javascript/src/components/Team/Details/DocumentDetails/index.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import React, { Fragment } from "react";
-
-const DocumentDetails = () => (
-
-
-
Document Details
-
-
-
-);
-
-export default DocumentDetails;
diff --git a/app/javascript/src/components/Team/Details/EmploymentDetails/Edit/StaticPage.tsx b/app/javascript/src/components/Team/Details/EmploymentDetails/Edit/StaticPage.tsx
deleted file mode 100644
index cb674a7de1..0000000000
--- a/app/javascript/src/components/Team/Details/EmploymentDetails/Edit/StaticPage.tsx
+++ /dev/null
@@ -1,314 +0,0 @@
-import React from "react";
-
-import dayjs from "dayjs";
-import { ProjectsIcon, CalendarIcon, DeleteIcon } from "miruIcons";
-import "react-phone-number-input/style.css";
-import { Button } from "StyledComponents";
-
-import CustomDatePicker from "common/CustomDatePicker";
-import { CustomInputText } from "common/CustomInputText";
-import { CustomReactSelect } from "common/CustomReactSelect";
-import { ErrorSpan } from "common/ErrorSpan";
-
-const inputClass =
- "form__input block w-full appearance-none bg-white p-4 text-base h-12 focus-within:border-miru-han-purple-1000";
-
-const labelClass =
- "absolute top-0.5 left-1 h-6 z-1 origin-0 bg-white p-2 text-base font-medium duration-300";
-
-const StaticPage = ({
- employeeTypes,
- employeeType,
- handleOnChangeEmployeeType,
- updateCurrentEmploymentDetails,
- employmentDetails,
- showDORDatePicker,
- showDOJDatePicker,
- setShowDOJDatePicker,
- setShowDORDatePicker,
- handleDOJDatePicker,
- handleDORDatePicker,
- errDetails,
- DOJRef,
- DORRef,
- previousEmployments,
- handleDeletePreviousEmployment,
- handleAddPastEmployment,
- updatePreviousEmploymentValues,
- dateFormat,
- joinedAt,
- resignedAt,
-}) => {
- const getDOJ = joinedAt && dayjs(joinedAt, dateFormat).format(dateFormat);
-
- const getDOR = resignedAt && dayjs(resignedAt, dateFormat).format(dateFormat);
-
- return (
-
-
-
-
-
- Current
Employment
-
-
-
-
-
- {
- updateCurrentEmploymentDetails(e.target.value, "employee_id");
- }}
- />
- {errDetails.employee_id_err && (
-
- )}
-
-
- {
- updateCurrentEmploymentDetails(e.target.value, "designation");
- }}
- />
- {errDetails.designation_err && (
-
- )}
-
-
-
-
- {
- updateCurrentEmploymentDetails(e.target.value, "email");
- }}
- />
- {errDetails.email_err && (
-
- )}
-
-
-
- {errDetails.employment_err && (
-
- )}
-
-
-
-
-
- setShowDOJDatePicker({
- visibility: !showDOJDatePicker.visibility,
- })
- }
- >
-
-
-
- {errDetails.joined_at_err && (
-
- )}
- {showDOJDatePicker.visibility && (
-
- )}
-
-
-
- setShowDORDatePicker({
- visibility: !showDORDatePicker.visibility,
- })
- }
- >
-
-
-
- {errDetails.resigned_at_err && (
-
- )}
- {showDORDatePicker.visibility && (
-
- )}
-
-
-
-
-
-
-
-
- Previous
Employment
-
-
-
- {previousEmployments.length > 0 &&
- previousEmployments.map((previous, index) => (
-
-
-
- {
- updatePreviousEmploymentValues(previous, e);
- }}
- />
-
-
- {
- updatePreviousEmploymentValues(previous, e);
- }}
- />
-
-
-
-
- ))}
-
-
-
-
-
-
-
- );
-};
-
-export default StaticPage;
diff --git a/app/javascript/src/components/Team/Details/EmploymentDetails/Edit/index.tsx b/app/javascript/src/components/Team/Details/EmploymentDetails/Edit/index.tsx
deleted file mode 100644
index 2dc800dc87..0000000000
--- a/app/javascript/src/components/Team/Details/EmploymentDetails/Edit/index.tsx
+++ /dev/null
@@ -1,330 +0,0 @@
-/* eslint-disable no-unused-vars */
-import React, { Fragment, useEffect, useRef, useState } from "react";
-
-import dayjs from "dayjs";
-import utc from "dayjs/plugin/utc";
-import { useOutsideClick } from "helpers";
-import { useNavigate, useParams } from "react-router-dom";
-import * as Yup from "yup";
-
-import teamsApi from "apis/teams";
-import Loader from "common/Loader/index";
-import { useTeamDetails } from "context/TeamDetailsContext";
-import { useUserContext } from "context/UserContext";
-import { employmentMapper } from "mapper/teams.mapper";
-
-import StaticPage from "./StaticPage";
-import { employmentSchema } from "./validationSchema";
-
-dayjs.extend(utc);
-
-const schema = Yup.object().shape(employmentSchema);
-
-const EmploymentDetails = () => {
- const initialErrState = {
- employee_id_err: "",
- employment_type_err: "",
- email_err: "",
- designation_err: "",
- joined_at_err: "",
- resigned_at_err: "",
- company_name_err: "",
- role_err: "",
- };
-
- const { memberId } = useParams();
- const {
- updateDetails,
- details: { employmentDetails },
- } = useTeamDetails();
- const navigate = useNavigate();
- const { isDesktop } = useUserContext();
-
- const DOJRef = useRef(null);
- const DORRef = useRef(null);
-
- const InitialPrevEmployments = {
- added_employments: [],
- updated_employments: [],
- removed_employment_ids: [],
- };
-
- const [previousEmployments, setPreviousEmployments] = useState([]);
- const [employeeType, setEmployeeType] = useState({ label: "", value: "" });
- const [showDOJDatePicker, setShowDOJDatePicker] = useState({
- visibility: false,
- });
-
- const [showDORDatePicker, setShowDORDatePicker] = useState({
- visibility: false,
- });
- const [errDetails, setErrDetails] = useState(initialErrState);
- const [isLoading, setIsLoading] = useState(false);
- const [dateFormat, setDateFormat] = useState("DD-MM-YYYY");
- const [resignedAt, setResignedAt] = useState(null);
- const [joinedAt, setJoinedAt] = useState(null);
-
- useOutsideClick(DOJRef, () => setShowDOJDatePicker({ visibility: false }));
- useOutsideClick(DORRef, () => setShowDORDatePicker({ visibility: false }));
-
- const employeeTypes = [
- { label: "Salaried Employee", value: "salaried" },
- { label: "Contractor", value: "contractor" },
- ];
-
- const getDetails = async () => {
- const curr: any = await teamsApi.getEmploymentDetails(memberId);
- const prev: any = await teamsApi.getPreviousEmployments(memberId);
- setDateFormat(curr.data.date_format);
- setJoinedAt(curr.data.employment.joined_at);
- setResignedAt(curr.data.employment.resigned_at);
- const employmentData = employmentMapper(
- curr.data.employment,
- prev.data.previous_employments
- );
- if (employmentData.current_employment?.employment_type?.length > 0) {
- setEmployeeType(
- employeeTypes.find(
- item =>
- item.value === employmentData.current_employment.employment_type
- )
- );
- } else {
- setEmployeeType(employeeTypes[0]);
- employmentData.current_employment.employment_type =
- employeeTypes[0].value;
- }
- updateDetails("employment", employmentData);
- if (employmentData.previous_employments?.length > 0) {
- setPreviousEmployments(employmentData.previous_employments);
- }
- setIsLoading(false);
- };
-
- useEffect(() => {
- setIsLoading(true);
- getDetails();
- }, []);
-
- const handleOnChangeEmployeeType = empType => {
- setEmployeeType(empType);
- updateDetails("employment", {
- ...employmentDetails,
- ...{
- current_employment: {
- ...employmentDetails.current_employment,
- ...{ employment_type: empType.value },
- },
- },
- });
- };
-
- const updateCurrentEmploymentDetails = (value, type) => {
- updateDetails("employment", {
- ...employmentDetails,
- ...{
- current_employment: {
- ...employmentDetails.current_employment,
- ...{ [type]: value },
- },
- },
- });
- };
-
- const updatePreviousEmploymentValues = (previous, event) => {
- const { name, value } = event.target;
- const updatedPreviousEmployments = previousEmployments.map(prevEmployment =>
- prevEmployment == previous
- ? { ...prevEmployment, [name]: value }
- : prevEmployment
- );
- setPreviousEmployments(updatedPreviousEmployments);
- };
-
- const handleDOJDatePicker = date => {
- setShowDOJDatePicker({ visibility: !showDOJDatePicker.visibility });
- setJoinedAt(date);
- updateDetails("employment", {
- ...employmentDetails,
- ...{
- current_employment: {
- ...employmentDetails.current_employment,
- ...{
- joined_at:
- dateFormat == "DD-MM-YYYY"
- ? date
- : dayjs(date).format("DD-MM-YYYY"),
- },
- },
- },
- });
- };
-
- const handleDORDatePicker = date => {
- setShowDORDatePicker({ visibility: !showDORDatePicker.visibility });
- setResignedAt(date);
- updateDetails("employment", {
- ...employmentDetails,
- ...{
- current_employment: {
- ...employmentDetails.current_employment,
- ...{
- resigned_at:
- dateFormat == "DD-MM-YYYY"
- ? date
- : dayjs(date).format("DD-MM-YYYY"),
- },
- },
- },
- });
- };
-
- const handleAddPastEmployment = () => {
- const pastEmployments = [
- ...previousEmployments,
- { company_name: "", role: "" },
- ];
- setPreviousEmployments(pastEmployments);
- };
-
- const handleDeletePreviousEmployment = previous => {
- setPreviousEmployments(
- previousEmployments.filter(prev => prev !== previous)
- );
- };
-
- const handleUpdateDetails = async () => {
- setIsLoading(true);
- const getDifference = (array1, array2) =>
- array1.filter(object1 => !array2.some(object2 => object1 === object2));
-
- //creating an array which includes removed records
- const removed = employmentDetails.previous_employments.filter(
- e => !previousEmployments.includes(e)
- );
-
- //creating an array which includes updated and added records
- const unSortedEmployments = getDifference(
- previousEmployments,
- employmentDetails.previous_employments
- );
-
- const pastEmployments = InitialPrevEmployments;
-
- //sorting new entries and updated entries into
- unSortedEmployments.map(unSorted => {
- if (unSorted.id) {
- pastEmployments.updated_employments.push(unSorted);
- } else {
- pastEmployments.added_employments.push(unSorted);
- }
- });
-
- //Extracting removed records id
- if (removed.length > 0) {
- removed.map(remove => {
- if (pastEmployments.updated_employments.length > 0) {
- pastEmployments.updated_employments.filter(updated => {
- if (updated.id !== remove.id) {
- pastEmployments.removed_employment_ids.push(remove?.id);
- }
- });
- } else {
- pastEmployments.removed_employment_ids.push(remove?.id);
- }
- });
- }
- updateEmploymentDetails(pastEmployments);
- };
-
- const updateEmploymentDetails = async updatedPreviousEmployments => {
- try {
- await schema.validate(employmentDetails, { abortEarly: false });
- const payload = {
- ...updatedPreviousEmployments,
- current_employment: employmentDetails.current_employment,
- };
-
- await teamsApi.updatePreviousEmployments(memberId, {
- employments: payload,
- });
- setIsLoading(false);
- navigate(`/team/${memberId}/employment`, { replace: true });
- } catch (err) {
- setIsLoading(false);
- const errObj = initialErrState;
- if (err.inner) {
- err.inner.map(item => {
- if (item.path.includes("current_employment")) {
- errObj[`${item.path.split(".").pop()}_err`] = item.message;
- } else {
- errObj[`${item.path}_err`] = item.message;
- }
- });
- setErrDetails(errObj);
- }
- }
- };
-
- const handleCancelDetails = () => {
- setIsLoading(true);
- navigate(`/team/${memberId}/employment`, { replace: true });
- };
-
- return (
-
- {isDesktop && (
-
-
-
- Employement Details
-
-
-
-
-
-
- {isLoading ? (
-
- ) : (
-
- )}
-
- )}
-
- );
-};
-
-export default EmploymentDetails;
diff --git a/app/javascript/src/components/Team/Details/EmploymentDetails/EmploymentDetailsState.tsx b/app/javascript/src/components/Team/Details/EmploymentDetails/EmploymentDetailsState.tsx
deleted file mode 100644
index 6627e53426..0000000000
--- a/app/javascript/src/components/Team/Details/EmploymentDetails/EmploymentDetailsState.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-export const EmploymentDetailsState = {
- current_employment: {
- employee_id: "",
- email: "",
- employment_type: "",
- designation: "",
- joined_at: "",
- resigned_at: "",
- },
- previous_employments: [
- {
- company_name: "",
- role: "",
- id: "",
- },
- ],
-};
diff --git a/app/javascript/src/components/Team/Details/EmploymentDetails/StaticPage.tsx b/app/javascript/src/components/Team/Details/EmploymentDetails/StaticPage.tsx
deleted file mode 100644
index c2862aeda4..0000000000
--- a/app/javascript/src/components/Team/Details/EmploymentDetails/StaticPage.tsx
+++ /dev/null
@@ -1,111 +0,0 @@
-import React from "react";
-
-import { ProjectsIcon } from "miruIcons";
-
-const StaticPage = ({ employmentDetails }) => (
-
-
-
-
-
- Current
Employment
-
-
-
-
-
-
- Employee ID
-
-
- {employmentDetails.current_employment.employee_id}
-
-
-
-
- Designation
-
-
- {employmentDetails.current_employment.designation}
-
-
-
-
-
-
- Email ID (Official)
-
-
- {employmentDetails.current_employment.email}
-
-
-
-
- Employee Type
-
-
- {employmentDetails.current_employment.employment_type}
-
-
-
-
-
-
- Date of Joining
-
-
- {employmentDetails.current_employment.joined_at}
-
-
-
-
- Date of Resignation
-
-
- {employmentDetails.current_employment.resigned_at}
-
-
-
-
-
-
-
-
-
- Previous
Employment
-
-
-
- {employmentDetails?.previous_employments[0]?.company_name ? (
- employmentDetails.previous_employments.map((previous, index) => (
-
-
-
- Company
-
-
- {previous.company_name}
-
-
-
-
Role
-
{previous.role}
-
-
- ))
- ) : (
-
No previous employments found
- )}
-
-
-
-);
-export default StaticPage;
diff --git a/app/javascript/src/components/Team/Details/EmploymentDetails/index.tsx b/app/javascript/src/components/Team/Details/EmploymentDetails/index.tsx
deleted file mode 100644
index 282f979a5a..0000000000
--- a/app/javascript/src/components/Team/Details/EmploymentDetails/index.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import React, { Fragment, useEffect, useState } from "react";
-
-import { useParams, useNavigate } from "react-router-dom";
-
-import teamsApi from "apis/teams";
-import Loader from "common/Loader/index";
-import { useTeamDetails } from "context/TeamDetailsContext";
-import { employmentMapper } from "mapper/teams.mapper";
-
-import StaticPage from "./StaticPage";
-
-const EmploymentDetails = () => {
- const {
- updateDetails,
- details: { employmentDetails },
- } = useTeamDetails();
- const { memberId } = useParams();
- const navigate = useNavigate();
- const [isLoading, setIsLoading] = useState(false);
-
- const getDetails = async () => {
- const res1: any = await teamsApi.getEmploymentDetails(memberId);
- const res: any = await teamsApi.getPreviousEmployments(memberId);
- const employmentData = employmentMapper(
- res1.data.employment,
- res.data.previous_employments
- );
- updateDetails("employment", employmentData);
- setIsLoading(false);
- };
-
- useEffect(() => {
- setIsLoading(true);
- getDetails();
- }, []);
-
- return (
-
-
-
Employment Details
-
-
- {isLoading ? (
-
- ) : (
-
- )}
-
- );
-};
-export default EmploymentDetails;
diff --git a/app/javascript/src/components/Team/Details/Layout/Header.tsx b/app/javascript/src/components/Team/Details/Layout/Header.tsx
deleted file mode 100644
index ba8b4a393c..0000000000
--- a/app/javascript/src/components/Team/Details/Layout/Header.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import React from "react";
-
-import { ArrowLeftIcon } from "miruIcons";
-import { useNavigate } from "react-router-dom";
-
-import { useTeamDetails } from "context/TeamDetailsContext";
-
-const Header = () => {
- const navigate = useNavigate();
- const {
- details: { personalDetails },
- } = useTeamDetails();
-
- return (
-
-
-
-
- {`${personalDetails.first_name} ${personalDetails.last_name}`}
-
-
-
- );
-};
-export default Header;
diff --git a/app/javascript/src/components/Team/Details/Layout/MobileNav.tsx b/app/javascript/src/components/Team/Details/Layout/MobileNav.tsx
deleted file mode 100644
index cff6cc2a1b..0000000000
--- a/app/javascript/src/components/Team/Details/Layout/MobileNav.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-/* eslint-disable no-unused-vars */
-
-import React from "react";
-
-import { UserIcon, ProjectsIcon, MobileIcon } from "miruIcons";
-import { useParams } from "react-router-dom";
-
-import withLayout from "common/Mobile/HOC/withLayout";
-
-import { TeamUrl } from "./TeamUrl";
-import { UserInformation } from "./UserInformation";
-
-const getTeamUrls = memberId => [
- {
- url: `/team/${memberId}/details`,
- text: "PERSONAL DETAILS",
- icon: ,
- },
- {
- url: `/team/${memberId}/employment`,
- text: "EMPLOYMENT DETAILS",
- icon: ,
- },
- {
- url: "/settings/devices",
- text: "ALLOCATED DEVICES",
- icon: ,
- },
-];
-
-const MobileNav = () => {
- const { memberId } = useParams();
- const urlList = getTeamUrls(memberId);
-
- const mobileView = () => (
-
-
-
-
- );
-
- const DisplayView = withLayout(mobileView, true, true);
-
- return ;
-};
-
-export default MobileNav;
diff --git a/app/javascript/src/components/Team/Details/Layout/SideNav.tsx b/app/javascript/src/components/Team/Details/Layout/SideNav.tsx
deleted file mode 100644
index 2623f4e598..0000000000
--- a/app/javascript/src/components/Team/Details/Layout/SideNav.tsx
+++ /dev/null
@@ -1,192 +0,0 @@
-import React, { useEffect, useState } from "react";
-
-import { DeleteIcon, EditIcon, ImageIcon, UserAvatarSVG } from "miruIcons";
-import { NavLink, useParams } from "react-router-dom";
-import { MoreOptions, Toastr, Tooltip } from "StyledComponents";
-
-import teamApi from "apis/team";
-import teamsApi from "apis/teams";
-import { useTeamDetails } from "context/TeamDetailsContext";
-
-const getActiveClassName = isActive => {
- if (isActive) {
- return "pl-4 py-5 border-l-8 border-miru-han-purple-600 bg-miru-gray-200 text-miru-han-purple-600 block";
- }
-
- return "pl-6 py-5 border-b-1 border-miru-gray-400 block";
-};
-
-const getTeamUrls = memberId => [
- {
- url: `/team/${memberId}`,
- text: "PERSONAL DETAILS",
- },
- {
- url: `/team/${memberId}/employment`,
- text: "EMPLOYMENT DETAILS",
- },
- //Todo: Uncomment while API integration
- // {
- // url: `/team/${memberId}/compensation`,
- // text: "COMPENSATION",
- // },
-];
-
-const UserInformation = ({ memberId }) => {
- const {
- details: {
- personalDetails: { first_name, last_name },
- },
- } = useTeamDetails();
-
- const [showProfileOptions, setShowProfileOptions] = useState(false);
- const [imageUrl, setImageUrl] = useState(null);
-
- const getAvatar = async () => {
- try {
- const responseData = await teamsApi.get(memberId);
- setImageUrl(responseData.data.avatar_url);
- } catch {
- Toastr.error("Error in getting Profile Image");
- }
- };
-
- useEffect(() => {
- getAvatar();
- }, []);
-
- const validateFileSize = file => {
- const sizeInKB = file.size / 1024;
- if (sizeInKB > 100) {
- throw new Error("Image size needs to be less than 100 KB");
- }
- };
-
- const createFormData = file => {
- const formData = new FormData();
- formData.append("user[avatar]", file);
-
- return formData;
- };
-
- const handleProfileImageChange = async e => {
- try {
- setShowProfileOptions(false);
- const file = e.target.files[0];
- validateFileSize(file);
- setImageUrl(URL.createObjectURL(file));
- const payload = createFormData(file);
- await teamApi.updateTeamMemberAvatar(memberId, payload);
- } catch (error) {
- Toastr.error(error.message);
- }
- };
-
- const handleDeleteProfileImage = async () => {
- try {
- setShowProfileOptions(false);
- await teamApi.destroyTeamMemberAvatar(memberId);
- setImageUrl(null);
- Toastr.success("Image deleted successfully");
- } catch {
- Toastr.success("Error in deleting Profile Image");
- }
- };
-
- return (
-
-
-
-
-
-
-
-
-
-
- {showProfileOptions && (
-
-
-
-
- {imageUrl && (
-
-
- Delete
-
- )}
-
-
- )}
-
-
-
- {`${first_name} ${last_name}`}
-
-
-
-
-
-
-
- );
-};
-
-const TeamUrl = ({ urlList }) => (
-
-
- {urlList.map((item, index) => (
- -
- getActiveClassName(isActive)}
- to={item.url}
- >
- {item.text}
-
-
- ))}
-
-
-);
-
-const SideNav = () => {
- const { memberId } = useParams();
- const urlList = getTeamUrls(memberId);
-
- return (
-
-
-
-
- );
-};
-
-export default SideNav;
diff --git a/app/javascript/src/components/Team/Details/Layout/TeamUrl.tsx b/app/javascript/src/components/Team/Details/Layout/TeamUrl.tsx
deleted file mode 100644
index 8c905aedcb..0000000000
--- a/app/javascript/src/components/Team/Details/Layout/TeamUrl.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import React from "react";
-
-import { RightArrowIcon } from "miruIcons";
-import { NavLink } from "react-router-dom";
-
-const getActiveClassName = isActive => {
- if (isActive) {
- return "pl-4 py-5 border-l-8 border-miru-han-purple-600 bg-miru-gray-200 text-miru-han-purple-600 block";
- }
-
- return "pl-6 py-5 border-b-1 border-miru-gray-400 block";
-};
-
-export const TeamUrl = ({ urlList }) => (
-
-
- {urlList.map((item, index) => (
- -
- getActiveClassName(isActive)}
- to={item.url}
- >
-
-
- {item.icon}
- {item.text}
-
-
-
-
-
-
-
- ))}
-
-
-);
diff --git a/app/javascript/src/components/Team/Details/Layout/UserInformation.tsx b/app/javascript/src/components/Team/Details/Layout/UserInformation.tsx
deleted file mode 100644
index d471a8f269..0000000000
--- a/app/javascript/src/components/Team/Details/Layout/UserInformation.tsx
+++ /dev/null
@@ -1,150 +0,0 @@
-/* eslint-disable no-unused-vars */
-
-import React, { useEffect, useState } from "react";
-
-import { UserAvatarSVG, DeleteIcon, ImageIcon, EditIcon } from "miruIcons";
-import { useParams } from "react-router-dom";
-import { MobileMoreOptions, Toastr, Tooltip } from "StyledComponents";
-
-import teamApi from "apis/team";
-import teamsApi from "apis/teams";
-import { useTeamDetails } from "context/TeamDetailsContext";
-import { teamsMapper } from "mapper/teams.mapper";
-
-export const UserInformation = () => {
- const [showImageUpdateOptions, setShowImageUpdateOptions] =
- useState(false);
- const [userImageUrl, setUserImageUrl] = useState(null);
- const {
- details: { personalDetails },
- updateDetails,
- } = useTeamDetails();
- const { memberId } = useParams();
-
- const getDetails = async () => {
- try {
- const res: any = await teamsApi.get(memberId);
- const addRes = await teamsApi.getAddress(memberId);
- const teamsObj = teamsMapper(res.data, addRes.data.addresses[0]);
- updateDetails("personal", teamsObj);
- } catch {
- Toastr.error("Something went wrong");
- }
- };
-
- const validateFileSize = file => {
- const sizeInKB = file.size / 1024;
- if (sizeInKB > 100) {
- throw new Error("Image size needs to be less than 100 KB");
- }
- };
-
- const createFormData = file => {
- const formData = new FormData();
- formData.append("user[avatar]", file);
-
- return formData;
- };
-
- const handleProfileImageChange = async e => {
- try {
- setShowImageUpdateOptions(false);
- const file = e.target.files[0];
- validateFileSize(file);
- setUserImageUrl(URL.createObjectURL(file));
- const payload = createFormData(file);
- await teamApi.updateTeamMemberAvatar(memberId, payload);
- } catch (error) {
- Toastr.error(error.message);
- }
- };
-
- const handleDeleteProfileImage = async () => {
- setShowImageUpdateOptions(false);
- await teamApi.destroyTeamMemberAvatar(memberId);
- setUserImageUrl(null);
- };
-
- const getAvatar = async () => {
- const responseData = await teamsApi.get(memberId);
- setUserImageUrl(responseData.data.avatar_url);
- };
-
- useEffect(() => {
- getAvatar();
- getDetails();
- }, []);
-
- return (
-
-
-
-
-
-
- {showImageUpdateOptions ? (
-
-
-
-
-
- {userImageUrl && (
-
-
-
-
-
- Delete
-
-
- )}
-
- ) : null}
-
-
-
-
- {`${personalDetails.first_name} ${personalDetails.last_name}`}
-
-
-
-
-
-
-
- );
-};
diff --git a/app/javascript/src/components/Team/Details/PersonalDetails/Edit/MobileEditPage.tsx b/app/javascript/src/components/Team/Details/PersonalDetails/Edit/MobileEditPage.tsx
deleted file mode 100644
index 323eb3143a..0000000000
--- a/app/javascript/src/components/Team/Details/PersonalDetails/Edit/MobileEditPage.tsx
+++ /dev/null
@@ -1,427 +0,0 @@
-import React from "react";
-
-import dayjs from "dayjs";
-import {
- CalendarIcon,
- GlobeIcon,
- InfoIcon,
- MapPinIcon,
- PhoneIcon,
-} from "miruIcons";
-import PhoneInput from "react-phone-number-input";
-import flags from "react-phone-number-input/flags";
-import "react-phone-number-input/style.css";
-
-import CustomDatePicker from "common/CustomDatePicker";
-import { CustomInputText } from "common/CustomInputText";
-import { CustomReactSelect } from "common/CustomReactSelect";
-import { Divider } from "common/Divider";
-import { ErrorSpan } from "common/ErrorSpan";
-
-const inputClass =
- "form__input block w-full appearance-none bg-white p-4 text-sm h-12 focus-within:border-miru-han-purple-1000";
-
-const labelClass =
- "absolute top-0.5 left-1 h-6 z-1 origin-0 bg-white p-2 text-sm font-medium duration-300";
-
-const MobileEditDetails = ({
- addrType,
- addressOptions,
- countries,
- handleOnChangeAddrType,
- handleOnChangeCountry,
- handleCancelDetails,
- handleUpdateDetails,
- updateBasicDetails,
- personalDetails,
- showDatePicker,
- setShowDatePicker,
- handleDatePicker,
- errDetails,
- handlePhoneNumberChange,
- wrapperRef,
- dateFormat,
-}) => (
-
-
-
- Basic Details
-
-
-
- {
- updateBasicDetails(e.target.value, "first_name", false, "");
- }}
- />
- {errDetails.first_name_err && (
-
- )}
-
-
- {
- updateBasicDetails(e.target.value, "last_name", false, "");
- }}
- />
- {errDetails.last_name_err && (
-
- )}
-
-
-
-
-
- setShowDatePicker({ visibility: !showDatePicker.visibility })
- }
- >
- {
- updateBasicDetails(e.target.value, "date_of_birth", false);
- }}
- />
-
-
- {showDatePicker.visibility && (
-
handleDatePicker(e, true)}
- date={
- personalDetails.date_of_birth
- ? personalDetails.date_of_birth
- : dayjs()
- }
- />
- )}
-
-
-
-
-
-
- Contact
- Details
-
-
-
-
- {
- updateBasicDetails(e.target.value, "email_id", false);
- }}
- />
- {errDetails.email_id_err && (
-
- )}
-
-
-
-
-
-
- Address
-
-
-
-
-
-
- {
- updateBasicDetails(e.target.value, "address_line_1", true);
- }}
- />
- {errDetails.address_line_1_err && (
-
- )}
-
-
- {
- updateBasicDetails(e.target.value, "address_line_2", true);
- }}
- />
-
-
-
- handleOnChangeCountry(value)}
- isErr={!!errDetails.country_err}
- label="Country"
- name="current_country_select"
- options={countries}
- value={{
- label: personalDetails.addresses.country,
- value: personalDetails.addresses.country,
- }}
- />
- {errDetails.country_err && (
-
- )}
-
-
- {
- updateBasicDetails(e.target.value, "state", true);
- }}
- />
- {errDetails.state_err && (
-
- )}
-
-
-
-
- {
- updateBasicDetails(e.target.value, "city", true);
- }}
- />
- {errDetails.city_err && (
-
- )}
-
-
- {
- updateBasicDetails(e.target.value, "pin", true);
- }}
- />
- {errDetails.pin_err && (
-
- )}
-
-
-
-
-
-
-
-
- Social Profiles
-
-
-
- {
- updateBasicDetails(e.target.value, "linkedin", false, "");
- }}
- />
-
-
- {
- updateBasicDetails(e.target.value, "github", false, "");
- }}
- />
-
-
-
-
-
-
-
-
-
-);
-
-export default MobileEditDetails;
diff --git a/app/javascript/src/components/Team/Details/PersonalDetails/Edit/StaticPage.tsx b/app/javascript/src/components/Team/Details/PersonalDetails/Edit/StaticPage.tsx
deleted file mode 100644
index 2678781432..0000000000
--- a/app/javascript/src/components/Team/Details/PersonalDetails/Edit/StaticPage.tsx
+++ /dev/null
@@ -1,417 +0,0 @@
-import React from "react";
-
-import dayjs from "dayjs";
-import {
- GlobeIcon,
- CalendarIcon,
- PhoneIcon,
- MapPinIcon,
- InfoIcon,
-} from "miruIcons";
-import PhoneInput from "react-phone-number-input";
-import flags from "react-phone-number-input/flags";
-import "react-phone-number-input/style.css";
-
-import CustomDatePicker from "common/CustomDatePicker";
-import { CustomInputText } from "common/CustomInputText";
-import { CustomReactSelect } from "common/CustomReactSelect";
-import { ErrorSpan } from "common/ErrorSpan";
-
-const inputClass =
- "form__input block w-full appearance-none bg-white p-4 text-base h-12 focus-within:border-miru-han-purple-1000";
-
-const labelClass =
- "absolute top-0.5 left-1 h-6 z-1 origin-0 bg-white p-2 text-base font-medium duration-300";
-
-const StaticPage = ({
- addressOptions,
- addrType,
- countries,
- handleOnChangeAddrType,
- handleOnChangeCountry,
- updateBasicDetails,
- personalDetails,
- showDatePicker,
- setShowDatePicker,
- handleDatePicker,
- errDetails,
- handlePhoneNumberChange,
- wrapperRef,
- dateFormat,
-}) => (
-
-
-
-
- Basic
- Details
-
-
-
-
-
- {
- updateBasicDetails(e.target.value, "first_name", false, "");
- }}
- />
- {errDetails.first_name_err && (
-
- )}
-
-
- {
- updateBasicDetails(e.target.value, "last_name", false, "");
- }}
- />
- {errDetails.last_name_err && (
-
- )}
-
-
-
-
- setShowDatePicker({ visibility: !showDatePicker.visibility })
- }
- >
- {
- updateBasicDetails(e.target.value, "date_of_birth", false);
- }}
- />
-
-
- {showDatePicker.visibility && (
-
handleDatePicker(e, true)}
- date={
- personalDetails.date_of_birth
- ? personalDetails.date_of_birth
- : dayjs()
- }
- />
- )}
-
-
-
-
-
-
-
- Contact Details
-
-
-
-
-
-
- {
- updateBasicDetails(e.target.value, "email_id", false);
- }}
- />
- {errDetails.email_id_err && (
-
- )}
-
-
-
-
-
-
-
-
- Address
-
-
-
-
-
- {
- updateBasicDetails(e.target.value, "address_line_1", true);
- }}
- />
- {errDetails.address_line_1_err && (
-
- )}
-
-
- {
- updateBasicDetails(e.target.value, "address_line_2", true);
- }}
- />
-
-
-
- handleOnChangeCountry(value)}
- isErr={!!errDetails.country_err}
- label="Country"
- name="current_country_select"
- options={countries}
- value={{
- label: personalDetails.addresses.country,
- value: personalDetails.addresses.country,
- }}
- />
- {errDetails.country_err && (
-
- )}
-
-
- {
- updateBasicDetails(e.target.value, "state", true);
- }}
- />
- {errDetails.state_err && (
-
- )}
-
-
-
-
- {
- updateBasicDetails(e.target.value, "city", true);
- }}
- />
- {errDetails.city_err && (
-
- )}
-
-
- {
- updateBasicDetails(e.target.value, "pin", true);
- }}
- />
- {errDetails.pin_err && (
-
- )}
-
-
-
-
-
-
-
-
- Social Profiles
-
-
-
-
-
- {
- updateBasicDetails(e.target.value, "linkedin", false);
- }}
- />
-
-
- {
- updateBasicDetails(e.target.value, "github", false);
- }}
- />
-
-
-
-
-
-);
-
-export default StaticPage;
diff --git a/app/javascript/src/components/Team/Details/PersonalDetails/Edit/index.tsx b/app/javascript/src/components/Team/Details/PersonalDetails/Edit/index.tsx
deleted file mode 100644
index 2d180199e5..0000000000
--- a/app/javascript/src/components/Team/Details/PersonalDetails/Edit/index.tsx
+++ /dev/null
@@ -1,303 +0,0 @@
-/* eslint-disable no-unused-vars */
-import React, { Fragment, useEffect, useRef, useState } from "react";
-
-import { Country } from "country-state-city";
-import dayjs from "dayjs";
-import utc from "dayjs/plugin/utc";
-import { useOutsideClick } from "helpers";
-import { useNavigate, useParams } from "react-router-dom";
-import * as Yup from "yup";
-
-import teamsApi from "apis/teams";
-import Loader from "common/Loader/index";
-import { MobileDetailsHeader } from "common/Mobile/MobileDetailsHeader";
-import { useTeamDetails } from "context/TeamDetailsContext";
-import { useUserContext } from "context/UserContext";
-import { teamsMapper } from "mapper/teams.mapper";
-
-import MobileEditPage from "./MobileEditPage";
-import StaticPage from "./StaticPage";
-import { userSchema } from "./validationSchema";
-
-dayjs.extend(utc);
-
-const addressOptions = [
- { label: "Current", value: "current" },
- { label: "Permanent", value: "permanent" },
-];
-
-const schema = Yup.object().shape(userSchema);
-
-const EmploymentDetails = () => {
- const initialErrState = {
- first_name_err: "",
- last_name_err: "",
- address_line_1_err: "",
- country_err: "",
- state_err: "",
- city_err: "",
- email_id_err: "",
- pin_err: "",
- };
-
- const { memberId } = useParams();
- const {
- updateDetails,
- details: { personalDetails },
- } = useTeamDetails();
- const navigate = useNavigate();
- const { isDesktop } = useUserContext();
- const wrapperRef = useRef(null);
-
- const [addrType, setAddrType] = useState({ label: "", value: "" });
- const [showDatePicker, setShowDatePicker] = useState({ visibility: false });
- const [countries, setCountries] = useState([]);
- const [errDetails, setErrDetails] = useState(initialErrState);
- const [isLoading, setIsLoading] = useState(false);
- const [addrId, setAddrId] = useState();
-
- useOutsideClick(wrapperRef, () => setShowDatePicker({ visibility: false }));
-
- const assignCountries = async allCountries => {
- const countryData = await allCountries.map(country => ({
- value: country.name,
- label: country.name,
- code: country.isoCode,
- }));
- setCountries(countryData);
- };
-
- const getDetails = async () => {
- const res: any = await teamsApi.get(memberId);
- const addRes = await teamsApi.getAddress(memberId);
- const teamsObj = teamsMapper(res.data, addRes.data.addresses[0]);
- updateDetails("personal", teamsObj);
- if (teamsObj.addresses?.address_type?.length > 0) {
- setAddrType(
- addressOptions.find(
- item => item.value === teamsObj.addresses.address_type
- )
- );
- }
- setAddrId(addRes.data.addresses[0]?.id);
- setIsLoading(false);
- };
-
- useEffect(() => {
- setIsLoading(true);
- const allCountries = Country.getAllCountries();
- assignCountries(allCountries);
- getDetails();
- }, []);
-
- const handleOnChangeCountry = selectCountry => {
- updateDetails("personal", {
- ...personalDetails,
- ...{
- addresses: {
- ...personalDetails.addresses,
- ...{ country: selectCountry.value, state: "", city: "" },
- },
- },
- });
- };
-
- const handleOnChangeAddrType = addreType => {
- setAddrType(addreType);
- updateDetails("personal", {
- ...personalDetails,
- ...{
- addresses: {
- ...personalDetails.addresses,
- ...{ address_type: addreType.value },
- },
- },
- });
- };
-
- const updateBasicDetails = (value, type, isAddress = false) => {
- if (isAddress) {
- updateDetails("personal", {
- ...personalDetails,
- ...{
- addresses: { ...personalDetails.addresses, ...{ [type]: value } },
- },
- });
- } else {
- updateDetails("personal", {
- ...personalDetails,
- ...{ [type]: value },
- });
- }
- };
-
- const handleDatePicker = date => {
- setShowDatePicker({ visibility: !showDatePicker.visibility });
- const formattedDate = dayjs(date, personalDetails.date_format).format(
- personalDetails.date_format
- );
-
- updateDetails("personal", {
- ...personalDetails,
- ...{ date_of_birth: formattedDate },
- });
- };
-
- const handleUpdateDetails = async () => {
- try {
- await schema.validate(
- {
- ...personalDetails,
- ...{
- is_email: personalDetails.email_id
- ? personalDetails.email_id.length > 0
- : false,
- },
- },
- { abortEarly: false }
- );
-
- await teamsApi.updateUser(memberId, {
- user: {
- first_name: personalDetails.first_name,
- last_name: personalDetails.last_name,
- date_of_birth: personalDetails.date_of_birth
- ? dayjs
- .utc(personalDetails.date_of_birth, personalDetails.date_format)
- .toISOString()
- : null,
- phone: personalDetails.phone_number || "",
- personal_email_id: personalDetails.email_id,
- social_accounts: {
- linkedin_url: personalDetails.linkedin,
- github_url: personalDetails.github,
- },
- },
- });
-
- const payload = {
- address: {
- address_line_1: personalDetails.addresses.address_line_1,
- address_line_2: personalDetails.addresses.address_line_2,
- address_type: personalDetails.addresses.address_type,
- city: personalDetails.addresses.city,
- state: personalDetails.addresses.state,
- country: personalDetails.addresses.country,
- pin: personalDetails.addresses.pin,
- },
- };
- if (addrId) {
- await teamsApi.updateAddress(memberId, addrId, {
- address: { ...personalDetails.addresses },
- });
- } else {
- await teamsApi.createAddress(memberId, payload);
- }
-
- setErrDetails(initialErrState);
- navigate(`/team/${memberId}`, { replace: true });
- } catch (err) {
- setIsLoading(false);
- const errObj = initialErrState;
- if (err.inner) {
- err.inner.map(item => {
- if (item.path.includes("addresses")) {
- errObj[`${item.path.split(".").pop()}_err`] = item.message;
- } else {
- errObj[`${item.path}_err`] = item.message;
- }
- });
- setErrDetails(errObj);
- }
- }
- };
-
- const handlePhoneNumberChange = phoneNumber => {
- updateBasicDetails(phoneNumber, "phone_number", false);
- };
-
- const handleCancelDetails = () => {
- setIsLoading(true);
- navigate(`/team/${memberId}`, { replace: true });
- };
-
- return (
-
- {isDesktop && (
-
-
-
Personal Details
-
-
-
-
-
- {isLoading ? (
-
- ) : (
-
- )}
-
- )}
- {!isDesktop && (
-
-
- {isLoading ? (
-
-
-
- ) : (
-
- )}
-
- )}
-
- );
-};
-
-export default EmploymentDetails;
diff --git a/app/javascript/src/components/Team/Details/PersonalDetails/Edit/validationSchema.ts b/app/javascript/src/components/Team/Details/PersonalDetails/Edit/validationSchema.ts
deleted file mode 100644
index 39c3640535..0000000000
--- a/app/javascript/src/components/Team/Details/PersonalDetails/Edit/validationSchema.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import * as Yup from "yup";
-
-export const userSchema = {
- first_name: Yup.string()
- .required("Please enter first name")
- .max(20, "Maximum 20 characters are allowed"),
- last_name: Yup.string()
- .required("Please enter last name")
- .max(20, "Maximum 20 characters are allowed"),
- addresses: Yup.object().shape({
- address_line_1: Yup.string().required("Please enter address line 1"),
- country: Yup.string().required("Please enter country"),
- state: Yup.string().required("Please enter state"),
- city: Yup.string().required("Please enter city"),
- pin: Yup.string().required("Please enter zipcode"),
- }),
- is_email: Yup.boolean(),
- email_id: Yup.string()
- .nullable()
- .when("is_email", {
- is: true,
- then: Yup.string().email("Please enter valid email"),
- }),
-};
diff --git a/app/javascript/src/components/Team/Details/PersonalDetails/MobilePersonalDetails.tsx b/app/javascript/src/components/Team/Details/PersonalDetails/MobilePersonalDetails.tsx
deleted file mode 100644
index 107f7f70a5..0000000000
--- a/app/javascript/src/components/Team/Details/PersonalDetails/MobilePersonalDetails.tsx
+++ /dev/null
@@ -1,101 +0,0 @@
-import React from "react";
-
-import dayjs from "dayjs";
-import { GlobeIcon, InfoIcon, MapPinIcon, PhoneIcon } from "miruIcons";
-
-import { Divider } from "common/Divider";
-import { InfoDescription } from "common/Mobile/InfoDescription";
-
-const MobilePersonalDetails = ({
- personalDetails: {
- first_name,
- last_name,
- date_of_birth,
- phone_number,
- email_id,
- addresses,
- linkedin,
- github,
- date_format,
- },
-}) => (
-
-
-
-
-
- Contact
- Details
-
-
-
-
-
-
- Address
-
-
-
- {addresses && (
-
- )}
-
-
-
-
-
-
-
- Social Profiles
-
-
-
-
-);
-
-export default MobilePersonalDetails;
diff --git a/app/javascript/src/components/Team/Details/PersonalDetails/PersonalDetailsState.tsx b/app/javascript/src/components/Team/Details/PersonalDetails/PersonalDetailsState.tsx
deleted file mode 100644
index 13cd48ed6a..0000000000
--- a/app/javascript/src/components/Team/Details/PersonalDetails/PersonalDetailsState.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-export const PersonalDetailsState = {
- first_name: "",
- last_name: "",
- date_of_birth: "",
- phone_number: "",
- email_id: "",
- addresses: {
- id: "",
- address_type: "",
- address_line_1: "",
- address_line_2: "",
- country: "",
- state: "",
- city: "",
- pin: "",
- },
- linkedin: "",
- github: "",
- date_format: "",
-};
diff --git a/app/javascript/src/components/Team/Details/PersonalDetails/StaticPage.tsx b/app/javascript/src/components/Team/Details/PersonalDetails/StaticPage.tsx
deleted file mode 100644
index bb41d5b976..0000000000
--- a/app/javascript/src/components/Team/Details/PersonalDetails/StaticPage.tsx
+++ /dev/null
@@ -1,123 +0,0 @@
-import React from "react";
-
-import dayjs from "dayjs";
-import customParseFormat from "dayjs/plugin/customParseFormat";
-import { GlobeIcon, InfoIcon, MapPinIcon, PhoneIcon } from "miruIcons";
-
-dayjs.extend(customParseFormat);
-
-const StaticPage = ({ personalDetails }) => (
-
-
-
-
- Basic
- Details
-
-
-
-
-
-
Name
-
- {personalDetails.first_name} {personalDetails.last_name}
-
-
-
-
- Date of Birth
-
-
- {personalDetails.date_of_birth &&
- dayjs(
- personalDetails.date_of_birth,
- personalDetails.date_format
- ).format(personalDetails.date_format)}
-
-
-
-
-
-
-
-
-
- Contact Details
-
-
-
-
-
-
- Phone Number
-
-
- {personalDetails.phone_number}
-
-
-
-
- Email ID (Personal)
-
-
- {personalDetails.email_id}
-
-
-
-
-
-
-
-
-
- Address
-
-
-
-
-
-
Address
-
- {personalDetails.addresses && (
- <>
- {personalDetails.addresses.address_line_1},
- {personalDetails.addresses.address_line_2}
- {personalDetails.addresses.city},
- {personalDetails.addresses.state},
- {personalDetails.addresses.country} -
- {personalDetails.addresses.pin}
- >
- )}
-
-
-
-
-
-
-
-
-
- Social Profiles
-
-
-
-
-
-
LinkedIn
-
- {personalDetails.linkedin}
-
-
-
-
Github
-
- {personalDetails.github}
-
-
-
-
-
-
-);
-
-export default StaticPage;
diff --git a/app/javascript/src/components/Team/Details/PersonalDetails/index.tsx b/app/javascript/src/components/Team/Details/PersonalDetails/index.tsx
deleted file mode 100644
index ba5f00db75..0000000000
--- a/app/javascript/src/components/Team/Details/PersonalDetails/index.tsx
+++ /dev/null
@@ -1,79 +0,0 @@
-import React, { Fragment, useEffect, useState } from "react";
-
-import { Outlet, useParams, useNavigate } from "react-router-dom";
-
-import teamsApi from "apis/teams";
-import Loader from "common/Loader/index";
-import { MobileEditHeader } from "common/Mobile/MobileEditHeader";
-import { useTeamDetails } from "context/TeamDetailsContext";
-import { useUserContext } from "context/UserContext";
-import { teamsMapper } from "mapper/teams.mapper";
-
-import MobilePersonalDetails from "./MobilePersonalDetails";
-import StaticPage from "./StaticPage";
-
-const PersonalDetails = () => {
- const { memberId } = useParams();
- const { isDesktop } = useUserContext();
- const {
- updateDetails,
- details: { personalDetails },
- } = useTeamDetails();
- const [isLoading, setIsLoading] = useState(false);
- const navigate = useNavigate();
-
- const getDetails = async () => {
- const res: any = await teamsApi.get(memberId);
- const addRes = await teamsApi.getAddress(memberId);
- const teamsObj = teamsMapper(res.data, addRes.data.addresses[0]);
- updateDetails("personal", teamsObj);
- setIsLoading(false);
- };
-
- useEffect(() => {
- setIsLoading(true);
- getDetails();
- }, []);
-
- return (
-
- {isDesktop && (
-
-
-
Personal Details
-
-
- {isLoading ? (
-
- ) : (
-
- )}
-
- )}
- {!isDesktop && (
-
-
- {isLoading ? (
-
- ) : (
-
- )}
-
- )}
-
-
- );
-};
-
-export default PersonalDetails;
diff --git a/app/javascript/src/components/Team/Details/ReimburstmentDetails/StaticPage.tsx b/app/javascript/src/components/Team/Details/ReimburstmentDetails/StaticPage.tsx
deleted file mode 100644
index dd1144e016..0000000000
--- a/app/javascript/src/components/Team/Details/ReimburstmentDetails/StaticPage.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-import React from "react";
-
-import { PenIcon, DeleteIcon } from "miruIcons";
-
-const StaticPage = () => (
-
-
-
-
- DATE |
- DESCRIPTION |
- STORE/MODE |
- AMOUNT |
- |
-
-
-
-
- 22.04.2022 |
-
- Medium annual team subscription
- |
- Online/Netbanking |
- ₹7,500 |
-
-
-
- |
-
-
- 22.04.2022 |
-
- Medium annual team subscription
- |
- Online/Netbanking |
- ₹7,500 |
-
-
-
- |
-
-
-
-
-);
-
-export default StaticPage;
diff --git a/app/javascript/src/components/Team/Details/ReimburstmentDetails/index.tsx b/app/javascript/src/components/Team/Details/ReimburstmentDetails/index.tsx
deleted file mode 100644
index d8bb67d259..0000000000
--- a/app/javascript/src/components/Team/Details/ReimburstmentDetails/index.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import React, { Fragment } from "react";
-
-import StaticPage from "./StaticPage";
-
-const ReimburstmentDetails = () => (
-
-
-
Reimburstment Details
-
-
-
-);
-
-export default ReimburstmentDetails;
diff --git a/app/javascript/src/components/Team/Details/index.tsx b/app/javascript/src/components/Team/Details/index.tsx
deleted file mode 100644
index 2b92994079..0000000000
--- a/app/javascript/src/components/Team/Details/index.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import React, { Fragment, useState } from "react";
-
-import { TeamDetailsContext } from "context/TeamDetailsContext";
-import { useUserContext } from "context/UserContext";
-
-import { CompensationDetailsState } from "./CompensationDetails/CompensationDetailsState";
-import { EmploymentDetailsState } from "./EmploymentDetails/EmploymentDetailsState";
-import Header from "./Layout/Header";
-import OutletWrapper from "./Layout/OutletWrapper";
-import SideNav from "./Layout/SideNav";
-import { PersonalDetailsState } from "./PersonalDetails/PersonalDetailsState";
-
-const TeamDetails = () => {
- const [details, setDetails] = useState({
- personalDetails: PersonalDetailsState,
- employmentDetails: EmploymentDetailsState,
- documentDetails: {},
- deviceDetails: {},
- compensationDetails: CompensationDetailsState,
- reimburstmentDetails: {},
- });
- const { isDesktop } = useUserContext();
- const updateDetails = (key, payload) => {
- setDetails({ ...details, [`${key}Details`]: payload });
- };
-
- return (
-
- {isDesktop && (
-
-
-
-
- )}
- {!isDesktop && }
-
- );
-};
-
-export default TeamDetails;
diff --git a/app/javascript/src/components/Team/List/Table/TableRow.tsx b/app/javascript/src/components/Team/List/Table/TableRow.tsx
index f857cb62c0..76c6ad8f91 100644
--- a/app/javascript/src/components/Team/List/Table/TableRow.tsx
+++ b/app/javascript/src/components/Team/List/Table/TableRow.tsx
@@ -48,7 +48,7 @@ const TableRow = ({ item }) => {
const handleRowClick = () => {
if (!status) return;
- navigate(`/team/${id}`, { replace: true });
+ navigate(`/team/${id}/profile`, { replace: true });
};
return (
diff --git a/app/javascript/src/components/Team/RouteConfig.tsx b/app/javascript/src/components/Team/RouteConfig.tsx
deleted file mode 100644
index 1fe95241f1..0000000000
--- a/app/javascript/src/components/Team/RouteConfig.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import React from "react";
-
-import { Route, Routes } from "react-router-dom";
-
-import Details from "./Details";
-import CompensationDetails from "./Details/CompensationDetails";
-import CompensationEdit from "./Details/CompensationDetails/Edit";
-import EmploymentDetails from "./Details/EmploymentDetails";
-import EmploymentEdit from "./Details/EmploymentDetails/Edit";
-import MobileNav from "./Details/Layout/MobileNav";
-import PersonalDetails from "./Details/PersonalDetails";
-import PersonalEdit from "./Details/PersonalDetails/Edit";
-
-const RouteConfig = () => (
-
- } path=":memberId">
- } />
- } path="edit" />
- } path="options" />
- } path="details" />
- } path="employment" />
- } path="employment_edit" />
- } path="compensation" />
- } path="compensation_edit" />
-
-
-);
-
-export default RouteConfig;
diff --git a/app/javascript/src/constants/routes.ts b/app/javascript/src/constants/routes.ts
index ced02d73a3..15f30499e1 100644
--- a/app/javascript/src/constants/routes.ts
+++ b/app/javascript/src/constants/routes.ts
@@ -10,6 +10,7 @@ import InvoiceEmail from "components/InvoiceEmail";
import InvoicesRouteConfig from "components/Invoices/InvoicesRouteConfig";
import LeaveManagement from "components/LeaveManagement";
import Success from "components/payments/Success";
+import ProfileRouteConfig from "components/Profile/Layout/RouteConfig";
import Projects from "components/Projects";
import AccountsAgingReport from "components/Reports/AccountsAgingReport";
import InvalidLink from "components/Team/List/InvalidLink";
@@ -19,7 +20,6 @@ import { Roles, Paths } from "constants/index";
import Clients from "../components/Clients";
import ClientDetails from "../components/Clients/Details";
import Payments from "../components/payments";
-import ProfileLayout from "../components/Profile/Layout";
import ProjectDetails from "../components/Projects/Details";
import ReportList from "../components/Reports/List";
import OutstandingInvoiceReport from "../components/Reports/OutstandingInvoiceReport";
@@ -27,7 +27,6 @@ import RevenueByClientReport from "../components/Reports/RevenueByClientReport";
import TimeEntryReports from "../components/Reports/TimeEntryReport";
import TotalHoursReport from "../components/Reports/totalHoursLogged";
import PlanSelection from "../components/Subscriptions/PlanSelection";
-import RouteConfig from "../components/Team/RouteConfig";
import TimesheetEntries from "../components/TimesheetEntries";
const ClientsRoutes = [
@@ -70,13 +69,13 @@ const LeaveManagementRoutes = [
{ path: "*", Component: ErrorPage },
];
-const TeamRoutes = [{ path: "*", Component: RouteConfig }];
+const TeamRoutes = [{ path: "*", Component: ProfileRouteConfig }];
const TeamsRoutes = [{ path: "*", Component: TeamsRouteConfig }];
const InvoiceRoutes = [{ path: "*", Component: InvoicesRouteConfig }];
-const SettingsRoutes = [{ path: "*", Component: ProfileLayout }];
+const SettingsRoutes = [{ path: "*", Component: ProfileRouteConfig }];
const ExpenseRoutes = [
{ path: "", Component: Expenses },
diff --git a/app/javascript/src/context/Profile/ProfileContext.tsx b/app/javascript/src/context/Profile/ProfileContext.tsx
new file mode 100644
index 0000000000..10cf333c1b
--- /dev/null
+++ b/app/javascript/src/context/Profile/ProfileContext.tsx
@@ -0,0 +1,23 @@
+import { createContext, useContext } from "react";
+
+import { CompensationDetailsState } from "components/Profile/Context/CompensationDetailsState";
+import { EmploymentDetailsState } from "components/Profile/Context/EmploymentDetailsState";
+import { PersonalDetailsState } from "components/Profile/Context/PersonalDetailsState";
+// Context Creation
+
+export const ProfileContext = createContext({
+ personalDetails: PersonalDetailsState,
+ employmentDetails: EmploymentDetailsState,
+ documentDetails: {},
+ deviceDetails: {},
+ compensationDetails: CompensationDetailsState,
+ reimburstmentDetails: {},
+ updateDetails: (key, payload) => {}, //eslint-disable-line
+ isCalledFromSettings: false,
+ setIsCalledFromSettings: val => {}, //eslint-disable-line
+ isCalledFromTeam: false,
+ setIsCalledFromTeam: val => {}, //eslint-disable-line
+});
+
+// Custom Hooks
+export const useProfileContext = () => useContext(ProfileContext);
diff --git a/app/javascript/src/context/TeamDetailsContext.tsx b/app/javascript/src/context/TeamDetailsContext.tsx
deleted file mode 100644
index d9467d3537..0000000000
--- a/app/javascript/src/context/TeamDetailsContext.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import { createContext, useContext } from "react";
-
-import { CompensationDetailsState } from "components/Team/Details/CompensationDetails/CompensationDetailsState";
-import { EmploymentDetailsState } from "components/Team/Details/EmploymentDetails/EmploymentDetailsState";
-import { PersonalDetailsState } from "components/Team/Details/PersonalDetails/PersonalDetailsState";
-// Context Creation
-
-export const TeamDetailsContext = createContext({
- details: {
- personalDetails: PersonalDetailsState,
- employmentDetails: EmploymentDetailsState,
- documentDetails: {},
- deviceDetails: {},
- compensationDetails: CompensationDetailsState,
- reimburstmentDetails: {},
- },
- updateDetails: (key, payload) => {}, //eslint-disable-line
-});
-
-// Custom Hooks
-export const useTeamDetails = () => useContext(TeamDetailsContext);
diff --git a/app/javascript/src/mapper/teams.mapper.ts b/app/javascript/src/mapper/teams.mapper.ts
index 015f06d44c..bf1fbabf33 100644
--- a/app/javascript/src/mapper/teams.mapper.ts
+++ b/app/javascript/src/mapper/teams.mapper.ts
@@ -1,6 +1,7 @@
import dayjs from "dayjs";
export const teamsMapper = (user, address) => ({
+ id: user.id,
first_name: user.first_name,
last_name: user.last_name,
date_of_birth:
diff --git a/app/policies/profile_policy.rb b/app/policies/profile_policy.rb
index 9c840768c2..6733733109 100644
--- a/app/policies/profile_policy.rb
+++ b/app/policies/profile_policy.rb
@@ -1,14 +1,6 @@
# frozen_string_literal: true
class ProfilePolicy < ApplicationPolicy
- def show?
- user
- end
-
- def remove_avatar?
- user
- end
-
def update?
user
end
diff --git a/app/policies/team_members/avatar_policy.rb b/app/policies/team_members/avatar_policy.rb
index 77ec917b9d..a3d6486806 100644
--- a/app/policies/team_members/avatar_policy.rb
+++ b/app/policies/team_members/avatar_policy.rb
@@ -17,6 +17,6 @@ def authorize_current_user
return false
end
- user_owner_role? || user_admin_role?
+ has_owner_or_admin_role? || record_belongs_to_user?
end
end
diff --git a/app/policies/team_members/detail_policy.rb b/app/policies/team_members/detail_policy.rb
index 7251b69303..a01f35cab8 100644
--- a/app/policies/team_members/detail_policy.rb
+++ b/app/policies/team_members/detail_policy.rb
@@ -21,6 +21,6 @@ def authorize_current_user
return false
end
- user_owner_role? || user_admin_role?
+ has_owner_or_admin_role? || record_belongs_to_user?
end
end
diff --git a/app/views/internal_api/v1/team_members/details/_detail.json.jbuilder b/app/views/internal_api/v1/team_members/details/_detail.json.jbuilder
index 19c2ae45c5..dace39a008 100644
--- a/app/views/internal_api/v1/team_members/details/_detail.json.jbuilder
+++ b/app/views/internal_api/v1/team_members/details/_detail.json.jbuilder
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-json.extract! user, :first_name, :last_name, :date_of_birth, :phone, :personal_email_id, :social_accounts
+json.extract! user, :id, :first_name, :last_name, :date_of_birth, :phone, :personal_email_id, :social_accounts
json.date_format current_company.date_format
json.avatar_url user.avatar_url
diff --git a/config/routes/internal_api.rb b/config/routes/internal_api.rb
index b7127daaff..cb714372d7 100644
--- a/config/routes/internal_api.rb
+++ b/config/routes/internal_api.rb
@@ -138,18 +138,12 @@
resources :providers, only: [:index, :update]
end
- resources :team, only: [:index, :destroy] do
- resource :details, only: [:show, :update], controller: "team_members/details"
- end
-
resources :users, concerns: :addressable do
resources :previous_employments, only: [:create, :index, :show, :update], controller: "users/previous_employments"
resources :devices, only: [:create, :index, :show, :update], controller: "users/devices"
end
- resource :profile, only: [:update, :show], controller: "profile" do
- delete "/remove_avatar", to: "profile#remove_avatar"
- end
+ resource :profile, only: [:update], controller: "profile"
resources :vendors, only: [:create]
resources :expense_categories, only: [:create]
diff --git a/spec/requests/internal_api/v1/profile/remove_avatar_spec.rb b/spec/requests/internal_api/v1/profile/remove_avatar_spec.rb
deleted file mode 100644
index e6dffd6e2c..0000000000
--- a/spec/requests/internal_api/v1/profile/remove_avatar_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require "rails_helper"
-
-RSpec.describe "InternalApi::V1::Profile#remove_avatar", type: :request do
- let(:user) { create(:user, :with_avatar) }
- let(:company) { create(:company) }
-
- describe "remove avatar" do
- before do
- user.add_role :employee, company
- sign_in user
- send_request :delete, remove_avatar_internal_api_v1_profile_path, headers: auth_headers(user)
- end
-
- it "removes user's avatar" do
- expect(response).to have_http_status(:ok)
- expect(user.reload.avatar.attached?).to be_falsey
- end
- end
-end
diff --git a/spec/requests/internal_api/v1/profile/show_spec.rb b/spec/requests/internal_api/v1/profile/show_spec.rb
deleted file mode 100644
index 51ee64fa7a..0000000000
--- a/spec/requests/internal_api/v1/profile/show_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require "rails_helper"
-
-RSpec.describe "InternalApi::V1::Profile#show", type: :request do
- let(:user) { create(:user, :with_avatar) }
- let(:company) { create(:company) }
-
- describe "index action" do
- before do
- user.add_role :employee, company
- sign_in user
- send_request :get, internal_api_v1_profile_path, headers: auth_headers(user)
- end
-
- it "fetches user details & avatar" do
- expect(response).to have_http_status(:ok)
- expect(json_response["user"]["avatar_url"]).to eq(user.avatar_url)
- expect(json_response["user"]["first_name"]).to eq(user.first_name)
- expect(json_response["user"]["last_name"]).to eq(user.last_name)
- end
- end
-end
diff --git a/spec/requests/internal_api/v1/team_members/avatar/destroy_spec.rb b/spec/requests/internal_api/v1/team_members/avatar/destroy_spec.rb
index 3c195efa6c..b406570893 100644
--- a/spec/requests/internal_api/v1/team_members/avatar/destroy_spec.rb
+++ b/spec/requests/internal_api/v1/team_members/avatar/destroy_spec.rb
@@ -2,7 +2,7 @@
require "rails_helper"
-RSpec.describe "InternalApi::V1::Profile#remove_avatar", type: :request do
+RSpec.describe "InternalApi::V1::TeamMembers::AvatarController#destroy", type: :request do
let(:company) { create(:company) }
let(:company2) { create(:company) }
let(:admin) { create(:user, current_workspace_id: company.id) }
@@ -45,6 +45,21 @@
end
end
+ context "when employee wants to remove own avatar" do
+ before do
+ create(:employment, user:, company:)
+
+ user.add_role :employee, company
+ sign_in user
+ send_request :delete, internal_api_v1_team_avatar_path(user.id), headers: auth_headers(user)
+ end
+
+ it "removes user's avatar" do
+ expect(response).to have_http_status(:ok)
+ expect(user.reload.avatar.attached?).to be_falsey
+ end
+ end
+
context "when logged in admin wants to remove avatar of employee from a different company" do
before do
create(:employment, user: admin, company:)
@@ -76,4 +91,21 @@
expect(response).to have_http_status(:not_found)
end
end
+
+ context "when logged in employee wants to remove avatar of another employee from a same company" do
+ before do
+ create(:employment, user:, company:)
+ create(:employment, user: user2, company:)
+
+ user.add_role :employee, company
+ user2.add_role :employee, company
+ sign_in user
+ send_request :delete, internal_api_v1_team_avatar_path(user2.id), headers: auth_headers(user)
+ end
+
+ it "is unsuccessful" do
+ expect(response).to have_http_status(:forbidden)
+ expect(json_response["errors"]).to eq("You are not authorized to perform this action.")
+ end
+ end
end
diff --git a/spec/requests/internal_api/v1/team_members/avatar/update_spec.rb b/spec/requests/internal_api/v1/team_members/avatar/update_spec.rb
index 1ed20bb50e..a19a9e68a5 100644
--- a/spec/requests/internal_api/v1/team_members/avatar/update_spec.rb
+++ b/spec/requests/internal_api/v1/team_members/avatar/update_spec.rb
@@ -2,7 +2,7 @@
require "rails_helper"
-RSpec.describe "InternalApi::V1::TeamMembers::AvatarController::#update", type: :request do
+RSpec.describe "InternalApi::V1::TeamMembers::AvatarController#update", type: :request do
let(:company) { create(:company) }
let(:company2) { create(:company) }
let(:admin) { create(:user, current_workspace_id: company.id) }
diff --git a/spec/requests/internal_api/v1/team_members/details/show_spec.rb b/spec/requests/internal_api/v1/team_members/details/show_spec.rb
index a577b086a8..fe24bd08cd 100644
--- a/spec/requests/internal_api/v1/team_members/details/show_spec.rb
+++ b/spec/requests/internal_api/v1/team_members/details/show_spec.rb
@@ -2,11 +2,11 @@
require "rails_helper"
-RSpec.describe "Details#show", type: :request do
+RSpec.describe "InternalApi::V1::TeamMembers::DetailsController#show", type: :request do
let(:company) { create(:company) }
let(:company2) { create(:company) }
- let(:user) { create(:user, current_workspace_id: company.id) }
- let(:user2) { create(:user, current_workspace_id: company2.id) }
+ let(:user) { create(:user, :with_avatar, current_workspace_id: company.id) }
+ let(:user2) { create(:user, :with_avatar, current_workspace_id: company2.id) }
let(:employment) { create(:employment, user:, company:) }
context "when Owner wants to see details of employee of his company" do
@@ -52,9 +52,15 @@
send_request :get, internal_api_v1_team_details_path(employment.user_id), headers: auth_headers(user)
end
- it "is unsuccessful" do
- expect(response).to have_http_status(:forbidden)
- expect(json_response["errors"]).to eq("You are not authorized to perform this action.")
+ it "is successful" do
+ expect(response).to have_http_status(:ok)
+ expect(json_response["avatar_url"]).to eq(JSON.parse(user.avatar_url.to_json))
+ expect(json_response["first_name"]).to eq(JSON.parse(user.first_name.to_json))
+ expect(json_response["last_name"]).to eq(JSON.parse(user.last_name.to_json))
+ expect(json_response["personal_email_id"]).to eq(JSON.parse(user.personal_email_id.to_json))
+ expect(json_response["date_of_birth"]).to eq(JSON.parse(user.date_of_birth.to_json))
+ expect(json_response["phone"]).to eq(JSON.parse(user.phone.to_json))
+ expect(json_response["social_accounts"]).to eq(JSON.parse(user.social_accounts.to_json))
end
end
diff --git a/spec/requests/internal_api/v1/team_members/details/update_spec.rb b/spec/requests/internal_api/v1/team_members/details/update_spec.rb
index 96bc0d24f3..8bb24619de 100644
--- a/spec/requests/internal_api/v1/team_members/details/update_spec.rb
+++ b/spec/requests/internal_api/v1/team_members/details/update_spec.rb
@@ -2,7 +2,7 @@
require "rails_helper"
-RSpec.describe "InternalApi::V1::TeamMembers::DetailsController::#update", type: :request do
+RSpec.describe "InternalApi::V1::TeamMembers::DetailsController#update", type: :request do
let(:company) { create(:company) }
let(:company2) { create(:company) }
let(:user) { create(:user, current_workspace_id: company.id) }
@@ -79,9 +79,14 @@
}), headers: auth_headers(user)
end
- it "is unsuccessful" do
- expect(response).to have_http_status(:forbidden)
- expect(json_response["errors"]).to eq("You are not authorized to perform this action.")
+ it "is successful" do
+ expect(response).to have_http_status(:ok)
+ expect(json_response["first_name"]).to eq(JSON.parse(@user_details["first_name"].to_json))
+ expect(json_response["last_name"]).to eq(JSON.parse(@user_details["last_name"].to_json))
+ expect(json_response["personal_email_id"]).to eq(JSON.parse(@user_details["personal_email_id"].to_json))
+ expect(json_response["date_of_birth"]).to eq(JSON.parse(@user_details["date_of_birth"].to_json))
+ expect(json_response["phone"]).to eq(JSON.parse(@user_details["phone"].to_json))
+ expect(json_response["social_accounts"]).to eq(JSON.parse(@user_details["social_accounts"].to_json))
end
end