Add more cosmatic changes for notes editor

This commit is contained in:
Vikas Nale 2025-06-12 18:48:30 +05:30
parent 3305c0b0d9
commit 6b9670b942
6 changed files with 142 additions and 116 deletions

View File

@ -128,9 +128,7 @@ const ManageBucket = () => {
setBucketList(updatedData);
showToast("Bucket Updated Successfully", "success");
}
else {
} else {
response = await DirectoryRepository.CreateBuckets(data);
const updatedBuckets = [...cache_buckets, response?.data];
@ -187,8 +185,8 @@ const ManageBucket = () => {
select_bucket(null);
setAction_bucket(false);
setSubmitting(false);
reset({ name: "", description: "" });
setSelectEmployee([]);
reset({ name: "", description: "" });
setSelectEmployee([]);
};
const sortedBucktesList = sortedBuckteList?.filter((bucket) => {
@ -255,9 +253,9 @@ const ManageBucket = () => {
}`}
onClick={() => {
setAction_bucket(true);
select_bucket(null);
reset({ name: "", description: "" });
setSelectEmployee([]);
select_bucket(null);
reset({ name: "", description: "" });
setSelectEmployee([]);
}}
>
<i className="bx bx-plus-circle me-2"></i>
@ -292,10 +290,13 @@ const ManageBucket = () => {
sortedBucktesList.map((bucket) => (
<div className="col" key={bucket.id}>
<div className="card h-100">
<div className="card-body">
<div className="card-body p-4">
<h6 className="card-title d-flex justify-content-between align-items-center">
<span>{bucket.name}</span>
{(DirManager || DirAdmin || bucket?.createdBy?.id === profile?.employeeInfo?.id) && (
{(DirManager ||
DirAdmin ||
bucket?.createdBy?.id ===
profile?.employeeInfo?.id) && (
<div className="d-flex gap-2">
<i
className="bx bx-edit bx-sm text-primary cursor-pointer"
@ -303,8 +304,12 @@ const ManageBucket = () => {
select_bucket(bucket);
setAction_bucket(true);
const initialSelectedEmployees = employeesList
.filter(emp => bucket.employeeIds?.includes(emp.employeeId))
.map(emp => ({ ...emp, isActive: true }));
.filter((emp) =>
bucket.employeeIds?.includes(
emp.employeeId
)
)
.map((emp) => ({ ...emp, isActive: true }));
setSelectEmployee(initialSelectedEmployees);
}}
></i>
@ -315,10 +320,16 @@ const ManageBucket = () => {
</div>
)}
</h6>
<h6 className="card-subtitle mb-2 text-muted">
Contacts: {bucket.numberOfContacts}
<h6 className="card-subtitle mb-2 text-muted text-start">
Contacts:{" "}
{bucket.numberOfContacts
? bucket.numberOfContacts
: 0}
</h6>
<p className="card-text text-start" title={bucket.description}>
<p
className="card-text text-start"
title={bucket.description}
>
{bucket.description || "No description available."}
</p>
</div>
@ -330,7 +341,9 @@ const ManageBucket = () => {
<>
<form onSubmit={handleSubmit(onSubmit)} className="px-2 px-sm-0">
<div className="mb-3">
<label htmlFor="bucketName" className="form-label">Bucket Name</label>
<label htmlFor="bucketName" className="form-label">
Bucket Name
</label>
<input
id="bucketName"
className="form-control form-control-sm"
@ -341,7 +354,9 @@ const ManageBucket = () => {
)}
</div>
<div className="mb-3">
<label htmlFor="bucketDescription" className="form-label">Bucket Description</label>
<label htmlFor="bucketDescription" className="form-label">
Bucket Description
</label>
<textarea
id="bucketDescription"
className="form-control form-control-sm"
@ -365,7 +380,7 @@ const ManageBucket = () => {
<div className="mt-4 d-flex justify-content-center gap-3">
<button
type="button"
type="button"
onClick={handleBack}
className="btn btn-sm btn-secondary"
disabled={isSubmitting}
@ -389,4 +404,4 @@ const ManageBucket = () => {
);
};
export default ManageBucket;
export default ManageBucket;

View File

@ -132,17 +132,17 @@ const NoteCardDirectory = ({
<div className="d-flex align-items-center">
<Avatar
size="xs"
firstName={noteItem.createdBy.firstName}
lastName={noteItem.createdBy.lastName}
firstName={noteItem?.createdBy?.firstName}
lastName={noteItem?.createdBy?.lastName}
className="m-0"
/>
<div className="d-flex flex-column ms-2">
<span className="fw-semibold small">
{noteItem.createdBy.firstName} {noteItem.createdBy.lastName}
{noteItem?.createdBy?.firstName} {noteItem?.createdBy?.lastName}
</span>
<span className="text-muted" style={{ fontSize: "10px" }}>
{moment
.utc(noteItem.createdAt)
.utc(noteItem?.createdAt)
.add(5, "hours")
.add(30, "minutes")
.format("MMMM DD, YYYY [at] hh:mm A")}
@ -160,7 +160,7 @@ const NoteCardDirectory = ({
{!isDeleting ? (
<i
className="bx bx-trash bx-sm me-1 text-secondary cursor-pointer"
onClick={() => handleDeleteNote(!noteItem.isActive)}
onClick={() => handleDeleteNote(!noteItem?.isActive)}
></i>
) : (
<div
@ -176,7 +176,7 @@ const NoteCardDirectory = ({
) : (
<i
className="bx bx-recycle me-1 text-primary cursor-pointer"
onClick={() => handleDeleteNote(!noteItem.isActive)}
onClick={() => handleDeleteNote(!noteItem?.isActive)}
title="Restore"
></i>
)}

View File

@ -103,34 +103,44 @@ const NotesDirectory = ({
<p className="fw-semibold m-0">Notes :</p>
</div>
<div className="d-flex align-items-center justify-content-between mb-5">
<div className="m-0 d-flex aligin-items-center">
<label className="switch switch-primary">
<input
type="checkbox"
className="switch-input"
onChange={() => handleSwitch(!IsActive)}
value={IsActive}
/>
<span className="switch-toggle-slider">
<span className="switch-on">
{/* <i class="icon-base bx bx-check"></i> */}
{contactNotes?.length > 0 && (
<div className="m-0 d-flex aligin-items-center">
<label className="switch switch-primary">
<input
type="checkbox"
className="switch-input"
onChange={() => handleSwitch(!IsActive)}
value={IsActive}
/>
<span className="switch-toggle-slider">
<span className="switch-on">
{/* <i class="icon-base bx bx-check"></i> */}
</span>
<span className="switch-off">
{/* <i class="icon-base bx bx-x"></i> */}
</span>
</span>
<span className="switch-off">
{/* <i class="icon-base bx bx-x"></i> */}
</span>
</span>
<span className="switch-label ">Include Deleted Notes</span>
</label>
</div>
<span className="switch-label ">Include Deleted Notes</span>
</label>
</div>
)}
{!addNote && (
<div className="d-flex justify-content-center px-2">
<div
className={`
${
contactNotes?.length > 0
? "d-flex justify-content-center px-2"
: "d-flex justify-content-center px-2w-100"
}`}
>
<span
className={`btn btn-sm ${
addNote ? "btn-danger" : "btn-primary"
}`}
onClick={() => setAddNote(!addNote)}
>
{addNote ? "Hide Editor" : "Add Note"}
{addNote ? "Hide Editor" : "Add a Note"}
</span>
</div>
)}

View File

@ -64,7 +64,7 @@ const Header = () => {
navigate(`/employee/${profile?.employeeInfo?.id}?for=attendance`);
};
// const { projects, loading: projectLoading } = useProjects();
const { projectNames, loading: projectLoading } = useProjectName();
const { projectNames, loading: projectLoading } = useProjectName();
const selectedProject = useSelector(
(store) => store.localVariables.projectId
@ -88,8 +88,11 @@ const Header = () => {
if (projectNames && selectedProject !== " ") {
dispatch(setProjectId(projectNames[0]?.id));
}
}, [projectNames, ]);
const isProjectPath = /^\/projectNames\/[a-f0-9-]{36}$/.test(location.pathname);
}, [projectNames]);
/** Check if current page id project details page */
const isProjectPath = /^\/projects\/[a-f0-9-]{36}$/.test(location.pathname);
return (
<nav
className="layout-navbar container-xxl navbar navbar-expand-xl navbar-detached align-items-center bg-navbar-theme"
@ -107,39 +110,45 @@ const Header = () => {
className="navbar-nav-right d-flex align-items-center justify-content-between"
id="navbar-collapse"
>
{projectNames?.length > 0 && ( <div className=" align-items-center">
{!isProjectPath && (
<>
<i
className="rounded-circle bx bx-building-house"
style={{ fontSize: "xx-large" }}
></i>
<div className="btn-group">
<button
className={`btn btn-sm-sm btn-xl ${projectNames?.length > 1 && "dropdown-toggle" } px-1`}
type="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
{displayText}
</button>
{projectNames?.length > 1 && ( <ul className="dropdown-menu">
{projectNames?.map((project) => (
<li key={project?.id}>
<button
className="dropdown-item"
onClick={() => dispatch(setProjectId(project?.id))}
>
{project?.name}
</button>
</li>
))}
</ul>)}
</div>
</>
)}
</div>)}
{projectNames?.length > 0 && (
<div className=" align-items-center">
{!isProjectPath && (
<>
<i
className="rounded-circle bx bx-building-house"
style={{ fontSize: "xx-large" }}
></i>
<div className="btn-group">
<button
className={`btn btn-sm-sm btn-xl ${
projectNames?.length > 1 && "dropdown-toggle"
} px-1`}
type="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
{displayText}
</button>
{projectNames?.length > 1 && (
<ul className="dropdown-menu">
{projectNames?.map((project) => (
<li key={project?.id}>
<button
className="dropdown-item"
onClick={() => dispatch(setProjectId(project?.id))}
>
{project?.name}
</button>
</li>
))}
</ul>
)}
</div>
</>
)}
</div>
)}
<ul className="navbar-nav flex-row align-items-center ms-md-auto">
<li className="nav-item dropdown-shortcuts navbar-dropdown dropdown me-2 me-xl-0">

View File

@ -6,15 +6,15 @@
"text": "Dashboard",
"icon": "bx bx-home",
"available": true,
"link": "/projects"
"link": "/dashboard"
},
{
{
"text": "Projects",
"icon": "bx bx-building-house",
"available": true,
"link": "/dashboard"
"link": "/projects"
},
{
{
"text": "Employees",
"icon": "bx bx-user",
"available": true,
@ -58,7 +58,7 @@
}
]
},
{
{
"text": "Directory",
"icon": "bx bx-group",
"available": true,

View File

@ -7,8 +7,7 @@ import { setProjectId } from "../slices/localVariablesSlice";
import EmployeeList from "../components/Directory/EmployeeList";
export const useProjects = () => {
const loggedUser = useSelector( ( store ) => store.globalVariables.loginUser )
const loggedUser = useSelector((store) => store.globalVariables.loginUser);
const [projects, setProjects] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState("");
@ -129,39 +128,34 @@ export const useProjectDetails = (projectId) => {
}
}, [projectId, profile]);
return { projects_Details, loading, error, refetch: fetchData }
}
return { projects_Details, loading, error, refetch: fetchData };
};
export const useProjectsByEmployee = ( employeeId ) =>
{
export const useProjectsByEmployee = (employeeId) => {
const [projectList, setProjectList] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const [error, setError] = useState("");
const fetchProjects = async (id) => {
try {
setLoading(true);
setError(''); // clear previous error
setError(""); // clear previous error
const res = await ProjectRepository.getProjectsByEmployee(id);
setProjectList(res.data);
cacheData( 'ProjectsByEmployee', {data: res.data, employeeId: id} );
setLoading(false)
cacheData("ProjectsByEmployee", { data: res.data, employeeId: id });
setLoading(false);
} catch (err) {
setError( err?.message || 'Failed to fetch projects' );
setLoading(false)
}
setError(err?.message || "Failed to fetch projects");
setLoading(false);
}
};
useEffect(() => {
if (!employeeId) return;
const cache_project = getCachedData('ProjectsByEmployee');
const cache_project = getCachedData("ProjectsByEmployee");
if (
!cache_project?.data ||
cache_project?.employeeId !== employeeId
) {
if (!cache_project?.data || cache_project?.employeeId !== employeeId) {
fetchProjects(employeeId);
} else {
setProjectList(cache_project.data);
@ -172,31 +166,29 @@ export const useProjectsByEmployee = ( employeeId ) =>
projectList,
loading,
error,
refetch : fetchProjects
}
refetch: fetchProjects,
};
};
export const useProjectName = () => {
const [loading, setLoading] = useState(true);
const [projectNames, setProjectName] = useState([]);
const[Error,setError] = useState()
const [Error, setError] = useState();
const fetchData = async () => {
try {
let response = await ProjectRepository.projectNameList();
console.log(response)
setProjectName(response.data);
cacheData("basicProjectNameList",response.data);
setLoading(false);
let response = await ProjectRepository.projectNameList();
setProjectName(response.data);
cacheData("basicProjectNameList", response.data);
setLoading(false);
} catch (err) {
setError("Failed to fetch data.");
setLoading(false);
}
};
useEffect(() => {
fetchData();
useEffect(() => {
fetchData();
}, []);
return { projectNames, loading, Error };
};