- Add date format hook
- add Ui for Activities
This commit is contained in:
parent
210d16c765
commit
beefe6396c
10
package-lock.json
generated
10
package-lock.json
generated
@ -18,6 +18,7 @@
|
||||
"apexcharts": "^4.5.0",
|
||||
"axios": "^1.7.9",
|
||||
"axios-retry": "^4.5.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"dotenv": "^16.4.7",
|
||||
"dotenv-webpack": "^8.1.0",
|
||||
"eventemitter3": "^5.0.1",
|
||||
@ -2455,6 +2456,15 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
|
||||
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/kossnocorp"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||
|
@ -21,6 +21,7 @@
|
||||
"apexcharts": "^4.5.0",
|
||||
"axios": "^1.7.9",
|
||||
"axios-retry": "^4.5.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"dotenv": "^16.4.7",
|
||||
"dotenv-webpack": "^8.1.0",
|
||||
"eventemitter3": "^5.0.1",
|
||||
|
155
src/components/Employee/EmpActivities.jsx
Normal file
155
src/components/Employee/EmpActivities.jsx
Normal file
@ -0,0 +1,155 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import moment from "moment";
|
||||
import DateRangePicker from "../common/DateRangePicker";
|
||||
import useFormattedDate from "../../hooks/useFormattedDate";
|
||||
import { useProjectTasksByEmployee } from "../../hooks/useProjects";
|
||||
|
||||
const EmpActivities = ({ employee }) => {
|
||||
const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" });
|
||||
const myDate = new Date("2025-08-06T10:30:00Z");
|
||||
const formattedToday = useFormattedDate(myDate, "dd-MMM-yyyy");
|
||||
console.log(employee);
|
||||
|
||||
const {
|
||||
ProjectTaskList,
|
||||
loading: selectedProjectLoding,
|
||||
refetch,
|
||||
} = useProjectTasksByEmployee(employee?.id);
|
||||
|
||||
console.log(ProjectTaskList);
|
||||
return (
|
||||
<>
|
||||
<div className="card h-100 mt-4">
|
||||
<div className="card-body">
|
||||
<div className="my-0 text-start">
|
||||
<DateRangePicker
|
||||
DateDifference="30"
|
||||
onRangeChange={setDateRange}
|
||||
endDateMode="today"
|
||||
/>
|
||||
</div>
|
||||
<ul className="timeline mb-0 mt-5 text-start">
|
||||
<li className="timeline-item timeline-item-transparent">
|
||||
<span className="timeline-point timeline-point-primary"></span>
|
||||
<div className="timeline-event">
|
||||
<div className="timeline-header mb-3">
|
||||
<h6 className="mb-0">Matrix Properties</h6>
|
||||
<small className="text-body-secondary">
|
||||
{formattedToday}
|
||||
</small>
|
||||
</div>
|
||||
<p className="mb-2">Branch Fitting</p>
|
||||
<p className="mb-2">
|
||||
Building 1 > First Floor > Zone One
|
||||
</p>
|
||||
<p className="mb-2">
|
||||
<span>Planned: 22 Meter</span>
|
||||
<span className="ms-2">Completed: 22 Meter</span>
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li className="timeline-item timeline-item-transparent">
|
||||
<span className="timeline-point timeline-point-success"></span>
|
||||
<div className="timeline-event">
|
||||
<div className="timeline-header mb-3">
|
||||
<h6 className="mb-0">Client Meeting</h6>
|
||||
<small className="text-body-secondary">45 min ago</small>
|
||||
</div>
|
||||
<p className="mb-2">Project meeting with john @10:15am</p>
|
||||
<div className="d-flex justify-content-between flex-wrap gap-2 mb-2">
|
||||
<div className="d-flex flex-wrap align-items-center mb-50">
|
||||
<div className="avatar avatar-sm me-2">
|
||||
<img
|
||||
src="../../assets/img/avatars/1.png"
|
||||
alt="Avatar"
|
||||
className="rounded-circle"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<p className="mb-0 small fw-medium">
|
||||
Lester McCarthy (Client)
|
||||
</p>
|
||||
<small>CEO of ThemeSelection</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li className="timeline-item timeline-item-transparent">
|
||||
<span className="timeline-point timeline-point-info"></span>
|
||||
<div className="timeline-event">
|
||||
<div className="timeline-header mb-3">
|
||||
<h6 className="mb-0">Create a new project for client</h6>
|
||||
<small className="text-body-secondary">2 Day Ago</small>
|
||||
</div>
|
||||
<p className="mb-2">6 team members in a project</p>
|
||||
<ul className="list-group list-group-flush">
|
||||
<li className="list-group-item d-flex justify-content-between align-items-center flex-wrap border-top-0 p-0">
|
||||
<div className="d-flex flex-wrap align-items-center">
|
||||
<ul className="list-unstyled users-list d-flex align-items-center avatar-group m-0 me-2">
|
||||
<li
|
||||
data-bs-toggle="tooltip"
|
||||
data-popup="tooltip-custom"
|
||||
data-bs-placement="top"
|
||||
className="avatar pull-up"
|
||||
aria-label="Vinnie Mostowy"
|
||||
data-bs-original-title="Vinnie Mostowy"
|
||||
>
|
||||
<img
|
||||
className="rounded-circle"
|
||||
src="../../assets/img/avatars/5.png"
|
||||
alt="Avatar"
|
||||
/>
|
||||
</li>
|
||||
<li
|
||||
data-bs-toggle="tooltip"
|
||||
data-popup="tooltip-custom"
|
||||
data-bs-placement="top"
|
||||
className="avatar pull-up"
|
||||
aria-label="Allen Rieske"
|
||||
data-bs-original-title="Allen Rieske"
|
||||
>
|
||||
<img
|
||||
className="rounded-circle"
|
||||
src="../../assets/img/avatars/12.png"
|
||||
alt="Avatar"
|
||||
/>
|
||||
</li>
|
||||
<li
|
||||
data-bs-toggle="tooltip"
|
||||
data-popup="tooltip-custom"
|
||||
data-bs-placement="top"
|
||||
className="avatar pull-up"
|
||||
aria-label="Julee Rossignol"
|
||||
data-bs-original-title="Julee Rossignol"
|
||||
>
|
||||
<img
|
||||
className="rounded-circle"
|
||||
src="../../assets/img/avatars/6.png"
|
||||
alt="Avatar"
|
||||
/>
|
||||
</li>
|
||||
<li className="avatar">
|
||||
<span
|
||||
className="avatar-initial rounded-circle pull-up"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-placement="bottom"
|
||||
data-bs-original-title="3 more"
|
||||
>
|
||||
+3
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default EmpActivities;
|
@ -120,7 +120,7 @@ const EmpAttendance = ({ employee }) => {
|
||||
<AttendLogs Id={attendanceId} />
|
||||
</GlobalModel>
|
||||
)}
|
||||
<div className="card px-4 mt-0 py-2 " style={{ minHeight: "500px" }}>
|
||||
<div className="card px-4 mt-5 py-2 " style={{ minHeight: "500px" }}>
|
||||
<div
|
||||
className="dataTables_length text-start py-2 d-flex justify-content-between "
|
||||
id="DataTables_Table_0_length"
|
||||
|
@ -24,7 +24,7 @@ const EmpBanner = ({ profile, loggedInUser }) => {
|
||||
)}
|
||||
<div className="user-profile-header d-flex flex-column flex-lg-row text-sm-start text-center mb-8">
|
||||
<div className="flex-shrink-0 mt-1 mx-sm-0 mx-auto">
|
||||
{profile.gender.toLowerCase() == "male" && (
|
||||
{profile?.gender?.toLowerCase() == "male" && (
|
||||
<img
|
||||
width={125}
|
||||
src="../../assets/img/avatars/avatar_m_01.png"
|
||||
@ -32,7 +32,7 @@ const EmpBanner = ({ profile, loggedInUser }) => {
|
||||
className="d-block h-auto ms-0 ms-sm-6 rounded-3 user-profile-img"
|
||||
/>
|
||||
)}
|
||||
{profile.gender.toLowerCase() == "female" && (
|
||||
{profile?.gender?.toLowerCase() == "female" && (
|
||||
<img
|
||||
width={125}
|
||||
src="../../assets/img/avatars/avatar_f_02.png"
|
||||
|
@ -5,7 +5,7 @@ const EmpDocuments = ({ profile, loggedInUser }) => {
|
||||
<>
|
||||
<div
|
||||
id="DataTables_Table_0_wrapper"
|
||||
class="dt-container dt-bootstrap5 dt-empty-footer"
|
||||
class=" card mt-5 dt-container dt-bootstrap5 dt-empty-footer"
|
||||
>
|
||||
<div class="row card-header border-bottom mx-0 px-3 py-2">
|
||||
<div class="d-md-flex justify-content-between align-items-center dt-layout-start col-md-auto me-auto">
|
||||
|
@ -27,8 +27,7 @@ const DateRangePicker = ({
|
||||
altInput: true,
|
||||
altFormat: "d-m-Y",
|
||||
defaultDate: [startDate, endDate],
|
||||
static: false,
|
||||
// appendTo: document.body,
|
||||
static: true,
|
||||
clickOpens: true,
|
||||
maxDate: endDate,
|
||||
onChange: (selectedDates, dateStr) => {
|
||||
|
26
src/hooks/useFormattedDate.js
Normal file
26
src/hooks/useFormattedDate.js
Normal file
@ -0,0 +1,26 @@
|
||||
import { format } from "date-fns";
|
||||
|
||||
/**
|
||||
* A custom hook to format a date string, object, or number.
|
||||
* @param {string | Date | number} date - The date to be formatted.
|
||||
* @param {string} formatString - The format string (e.g., 'MMMM do, yyyy').
|
||||
* @returns {string} The formatted date string.
|
||||
*/
|
||||
const useFormattedDate = (date, formatString) => {
|
||||
// Return early if no date is provided
|
||||
if (!date) {
|
||||
return "";
|
||||
}
|
||||
|
||||
try {
|
||||
const dateObj = new Date(date);
|
||||
// You could also add error handling for invalid dates
|
||||
// if (!isValid(dateObj)) return 'Invalid Date';
|
||||
return format(dateObj, formatString);
|
||||
} catch (error) {
|
||||
console.error("Error formatting date:", error);
|
||||
return ""; // Return an empty string or a default value on error
|
||||
}
|
||||
};
|
||||
|
||||
export default useFormattedDate;
|
@ -206,6 +206,34 @@ export const useProjectTasks = (workAreaId, IsExpandedArea = false) => {
|
||||
return { ProjectTaskList, isLoading, error };
|
||||
};
|
||||
|
||||
export const useProjectTasksByEmployee = (
|
||||
employeeId,
|
||||
fromDate,
|
||||
toDate,
|
||||
IsExpandedArea = false
|
||||
) => {
|
||||
const {
|
||||
data: ProjectTaskList,
|
||||
isLoading,
|
||||
error,
|
||||
} = useQuery({
|
||||
queryKey: ["TasksByEmployee", employeeId],
|
||||
queryFn: async () => {
|
||||
const res = await ProjectRepository.getProjectTasksByEmployee(
|
||||
employeeId,
|
||||
fromDate,
|
||||
toDate
|
||||
);
|
||||
return res.data;
|
||||
},
|
||||
enabled: !!employeeId && !!IsExpandedArea,
|
||||
onError: (error) => {
|
||||
showToast(error.message || "Error while Fetching project Tasks", "error");
|
||||
},
|
||||
});
|
||||
return { ProjectTaskList, isLoading, error };
|
||||
};
|
||||
|
||||
// -- -------------Mutation-------------------------------
|
||||
|
||||
export const useCreateProject = ({ onSuccessCallback }) => {
|
||||
|
@ -21,6 +21,7 @@ import ManageEmployee from "../../components/Employee/ManageEmployee";
|
||||
import EmpBanner from "../../components/Employee/EmpBanner";
|
||||
import EmpDashboard from "../../components/Employee/EmpDashboard";
|
||||
import EmpDocuments from "../../components/Employee/EmpDocuments";
|
||||
import EmpActivities from "../../components/Employee/EmpActivities";
|
||||
|
||||
const EmployeeProfile = () => {
|
||||
const { profile } = useProfile();
|
||||
@ -85,7 +86,7 @@ const EmployeeProfile = () => {
|
||||
case "activities": {
|
||||
return (
|
||||
<>
|
||||
<ComingSoonPage />
|
||||
<EmpActivities employee={currentEmployee} />
|
||||
</>
|
||||
);
|
||||
break;
|
||||
|
@ -33,6 +33,10 @@ const ProjectRepository = {
|
||||
getProjectDetails: (id) => api.get(`/api/project/details/${id}`),
|
||||
getProjectInfraByproject: (id) => api.get(`/api/project/infra-details/${id}`),
|
||||
getProjectTasksByWorkArea: (id) => api.get(`/api/project/tasks/${id}`),
|
||||
getProjectTasksByEmployee: (id, fromDate, toDate) =>
|
||||
api.get(
|
||||
`/api/project/tasks-employee/${id}?fromDate=${fromDate}&toDate:${toDate}`
|
||||
),
|
||||
};
|
||||
|
||||
export const TasksRepository = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user