diff --git a/src/components/Project/ProjectPermission.jsx b/src/components/Project/ProjectPermission.jsx index 4a6a5504..471e283d 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,50 +95,57 @@ const ProjectPermission = () => { permission: payloadPermissions, }; + console.log("Final payload:", payload); updatePermission(payload); }; - const useOnClick = useCallback((event) => {}, []); return (
+
+

Project Permission

+
-
-
+ {loading ? ( + + ) : ( + <> + + {[...employees] + ?.sort((a, b) => + `${a?.firstName} ${a?.firstName}`?.localeCompare( + `${b?.firstName} ${b?.lastName}` + ) ) - ) - ?.map((emp) => ( - - ))} - + ?.map((emp) => ( + + ))} + + )} + + {errors.employeeId && ( +
+ {errors.employeeId.message} +
)} -
- - {errors.employeeId && ( -
- {errors.employeeId.message} -
- )} +
- {isDirty && ( -
+ +
+ {isDirty && ( -
- )} + )} +
{ProjectModules.map((feature) => ( @@ -157,22 +165,41 @@ const ProjectPermission = () => {

{feature.name}

-
-
+ */}
{renderContent()}
diff --git a/src/pages/Home/LandingPage.jsx b/src/pages/Home/LandingPage.jsx index c7806349..6d5a44ca 100644 --- a/src/pages/Home/LandingPage.jsx +++ b/src/pages/Home/LandingPage.jsx @@ -636,12 +636,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.
@@ -664,12 +664,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.
@@ -692,17 +693,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.
@@ -725,12 +725,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.
@@ -753,15 +753,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. +
+
+
{" "} 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; 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)); }