main
حسین معصومی پور 2024-02-22 12:13:03 +03:30
parent 6f137b548e
commit 96835cf13f
9 changed files with 553 additions and 185 deletions

6
.env
View File

@ -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

View File

@ -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}

View File

@ -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;

View File

@ -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}

View File

@ -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 ? (

View File

@ -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>
)}

View File

@ -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="ویرایش فعالیت"

View File

@ -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>
</>
);

View File

@ -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 ">