report
parent
6f137b548e
commit
96835cf13f
6
.env
6
.env
|
@ -1,8 +1,8 @@
|
|||
NODE_ENV="development"
|
||||
|
||||
NEXT_PUBLIC_SERVER_URL=http://192.168.88.12:32769
|
||||
NEXT_PUBLIC_PUBLIC_URL=http://192.168.88.12:32769
|
||||
NEXT_PUBLIC_API_URL=http://192.168.88.12:32769/api
|
||||
NEXT_PUBLIC_SERVER_URL=http://192.168.189.123:32769
|
||||
NEXT_PUBLIC_PUBLIC_URL=http://192.168.189.123:32769
|
||||
NEXT_PUBLIC_API_URL=http://192.168.189.123:32769/api
|
||||
|
||||
# SECURE_LOCAL_STORAGE_HASH_KEY=f1da2b2c7a4c446934267fea631102ec389b5b99
|
||||
# NEXT_PUBLIC_API_URL_IMAGE=https://192.168.88.12:49154/Files/ReportImages
|
||||
|
|
|
@ -63,12 +63,6 @@ const LoginStep = (props) => {
|
|||
}`}
|
||||
>
|
||||
<div>
|
||||
{/* <input
|
||||
type="checkbox"
|
||||
className="w-[40px] h-[40px] !rounded-xl mx-2 custom-checkbox mt-1"
|
||||
value={}
|
||||
/> */}
|
||||
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={roleCheckBox ? true : false}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
"use client";
|
||||
|
||||
import React, { useContext, useEffect, useRef, useState } from "react";
|
||||
import { BottomSheet } from "react-spring-bottom-sheet";
|
||||
import Input from "plugins/Input/page";
|
||||
import AppContext from "@ctx/AppContext";
|
||||
import SimpleReactValidator from "simple-react-validator";
|
||||
import CheckBoxBriz from "plugins/CheckBoxBriz/page";
|
||||
import Buttonbriz from "plugins/Buttonbriz/page";
|
||||
import { toast } from "react-toastify";
|
||||
|
||||
const BottomSheetReport = (props) => {
|
||||
const CTX = useContext(AppContext);
|
||||
const reportDetail = CTX.state.reportDetail;
|
||||
|
||||
const handleSendReport_SHIFTPLAN = () => {
|
||||
CTX.ReportShiftPlan(reportDetail?.shiftId);
|
||||
CTX.setBottomSheetReportOpen(false);
|
||||
};
|
||||
|
||||
const handleSendReport_TASK = () => {
|
||||
CTX.ReportTask();
|
||||
CTX.setBottomSheetReportOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<BottomSheet
|
||||
open={CTX.state.BottomSheetReportOpen}
|
||||
onDismiss={() => CTX.setBottomSheetReportOpen(false)}
|
||||
blocking={false}
|
||||
>
|
||||
<div className="text-center py-2 bg-primary-300 ">
|
||||
<p className="mb-0 text-white relative top-[-5px]">گزارشات</p>
|
||||
</div>
|
||||
|
||||
<div className="px-3 pt-10 ">
|
||||
<p className="mb-0 text-center text-sm font-light">
|
||||
شما در حال گرفتن گزارش برای
|
||||
<small className="text-sm font-medium"> {reportDetail?.title} </small>
|
||||
هستید
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className=" p-4">
|
||||
<Buttonbriz
|
||||
title="گرفتن گزارش"
|
||||
color="INFO"
|
||||
icon="CHECK"
|
||||
buttonEvent={() => {
|
||||
if (reportDetail.typeReport == "TASK") {
|
||||
handleSendReport_TASK();
|
||||
} else if (reportDetail.typeReport == "SHIFTPLAN") {
|
||||
handleSendReport_SHIFTPLAN();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</BottomSheet>
|
||||
);
|
||||
};
|
||||
|
||||
export default BottomSheetReport;
|
|
@ -86,7 +86,7 @@ const Buttonbriz = ({
|
|||
>
|
||||
{icons.find((e) => e.iconName == icon)?.icon}
|
||||
</div>
|
||||
<span className="text-center mt-2">{title}</span>
|
||||
<span className="text-center mt-2 text-sm font-medium ">{title}</span>
|
||||
<div className="w-[40px] h-[40px] rounded-xl "></div>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -102,7 +102,9 @@ const Buttonbriz = ({
|
|||
>
|
||||
<p
|
||||
className={`mb-0 tr03 ${
|
||||
subButtonAction ? "text-white font-semibold" : "text-red-500"
|
||||
subButtonAction
|
||||
? "text-white font-medium text-sm"
|
||||
: "text-red-500"
|
||||
} `}
|
||||
>
|
||||
{subButtonTitle}
|
||||
|
|
|
@ -19,6 +19,7 @@ import Chapar, { getToken } from "plugins/Chapar";
|
|||
import TimePicker from "plugins/TimePicker/page";
|
||||
import axios from "axios";
|
||||
import "rc-slider/assets/index.css";
|
||||
import BottomSheetReport from "plugins/BottomSheet/BottomSheetReport";
|
||||
|
||||
const inter = Inter({ subsets: ["latin"] });
|
||||
|
||||
|
@ -55,6 +56,8 @@ export default function RootLayout({ children }) {
|
|||
const [BottomSheetChangeRoleOpen, setBottomSheetChangeRoleOpen] =
|
||||
useState(false);
|
||||
|
||||
const [BottomSheetReportOpen, setBottomSheetReportOpen] = useState(false);
|
||||
|
||||
// BigPlus
|
||||
const [BigPlusOpen, setBigPlusOpen] = useState(false);
|
||||
const [BigPlusRotateIcon, setBigPlusRotateIcon] = useState(false);
|
||||
|
@ -117,6 +120,7 @@ export default function RootLayout({ children }) {
|
|||
const [goToEditShift, setGoToEditShift] = useState(false);
|
||||
const [idEditShift, setIdEditShift] = useState(null);
|
||||
const [shiftPlanData, setShiftPlanData] = useState([]);
|
||||
const [shiftPlansData, setShifPlansData] = useState([]);
|
||||
|
||||
// task
|
||||
const [routineForTaskChoose, setRoutineForTaskChoose] = useState([]);
|
||||
|
@ -145,6 +149,9 @@ export default function RootLayout({ children }) {
|
|||
// closeShift
|
||||
const [completeActivities, setCompleteActivities] = useState([]);
|
||||
|
||||
//report
|
||||
const [reportDetail, setReportDetail] = useState(null);
|
||||
|
||||
const pathname = usePathname();
|
||||
const router = useRouter();
|
||||
const hiddenUrls = ["/login", "/pricing", "/about-us", "/"];
|
||||
|
@ -263,7 +270,6 @@ export default function RootLayout({ children }) {
|
|||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const CreateRole = async (body) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
|
@ -388,7 +394,6 @@ export default function RootLayout({ children }) {
|
|||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const CreateUser = async (body) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
|
@ -514,7 +519,6 @@ export default function RootLayout({ children }) {
|
|||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const CreateShift = async (body) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
|
@ -600,57 +604,6 @@ export default function RootLayout({ children }) {
|
|||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const GetShiftPlan = async (id) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const data = await Chapar.get(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/shift/plan/${id}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: getToken(),
|
||||
},
|
||||
}
|
||||
);
|
||||
setShiftPlanData(data);
|
||||
setLoading(false);
|
||||
} catch ({ error, status }) {
|
||||
toast.error(`${error?.response?.data?.message}`, {
|
||||
position: "bottom-right",
|
||||
closeOnClick: true,
|
||||
});
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
const UpdateShiftPlan = async (body, id) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const data = await Chapar.put(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/shift/plan`,
|
||||
body,
|
||||
|
||||
{
|
||||
headers: {
|
||||
Authorization: getToken(),
|
||||
},
|
||||
}
|
||||
);
|
||||
toast.success(`شیفت ویرایش شد`, {
|
||||
position: "bottom-right",
|
||||
closeOnClick: true,
|
||||
});
|
||||
|
||||
setLoading(false);
|
||||
setShiftPlanData(id);
|
||||
} catch ({ error, status }) {
|
||||
toast.error(`${error?.response?.data?.message}`, {
|
||||
position: "bottom-right",
|
||||
closeOnClick: true,
|
||||
});
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const GetShift = async (id) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
|
@ -697,7 +650,6 @@ export default function RootLayout({ children }) {
|
|||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const CreateSection = async (body) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
|
@ -822,7 +774,6 @@ export default function RootLayout({ children }) {
|
|||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const CreateRoutine = async (body) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
|
@ -927,7 +878,6 @@ export default function RootLayout({ children }) {
|
|||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const GetRoutineShiftPlan = async (id, time) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
|
@ -951,6 +901,56 @@ export default function RootLayout({ children }) {
|
|||
setLoading(false);
|
||||
}
|
||||
};
|
||||
const GetShiftPlan = async (id) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const data = await Chapar.get(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/shift/plan/${id}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: getToken(),
|
||||
},
|
||||
}
|
||||
);
|
||||
setShiftPlanData(data);
|
||||
setLoading(false);
|
||||
} catch ({ error, status }) {
|
||||
toast.error(`${error?.response?.data?.message}`, {
|
||||
position: "bottom-right",
|
||||
closeOnClick: true,
|
||||
});
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
const UpdateShiftPlan = async (body, id) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const data = await Chapar.put(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/shift/plan`,
|
||||
body,
|
||||
|
||||
{
|
||||
headers: {
|
||||
Authorization: getToken(),
|
||||
},
|
||||
}
|
||||
);
|
||||
toast.success(`شیفت ویرایش شد`, {
|
||||
position: "bottom-right",
|
||||
closeOnClick: true,
|
||||
});
|
||||
|
||||
setLoading(false);
|
||||
setShiftPlanData(id);
|
||||
router.push("/shifts");
|
||||
} catch ({ error, status }) {
|
||||
toast.error(`${error?.response?.data?.message}`, {
|
||||
position: "bottom-right",
|
||||
closeOnClick: true,
|
||||
});
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
const CreateShifPlan = async (body) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
|
@ -967,6 +967,8 @@ export default function RootLayout({ children }) {
|
|||
position: "bottom-right",
|
||||
closeOnClick: true,
|
||||
});
|
||||
|
||||
router.push("/shifts");
|
||||
} catch ({ error, status }) {
|
||||
toast.error(`${error?.response?.data?.message}`, {
|
||||
position: "bottom-right",
|
||||
|
@ -975,7 +977,31 @@ export default function RootLayout({ children }) {
|
|||
setLoading(false);
|
||||
}
|
||||
};
|
||||
const GetShifPlans = async (page) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const data = await Chapar.get(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/shift/plan?page=${page}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: getToken(),
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
console.log(data);
|
||||
|
||||
setShifPlansData(data);
|
||||
|
||||
setLoading(false);
|
||||
} catch ({ error, status }) {
|
||||
toast.error(`${error?.response?.data?.message}`, {
|
||||
position: "bottom-right",
|
||||
closeOnClick: true,
|
||||
});
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
const DeleteRoutine = async (id) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
|
@ -1000,7 +1026,6 @@ export default function RootLayout({ children }) {
|
|||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const CreatePosition = async (body) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
|
@ -1125,7 +1150,6 @@ export default function RootLayout({ children }) {
|
|||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const CreateTask = async (body) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
|
@ -1427,6 +1451,76 @@ export default function RootLayout({ children }) {
|
|||
}
|
||||
};
|
||||
|
||||
const ReportShiftPlan = async (shiftPlanId) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/report/shift/plan/${shiftPlanId}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: getToken(),
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to download report");
|
||||
}
|
||||
|
||||
const blob = await response.blob();
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = "report.xlsx"; // Change the filename if needed
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
toast.error(error.message, {
|
||||
position: "bottom-right",
|
||||
closeOnClick: true,
|
||||
});
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const ReportTask = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/report/task`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: getToken(),
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to download report");
|
||||
}
|
||||
|
||||
const blob = await response.blob();
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = "report.xlsx"; // Change the filename if needed
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
toast.error(error.message, {
|
||||
position: "bottom-right",
|
||||
closeOnClick: true,
|
||||
});
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
console.log(`
|
||||
bbbbbbbb
|
||||
|
@ -1526,6 +1620,9 @@ export default function RootLayout({ children }) {
|
|||
pageGetTasks,
|
||||
stopGetActivities,
|
||||
pageGetActivity,
|
||||
shiftPlansData,
|
||||
BottomSheetReportOpen,
|
||||
reportDetail,
|
||||
},
|
||||
setBottomSheetCreateRoleOpen,
|
||||
setBottomSheetCreateEmployeesOpen,
|
||||
|
@ -1641,6 +1738,12 @@ export default function RootLayout({ children }) {
|
|||
setPageGetTasks,
|
||||
setStopGetActivities,
|
||||
setPageGetActivity,
|
||||
setShifPlansData,
|
||||
GetShifPlans,
|
||||
setBottomSheetReportOpen,
|
||||
setReportDetail,
|
||||
ReportShiftPlan,
|
||||
ReportTask,
|
||||
}}
|
||||
>
|
||||
<html lang="en">
|
||||
|
@ -1649,6 +1752,7 @@ export default function RootLayout({ children }) {
|
|||
{shouldRenderComponent && <NavBAr />}
|
||||
<ToastContainer position="bottom-right" closeOnClick={true} rtl />
|
||||
<Loading />
|
||||
<BottomSheetReport />
|
||||
|
||||
{openTimePicker && <TimePicker />}
|
||||
{BigPlusOpen ? (
|
||||
|
|
|
@ -134,6 +134,15 @@ const CompleteShift = () => {
|
|||
// ;
|
||||
};
|
||||
|
||||
const handleGoToReport = (title, shiftId) => {
|
||||
CTX.setReportDetail({
|
||||
title: title,
|
||||
shiftId: shiftId,
|
||||
typeReport: "SHIFTPLAN",
|
||||
});
|
||||
CTX.setBottomSheetReportOpen(true);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
handleDayCloseShift(1);
|
||||
}, []);
|
||||
|
@ -173,7 +182,7 @@ const CompleteShift = () => {
|
|||
/>
|
||||
|
||||
<div className="bg-body-100 relative top-[-30px] rounded-t-3xl overflow-hidden p-4 rtl">
|
||||
<div className="flex overflow-auto whitespace-nowrap">
|
||||
<div className="flex overflow-auto whitespace-nowrap mb-7">
|
||||
<div
|
||||
className={`mx-1 rtl py-1 px-2 rounded-full font-bold inline-block tr03 ${
|
||||
selectDayForShift == 0
|
||||
|
@ -216,46 +225,62 @@ const CompleteShift = () => {
|
|||
className={`bg-gray-200 p-2 rounded-full flex justify-between ${
|
||||
activeShifPlan == index ? "bg-gray-300 " : "bg-gray-200 "
|
||||
} `}
|
||||
onClick={() =>
|
||||
handleOpenShift(
|
||||
e?.isCompleted,
|
||||
e?.id,
|
||||
index,
|
||||
e?.hasCurrentShiftPlan
|
||||
)
|
||||
}
|
||||
>
|
||||
<p className="mb-0">{e?.title} </p>
|
||||
|
||||
<div className="flex">
|
||||
<div className="bg-gray-400 rounded-full mr-1">
|
||||
<p className="mb-0 text-sm p-1 text-white ">
|
||||
{" "}
|
||||
<PersianNumber
|
||||
number={e?.totalActivitiesCount}
|
||||
style="mx-1 text-base"
|
||||
/>
|
||||
فعالیت
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{e?.undoneActivitiesCount != 0 && (
|
||||
<div className="bg-red-700 w-[30px] h-[30px] rounded-full mr-1">
|
||||
<p className="mb-0 text-sm p-1 text-white text-center mt-[2px]">
|
||||
<div
|
||||
className="flex w-full justify-between"
|
||||
onClick={() =>
|
||||
handleOpenShift(
|
||||
e?.isCompleted,
|
||||
e?.id,
|
||||
index,
|
||||
e?.hasCurrentShiftPlan
|
||||
)
|
||||
}
|
||||
>
|
||||
<p className="mb-0">{e?.title} </p>
|
||||
<div className="flex">
|
||||
<div
|
||||
className={`bg-gray-400 rounded-full mr-1 ${
|
||||
e?.isCompleted
|
||||
? "w-[30px] h-[30px] text-center pt-[2px]"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
<p className="mb-0 text-sm p-1 text-white ">
|
||||
{" "}
|
||||
<PersianNumber
|
||||
number={e?.undoneActivitiesCount}
|
||||
number={e?.totalActivitiesCount}
|
||||
style="mx-1 text-base"
|
||||
/>
|
||||
{!e?.isCompleted && "فعالیت"}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{e?.undoneActivitiesCount != 0 && (
|
||||
<div className="bg-red-700 w-[30px] h-[30px] rounded-full mr-1">
|
||||
<p className="mb-0 text-sm p-1 text-white text-center mt-[2px]">
|
||||
{" "}
|
||||
<PersianNumber
|
||||
number={e?.undoneActivitiesCount}
|
||||
style="mx-1 text-base"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={` ${e?.isCompleted ? "w-[170px]" : ""}`}>
|
||||
{e?.isCompleted && (
|
||||
<div className="bg-yellow-500 w-fit px-2 h-[30px] rounded-full mr-1">
|
||||
<div
|
||||
className="bg-sky-600 w-fit px-2 h-[30px] rounded-full mr-1 !z-50 relative"
|
||||
onClick={() =>
|
||||
handleGoToReport(e.title, e.currentShiftPlanId)
|
||||
}
|
||||
>
|
||||
<p className="mb-0 text-sm p-1 text-white text-center mt-[2px]">
|
||||
{" "}
|
||||
بسته شده
|
||||
گزارش شیفت{" "}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
@ -33,6 +33,8 @@ const Calendar = () => {
|
|||
const [shiftsPlan, setShiftsPlan] = useState([]);
|
||||
const [manageShiftEmployeesData, setManageShiftEmployeesData] = useState([]);
|
||||
const [editManageShift, setEditManageShift] = useState(false);
|
||||
const [superId, setSuperId] = useState(null);
|
||||
const [superData, setSuperData] = useState(false);
|
||||
|
||||
const [shiftPlanSteps, setShiftPlanSteps] = useState(0);
|
||||
|
||||
|
@ -110,6 +112,7 @@ const Calendar = () => {
|
|||
1000,
|
||||
shiftId: shiftsPlan && shiftsPlan[selectShift]?.id,
|
||||
routineId: routinesData && routinesData[selectRoutine]?.id,
|
||||
supervisionUserId: superId,
|
||||
userAndPositionIds,
|
||||
};
|
||||
|
||||
|
@ -121,6 +124,7 @@ const Calendar = () => {
|
|||
shiftId: shiftsPlan && shiftsPlan[selectShift]?.id,
|
||||
routineId: routinesData && routinesData[selectRoutine]?.id,
|
||||
userAndPositionIds,
|
||||
supervisionUserId: superId,
|
||||
id: currentShiftPlanId,
|
||||
};
|
||||
|
||||
|
@ -143,10 +147,8 @@ const Calendar = () => {
|
|||
const handleCreateShiftPlan = (update) => {
|
||||
if (update == "UPDATE") {
|
||||
CTX.UpdateShiftPlan(bodyUpdate);
|
||||
setShiftPlanSteps(1);
|
||||
} else {
|
||||
CTX.CreateShifPlan(body);
|
||||
setShiftPlanSteps(1);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -195,8 +197,25 @@ const Calendar = () => {
|
|||
setUserAndPositionIds(
|
||||
shiftPlanData?.users?.map((e) => ({ key: e.positionId, value: e.userId }))
|
||||
);
|
||||
|
||||
setSuperId(shiftPlanData?.supervisorId);
|
||||
}, [shiftPlanData]);
|
||||
|
||||
useEffect(() => {
|
||||
const userJustSuper = usersData?.filter((obj) =>
|
||||
obj.roleNames.includes("سوپروایزر")
|
||||
);
|
||||
|
||||
setSuperData(
|
||||
userJustSuper?.map((item) => ({
|
||||
key: item.firstName + " " + item.lastName,
|
||||
value: item.userId,
|
||||
}))
|
||||
);
|
||||
}, [usersData]);
|
||||
|
||||
console.log(superData, usersData);
|
||||
|
||||
return (
|
||||
<div className="pb-20">
|
||||
<AppHeader
|
||||
|
@ -215,8 +234,8 @@ const Calendar = () => {
|
|||
}}
|
||||
/>
|
||||
|
||||
<div className="bg-body-100 relative top-[-30px] rounded-t-3xl overflow-hidden p-4 rtl">
|
||||
<div className="font-bold text-right">
|
||||
<div className="bg-body-100 relative top-[-30px] rounded-t-3xl overflow-hidden px-4 rtl ">
|
||||
<div className="font-medium text-right mt-5">
|
||||
<p className="mb-0">روتین را انتخاب کنید</p>
|
||||
</div>
|
||||
<div
|
||||
|
@ -246,14 +265,16 @@ const Calendar = () => {
|
|||
}
|
||||
}}
|
||||
>
|
||||
<p className="mb-0">{e.name}</p>
|
||||
<p className="mb-0 text-sm">{e.name}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{shiftPlanSteps >= 1 && (
|
||||
{shiftPlanSteps >= 0 && (
|
||||
<div className="bg-body-100 relative top-[-40px] rounded-t-3xl overflow-hidden px-4 rtl ">
|
||||
<>
|
||||
<div className="font-bold text-right mt-3">
|
||||
<div className="font-medium text-right mt-3 pb-2">
|
||||
<p className="mb-0">تاریخ را انتخاب کنید</p>
|
||||
</div>
|
||||
<Swiper
|
||||
|
@ -271,7 +292,16 @@ const Calendar = () => {
|
|||
: " opacity-70"
|
||||
}`}
|
||||
key={index}
|
||||
onClick={() => handleRoutineShiftPlanWithDay(index)}
|
||||
onClick={() => {
|
||||
if (shiftPlanSteps >= 1) {
|
||||
handleRoutineShiftPlanWithDay(index);
|
||||
} else {
|
||||
toast.error(`ابتدا روتین را انتخاب کنید`, {
|
||||
position: "bottom-right",
|
||||
closeOnClick: true,
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="py-2">
|
||||
<p className="mb-0 text-center ">
|
||||
|
@ -309,14 +339,13 @@ const Calendar = () => {
|
|||
))}
|
||||
</Swiper>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{shiftPlanSteps >= 2 && (
|
||||
</div>
|
||||
)}
|
||||
{shiftPlanSteps >= 0 && (
|
||||
<>
|
||||
<div className="bg-body-100 relative top-[-40px] rounded-t-3xl overflow-hidden px-4 rtl">
|
||||
<>
|
||||
<div className="font-bold text-right mt-3">
|
||||
<div className="font-medium text-right mt-3">
|
||||
<p className="mb-0">شیفت را انتخاب کنید</p>
|
||||
</div>
|
||||
{!!routineShiftPlan?.find(
|
||||
|
@ -338,7 +367,7 @@ const Calendar = () => {
|
|||
setShiftPlanSteps(3);
|
||||
}}
|
||||
>
|
||||
<p className="mb-0">{e?.title}</p>
|
||||
<p className="mb-0 text-sm">{e?.title}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
@ -357,8 +386,8 @@ const Calendar = () => {
|
|||
)}
|
||||
|
||||
{shiftPlanSteps >= 3 && (
|
||||
<div className="bg-white relative top-[15px] rounded-t-3xl p-4 rtl pt-6 sm:h-auto pb-20">
|
||||
<div className="mx-3 flex justify-center mb-10">
|
||||
<div className="bg-white relative top-[15px] rounded-t-3xl p-4 rtl pt-3 sm:h-auto pb-20">
|
||||
<div className="mx-3 flex justify-center mb-5">
|
||||
<div className=" bg-gray-100 rounded-xl w-fit mr-0 p-3">
|
||||
<p className="mb-0 text-right text-sm rtl opacity-80">
|
||||
ویرایش برای{" "}
|
||||
|
@ -376,6 +405,9 @@ const Calendar = () => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className=" text-right mt-3 mb-5">
|
||||
<p className="mb-0 font-medium m">پرسنل را انتخاب کنید</p>
|
||||
</div>
|
||||
{positionsData.map((e) => (
|
||||
<div className="">
|
||||
<div className="flex justify-between bg-gray-200 rounded-2xl">
|
||||
|
@ -397,84 +429,104 @@ const Calendar = () => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* <div className=" m-1">
|
||||
<Input
|
||||
lable="جستجوی افراد"
|
||||
id="SearchUser-id"
|
||||
name="SearchUser"
|
||||
type={"text"}
|
||||
value={searchUserCurrntData}
|
||||
inputEvent={(e) => {
|
||||
setSearchUserCurrntData(e.target.value);
|
||||
|
||||
if (!!searchUserChoose.find((b) => b == e.target.value)) {
|
||||
toast.error("نقش تکراری است", {
|
||||
position: "bottom-right",
|
||||
closeOnClick: true,
|
||||
});
|
||||
} else {
|
||||
CTX.setSearchUserChoose((current) => [
|
||||
...current,
|
||||
e.target.value,
|
||||
]);
|
||||
}
|
||||
}}
|
||||
style="text-right"
|
||||
select={true}
|
||||
selectData={manageShiftEmployeesData}
|
||||
theme={1}
|
||||
defaultValue={"انتخاب کنید"}
|
||||
/>
|
||||
</div> */}
|
||||
|
||||
<div
|
||||
className={`flex j flex-wrap mt-2 rtl ${
|
||||
userAndPositionIds?.length > 0 ? "" : "justify-center"
|
||||
}`}
|
||||
>
|
||||
{userAndPositionIds?.length > 0 ? (
|
||||
userAndPositionIds?.map((item) => (
|
||||
<>
|
||||
{e.id == item.key && (
|
||||
<div className="flex bg-gray-100 p-1 rounded-full m-1 justify-start mb-7 ">
|
||||
<div
|
||||
className="w-[30px] h-[30px] rounded-full bg-gray-400 "
|
||||
// onClick={() => deleteSearchUser(e)}
|
||||
>
|
||||
<Avatar
|
||||
size={30}
|
||||
name={
|
||||
usersData.find((b) => b?.userId == item?.value)
|
||||
?.firstName
|
||||
}
|
||||
variant="beam"
|
||||
colors={["#9d9f88", "#83af96", "#b2de93"]}
|
||||
/>
|
||||
</div>
|
||||
{userAndPositionIds?.length > 0
|
||||
? userAndPositionIds?.map((item) => (
|
||||
<>
|
||||
{e.id == item.key && (
|
||||
<div className="flex bg-gray-100 p-1 rounded-full m-1 justify-start mb-7 ">
|
||||
<div
|
||||
className="w-[30px] h-[30px] rounded-full bg-gray-400 "
|
||||
// onClick={() => deleteSearchUser(e)}
|
||||
>
|
||||
<Avatar
|
||||
size={30}
|
||||
name={
|
||||
usersData.find(
|
||||
(b) => b?.userId == item?.value
|
||||
)?.firstName
|
||||
}
|
||||
variant="beam"
|
||||
colors={["#9d9f88", "#83af96", "#b2de93"]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="mb-0 px-3 text-sm mt-1">
|
||||
{
|
||||
usersData.find((b) => b.userId == item?.value)
|
||||
?.firstName
|
||||
}
|
||||
</p>
|
||||
<div>
|
||||
<p className="mb-0 px-3 text-sm mt-1">
|
||||
{
|
||||
usersData.find((b) => b.userId == item?.value)
|
||||
?.firstName
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
))
|
||||
) : (
|
||||
<div className="flex justify-center mb-3 ">
|
||||
<div className="bg-gray-100 w-fit rounded-full p-2 px-4">
|
||||
چیزی یافت نشد
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
</>
|
||||
))
|
||||
: ""}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<div>
|
||||
|
||||
<div className="mt-8">
|
||||
<div className=" text-right mt-3">
|
||||
<p className="mb-0 font-medium">
|
||||
سوپروایزر را انتخاب کنید
|
||||
<small className="text-red-500 mx-1">(ضروری)</small>
|
||||
</p>
|
||||
<p className="mb-0 text-right text-[12px] text-primary-300">
|
||||
شیفت توسط سوپروایزر بسته میشود لطفا برای هر شیفت آن را مشخص کنید
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="">
|
||||
<Input
|
||||
lable="سوپروایزر"
|
||||
id="superId-id"
|
||||
name="superId"
|
||||
type={"text"}
|
||||
value={superId}
|
||||
inputEvent={(e) => {
|
||||
setSuperId(e.target.value);
|
||||
console.log(e.target.value);
|
||||
}}
|
||||
style="text-right"
|
||||
select={true}
|
||||
selectData={superData}
|
||||
defaultValue={"انتخاب کنید"}
|
||||
theme={1}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-8">
|
||||
<p className="mb-0 font-medium ">غیر فعال کردن شیفت </p>
|
||||
<div
|
||||
className={`flex rtl tr03 border-[2px] border-transparent py-2 ${
|
||||
1 ? "animate-pulse-1 " : ""
|
||||
}`}
|
||||
>
|
||||
<div>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={1 ? true : false}
|
||||
defaultValue={true}
|
||||
className="w-[40px] h-[40px] !rounded-xl ml-2 custom-checkbox mt-1"
|
||||
name="hasSchengenRelative"
|
||||
// onClick={(e) => setRoleCheckBox(e.target.checked)}
|
||||
/>
|
||||
</div>
|
||||
<p className="mb-0 text-right mt-1 text-[12px] text-red-600 font-medium">
|
||||
با خاموش کردن شیفت فعالیت ها برای افراد داخل شیفت خاموش میشود{" "}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-5">
|
||||
{editManageShift ? (
|
||||
<Buttonbriz
|
||||
title="ویرایش فعالیت"
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
import AppHeader from "@comp/AppHeader/page";
|
||||
import AppContext from "@ctx/AppContext";
|
||||
import moment from "jalali-moment";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
import PersianNumber from "plugins/PersianNumber";
|
||||
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
|
||||
|
@ -12,6 +14,55 @@ const Shifts = (props) => {
|
|||
const CTX = useContext(AppContext);
|
||||
const router = useRouter();
|
||||
|
||||
const [shiftplans, setShiftplans] = useState([]);
|
||||
const [shiftPlansSelect, setShiftPlansSelect] = useState(0);
|
||||
|
||||
const shiftplansData = CTX.state.shiftPlansData;
|
||||
|
||||
const groupObjectsByPlanFor = (responseData) => {
|
||||
const groupedData = {};
|
||||
|
||||
// Iterate through the array
|
||||
responseData.forEach((obj) => {
|
||||
const { planFor } = obj;
|
||||
|
||||
// If the planFor value is not in the groupedData object, create a new array
|
||||
if (!groupedData[planFor]) {
|
||||
groupedData[planFor] = [obj];
|
||||
} else {
|
||||
// If the planFor value already exists, push the object into the existing array
|
||||
groupedData[planFor].push(obj);
|
||||
}
|
||||
});
|
||||
|
||||
// Sort the objects within each group by the planFor date
|
||||
Object.keys(groupedData).forEach((key) => {
|
||||
groupedData[key].sort(
|
||||
(a, b) => new Date(a.planFor) - new Date(b.planFor)
|
||||
);
|
||||
});
|
||||
|
||||
// Convert the groupedData object into an array of objects
|
||||
const groupedArray = Object.keys(groupedData).map((key) => ({
|
||||
planFor: key,
|
||||
data: groupedData[key],
|
||||
}));
|
||||
|
||||
// Sort the groupedArray by the planFor date
|
||||
groupedArray.sort((a, b) => new Date(a.planFor) - new Date(b.planFor));
|
||||
|
||||
console.log(groupedArray);
|
||||
setShiftplans(groupedArray);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
CTX.GetShifPlans(0);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
groupObjectsByPlanFor(shiftplansData);
|
||||
}, [shiftplansData]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="pb-20">
|
||||
|
@ -62,7 +113,62 @@ const Shifts = (props) => {
|
|||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="bg-body-100 relative top-[-30px] rounded-t-3xl overflow-hidden p-4 rtl mt-2"></div>
|
||||
<div className="bg-body-100 relative top-[-30px] rounded-t-3xl overflow-hidden p-4 rtl mt-2">
|
||||
{shiftplans?.map((e, index) => (
|
||||
<>
|
||||
<div
|
||||
className={` bg-gray-200 rounded-xl p-5 my-3 tr03 ${
|
||||
shiftPlansSelect == index ? "h-fit " : "h-[65px]"
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={`flex justify-between ${
|
||||
shiftPlansSelect == index
|
||||
? "border-b border-gray-300 pb-3"
|
||||
: ""
|
||||
}`}
|
||||
onClick={() => setShiftPlansSelect(index)}
|
||||
>
|
||||
<div className="">
|
||||
<PersianNumber
|
||||
number={moment(e.planFor).format("jYYYY/jM/jD")}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="bg-gray-500 fit rounded-xl p-1 px-2 h-fit">
|
||||
<p className="mb-0 text-sm text-white">
|
||||
<PersianNumber number={e.data.length} style={"ml-1"} />
|
||||
شیفت
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{shiftPlansSelect == index && (
|
||||
<div className="flex">
|
||||
{e.data.map((e) => (
|
||||
<div className="ml-2 bg-white rounded-xl mt-3 p-2">
|
||||
<p className="text-sm mb-0 text-gray-700 font-medium">
|
||||
{" "}
|
||||
{e.shiftTitle}
|
||||
</p>
|
||||
|
||||
<div className="flex justify-center">
|
||||
<p className="mb-0 text-[12px] text-center w-fit bg-primary-100 px-1 rounded-xl mt-2 ">
|
||||
<PersianNumber
|
||||
number={e.totalActivitiesCount}
|
||||
style={"ml-1 !text-[12px]"}
|
||||
/>
|
||||
فعالیت
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -44,6 +44,7 @@ const page = () => {
|
|||
CTX.setPageGetTasks((e) => e + 1);
|
||||
CTX.GetTasks(pageGetTasks + 1);
|
||||
};
|
||||
|
||||
const handleInfiniteNextFetchActivity = () => {
|
||||
CTX.setPageGetActivity((e) => e + 1);
|
||||
CTX.GetActivity(
|
||||
|
@ -53,6 +54,15 @@ const page = () => {
|
|||
);
|
||||
};
|
||||
|
||||
const handleGoToReport = () => {
|
||||
CTX.setReportDetail({
|
||||
title: "فعالیت های مجموعه",
|
||||
shiftId: "",
|
||||
typeReport: "TASK",
|
||||
});
|
||||
CTX.setBottomSheetReportOpen(true);
|
||||
};
|
||||
|
||||
console.log(activities.length);
|
||||
|
||||
return (
|
||||
|
@ -75,7 +85,20 @@ const page = () => {
|
|||
GoBack();
|
||||
}}
|
||||
/>
|
||||
<div className="bg-primary-300 flex whitespace-nowrap rtl p-3">
|
||||
<div
|
||||
className=" bg-white rounded-3xl p-5 inline-block w-fit relative top-[-32px] mx-2"
|
||||
onClick={() => handleGoToReport()}
|
||||
>
|
||||
<div>
|
||||
<h2> خروجی گرفتن از فعالیت ها </h2>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<div className="w-10 h-5 rounded-full bg-secondary-200 opacity-30"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-body-100 relative top-[-30px] rounded-t-3xl overflow-hidden p-5 rtl ">
|
||||
{!!HasPermission("ManageTasks", permissions) && (
|
||||
<div className="flex mb-6 ">
|
||||
|
|
Loading…
Reference in New Issue