main
حسین معصومی پور 2024-05-06 14:08:12 +03:30
parent 564ab216c7
commit 644f19eebe
10 changed files with 234 additions and 36 deletions

8
.env
View File

@ -1,9 +1,9 @@
NODE_ENV="development" NODE_ENV="development"
NEXT_PUBLIC_SERVER_URL=http://192.168.1.12:32768 NEXT_PUBLIC_SERVER_URL=http://192.168.1.12:32767
NEXT_PUBLIC_PUBLIC_URL=http://192.168.1.12:32768 NEXT_PUBLIC_PUBLIC_URL=http://192.168.1.12:32767
NEXT_PUBLIC_API_URL=http://192.168.1.12:32768/api NEXT_PUBLIC_API_URL=http://192.168.1.12:32767/api
NEXT_PUBLIC_VERSION=0.2.7 NEXT_PUBLIC_VERSION=0.3.0
# SECURE_LOCAL_STORAGE_HASH_KEY=f1da2b2c7a4c446934267fea631102ec389b5b99 # SECURE_LOCAL_STORAGE_HASH_KEY=f1da2b2c7a4c446934267fea631102ec389b5b99
# NEXT_PUBLIC_API_URL_IMAGE=https://192.168.88.12:49154/Files/ReportImages # NEXT_PUBLIC_API_URL_IMAGE=https://192.168.88.12:49154/Files/ReportImages

View File

