From 95fbac4760bf7fb67ab3e113792130962b8a487e Mon Sep 17 00:00:00 2001 From: pramod mahajan Date: Wed, 17 Sep 2025 12:41:00 +0530 Subject: [PATCH 1/6] fixed prevent removed existen permission whenever add new one --- src/components/Project/ProjectPermission.jsx | 137 +++++++++++-------- 1 file changed, 80 insertions(+), 57 deletions(-) diff --git a/src/components/Project/ProjectPermission.jsx b/src/components/Project/ProjectPermission.jsx index 4a6a5504..b7d30adb 100644 --- a/src/components/Project/ProjectPermission.jsx +++ b/src/components/Project/ProjectPermission.jsx @@ -6,7 +6,7 @@ import { } from "../../hooks/useProjects"; import { useSelectedProject } from "../../slices/apiDataManager"; import { useEmployeesByProject } from "../../hooks/useEmployees"; -import { useForm } from "react-hook-form"; +import { useForm, Controller } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import showToast from "../../services/toastService"; @@ -27,6 +27,7 @@ const ProjectPermission = () => { watch, handleSubmit, reset, + control, formState: { errors, isDirty }, } = useForm({ resolver: zodResolver(ProjectPermissionSchema), @@ -73,15 +74,15 @@ const ProjectPermission = () => { const newSelectedIds = formData.selectedPermissions || []; - const removed = existingEnabledIds - .filter((id) => !newSelectedIds.includes(id)) - .map((id) => ({ id, isEnabled: false })); - const added = newSelectedIds .filter((id) => !existingEnabledIds.includes(id)) .map((id) => ({ id, isEnabled: true })); - const payloadPermissions = [...removed, ...added]; + const removed = existingEnabledIds + .filter((id) => !newSelectedIds.includes(id)) + .map((id) => ({ id, isEnabled: false })); + + const payloadPermissions = [...added, ...removed]; if (payloadPermissions.length === 0) { showToast("No changes detected", "info"); @@ -94,41 +95,45 @@ const ProjectPermission = () => { permission: payloadPermissions, }; + console.log("Final payload:", payload); updatePermission(payload); }; - const useOnClick = useCallback((event) => {}, []); return (
-
-
+ {loading ? ( + + ) : ( + <> + + {[...employees] + ?.sort((a, b) => + `${a?.firstName} ${a?.firstName}`?.localeCompare( + `${b?.firstName} ${b?.lastName}` + ) ) - ) - ?.map((emp) => ( - - ))} - - )} -
+ ?.map((emp) => ( + + ))} + + )} + +
{errors.employeeId && (
@@ -136,17 +141,16 @@ const ProjectPermission = () => {
)}
- {isDirty && ( -
- -
- )} + +
+ +
{ProjectModules.map((feature) => ( @@ -157,22 +161,41 @@ const ProjectPermission = () => {

{feature.name}

-
    +
      {feature.featurePermissions?.map((perm) => (
      - + { + const value = field.value || []; + const isChecked = value.includes(perm.id); + + return ( + + ); + }} + />
      ))}
    From cc7ef47055c828a6ef1ea7f3a867dfef28d7f3d5 Mon Sep 17 00:00:00 2001 From: pramod mahajan Date: Wed, 17 Sep 2025 12:54:40 +0530 Subject: [PATCH 2/6] fixed validation msg set bottom of select box --- src/components/Project/ProjectPermission.jsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/components/Project/ProjectPermission.jsx b/src/components/Project/ProjectPermission.jsx index b7d30adb..351ddd1a 100644 --- a/src/components/Project/ProjectPermission.jsx +++ b/src/components/Project/ProjectPermission.jsx @@ -133,23 +133,25 @@ const ProjectPermission = () => { )} -
- - {errors.employeeId && ( -
+ {errors.employeeId && ( +
{errors.employeeId.message}
)} +
+ +
- + )} +
From a835e75f664def00e03e2d4cccd9d26ccfefb9fa Mon Sep 17 00:00:00 2001 From: pramod mahajan Date: Wed, 17 Sep 2025 13:15:00 +0530 Subject: [PATCH 3/6] fixed view project --- src/pages/project/ProjectDetails.jsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/pages/project/ProjectDetails.jsx b/src/pages/project/ProjectDetails.jsx index e32a185b..deaf8a9e 100644 --- a/src/pages/project/ProjectDetails.jsx +++ b/src/pages/project/ProjectDetails.jsx @@ -27,15 +27,23 @@ import ProjectDocument from "../../components/Project/ProjectDocuments"; import ProjectDocuments from "../../components/Project/ProjectDocuments"; import ProjectSetting from "../../components/Project/ProjectSetting"; import DirectoryPage from "../Directory/DirectoryPage"; +import { useHasAnyPermission } from "../../hooks/useExpense"; +import { VIEW_PROJECTS } from "../../utils/constants"; +import { useNavigate, useRoutes } from "react-router-dom"; const ProjectDetails = () => { const projectId = useSelectedProject() + const CanViewProject = useHasAnyPermission(VIEW_PROJECTS); + const navigate = useNavigate() const { projectNames, fetchData } = useProjectName(); const dispatch = useDispatch(); useEffect(() => { + if(!CanViewProject){ + navigate("/dashboard") + } if (projectId == null) { dispatch(setProjectId(projectNames[0]?.id)); } From 889b477dd0c0c6408e2a18b7432beaeb89786c95 Mon Sep 17 00:00:00 2001 From: pramod mahajan Date: Wed, 17 Sep 2025 14:24:45 +0530 Subject: [PATCH 4/6] removed subMenu of Project setting --- src/components/Project/ProjectPermission.jsx | 30 +++++++++++--------- src/components/Project/ProjectSetting.jsx | 11 +++---- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/components/Project/ProjectPermission.jsx b/src/components/Project/ProjectPermission.jsx index 351ddd1a..471e283d 100644 --- a/src/components/Project/ProjectPermission.jsx +++ b/src/components/Project/ProjectPermission.jsx @@ -101,6 +101,9 @@ const ProjectPermission = () => { return (
+
+

Project Permission

+
@@ -134,24 +137,23 @@ const ProjectPermission = () => { )} {errors.employeeId && ( -
- {errors.employeeId.message} -
- )} +
+ {errors.employeeId.message} +
+ )}
- -
- {isDirty && ( )} - + {isDirty && ( + + )}
diff --git a/src/components/Project/ProjectSetting.jsx b/src/components/Project/ProjectSetting.jsx index 54991cec..35e334bf 100644 --- a/src/components/Project/ProjectSetting.jsx +++ b/src/components/Project/ProjectSetting.jsx @@ -3,9 +3,10 @@ import { ComingSoonPage } from "../../pages/Misc/ComingSoonPage"; import ProjectPermission from "./ProjectPermission"; const ProjectSetting = () => { - const [activePill, setActivePill] = useState(() => { - return localStorage.getItem("lastActiveProjectSettingTab") || "Permissions"; - }); + const [activePill, setActivePill] = useState("Permissions") + // const [activePill, setActivePill] = useState(() => { + // return localStorage.getItem("lastActiveProjectSettingTab") || "Permissions"; + // }); const projectSettingTab = [ { key: "Permissions", label: "Permissions" }, { key: "Notification", label: "Notification" }, @@ -32,7 +33,7 @@ const ProjectSetting = () => { return (
-
+ {/*
-
+
*/}
{renderContent()}
From 4ad87af7f40f95a55b406a9d763b158b7a1e3442 Mon Sep 17 00:00:00 2001 From: Vikas Nale Date: Wed, 17 Sep 2025 15:22:25 +0530 Subject: [PATCH 5/6] Add FAQ Answers on landing page --- src/pages/Home/LandingPage.jsx | 102 ++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 35 deletions(-) diff --git a/src/pages/Home/LandingPage.jsx b/src/pages/Home/LandingPage.jsx index 0156ae5b..bffadf03 100644 --- a/src/pages/Home/LandingPage.jsx +++ b/src/pages/Home/LandingPage.jsx @@ -968,12 +968,12 @@ const LandingPage = () => { className="accordion-collapse collapse" data-bs-parent="#accordionExample" > -
- Lemon drops chocolate cake gummies carrot cake chupa - chups muffin topping. Sesame snaps icing marzipan gummi - bears macaroon dragée danish caramels powder. Bear claw - dragée pastry topping soufflé. Wafer gummi bears - marshmallow pastry pie. +
+ A smart Project Management System designed to bring + teams, tasks, and timelines together in one place. With + AI-driven insights, role-based access, and seamless + reporting, it empowers organizations to deliver projects + faster and smarter.
@@ -996,12 +996,13 @@ const LandingPage = () => { aria-labelledby="headingTwo" data-bs-parent="#accordionExample" > -
- Dessert ice cream donut oat cake jelly-o pie sugar plum - cheesecake. Bear claw dragée oat cake dragée ice cream - halvah tootsie roll. Danish cake oat cake pie macaroon - tart donut gummies. Jelly beans candy canes carrot cake. - Fruitcake chocolate chupa chups. +
+ Yes, you have full flexibility to manage your + subscription. You can upgrade to a higher plan to unlock + more features, downgrade to a smaller plan if your needs + change, or cancel your subscription anytime. Plan + changes take effect instantly, and billing adjustments + are applied on a pro-rated basis.
@@ -1024,17 +1025,16 @@ const LandingPage = () => { aria-labelledby="headingThree" data-bs-parent="#accordionExample" > -
- Regular license can be used for end products that do not - charge users for access or service(access is free and - there will be no monthly subscription fee). Single - regular license can be used for single end product and - end product can be used by you or your client. If you - want to sell end product to multiple clients then you - will need to purchase separate license for each client. - The same rule applies if you want to use the same end - product on multiple domains(unique setup). For more info - on regular license you can check official description. +
+ Security is at the core of Marco PMS. We use + industry-standard encryption (SSL/TLS) to protect data + in transit and advanced encryption to safeguard data at + rest. Role-based access controls ensure that only + authorized users can access sensitive information. Our + system is hosted on secure, cloud-ready infrastructure + with regular backups, monitoring, and compliance with + best practices to keep your data safe and available at + all times.
@@ -1057,12 +1057,12 @@ const LandingPage = () => { aria-labelledby="headingFour" data-bs-parent="#accordionExample" > -
- Lorem ipsum dolor sit amet consectetur adipisicing elit. - Nobis et aliquid quaerat possimus maxime! Mollitia - reprehenderit neque repellat deleniti delectus - architecto dolorum maxime, blanditiis earum ea, incidunt - quam possimus cumque. +
+ You can reach our support team anytime through the + in-app help center, email, or live chat. We also provide + a detailed knowledge base and FAQs to guide you through + common queries. For personalized assistance, our support + specialists are always ready to help you.
@@ -1085,15 +1085,47 @@ const LandingPage = () => { aria-labelledby="headingFive" data-bs-parent="#accordionExample" > -
- Lorem ipsum dolor sit amet consectetur, adipisicing - elit. Sequi molestias exercitationem ab cum nemo facere - voluptates veritatis quia, eveniet veniam at et - repudiandae mollitia ipsam quasi labore enim architecto - non! +
+ Marco PMS operate under a proprietary license combined + with a subscription model. This means customers don’t + own the software but are granted the right to access and + use it through the cloud under our Terms of Service. + Depending on the plan, licensing may be based on users, + features, or usage, and you can upgrade, downgrade, or + cancel at any time. non!
+
+

+ +

+
+
+ Yes, Marco PMS is designed to be flexible and adaptable. + You can customize workflows, user roles, permissions, + and reporting to match your organization’s unique + processes. Depending on your plan, we also support + advanced customization such as integrating with + third-party tools, adding custom fields, and tailoring + modules to fit your business requirements. +
+
+
{" "} From d3218eb77a9e5cbb115a8c70dd5f3530a19eb45a Mon Sep 17 00:00:00 2001 From: pramod mahajan Date: Wed, 17 Sep 2025 15:50:44 +0530 Subject: [PATCH 6/6] handle project set null at employee details page --- src/pages/employee/EmployeeProfile.jsx | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/pages/employee/EmployeeProfile.jsx b/src/pages/employee/EmployeeProfile.jsx index 26b3da7b..164643d1 100644 --- a/src/pages/employee/EmployeeProfile.jsx +++ b/src/pages/employee/EmployeeProfile.jsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from "react"; import { useSearchParams, useParams, useNavigate } from "react-router-dom"; -import { useSelector } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import { useEmployee, @@ -23,22 +23,33 @@ import EmpBanner from "../../components/Employee/EmpBanner"; import EmpDashboard from "../../components/Employee/EmpDashboard"; import EmpDocuments from "../../components/Employee/EmpDocuments"; import EmpActivities from "../../components/Employee/EmpActivities"; +import { setProjectId } from "../../slices/localVariablesSlice"; const EmployeeProfile = () => { const { profile } = useProfile(); const projectID = useSelector((store) => store.localVariables.projectId); + const { employeeId } = useParams(); + const dispatch = useDispatch(); const [SearchParams] = useSearchParams(); const tab = SearchParams.get("for"); const [activePill, setActivePill] = useState(tab || "profile"); const [showModal, setShowModal] = useState(false); - const {data:currentEmployee,isLoading,isError,error} = useEmployee(employeeId) + const { + data: currentEmployee, + isLoading, + isError, + error, + } = useEmployee(employeeId); const handlePillClick = (pillKey) => { setActivePill(pillKey); }; + useEffect(() => { + dispatch(setProjectId(null)); + }, [projectID]); const navigate = useNavigate(); const renderContent = () => { @@ -87,7 +98,7 @@ const EmployeeProfile = () => { if (isLoading) { return
Loading...
; } - if(isError) return
{error.message}
+ if (isError) return
{error.message}
; return ( <>
@@ -115,11 +126,11 @@ const EmployeeProfile = () => {
-
{renderContent()}
+
{renderContent()}
); }; -export default EmployeeProfile; \ No newline at end of file +export default EmployeeProfile;