@ -1,8 +1,10 @@
"use client"; "use client";
import AppContext from "@ctx/AppContext"; import AppContext from "@ctx/AppContext";
import Avatar from "boring-avatars"; import Avatar from "boring-avatars";
import moment from "jalali-moment";
import Buttonbriz from "plugins/Buttonbriz/page"; import Buttonbriz from "plugins/Buttonbriz/page";
import Input from "plugins/Input/page"; import Input from "plugins/Input/page";
import PersianNumber from "plugins/PersianNumber";
import React, { useContext, useRef, useState } from "react"; import React, { useContext, useRef, useState } from "react";
import SimpleReactValidator from "simple-react-validator"; import SimpleReactValidator from "simple-react-validator";
@ -113,6 +115,18 @@ const ActivityCardCloseShift = ({ data }) => {
{data?.shiftTitle} {data?.shiftTitle}
</div> </div>
</div> </div>
<div className=" w-fit relative text-[11px] rounded-full bg-gray-300 text-black px-2 h-fit">
{data?.userFullName}
</div>
{data?.doneAt !== "0001-01-01T00:00:00" && (
<div className=" w-fit relative text-[11px] rounded-full bg-primary-100 text-primary-300 px-2 h-fit mr-1 mt-[-1px]">
<PersianNumber
number={moment(data?.doneAt).locale("fa").format("HH:mm")}
style={"!text-[11px]"}
/>{" "}
</div>
)}
</div> </div>
</div> </div>
@ -276,7 +290,7 @@ const ActivityCardCloseShift = ({ data }) => {
> >
<div className=""> <div className="">
<Input <Input
lable="چرا انجام نشد ؟؟؟ " // lable="چرا انجام نشد ؟؟؟ "
id="undoneResone-id" id="undoneResone-id"
name="undoneResone" name="undoneResone"
type={"text"} type={"text"}

View File

@ -21,6 +21,8 @@ const TasksCard = ({ tasksData, permissions }) => {
} }
}; };
console.log("tasksData", tasksData.days);
return ( return (
<div className="mt-3"> <div className="mt-3">
{tasksData?.map((e, index) => ( {tasksData?.map((e, index) => (
@ -30,7 +32,7 @@ const TasksCard = ({ tasksData, permissions }) => {
goToEditTask(e.id); goToEditTask(e.id);
}} }}
> >
<div className="flex"> <div className="flex whitespace-nowrap overflow-auto">
{/* <div className=" w-fit relative px-2 text-[12px] my-2 mx-1 rounded-3xl text-primary-300 bg-red-200 px-2"> {/* <div className=" w-fit relative px-2 text-[12px] my-2 mx-1 rounded-3xl text-primary-300 bg-red-200 px-2">
<PersianNumber number={index + 1} /> <PersianNumber number={index + 1} />
</div> */} </div> */}
@ -53,6 +55,17 @@ const TasksCard = ({ tasksData, permissions }) => {
</div> </div>
</div> </div>
{e?.days?.length > 0 && (
<>
{e?.days.map((s) => (
<div className=" w-fit relative px-2 text-[12px] mr-1 rounded-full bg-primary-100 text-green-700 text-center ">
{" "}
{s}
</div>
))}
</>
)}
<div className=" w-fit relative px-2 text-[12px] mr-1 rounded-full bg-gray-300 text-gray-600 text-center "> <div className=" w-fit relative px-2 text-[12px] mr-1 rounded-full bg-gray-300 text-gray-600 text-center ">
{" "} {" "}
{e?.positions[0]} {e?.positions[0]}

View File

@ -31,10 +31,10 @@ Chapar.interceptors.response.use(
// Do something with response error // Do something with response error
// ; // ;
// if (error.response.status === 401) { if (error.response.status === 401) {
// localStorage.removeItem("token"); localStorage.removeItem("token");
// window.location.href = "/login"; window.location.href = "/login";
// } }
return Promise.reject({ error, status: error?.response?.status }); return Promise.reject({ error, status: error?.response?.status });
} }

View File

@ -92,6 +92,8 @@ const Home = (props) => {
const today = new Date(); const today = new Date();
const formattedDate = formatJalaliDate(today); const formattedDate = formatJalaliDate(today);
console.log(homePageData?.todayStaffNames?.slice(0, 4));
return ( return (
<div className="pb-20"> <div className="pb-20">
<AppHeader <AppHeader
@ -109,18 +111,40 @@ const Home = (props) => {
/> />
<div className="bg-body-100 relative top-[-30px] rounded-t-3xl overflow-hidden p-5 rtl"> <div className="bg-body-100 relative top-[-30px] rounded-t-3xl overflow-hidden p-5 rtl">
<div className="p-3 text-right flex">
<div className="relative mt-1 ml-1 ">
<div className="blink_me w-3 h-3 rounded-full bg-green-600 "></div>
</div>
<div>
<h3 className=" text-sm font-bold">
<PersianNumber number={formattedDate} />
</h3>
<p className="mb-0 text-sm text-gray-600">
{homePageData?.currentShift}-{homePageData?.currentPosition}
</p>
</div>
</div>
{homePageData?.totalStaffToday > 0 && ( {homePageData?.totalStaffToday > 0 && (
<div> <div>
<div className="bg-white p-5 rounded-full shadow"> <div className="bg-white pt-4 pb-5 px-5 rounded-full shadow">
<div className="flex justify-between"> <div className="flex justify-between">
<div className="flex mt-[-3px]"> <div className="flex mt-[-3px]">
{homePageData?.todayStaffNames {homePageData?.todayStaffNames
?.slice(0, 4) ?.slice(0, 4)
.map((e, index) => ( .map((e, index) => (
<div <div
className={`w-[50px] h-[50px] rounded-full bg-white border-[5px] absolute mr-[${ className={`w-[50px] h-[50px] rounded-full bg-white border-[5px] absolute ${
index * 30 index == 0
}px]`} ? "avatarHomePage-0"
: index === 1
? "avatarHomePage-1"
: index === 2
? "avatarHomePage-2"
: index === 3
? "avatarHomePage-3"
: "avatarHomePage-0"
}`}
> >
<div className=" rounded-full z-10 "> <div className=" rounded-full z-10 ">
<Avatar <Avatar
@ -147,10 +171,8 @@ const Home = (props) => {
</div> </div>
</div> </div>
)} )}
<div className="mt-5"> <div className="mt-5">
<h3 className="text-right p-3 text-sm font-bold">
<PersianNumber number={formattedDate} />
</h3>
<div className="grid xs:grid-cols-2 gap-4 rtl"> <div className="grid xs:grid-cols-2 gap-4 rtl">
<div> <div>
<div className="bg-dahs-chart rounded-2xl p-2 h-[195px]"> <div className="bg-dahs-chart rounded-2xl p-2 h-[195px]">

View File

@ -984,11 +984,11 @@ export default function RootLayout({ children }) {
setLoading(false); setLoading(false);
} }
}; };
const GetShifPlans = async (page) => { const GetShifPlans = async (page, dataFilter) => {
setLoading(true); setLoading(true);
try { try {
const data = await Chapar.get( const data = await Chapar.get(
`${process.env.NEXT_PUBLIC_API_URL}/shift/plan?page=${page}`, `${process.env.NEXT_PUBLIC_API_URL}/shift/plan?page=${page}&dateFilter=${dataFilter}`,
{ {
headers: { headers: {
Authorization: "Bearer " + localStorage.getItem("token"), Authorization: "Bearer " + localStorage.getItem("token"),
@ -1312,7 +1312,7 @@ export default function RootLayout({ children }) {
} }
); );
if (data.length < 14) { if (data.length < 19) {
setStopGetActivities(true); setStopGetActivities(true);
} }
@ -1584,9 +1584,9 @@ export default function RootLayout({ children }) {
`); `);
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
if (!token) { // if (!token) {
router.push("/login"); // router.push("/login");
} // }
if (profile.length <= 0 && token) CheckUser(); if (profile.length <= 0 && token) CheckUser();
}, []); }, []);

View File

@ -21,6 +21,7 @@ const CompleteShift = () => {
const [closeShiftScore, setCloseShiftScore] = useState(50); const [closeShiftScore, setCloseShiftScore] = useState(50);
const [activeShifPlan, setActiveShifPlan] = useState(-1); const [activeShifPlan, setActiveShifPlan] = useState(-1);
const [selectDayForShift, setSelectDayForShift] = useState(-1); const [selectDayForShift, setSelectDayForShift] = useState(-1);
const currentDate = new Date(); const currentDate = new Date();
const siftsData = CTX.state.shiftsData; const siftsData = CTX.state.shiftsData;
@ -70,6 +71,8 @@ const CompleteShift = () => {
}; };
const handleOpenShift = (isCompleted, id, index, hasCurrentShiftPlan) => { const handleOpenShift = (isCompleted, id, index, hasCurrentShiftPlan) => {
CTX.setStopGetActivities(false);
CTX.setPageGetActivity(0);
if (isCompleted) { if (isCompleted) {
toast.warning(`شیفت بسته شده است `, { toast.warning(`شیفت بسته شده است `, {
position: "bottom-right", position: "bottom-right",
@ -132,6 +135,7 @@ const CompleteShift = () => {
CTX.CloseShift(body, siftsData[activeShifPlan]?.currentShiftPlanId); CTX.CloseShift(body, siftsData[activeShifPlan]?.currentShiftPlanId);
setActiveShifPlan(-1); setActiveShifPlan(-1);
handleDayCloseShift(1); handleDayCloseShift(1);
CTX.GetShifts(moment().locale("fa").startOf("day").unix() * 1000);
}, },
[siftsData[activeShifPlan]?.currentShiftPlanId], [siftsData[activeShifPlan]?.currentShiftPlanId],
body body
@ -170,13 +174,34 @@ const CompleteShift = () => {
const handleInfiniteNextFetchActivity = () => { const handleInfiniteNextFetchActivity = () => {
CTX.setPageGetActivity((e) => e + 1); CTX.setPageGetActivity((e) => e + 1);
CTX.GetActivity(
moment().locale("fa").startOf("day").unix() * 1000, if (selectDayForShift == 0) {
null, CTX.GetActivity(
pageGetActivity + 1 moment().locale("fa").subtract(1, "day")?.unix() * 1000,
); siftsData[activeShifPlan].id,
pageGetActivity + 1
);
} else if (selectDayForShift == 1) {
CTX.GetActivity(
moment().locale("fa").startOf("day").unix() * 1000,
siftsData[activeShifPlan].id,
pageGetActivity + 1
);
} else if (selectDayForShift == 2) {
CTX.GetActivity(
moment().locale("fa").add(1, "day").unix() * 1000,
siftsData[activeShifPlan].id,
pageGetActivity + 1
);
}
}; };
console.log(siftsData[activeShifPlan]);
console.log(
"getYesterdayPersianDate",
moment().locale("fa").subtract(1, "day")?.unix() * 1000
);
return ( return (
<div className="pb-20"> <div className="pb-20">
<AppHeader <AppHeader
@ -298,7 +323,7 @@ const CompleteShift = () => {
{activeShifPlan == index && ( {activeShifPlan == index && (
<> <>
<InfiniteScroll <InfiniteScroll
dataLength={activitiesData.length} dataLength={siftsData[activeShifPlan]?.totalActivitiesCount}
next={handleInfiniteNextFetchActivity} next={handleInfiniteNextFetchActivity}
hasMore={!stopGetActivities} hasMore={!stopGetActivities}
> >

View File

@ -18,9 +18,15 @@ const Shifts = (props) => {
const [shiftplans, setShiftplans] = useState([]); const [shiftplans, setShiftplans] = useState([]);
const [shiftPlansSelect, setShiftPlansSelect] = useState(0); const [shiftPlansSelect, setShiftPlansSelect] = useState(0);
const [shifilterShifPlaneSelect, setFilterShifPlaneSelect] = useState(0);
const shiftplansData = CTX.state.shiftPlansData; const shiftplansData = CTX.state.shiftPlansData;
const handleFilterGetShifPlane = (num, index) => {
setFilterShifPlaneSelect(index);
CTX.GetShifPlans(0, num);
};
const groupObjectsByPlanFor = (responseData) => { const groupObjectsByPlanFor = (responseData) => {
const groupedData = {}; const groupedData = {};
@ -87,7 +93,8 @@ const Shifts = (props) => {
} }
useEffect(() => { useEffect(() => {
CTX.GetShifPlans(0); CTX.GetShifPlans(0, 12);
setFilterShifPlaneSelect(1);
}, []); }, []);
useEffect(() => { useEffect(() => {
@ -128,7 +135,7 @@ const Shifts = (props) => {
{HasPermission("ManageShiftPlans", permissions) && ( {HasPermission("ManageShiftPlans", permissions) && (
<> <>
<Link href={"/shifts/manage-shift"}> <Link href={"/shifts/manage-shift"}>
<div className="bg-[#e29d494b] p-4 rounded-2xl mb-5 "> <div className="bg-[#e29d494b] p-4 rounded-2xl ">
<p className="mb-0 text-center text-[#66451d] text-sm font-medium"> <p className="mb-0 text-center text-[#66451d] text-sm font-medium">
شیفت بندی هفته{" "} شیفت بندی هفته{" "}
</p> </p>
@ -136,6 +143,100 @@ const Shifts = (props) => {
</Link> </Link>
</> </>
)} )}
<div
className="flex justify-start whitespace-nowrap overflow-auto pb-4"
id="swich-shifts"
>
<div
className={`border-2 px-2 py-1 w-fit rounded-full flex mt-2 tr03 mr-1 ${
shifilterShifPlaneSelect == 1
? " bg-primary-100"
: "opacity-50 border-gray-300"
}`}
onClick={() => handleFilterGetShifPlane(12, 1)}
>
<div className="mr-1">
<p className="mb-0 text-[12px] text-primary-300 font-medium">
شیفت های هفته{" "}
</p>
</div>
</div>
<div
className={`border-2 px-2 py-1 w-fit rounded-full flex mt-2 tr03 mr-1 ${
shifilterShifPlaneSelect == 6
? " bg-primary-100"
: "opacity-50 border-gray-300"
}`}
onClick={() => handleFilterGetShifPlane(22, 6)}
>
<div className="mr-1">
<p className="mb-0 text-[12px] text-primary-300 font-medium">
شیفت های ماه{" "}
</p>
</div>
</div>
<div
className={`border-2 px-2 py-1 w-fit rounded-full flex mt-2 tr03 mr-1 ${
shifilterShifPlaneSelect == 2
? " bg-primary-100"
: "opacity-50 border-gray-300"
}`}
onClick={() => handleFilterGetShifPlane(11, 2)}
>
<div className="mr-1">
<p className="mb-0 text-[12px] text-primary-300 font-medium">
شیفت های هفته بعد{" "}
</p>
</div>
</div>
<div
className={`border-2 px-2 py-1 w-fit rounded-full flex mt-2 tr03 mr-1 ${
shifilterShifPlaneSelect == 3
? " bg-primary-100"
: "opacity-50 border-gray-300"
}`}
onClick={() => handleFilterGetShifPlane(10, 3)}
>
<div className="mr-1">
<p className="mb-0 text-[12px] text-primary-300 font-medium">
شیفت های هفته قبل{" "}
</p>
</div>
</div>
<div
className={`border-2 px-2 py-1 w-fit rounded-full flex mt-2 tr03 mr-1 ${
shifilterShifPlaneSelect == 4
? " bg-primary-100"
: "opacity-50 border-gray-300"
}`}
onClick={() => handleFilterGetShifPlane(20, 4)}
>
<div className="mr-1">
<p className="mb-0 text-[12px] text-primary-300 font-medium">
شیفت های ماه قبل{" "}
</p>
</div>
</div>
<div
className={`border-2 px-2 py-1 w-fit rounded-full flex mt-2 tr03 mr-1 ${
shifilterShifPlaneSelect == 5
? " bg-primary-100"
: "opacity-50 border-gray-300"
}`}
onClick={() => handleFilterGetShifPlane(21, 5)}
>
<div className="mr-1">
<p className="mb-0 text-[12px] text-primary-300 font-medium">
شیفت های ماه بعد{" "}
</p>
</div>
</div>
</div>
{shiftplans.length <= 0 ? ( {shiftplans.length <= 0 ? (
<div className="flex justify-center py-5"> <div className="flex justify-center py-5">
<div className="bg-white shadow mt-5 w-fit rounded-full text-sm p-4"> <div className="bg-white shadow mt-5 w-fit rounded-full text-sm p-4">

View File

@ -112,11 +112,11 @@ const page = () => {
</div> </div>
)} )}
<div <div className="flex justify-start">
className="flex justify-start" <div
onClick={() => CTX.setBottomFilterActivitiesOpen(true)} className="border-2 border-gray-300 px-2 py-1 w-fit rounded-full flex mt-2"
> onClick={() => CTX.setBottomFilterActivitiesOpen(true)}
<div className="border-2 border-gray-300 px-2 py-1 w-fit rounded-full flex mt-2"> >
<div> <div>
<svg <svg
width="15" width="15"

View File

@ -470,3 +470,26 @@ body {
#c95040 #c95040
); );
} }
.avatarHomePage-0 {
margin-right: 0;
}
.avatarHomePage-1 {
margin-right: 20px;
}
.avatarHomePage-2 {
margin-right: 40px;
}
.avatarHomePage-3 {
margin-right: 60px;
}
.blink_me {
animation: blinker 3s linear infinite;
}
@keyframes blinker {
50% {
opacity: 0;
}
}