Compare commits
66 Commits
9b74be078f
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| 4138ea652a | |||
| 313364a304 | |||
| 472d0e66cc | |||
| 5572ed070e | |||
| 11bb774b9c | |||
| 88ec9ed3b6 | |||
| ff6089bfb0 | |||
| 25c8171f87 | |||
| 9ab4977b50 | |||
| defa1e3e08 | |||
| e6ff022335 | |||
| 043ad77b83 | |||
| 0743d6c86f | |||
| 2829f68831 | |||
| d7d4848f2a | |||
| b8ae9757d4 | |||
| e7f4c55bfe | |||
| 1f763a33ac | |||
| 32246fd0cc | |||
| 78c7bb22e3 | |||
| a3c9163787 | |||
| 741385e282 | |||
| 9d87907f81 | |||
| 561ecafe0f | |||
| 26c13018e7 | |||
| b3892b6a8a | |||
| 44037758ed | |||
| c55e1f907a | |||
| b3dde3c0ec | |||
| 4245dce136 | |||
| d9aed4d215 | |||
| 4a5bdd7f89 | |||
| 21dcc7dca8 | |||
| e507d08835 | |||
| 225b2d874d | |||
| c7b3eb80ec | |||
| 33233cf9e0 | |||
| abe53b885a | |||
| c0b8472c72 | |||
| f473c729fe | |||
| e8a75fcc74 | |||
| ec087e59bc | |||
| 468ad9079e | |||
| 28f7d5c991 | |||
| 763d5b79d3 | |||
| f8e8e7f1f1 | |||
| 63aed5572c | |||
| 59ae3b76d9 | |||
| 93867ce7ee | |||
| 4210dbd7e2 | |||
| 3624b3bc70 | |||
| 4d00b0d492 | |||
| ed7b257ed8 | |||
| 03136f5f30 | |||
| 908a69ce0e | |||
| a818683247 | |||
| 95780cfbc9 | |||
| 071c3e159b | |||
| 90f51c6899 | |||
| e967329108 | |||
| f8d2da4f28 | |||
| bb1d5b3315 | |||
| d8d415a8f5 | |||
| f58c8e6c58 | |||
| 3a17fcb448 | |||
| 6e219aca1a |
@@ -32,7 +32,7 @@ export default function Dashboard() {
|
|||||||
useDashboardTabStore();
|
useDashboardTabStore();
|
||||||
|
|
||||||
const menuItems: ItemWithSubItems[] = getUserPermissions(
|
const menuItems: ItemWithSubItems[] = getUserPermissions(
|
||||||
profile?.permissions
|
profile?.permissions,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [tabs, setTabs] = useState<Tab[]>(dashboarTabs || []);
|
const [tabs, setTabs] = useState<Tab[]>(dashboarTabs || []);
|
||||||
@@ -55,7 +55,7 @@ export default function Dashboard() {
|
|||||||
hour: "2-digit",
|
hour: "2-digit",
|
||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
hour12: false,
|
hour12: false,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -65,7 +65,7 @@ export default function Dashboard() {
|
|||||||
hour: "2-digit",
|
hour: "2-digit",
|
||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
hour12: false,
|
hour12: false,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}, 60000);
|
}, 60000);
|
||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
@@ -96,7 +96,7 @@ export default function Dashboard() {
|
|||||||
|
|
||||||
if (activeTabId === id) {
|
if (activeTabId === id) {
|
||||||
setActiveTabId(
|
setActiveTabId(
|
||||||
newTabs.length > 0 ? newTabs[newTabs.length - 1].id : null
|
newTabs.length > 0 ? newTabs[newTabs.length - 1].id : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -113,14 +113,49 @@ export default function Dashboard() {
|
|||||||
(subItem) =>
|
(subItem) =>
|
||||||
!subItem.path.includes("$") &&
|
!subItem.path.includes("$") &&
|
||||||
(search.trim() === "" ||
|
(search.trim() === "" ||
|
||||||
getFaPermissions(subItem.name).includes(search.trim()))
|
getFaPermissions(subItem.name).includes(search.trim())),
|
||||||
),
|
),
|
||||||
}))
|
}))
|
||||||
.filter((item) => item.subItems.length > 0);
|
.filter((item) => item.subItems.length > 0);
|
||||||
|
|
||||||
|
const adminFilteredItems = filteredMenuItems.filter(
|
||||||
|
(item) => item.en === "admin",
|
||||||
|
);
|
||||||
|
const nonAdminFilteredItems = filteredMenuItems.filter(
|
||||||
|
(item) => item.en !== "admin",
|
||||||
|
);
|
||||||
|
|
||||||
|
const permissionDomainMap = new Map<string, string>();
|
||||||
|
(profile?.permissions || []).forEach((permission: any) => {
|
||||||
|
if (permission?.page_name) {
|
||||||
|
permissionDomainMap.set(
|
||||||
|
permission.page_name,
|
||||||
|
permission?.domain_fa_name || "سایر حوزه ها",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupedFilteredItems = nonAdminFilteredItems.reduce(
|
||||||
|
(acc, item) => {
|
||||||
|
const firstSubItem = item.subItems?.find((sub) =>
|
||||||
|
permissionDomainMap.has(sub.name),
|
||||||
|
);
|
||||||
|
const domainTitle = firstSubItem
|
||||||
|
? permissionDomainMap.get(firstSubItem.name) || "سایر حوزه ها"
|
||||||
|
: "سایر حوزه ها";
|
||||||
|
if (!acc[domainTitle]) {
|
||||||
|
acc[domainTitle] = [];
|
||||||
|
}
|
||||||
|
acc[domainTitle].push(item);
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{} as Record<string, ItemWithSubItems[]>,
|
||||||
|
);
|
||||||
|
const showDomainGrouping = Object.keys(groupedFilteredItems).length > 1;
|
||||||
|
|
||||||
function findSubItemByPath(
|
function findSubItemByPath(
|
||||||
items: ItemWithSubItems[],
|
items: ItemWithSubItems[],
|
||||||
path: string
|
path: string,
|
||||||
): ItemWithSubItems["subItems"][0] | null {
|
): ItemWithSubItems["subItems"][0] | null {
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
for (const subItem of item.subItems) {
|
for (const subItem of item.subItems) {
|
||||||
@@ -243,18 +278,11 @@ export default function Dashboard() {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{checkIsMobile()
|
{checkIsMobile()
|
||||||
? filteredMenuItems.map(({ fa, icon: Icon, subItems }, index) => {
|
? (
|
||||||
const filteredSubItems = subItems.filter(
|
<>
|
||||||
(item) =>
|
{adminFilteredItems.map(({ fa, icon: Icon, subItems }, index) => (
|
||||||
!item.path.includes("$") &&
|
|
||||||
getFaPermissions(item.name).includes(search.trim())
|
|
||||||
);
|
|
||||||
|
|
||||||
if (filteredSubItems.length === 0) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<section
|
<section
|
||||||
key={index}
|
key={`admin-mobile-${index}`}
|
||||||
className="w-full space-y-5 border border-gray-200 dark:border-dark-600 bg-white dark:bg-dark-800 rounded-2xl p-6 shadow-sm"
|
className="w-full space-y-5 border border-gray-200 dark:border-dark-600 bg-white dark:bg-dark-800 rounded-2xl p-6 shadow-sm"
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
@@ -263,9 +291,8 @@ export default function Dashboard() {
|
|||||||
{fa}
|
{fa}
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 xl:grid-cols-5 gap-4">
|
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 xl:grid-cols-5 gap-4">
|
||||||
{filteredSubItems.map((sub, subIndex) => (
|
{subItems.map((sub, subIndex) => (
|
||||||
<motion.button
|
<motion.button
|
||||||
key={subIndex}
|
key={subIndex}
|
||||||
onClick={() => navigate({ to: sub.path })}
|
onClick={() => navigate({ to: sub.path })}
|
||||||
@@ -281,11 +308,88 @@ export default function Dashboard() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
))}
|
||||||
})
|
{showDomainGrouping
|
||||||
: filteredMenuItems.map(({ fa, icon: Icon, subItems }, index) => (
|
? Object.entries(groupedFilteredItems).map(
|
||||||
|
([domainTitle, domainItems], domainIndex) => (
|
||||||
|
<section
|
||||||
|
key={`domain-mobile-${domainTitle}-${domainIndex}`}
|
||||||
|
className="w-full space-y-3 border border-gray-200 dark:border-dark-600 bg-white dark:bg-dark-800 rounded-2xl p-4 shadow-sm"
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-2 pb-2 border-b border-gray-200 dark:border-dark-600">
|
||||||
|
<Squares2X2Icon className="w-4 h-4 text-primary-500" />
|
||||||
|
<h2 className="text-sm font-bold text-primary-700 dark:text-primary-300">
|
||||||
|
{domainTitle}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
{domainItems.map(({ fa, icon: Icon, subItems }, index) => (
|
||||||
|
<section
|
||||||
|
key={`domain-item-mobile-${domainTitle}-${index}`}
|
||||||
|
className="w-full space-y-3 border border-gray-200 dark:border-dark-600 bg-gray-50 dark:bg-dark-700 rounded-xl p-4"
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Icon className="w-5 h-5 text-primary-600 dark:text-primary-400" />
|
||||||
|
<h3 className="text-base font-bold text-dark-900 dark:text-white">
|
||||||
|
{fa}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-2 sm:grid-cols-3 gap-3">
|
||||||
|
{subItems.map((sub, subIndex) => (
|
||||||
|
<motion.button
|
||||||
|
key={subIndex}
|
||||||
|
onClick={() => navigate({ to: sub.path })}
|
||||||
|
whileHover={{ scale: 1.03 }}
|
||||||
|
whileTap={{ scale: 0.97 }}
|
||||||
|
className="flex items-center gap-2 cursor-pointer bg-white dark:bg-dark-800 text-right border border-gray-200 dark:border-dark-600 hover:border-primary-500 dark:hover:border-primary-400 shadow-sm rounded-xl p-3 transition-all duration-200"
|
||||||
|
>
|
||||||
|
<ArrowRightCircleIcon className="w-5 h-5 text-primary-500 dark:text-primary-400" />
|
||||||
|
<span className="text-sm font-medium text-dark-800 dark:text-white">
|
||||||
|
{getFaPermissions(sub.name)}
|
||||||
|
</span>
|
||||||
|
</motion.button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
))}
|
||||||
|
</section>
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: nonAdminFilteredItems.map(({ fa, icon: Icon, subItems }, index) => (
|
||||||
|
<section
|
||||||
|
key={`plain-mobile-${index}`}
|
||||||
|
className="w-full space-y-5 border border-gray-200 dark:border-dark-600 bg-white dark:bg-dark-800 rounded-2xl p-6 shadow-sm"
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<Icon className="w-6 h-6 text-primary-600 dark:text-primary-400" />
|
||||||
|
<h2 className="text-xl font-bold text-dark-900 dark:text-white">
|
||||||
|
{fa}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 xl:grid-cols-5 gap-4">
|
||||||
|
{subItems.map((sub, subIndex) => (
|
||||||
|
<motion.button
|
||||||
|
key={subIndex}
|
||||||
|
onClick={() => navigate({ to: sub.path })}
|
||||||
|
whileHover={{ scale: 1.03 }}
|
||||||
|
whileTap={{ scale: 0.97 }}
|
||||||
|
className="flex items-center gap-2 cursor-pointer bg-gray-50 dark:bg-dark-700 text-right border border-gray-200 dark:border-dark-600 hover:border-primary-500 dark:hover:border-primary-400 shadow-sm rounded-xl p-3 transition-all duration-200"
|
||||||
|
>
|
||||||
|
<ArrowRightCircleIcon className="w-5 h-5 text-primary-500 dark:text-primary-400" />
|
||||||
|
<span className="text-sm font-medium text-dark-800 dark:text-white">
|
||||||
|
{getFaPermissions(sub.name)}
|
||||||
|
</span>
|
||||||
|
</motion.button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<>
|
||||||
|
{adminFilteredItems.map(({ fa, icon: Icon, subItems }, index) => (
|
||||||
<motion.div
|
<motion.div
|
||||||
key={index}
|
key={`admin-desktop-${index}`}
|
||||||
initial={{ opacity: 0, x: -10 }}
|
initial={{ opacity: 0, x: -10 }}
|
||||||
animate={{ opacity: 1, x: 0 }}
|
animate={{ opacity: 1, x: 0 }}
|
||||||
transition={{ delay: index * 0.05 }}
|
transition={{ delay: index * 0.05 }}
|
||||||
@@ -301,12 +405,86 @@ export default function Dashboard() {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="p-1.5 space-y-0.5">
|
||||||
|
{subItems.map((sub, subIndex) => {
|
||||||
|
const isActive = tabs.some(
|
||||||
|
(tab) => tab.path === sub.path && activeTabId === tab.id,
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<motion.div
|
||||||
|
key={subIndex}
|
||||||
|
initial={{ opacity: 0, x: -5 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ delay: index * 0.05 + subIndex * 0.02 }}
|
||||||
|
whileHover={{ x: 1 }}
|
||||||
|
whileTap={{ scale: 0.98 }}
|
||||||
|
onClick={() => openTab(sub)}
|
||||||
|
className={`flex items-center gap-1.5 px-2 py-1.5 text-xs rounded-md cursor-pointer transition-all duration-200 focus:outline-none ${
|
||||||
|
isActive
|
||||||
|
? "backdrop-blur-sm bg-primary-500/20 dark:bg-primary-400/20 text-primary-700 dark:text-primary-300 "
|
||||||
|
: "hover:backdrop-blur-sm hover:bg-white/30 dark:hover:bg-dark-600/30 border-none"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={`w-1.5 h-1.5 rounded-full ${
|
||||||
|
isActive
|
||||||
|
? "bg-primary-600 dark:bg-primary-400"
|
||||||
|
: "bg-dark-400 dark:bg-dark-500"
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
className={`truncate ${
|
||||||
|
isActive
|
||||||
|
? "text-primary-700 dark:text-white font-medium"
|
||||||
|
: "text-dark-600 dark:text-dark-200/80"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{getFaPermissions(sub.name)}
|
||||||
|
</span>
|
||||||
|
</motion.div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
{showDomainGrouping
|
||||||
|
? Object.entries(groupedFilteredItems).map(
|
||||||
|
([domainTitle, domainItems], domainIndex) => (
|
||||||
|
<div
|
||||||
|
key={`domain-desktop-${domainTitle}-${domainIndex}`}
|
||||||
|
className="flex-none w-56 space-y-2"
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-2 px-1">
|
||||||
|
<Squares2X2Icon className="w-4 h-4 text-primary-500" />
|
||||||
|
<span className="text-xs font-bold text-primary-700 dark:text-primary-300">
|
||||||
|
{domainTitle}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
{domainItems.map(({ fa, icon: Icon, subItems }, index) => (
|
||||||
|
<motion.div
|
||||||
|
key={`domain-item-desktop-${domainTitle}-${index}`}
|
||||||
|
initial={{ opacity: 0, x: -10 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ delay: index * 0.05 }}
|
||||||
|
className="w-full backdrop-blur-xl bg-white/20 dark:bg-dark-800/80 rounded-xl shadow-lg border border-white/30 dark:border-dark-700/30 overflow-hidden"
|
||||||
|
>
|
||||||
|
<div className="backdrop-blur-sm bg-white/30 dark:bg-dark-700/30 px-3 py-2 border-b border-white/20 dark:border-dark-600/20">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="p-1.5 rounded-md backdrop-blur-sm bg-primary-500/20 dark:bg-primary-400/20">
|
||||||
|
<Icon className="w-3.5 h-3.5 text-primary-600 dark:text-primary-400" />
|
||||||
|
</div>
|
||||||
|
<span className="text-xs font-semibold text-dark-800 dark:text-dark-100 truncate">
|
||||||
|
{fa}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="p-1.5 space-y-0.5">
|
<div className="p-1.5 space-y-0.5">
|
||||||
{subItems.map((sub, subIndex) => {
|
{subItems.map((sub, subIndex) => {
|
||||||
const isActive = tabs.some(
|
const isActive = tabs.some(
|
||||||
(tab) =>
|
(tab) =>
|
||||||
tab.path === sub.path && activeTabId === tab.id
|
tab.path === sub.path &&
|
||||||
|
activeTabId === tab.id,
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
@@ -348,6 +526,75 @@ export default function Dashboard() {
|
|||||||
</motion.div>
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: nonAdminFilteredItems.map(({ fa, icon: Icon, subItems }, index) => (
|
||||||
|
<motion.div
|
||||||
|
key={`plain-desktop-${index}`}
|
||||||
|
initial={{ opacity: 0, x: -10 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ delay: index * 0.05 }}
|
||||||
|
className="flex-none w-48 backdrop-blur-xl bg-white/20 dark:bg-dark-800/80 rounded-xl shadow-lg border border-white/30 dark:border-dark-700/30 overflow-hidden"
|
||||||
|
>
|
||||||
|
<div className="backdrop-blur-sm bg-white/30 dark:bg-dark-700/30 px-3 py-2 border-b border-white/20 dark:border-dark-600/20">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="p-1.5 rounded-md backdrop-blur-sm bg-primary-500/20 dark:bg-primary-400/20">
|
||||||
|
<Icon className="w-3.5 h-3.5 text-primary-600 dark:text-primary-400" />
|
||||||
|
</div>
|
||||||
|
<span className="text-xs font-semibold text-dark-800 dark:text-dark-100 truncate">
|
||||||
|
{fa}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="p-1.5 space-y-0.5">
|
||||||
|
{subItems.map((sub, subIndex) => {
|
||||||
|
const isActive = tabs.some(
|
||||||
|
(tab) =>
|
||||||
|
tab.path === sub.path && activeTabId === tab.id,
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<motion.div
|
||||||
|
key={subIndex}
|
||||||
|
initial={{ opacity: 0, x: -5 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{
|
||||||
|
delay: index * 0.05 + subIndex * 0.02,
|
||||||
|
}}
|
||||||
|
whileHover={{ x: 1 }}
|
||||||
|
whileTap={{ scale: 0.98 }}
|
||||||
|
onClick={() => openTab(sub)}
|
||||||
|
className={`flex items-center gap-1.5 px-2 py-1.5 text-xs rounded-md cursor-pointer transition-all duration-200 focus:outline-none ${
|
||||||
|
isActive
|
||||||
|
? "backdrop-blur-sm bg-primary-500/20 dark:bg-primary-400/20 text-primary-700 dark:text-primary-300 "
|
||||||
|
: "hover:backdrop-blur-sm hover:bg-white/30 dark:hover:bg-dark-600/30 border-none"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={`w-1.5 h-1.5 rounded-full ${
|
||||||
|
isActive
|
||||||
|
? "bg-primary-600 dark:bg-primary-400"
|
||||||
|
: "bg-dark-400 dark:bg-dark-500"
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
className={`truncate ${
|
||||||
|
isActive
|
||||||
|
? "text-primary-700 dark:text-white font-medium"
|
||||||
|
: "text-dark-600 dark:text-dark-200/80"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{getFaPermissions(sub.name)}
|
||||||
|
</span>
|
||||||
|
</motion.div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
84
src/Pages/Domains.tsx
Normal file
84
src/Pages/Domains.tsx
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useApiRequest } from "../utils/useApiRequest";
|
||||||
|
import { useModalStore } from "../context/zustand-store/appStore";
|
||||||
|
import Table from "../components/Table/Table";
|
||||||
|
import { Grid } from "../components/Grid/Grid";
|
||||||
|
import Button from "../components/Button/Button";
|
||||||
|
import { AddDomain } from "../partials/Admin/AddDomain";
|
||||||
|
import { Popover } from "../components/PopOver/PopOver";
|
||||||
|
import { Tooltip } from "../components/Tooltip/Tooltip";
|
||||||
|
import { DeleteButtonForPopOver } from "../components/PopOverButtons/PopOverButtons";
|
||||||
|
|
||||||
|
export default function Domains() {
|
||||||
|
const { openModal } = useModalStore();
|
||||||
|
const [domainsInfo, setDomainsInfo] = useState({ page: 1, page_size: 10 });
|
||||||
|
const [domainsTableData, setDomainsTableData] = useState([]);
|
||||||
|
|
||||||
|
const { data: domainsData, refetch } = useApiRequest({
|
||||||
|
api: "/core/domain/",
|
||||||
|
method: "get",
|
||||||
|
params: domainsInfo,
|
||||||
|
queryKey: ["domains", domainsInfo],
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (domainsData?.results) {
|
||||||
|
const formattedData = domainsData.results.map((item: any, i: number) => {
|
||||||
|
return [
|
||||||
|
domainsInfo.page === 1
|
||||||
|
? i + 1
|
||||||
|
: i + domainsInfo.page_size * (domainsInfo.page - 1) + 1,
|
||||||
|
item?.fa_name,
|
||||||
|
item?.code,
|
||||||
|
item?.name,
|
||||||
|
<Popover key={i}>
|
||||||
|
<Tooltip title="ویرایش" position="right">
|
||||||
|
<Button
|
||||||
|
variant="edit"
|
||||||
|
onClick={() => {
|
||||||
|
openModal({
|
||||||
|
title: "ویرایش حوزه",
|
||||||
|
content: <AddDomain item={item} getData={refetch} />,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<DeleteButtonForPopOver
|
||||||
|
api={`core/domain/${item?.id}/`}
|
||||||
|
getData={refetch}
|
||||||
|
/>
|
||||||
|
</Popover>,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
setDomainsTableData(formattedData);
|
||||||
|
}
|
||||||
|
}, [domainsData, domainsInfo]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid container column>
|
||||||
|
<Grid container className="items-center gap-2">
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
variant="submit"
|
||||||
|
onClick={() => {
|
||||||
|
openModal({
|
||||||
|
title: "ایجاد حوزه",
|
||||||
|
content: <AddDomain getData={refetch} />,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
ایجاد حوزه
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
<Table
|
||||||
|
className="mt-2"
|
||||||
|
onChange={setDomainsInfo}
|
||||||
|
count={domainsData?.count || 10}
|
||||||
|
isPaginated
|
||||||
|
title="حوزه ها"
|
||||||
|
columns={["ردیف", "نام حوزه", "کد حوزه", "نام انگلیسی", "عملیات"]}
|
||||||
|
rows={domainsTableData}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApiRequest } from "../utils/useApiRequest";
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Table from "../components/Table/Table";
|
import Table from "../../components/Table/Table";
|
||||||
import { useNavigate, useParams } from "@tanstack/react-router";
|
import { useNavigate, useParams } from "@tanstack/react-router";
|
||||||
import { Popover } from "../components/PopOver/PopOver";
|
import { Popover } from "../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
||||||
import Button from "../components/Button/Button";
|
import Button from "../../components/Button/Button";
|
||||||
import { useModalStore } from "../context/zustand-store/appStore";
|
import { useModalStore } from "../../context/zustand-store/appStore";
|
||||||
import { LIVESTOCK_FARMERS } from "../routes/paths";
|
import { LIVESTOCK_FARMERS } from "../../routes/paths";
|
||||||
import { TableButton } from "../components/TableButton/TableButton";
|
import { TableButton } from "../../components/TableButton/TableButton";
|
||||||
import { CooperativesDashboardDetails } from "../partials/cooperatives/CooperativesDashboardDetails";
|
import { CooperativesDashboardDetails } from "../../partials/LiveStock/cooperatives/CooperativesDashboardDetails";
|
||||||
import { DeleteButtonForPopOver } from "../components/PopOverButtons/PopOverButtons";
|
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
||||||
|
|
||||||
export default function CooperativeRanchers() {
|
export default function CooperativeRanchers() {
|
||||||
const { openModal } = useModalStore();
|
const { openModal } = useModalStore();
|
||||||
@@ -98,7 +98,7 @@ export default function CooperativeRanchers() {
|
|||||||
/>
|
/>
|
||||||
</Popover>,
|
</Popover>,
|
||||||
];
|
];
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
setCooperativesTableData(tableData);
|
setCooperativesTableData(tableData);
|
||||||
}
|
}
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApiRequest } from "../utils/useApiRequest";
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Table from "../components/Table/Table";
|
import Table from "../../components/Table/Table";
|
||||||
import { useNavigate, useParams } from "@tanstack/react-router";
|
import { useNavigate, useParams } from "@tanstack/react-router";
|
||||||
import { Popover } from "../components/PopOver/PopOver";
|
import { Popover } from "../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
||||||
import Button from "../components/Button/Button";
|
import Button from "../../components/Button/Button";
|
||||||
import { useModalStore } from "../context/zustand-store/appStore";
|
import { useModalStore } from "../../context/zustand-store/appStore";
|
||||||
import { ChildOrganizations } from "../partials/cooperatives/ChildOrganizations";
|
import { ChildOrganizations } from "../../partials/LiveStock/cooperatives/ChildOrganizations";
|
||||||
import { COOPERATIVE_LIST } from "../routes/paths";
|
import { COOPERATIVE_LIST } from "../../routes/paths";
|
||||||
import { TableButton } from "../components/TableButton/TableButton";
|
import { TableButton } from "../../components/TableButton/TableButton";
|
||||||
import { CooperativesDashboardDetails } from "../partials/cooperatives/CooperativesDashboardDetails";
|
import { CooperativesDashboardDetails } from "../../partials/LiveStock/cooperatives/CooperativesDashboardDetails";
|
||||||
import { AddActivityType } from "../partials/cooperatives/AddActivityType";
|
import { AddActivityType } from "../../partials/LiveStock/cooperatives/AddActivityType";
|
||||||
import ShowMoreInfo from "../components/ShowMoreInfo/ShowMoreInfo";
|
import ShowMoreInfo from "../../components/ShowMoreInfo/ShowMoreInfo";
|
||||||
import ShowStringList from "../components/ShowStringList/ShowStringList";
|
import ShowStringList from "../../components/ShowStringList/ShowStringList";
|
||||||
|
|
||||||
export default function Cooperatives() {
|
export default function Cooperatives() {
|
||||||
const { openModal } = useModalStore();
|
const { openModal } = useModalStore();
|
||||||
@@ -64,7 +64,7 @@ export default function Cooperatives() {
|
|||||||
<ShowStringList
|
<ShowStringList
|
||||||
showSearch={false}
|
showSearch={false}
|
||||||
strings={item.org_service_area.map(
|
strings={item.org_service_area.map(
|
||||||
(city: any) => city.name
|
(city: any) => city.name,
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
@@ -131,7 +131,7 @@ export default function Cooperatives() {
|
|||||||
/>
|
/>
|
||||||
</Tooltip>,
|
</Tooltip>,
|
||||||
];
|
];
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
setCooperativesTableData(formattedData);
|
setCooperativesTableData(formattedData);
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Table from "../components/Table/Table";
|
import Table from "../../components/Table/Table";
|
||||||
import { useApiRequest } from "../utils/useApiRequest";
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
import { Popover } from "../components/PopOver/PopOver";
|
import { Popover } from "../../components/PopOver/PopOver";
|
||||||
import { DeleteButtonForPopOver } from "../components/PopOverButtons/PopOverButtons";
|
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
||||||
import { Tooltip } from "../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
||||||
import Button from "../components/Button/Button";
|
import Button from "../../components/Button/Button";
|
||||||
import {
|
import {
|
||||||
useDrawerStore,
|
useDrawerStore,
|
||||||
useModalStore,
|
useModalStore,
|
||||||
} from "../context/zustand-store/appStore";
|
} from "../../context/zustand-store/appStore";
|
||||||
import { LiveStockAddHerd } from "../partials/live-stock/LiveStockAddHerd";
|
import { LiveStockAddHerd } from "../../partials/LiveStock/live-stock/LiveStockAddHerd";
|
||||||
import { useNavigate, useParams } from "@tanstack/react-router";
|
import { useNavigate, useParams } from "@tanstack/react-router";
|
||||||
import { LIVESTOCKS } from "../routes/paths";
|
import { LIVESTOCKS } from "../../routes/paths";
|
||||||
import { LiveStockAddLiveStock } from "../partials/live-stock/LiveStockAddLiveStock";
|
import { LiveStockAddLiveStock } from "../../partials/LiveStock/live-stock/LiveStockAddLiveStock";
|
||||||
import { TableButton } from "../components/TableButton/TableButton";
|
import { TableButton } from "../../components/TableButton/TableButton";
|
||||||
import { LiveStockHerdDetails } from "../partials/live-stock/LiveStockHerdDetails";
|
import { LiveStockHerdDetails } from "../../partials/LiveStock/live-stock/LiveStockHerdDetails";
|
||||||
|
|
||||||
export default function LiveStocks() {
|
export default function LiveStocks() {
|
||||||
const [pagesInfo, setPagesInfo] = useState({ page: 1, page_size: 10 });
|
const [pagesInfo, setPagesInfo] = useState({ page: 1, page_size: 10 });
|
||||||
@@ -38,7 +38,7 @@ export default function LiveStocks() {
|
|||||||
? `/herd/web/api/v1/rancher/${farmid}/rancher_dashboard/`
|
? `/herd/web/api/v1/rancher/${farmid}/rancher_dashboard/`
|
||||||
: "/herd/web/api/v1/rancher/rancher_main_dashboard/",
|
: "/herd/web/api/v1/rancher/rancher_main_dashboard/",
|
||||||
queryKey: ["HerdsDashboard"],
|
queryKey: ["HerdsDashboard"],
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleUpdate = () => {
|
const handleUpdate = () => {
|
||||||
@@ -156,6 +156,8 @@ export default function LiveStocks() {
|
|||||||
"تعداد دام سنگین",
|
"تعداد دام سنگین",
|
||||||
"تعداد دام سبک",
|
"تعداد دام سبک",
|
||||||
"مجموع وزن خرید از سهمیه ها",
|
"مجموع وزن خرید از سهمیه ها",
|
||||||
|
"تعداد دام های فعال",
|
||||||
|
"تعداد دام های غیرفعال",
|
||||||
"جزئیات",
|
"جزئیات",
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
@@ -186,6 +188,10 @@ export default function LiveStocks() {
|
|||||||
"0",
|
"0",
|
||||||
DashboardData?.total_purchase_weight?.toLocaleString() ||
|
DashboardData?.total_purchase_weight?.toLocaleString() ||
|
||||||
"0",
|
"0",
|
||||||
|
DashboardData?.total_active_livestock_count?.toLocaleString() ||
|
||||||
|
"0",
|
||||||
|
DashboardData?.total_deactive_livestock_count?.toLocaleString() ||
|
||||||
|
"0",
|
||||||
<TableButton
|
<TableButton
|
||||||
size="small"
|
size="small"
|
||||||
key={DashboardData}
|
key={DashboardData}
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Popover } from "../components/PopOver/PopOver";
|
import { Popover } from "../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
||||||
import Button from "../components/Button/Button";
|
import Button from "../../components/Button/Button";
|
||||||
import { DeleteButtonForPopOver } from "../components/PopOverButtons/PopOverButtons";
|
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
||||||
import { useModalStore } from "../context/zustand-store/appStore";
|
import { useModalStore } from "../../context/zustand-store/appStore";
|
||||||
import { useApiRequest } from "../utils/useApiRequest";
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Table from "../components/Table/Table";
|
import Table from "../../components/Table/Table";
|
||||||
import { formatJustDate } from "../utils/formatTime";
|
import { formatJustDate } from "../../utils/formatTime";
|
||||||
import { AddIncentivePlan } from "../partials/quota/AddIncentivePlan";
|
import { AddIncentivePlan } from "../../partials/LiveStock/quota/AddIncentivePlan";
|
||||||
import AutoComplete from "../components/AutoComplete/AutoComplete";
|
import AutoComplete from "../../components/AutoComplete/AutoComplete";
|
||||||
|
|
||||||
export default function IncentivePlans() {
|
export default function IncentivePlans() {
|
||||||
const { openModal } = useModalStore();
|
const { openModal } = useModalStore();
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Tabs from "../components/Tab/Tab";
|
import Tabs from "../../components/Tab/Tab";
|
||||||
import { useUserProfileStore } from "../context/zustand-store/userStore";
|
import { useUserProfileStore } from "../../context/zustand-store/userStore";
|
||||||
import { InventoryStakeHolderAllocations } from "../partials/inventory/InventoryStakeHolderAllocations";
|
import { InventoryStakeHolderAllocations } from "../../partials/LiveStock/inventory/InventoryStakeHolderAllocations";
|
||||||
import { InventoryWarehouseEntryTab } from "../partials/inventory/InventoryWarehouseEntryTab";
|
import { InventoryWarehouseEntryTab } from "../../partials/LiveStock/inventory/InventoryWarehouseEntryTab";
|
||||||
import { useParams } from "@tanstack/react-router";
|
import { useParams } from "@tanstack/react-router";
|
||||||
import { InventoryEntriesList } from "../partials/inventory/InventoryEntriesList";
|
import { InventoryEntriesList } from "../../partials/LiveStock/inventory/InventoryEntriesList";
|
||||||
|
|
||||||
export default function Inventory() {
|
export default function Inventory() {
|
||||||
const [selectedTab, setSelectedTab] = useState<number>(0);
|
const [selectedTab, setSelectedTab] = useState<number>(0);
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Table from "../components/Table/Table";
|
import Table from "../../components/Table/Table";
|
||||||
import { useApiRequest } from "../utils/useApiRequest";
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
import Button from "../components/Button/Button";
|
import Button from "../../components/Button/Button";
|
||||||
import { LiveStockAddRancher } from "../partials/live-stock/LiveStockAddRancher";
|
import { LiveStockAddRancher } from "../../partials/LiveStock/live-stock/LiveStockAddRancher";
|
||||||
import {
|
import {
|
||||||
useDrawerStore,
|
useDrawerStore,
|
||||||
useModalStore,
|
useModalStore,
|
||||||
} from "../context/zustand-store/appStore";
|
} from "../../context/zustand-store/appStore";
|
||||||
import { Popover } from "../components/PopOver/PopOver";
|
import { Popover } from "../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
||||||
import { DeleteButtonForPopOver } from "../components/PopOverButtons/PopOverButtons";
|
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
||||||
import { LiveStockAddHerd } from "../partials/live-stock/LiveStockAddHerd";
|
import { LiveStockAddHerd } from "../../partials/LiveStock/live-stock/LiveStockAddHerd";
|
||||||
import { LiveStockAllocateCooperative } from "../partials/live-stock/LiveStockAllocateCooperative";
|
import { LiveStockAllocateCooperative } from "../../partials/LiveStock/live-stock/LiveStockAllocateCooperative";
|
||||||
import { useNavigate } from "@tanstack/react-router";
|
import { useNavigate } from "@tanstack/react-router";
|
||||||
import { LIVESTOCK_FARMERS } from "../routes/paths";
|
import { LIVESTOCK_FARMERS } from "../../routes/paths";
|
||||||
import { LiveStockFarmersDashboardResponse } from "../types/LiveStockFarmers";
|
import { LiveStockFarmersDashboardResponse } from "../../types/LiveStockFarmers";
|
||||||
|
|
||||||
export default function LiveStockFarmers() {
|
export default function LiveStockFarmers() {
|
||||||
const [pagesInfo, setPagesInfo] = useState({ page: 1, page_size: 10 });
|
const [pagesInfo, setPagesInfo] = useState({ page: 1, page_size: 10 });
|
||||||
@@ -137,7 +137,7 @@ export default function LiveStockFarmers() {
|
|||||||
"/plans/" +
|
"/plans/" +
|
||||||
item.id +
|
item.id +
|
||||||
"/" +
|
"/" +
|
||||||
item?.ranching_farm;
|
`${item?.first_name.replace(":", " ") || ""} ${item?.last_name || ""} ${item?.ranching_farm ? " (" + item?.ranching_farm + ") " : ""}`;
|
||||||
navigate({ to: path });
|
navigate({ to: path });
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -1,30 +1,47 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Table from "../components/Table/Table";
|
import Table from "../../components/Table/Table";
|
||||||
import { useApiRequest } from "../utils/useApiRequest";
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
import { Popover } from "../components/PopOver/PopOver";
|
import { Popover } from "../../components/PopOver/PopOver";
|
||||||
import { DeleteButtonForPopOver } from "../components/PopOverButtons/PopOverButtons";
|
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
||||||
import { useParams } from "@tanstack/react-router";
|
import { useParams } from "@tanstack/react-router";
|
||||||
import { formatAgeCalcuation, formatJustDate } from "../utils/formatTime";
|
import { formatAgeCalcuation, formatJustDate } from "../../utils/formatTime";
|
||||||
import { Tooltip } from "../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
||||||
import Button from "../components/Button/Button";
|
import Button from "../../components/Button/Button";
|
||||||
import { LiveStockAddLiveStock } from "../partials/live-stock/LiveStockAddLiveStock";
|
import { LiveStockAddLiveStock } from "../../partials/LiveStock/live-stock/LiveStockAddLiveStock";
|
||||||
import { useDrawerStore } from "../context/zustand-store/appStore";
|
import { useDrawerStore } from "../../context/zustand-store/appStore";
|
||||||
|
import { CheckCircleIcon, XCircleIcon } from "@heroicons/react/24/outline";
|
||||||
|
import AutoComplete from "../../components/AutoComplete/AutoComplete";
|
||||||
|
|
||||||
export default function LiveStocks() {
|
export default function LiveStocks() {
|
||||||
const [pagesInfo, setPagesInfo] = useState({ page: 1, page_size: 10 });
|
const [pagesInfo, setPagesInfo] = useState({ page: 1, page_size: 10 });
|
||||||
const [pagesTableData, setPagesTableData] = useState([]);
|
const [pagesTableData, setPagesTableData] = useState([]);
|
||||||
|
const [selectedStatusKeys, setSelectedStatusKeys] = useState<
|
||||||
|
(string | number)[]
|
||||||
|
>([]);
|
||||||
|
|
||||||
const { openDrawer } = useDrawerStore();
|
const { openDrawer } = useDrawerStore();
|
||||||
|
|
||||||
|
const statusItems = [
|
||||||
|
{ key: "", value: "همه" },
|
||||||
|
{ key: "true", value: "فعال" },
|
||||||
|
{ key: "false", value: "غیرفعال" },
|
||||||
|
];
|
||||||
|
|
||||||
const { herdid, name } = useParams({ strict: false });
|
const { herdid, name } = useParams({ strict: false });
|
||||||
|
|
||||||
|
const activeParam =
|
||||||
|
selectedStatusKeys.length && selectedStatusKeys[0] !== ""
|
||||||
|
? { active: selectedStatusKeys[0] }
|
||||||
|
: {};
|
||||||
|
|
||||||
const { data: pagesData, refetch } = useApiRequest({
|
const { data: pagesData, refetch } = useApiRequest({
|
||||||
api: herdid
|
api: herdid
|
||||||
? `herd/web/api/v1/herd/${herdid}/live_stocks/`
|
? `herd/web/api/v1/herd/${herdid}/live_stocks/`
|
||||||
: "/livestock/web/api/v1/livestock/",
|
: "/livestock/web/api/v1/livestock/",
|
||||||
method: "get",
|
method: "get",
|
||||||
params: pagesInfo,
|
params: { ...pagesInfo, ...activeParam },
|
||||||
queryKey: ["LiveStockFarmers", pagesInfo],
|
queryKey: ["LiveStockFarmers", pagesInfo, selectedStatusKeys],
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -42,6 +59,19 @@ export default function LiveStocks() {
|
|||||||
item?.gender === 1 ? "نر" : "ماده",
|
item?.gender === 1 ? "نر" : "ماده",
|
||||||
// item?.species?.name,
|
// item?.species?.name,
|
||||||
item?.weight_type === "L" ? "سبک" : "سنگین",
|
item?.weight_type === "L" ? "سبک" : "سنگین",
|
||||||
|
<span className="flex items-center gap-1">
|
||||||
|
{item?.active ? (
|
||||||
|
<>
|
||||||
|
<span className="text-green-500">فعال</span>
|
||||||
|
<CheckCircleIcon className="w-5 h-5 text-green-500" />
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<span className="text-red-500">غیرفعال</span>
|
||||||
|
<XCircleIcon className="w-5 h-5 text-red-500" />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</span>,
|
||||||
<Popover key={i}>
|
<Popover key={i}>
|
||||||
<Tooltip title="ویرایش دام" position="right">
|
<Tooltip title="ویرایش دام" position="right">
|
||||||
<Button
|
<Button
|
||||||
@@ -77,6 +107,18 @@ export default function LiveStocks() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid container column>
|
<Grid container column>
|
||||||
|
<Grid container className="items-center gap-2">
|
||||||
|
<Grid>
|
||||||
|
<AutoComplete
|
||||||
|
inPage
|
||||||
|
size="small"
|
||||||
|
data={statusItems}
|
||||||
|
selectedKeys={selectedStatusKeys}
|
||||||
|
onChange={setSelectedStatusKeys}
|
||||||
|
title="فیلتر وضعیت"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
<Table
|
<Table
|
||||||
className="mt-2"
|
className="mt-2"
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@@ -95,6 +137,7 @@ export default function LiveStocks() {
|
|||||||
"جنسیت",
|
"جنسیت",
|
||||||
// "گونه",
|
// "گونه",
|
||||||
"دسته وزنی",
|
"دسته وزنی",
|
||||||
|
"وضعیت",
|
||||||
"عملیات",
|
"عملیات",
|
||||||
]}
|
]}
|
||||||
rows={pagesTableData}
|
rows={pagesTableData}
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import Tabs from "../components/Tab/Tab";
|
import Tabs from "../../components/Tab/Tab";
|
||||||
import { OrganizationsList } from "../partials/management/OrganizationsList";
|
import { OrganizationsList } from "../../partials/LiveStock/management/OrganizationsList";
|
||||||
import { OrganizationsTypes } from "../partials/management/OrganizationsTypes";
|
import { OrganizationsTypes } from "../../partials/LiveStock/management/OrganizationsTypes";
|
||||||
|
|
||||||
export default function Organizations() {
|
export default function Organizations() {
|
||||||
const tabItems = [
|
const tabItems = [
|
||||||
{ label: "سازمان ها" },
|
|
||||||
{
|
{
|
||||||
label: "نهاد",
|
label: "نهاد",
|
||||||
page: "organizations",
|
page: "organizations",
|
||||||
access: "Show-Organization-Type",
|
access: "Show-Organization-Type",
|
||||||
},
|
},
|
||||||
|
{ label: "سازمان ها" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const [selectedTab, setSelectedTab] = useState<number>(0);
|
const [selectedTab, setSelectedTab] = useState<number>(0);
|
||||||
@@ -22,7 +22,7 @@ export default function Organizations() {
|
|||||||
return (
|
return (
|
||||||
<Grid container column className="gap-2">
|
<Grid container column className="gap-2">
|
||||||
<Tabs tabs={tabItems} onChange={handleTabChange} size="medium" />
|
<Tabs tabs={tabItems} onChange={handleTabChange} size="medium" />
|
||||||
{selectedTab === 0 ? <OrganizationsList /> : <OrganizationsTypes />}
|
{selectedTab === 0 ? <OrganizationsTypes /> : <OrganizationsList />}
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApiRequest } from "../utils/useApiRequest";
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Table from "../components/Table/Table";
|
import Table from "../../components/Table/Table";
|
||||||
import Button from "../components/Button/Button";
|
import Button from "../../components/Button/Button";
|
||||||
import { useModalStore } from "../context/zustand-store/appStore";
|
import { useModalStore } from "../../context/zustand-store/appStore";
|
||||||
import { AddPos } from "../partials/pos/AddPos";
|
import { AddPos } from "../../partials/LiveStock/pos/AddPos";
|
||||||
import { Popover } from "../components/PopOver/PopOver";
|
import { Popover } from "../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
||||||
import { DeleteButtonForPopOver } from "../components/PopOverButtons/PopOverButtons";
|
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
||||||
import { useUserProfileStore } from "../context/zustand-store/userStore";
|
import { useUserProfileStore } from "../../context/zustand-store/userStore";
|
||||||
import { useNavigate, useParams } from "@tanstack/react-router";
|
import { useNavigate, useParams } from "@tanstack/react-router";
|
||||||
import { AllocatePos } from "../partials/pos/AllocatePos";
|
import { AllocatePos } from "../../partials/LiveStock/pos/AllocatePos";
|
||||||
import { CreditCardIcon } from "@heroicons/react/24/outline";
|
import { CreditCardIcon } from "@heroicons/react/24/outline";
|
||||||
import { POS_POS_LIST } from "../routes/paths";
|
import { POS_POS_LIST } from "../../routes/paths";
|
||||||
|
|
||||||
export default function Pos() {
|
export default function Pos() {
|
||||||
const { openModal } = useModalStore();
|
const { openModal } = useModalStore();
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApiRequest } from "../utils/useApiRequest";
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Table from "../components/Table/Table";
|
import Table from "../../components/Table/Table";
|
||||||
import Button from "../components/Button/Button";
|
import Button from "../../components/Button/Button";
|
||||||
import { useModalStore } from "../context/zustand-store/appStore";
|
import { useModalStore } from "../../context/zustand-store/appStore";
|
||||||
import { AddPos } from "../partials/pos/AddPos";
|
import { AddPos } from "../../partials/LiveStock/pos/AddPos";
|
||||||
import { Popover } from "../components/PopOver/PopOver";
|
import { Popover } from "../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
||||||
import { DeleteButtonForPopOver } from "../components/PopOverButtons/PopOverButtons";
|
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
||||||
import { useParams } from "@tanstack/react-router";
|
import { useParams } from "@tanstack/react-router";
|
||||||
import { AllocatePos } from "../partials/pos/AllocatePos";
|
import { AllocatePos } from "../../partials/LiveStock/pos/AllocatePos";
|
||||||
import { PosAllocateOrganizationAccount } from "../partials/pos/PosAllocateOrganizationAccount";
|
import { PosAllocateOrganizationAccount } from "../../partials/LiveStock/pos/PosAllocateOrganizationAccount";
|
||||||
import { AllocateAccountToBroker } from "../partials/pos/AllocateAccountToBroker";
|
import { AllocateAccountToBroker } from "../../partials/LiveStock/pos/AllocateAccountToBroker";
|
||||||
import { BooleanQuestion } from "../components/BooleanQuestion/BooleanQuestion";
|
import { BooleanQuestion } from "../../components/BooleanQuestion/BooleanQuestion";
|
||||||
|
|
||||||
export default function PosAccounts() {
|
export default function PosAccounts() {
|
||||||
const { openModal } = useModalStore();
|
const { openModal } = useModalStore();
|
||||||
@@ -102,7 +102,7 @@ export default function PosAccounts() {
|
|||||||
/>
|
/>
|
||||||
</Popover>,
|
</Popover>,
|
||||||
];
|
];
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
setAccountsTableData(formattedData);
|
setAccountsTableData(formattedData);
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Table from "../components/Table/Table";
|
import Table from "../../components/Table/Table";
|
||||||
import { useApiRequest } from "../utils/useApiRequest";
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
import { Popover } from "../components/PopOver/PopOver";
|
import { Popover } from "../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
||||||
import Button from "../components/Button/Button";
|
import Button from "../../components/Button/Button";
|
||||||
import { useNavigate } from "@tanstack/react-router";
|
import { useNavigate } from "@tanstack/react-router";
|
||||||
import { POS_COMPANIES } from "../routes/paths";
|
import { POS_COMPANIES } from "../../routes/paths";
|
||||||
|
|
||||||
export default function PosCompanies() {
|
export default function PosCompanies() {
|
||||||
const [pagesInfo, setPagesInfo] = useState({ page: 1, page_size: 10 });
|
const [pagesInfo, setPagesInfo] = useState({ page: 1, page_size: 10 });
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Tabs from "../components/Tab/Tab";
|
import Tabs from "../../components/Tab/Tab";
|
||||||
import { Attributes } from "../partials/feed-input/Attributes";
|
import { Attributes } from "../../partials/LiveStock/feed-input/Attributes";
|
||||||
import { Brokers } from "../partials/feed-input/Brokers";
|
import { Brokers } from "../../partials/LiveStock/feed-input/Brokers";
|
||||||
import { SaleUnits } from "../partials/feed-input/SaleUnits";
|
import { SaleUnits } from "../../partials/LiveStock/feed-input/SaleUnits";
|
||||||
const tabItems = [
|
const tabItems = [
|
||||||
{ label: "مولفه" },
|
{ label: "مولفه" },
|
||||||
{ label: "کارگزار" },
|
{ label: "کارگزار" },
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { useApiRequest } from "../utils/useApiRequest";
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
import sabos from "../assets/images/products/saboos.png";
|
import sabos from "../../assets/images/products/saboos.png";
|
||||||
import jo from "../assets/images/products/jo.png";
|
import jo from "../../assets/images/products/jo.png";
|
||||||
import soya from "../assets/images/products/soya.png";
|
import soya from "../../assets/images/products/soya.png";
|
||||||
import zorat from "../assets/images/products/zorat.png";
|
import zorat from "../../assets/images/products/zorat.png";
|
||||||
import goosfandi from "../assets/images/products/constantre-goosfandi.png";
|
import goosfandi from "../../assets/images/products/constantre-goosfandi.png";
|
||||||
import parvari from "../assets/images/products/constantre-parvari.png";
|
import parvari from "../../assets/images/products/constantre-parvari.png";
|
||||||
import porTolid from "../assets/images/products/constantre-gave-shiri-por-tolid.png";
|
import porTolid from "../../assets/images/products/constantre-gave-shiri-por-tolid.png";
|
||||||
import shiriMotevaset from "../assets/images/products/constantre-gave-shiri-motevaset.png";
|
import shiriMotevaset from "../../assets/images/products/constantre-gave-shiri-motevaset.png";
|
||||||
import defaultImage from "../assets/images/products/default.png";
|
import defaultImage from "../../assets/images/products/default.png";
|
||||||
import Button from "../components/Button/Button";
|
import Button from "../../components/Button/Button";
|
||||||
import { PencilIcon, TrashIcon } from "@heroicons/react/24/outline";
|
import { PencilIcon, TrashIcon } from "@heroicons/react/24/outline";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import { useModalStore } from "../context/zustand-store/appStore";
|
import { useModalStore } from "../../context/zustand-store/appStore";
|
||||||
import { AddProduct } from "../partials/feed-input/AddProduct";
|
import { AddProduct } from "../../partials/LiveStock/feed-input/AddProduct";
|
||||||
import { getAbleToSee } from "../utils/getAbleToSee";
|
import { getAbleToSee } from "../../utils/getAbleToSee";
|
||||||
import { DeleteProduct } from "../partials/feed-input/DeleteProduct";
|
import { DeleteProduct } from "../../partials/LiveStock/feed-input/DeleteProduct";
|
||||||
|
|
||||||
interface Category {
|
interface Category {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -232,7 +232,7 @@ export default function Products() {
|
|||||||
<button
|
<button
|
||||||
className={`${getAbleToSee(
|
className={`${getAbleToSee(
|
||||||
"feed_input_products",
|
"feed_input_products",
|
||||||
"Edit-Product"
|
"Edit-Product",
|
||||||
)} rounded-full text-primary-600 text-sm`}
|
)} rounded-full text-primary-600 text-sm`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
openModal({
|
openModal({
|
||||||
@@ -252,7 +252,7 @@ export default function Products() {
|
|||||||
}}
|
}}
|
||||||
className={`${getAbleToSee(
|
className={`${getAbleToSee(
|
||||||
"feed_input_products",
|
"feed_input_products",
|
||||||
"Delete-Product"
|
"Delete-Product",
|
||||||
)} text-red-400 rounded-lg text-sm`}
|
)} text-red-400 rounded-lg text-sm`}
|
||||||
>
|
>
|
||||||
<TrashIcon className="w-5" />
|
<TrashIcon className="w-5" />
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useModalStore } from "../context/zustand-store/appStore";
|
import { useModalStore } from "../../context/zustand-store/appStore";
|
||||||
import { useApiRequest } from "../utils/useApiRequest";
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
import { Popover } from "../components/PopOver/PopOver";
|
import { Popover } from "../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
||||||
import Button from "../components/Button/Button";
|
import Button from "../../components/Button/Button";
|
||||||
import { DeleteButtonForPopOver } from "../components/PopOverButtons/PopOverButtons";
|
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Table from "../components/Table/Table";
|
import Table from "../../components/Table/Table";
|
||||||
import { AddProductCategory } from "../partials/feed-input/AddProductCategory";
|
import { AddProductCategory } from "../../partials/LiveStock/feed-input/AddProductCategory";
|
||||||
|
|
||||||
export const ProductsCategories = () => {
|
export const ProductsCategories = () => {
|
||||||
const { openModal } = useModalStore();
|
const { openModal } = useModalStore();
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import Tabs from "../components/Tab/Tab";
|
import Tabs from "../../components/Tab/Tab";
|
||||||
import { QuotaActives } from "../partials/quota/QuotaActives";
|
import { QuotaActives } from "../../partials/LiveStock/quota/QuotaActives";
|
||||||
import { QuotaClosed } from "../partials/quota/QuotaClosed";
|
import { QuotaClosed } from "../../partials/LiveStock/quota/QuotaClosed";
|
||||||
import { useParams } from "@tanstack/react-router";
|
import { useParams } from "@tanstack/react-router";
|
||||||
import { QuotaDistributions } from "../partials/quota/QuotaDistributions";
|
import { QuotaDistributions } from "../../partials/LiveStock/quota/QuotaDistributions";
|
||||||
import { QuotaAllDistributions } from "../partials/quota/QuotaAllDistributions";
|
import { QuotaAllDistributions } from "../../partials/LiveStock/quota/QuotaAllDistributions";
|
||||||
|
|
||||||
export default function Quota() {
|
export default function Quota() {
|
||||||
const [selectedTab, setSelectedTab] = useState<number>(0);
|
const [selectedTab, setSelectedTab] = useState<number>(0);
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Popover } from "../components/PopOver/PopOver";
|
import { Popover } from "../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../components/Tooltip/Tooltip";
|
import Button from "../../components/Button/Button";
|
||||||
import Button from "../components/Button/Button";
|
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
||||||
import { DeleteButtonForPopOver } from "../components/PopOverButtons/PopOverButtons";
|
import { useModalStore } from "../../context/zustand-store/appStore";
|
||||||
import { useModalStore } from "../context/zustand-store/appStore";
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
import { useApiRequest } from "../utils/useApiRequest";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import Table from "../../components/Table/Table";
|
||||||
import Table from "../components/Table/Table";
|
import { LiveStockRancherAllocateIncentivePlan } from "../../partials/LiveStock/live-stock/LiveStockRancherAllocateIncentivePlan";
|
||||||
import { AddIncentivePlan } from "../partials/quota/AddIncentivePlan";
|
|
||||||
import { useParams } from "@tanstack/react-router";
|
import { useParams } from "@tanstack/react-router";
|
||||||
|
|
||||||
export default function RancherPlans() {
|
export default function RancherPlans() {
|
||||||
@@ -34,25 +33,11 @@ export default function RancherPlans() {
|
|||||||
item?.livestock_type_name,
|
item?.livestock_type_name,
|
||||||
item?.allowed_quantity?.toLocaleString(),
|
item?.allowed_quantity?.toLocaleString(),
|
||||||
<Popover key={i}>
|
<Popover key={i}>
|
||||||
<Tooltip title="ویرایش طرح" position="right">
|
|
||||||
<Button
|
|
||||||
page="farmer_plans"
|
|
||||||
access="Edit-Rancher-Incentive-Plan"
|
|
||||||
variant="edit"
|
|
||||||
onClick={() => {
|
|
||||||
openModal({
|
|
||||||
title: "ویرایش طرح",
|
|
||||||
content: <AddIncentivePlan getData={refetch} item={item} />,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<DeleteButtonForPopOver
|
<DeleteButtonForPopOver
|
||||||
page="farmer_plans"
|
page="farmer_plans"
|
||||||
access="Delete-Rancher-Incentive-Plan"
|
access="Delete-Rancher-Incentive-Plan"
|
||||||
title="از حذف طرح تشویقی اطمینان دارید؟"
|
title="از حذف طرح تشویقی اطمینان دارید؟"
|
||||||
api={`/product/web/api/v1/incentive_plan/${item?.id}/`}
|
api={`/product/web/api/v1/rancher_incentive_plan/${item?.id}/`}
|
||||||
getData={refetch}
|
getData={refetch}
|
||||||
/>
|
/>
|
||||||
</Popover>,
|
</Popover>,
|
||||||
@@ -67,7 +52,6 @@ export default function RancherPlans() {
|
|||||||
<Grid container className="items-center gap-2">
|
<Grid container className="items-center gap-2">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Button
|
<Button
|
||||||
className="hidden"
|
|
||||||
size="small"
|
size="small"
|
||||||
page="farmer_plans"
|
page="farmer_plans"
|
||||||
access="Post-Rancher-Incentive-Plan"
|
access="Post-Rancher-Incentive-Plan"
|
||||||
@@ -75,7 +59,12 @@ export default function RancherPlans() {
|
|||||||
onClick={() =>
|
onClick={() =>
|
||||||
openModal({
|
openModal({
|
||||||
title: "تخصیص طرح تشویقی",
|
title: "تخصیص طرح تشویقی",
|
||||||
content: <AddIncentivePlan getData={refetch} />,
|
content: (
|
||||||
|
<LiveStockRancherAllocateIncentivePlan
|
||||||
|
getData={refetch}
|
||||||
|
rancher={farmid}
|
||||||
|
/>
|
||||||
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -95,13 +84,7 @@ export default function RancherPlans() {
|
|||||||
title={`طرح های تشویقی دامدار (${name})`}
|
title={`طرح های تشویقی دامدار (${name})`}
|
||||||
isPaginated
|
isPaginated
|
||||||
count={apiData?.count || 10}
|
count={apiData?.count || 10}
|
||||||
columns={[
|
columns={["ردیف", "نام طرح", "نوع دام", "تعداد راس مجاز", "عملیات"]}
|
||||||
"ردیف",
|
|
||||||
"نام طرح",
|
|
||||||
"نوع دام",
|
|
||||||
"تعداد راس مجاز",
|
|
||||||
// , "عملیات"
|
|
||||||
]}
|
|
||||||
rows={tableData}
|
rows={tableData}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Tabs from "../components/Tab/Tab";
|
import Tabs from "../../components/Tab/Tab";
|
||||||
import { QuotaReportingProducts } from "../partials/quota/QuotaReportingProducts";
|
import { QuotaReportingProducts } from "../../partials/LiveStock/quota/QuotaReportingProducts";
|
||||||
import { useParams } from "@tanstack/react-router";
|
import { useParams } from "@tanstack/react-router";
|
||||||
import { QuotaReportingProductDetails } from "../partials/quota/QuotaReportingProductDetails";
|
import { QuotaReportingProductDetails } from "../../partials/LiveStock/quota/QuotaReportingProductDetails";
|
||||||
import { QuotaReportingQuotaDistributions } from "../partials/quota/QuotaReportingQuotaDistributions";
|
import { QuotaReportingQuotaDistributions } from "../../partials/LiveStock/quota/QuotaReportingQuotaDistributions";
|
||||||
|
|
||||||
const tabItems = [
|
const tabItems = [
|
||||||
{ label: "محصول" },
|
{ label: "محصول" },
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useModalStore } from "../context/zustand-store/appStore";
|
import { useModalStore } from "../../context/zustand-store/appStore";
|
||||||
import { useApiRequest } from "../utils/useApiRequest";
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
import { Popover } from "../components/PopOver/PopOver";
|
import { Popover } from "../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
||||||
import Button from "../components/Button/Button";
|
import Button from "../../components/Button/Button";
|
||||||
import { DeleteButtonForPopOver } from "../components/PopOverButtons/PopOverButtons";
|
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Table from "../components/Table/Table";
|
import Table from "../../components/Table/Table";
|
||||||
import { AddRole } from "../partials/management/AddRole";
|
import { AddRole } from "../../partials/LiveStock/management/AddRole";
|
||||||
import { getFaPermissions } from "../utils/getFaPermissions";
|
import { getFaPermissions } from "../../utils/getFaPermissions";
|
||||||
import ShowStringList from "../components/ShowStringList/ShowStringList";
|
import ShowStringList from "../../components/ShowStringList/ShowStringList";
|
||||||
import ShowMoreInfo from "../components/ShowMoreInfo/ShowMoreInfo";
|
import ShowMoreInfo from "../../components/ShowMoreInfo/ShowMoreInfo";
|
||||||
import Typography from "../components/Typography/Typography";
|
import Typography from "../../components/Typography/Typography";
|
||||||
|
|
||||||
export default function Roles() {
|
export default function Roles() {
|
||||||
const { openModal } = useModalStore();
|
const { openModal } = useModalStore();
|
||||||
@@ -40,7 +40,7 @@ export default function Roles() {
|
|||||||
acc[item.page].names.push(item.name);
|
acc[item.page].names.push(item.name);
|
||||||
acc[item.page].descriptions.push(item.description);
|
acc[item.page].descriptions.push(item.description);
|
||||||
return acc;
|
return acc;
|
||||||
}, {})
|
}, {}),
|
||||||
);
|
);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Tabs from "../components/Tab/Tab";
|
import Tabs from "../../components/Tab/Tab";
|
||||||
import SettingCard from "../components/SettingCard/SettingCard";
|
import SettingCard from "../../components/SettingCard/SettingCard";
|
||||||
import { ShieldExclamationIcon, MapPinIcon } from "@heroicons/react/24/outline";
|
import { ShieldExclamationIcon, MapPinIcon } from "@heroicons/react/24/outline";
|
||||||
import { useModalStore } from "../context/zustand-store/appStore";
|
import { useModalStore } from "../../context/zustand-store/appStore";
|
||||||
import { CooperativesSettingsTable } from "../partials/units/CooperativesSettingsTable";
|
import { CooperativesSettingsTable } from "../../partials/LiveStock/units/CooperativesSettingsTable";
|
||||||
|
|
||||||
const tabItems = [
|
const tabItems = [
|
||||||
{ label: "اتحادیه ها", visible: false },
|
{ label: "اتحادیه ها", visible: false },
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Tabs from "../components/Tab/Tab";
|
import Tabs from "../../components/Tab/Tab";
|
||||||
import TagActiveDistributions from "../partials/tagging/TagActiveDistributions";
|
import TagActiveDistributions from "../../partials/LiveStock/tagging/TagActiveDistributions";
|
||||||
import TagCanceledDistributions from "../partials/tagging/TagCanceledDistributions";
|
import TagCanceledDistributions from "../../partials/LiveStock/tagging/TagCanceledDistributions";
|
||||||
|
|
||||||
export default function TagDistribtution() {
|
export default function TagDistribtution() {
|
||||||
const [selectedTab, setSelectedTab] = useState<number>(0);
|
const [selectedTab, setSelectedTab] = useState<number>(0);
|
||||||
412
src/Pages/LiveStock/TagDistributionDetails.tsx
Normal file
412
src/Pages/LiveStock/TagDistributionDetails.tsx
Normal file
@@ -0,0 +1,412 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useParams } from "@tanstack/react-router";
|
||||||
|
import { Bars3Icon, CubeIcon, SparklesIcon } from "@heroicons/react/24/outline";
|
||||||
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
|
import { useModalStore } from "../../context/zustand-store/appStore";
|
||||||
|
import { formatJustDate, formatJustTime } from "../../utils/formatTime";
|
||||||
|
import ShowMoreInfo from "../../components/ShowMoreInfo/ShowMoreInfo";
|
||||||
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
|
import Typography from "../../components/Typography/Typography";
|
||||||
|
import Table from "../../components/Table/Table";
|
||||||
|
import { Popover } from "../../components/PopOver/PopOver";
|
||||||
|
import Button from "../../components/Button/Button";
|
||||||
|
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
||||||
|
import { DistributeFromDistribution } from "../../partials/LiveStock/tagging/DistributeFromDistribution";
|
||||||
|
import { DocumentOperation } from "../../components/DocumentOperation/DocumentOperation";
|
||||||
|
import { DocumentDownloader } from "../../components/DocumentDownloader/DocumentDownloader";
|
||||||
|
import { BooleanQuestion } from "../../components/BooleanQuestion/BooleanQuestion";
|
||||||
|
import { useUserProfileStore } from "../../context/zustand-store/userStore";
|
||||||
|
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
||||||
|
|
||||||
|
const speciesMap: Record<number, string> = {
|
||||||
|
1: "گاو",
|
||||||
|
2: "گاومیش",
|
||||||
|
3: "شتر",
|
||||||
|
4: "گوسفند",
|
||||||
|
5: "بز",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function TagDistribtutionDetails() {
|
||||||
|
const { id } = useParams({ strict: false });
|
||||||
|
const { openModal } = useModalStore();
|
||||||
|
const [childTableInfo, setChildTableInfo] = useState({
|
||||||
|
page: 1,
|
||||||
|
page_size: 10,
|
||||||
|
});
|
||||||
|
const [childTableData, setChildTableData] = useState([]);
|
||||||
|
|
||||||
|
const { data, refetch: refetchData } = useApiRequest({
|
||||||
|
api: `/tag/web/api/v1/tag_distribution_batch/${id}/`,
|
||||||
|
method: "get",
|
||||||
|
queryKey: ["tagBatchInnerDashboard", id],
|
||||||
|
enabled: !!id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { data: childData, refetch: refetchChildList } = useApiRequest({
|
||||||
|
api: `/tag/web/api/v1/tag_distribution_batch/${id}/child_list/`,
|
||||||
|
method: "get",
|
||||||
|
queryKey: ["tagDistributionChildList", id, childTableInfo],
|
||||||
|
params: {
|
||||||
|
...childTableInfo,
|
||||||
|
},
|
||||||
|
enabled: !!id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { profile } = useUserProfileStore();
|
||||||
|
|
||||||
|
const showAssignDocColumn =
|
||||||
|
childData?.results?.some(
|
||||||
|
(item: any) =>
|
||||||
|
profile?.role?.type?.key === "ADM" ||
|
||||||
|
profile?.organization?.id === item?.assigned_org?.id,
|
||||||
|
) ?? false;
|
||||||
|
|
||||||
|
const AbleToSeeAssignDoc = (item: any) => {
|
||||||
|
if (
|
||||||
|
profile?.role?.type?.key === "ADM" ||
|
||||||
|
profile?.organization?.id === item?.assigned_org?.id
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<DocumentOperation
|
||||||
|
key={item?.id}
|
||||||
|
downloadLink={`/tag/web/api/v1/tag_distribution_batch/${item?.id}/distribution_pdf_view/`}
|
||||||
|
payloadKey="dist_exit_document"
|
||||||
|
validFiles={["pdf"]}
|
||||||
|
page="tag_distribution"
|
||||||
|
access="Upload-Assign-Document"
|
||||||
|
uploadLink={`/tag/web/api/v1/tag_distribution_batch/${item?.id}/assign_document/`}
|
||||||
|
onUploadSuccess={handleUpdate}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUpdate = () => {
|
||||||
|
refetchData();
|
||||||
|
refetchChildList();
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (childData?.results) {
|
||||||
|
const formattedData = childData.results.map(
|
||||||
|
(item: any, index: number) => {
|
||||||
|
const dist = item?.distributions;
|
||||||
|
|
||||||
|
return [
|
||||||
|
childTableInfo.page === 1
|
||||||
|
? index + 1
|
||||||
|
: index +
|
||||||
|
childTableInfo.page_size * (childTableInfo.page - 1) +
|
||||||
|
1,
|
||||||
|
item?.dist_batch_identity ?? "-",
|
||||||
|
`${formatJustDate(item?.create_date) ?? "-"} (${
|
||||||
|
formatJustDate(item?.create_date)
|
||||||
|
? (formatJustTime(item?.create_date) ?? "-")
|
||||||
|
: "-"
|
||||||
|
})`,
|
||||||
|
item?.assigner_org?.name ?? "-",
|
||||||
|
item?.assigned_org?.name ?? "-",
|
||||||
|
item?.total_tag_count?.toLocaleString() ?? "-",
|
||||||
|
item?.total_distributed_tag_count?.toLocaleString() ?? "-",
|
||||||
|
item?.remaining_tag_count?.toLocaleString() ?? "-",
|
||||||
|
item?.distribution_type === "batch"
|
||||||
|
? "توزیع گروهی"
|
||||||
|
: "توزیع تصادفی",
|
||||||
|
<ShowMoreInfo key={item?.id} title="جزئیات توزیع">
|
||||||
|
<Grid container column className="gap-4 w-full">
|
||||||
|
{dist?.map((opt: any, idx: number) => (
|
||||||
|
<Grid
|
||||||
|
key={idx}
|
||||||
|
container
|
||||||
|
column
|
||||||
|
className="gap-3 w-full rounded-xl border border-gray-200 dark:border-gray-700 p-4"
|
||||||
|
>
|
||||||
|
<Grid container className="gap-2 items-center">
|
||||||
|
<SparklesIcon className="w-5 h-5 text-gray-500 dark:text-gray-300" />
|
||||||
|
<Typography variant="body2" className="font-medium">
|
||||||
|
گونه:
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
className="text-gray-700 dark:text-gray-300"
|
||||||
|
>
|
||||||
|
{speciesMap[opt?.species_code] ?? "-"}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{item?.distribution_type === "batch" &&
|
||||||
|
opt?.serial_from != null && (
|
||||||
|
<Grid container className="gap-2 items-center">
|
||||||
|
<Bars3Icon className="w-5 h-5 text-gray-500 dark:text-gray-300" />
|
||||||
|
<Typography variant="body2" className="font-medium">
|
||||||
|
بازه سریال:
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
className="text-gray-600 dark:text-gray-400"
|
||||||
|
>
|
||||||
|
از {opt?.serial_from ?? "-"} تا{" "}
|
||||||
|
{opt?.serial_to ?? "-"}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Grid container className="gap-2 items-center">
|
||||||
|
<CubeIcon className="w-5 h-5 text-gray-500 dark:text-gray-300" />
|
||||||
|
<Typography variant="body2" className="font-medium">
|
||||||
|
تعداد پلاک:
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
className="text-gray-700 dark:text-gray-300"
|
||||||
|
>
|
||||||
|
{opt?.total_tag_count?.toLocaleString() ?? "-"}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid container className="gap-2 items-center">
|
||||||
|
<CubeIcon className="w-5 h-5 text-gray-500 dark:text-gray-300" />
|
||||||
|
<Typography variant="body2" className="font-medium">
|
||||||
|
پلاک های توزیع شده:
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
className="text-gray-700 dark:text-gray-300"
|
||||||
|
>
|
||||||
|
{opt?.distributed_number?.toLocaleString() ?? "-"}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid container className="gap-2 items-center">
|
||||||
|
<CubeIcon className="w-5 h-5 text-gray-500 dark:text-gray-300" />
|
||||||
|
<Typography variant="body2" className="font-medium">
|
||||||
|
پلاک های باقیمانده:
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
className="text-gray-700 dark:text-gray-300"
|
||||||
|
>
|
||||||
|
{opt?.remaining_number?.toLocaleString() ?? "-"}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</ShowMoreInfo>,
|
||||||
|
...(showAssignDocColumn ? [AbleToSeeAssignDoc(item)] : []),
|
||||||
|
<DocumentDownloader
|
||||||
|
key={`doc-${item?.id}`}
|
||||||
|
link={item?.warehouse_exit_doc}
|
||||||
|
title="دانلود"
|
||||||
|
/>,
|
||||||
|
item?.exit_doc_status ? (
|
||||||
|
"تایید شده"
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
key={`btn-${item?.id}`}
|
||||||
|
page="tag_distribution"
|
||||||
|
access="Accept-Assign-Document"
|
||||||
|
size="small"
|
||||||
|
disabled={item?.exit_doc_status}
|
||||||
|
onClick={() => {
|
||||||
|
openModal({
|
||||||
|
title: "تایید سند خروج",
|
||||||
|
content: (
|
||||||
|
<BooleanQuestion
|
||||||
|
api={`/tag/web/api/v1/tag_distribution_batch/${item?.id}/accept_exit_doc/`}
|
||||||
|
method="post"
|
||||||
|
getData={handleUpdate}
|
||||||
|
title="آیا از تایید سند خروج مطمئنید؟"
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
تایید سند خروج
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
<Popover key={`popover-${item?.id}`}>
|
||||||
|
<Tooltip title="ویرایش توزیع" position="right">
|
||||||
|
<Button
|
||||||
|
variant="edit"
|
||||||
|
page="tag_distribution"
|
||||||
|
access="Submit-Tag-Distribution"
|
||||||
|
onClick={() => {
|
||||||
|
openModal({
|
||||||
|
title: "ویرایش توزیع",
|
||||||
|
content: (
|
||||||
|
<DistributeFromDistribution
|
||||||
|
getData={handleUpdate}
|
||||||
|
item={item}
|
||||||
|
isEdit
|
||||||
|
parentDistributions={data?.distributions}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<DeleteButtonForPopOver
|
||||||
|
page="tag_distribution"
|
||||||
|
access="Delete-Tag-Distribution"
|
||||||
|
api={`/tag/web/api/v1/tag_distribution_batch/${item?.id}/`}
|
||||||
|
getData={handleUpdate}
|
||||||
|
/>
|
||||||
|
</Popover>,
|
||||||
|
];
|
||||||
|
},
|
||||||
|
);
|
||||||
|
setChildTableData(formattedData);
|
||||||
|
} else {
|
||||||
|
setChildTableData([]);
|
||||||
|
}
|
||||||
|
}, [childData, childTableInfo]);
|
||||||
|
|
||||||
|
const dist = data?.distributions;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid container column className="gap-4 mt-2">
|
||||||
|
<Grid isDashboard>
|
||||||
|
<Table
|
||||||
|
isDashboard
|
||||||
|
title="مشخصات توزیع پلاک"
|
||||||
|
noSearch
|
||||||
|
noPagination
|
||||||
|
columns={[
|
||||||
|
"شناسه توزیع",
|
||||||
|
"تاریخ ثبت",
|
||||||
|
"توزیع کننده",
|
||||||
|
"دریافت کننده",
|
||||||
|
"تعداد کل پلاک",
|
||||||
|
"پلاک های توزیع شده",
|
||||||
|
"پلاک های باقیمانده",
|
||||||
|
"نوع توزیع",
|
||||||
|
"جزئیات توزیع",
|
||||||
|
]}
|
||||||
|
rows={[
|
||||||
|
[
|
||||||
|
data?.dist_batch_identity ?? "-",
|
||||||
|
`${formatJustDate(data?.create_date) ?? "-"} (${
|
||||||
|
formatJustDate(data?.create_date)
|
||||||
|
? (formatJustTime(data?.create_date) ?? "-")
|
||||||
|
: "-"
|
||||||
|
})`,
|
||||||
|
data?.assigner_org?.name ?? "-",
|
||||||
|
data?.assigned_org?.name ?? "-",
|
||||||
|
data?.total_tag_count?.toLocaleString() ?? "-",
|
||||||
|
data?.total_distributed_tag_count?.toLocaleString() ?? "-",
|
||||||
|
data?.remaining_tag_count?.toLocaleString() ?? "-",
|
||||||
|
data?.distribution_type === "batch"
|
||||||
|
? "توزیع گروهی"
|
||||||
|
: "توزیع تصادفی",
|
||||||
|
<ShowMoreInfo key={data?.id} title="جزئیات توزیع">
|
||||||
|
<Grid container column className="gap-4 w-full">
|
||||||
|
{dist?.map((opt: any, index: number) => (
|
||||||
|
<Grid
|
||||||
|
key={index}
|
||||||
|
container
|
||||||
|
column
|
||||||
|
className="gap-3 w-full rounded-xl border border-gray-200 dark:border-gray-700 p-4"
|
||||||
|
>
|
||||||
|
<Grid container className="gap-2 items-center">
|
||||||
|
<SparklesIcon className="w-5 h-5 text-gray-500 dark:text-gray-300" />
|
||||||
|
<Typography variant="body2" className="font-medium">
|
||||||
|
گونه:
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
className="text-gray-700 dark:text-gray-300"
|
||||||
|
>
|
||||||
|
{speciesMap[opt?.species_code] ?? "-"}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{data?.distribution_type === "batch" &&
|
||||||
|
opt?.serial_from != null && (
|
||||||
|
<Grid container className="gap-2 items-center">
|
||||||
|
<Bars3Icon className="w-5 h-5 text-gray-500 dark:text-gray-300" />
|
||||||
|
<Typography variant="body2" className="font-medium">
|
||||||
|
بازه سریال:
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
className="text-gray-600 dark:text-gray-400"
|
||||||
|
>
|
||||||
|
از {opt?.serial_from ?? "-"} تا{" "}
|
||||||
|
{opt?.serial_to ?? "-"}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Grid container className="gap-2 items-center">
|
||||||
|
<CubeIcon className="w-5 h-5 text-gray-500 dark:text-gray-300" />
|
||||||
|
<Typography variant="body2" className="font-medium">
|
||||||
|
تعداد پلاک:
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
className="text-gray-700 dark:text-gray-300"
|
||||||
|
>
|
||||||
|
{opt?.total_tag_count?.toLocaleString() ?? "-"}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid container className="gap-2 items-center">
|
||||||
|
<CubeIcon className="w-5 h-5 text-gray-500 dark:text-gray-300" />
|
||||||
|
<Typography variant="body2" className="font-medium">
|
||||||
|
پلاک های توزیع شده:
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
className="text-gray-700 dark:text-gray-300"
|
||||||
|
>
|
||||||
|
{opt?.distributed_number?.toLocaleString() ?? "-"}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid container className="gap-2 items-center">
|
||||||
|
<CubeIcon className="w-5 h-5 text-gray-500 dark:text-gray-300" />
|
||||||
|
<Typography variant="body2" className="font-medium">
|
||||||
|
پلاک های باقیمانده:
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
className="text-gray-700 dark:text-gray-300"
|
||||||
|
>
|
||||||
|
{opt?.remaining_number?.toLocaleString() ?? "-"}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</ShowMoreInfo>,
|
||||||
|
],
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Table
|
||||||
|
className="mt-2"
|
||||||
|
onChange={setChildTableInfo}
|
||||||
|
count={childData?.count || 0}
|
||||||
|
isPaginated
|
||||||
|
title="توزیع های مجدد"
|
||||||
|
columns={[
|
||||||
|
"ردیف",
|
||||||
|
"شناسه توزیع",
|
||||||
|
"تاریخ ثبت",
|
||||||
|
"توزیع کننده",
|
||||||
|
"دریافت کننده",
|
||||||
|
"تعداد کل پلاک",
|
||||||
|
"پلاک های توزیع شده",
|
||||||
|
"پلاک های باقیمانده",
|
||||||
|
"نوع توزیع",
|
||||||
|
"جزئیات توزیع",
|
||||||
|
...(showAssignDocColumn ? ["امضا سند خروج از انبار"] : []),
|
||||||
|
"سند خروج از انبار",
|
||||||
|
"تایید سند خروج",
|
||||||
|
"عملیات",
|
||||||
|
]}
|
||||||
|
rows={childTableData}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
27
src/Pages/LiveStock/Tagging.tsx
Normal file
27
src/Pages/LiveStock/Tagging.tsx
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
|
import Tabs from "../../components/Tab/Tab";
|
||||||
|
import Taggings from "../../partials/LiveStock/tagging/Taggings";
|
||||||
|
import Tags from "../../partials/LiveStock/tagging/Tags";
|
||||||
|
|
||||||
|
const tabItems = [
|
||||||
|
{ label: "ثبت پلاک" },
|
||||||
|
{ label: "پلاک ها", page: "tagging_detail", access: "Show-Tagging-Detail" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function Tagging() {
|
||||||
|
const [selectedTab, setSelectedTab] = useState<number>(0);
|
||||||
|
const handleTabChange = (index: number) => {
|
||||||
|
setSelectedTab(index);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid container column className="justify-center mt-2">
|
||||||
|
<Tabs tabs={tabItems} onChange={handleTabChange} size="medium" />
|
||||||
|
<Grid container column className="mt-2">
|
||||||
|
{selectedTab === 0 && <Taggings />}
|
||||||
|
{selectedTab === 1 && <Tags />}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,16 +1,19 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import Table from "../components/Table/Table";
|
import Table from "../../components/Table/Table";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import { useApiRequest } from "../utils/useApiRequest";
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
import { formatJustDate, formatJustTime } from "../utils/formatTime";
|
import { formatJustDate, formatJustTime } from "../../utils/formatTime";
|
||||||
import { TableButton } from "../components/TableButton/TableButton";
|
import { TableButton } from "../../components/TableButton/TableButton";
|
||||||
import { useModalStore } from "../context/zustand-store/appStore";
|
import { useModalStore } from "../../context/zustand-store/appStore";
|
||||||
import TransactionDetails from "../partials/transactions/TransactionDetails";
|
import TransactionDetails from "../../partials/LiveStock/transactions/TransactionDetails";
|
||||||
import { DashboardResponse, ProductSummaryItem } from "../types/transactions";
|
import {
|
||||||
import { ProductSummaryModal } from "../partials/transactions/ProductSummaryModal";
|
DashboardResponse,
|
||||||
import { PaginationParameters } from "../components/PaginationParameters/PaginationParameters";
|
ProductSummaryItem,
|
||||||
import TransactionSharingDetails from "../partials/transactions/TransactionSharingDetails";
|
} from "../../types/transactions";
|
||||||
import { convertNumberToPersian } from "../utils/convertNumberToPersian";
|
import { ProductSummaryModal } from "../../partials/LiveStock/transactions/ProductSummaryModal";
|
||||||
|
import { PaginationParameters } from "../../components/PaginationParameters/PaginationParameters";
|
||||||
|
import TransactionSharingDetails from "../../partials/LiveStock/transactions/TransactionSharingDetails";
|
||||||
|
import { convertNumberToPersian } from "../../utils/convertNumberToPersian";
|
||||||
|
|
||||||
type TransactionResponse = {
|
type TransactionResponse = {
|
||||||
results?: any[];
|
results?: any[];
|
||||||
@@ -72,7 +75,7 @@ export default function Transactions() {
|
|||||||
.filter((unit: any) => unit);
|
.filter((unit: any) => unit);
|
||||||
const totalWeight = items.reduce(
|
const totalWeight = items.reduce(
|
||||||
(sum: number, p: any) => sum + (p?.weight || 0),
|
(sum: number, p: any) => sum + (p?.weight || 0),
|
||||||
0
|
0,
|
||||||
);
|
);
|
||||||
|
|
||||||
let weightNature;
|
let weightNature;
|
||||||
@@ -210,7 +213,7 @@ export default function Transactions() {
|
|||||||
DashboardData?.transaction_summary?.total_amount?.toLocaleString() ||
|
DashboardData?.transaction_summary?.total_amount?.toLocaleString() ||
|
||||||
0,
|
0,
|
||||||
convertNumberToPersian(
|
convertNumberToPersian(
|
||||||
DashboardData?.transaction_summary?.total_amount || 0
|
DashboardData?.transaction_summary?.total_amount || 0,
|
||||||
),
|
),
|
||||||
DashboardData?.transaction_summary?.total_weight?.toLocaleString() ||
|
DashboardData?.transaction_summary?.total_weight?.toLocaleString() ||
|
||||||
0,
|
0,
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApiRequest } from "../utils/useApiRequest";
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Table from "../components/Table/Table";
|
import Table from "../../components/Table/Table";
|
||||||
import { Popover } from "../components/PopOver/PopOver";
|
import { Popover } from "../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
||||||
import Button from "../components/Button/Button";
|
import Button from "../../components/Button/Button";
|
||||||
import { COOPERATIVE_LIST } from "../routes/paths";
|
import { COOPERATIVE_LIST } from "../../routes/paths";
|
||||||
import { useNavigate } from "@tanstack/react-router";
|
import { useNavigate } from "@tanstack/react-router";
|
||||||
|
|
||||||
export default function Unions() {
|
export default function Unions() {
|
||||||
81
src/Pages/LiveStock/UnitsInventory.tsx
Normal file
81
src/Pages/LiveStock/UnitsInventory.tsx
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
|
import Table from "../../components/Table/Table";
|
||||||
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
|
import { formatJustDate } from "../../utils/formatTime";
|
||||||
|
import CheckTrackingCode from "../../components/CheckTrackingCode/CheckTrackingCode";
|
||||||
|
|
||||||
|
type UnitsInventoryResponse = {
|
||||||
|
results?: any[];
|
||||||
|
count?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function UnitsInventory() {
|
||||||
|
const [params, setParams] = useState({ page: 1, page_size: 10 });
|
||||||
|
const [tableData, setTableData] = useState<any[]>([]);
|
||||||
|
|
||||||
|
const { data } = useApiRequest<UnitsInventoryResponse>({
|
||||||
|
api: "/rsi/web/api/v1/org_rsi_data/",
|
||||||
|
method: "get",
|
||||||
|
params,
|
||||||
|
queryKey: ["units_inventory", params],
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (data?.results) {
|
||||||
|
const formattedData = data.results.map((item: any, i: number) => [
|
||||||
|
params.page === 1
|
||||||
|
? i + 1
|
||||||
|
: i + params.page_size * (params.page - 1) + 1,
|
||||||
|
<CheckTrackingCode key={`${item?.id}-tracking`} tracking={item?.tracking} />,
|
||||||
|
item?.record_id || "-",
|
||||||
|
formatJustDate(item?.data) || "-",
|
||||||
|
item?.product || "-",
|
||||||
|
item?.quantity ? Number(item.quantity).toLocaleString() : "-",
|
||||||
|
item?.unit || "-",
|
||||||
|
item?.origin_province || "-",
|
||||||
|
item?.destination_province || "-",
|
||||||
|
item?.origin_city || "-",
|
||||||
|
item?.destination_city || "-",
|
||||||
|
item?.origin || "-",
|
||||||
|
item?.destination || "-",
|
||||||
|
item?.driver_name || "-",
|
||||||
|
item?.car_tracking_code || "-",
|
||||||
|
]);
|
||||||
|
|
||||||
|
setTableData(formattedData);
|
||||||
|
} else {
|
||||||
|
setTableData([]);
|
||||||
|
}
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid container column>
|
||||||
|
<Table
|
||||||
|
className="mt-2"
|
||||||
|
onChange={setParams}
|
||||||
|
count={data?.count || 0}
|
||||||
|
isPaginated
|
||||||
|
title="انبار واحدها"
|
||||||
|
columns={[
|
||||||
|
"ردیف",
|
||||||
|
"کد رهگیری",
|
||||||
|
"شماره رکورد",
|
||||||
|
"تاریخ",
|
||||||
|
"محصول",
|
||||||
|
"مقدار",
|
||||||
|
"واحد",
|
||||||
|
"استان مبدا",
|
||||||
|
"استان مقصد",
|
||||||
|
"شهرستان مبدا",
|
||||||
|
"شهرستان مقصد",
|
||||||
|
"مبدا",
|
||||||
|
"مقصد",
|
||||||
|
"راننده",
|
||||||
|
"کد رهگیری خودرو",
|
||||||
|
]}
|
||||||
|
rows={tableData}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
import Table from "../components/Table/Table";
|
import Table from "../../components/Table/Table";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import { useApiRequest } from "../utils/useApiRequest";
|
import { useApiRequest } from "../../utils/useApiRequest";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { getFaPermissions } from "../utils/getFaPermissions";
|
import { getFaPermissions } from "../../utils/getFaPermissions";
|
||||||
import { Popover } from "../components/PopOver/PopOver";
|
import { Popover } from "../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
||||||
import Button from "../components/Button/Button";
|
import Button from "../../components/Button/Button";
|
||||||
import { DeleteButtonForPopOver } from "../components/PopOverButtons/PopOverButtons";
|
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
||||||
import {
|
import {
|
||||||
useDrawerStore,
|
useDrawerStore,
|
||||||
useModalStore,
|
useModalStore,
|
||||||
} from "../context/zustand-store/appStore";
|
} from "../../context/zustand-store/appStore";
|
||||||
import { EditAccess } from "../partials/management/EditAccess";
|
import { EditAccess } from "../../partials/Admin/EditAccess";
|
||||||
import { AddUser } from "../partials/management/AddUser";
|
import { AddUser } from "../../partials/LiveStock/management/AddUser";
|
||||||
import ShowStringList from "../components/ShowStringList/ShowStringList";
|
import ShowStringList from "../../components/ShowStringList/ShowStringList";
|
||||||
import ShowMoreInfo from "../components/ShowMoreInfo/ShowMoreInfo";
|
import ShowMoreInfo from "../../components/ShowMoreInfo/ShowMoreInfo";
|
||||||
import AutoComplete from "../components/AutoComplete/AutoComplete";
|
import AutoComplete from "../../components/AutoComplete/AutoComplete";
|
||||||
import { useUserProfileStore } from "../context/zustand-store/userStore";
|
import { useUserProfileStore } from "../../context/zustand-store/userStore";
|
||||||
|
|
||||||
type PermissionType = {
|
type PermissionType = {
|
||||||
page_name: string;
|
page_name: string;
|
||||||
@@ -95,7 +95,7 @@ export default function Users() {
|
|||||||
>
|
>
|
||||||
<ShowStringList
|
<ShowStringList
|
||||||
strings={item?.permissions?.map((option: PermissionType) =>
|
strings={item?.permissions?.map((option: PermissionType) =>
|
||||||
getFaPermissions(option?.page_name)
|
getFaPermissions(option?.page_name),
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</ShowMoreInfo>,
|
</ShowMoreInfo>,
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Grid } from "../components/Grid/Grid";
|
import { Grid } from "../components/Grid/Grid";
|
||||||
import Tabs from "../components/Tab/Tab";
|
import Tabs from "../components/Tab/Tab";
|
||||||
import Pages from "../partials/management/Pages";
|
import Pages from "../partials/Admin/Pages";
|
||||||
import Access from "../partials/management/Access";
|
import Access from "../partials/Admin/Access";
|
||||||
import UnusedAccess from "../partials/management/UnusedAccess";
|
import UnusedAccess from "../partials/Admin/UnusedAccess";
|
||||||
|
|
||||||
const tabItems = [
|
const tabItems = [
|
||||||
{ label: "صفحات" },
|
{ label: "صفحات" },
|
||||||
|
|||||||
@@ -7,7 +7,11 @@ import { useUserProfileStore } from "../context/zustand-store/userStore";
|
|||||||
import { getUserPermissions } from "../utils/getUserAvalableItems";
|
import { getUserPermissions } from "../utils/getUserAvalableItems";
|
||||||
import { ItemWithSubItems } from "../types/userPermissions";
|
import { ItemWithSubItems } from "../types/userPermissions";
|
||||||
import { useNavigate } from "@tanstack/react-router";
|
import { useNavigate } from "@tanstack/react-router";
|
||||||
import { Bars3Icon, QueueListIcon } from "@heroicons/react/24/outline";
|
import {
|
||||||
|
Bars3Icon,
|
||||||
|
QueueListIcon,
|
||||||
|
Squares2X2Icon,
|
||||||
|
} from "@heroicons/react/24/outline";
|
||||||
import { getFaPermissions } from "../utils/getFaPermissions";
|
import { getFaPermissions } from "../utils/getFaPermissions";
|
||||||
import SVGImage from "../components/SvgImage/SvgImage";
|
import SVGImage from "../components/SvgImage/SvgImage";
|
||||||
|
|
||||||
@@ -58,13 +62,13 @@ export const Menu = () => {
|
|||||||
const { profile } = useUserProfileStore();
|
const { profile } = useUserProfileStore();
|
||||||
|
|
||||||
const menuItems: ItemWithSubItems[] = getUserPermissions(
|
const menuItems: ItemWithSubItems[] = getUserPermissions(
|
||||||
profile?.permissions
|
profile?.permissions,
|
||||||
);
|
);
|
||||||
|
|
||||||
const getOpenedItem = () => {
|
const getOpenedItem = () => {
|
||||||
if (window.location.pathname !== "/") {
|
if (window.location.pathname !== "/") {
|
||||||
const matchedIndex = menuItems.findIndex((item) =>
|
const matchedIndex = menuItems.findIndex((item) =>
|
||||||
item.subItems.some((sub) => sub.path === window.location.pathname)
|
item.subItems.some((sub) => sub.path === window.location.pathname),
|
||||||
);
|
);
|
||||||
return matchedIndex;
|
return matchedIndex;
|
||||||
} else {
|
} else {
|
||||||
@@ -73,12 +77,62 @@ export const Menu = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const [openIndex, setOpenIndex] = useState<number | null>(getOpenedItem());
|
const [openIndex, setOpenIndex] = useState<number | null>(getOpenedItem());
|
||||||
|
const [openDomains, setOpenDomains] = useState<Record<string, boolean>>({});
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const adminItems = menuItems
|
||||||
|
.map((item, index) => ({ ...item, originalIndex: index }))
|
||||||
|
.filter((item) => item.en === "admin");
|
||||||
|
const indexedNonAdminItems = menuItems
|
||||||
|
.map((item, index) => ({ ...item, originalIndex: index }))
|
||||||
|
.filter((item) => item.en !== "admin");
|
||||||
|
|
||||||
|
const permissionDomainMap = new Map<string, string>();
|
||||||
|
(profile?.permissions || []).forEach((permission: any) => {
|
||||||
|
if (permission?.page_name) {
|
||||||
|
permissionDomainMap.set(
|
||||||
|
permission.page_name,
|
||||||
|
permission?.domain_fa_name || "سایر حوزه ها",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupedItems = indexedNonAdminItems.reduce(
|
||||||
|
(acc, item) => {
|
||||||
|
const firstSubItem = item.subItems?.find((sub) =>
|
||||||
|
permissionDomainMap.has(sub.name),
|
||||||
|
);
|
||||||
|
const domainTitle = firstSubItem
|
||||||
|
? permissionDomainMap.get(firstSubItem.name) || "سایر حوزه ها"
|
||||||
|
: "سایر حوزه ها";
|
||||||
|
|
||||||
|
if (!acc[domainTitle]) {
|
||||||
|
acc[domainTitle] = [];
|
||||||
|
}
|
||||||
|
acc[domainTitle].push(item);
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{} as Record<
|
||||||
|
string,
|
||||||
|
(ItemWithSubItems & { originalIndex: number })[]
|
||||||
|
>,
|
||||||
|
);
|
||||||
|
const showDomainGrouping = Object.keys(groupedItems).length > 1;
|
||||||
|
|
||||||
const toggleSubmenu = (index: number) => {
|
const toggleSubmenu = (index: number) => {
|
||||||
setOpenIndex((prev) => (prev === index ? null : index));
|
setOpenIndex((prev) => (prev === index ? null : index));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isDomainOpen = (domainTitle: string) =>
|
||||||
|
openDomains[domainTitle] ?? true;
|
||||||
|
|
||||||
|
const toggleDomain = (domainTitle: string) => {
|
||||||
|
setOpenDomains((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[domainTitle]: !(prev[domainTitle] ?? true),
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid
|
<Grid
|
||||||
container
|
container
|
||||||
@@ -99,14 +153,14 @@ export const Menu = () => {
|
|||||||
animate="visible"
|
animate="visible"
|
||||||
className="flex flex-col items-center gap-4 w-full"
|
className="flex flex-col items-center gap-4 w-full"
|
||||||
>
|
>
|
||||||
{menuItems.map(({ fa, icon: Icon, subItems }, index) => (
|
{adminItems.map(({ fa, icon: Icon, subItems, originalIndex }) => (
|
||||||
<motion.div
|
<motion.div
|
||||||
key={index}
|
key={`admin-${originalIndex}`}
|
||||||
variants={itemVariants}
|
variants={itemVariants}
|
||||||
className="w-full max-w-sm"
|
className="w-full max-w-sm"
|
||||||
>
|
>
|
||||||
<motion.button
|
<motion.button
|
||||||
onClick={() => toggleSubmenu(index)}
|
onClick={() => toggleSubmenu(originalIndex)}
|
||||||
whileTap={{ scale: 0.97 }}
|
whileTap={{ scale: 0.97 }}
|
||||||
className="w-full flex justify-between items-center gap-3 px-4 py-3 rounded-lg shadow-xs dark:shadow-sm shadow-dark-300 dark:shadow-dark-500 backdrop-blur-md bg-gradient-to-r from-transparent to-transparent dark:via-gray-800 via-gray-100 border border-dark-200 dark:border-dark-700 text-dark-800 dark:text-dark-100 transition-all duration-200"
|
className="w-full flex justify-between items-center gap-3 px-4 py-3 rounded-lg shadow-xs dark:shadow-sm shadow-dark-300 dark:shadow-dark-500 backdrop-blur-md bg-gradient-to-r from-transparent to-transparent dark:via-gray-800 via-gray-100 border border-dark-200 dark:border-dark-700 text-dark-800 dark:text-dark-100 transition-all duration-200"
|
||||||
>
|
>
|
||||||
@@ -120,13 +174,13 @@ export const Menu = () => {
|
|||||||
</div>
|
</div>
|
||||||
<ChevronDownIcon
|
<ChevronDownIcon
|
||||||
className={`w-5 h-5 text-dark-500 dark:text-dark-300 transition-transform duration-300 ${
|
className={`w-5 h-5 text-dark-500 dark:text-dark-300 transition-transform duration-300 ${
|
||||||
openIndex === index ? "rotate-180" : ""
|
openIndex === originalIndex ? "rotate-180" : ""
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
</motion.button>
|
</motion.button>
|
||||||
|
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{openIndex === index && (
|
{openIndex === originalIndex && (
|
||||||
<motion.div
|
<motion.div
|
||||||
key="submenu"
|
key="submenu"
|
||||||
variants={submenuVariants}
|
variants={submenuVariants}
|
||||||
@@ -156,6 +210,146 @@ export const Menu = () => {
|
|||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
{showDomainGrouping
|
||||||
|
? Object.entries(groupedItems).map(([domainTitle, domainItems]) => (
|
||||||
|
<div key={domainTitle} className="w-full max-w-sm">
|
||||||
|
<button
|
||||||
|
onClick={() => toggleDomain(domainTitle)}
|
||||||
|
className="w-full px-1 py-1 text-primary-700 dark:text-primary-200 text-sm font-bold flex items-center justify-between cursor-pointer"
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Squares2X2Icon className="w-4 h-4 text-primary-600 dark:text-primary-300" />
|
||||||
|
<span>{domainTitle}</span>
|
||||||
|
</div>
|
||||||
|
<ChevronDownIcon
|
||||||
|
className={`w-4 h-4 transition-transform duration-300 ${
|
||||||
|
isDomainOpen(domainTitle) ? "rotate-180" : ""
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{(isDomainOpen(domainTitle) || !domainTitle) && (
|
||||||
|
<div className="mt-1 mr-2 border-r-2 border-primary-200 dark:border-primary-500/40 pr-2 flex flex-col gap-3">
|
||||||
|
{domainItems.map(
|
||||||
|
({ fa, icon: Icon, subItems, originalIndex }) => (
|
||||||
|
<motion.div
|
||||||
|
key={`group-${domainTitle}-${originalIndex}`}
|
||||||
|
variants={itemVariants}
|
||||||
|
className="w-full"
|
||||||
|
>
|
||||||
|
<motion.button
|
||||||
|
onClick={() => toggleSubmenu(originalIndex)}
|
||||||
|
whileTap={{ scale: 0.97 }}
|
||||||
|
className="w-full flex justify-between items-center gap-3 px-4 py-3 rounded-lg shadow-xs dark:shadow-sm shadow-dark-300 dark:shadow-dark-500 backdrop-blur-md bg-gradient-to-r from-transparent to-transparent dark:via-gray-800 via-gray-100 border border-dark-200 dark:border-dark-700 text-dark-800 dark:text-dark-100 transition-all duration-200"
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<SVGImage
|
||||||
|
src={Icon}
|
||||||
|
className={` text-primary-800 dark:text-primary-100`}
|
||||||
|
/>
|
||||||
|
<span className="text-base font-medium">{fa}</span>
|
||||||
|
</div>
|
||||||
|
<ChevronDownIcon
|
||||||
|
className={`w-5 h-5 text-dark-500 dark:text-dark-300 transition-transform duration-300 ${
|
||||||
|
openIndex === originalIndex ? "rotate-180" : ""
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
</motion.button>
|
||||||
|
|
||||||
|
<AnimatePresence>
|
||||||
|
{openIndex === originalIndex && (
|
||||||
|
<motion.div
|
||||||
|
key="submenu"
|
||||||
|
variants={submenuVariants}
|
||||||
|
initial="hidden"
|
||||||
|
animate="visible"
|
||||||
|
exit="exit"
|
||||||
|
className="mt-2 mr-4 border-r-2 border-primary-500 dark:border-primary-400 pr-4 flex flex-col gap-2"
|
||||||
|
>
|
||||||
|
{subItems
|
||||||
|
.filter((item) => !item?.path.includes("$"))
|
||||||
|
?.map((sub, subIndex) => (
|
||||||
|
<motion.button
|
||||||
|
onClick={() => {
|
||||||
|
navigate({ to: sub.path });
|
||||||
|
}}
|
||||||
|
key={subIndex}
|
||||||
|
whileTap={{ scale: 0.97 }}
|
||||||
|
className="text-sm flex items-center gap-2 text-dark-700 dark:text-dark-200 bg-white dark:bg-dark-700 shadow-sm px-3 py-2 rounded-lg w-full text-right"
|
||||||
|
>
|
||||||
|
<QueueListIcon className="w-3" />
|
||||||
|
{getFaPermissions(sub.name)}
|
||||||
|
</motion.button>
|
||||||
|
))}
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
</motion.div>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
: indexedNonAdminItems.map(
|
||||||
|
({ fa, icon: Icon, subItems, originalIndex }) => (
|
||||||
|
<motion.div
|
||||||
|
key={`plain-${originalIndex}`}
|
||||||
|
variants={itemVariants}
|
||||||
|
className="w-full max-w-sm"
|
||||||
|
>
|
||||||
|
<motion.button
|
||||||
|
onClick={() => toggleSubmenu(originalIndex)}
|
||||||
|
whileTap={{ scale: 0.97 }}
|
||||||
|
className="w-full flex justify-between items-center gap-3 px-4 py-3 rounded-lg shadow-xs dark:shadow-sm shadow-dark-300 dark:shadow-dark-500 backdrop-blur-md bg-gradient-to-r from-transparent to-transparent dark:via-gray-800 via-gray-100 border border-dark-200 dark:border-dark-700 text-dark-800 dark:text-dark-100 transition-all duration-200"
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<SVGImage
|
||||||
|
src={Icon}
|
||||||
|
className={` text-primary-800 dark:text-primary-100`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<span className="text-base font-medium">{fa}</span>
|
||||||
|
</div>
|
||||||
|
<ChevronDownIcon
|
||||||
|
className={`w-5 h-5 text-dark-500 dark:text-dark-300 transition-transform duration-300 ${
|
||||||
|
openIndex === originalIndex ? "rotate-180" : ""
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
</motion.button>
|
||||||
|
|
||||||
|
<AnimatePresence>
|
||||||
|
{openIndex === originalIndex && (
|
||||||
|
<motion.div
|
||||||
|
key="submenu"
|
||||||
|
variants={submenuVariants}
|
||||||
|
initial="hidden"
|
||||||
|
animate="visible"
|
||||||
|
exit="exit"
|
||||||
|
className="mt-2 mr-4 border-r-2 border-primary-500 dark:border-primary-400 pr-4 flex flex-col gap-2"
|
||||||
|
>
|
||||||
|
{subItems
|
||||||
|
.filter((item) => !item?.path.includes("$"))
|
||||||
|
?.map((sub, subIndex) => (
|
||||||
|
<motion.button
|
||||||
|
onClick={() => {
|
||||||
|
navigate({ to: sub.path });
|
||||||
|
}}
|
||||||
|
key={subIndex}
|
||||||
|
whileTap={{ scale: 0.97 }}
|
||||||
|
className="text-sm flex items-center gap-2 text-dark-700 dark:text-dark-200 bg-white dark:bg-dark-700 shadow-sm px-3 py-2 rounded-lg w-full text-right"
|
||||||
|
>
|
||||||
|
<QueueListIcon className="w-3" />
|
||||||
|
{getFaPermissions(sub.name)}
|
||||||
|
</motion.button>
|
||||||
|
))}
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
</motion.div>
|
||||||
|
),
|
||||||
|
)}
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
import { useEffect, useState } from "react";
|
|
||||||
import { useParams } from "@tanstack/react-router";
|
|
||||||
import { useApiRequest } from "../utils/useApiRequest";
|
|
||||||
import { Grid } from "../components/Grid/Grid";
|
|
||||||
import Table from "../components/Table/Table";
|
|
||||||
|
|
||||||
export default function TagDistribtutionDetails() {
|
|
||||||
const { id } = useParams({ strict: false });
|
|
||||||
const [tableData, setTableData] = useState([]);
|
|
||||||
|
|
||||||
const { data } = useApiRequest({
|
|
||||||
api: `/tag/web/api/v1/tag_distribution_batch/${id}/`,
|
|
||||||
method: "get",
|
|
||||||
queryKey: ["tagBatchInnerDashboard", id],
|
|
||||||
enabled: !!id,
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (data?.distributions) {
|
|
||||||
const rows = data.distributions.map((item: any, index: number) => [
|
|
||||||
index + 1,
|
|
||||||
item?.dist_identity,
|
|
||||||
item?.batch_identity,
|
|
||||||
item?.distribution_type === "batch" ? "توزیع گروهی" : "توزیع تصادفی",
|
|
||||||
item?.species_code,
|
|
||||||
item?.total_tag_count,
|
|
||||||
item?.distributed_number,
|
|
||||||
item?.remaining_number,
|
|
||||||
`از ${item?.serial_from} تا ${item?.serial_to}`,
|
|
||||||
]);
|
|
||||||
setTableData(rows);
|
|
||||||
}
|
|
||||||
}, [data]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Grid container column className="gap-4">
|
|
||||||
<Table
|
|
||||||
title="جزئیات توزیع پلاک"
|
|
||||||
noSearch
|
|
||||||
noPagination
|
|
||||||
columns={[
|
|
||||||
"ردیف",
|
|
||||||
"شناسه توزیع",
|
|
||||||
"شناسه پلاک",
|
|
||||||
"نوع توزیع",
|
|
||||||
"کد گونه",
|
|
||||||
"تعداد کل پلاک ها",
|
|
||||||
"تعداد توزیع شده",
|
|
||||||
"تعداد باقیمانده",
|
|
||||||
"بازه سریال",
|
|
||||||
]}
|
|
||||||
rows={tableData}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -16,7 +16,7 @@ import { Grid } from "../components/Grid/Grid";
|
|||||||
import { useDarkMode } from "../hooks/useDarkMode";
|
import { useDarkMode } from "../hooks/useDarkMode";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { useModalStore } from "../context/zustand-store/appStore";
|
import { useModalStore } from "../context/zustand-store/appStore";
|
||||||
import { Logout } from "../partials/auth/Logout";
|
import { Logout } from "../partials/Auth/Logout";
|
||||||
import { useUserProfileStore } from "../context/zustand-store/userStore";
|
import { useUserProfileStore } from "../context/zustand-store/userStore";
|
||||||
import { formatJustDate } from "../utils/formatTime";
|
import { formatJustDate } from "../utils/formatTime";
|
||||||
import bg from "../assets/images/profile-bg.png";
|
import bg from "../assets/images/profile-bg.png";
|
||||||
@@ -46,14 +46,14 @@ const ProfileCard = ({
|
|||||||
return (
|
return (
|
||||||
<Grid
|
<Grid
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"group relative p-4 transition-all duration-500 hover:-translate-y-1 hover:scale-[1.01]"
|
"group relative p-4 transition-all duration-500 hover:-translate-y-1 hover:scale-[1.01]",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Grid className="relative flex items-start gap-4">
|
<Grid className="relative flex items-start gap-4">
|
||||||
<Grid
|
<Grid
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"rounded-xl p-3 shadow-lg group-hover:shadow-xl transition-all duration-500 group-hover:scale-110",
|
"rounded-xl p-3 shadow-lg group-hover:shadow-xl transition-all duration-500 group-hover:scale-110",
|
||||||
"bg-primary-600"
|
"bg-primary-600",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Icon className="h-5 w-5 text-white" />
|
<Icon className="h-5 w-5 text-white" />
|
||||||
@@ -128,12 +128,12 @@ export default function UserProfile() {
|
|||||||
<button
|
<button
|
||||||
onClick={() => setIsDark(!isDark)}
|
onClick={() => setIsDark(!isDark)}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"group relative flex items-center gap-3 rounded-2xl transition-all duration-500 cursor-pointer"
|
"group relative flex items-center gap-3 rounded-2xl transition-all duration-500 cursor-pointer",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Grid
|
<Grid
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"rounded-xl transition-all duration-500 group-hover:scale-110 bg-transparent"
|
"rounded-xl transition-all duration-500 group-hover:scale-110 bg-transparent",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{isDark ? (
|
{isDark ? (
|
||||||
@@ -153,12 +153,12 @@ export default function UserProfile() {
|
|||||||
navigate({ to: path });
|
navigate({ to: path });
|
||||||
}}
|
}}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"group relative flex items-center gap-3 rounded-2xl transition-all duration-500 cursor-pointer"
|
"group relative flex items-center gap-3 rounded-2xl transition-all duration-500 cursor-pointer",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Grid
|
<Grid
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"rounded-xl transition-all duration-500 group-hover:scale-110 bg-transparent"
|
"rounded-xl transition-all duration-500 group-hover:scale-110 bg-transparent",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<BookOpenIcon className="h-5 w-5 text-green-500" />
|
<BookOpenIcon className="h-5 w-5 text-green-500" />
|
||||||
@@ -176,12 +176,12 @@ export default function UserProfile() {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"group relative flex items-center gap-3 rounded-2xl transition-all duration-500 cursor-pointer"
|
"group relative flex items-center gap-3 rounded-2xl transition-all duration-500 cursor-pointer",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Grid
|
<Grid
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"rounded-xl transition-all duration-500 group-hover:scale-110 bg-transparent"
|
"rounded-xl transition-all duration-500 group-hover:scale-110 bg-transparent",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<ArrowLeftStartOnRectangleIcon className="h-5 w-5 text-red-700" />
|
<ArrowLeftStartOnRectangleIcon className="h-5 w-5 text-red-700" />
|
||||||
|
|||||||
4
src/assets/images/svg/admin.svg
Normal file
4
src/assets/images/svg/admin.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg fill="currentColor" width="800px" height="800px" viewBox="0 0 1920 1920" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M276.941 440.584v565.722c0 422.4 374.174 625.468 674.71 788.668l8.02 4.292 8.131-4.292c300.537-163.2 674.71-366.268 674.71-788.668V440.584l-682.84-321.657L276.94 440.584Zm682.73 1479.529c-9.262 0-18.523-2.372-26.993-6.89l-34.9-18.974C588.095 1726.08 164 1495.906 164 1006.306V404.78c0-21.91 12.65-41.788 32.414-51.162L935.727 5.42c15.134-7.228 32.866-7.228 48 0l739.313 348.2c19.765 9.374 32.414 29.252 32.414 51.162v601.525c0 489.6-424.207 719.774-733.779 887.943l-34.899 18.975c-8.47 4.517-17.731 6.889-27.105 6.889Zm467.158-547.652h-313.412l-91.595-91.482v-83.803H905.041v-116.78h-83.69l-58.503-58.504c-1.92.113-3.84.113-5.76.113-176.075 0-319.285-143.21-319.285-319.285 0-176.075 143.21-319.398 319.285-319.398 176.075 0 319.285 143.323 319.285 319.398 0 1.92 0 3.84-.113 5.647l350.57 350.682v313.412Zm-266.654-112.941h153.713v-153.713L958.462 750.155l3.953-37.27c1.017-123.897-91.595-216.621-205.327-216.621S550.744 588.988 550.744 702.72c0 113.845 92.612 206.344 206.344 206.344l47.21-5.309 63.811 63.7h149.873v116.78h116.781v149.986l25.412 25.299Zm-313.4-553.57c0 46.758-37.949 84.706-84.706 84.706-46.758 0-84.706-37.948-84.706-84.706s37.948-84.706 84.706-84.706c46.757 0 84.706 37.948 84.706 84.706" fill-rule="evenodd"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -196,11 +196,11 @@ const AutoComplete: React.FC<AutoCompleteProps> = ({
|
|||||||
if (window.visualViewport) {
|
if (window.visualViewport) {
|
||||||
window.visualViewport.addEventListener(
|
window.visualViewport.addEventListener(
|
||||||
"resize",
|
"resize",
|
||||||
handleVisualViewportResize
|
handleVisualViewportResize,
|
||||||
);
|
);
|
||||||
window.visualViewport.addEventListener(
|
window.visualViewport.addEventListener(
|
||||||
"scroll",
|
"scroll",
|
||||||
handleVisualViewportScroll
|
handleVisualViewportScroll,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const inputElement = inputRef.current;
|
const inputElement = inputRef.current;
|
||||||
@@ -222,11 +222,11 @@ const AutoComplete: React.FC<AutoCompleteProps> = ({
|
|||||||
if (window.visualViewport) {
|
if (window.visualViewport) {
|
||||||
window.visualViewport.removeEventListener(
|
window.visualViewport.removeEventListener(
|
||||||
"resize",
|
"resize",
|
||||||
handleVisualViewportResize
|
handleVisualViewportResize,
|
||||||
);
|
);
|
||||||
window.visualViewport.removeEventListener(
|
window.visualViewport.removeEventListener(
|
||||||
"scroll",
|
"scroll",
|
||||||
handleVisualViewportScroll
|
handleVisualViewportScroll,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const inputElement = inputRef.current;
|
const inputElement = inputRef.current;
|
||||||
@@ -247,7 +247,7 @@ const AutoComplete: React.FC<AutoCompleteProps> = ({
|
|||||||
target.closest(".select-group") && !clickedInsideCurrent;
|
target.closest(".select-group") && !clickedInsideCurrent;
|
||||||
|
|
||||||
const clickedOnPortalDropdown = target.closest(
|
const clickedOnPortalDropdown = target.closest(
|
||||||
`[data-autocomplete-portal="${uniqueId}"]`
|
`[data-autocomplete-portal="${uniqueId}"]`,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (clickedOnAnotherAutocomplete) {
|
if (clickedOnAnotherAutocomplete) {
|
||||||
@@ -318,7 +318,7 @@ const AutoComplete: React.FC<AutoCompleteProps> = ({
|
|||||||
const preventTouchMove = (e: TouchEvent) => {
|
const preventTouchMove = (e: TouchEvent) => {
|
||||||
const target = e.target as HTMLElement;
|
const target = e.target as HTMLElement;
|
||||||
const dropdown = document.querySelector(
|
const dropdown = document.querySelector(
|
||||||
`[data-autocomplete-portal="${uniqueId}"]`
|
`[data-autocomplete-portal="${uniqueId}"]`,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (dropdown) {
|
if (dropdown) {
|
||||||
@@ -326,7 +326,7 @@ const AutoComplete: React.FC<AutoCompleteProps> = ({
|
|||||||
if (touch) {
|
if (touch) {
|
||||||
const elementAtPoint = document.elementFromPoint(
|
const elementAtPoint = document.elementFromPoint(
|
||||||
touch.clientX,
|
touch.clientX,
|
||||||
touch.clientY
|
touch.clientY,
|
||||||
);
|
);
|
||||||
if (
|
if (
|
||||||
elementAtPoint &&
|
elementAtPoint &&
|
||||||
@@ -375,12 +375,12 @@ const AutoComplete: React.FC<AutoCompleteProps> = ({
|
|||||||
setLocalInputValue(value);
|
setLocalInputValue(value);
|
||||||
setIsTyping(true);
|
setIsTyping(true);
|
||||||
const filtered = data.filter((item) =>
|
const filtered = data.filter((item) =>
|
||||||
item.value.toLowerCase().includes(value.toLowerCase())
|
item.value.toLowerCase().includes(value.toLowerCase()),
|
||||||
);
|
);
|
||||||
setFilteredData(filtered);
|
setFilteredData(filtered);
|
||||||
setShowOptions(true);
|
setShowOptions(true);
|
||||||
},
|
},
|
||||||
[data]
|
[data],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleChange = useCallback(
|
const handleChange = useCallback(
|
||||||
@@ -390,7 +390,7 @@ const AutoComplete: React.FC<AutoCompleteProps> = ({
|
|||||||
|
|
||||||
if (onChangeValue && newSelectedKeys.length > 0) {
|
if (onChangeValue && newSelectedKeys.length > 0) {
|
||||||
const selectedItem = data.find(
|
const selectedItem = data.find(
|
||||||
(item) => item.key === newSelectedKeys[0]
|
(item) => item.key === newSelectedKeys[0],
|
||||||
);
|
);
|
||||||
if (selectedItem) {
|
if (selectedItem) {
|
||||||
onChangeValue({
|
onChangeValue({
|
||||||
@@ -400,7 +400,7 @@ const AutoComplete: React.FC<AutoCompleteProps> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[onChange, onChangeValue, data]
|
[onChange, onChangeValue, data],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleOptionClick = useCallback(
|
const handleOptionClick = useCallback(
|
||||||
@@ -430,7 +430,7 @@ const AutoComplete: React.FC<AutoCompleteProps> = ({
|
|||||||
setShowOptions(false);
|
setShowOptions(false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[multiselect, handleChange]
|
[multiselect, handleChange],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleInputClick = useCallback(() => {
|
const handleInputClick = useCallback(() => {
|
||||||
@@ -602,7 +602,7 @@ const AutoComplete: React.FC<AutoCompleteProps> = ({
|
|||||||
>
|
>
|
||||||
{dropdownOptions}
|
{dropdownOptions}
|
||||||
</motion.ul>,
|
</motion.ul>,
|
||||||
document.body
|
document.body,
|
||||||
);
|
);
|
||||||
}, [
|
}, [
|
||||||
showOptions,
|
showOptions,
|
||||||
@@ -638,6 +638,7 @@ const AutoComplete: React.FC<AutoCompleteProps> = ({
|
|||||||
placeholder={title || "انتخاب کنید..."}
|
placeholder={title || "انتخاب کنید..."}
|
||||||
/>
|
/>
|
||||||
<ChevronDownIcon
|
<ChevronDownIcon
|
||||||
|
onClick={handleInputClick}
|
||||||
className={`absolute left-3 text-dark-400 dark:text-dark-100 transition-transform duration-200 ${
|
className={`absolute left-3 text-dark-400 dark:text-dark-100 transition-transform duration-200 ${
|
||||||
showOptions ? "transform rotate-180" : ""
|
showOptions ? "transform rotate-180" : ""
|
||||||
} ${getSizeStyles(size).icon}`}
|
} ${getSizeStyles(size).icon}`}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import React, {
|
|||||||
} from "react";
|
} from "react";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import {
|
import {
|
||||||
|
ArrowUpCircleIcon,
|
||||||
ChartBarIcon,
|
ChartBarIcon,
|
||||||
DocumentChartBarIcon,
|
DocumentChartBarIcon,
|
||||||
EyeIcon,
|
EyeIcon,
|
||||||
@@ -56,7 +57,8 @@ type ButtonProps = {
|
|||||||
| "view"
|
| "view"
|
||||||
| "info"
|
| "info"
|
||||||
| "chart"
|
| "chart"
|
||||||
| "set";
|
| "set"
|
||||||
|
| "share";
|
||||||
page?: string;
|
page?: string;
|
||||||
access?: string;
|
access?: string;
|
||||||
height?: string | number;
|
height?: string | number;
|
||||||
@@ -161,6 +163,10 @@ const Button: React.FC<ButtonProps> = ({
|
|||||||
return (
|
return (
|
||||||
<WrenchIcon className="w-5 h-5 text-purple-400 dark:text-purple-100" />
|
<WrenchIcon className="w-5 h-5 text-purple-400 dark:text-purple-100" />
|
||||||
);
|
);
|
||||||
|
case "share":
|
||||||
|
return (
|
||||||
|
<ArrowUpCircleIcon className="w-5 h-5 text-purple-400 dark:text-purple-100" />
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -181,7 +187,7 @@ const Button: React.FC<ButtonProps> = ({
|
|||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
const finded = profile?.permissions?.find(
|
const finded = profile?.permissions?.find(
|
||||||
(item: any) => item.page_name === page
|
(item: any) => item.page_name === page,
|
||||||
);
|
);
|
||||||
if (finded && finded.page_access.includes(access)) {
|
if (finded && finded.page_access.includes(access)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -237,7 +243,7 @@ const Button: React.FC<ButtonProps> = ({
|
|||||||
sizeStyles.padding,
|
sizeStyles.padding,
|
||||||
sizeStyles.text,
|
sizeStyles.text,
|
||||||
className,
|
className,
|
||||||
checkIsMobile() && !icon && !variant && children && mobileBorders
|
checkIsMobile() && !icon && !variant && children && mobileBorders,
|
||||||
)}
|
)}
|
||||||
style={{ height }}
|
style={{ height }}
|
||||||
>
|
>
|
||||||
@@ -256,7 +262,7 @@ const Button: React.FC<ButtonProps> = ({
|
|||||||
.then((response) => {
|
.then((response) => {
|
||||||
closeBackdrop();
|
closeBackdrop();
|
||||||
const url = window.URL.createObjectURL(
|
const url = window.URL.createObjectURL(
|
||||||
new Blob([response.data])
|
new Blob([response.data]),
|
||||||
);
|
);
|
||||||
|
|
||||||
const link = document.createElement("a");
|
const link = document.createElement("a");
|
||||||
|
|||||||
44
src/components/CheckTrackingCode/CheckTrackingCode.tsx
Normal file
44
src/components/CheckTrackingCode/CheckTrackingCode.tsx
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { ArrowTopRightOnSquareIcon } from "@heroicons/react/24/outline";
|
||||||
|
import { useRef } from "react";
|
||||||
|
|
||||||
|
type CheckTrackingCodeProps = {
|
||||||
|
tracking?: string | number | null;
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function CheckTrackingCode({
|
||||||
|
tracking,
|
||||||
|
className = "",
|
||||||
|
}: CheckTrackingCodeProps) {
|
||||||
|
const formRef = useRef<HTMLFormElement>(null);
|
||||||
|
const safeTracking = tracking ? String(tracking) : "";
|
||||||
|
|
||||||
|
const handleSubmit = () => {
|
||||||
|
if (!safeTracking) return;
|
||||||
|
formRef.current?.submit();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!safeTracking) {
|
||||||
|
return <span>-</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form
|
||||||
|
action="https://e.ivo.ir/Rahgiri/Gidprnt.aspx"
|
||||||
|
method="post"
|
||||||
|
target="_blank"
|
||||||
|
ref={formRef}
|
||||||
|
className={`inline-flex ${className}`}
|
||||||
|
>
|
||||||
|
<input name="gid" type="hidden" value={safeTracking} />
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleSubmit}
|
||||||
|
className="group inline-flex cursor-pointer items-center gap-1.5 rounded-xl border border-primary-500/30 bg-gradient-to-r from-primary-500/10 to-primary-500/20 px-3 py-1.5 text-xs font-medium text-primary-700 transition-all duration-200 hover:from-primary-500/20 hover:to-primary-500/30 hover:shadow-sm dark:border-primary-200/20 dark:from-primary-100/10 dark:to-primary-100/20 dark:text-primary-200"
|
||||||
|
>
|
||||||
|
<span className="tracking-wide">{safeTracking}</span>
|
||||||
|
<ArrowTopRightOnSquareIcon className="h-3.5 w-3.5 transition-transform duration-200 group-hover:-translate-y-0.5 group-hover:translate-x-0.5" />
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
||||||
236
src/components/DocumentOperation/DocumentOperation.tsx
Normal file
236
src/components/DocumentOperation/DocumentOperation.tsx
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
import React, { useRef, useState, useEffect, ChangeEvent } from "react";
|
||||||
|
import {
|
||||||
|
ArrowDownTrayIcon,
|
||||||
|
ArrowUpTrayIcon,
|
||||||
|
CheckCircleIcon,
|
||||||
|
} from "@heroicons/react/24/outline";
|
||||||
|
import api from "../../utils/axios";
|
||||||
|
import { useBackdropStore } from "../../context/zustand-store/appStore";
|
||||||
|
import { useToast } from "../../hooks/useToast";
|
||||||
|
import { useUserProfileStore } from "../../context/zustand-store/userStore";
|
||||||
|
import { RolesContextMenu } from "../Button/RolesContextMenu";
|
||||||
|
|
||||||
|
interface DocumentOperationProps {
|
||||||
|
downloadLink: string;
|
||||||
|
uploadLink: string;
|
||||||
|
validFiles?: string[];
|
||||||
|
payloadKey: string;
|
||||||
|
onUploadSuccess?: () => void;
|
||||||
|
page?: string;
|
||||||
|
access?: string;
|
||||||
|
limitSize?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const buildAcceptString = (extensions: string[]): string => {
|
||||||
|
const mimeTypes: string[] = [];
|
||||||
|
|
||||||
|
extensions.forEach((ext) => {
|
||||||
|
const lower = ext.toLowerCase().replace(".", "");
|
||||||
|
|
||||||
|
if (lower === "img" || lower === "image") {
|
||||||
|
mimeTypes.push("image/*");
|
||||||
|
} else {
|
||||||
|
mimeTypes.push(`.${lower}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return mimeTypes.join(",");
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DocumentOperation = ({
|
||||||
|
downloadLink,
|
||||||
|
uploadLink,
|
||||||
|
validFiles = [],
|
||||||
|
payloadKey,
|
||||||
|
onUploadSuccess,
|
||||||
|
page = "",
|
||||||
|
access = "",
|
||||||
|
limitSize,
|
||||||
|
}: DocumentOperationProps) => {
|
||||||
|
const { openBackdrop, closeBackdrop } = useBackdropStore();
|
||||||
|
const showToast = useToast();
|
||||||
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
const [uploadedFileName, setUploadedFileName] = useState<string>("");
|
||||||
|
const { profile } = useUserProfileStore();
|
||||||
|
const [contextMenu, setContextMenu] = useState<{
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
|
const isAdmin = profile?.role?.type?.key === "ADM";
|
||||||
|
|
||||||
|
const ableToSee = () => {
|
||||||
|
if (!access || !page) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const found = profile?.permissions?.find(
|
||||||
|
(item: any) => item.page_name === page,
|
||||||
|
);
|
||||||
|
if (found && found.page_access.includes(access)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleContextMenu = (e: React.MouseEvent<HTMLDivElement>) => {
|
||||||
|
if (isAdmin && page && access) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
setContextMenu({
|
||||||
|
x: e.clientX,
|
||||||
|
y: e.clientY,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleClick = () => {
|
||||||
|
if (contextMenu) {
|
||||||
|
setContextMenu(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (contextMenu) {
|
||||||
|
document.addEventListener("click", handleClick);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("click", handleClick);
|
||||||
|
};
|
||||||
|
}, [contextMenu]);
|
||||||
|
|
||||||
|
const handleDownload = async () => {
|
||||||
|
if (!downloadLink) return;
|
||||||
|
|
||||||
|
openBackdrop();
|
||||||
|
try {
|
||||||
|
const response = await api.get(downloadLink, {
|
||||||
|
responseType: "blob",
|
||||||
|
});
|
||||||
|
|
||||||
|
const contentDisposition = response.headers["content-disposition"];
|
||||||
|
let fileName = "document";
|
||||||
|
|
||||||
|
if (contentDisposition) {
|
||||||
|
const match = contentDisposition.match(
|
||||||
|
/filename\*?=(?:UTF-8''|"?)([^";]+)/i,
|
||||||
|
);
|
||||||
|
if (match?.[1]) {
|
||||||
|
fileName = decodeURIComponent(match[1].replace(/"/g, ""));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const urlParts = downloadLink.split("/").filter(Boolean);
|
||||||
|
const lastPart = urlParts[urlParts.length - 1];
|
||||||
|
if (lastPart && lastPart.includes(".")) {
|
||||||
|
fileName = lastPart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = window.URL.createObjectURL(new Blob([response.data]));
|
||||||
|
const link = document.createElement("a");
|
||||||
|
link.href = url;
|
||||||
|
link.setAttribute("download", fileName);
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
|
||||||
|
showToast("فایل با موفقیت دانلود شد", "success");
|
||||||
|
} catch {
|
||||||
|
showToast("خطا در دانلود فایل", "error");
|
||||||
|
} finally {
|
||||||
|
closeBackdrop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUploadClick = () => {
|
||||||
|
fileInputRef.current?.click();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFileChange = async (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const file = e.target.files?.[0];
|
||||||
|
if (!file) return;
|
||||||
|
|
||||||
|
if (fileInputRef.current) {
|
||||||
|
fileInputRef.current.value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (limitSize && file.size > limitSize * 1024 * 1024) {
|
||||||
|
showToast(`حداکثر حجم فایل ${limitSize} مگابایت است`, "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
openBackdrop();
|
||||||
|
try {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append(payloadKey, file);
|
||||||
|
|
||||||
|
await api.post(uploadLink, formData, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "multipart/form-data",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
setUploadedFileName(file.name);
|
||||||
|
showToast("فایل با موفقیت آپلود شد", "success");
|
||||||
|
onUploadSuccess?.();
|
||||||
|
} catch {
|
||||||
|
showToast("خطا در آپلود فایل", "error");
|
||||||
|
} finally {
|
||||||
|
closeBackdrop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const acceptString =
|
||||||
|
validFiles.length > 0 ? buildAcceptString(validFiles) : undefined;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
className="inline-flex items-center"
|
||||||
|
onContextMenu={handleContextMenu}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
ref={fileInputRef}
|
||||||
|
onChange={handleFileChange}
|
||||||
|
className="hidden"
|
||||||
|
accept={acceptString}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleDownload}
|
||||||
|
disabled={!downloadLink || !ableToSee()}
|
||||||
|
className="flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-r-lg border border-l-0 border-primary-300 dark:border-dark-400 bg-primary-50 dark:bg-dark-600 text-primary-700 dark:text-primary-200 hover:bg-primary-100 dark:hover:bg-dark-500 transition-colors duration-200 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
>
|
||||||
|
<ArrowDownTrayIcon className="w-4 h-4" />
|
||||||
|
<span>دانلود</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleUploadClick}
|
||||||
|
disabled={!uploadLink || !ableToSee()}
|
||||||
|
className="flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-l-lg border border-primary-300 dark:border-dark-400 bg-primary-600 dark:bg-primary-700 text-white hover:bg-primary-500 dark:hover:bg-primary-800 transition-colors duration-200 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
>
|
||||||
|
{uploadedFileName ? (
|
||||||
|
<CheckCircleIcon className="w-4 h-4 text-green-300" />
|
||||||
|
) : (
|
||||||
|
<ArrowUpTrayIcon className="w-4 h-4" />
|
||||||
|
)}
|
||||||
|
<span>آپلود</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{contextMenu && page && access && (
|
||||||
|
<RolesContextMenu
|
||||||
|
page={page}
|
||||||
|
access={access}
|
||||||
|
position={contextMenu}
|
||||||
|
onClose={() => setContextMenu(null)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -7,6 +7,7 @@ import { getNestedValue } from "../../utils/getNestedValue";
|
|||||||
type FormEnterLocationsProps = {
|
type FormEnterLocationsProps = {
|
||||||
title: string;
|
title: string;
|
||||||
api: string;
|
api: string;
|
||||||
|
size?: "small" | "medium" | "large";
|
||||||
error?: boolean;
|
error?: boolean;
|
||||||
errorMessage?: any;
|
errorMessage?: any;
|
||||||
multiple?: boolean;
|
multiple?: boolean;
|
||||||
@@ -15,6 +16,7 @@ type FormEnterLocationsProps = {
|
|||||||
keyField?: string;
|
keyField?: string;
|
||||||
secondaryKey?: string | string[];
|
secondaryKey?: string | string[];
|
||||||
tertiaryKey?: string | string[];
|
tertiaryKey?: string | string[];
|
||||||
|
quaternaryKey?: string | string[];
|
||||||
valueField?: string | string[];
|
valueField?: string | string[];
|
||||||
valueField2?: string | string[];
|
valueField2?: string | string[];
|
||||||
valueField3?: string | string[];
|
valueField3?: string | string[];
|
||||||
@@ -25,12 +27,14 @@ type FormEnterLocationsProps = {
|
|||||||
valueTemplateProps?: Array<{ [key: string]: "string" | "number" }>;
|
valueTemplateProps?: Array<{ [key: string]: "string" | "number" }>;
|
||||||
groupBy?: string | string[];
|
groupBy?: string | string[];
|
||||||
groupFunction?: (item: any) => string;
|
groupFunction?: (item: any) => string;
|
||||||
|
valueFieldFunction?: (item: any) => any;
|
||||||
selectField?: boolean;
|
selectField?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FormApiBasedAutoComplete = ({
|
export const FormApiBasedAutoComplete = ({
|
||||||
title,
|
title,
|
||||||
api,
|
api,
|
||||||
|
size,
|
||||||
error,
|
error,
|
||||||
errorMessage,
|
errorMessage,
|
||||||
onChange,
|
onChange,
|
||||||
@@ -38,6 +42,7 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
keyField = "id",
|
keyField = "id",
|
||||||
secondaryKey,
|
secondaryKey,
|
||||||
tertiaryKey,
|
tertiaryKey,
|
||||||
|
quaternaryKey,
|
||||||
valueField = "name",
|
valueField = "name",
|
||||||
valueField2,
|
valueField2,
|
||||||
valueField3,
|
valueField3,
|
||||||
@@ -49,6 +54,7 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
valueTemplateProps,
|
valueTemplateProps,
|
||||||
groupBy,
|
groupBy,
|
||||||
groupFunction,
|
groupFunction,
|
||||||
|
valueFieldFunction,
|
||||||
selectField = false,
|
selectField = false,
|
||||||
}: FormEnterLocationsProps) => {
|
}: FormEnterLocationsProps) => {
|
||||||
const [data, setData] = useState<any>([]);
|
const [data, setData] = useState<any>([]);
|
||||||
@@ -79,6 +85,18 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getPrimaryValue = (option: any) => {
|
||||||
|
if (valueFieldFunction) {
|
||||||
|
return valueFieldFunction(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
return valueField === "page"
|
||||||
|
? getFaPermissions(option[valueField])
|
||||||
|
: typeof valueField === "string"
|
||||||
|
? option[valueField]
|
||||||
|
: getNestedValue(option, valueField);
|
||||||
|
};
|
||||||
|
|
||||||
const { data: apiData } = useApiRequest({
|
const { data: apiData } = useApiRequest({
|
||||||
api: api,
|
api: api,
|
||||||
method: "get",
|
method: "get",
|
||||||
@@ -94,7 +112,7 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
if (filterAddress && filterValue) {
|
if (filterAddress && filterValue) {
|
||||||
data = apiData.results?.filter(
|
data = apiData.results?.filter(
|
||||||
(item: any) =>
|
(item: any) =>
|
||||||
!filterValue.includes(getNestedValue(item, filterAddress))
|
!filterValue.includes(getNestedValue(item, filterAddress)),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
data = apiData.results;
|
data = apiData.results;
|
||||||
@@ -111,19 +129,14 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
? option[tertiaryKey]
|
? option[tertiaryKey]
|
||||||
: getNestedValue(option, tertiaryKey)
|
: getNestedValue(option, tertiaryKey)
|
||||||
: undefined,
|
: undefined,
|
||||||
|
quaternaryKey: quaternaryKey
|
||||||
|
? typeof quaternaryKey === "string"
|
||||||
|
? option[quaternaryKey]
|
||||||
|
: getNestedValue(option, quaternaryKey)
|
||||||
|
: undefined,
|
||||||
value: valueTemplate
|
value: valueTemplate
|
||||||
? valueTemplate
|
? valueTemplate
|
||||||
.replace(
|
.replace(/v1/g, formatValue(getPrimaryValue(option), "v1"))
|
||||||
/v1/g,
|
|
||||||
formatValue(
|
|
||||||
valueField === "page"
|
|
||||||
? getFaPermissions(option[valueField])
|
|
||||||
: typeof valueField === "string"
|
|
||||||
? option[valueField]
|
|
||||||
: getNestedValue(option, valueField),
|
|
||||||
"v1"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.replace(
|
.replace(
|
||||||
/v2/g,
|
/v2/g,
|
||||||
formatValue(
|
formatValue(
|
||||||
@@ -132,8 +145,8 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
? option[valueField2]
|
? option[valueField2]
|
||||||
: getNestedValue(option, valueField2)
|
: getNestedValue(option, valueField2)
|
||||||
: "",
|
: "",
|
||||||
"v2"
|
"v2",
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
.replace(
|
.replace(
|
||||||
/v3/g,
|
/v3/g,
|
||||||
@@ -143,16 +156,10 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
? option[valueField3]
|
? option[valueField3]
|
||||||
: getNestedValue(option, valueField3)
|
: getNestedValue(option, valueField3)
|
||||||
: "",
|
: "",
|
||||||
"v3"
|
"v3",
|
||||||
|
),
|
||||||
)
|
)
|
||||||
)
|
: `${getPrimaryValue(option)} ${
|
||||||
: `${
|
|
||||||
valueField === "page"
|
|
||||||
? getFaPermissions(option[valueField])
|
|
||||||
: typeof valueField === "string"
|
|
||||||
? option[valueField]
|
|
||||||
: getNestedValue(option, valueField)
|
|
||||||
} ${
|
|
||||||
valueField2
|
valueField2
|
||||||
? " - " +
|
? " - " +
|
||||||
(typeof valueField2 === "string"
|
(typeof valueField2 === "string"
|
||||||
@@ -208,7 +215,7 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
setData(finalData);
|
setData(finalData);
|
||||||
|
|
||||||
const actualDataItems = finalData.filter(
|
const actualDataItems = finalData.filter(
|
||||||
(item: any) => !item.isGroupHeader && !item.disabled
|
(item: any) => !item.isGroupHeader && !item.disabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (defaultKey !== undefined && defaultKey !== null) {
|
if (defaultKey !== undefined && defaultKey !== null) {
|
||||||
@@ -218,10 +225,10 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
setSelectedKeys([]);
|
setSelectedKeys([]);
|
||||||
} else {
|
} else {
|
||||||
const defaultIds = defaultKey.map((item: any) =>
|
const defaultIds = defaultKey.map((item: any) =>
|
||||||
typeof item === "object" ? item[keyField] : item
|
typeof item === "object" ? item[keyField] : item,
|
||||||
);
|
);
|
||||||
const defaultItems = actualDataItems.filter((item: any) =>
|
const defaultItems = actualDataItems.filter((item: any) =>
|
||||||
defaultIds.includes(item.key)
|
defaultIds.includes(item.key),
|
||||||
);
|
);
|
||||||
setSelectedKeys(defaultItems.map((item: any) => item.key));
|
setSelectedKeys(defaultItems.map((item: any) => item.key));
|
||||||
if (onChange) {
|
if (onChange) {
|
||||||
@@ -237,12 +244,17 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
key3: item?.tertiaryKey,
|
key3: item?.tertiaryKey,
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
|
...(quaternaryKey
|
||||||
|
? {
|
||||||
|
key4: item?.quaternaryKey,
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
};
|
};
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
if (onChangeValue) {
|
if (onChangeValue) {
|
||||||
onChangeValue(
|
onChangeValue(
|
||||||
defaultItems.map((item: any) => item.value.trim())
|
defaultItems.map((item: any) => item.value.trim()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -258,7 +270,7 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
? defaultKey[keyField]
|
? defaultKey[keyField]
|
||||||
: defaultKey;
|
: defaultKey;
|
||||||
const defaultItem = actualDataItems.find(
|
const defaultItem = actualDataItems.find(
|
||||||
(item: any) => item.key === keyToFind
|
(item: any) => item.key === keyToFind,
|
||||||
);
|
);
|
||||||
if (defaultItem) {
|
if (defaultItem) {
|
||||||
setSelectedKeys([keyToFind]);
|
setSelectedKeys([keyToFind]);
|
||||||
@@ -268,6 +280,9 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
key1: defaultItem.key,
|
key1: defaultItem.key,
|
||||||
key2: defaultItem.secondaryKey,
|
key2: defaultItem.secondaryKey,
|
||||||
...(tertiaryKey ? { key3: defaultItem.tertiaryKey } : {}),
|
...(tertiaryKey ? { key3: defaultItem.tertiaryKey } : {}),
|
||||||
|
...(quaternaryKey
|
||||||
|
? { key4: defaultItem.quaternaryKey }
|
||||||
|
: {}),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
onChange(keyToFind);
|
onChange(keyToFind);
|
||||||
@@ -278,6 +293,7 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
key1: defaultItem.key,
|
key1: defaultItem.key,
|
||||||
key2: defaultItem.secondaryKey,
|
key2: defaultItem.secondaryKey,
|
||||||
...(tertiaryKey ? { key3: defaultItem.tertiaryKey } : {}),
|
...(tertiaryKey ? { key3: defaultItem.tertiaryKey } : {}),
|
||||||
|
...(quaternaryKey ? { key4: defaultItem.quaternaryKey } : {}),
|
||||||
value: defaultItem.value.trim(),
|
value: defaultItem.value.trim(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -296,18 +312,18 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
|
|
||||||
const groupItemKeys = groupItems.map((item: any) => item.key);
|
const groupItemKeys = groupItems.map((item: any) => item.key);
|
||||||
const allGroupItemsSelected = groupItemKeys.every((key) =>
|
const allGroupItemsSelected = groupItemKeys.every((key) =>
|
||||||
selectedKeys.includes(key)
|
selectedKeys.includes(key),
|
||||||
);
|
);
|
||||||
|
|
||||||
let newSelectedKeys: (string | number)[];
|
let newSelectedKeys: (string | number)[];
|
||||||
|
|
||||||
if (allGroupItemsSelected) {
|
if (allGroupItemsSelected) {
|
||||||
newSelectedKeys = selectedKeys.filter(
|
newSelectedKeys = selectedKeys.filter(
|
||||||
(key) => !groupItemKeys.includes(key)
|
(key) => !groupItemKeys.includes(key),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const newKeys = groupItemKeys.filter(
|
const newKeys = groupItemKeys.filter(
|
||||||
(key) => !selectedKeys.includes(key)
|
(key) => !selectedKeys.includes(key),
|
||||||
);
|
);
|
||||||
newSelectedKeys = [...selectedKeys, ...newKeys];
|
newSelectedKeys = [...selectedKeys, ...newKeys];
|
||||||
}
|
}
|
||||||
@@ -320,7 +336,7 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
(item: any) =>
|
(item: any) =>
|
||||||
newSelectedKeys.includes(item.key) &&
|
newSelectedKeys.includes(item.key) &&
|
||||||
!item.isGroupHeader &&
|
!item.isGroupHeader &&
|
||||||
!item.disabled
|
!item.disabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (secondaryKey) {
|
if (secondaryKey) {
|
||||||
@@ -329,7 +345,8 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
key1: item.key,
|
key1: item.key,
|
||||||
key2: item.secondaryKey,
|
key2: item.secondaryKey,
|
||||||
...(tertiaryKey ? { key3: item.tertiaryKey } : {}),
|
...(tertiaryKey ? { key3: item.tertiaryKey } : {}),
|
||||||
}))
|
...(quaternaryKey ? { key4: item.quaternaryKey } : {}),
|
||||||
|
})),
|
||||||
);
|
);
|
||||||
if (onChangeValue) {
|
if (onChangeValue) {
|
||||||
onChangeValue(selectedItems.map((item: any) => item.value.trim()));
|
onChangeValue(selectedItems.map((item: any) => item.value.trim()));
|
||||||
@@ -344,6 +361,7 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
<AutoComplete
|
<AutoComplete
|
||||||
multiselect={multiple}
|
multiselect={multiple}
|
||||||
selectField={selectField}
|
selectField={selectField}
|
||||||
|
size={size}
|
||||||
data={data}
|
data={data}
|
||||||
selectedKeys={selectedKeys}
|
selectedKeys={selectedKeys}
|
||||||
onChange={(newSelectedKeys) => {
|
onChange={(newSelectedKeys) => {
|
||||||
@@ -357,7 +375,7 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
(item: any) =>
|
(item: any) =>
|
||||||
newSelectedKeys.includes(item.key) &&
|
newSelectedKeys.includes(item.key) &&
|
||||||
!item.isGroupHeader &&
|
!item.isGroupHeader &&
|
||||||
!item.disabled
|
!item.disabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
onChange(
|
onChange(
|
||||||
@@ -365,16 +383,17 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
key1: item.key,
|
key1: item.key,
|
||||||
key2: item.secondaryKey,
|
key2: item.secondaryKey,
|
||||||
...(tertiaryKey ? { key3: item.tertiaryKey } : {}),
|
...(tertiaryKey ? { key3: item.tertiaryKey } : {}),
|
||||||
}))
|
...(quaternaryKey ? { key4: item.quaternaryKey } : {}),
|
||||||
|
})),
|
||||||
);
|
);
|
||||||
if (onChangeValue) {
|
if (onChangeValue) {
|
||||||
onChangeValue(
|
onChangeValue(
|
||||||
selectedItems.map((item: any) => item.value.trim())
|
selectedItems.map((item: any) => item.value.trim()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const validKeys = newSelectedKeys.filter(
|
const validKeys = newSelectedKeys.filter(
|
||||||
(key) => !String(key).startsWith("__group__")
|
(key) => !String(key).startsWith("__group__"),
|
||||||
);
|
);
|
||||||
onChange(validKeys);
|
onChange(validKeys);
|
||||||
}
|
}
|
||||||
@@ -384,7 +403,7 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
(item: any) =>
|
(item: any) =>
|
||||||
item.key === newSelectedKeys[0] &&
|
item.key === newSelectedKeys[0] &&
|
||||||
!item.isGroupHeader &&
|
!item.isGroupHeader &&
|
||||||
!item.disabled
|
!item.disabled,
|
||||||
);
|
);
|
||||||
if (onChangeValue) {
|
if (onChangeValue) {
|
||||||
onChangeValue({
|
onChangeValue({
|
||||||
@@ -394,6 +413,9 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
...(tertiaryKey
|
...(tertiaryKey
|
||||||
? { key3: selectedItem?.tertiaryKey ?? "" }
|
? { key3: selectedItem?.tertiaryKey ?? "" }
|
||||||
: {}),
|
: {}),
|
||||||
|
...(quaternaryKey
|
||||||
|
? { key4: selectedItem?.quaternaryKey ?? "" }
|
||||||
|
: {}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,6 +424,9 @@ export const FormApiBasedAutoComplete = ({
|
|||||||
key1: selectedItem.key,
|
key1: selectedItem.key,
|
||||||
key2: selectedItem.secondaryKey,
|
key2: selectedItem.secondaryKey,
|
||||||
...(tertiaryKey ? { key3: selectedItem.tertiaryKey } : {}),
|
...(tertiaryKey ? { key3: selectedItem.tertiaryKey } : {}),
|
||||||
|
...(quaternaryKey
|
||||||
|
? { key4: selectedItem.quaternaryKey }
|
||||||
|
: {}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -8,9 +8,16 @@ interface UseUserProfileStore {
|
|||||||
clearProfile: () => void;
|
clearProfile: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserPermission = {
|
||||||
|
page_name: string;
|
||||||
|
domain_name?: string;
|
||||||
|
domain_fa_name?: string;
|
||||||
|
page_access: string[];
|
||||||
|
};
|
||||||
|
|
||||||
const arePermissionsEqual = (
|
const arePermissionsEqual = (
|
||||||
permissions1?: Array<{ page_name: string; page_access: string[] }>,
|
permissions1?: UserPermission[],
|
||||||
permissions2?: Array<{ page_name: string; page_access: string[] }>
|
permissions2?: UserPermission[]
|
||||||
): boolean => {
|
): boolean => {
|
||||||
if (!permissions1 && !permissions2) return true;
|
if (!permissions1 && !permissions2) return true;
|
||||||
if (!permissions1 || !permissions2) return false;
|
if (!permissions1 || !permissions2) return false;
|
||||||
@@ -20,11 +27,13 @@ const arePermissionsEqual = (
|
|||||||
const map2 = new Map<string, Set<string>>();
|
const map2 = new Map<string, Set<string>>();
|
||||||
|
|
||||||
permissions1.forEach((perm) => {
|
permissions1.forEach((perm) => {
|
||||||
map1.set(perm.page_name, new Set(perm.page_access.sort()));
|
const key = `${perm.domain_name || ""}::${perm.domain_fa_name || ""}::${perm.page_name}`;
|
||||||
|
map1.set(key, new Set([...(perm.page_access || [])].sort()));
|
||||||
});
|
});
|
||||||
|
|
||||||
permissions2.forEach((perm) => {
|
permissions2.forEach((perm) => {
|
||||||
map2.set(perm.page_name, new Set(perm.page_access.sort()));
|
const key = `${perm.domain_name || ""}::${perm.domain_fa_name || ""}::${perm.page_name}`;
|
||||||
|
map2.set(key, new Set([...(perm.page_access || [])].sort()));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (map1.size !== map2.size) return false;
|
if (map1.size !== map2.size) return false;
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ export default function Access() {
|
|||||||
pagesInfo.page === 1
|
pagesInfo.page === 1
|
||||||
? i + 1
|
? i + 1
|
||||||
: i + pagesInfo.page_size * (pagesInfo.page - 1) + 1,
|
: i + pagesInfo.page_size * (pagesInfo.page - 1) + 1,
|
||||||
|
item?.domain?.fa_name || item?.page_data?.domain?.fa_name || "-",
|
||||||
item?.name,
|
item?.name,
|
||||||
item?.description,
|
item?.description,
|
||||||
`${getFaPermissions(item?.page)} (${item?.page})`,
|
`${getFaPermissions(item?.page)} (${item?.page})`,
|
||||||
@@ -119,6 +120,7 @@ export default function Access() {
|
|||||||
title="مدیریت دسترسی ها"
|
title="مدیریت دسترسی ها"
|
||||||
columns={[
|
columns={[
|
||||||
"ردیف",
|
"ردیف",
|
||||||
|
"حوزه",
|
||||||
"دسترسی",
|
"دسترسی",
|
||||||
"توضیحات",
|
"توضیحات",
|
||||||
"صفحه",
|
"صفحه",
|
||||||
@@ -3,15 +3,14 @@ import Button from "../../components/Button/Button";
|
|||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../components/Textfeild/Textfeild";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import { zValidateString } from "../../data/getFormTypeErrors";
|
import { zValidateNumber, zValidateString } from "../../data/getFormTypeErrors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../utils/useApiRequest";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../context/zustand-store/appStore";
|
||||||
import AutoComplete from "../../components/AutoComplete/AutoComplete";
|
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import { getFaPermissions } from "../../utils/getFaPermissions";
|
|
||||||
import Checkbox from "../../components/CheckBox/CheckBox";
|
import Checkbox from "../../components/CheckBox/CheckBox";
|
||||||
|
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
|
import { getFaPermissions } from "../../utils/getFaPermissions";
|
||||||
|
|
||||||
type FormValues = z.infer<typeof schema>;
|
type FormValues = z.infer<typeof schema>;
|
||||||
type AddAccessProps = {
|
type AddAccessProps = {
|
||||||
@@ -22,9 +21,8 @@ type AddAccessProps = {
|
|||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
access: zValidateString("نام صفحه"),
|
access: zValidateString("نام صفحه"),
|
||||||
description: zValidateString("توضیحات"),
|
description: zValidateString("توضیحات"),
|
||||||
selectedPageId: z
|
selectedPageId: zValidateNumber("صفحه"),
|
||||||
.array(z.union([z.string(), z.number()]))
|
domain: z.union([z.string(), z.number()]).optional(),
|
||||||
.min(1, { message: "لطفاً یک صفحه انتخاب کنید." }),
|
|
||||||
modify_state: z.boolean(),
|
modify_state: z.boolean(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -32,80 +30,28 @@ export const AddAccess = ({ getData, item }: AddAccessProps) => {
|
|||||||
const showToast = useToast();
|
const showToast = useToast();
|
||||||
const { closeModal } = useModalStore();
|
const { closeModal } = useModalStore();
|
||||||
|
|
||||||
const [selectedKeys, setSelectedKeys] = useState<(string | number)[]>([]);
|
|
||||||
const [data, setData] = useState<any>([]);
|
|
||||||
const [pagesData, setPagesData] = useState<any>(null);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
control,
|
control,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
setValue,
|
setValue,
|
||||||
|
trigger,
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = useForm<FormValues>({
|
} = useForm<FormValues>({
|
||||||
resolver: zodResolver(schema),
|
resolver: zodResolver(schema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
access: item?.name || "",
|
access: item?.name || "",
|
||||||
description: item?.description || "",
|
description: item?.description || "",
|
||||||
selectedPageId: [],
|
selectedPageId: item?.page_data?.id || "",
|
||||||
|
domain: item?.domain?.id || item?.page_data?.domain?.id || "",
|
||||||
modify_state: item?.modify_state || false,
|
modify_state: item?.modify_state || false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (selectedKeys.length > 0) {
|
|
||||||
setValue("selectedPageId", selectedKeys);
|
|
||||||
}
|
|
||||||
}, [selectedKeys, setValue]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (pagesData?.results && item?.page) {
|
|
||||||
const matchingPage = pagesData.results.find(
|
|
||||||
(page: any) => page.name === item.page
|
|
||||||
);
|
|
||||||
if (matchingPage) {
|
|
||||||
const keys = [matchingPage.id];
|
|
||||||
setSelectedKeys(keys);
|
|
||||||
setValue("selectedPageId", keys);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [pagesData, item, setValue]);
|
|
||||||
|
|
||||||
const handleChangeComplete = (newSelectedKeys: (number | string)[]) => {
|
|
||||||
setSelectedKeys(newSelectedKeys);
|
|
||||||
};
|
|
||||||
|
|
||||||
const mutationPages = useApiMutation({
|
|
||||||
api: "/auth/api/v1/page/",
|
|
||||||
method: "get",
|
|
||||||
});
|
|
||||||
|
|
||||||
const mutation = useApiMutation({
|
const mutation = useApiMutation({
|
||||||
api: `/auth/api/v1/permission/${item ? item?.id + "/" : ""}`,
|
api: `/auth/api/v1/permission/${item ? item?.id + "/" : ""}`,
|
||||||
method: item ? "put" : "post",
|
method: item ? "put" : "post",
|
||||||
});
|
});
|
||||||
|
|
||||||
const getPages = async () => {
|
|
||||||
const data = await mutationPages.mutateAsync({
|
|
||||||
page: 1,
|
|
||||||
page_size: 1000,
|
|
||||||
});
|
|
||||||
setPagesData(data);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
getPages();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (pagesData?.results) {
|
|
||||||
const d = pagesData.results.map((page: any) => ({
|
|
||||||
key: page.id,
|
|
||||||
value: `${getFaPermissions(page.name)} (${page.name})`,
|
|
||||||
}));
|
|
||||||
setData(d);
|
|
||||||
}
|
|
||||||
}, [pagesData]);
|
|
||||||
|
|
||||||
const onSubmit = async (data: FormValues) => {
|
const onSubmit = async (data: FormValues) => {
|
||||||
try {
|
try {
|
||||||
await mutation.mutateAsync({
|
await mutation.mutateAsync({
|
||||||
@@ -113,7 +59,8 @@ export const AddAccess = ({ getData, item }: AddAccessProps) => {
|
|||||||
description: data.description,
|
description: data.description,
|
||||||
category: "api",
|
category: "api",
|
||||||
meta: {},
|
meta: {},
|
||||||
page: selectedKeys[0],
|
page: data.selectedPageId,
|
||||||
|
domain: data.domain,
|
||||||
modify_state: data?.modify_state,
|
modify_state: data?.modify_state,
|
||||||
});
|
});
|
||||||
showToast("عملیات با موفقیت انجام شد", "success");
|
showToast("عملیات با موفقیت انجام شد", "success");
|
||||||
@@ -132,17 +79,21 @@ export const AddAccess = ({ getData, item }: AddAccessProps) => {
|
|||||||
<Controller
|
<Controller
|
||||||
name="selectedPageId"
|
name="selectedPageId"
|
||||||
control={control}
|
control={control}
|
||||||
render={({ field }) => (
|
render={() => (
|
||||||
<AutoComplete
|
<FormApiBasedAutoComplete
|
||||||
data={data}
|
defaultKey={item?.page_id}
|
||||||
selectedKeys={selectedKeys}
|
|
||||||
onChange={(newSelectedKeys) => {
|
|
||||||
handleChangeComplete(newSelectedKeys);
|
|
||||||
field.onChange(newSelectedKeys);
|
|
||||||
}}
|
|
||||||
title="انتخاب صفحه"
|
title="انتخاب صفحه"
|
||||||
|
api="auth/api/v1/page/"
|
||||||
|
keyField="id"
|
||||||
|
valueFieldFunction={(item) => getFaPermissions(item?.name)}
|
||||||
|
secondaryKey={["domain", "id"]}
|
||||||
|
onChange={(selectedPage) => {
|
||||||
|
setValue("selectedPageId", selectedPage?.key1 || "");
|
||||||
|
setValue("domain", selectedPage?.key2 || "");
|
||||||
|
trigger("selectedPageId");
|
||||||
|
}}
|
||||||
error={!!errors.selectedPageId}
|
error={!!errors.selectedPageId}
|
||||||
helperText={errors.selectedPageId?.message}
|
errorMessage={errors.selectedPageId?.message}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
125
src/partials/Admin/AddDomain.tsx
Normal file
125
src/partials/Admin/AddDomain.tsx
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import Button from "../../components/Button/Button";
|
||||||
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
|
import Textfield from "../../components/Textfeild/Textfeild";
|
||||||
|
import { useForm, Controller } from "react-hook-form";
|
||||||
|
import {
|
||||||
|
zValidateString,
|
||||||
|
zValidateEnglishString,
|
||||||
|
} from "../../data/getFormTypeErrors";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { useApiMutation } from "../../utils/useApiRequest";
|
||||||
|
import { useToast } from "../../hooks/useToast";
|
||||||
|
import { useModalStore } from "../../context/zustand-store/appStore";
|
||||||
|
import { getToastResponse } from "../../data/getToastResponse";
|
||||||
|
|
||||||
|
const schema = z.object({
|
||||||
|
code: zValidateString("کد حوزه"),
|
||||||
|
name: zValidateEnglishString("نام انگلیسی حوزه"),
|
||||||
|
fa_name: zValidateString("نام حوزه"),
|
||||||
|
});
|
||||||
|
|
||||||
|
type AddDomainProps = {
|
||||||
|
getData: () => void;
|
||||||
|
item?: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
type FormValues = z.infer<typeof schema>;
|
||||||
|
|
||||||
|
export const AddDomain = ({ getData, item }: AddDomainProps) => {
|
||||||
|
const showToast = useToast();
|
||||||
|
const { closeModal } = useModalStore();
|
||||||
|
|
||||||
|
const {
|
||||||
|
control,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm<FormValues>({
|
||||||
|
resolver: zodResolver(schema),
|
||||||
|
defaultValues: {
|
||||||
|
code: item?.code || "",
|
||||||
|
name: item?.name || "",
|
||||||
|
fa_name: item?.fa_name || "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const mutation = useApiMutation({
|
||||||
|
api: `/core/domain/${item ? item?.id + "/" : ""}`,
|
||||||
|
method: item ? "put" : "post",
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = async (data: FormValues) => {
|
||||||
|
try {
|
||||||
|
await mutation.mutateAsync({
|
||||||
|
code: data.code,
|
||||||
|
name: data.name,
|
||||||
|
fa_name: data.fa_name,
|
||||||
|
});
|
||||||
|
showToast(getToastResponse(item, "حوزه"), "success");
|
||||||
|
closeModal();
|
||||||
|
getData();
|
||||||
|
} catch (error: any) {
|
||||||
|
if (error?.status === 403) {
|
||||||
|
showToast(
|
||||||
|
error?.response?.data?.message || "این مورد تکراری است!",
|
||||||
|
"error",
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
showToast(
|
||||||
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
|
"error",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<Grid container column className="gap-2">
|
||||||
|
<Controller
|
||||||
|
name="code"
|
||||||
|
control={control}
|
||||||
|
render={({ field }) => (
|
||||||
|
<Textfield
|
||||||
|
fullWidth
|
||||||
|
placeholder="کد حوزه"
|
||||||
|
value={field.value}
|
||||||
|
onChange={field.onChange}
|
||||||
|
error={!!errors.code}
|
||||||
|
helperText={errors.code?.message}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Controller
|
||||||
|
name="name"
|
||||||
|
control={control}
|
||||||
|
render={({ field }) => (
|
||||||
|
<Textfield
|
||||||
|
fullWidth
|
||||||
|
placeholder="نام انگلیسی حوزه"
|
||||||
|
value={field.value}
|
||||||
|
onChange={field.onChange}
|
||||||
|
error={!!errors.name}
|
||||||
|
helperText={errors.name?.message}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Controller
|
||||||
|
name="fa_name"
|
||||||
|
control={control}
|
||||||
|
render={({ field }) => (
|
||||||
|
<Textfield
|
||||||
|
fullWidth
|
||||||
|
placeholder="نام حوزه"
|
||||||
|
value={field.value}
|
||||||
|
onChange={field.onChange}
|
||||||
|
error={!!errors.fa_name}
|
||||||
|
helperText={errors.fa_name?.message}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Button type="submit">ثبت</Button>
|
||||||
|
</Grid>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -3,14 +3,19 @@ import Button from "../../components/Button/Button";
|
|||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../components/Textfeild/Textfeild";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import { zValidateEnglishString } from "../../data/getFormTypeErrors";
|
import {
|
||||||
|
zValidateEnglishString,
|
||||||
|
zValidateNumber,
|
||||||
|
} from "../../data/getFormTypeErrors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../utils/useApiRequest";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../context/zustand-store/appStore";
|
||||||
|
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
page: zValidateEnglishString("نام صفحه"),
|
page: zValidateEnglishString("نام صفحه"),
|
||||||
|
domain: zValidateNumber("حوزه"),
|
||||||
});
|
});
|
||||||
|
|
||||||
type AddPageProps = {
|
type AddPageProps = {
|
||||||
@@ -27,11 +32,13 @@ export const AddPage = ({ getData, item }: AddPageProps) => {
|
|||||||
const {
|
const {
|
||||||
control,
|
control,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
|
setValue,
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = useForm<FormValues>({
|
} = useForm<FormValues>({
|
||||||
resolver: zodResolver(schema),
|
resolver: zodResolver(schema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
page: item?.name || "",
|
page: item?.name || "",
|
||||||
|
domain: item?.domain?.id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -45,6 +52,7 @@ export const AddPage = ({ getData, item }: AddPageProps) => {
|
|||||||
const payload = {
|
const payload = {
|
||||||
name: data.page,
|
name: data.page,
|
||||||
code: data.page + ".view",
|
code: data.page + ".view",
|
||||||
|
domain: data.domain,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (item) {
|
if (item) {
|
||||||
@@ -69,6 +77,25 @@ export const AddPage = ({ getData, item }: AddPageProps) => {
|
|||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<Grid container column className="gap-2">
|
<Grid container column className="gap-2">
|
||||||
|
<Controller
|
||||||
|
name="domain"
|
||||||
|
control={control}
|
||||||
|
render={() => (
|
||||||
|
<FormApiBasedAutoComplete
|
||||||
|
selectField
|
||||||
|
defaultKey={item?.domain?.id}
|
||||||
|
title="انتخاب حوزه"
|
||||||
|
api="/core/domain/"
|
||||||
|
keyField="id"
|
||||||
|
valueField="fa_name"
|
||||||
|
error={!!errors.domain}
|
||||||
|
errorMessage={errors.domain?.message}
|
||||||
|
onChange={(value) => {
|
||||||
|
setValue("domain", value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
<Controller
|
<Controller
|
||||||
name="page"
|
name="page"
|
||||||
control={control}
|
control={control}
|
||||||
@@ -83,6 +110,7 @@ export const AddPage = ({ getData, item }: AddPageProps) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button type="submit">ثبت</Button>
|
<Button type="submit">ثبت</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
</form>
|
</form>
|
||||||
@@ -52,11 +52,11 @@ export const EditAccess = ({ getData, item }: AddAccessProps) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (accessData?.results && item?.permissions) {
|
if (accessData?.results && item?.permissions) {
|
||||||
const permissionPageAccesses = item.permissions.flatMap(
|
const permissionPageAccesses = item.permissions.flatMap(
|
||||||
(option: any) => option.page_access || []
|
(option: any) => option.page_access || [],
|
||||||
);
|
);
|
||||||
|
|
||||||
const matchingPages = accessData.results.filter((page: any) =>
|
const matchingPages = accessData.results.filter((page: any) =>
|
||||||
permissionPageAccesses.includes(page.name)
|
permissionPageAccesses.includes(page.name),
|
||||||
);
|
);
|
||||||
|
|
||||||
const matchingIds = matchingPages.map((page: any) => page.id);
|
const matchingIds = matchingPages.map((page: any) => page.id);
|
||||||
@@ -32,6 +32,7 @@ export default function Pages() {
|
|||||||
? i + 1
|
? i + 1
|
||||||
: i + pagesInfo.page_size * (pagesInfo.page - 1) + 1,
|
: i + pagesInfo.page_size * (pagesInfo.page - 1) + 1,
|
||||||
getFaPermissions(item?.name),
|
getFaPermissions(item?.name),
|
||||||
|
item?.domain?.fa_name || "-",
|
||||||
item?.name,
|
item?.name,
|
||||||
item?.permissions?.map((option: any) => option.name)?.join(" - "),
|
item?.permissions?.map((option: any) => option.name)?.join(" - "),
|
||||||
<Popover key={i}>
|
<Popover key={i}>
|
||||||
@@ -110,7 +111,7 @@ export default function Pages() {
|
|||||||
count={pagesData?.count || 10}
|
count={pagesData?.count || 10}
|
||||||
isPaginated
|
isPaginated
|
||||||
title="صفحات سامانه"
|
title="صفحات سامانه"
|
||||||
columns={["ردیف", "صفحه", "کلید", "دسترسی ها", "عملیات"]}
|
columns={["ردیف", "صفحه", "حوزه", "کلید", "دسترسی ها", "عملیات"]}
|
||||||
rows={pagesTableData}
|
rows={pagesTableData}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
@@ -29,6 +29,7 @@ export default function UnusedAccess() {
|
|||||||
pagesInfo.page === 1
|
pagesInfo.page === 1
|
||||||
? i + 1
|
? i + 1
|
||||||
: i + pagesInfo.page_size * (pagesInfo.page - 1) + 1,
|
: i + pagesInfo.page_size * (pagesInfo.page - 1) + 1,
|
||||||
|
item?.domain?.fa_name || item?.page_data?.domain?.fa_name || "-",
|
||||||
item?.name,
|
item?.name,
|
||||||
item?.description,
|
item?.description,
|
||||||
`${getFaPermissions(item?.page)} (${item?.page})`,
|
`${getFaPermissions(item?.page)} (${item?.page})`,
|
||||||
@@ -63,7 +64,7 @@ export default function UnusedAccess() {
|
|||||||
count={pagesData?.count || 10}
|
count={pagesData?.count || 10}
|
||||||
isPaginated
|
isPaginated
|
||||||
title="دسترسی های غیر فعال"
|
title="دسترسی های غیر فعال"
|
||||||
columns={["ردیف", "دسترسی", "توضیحات", "صفحه", "عملیات"]}
|
columns={["ردیف", "حوزه", "دسترسی", "توضیحات", "صفحه", "عملیات"]}
|
||||||
rows={pagesTableData}
|
rows={pagesTableData}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import {
|
import {
|
||||||
zValidateAutoComplete,
|
zValidateAutoComplete,
|
||||||
zValidateString,
|
zValidateString,
|
||||||
} from "../../data/getFormTypeErrors";
|
} from "../../../data/getFormTypeErrors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useApiMutation, useApiRequest } from "../../utils/useApiRequest";
|
import { useApiMutation, useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import AutoComplete from "../../components/AutoComplete/AutoComplete";
|
import AutoComplete from "../../../components/AutoComplete/AutoComplete";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
@@ -107,7 +107,7 @@ export const AddActivityType = ({ getData, item }: AddActivityTypeProps) => {
|
|||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Table from "../../components/Table/Table";
|
import Table from "../../../components/Table/Table";
|
||||||
|
|
||||||
interface ChildOrganizationsProps {
|
interface ChildOrganizationsProps {
|
||||||
orgId: number;
|
orgId: number;
|
||||||
@@ -40,7 +40,7 @@ export const ChildOrganizations: React.FC<ChildOrganizationsProps> = ({
|
|||||||
item?.national_unique_id || "-",
|
item?.national_unique_id || "-",
|
||||||
item?.address || "-",
|
item?.address || "-",
|
||||||
];
|
];
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
setChildOrgsTableData(formattedData);
|
setChildOrgsTableData(formattedData);
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import Table from "../../components/Table/Table";
|
import Table from "../../../components/Table/Table";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import { ShowWeight } from "../../components/ShowWeight/ShowWeight";
|
import { ShowWeight } from "../../../components/ShowWeight/ShowWeight";
|
||||||
|
|
||||||
interface QuotaDashboardByProduct {
|
interface QuotaDashboardByProduct {
|
||||||
quotas_count: string;
|
quotas_count: string;
|
||||||
@@ -3,19 +3,19 @@ import {
|
|||||||
zValidateAutoComplete,
|
zValidateAutoComplete,
|
||||||
zValidateAutoCompleteOptional,
|
zValidateAutoCompleteOptional,
|
||||||
zValidateString,
|
zValidateString,
|
||||||
} from "../../data/getFormTypeErrors";
|
} from "../../../data/getFormTypeErrors";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { RadioGroup } from "../../components/RadioButton/RadioGroup";
|
import { RadioGroup } from "../../../components/RadioButton/RadioGroup";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
getData: () => void;
|
getData: () => void;
|
||||||
@@ -82,7 +82,7 @@ export const AddAttribute = ({ getData, item }: Props) => {
|
|||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import {
|
import {
|
||||||
zValidateAutoComplete,
|
zValidateAutoComplete,
|
||||||
@@ -9,17 +9,17 @@ import {
|
|||||||
zValidateNumber,
|
zValidateNumber,
|
||||||
zValidateNumberOptional,
|
zValidateNumberOptional,
|
||||||
zValidateString,
|
zValidateString,
|
||||||
} from "../../data/getFormTypeErrors";
|
} from "../../../data/getFormTypeErrors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
import { RadioGroup } from "../../components/RadioButton/RadioGroup";
|
import { RadioGroup } from "../../../components/RadioButton/RadioGroup";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { checkAccess } from "../../utils/checkAccess";
|
import { checkAccess } from "../../../utils/checkAccess";
|
||||||
import Checkbox from "../../components/CheckBox/CheckBox";
|
import Checkbox from "../../../components/CheckBox/CheckBox";
|
||||||
|
|
||||||
type AddPageProps = {
|
type AddPageProps = {
|
||||||
getData: () => void;
|
getData: () => void;
|
||||||
@@ -47,7 +47,7 @@ export const AddBroker = ({ getData, item }: AddPageProps) => {
|
|||||||
const { closeModal } = useModalStore();
|
const { closeModal } = useModalStore();
|
||||||
|
|
||||||
const [isGlobal, setIsGlobal] = useState(
|
const [isGlobal, setIsGlobal] = useState(
|
||||||
item?.broker_type === "exclusive" ? false : true
|
item?.broker_type === "exclusive" ? false : true,
|
||||||
);
|
);
|
||||||
const [isRequired, setIsRequired] = useState(item ? item?.required : true);
|
const [isRequired, setIsRequired] = useState(item ? item?.required : true);
|
||||||
|
|
||||||
@@ -114,12 +114,12 @@ export const AddBroker = ({ getData, item }: AddPageProps) => {
|
|||||||
if (error?.status === 403) {
|
if (error?.status === 403) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "این مورد تکراری است!",
|
error?.response?.data?.message || "این مورد تکراری است!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import {
|
import {
|
||||||
zValidateAutoComplete,
|
zValidateAutoComplete,
|
||||||
zValidateNumber,
|
zValidateNumber,
|
||||||
zValidateString,
|
zValidateString,
|
||||||
} from "../../data/getFormTypeErrors";
|
} from "../../../data/getFormTypeErrors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
import AutoComplete from "../../components/AutoComplete/AutoComplete";
|
import AutoComplete from "../../../components/AutoComplete/AutoComplete";
|
||||||
import { ImageUploader } from "../../components/ImageUploader/ImageUploader";
|
import { ImageUploader } from "../../../components/ImageUploader/ImageUploader";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
@@ -74,12 +74,12 @@ export const AddProduct = ({ getData, item }: AddPageProps) => {
|
|||||||
if (error?.status === 403) {
|
if (error?.status === 403) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "این مورد تکراری است!",
|
error?.response?.data?.message || "این مورد تکراری است!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import { zValidateString } from "../../data/getFormTypeErrors";
|
import { zValidateString } from "../../../data/getFormTypeErrors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
name: zValidateString("نام "),
|
name: zValidateString("نام "),
|
||||||
@@ -53,12 +53,12 @@ export const AddProductCategory = ({ getData, item }: AddPageProps) => {
|
|||||||
if (error?.status === 403) {
|
if (error?.status === 403) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "این مورد تکراری است!",
|
error?.response?.data?.message || "این مورد تکراری است!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import { zValidateString } from "../../data/getFormTypeErrors";
|
import { zValidateString } from "../../../data/getFormTypeErrors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
unit: zValidateString("نام واحد فروش"),
|
unit: zValidateString("نام واحد فروش"),
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import SVGImage from "../../components/SvgImage/SvgImage";
|
import SVGImage from "../../../components/SvgImage/SvgImage";
|
||||||
import editIcon from "../../assets/images/svg/edit.svg?react";
|
import editIcon from "../../../assets/images/svg/edit.svg?react";
|
||||||
import trashIcon from "../../assets/images/svg/trash.svg?react";
|
import trashIcon from "../../../assets/images/svg/trash.svg?react";
|
||||||
import { AddAttribute } from "./AddAttribute";
|
import { AddAttribute } from "./AddAttribute";
|
||||||
import { NoData } from "../../components/NoData/NoData";
|
import { NoData } from "../../../components/NoData/NoData";
|
||||||
import { PageTitle } from "../../components/PageTitle/PageTitle";
|
import { PageTitle } from "../../../components/PageTitle/PageTitle";
|
||||||
import { checkAccess } from "../../utils/checkAccess";
|
import { checkAccess } from "../../../utils/checkAccess";
|
||||||
import { BooleanQuestion } from "../../components/BooleanQuestion/BooleanQuestion";
|
import { BooleanQuestion } from "../../../components/BooleanQuestion/BooleanQuestion";
|
||||||
|
|
||||||
export const Attributes = () => {
|
export const Attributes = () => {
|
||||||
const { openModal } = useModalStore();
|
const { openModal } = useModalStore();
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import SVGImage from "../../components/SvgImage/SvgImage";
|
import SVGImage from "../../../components/SvgImage/SvgImage";
|
||||||
import editIcon from "../../assets/images/svg/edit.svg?react";
|
import editIcon from "../../../assets/images/svg/edit.svg?react";
|
||||||
import { AddBroker } from "./AddBroker";
|
import { AddBroker } from "./AddBroker";
|
||||||
import { NoData } from "../../components/NoData/NoData";
|
import { NoData } from "../../../components/NoData/NoData";
|
||||||
import { PageTitle } from "../../components/PageTitle/PageTitle";
|
import { PageTitle } from "../../../components/PageTitle/PageTitle";
|
||||||
import { checkAccess } from "../../utils/checkAccess";
|
import { checkAccess } from "../../../utils/checkAccess";
|
||||||
import { BooleanQuestion } from "../../components/BooleanQuestion/BooleanQuestion";
|
import { BooleanQuestion } from "../../../components/BooleanQuestion/BooleanQuestion";
|
||||||
import trashIcon from "../../assets/images/svg/trash.svg?react";
|
import trashIcon from "../../../assets/images/svg/trash.svg?react";
|
||||||
|
|
||||||
export const Brokers = () => {
|
export const Brokers = () => {
|
||||||
const { openModal } = useModalStore();
|
const { openModal } = useModalStore();
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
item: any;
|
item: any;
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import SVGImage from "../../components/SvgImage/SvgImage";
|
import SVGImage from "../../../components/SvgImage/SvgImage";
|
||||||
import editIcon from "../../assets/images/svg/edit.svg?react";
|
import editIcon from "../../../assets/images/svg/edit.svg?react";
|
||||||
import { AddSaleUnit } from "./AddSaleUnit";
|
import { AddSaleUnit } from "./AddSaleUnit";
|
||||||
import { NoData } from "../../components/NoData/NoData";
|
import { NoData } from "../../../components/NoData/NoData";
|
||||||
import { PageTitle } from "../../components/PageTitle/PageTitle";
|
import { PageTitle } from "../../../components/PageTitle/PageTitle";
|
||||||
import { checkAccess } from "../../utils/checkAccess";
|
import { checkAccess } from "../../../utils/checkAccess";
|
||||||
import { BooleanQuestion } from "../../components/BooleanQuestion/BooleanQuestion";
|
import { BooleanQuestion } from "../../../components/BooleanQuestion/BooleanQuestion";
|
||||||
import trashIcon from "../../assets/images/svg/trash.svg?react";
|
import trashIcon from "../../../assets/images/svg/trash.svg?react";
|
||||||
|
|
||||||
export const SaleUnits = () => {
|
export const SaleUnits = () => {
|
||||||
const { openModal } = useModalStore();
|
const { openModal } = useModalStore();
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
import { useParams } from "@tanstack/react-router";
|
import { useParams } from "@tanstack/react-router";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import Table from "../../components/Table/Table";
|
import Table from "../../../components/Table/Table";
|
||||||
import { formatJustDate, formatJustTime } from "../../utils/formatTime";
|
import { formatJustDate, formatJustTime } from "../../../utils/formatTime";
|
||||||
import { ShowWeight } from "../../components/ShowWeight/ShowWeight";
|
import { ShowWeight } from "../../../components/ShowWeight/ShowWeight";
|
||||||
import { Popover } from "../../components/PopOver/PopOver";
|
import { Popover } from "../../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../../components/Tooltip/Tooltip";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { QuotaDistributionEntryInventory } from "../quota/QuotaDistributionEntryInventory";
|
import { QuotaDistributionEntryInventory } from "../quota/QuotaDistributionEntryInventory";
|
||||||
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
import { DeleteButtonForPopOver } from "../../../components/PopOverButtons/PopOverButtons";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { DocumentDownloader } from "../../components/DocumentDownloader/DocumentDownloader";
|
import { DocumentDownloader } from "../../../components/DocumentDownloader/DocumentDownloader";
|
||||||
|
|
||||||
const formatGroupNames = (groups?: any[]) =>
|
const formatGroupNames = (groups?: any[]) =>
|
||||||
groups
|
groups
|
||||||
@@ -20,7 +20,7 @@ const formatGroupNames = (groups?: any[]) =>
|
|||||||
? "روستایی"
|
? "روستایی"
|
||||||
: group === "industrial"
|
: group === "industrial"
|
||||||
? "صنعتی"
|
? "صنعتی"
|
||||||
: "عشایری"
|
: "عشایری",
|
||||||
)
|
)
|
||||||
.join(", ");
|
.join(", ");
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ export const InventoryEntriesList = () => {
|
|||||||
? i + 1
|
? i + 1
|
||||||
: i + pagesInfo.page_size * (pagesInfo.page - 1) + 1,
|
: i + pagesInfo.page_size * (pagesInfo.page - 1) + 1,
|
||||||
`${formatJustDate(item?.create_date)} (${formatJustTime(
|
`${formatJustDate(item?.create_date)} (${formatJustTime(
|
||||||
item?.create_date
|
item?.create_date,
|
||||||
)})`,
|
)})`,
|
||||||
<ShowWeight
|
<ShowWeight
|
||||||
key={i}
|
key={i}
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import { formatJustDate, formatJustTime } from "../../utils/formatTime";
|
import { formatJustDate, formatJustTime } from "../../../utils/formatTime";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Table from "../../components/Table/Table";
|
import Table from "../../../components/Table/Table";
|
||||||
import { ShowWeight } from "../../components/ShowWeight/ShowWeight";
|
import { ShowWeight } from "../../../components/ShowWeight/ShowWeight";
|
||||||
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../../components/Tooltip/Tooltip";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { BarsArrowUpIcon } from "@heroicons/react/24/outline";
|
import { BarsArrowUpIcon } from "@heroicons/react/24/outline";
|
||||||
import { QuotaAllocateToStakeHolders } from "../quota/QuotaAllocateToStakeHolders";
|
import { QuotaAllocateToStakeHolders } from "../quota/QuotaAllocateToStakeHolders";
|
||||||
import { Popover } from "../../components/PopOver/PopOver";
|
import { Popover } from "../../../components/PopOver/PopOver";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
import { DeleteButtonForPopOver } from "../../../components/PopOverButtons/PopOverButtons";
|
||||||
|
|
||||||
export const InventoryStakeHolderAllocations = () => {
|
export const InventoryStakeHolderAllocations = () => {
|
||||||
const { openModal } = useModalStore();
|
const { openModal } = useModalStore();
|
||||||
@@ -34,7 +34,7 @@ export const InventoryStakeHolderAllocations = () => {
|
|||||||
item?.quota_distribution?.distribution_id,
|
item?.quota_distribution?.distribution_id,
|
||||||
item?.quota_distribution?.quota?.quota_id,
|
item?.quota_distribution?.quota?.quota_id,
|
||||||
`${formatJustDate(item?.create_date)} (${formatJustTime(
|
`${formatJustDate(item?.create_date)} (${formatJustTime(
|
||||||
item?.quota_distribution?.create_date
|
item?.quota_distribution?.create_date,
|
||||||
)})`,
|
)})`,
|
||||||
item?.quota_distribution?.assigner_organization?.organization,
|
item?.quota_distribution?.assigner_organization?.organization,
|
||||||
item?.quota_distribution?.assigned_organization?.organization,
|
item?.quota_distribution?.assigned_organization?.organization,
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Popover } from "../../components/PopOver/PopOver";
|
import { Popover } from "../../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../../components/Tooltip/Tooltip";
|
||||||
import { ShowWeight } from "../../components/ShowWeight/ShowWeight";
|
import { ShowWeight } from "../../../components/ShowWeight/ShowWeight";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Table from "../../components/Table/Table";
|
import Table from "../../../components/Table/Table";
|
||||||
import { ListBulletIcon } from "@heroicons/react/24/outline";
|
import { ListBulletIcon } from "@heroicons/react/24/outline";
|
||||||
import { INVENTORY } from "../../routes/paths";
|
import { INVENTORY } from "../../../routes/paths";
|
||||||
import { useNavigate } from "@tanstack/react-router";
|
import { useNavigate } from "@tanstack/react-router";
|
||||||
import { PaginationParameters } from "../../components/PaginationParameters/PaginationParameters";
|
import { PaginationParameters } from "../../../components/PaginationParameters/PaginationParameters";
|
||||||
|
|
||||||
const formatDeviceSaleType = (value?: string) =>
|
const formatDeviceSaleType = (value?: string) =>
|
||||||
value === "all"
|
value === "all"
|
||||||
@@ -63,7 +63,7 @@ export const InventoryWarehouseEntryTab = () => {
|
|||||||
? "روستایی"
|
? "روستایی"
|
||||||
: group === "industrial"
|
: group === "industrial"
|
||||||
? "صنعتی"
|
? "صنعتی"
|
||||||
: "عشایری"
|
: "عشایری",
|
||||||
)
|
)
|
||||||
.join(", ");
|
.join(", ");
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ export const InventoryWarehouseEntryTab = () => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Popover>,
|
</Popover>,
|
||||||
];
|
];
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
setPagesTableData(formattedData);
|
setPagesTableData(formattedData);
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,23 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import {
|
import {
|
||||||
zValidateNumber,
|
zValidateNumber,
|
||||||
zValidateNumberOptional,
|
zValidateNumberOptional,
|
||||||
zValidateString,
|
zValidateString,
|
||||||
} from "../../data/getFormTypeErrors";
|
} from "../../../data/getFormTypeErrors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useDrawerStore } from "../../context/zustand-store/appStore";
|
import { useDrawerStore } from "../../../context/zustand-store/appStore";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import { RadioGroup } from "../../components/RadioButton/RadioGroup";
|
import { RadioGroup } from "../../../components/RadioButton/RadioGroup";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { FormEnterLocations } from "../../components/FormItems/FormEnterLocation";
|
import { FormEnterLocations } from "../../../components/FormItems/FormEnterLocation";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
import { useUserProfileStore } from "../../context/zustand-store/userStore";
|
import { useUserProfileStore } from "../../../context/zustand-store/userStore";
|
||||||
|
|
||||||
type AddPageProps = {
|
type AddPageProps = {
|
||||||
getData: () => void;
|
getData: () => void;
|
||||||
@@ -71,10 +71,10 @@ export const LiveStockAddHerd = ({ getData, item, rancher }: AddPageProps) => {
|
|||||||
const [activityType, setActivityType] = useState(item?.activity || "V");
|
const [activityType, setActivityType] = useState(item?.activity || "V");
|
||||||
|
|
||||||
const [activityState, setActivityState] = useState(
|
const [activityState, setActivityState] = useState(
|
||||||
item ? item?.activity_state : true
|
item ? item?.activity_state : true,
|
||||||
);
|
);
|
||||||
const [operatingLicenseState, setOperatingLicenseState] = useState(
|
const [operatingLicenseState, setOperatingLicenseState] = useState(
|
||||||
item ? item?.operating_license_state : true
|
item ? item?.operating_license_state : true,
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -137,12 +137,12 @@ export const LiveStockAddHerd = ({ getData, item, rancher }: AddPageProps) => {
|
|||||||
if (error?.status === 403) {
|
if (error?.status === 403) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "این مورد تکراری است!",
|
error?.response?.data?.message || "این مورد تکراری است!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import {
|
import {
|
||||||
zValidateNumber,
|
zValidateNumber,
|
||||||
zValidateNumberOptional,
|
zValidateNumberOptional,
|
||||||
zValidateString,
|
zValidateString,
|
||||||
} from "../../data/getFormTypeErrors";
|
} from "../../../data/getFormTypeErrors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useDrawerStore } from "../../context/zustand-store/appStore";
|
import { useDrawerStore } from "../../../context/zustand-store/appStore";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import { RadioGroup } from "../../components/RadioButton/RadioGroup";
|
import { RadioGroup } from "../../../components/RadioButton/RadioGroup";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
import DatePicker from "../../components/date-picker/DatePicker";
|
import DatePicker from "../../../components/date-picker/DatePicker";
|
||||||
|
|
||||||
type AddPageProps = {
|
type AddPageProps = {
|
||||||
getData: () => void;
|
getData: () => void;
|
||||||
@@ -51,7 +51,7 @@ export const LiveStockAddLiveStock = ({
|
|||||||
const { closeDrawer } = useDrawerStore();
|
const { closeDrawer } = useDrawerStore();
|
||||||
const [gender, setGender] = useState(item?.gender || 1);
|
const [gender, setGender] = useState(item?.gender || 1);
|
||||||
const [weightType, setWeightType] = useState(
|
const [weightType, setWeightType] = useState(
|
||||||
item?.weight_type === "H" ? "H" : "L"
|
item?.weight_type === "H" ? "H" : "L",
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -92,12 +92,12 @@ export const LiveStockAddLiveStock = ({
|
|||||||
if (error?.status === 403) {
|
if (error?.status === 403) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "این مورد تکراری است!",
|
error?.response?.data?.message || "این مورد تکراری است!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import {
|
import {
|
||||||
zValidateAutoComplete,
|
zValidateAutoComplete,
|
||||||
@@ -10,16 +10,16 @@ import {
|
|||||||
zValidateNumber,
|
zValidateNumber,
|
||||||
zValidateString,
|
zValidateString,
|
||||||
zValidateStringOptional,
|
zValidateStringOptional,
|
||||||
} from "../../data/getFormTypeErrors";
|
} from "../../../data/getFormTypeErrors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useDrawerStore } from "../../context/zustand-store/appStore";
|
import { useDrawerStore } from "../../../context/zustand-store/appStore";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import { FormEnterLocations } from "../../components/FormItems/FormEnterLocation";
|
import { FormEnterLocations } from "../../../components/FormItems/FormEnterLocation";
|
||||||
import { RadioGroup } from "../../components/RadioButton/RadioGroup";
|
import { RadioGroup } from "../../../components/RadioButton/RadioGroup";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import AutoComplete from "../../components/AutoComplete/AutoComplete";
|
import AutoComplete from "../../../components/AutoComplete/AutoComplete";
|
||||||
|
|
||||||
type AddPageProps = {
|
type AddPageProps = {
|
||||||
getData: () => void;
|
getData: () => void;
|
||||||
@@ -67,7 +67,7 @@ export const LiveStockAddRancher = ({ getData, item }: AddPageProps) => {
|
|||||||
{
|
{
|
||||||
message: "نام واحد حقوقی نمیتواند خالی باشد",
|
message: "نام واحد حقوقی نمیتواند خالی باشد",
|
||||||
path: ["union_name"],
|
path: ["union_name"],
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
.refine(
|
.refine(
|
||||||
(data) => {
|
(data) => {
|
||||||
@@ -79,7 +79,7 @@ export const LiveStockAddRancher = ({ getData, item }: AddPageProps) => {
|
|||||||
{
|
{
|
||||||
message: "شناسه ملی واحد حقوقی نمیتواند خالی باشد",
|
message: "شناسه ملی واحد حقوقی نمیتواند خالی باشد",
|
||||||
path: ["union_code"],
|
path: ["union_code"],
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
type FormValues = z.infer<typeof schema>;
|
type FormValues = z.infer<typeof schema>;
|
||||||
@@ -90,7 +90,7 @@ export const LiveStockAddRancher = ({ getData, item }: AddPageProps) => {
|
|||||||
const [activityType, setActivityType] = useState(item?.activity || "V");
|
const [activityType, setActivityType] = useState(item?.activity || "V");
|
||||||
|
|
||||||
const [rancherHerdType, setRancherHerdType] = useState(
|
const [rancherHerdType, setRancherHerdType] = useState(
|
||||||
item ? item?.without_herd : false
|
item ? item?.without_herd : false,
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -149,12 +149,12 @@ export const LiveStockAddRancher = ({ getData, item }: AddPageProps) => {
|
|||||||
if (error?.status === 403) {
|
if (error?.status === 403) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "این مورد تکراری است!",
|
error?.response?.data?.message || "این مورد تکراری است!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { zValidateAutoComplete } from "../../data/getFormTypeErrors";
|
import { zValidateAutoComplete } from "../../../data/getFormTypeErrors";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
getData: () => void;
|
getData: () => void;
|
||||||
@@ -57,7 +57,7 @@ export const LiveStockAllocateCooperative = ({ getData, item }: Props) => {
|
|||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
TruckIcon,
|
TruckIcon,
|
||||||
UserIcon,
|
UserIcon,
|
||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
|
|
||||||
export const LiveStockHerdDetails = ({
|
export const LiveStockHerdDetails = ({
|
||||||
farmid,
|
farmid,
|
||||||
@@ -23,7 +23,7 @@ export const LiveStockHerdDetails = ({
|
|||||||
Record<number, boolean>
|
Record<number, boolean>
|
||||||
>({});
|
>({});
|
||||||
const [expandedItems, setExpandedItems] = useState<Record<string, boolean>>(
|
const [expandedItems, setExpandedItems] = useState<Record<string, boolean>>(
|
||||||
{}
|
{},
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data: herdData } = useApiRequest({
|
const { data: herdData } = useApiRequest({
|
||||||
@@ -237,12 +237,12 @@ export const LiveStockHerdDetails = ({
|
|||||||
{item?.by_type?.length > 0 &&
|
{item?.by_type?.length > 0 &&
|
||||||
item?.by_type
|
item?.by_type
|
||||||
.filter(
|
.filter(
|
||||||
(animal: any) => animal.weight > 0
|
(animal: any) => animal.weight > 0,
|
||||||
)
|
)
|
||||||
.map(
|
.map(
|
||||||
(
|
(
|
||||||
animal: any,
|
animal: any,
|
||||||
animalIndex: number
|
animalIndex: number,
|
||||||
) => (
|
) => (
|
||||||
<motion.div
|
<motion.div
|
||||||
key={animal.name}
|
key={animal.name}
|
||||||
@@ -261,23 +261,23 @@ export const LiveStockHerdDetails = ({
|
|||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={`text-xs px-2 py-1 rounded-full ${getAnimalTypeColor(
|
className={`text-xs px-2 py-1 rounded-full ${getAnimalTypeColor(
|
||||||
animal.type
|
animal.type,
|
||||||
)}`}
|
)}`}
|
||||||
>
|
>
|
||||||
{getAnimalTypeText(
|
{getAnimalTypeText(
|
||||||
animal.type
|
animal.type,
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-lg font-bold text-gray-800 dark:text-gray-200 mt-2">
|
<p className="text-lg font-bold text-gray-800 dark:text-gray-200 mt-2">
|
||||||
{formatWeight(
|
{formatWeight(
|
||||||
animal.weight
|
animal.weight,
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
)
|
),
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { useToast } from "../../../hooks/useToast";
|
||||||
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
|
import { useApiMutation, useApiRequest } from "../../../utils/useApiRequest";
|
||||||
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
|
import Button from "../../../components/Button/Button";
|
||||||
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
|
import AutoComplete from "../../../components/AutoComplete/AutoComplete";
|
||||||
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
getData: () => void;
|
||||||
|
rancher: string | number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type LivestockEntry = {
|
||||||
|
livestock_type: number;
|
||||||
|
allowed_quantity: number | "";
|
||||||
|
};
|
||||||
|
|
||||||
|
type PlanAllocation = {
|
||||||
|
plan: string | number;
|
||||||
|
plan_name: string;
|
||||||
|
livestock_entries: LivestockEntry[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LiveStockRancherAllocateIncentivePlan = ({
|
||||||
|
getData,
|
||||||
|
rancher,
|
||||||
|
}: Props) => {
|
||||||
|
const showToast = useToast();
|
||||||
|
const { closeModal } = useModalStore();
|
||||||
|
|
||||||
|
const [planAllocations, setPlanAllocations] = useState<PlanAllocation[]>([]);
|
||||||
|
|
||||||
|
const { data: speciesData } = useApiRequest({
|
||||||
|
api: "/livestock/web/api/v1/livestock_type",
|
||||||
|
method: "get",
|
||||||
|
params: { page: 1, page_size: 1000 },
|
||||||
|
queryKey: ["livestock_species"],
|
||||||
|
});
|
||||||
|
|
||||||
|
const speciesOptions = () => {
|
||||||
|
return (
|
||||||
|
speciesData?.results?.map((opt: any) => ({
|
||||||
|
key: opt?.id,
|
||||||
|
value: opt?.name,
|
||||||
|
})) ?? []
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const mutation = useApiMutation({
|
||||||
|
api: "/product/web/api/v1/rancher_incentive_plan/",
|
||||||
|
method: "post",
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const payload = planAllocations.flatMap((pa) =>
|
||||||
|
pa.livestock_entries.map((entry) => ({
|
||||||
|
plan: pa.plan,
|
||||||
|
rancher: Number(rancher),
|
||||||
|
livestock_type: entry.livestock_type,
|
||||||
|
allowed_quantity: Number(entry.allowed_quantity),
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (payload.length === 0) {
|
||||||
|
showToast("لطفاً حداقل یک طرح و نوع دام انتخاب کنید!", "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await mutation.mutateAsync({ data: payload });
|
||||||
|
showToast("تخصیص طرح تشویقی با موفقیت انجام شد", "success");
|
||||||
|
getData();
|
||||||
|
closeModal();
|
||||||
|
} catch (error: any) {
|
||||||
|
showToast(
|
||||||
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
|
"error",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<Grid container column className="gap-3">
|
||||||
|
<FormApiBasedAutoComplete
|
||||||
|
title="انتخاب طرح تشویقی"
|
||||||
|
api="product/web/api/v1/incentive_plan/active_plans/"
|
||||||
|
keyField="id"
|
||||||
|
valueField="name"
|
||||||
|
secondaryKey="name"
|
||||||
|
multiple
|
||||||
|
onChange={(items) => {
|
||||||
|
const selectedItems = Array.isArray(items) ? items : [];
|
||||||
|
setPlanAllocations((prev) =>
|
||||||
|
selectedItems.map((item: any) => {
|
||||||
|
const existing = prev.find((pa) => pa.plan === item.key1);
|
||||||
|
return (
|
||||||
|
existing || {
|
||||||
|
plan: item.key1,
|
||||||
|
plan_name: item.key2,
|
||||||
|
livestock_entries: [],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
onChangeValue={(names) => {
|
||||||
|
setPlanAllocations((prev) =>
|
||||||
|
prev.map((pa, i) => ({
|
||||||
|
...pa,
|
||||||
|
plan_name: names[i] || pa.plan_name,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{planAllocations.map((pa, planIndex) => (
|
||||||
|
<Grid
|
||||||
|
key={pa.plan}
|
||||||
|
container
|
||||||
|
column
|
||||||
|
className="gap-2 border p-3 rounded-lg"
|
||||||
|
>
|
||||||
|
<span className="font-bold text-sm">{pa.plan_name}</span>
|
||||||
|
|
||||||
|
{speciesData?.results && (
|
||||||
|
<AutoComplete
|
||||||
|
data={speciesOptions()}
|
||||||
|
multiselect
|
||||||
|
selectedKeys={pa.livestock_entries.map((e) => e.livestock_type)}
|
||||||
|
onChange={(keys: (string | number)[]) => {
|
||||||
|
setPlanAllocations((prev) => {
|
||||||
|
const next = [...prev];
|
||||||
|
next[planIndex] = {
|
||||||
|
...next[planIndex],
|
||||||
|
livestock_entries: keys.map((k) => {
|
||||||
|
const existing = next[planIndex].livestock_entries.find(
|
||||||
|
(e) => e.livestock_type === k,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
livestock_type: k as number,
|
||||||
|
allowed_quantity: existing?.allowed_quantity ?? "",
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
title="نوع دام"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{pa.livestock_entries.map((entry, entryIndex) => (
|
||||||
|
<Textfield
|
||||||
|
key={entry.livestock_type}
|
||||||
|
fullWidth
|
||||||
|
formattedNumber
|
||||||
|
placeholder={`تعداد مجاز ${
|
||||||
|
speciesOptions().find(
|
||||||
|
(s: any) => s.key === entry.livestock_type,
|
||||||
|
)?.value || ""
|
||||||
|
}`}
|
||||||
|
value={entry.allowed_quantity}
|
||||||
|
onChange={(e) => {
|
||||||
|
setPlanAllocations((prev) => {
|
||||||
|
const next = [...prev];
|
||||||
|
const entries = [...next[planIndex].livestock_entries];
|
||||||
|
entries[entryIndex] = {
|
||||||
|
...entries[entryIndex],
|
||||||
|
allowed_quantity: Number(e.target.value),
|
||||||
|
};
|
||||||
|
next[planIndex] = {
|
||||||
|
...next[planIndex],
|
||||||
|
livestock_entries: entries,
|
||||||
|
};
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<Button
|
||||||
|
disabled={
|
||||||
|
planAllocations.length === 0 ||
|
||||||
|
planAllocations.some((pa) => pa.livestock_entries.length === 0) ||
|
||||||
|
planAllocations.some((pa) =>
|
||||||
|
pa.livestock_entries.some(
|
||||||
|
(e) =>
|
||||||
|
e.allowed_quantity === "" || Number(e.allowed_quantity) <= 0,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
ثبت
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -1,35 +1,35 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import {
|
import {
|
||||||
zValidateBigNumber,
|
zValidateBigNumber,
|
||||||
zValidateNumber,
|
zValidateNumber,
|
||||||
zValidateNumberOptional,
|
zValidateNumberOptional,
|
||||||
zValidateStringOptional,
|
zValidateStringOptional,
|
||||||
} from "../../data/getFormTypeErrors";
|
} from "../../../data/getFormTypeErrors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import Typography from "../../components/Typography/Typography";
|
import Typography from "../../../components/Typography/Typography";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import ansar from "../../assets/images/banks/ansar.png";
|
import ansar from "../../../assets/images/banks/ansar.png";
|
||||||
import ayandeh from "../../assets/images/banks/ayandeh.png";
|
import ayandeh from "../../../assets/images/banks/ayandeh.png";
|
||||||
import eghtesadNovin from "../../assets/images/banks/eghtesad-novin.png";
|
import eghtesadNovin from "../../../assets/images/banks/eghtesad-novin.png";
|
||||||
import keshavarzi from "../../assets/images/banks/keshavarzi.png";
|
import keshavarzi from "../../../assets/images/banks/keshavarzi.png";
|
||||||
import maskan from "../../assets/images/banks/maskan.png";
|
import maskan from "../../../assets/images/banks/maskan.png";
|
||||||
import mehriran from "../../assets/images/banks/mehriran.png";
|
import mehriran from "../../../assets/images/banks/mehriran.png";
|
||||||
import meli from "../../assets/images/banks/meli.png";
|
import meli from "../../../assets/images/banks/meli.png";
|
||||||
import mellat from "../../assets/images/banks/mellat.png";
|
import mellat from "../../../assets/images/banks/mellat.png";
|
||||||
import pasargad from "../../assets/images/banks/pasargad.png";
|
import pasargad from "../../../assets/images/banks/pasargad.png";
|
||||||
import saderat from "../../assets/images/banks/saderat.png";
|
import saderat from "../../../assets/images/banks/saderat.png";
|
||||||
import saman from "../../assets/images/banks/saman.png";
|
import saman from "../../../assets/images/banks/saman.png";
|
||||||
import sina from "../../assets/images/banks/sina.png";
|
import sina from "../../../assets/images/banks/sina.png";
|
||||||
import tejarat from "../../assets/images/banks/tejarat.png";
|
import tejarat from "../../../assets/images/banks/tejarat.png";
|
||||||
import toseeTavon from "../../assets/images/banks/tosee-tavon.png";
|
import toseeTavon from "../../../assets/images/banks/tosee-tavon.png";
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
name: zValidateStringOptional("بانک"),
|
name: zValidateStringOptional("بانک"),
|
||||||
@@ -112,7 +112,7 @@ export const AddCard = ({ getData, item, target }: AddPageProps) => {
|
|||||||
const foundBank =
|
const foundBank =
|
||||||
cardToBank[
|
cardToBank[
|
||||||
Object.keys(cardToBank).find((prefix) =>
|
Object.keys(cardToBank).find((prefix) =>
|
||||||
cardNumber.toString().startsWith(prefix)
|
cardNumber.toString().startsWith(prefix),
|
||||||
) || ""
|
) || ""
|
||||||
];
|
];
|
||||||
if (foundBank) setValue("name", foundBank);
|
if (foundBank) setValue("name", foundBank);
|
||||||
@@ -145,7 +145,7 @@ export const AddCard = ({ getData, item, target }: AddPageProps) => {
|
|||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,36 +1,42 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import {
|
import {
|
||||||
zValidateAutoComplete,
|
zValidateAutoComplete,
|
||||||
zValidateNumber,
|
zValidateNumber,
|
||||||
zValidateNumberOptional,
|
zValidateNumberOptional,
|
||||||
zValidateString,
|
zValidateString,
|
||||||
zValidateStringOptional,
|
} from "../../../data/getFormTypeErrors";
|
||||||
} from "../../data/getFormTypeErrors";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { FormEnterLocations } from "../../components/FormItems/FormEnterLocation";
|
import { FormEnterLocations } from "../../../components/FormItems/FormEnterLocation";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
import AutoComplete from "../../components/AutoComplete/AutoComplete";
|
import AutoComplete from "../../../components/AutoComplete/AutoComplete";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import { useUserProfileStore } from "../../context/zustand-store/userStore";
|
import { useUserProfileStore } from "../../../context/zustand-store/userStore";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import Checkbox from "../../components/CheckBox/CheckBox";
|
import Checkbox from "../../../components/CheckBox/CheckBox";
|
||||||
|
import {
|
||||||
|
ArrowPathIcon,
|
||||||
|
CheckBadgeIcon,
|
||||||
|
PlusIcon,
|
||||||
|
TrashIcon,
|
||||||
|
} from "@heroicons/react/24/outline";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
name: zValidateString("نام سازمان"),
|
name: zValidateString("نام سازمان"),
|
||||||
national_unique_id: zValidateString("شناسه کشوری"),
|
national_unique_id: zValidateString("شناسه کشوری"),
|
||||||
address: zValidateStringOptional("آدرس"),
|
|
||||||
field_of_activity: zValidateAutoComplete("حوزه فعالیت"),
|
field_of_activity: zValidateAutoComplete("حوزه فعالیت"),
|
||||||
province: zValidateNumber("استان"),
|
province: zValidateNumber("استان"),
|
||||||
city: zValidateNumber("شهر"),
|
city: zValidateNumber("شهر"),
|
||||||
organization: zValidateNumberOptional("سازمان"),
|
organization: zValidateNumberOptional("سازمان"),
|
||||||
organizationType: zValidateNumber("سازمان"),
|
organizationType: zValidateNumber("سازمان"),
|
||||||
|
unique_unit_identity: zValidateNumberOptional("شناسه یکتا واحد"),
|
||||||
is_repeatable: z.boolean(),
|
is_repeatable: z.boolean(),
|
||||||
free_visibility_by_scope: z.boolean(),
|
free_visibility_by_scope: z.boolean(),
|
||||||
});
|
});
|
||||||
@@ -75,8 +81,8 @@ export const AddOrganization = ({ getData, item }: AddPageProps) => {
|
|||||||
resolver: zodResolver(schema),
|
resolver: zodResolver(schema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
name: item?.name || "",
|
name: item?.name || "",
|
||||||
address: item?.address || "",
|
|
||||||
national_unique_id: item?.national_unique_id || "",
|
national_unique_id: item?.national_unique_id || "",
|
||||||
|
unique_unit_identity: item?.unique_unit_identity || "",
|
||||||
free_visibility_by_scope: item?.free_visibility_by_scope || false,
|
free_visibility_by_scope: item?.free_visibility_by_scope || false,
|
||||||
field_of_activity:
|
field_of_activity:
|
||||||
item && item?.field_of_activity !== "EM"
|
item && item?.field_of_activity !== "EM"
|
||||||
@@ -95,9 +101,78 @@ export const AddOrganization = ({ getData, item }: AddPageProps) => {
|
|||||||
city: string | any;
|
city: string | any;
|
||||||
}>({ province: "", city: "" });
|
}>({ province: "", city: "" });
|
||||||
|
|
||||||
|
const [addresses, setAddresses] = useState<
|
||||||
|
{ postal_code: string; address: string }[]
|
||||||
|
>(
|
||||||
|
item?.addresses?.length
|
||||||
|
? item.addresses.map((a: any) => ({
|
||||||
|
postal_code: a.postal_code || "",
|
||||||
|
address: a.address || "",
|
||||||
|
}))
|
||||||
|
: [{ postal_code: "", address: "" }],
|
||||||
|
);
|
||||||
|
|
||||||
|
const [isInquiryRequired, setIsInquiryRequired] = useState(false);
|
||||||
|
const [inquiryPassed, setInquiryPassed] = useState(false);
|
||||||
|
const [inquiryLoading, setInquiryLoading] = useState(false);
|
||||||
|
|
||||||
|
const handleAddAddress = () => {
|
||||||
|
setAddresses((prev) => [...prev, { postal_code: "", address: "" }]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRemoveAddress = (index: number) => {
|
||||||
|
setAddresses((prev) => prev.filter((_, i) => i !== index));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddressChange = (
|
||||||
|
index: number,
|
||||||
|
field: "postal_code" | "address",
|
||||||
|
value: string,
|
||||||
|
) => {
|
||||||
|
setAddresses((prev) =>
|
||||||
|
prev.map((item, i) => (i === index ? { ...item, [field]: value } : item)),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInquiry = async () => {
|
||||||
|
const code = getValues("unique_unit_identity");
|
||||||
|
if (!code) {
|
||||||
|
showToast("لطفاً شناسه یکتا واحد را وارد کنید!", "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setInquiryLoading(true);
|
||||||
|
try {
|
||||||
|
await axios.get(
|
||||||
|
`https://rsibackend.rasadyar.com/app/has_code_in_db/?code=${code}`,
|
||||||
|
);
|
||||||
|
setInquiryPassed(true);
|
||||||
|
showToast("استعلام با موفقیت انجام شد!", "success");
|
||||||
|
} catch (error: any) {
|
||||||
|
if (error?.response?.status === 404) {
|
||||||
|
setInquiryPassed(false);
|
||||||
|
showToast("شناسه موجود نیست!", "error");
|
||||||
|
} else {
|
||||||
|
showToast("خطا در استعلام!", "error");
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setInquiryLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const onSubmit = async (data: FormValues) => {
|
const onSubmit = async (data: FormValues) => {
|
||||||
|
if (isInquiryRequired && !data.unique_unit_identity) {
|
||||||
|
showToast("شناسه یکتا واحد الزامی است!", "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isInquiryRequired && !inquiryPassed) {
|
||||||
|
showToast("لطفاً ابتدا استعلام شناسه یکتا واحد را انجام دهید!", "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await mutation.mutateAsync({
|
await mutation.mutateAsync({
|
||||||
|
addresses: addresses.filter(
|
||||||
|
(a) => a.postal_code.trim() || a.address.trim(),
|
||||||
|
),
|
||||||
organization: {
|
organization: {
|
||||||
name: `${data?.name} ${
|
name: `${data?.name} ${
|
||||||
data?.is_repeatable
|
data?.is_repeatable
|
||||||
@@ -111,6 +186,9 @@ export const AddOrganization = ({ getData, item }: AddPageProps) => {
|
|||||||
type: data.organizationType,
|
type: data.organizationType,
|
||||||
}),
|
}),
|
||||||
national_unique_id: data?.national_unique_id,
|
national_unique_id: data?.national_unique_id,
|
||||||
|
...(data?.unique_unit_identity && {
|
||||||
|
unique_unit_identity: data.unique_unit_identity,
|
||||||
|
}),
|
||||||
province: data?.province,
|
province: data?.province,
|
||||||
city: data?.city,
|
city: data?.city,
|
||||||
...(data.organization && {
|
...(data.organization && {
|
||||||
@@ -118,7 +196,6 @@ export const AddOrganization = ({ getData, item }: AddPageProps) => {
|
|||||||
}),
|
}),
|
||||||
field_of_activity: data.field_of_activity[0],
|
field_of_activity: data.field_of_activity[0],
|
||||||
free_visibility_by_scope: data.free_visibility_by_scope,
|
free_visibility_by_scope: data.free_visibility_by_scope,
|
||||||
address: data.address,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
showToast(getToastResponse(item, "سازمان"), "success");
|
showToast(getToastResponse(item, "سازمان"), "success");
|
||||||
@@ -128,12 +205,12 @@ export const AddOrganization = ({ getData, item }: AddPageProps) => {
|
|||||||
if (error?.status === 403) {
|
if (error?.status === 403) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "این سازمان تکراری است!",
|
error?.response?.data?.message || "این سازمان تکراری است!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,6 +230,7 @@ export const AddOrganization = ({ getData, item }: AddPageProps) => {
|
|||||||
keyField="id"
|
keyField="id"
|
||||||
secondaryKey="is_repeatable"
|
secondaryKey="is_repeatable"
|
||||||
tertiaryKey="org_type_field"
|
tertiaryKey="org_type_field"
|
||||||
|
quaternaryKey="key"
|
||||||
valueField="name"
|
valueField="name"
|
||||||
error={!!errors.organizationType}
|
error={!!errors.organizationType}
|
||||||
errorMessage={errors.organizationType?.message}
|
errorMessage={errors.organizationType?.message}
|
||||||
@@ -163,6 +241,12 @@ export const AddOrganization = ({ getData, item }: AddPageProps) => {
|
|||||||
trigger(["organizationType"]);
|
trigger(["organizationType"]);
|
||||||
}}
|
}}
|
||||||
onChangeValue={(r) => {
|
onChangeValue={(r) => {
|
||||||
|
if (r.key4 === "U" || r.key4 === "CO") {
|
||||||
|
setIsInquiryRequired(true);
|
||||||
|
} else {
|
||||||
|
setIsInquiryRequired(false);
|
||||||
|
setInquiryPassed(false);
|
||||||
|
}
|
||||||
if (!r.key2) {
|
if (!r.key2) {
|
||||||
setValue("name", r.value);
|
setValue("name", r.value);
|
||||||
} else {
|
} else {
|
||||||
@@ -223,6 +307,62 @@ export const AddOrganization = ({ getData, item }: AddPageProps) => {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Controller
|
||||||
|
name="unique_unit_identity"
|
||||||
|
control={control}
|
||||||
|
render={({ field }) => (
|
||||||
|
<div className="flex items-start gap-2 w-full">
|
||||||
|
<Textfield
|
||||||
|
fullWidth
|
||||||
|
placeholder={
|
||||||
|
isInquiryRequired
|
||||||
|
? "شناسه یکتا واحد"
|
||||||
|
: "شناسه یکتا واحد (اختیاری)"
|
||||||
|
}
|
||||||
|
value={field.value}
|
||||||
|
onChange={(e) => {
|
||||||
|
field.onChange(e);
|
||||||
|
setInquiryPassed(false);
|
||||||
|
}}
|
||||||
|
error={
|
||||||
|
!!errors.unique_unit_identity ||
|
||||||
|
(isInquiryRequired && !inquiryPassed && !!field.value)
|
||||||
|
}
|
||||||
|
helperText={
|
||||||
|
errors.unique_unit_identity?.message ||
|
||||||
|
(isInquiryRequired && inquiryPassed
|
||||||
|
? "استعلام تایید شده"
|
||||||
|
: undefined)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{isInquiryRequired && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleInquiry}
|
||||||
|
disabled={inquiryLoading || !field.value}
|
||||||
|
className={`shrink-0 flex items-center gap-1 mt-[2px] px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
|
||||||
|
inquiryPassed
|
||||||
|
? "bg-green-500 text-white hover:bg-green-600"
|
||||||
|
: "bg-blue-500 text-white hover:bg-blue-600"
|
||||||
|
} disabled:opacity-50 disabled:cursor-not-allowed`}
|
||||||
|
>
|
||||||
|
{inquiryLoading
|
||||||
|
? "..."
|
||||||
|
: inquiryPassed
|
||||||
|
? "تایید شده"
|
||||||
|
: "استعلام"}
|
||||||
|
|
||||||
|
{inquiryPassed && !inquiryLoading ? (
|
||||||
|
<CheckBadgeIcon className="w-4 h-4 text-white" />
|
||||||
|
) : (
|
||||||
|
<ArrowPathIcon className="w-4 h-4 text-white" />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
<Controller
|
<Controller
|
||||||
name="province"
|
name="province"
|
||||||
control={control}
|
control={control}
|
||||||
@@ -258,7 +398,7 @@ export const AddOrganization = ({ getData, item }: AddPageProps) => {
|
|||||||
defaultKey={item?.parent_organization?.id}
|
defaultKey={item?.parent_organization?.id}
|
||||||
title="سازمان والد (اختیاری)"
|
title="سازمان والد (اختیاری)"
|
||||||
api={`auth/api/v1/organization/organizations_by_province?province=${getValues(
|
api={`auth/api/v1/organization/organizations_by_province?province=${getValues(
|
||||||
"province"
|
"province",
|
||||||
)}`}
|
)}`}
|
||||||
keyField="id"
|
keyField="id"
|
||||||
valueField="name"
|
valueField="name"
|
||||||
@@ -273,20 +413,53 @@ export const AddOrganization = ({ getData, item }: AddPageProps) => {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Controller
|
<div className="flex flex-col gap-2 w-full">
|
||||||
name="address"
|
<div className="flex items-center justify-between">
|
||||||
control={control}
|
<span className="text-sm font-medium text-gray-700">آدرسها</span>
|
||||||
render={({ field }) => (
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleAddAddress}
|
||||||
|
className="flex items-center gap-1 text-sm text-blue-500 dark:text-blue-300 hover:text-blue-800 transition-colors"
|
||||||
|
>
|
||||||
|
<PlusIcon className="w-4 h-4" />
|
||||||
|
افزودن آدرس
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{addresses.map((addr, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className="flex items-start gap-2 p-3 border border-gray-200 rounded-lg"
|
||||||
|
>
|
||||||
|
<div className="flex flex-col gap-2 flex-1">
|
||||||
<Textfield
|
<Textfield
|
||||||
fullWidth
|
fullWidth
|
||||||
placeholder="آدرس (اختیاری)"
|
placeholder="کد پستی"
|
||||||
value={field.value}
|
value={addr.postal_code}
|
||||||
onChange={field.onChange}
|
onChange={(e) =>
|
||||||
error={!!errors.address}
|
handleAddressChange(index, "postal_code", e.target.value)
|
||||||
helperText={errors.address?.message}
|
}
|
||||||
/>
|
/>
|
||||||
|
<Textfield
|
||||||
|
fullWidth
|
||||||
|
placeholder="آدرس"
|
||||||
|
value={addr.address}
|
||||||
|
onChange={(e) =>
|
||||||
|
handleAddressChange(index, "address", e.target.value)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{addresses.length > 1 && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleRemoveAddress(index)}
|
||||||
|
className="mt-2 text-red-500 hover:text-red-700 transition-colors shrink-0"
|
||||||
|
>
|
||||||
|
<TrashIcon className="w-5 h-5" />
|
||||||
|
</button>
|
||||||
)}
|
)}
|
||||||
/>
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
<Controller
|
<Controller
|
||||||
name="free_visibility_by_scope"
|
name="free_visibility_by_scope"
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import {
|
import {
|
||||||
zValidateAutoComplete,
|
zValidateAutoComplete,
|
||||||
zValidateNumberOptional,
|
zValidateNumberOptional,
|
||||||
zValidateString,
|
zValidateString,
|
||||||
} from "../../data/getFormTypeErrors";
|
} from "../../../data/getFormTypeErrors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import AutoComplete from "../../components/AutoComplete/AutoComplete";
|
import AutoComplete from "../../../components/AutoComplete/AutoComplete";
|
||||||
import Checkbox from "../../components/CheckBox/CheckBox";
|
import Checkbox from "../../../components/CheckBox/CheckBox";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
name: zValidateString("نام نهاد "),
|
name: zValidateString("نام نهاد "),
|
||||||
@@ -81,12 +81,12 @@ export const AddOrganizationType = ({ getData, item }: AddPageProps) => {
|
|||||||
if (error?.status === 403) {
|
if (error?.status === 403) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "این مورد تکراری است!",
|
error?.response?.data?.message || "این مورد تکراری است!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import {
|
import {
|
||||||
zValidateAutoComplete,
|
zValidateAutoComplete,
|
||||||
@@ -9,15 +9,15 @@ import {
|
|||||||
zValidateNumberOptional,
|
zValidateNumberOptional,
|
||||||
zValidateString,
|
zValidateString,
|
||||||
zValidateStringOptional,
|
zValidateStringOptional,
|
||||||
} from "../../data/getFormTypeErrors";
|
} from "../../../data/getFormTypeErrors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
import { useFetchProfile } from "../../hooks/useFetchProfile";
|
import { useFetchProfile } from "../../../hooks/useFetchProfile";
|
||||||
import { getFaPermissions } from "../../utils/getFaPermissions";
|
import { getFaPermissions } from "../../../utils/getFaPermissions";
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
name: zValidateString("نام سازمان"),
|
name: zValidateString("نام سازمان"),
|
||||||
@@ -79,7 +79,7 @@ export const AddRole = ({ getData, item }: AddPageProps) => {
|
|||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,23 +6,23 @@ import {
|
|||||||
zValidateNumber,
|
zValidateNumber,
|
||||||
zValidateString,
|
zValidateString,
|
||||||
zValidateStringOptional,
|
zValidateStringOptional,
|
||||||
} from "../../data/getFormTypeErrors";
|
} from "../../../data/getFormTypeErrors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import DatePicker from "../../components/date-picker/DatePicker";
|
import DatePicker from "../../../components/date-picker/DatePicker";
|
||||||
import AutoComplete from "../../components/AutoComplete/AutoComplete";
|
import AutoComplete from "../../../components/AutoComplete/AutoComplete";
|
||||||
import { FormEnterLocations } from "../../components/FormItems/FormEnterLocation";
|
import { FormEnterLocations } from "../../../components/FormItems/FormEnterLocation";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useDrawerStore } from "../../context/zustand-store/appStore";
|
import { useDrawerStore } from "../../../context/zustand-store/appStore";
|
||||||
import Typography from "../../components/Typography/Typography";
|
import Typography from "../../../components/Typography/Typography";
|
||||||
import { useFetchProfile } from "../../hooks/useFetchProfile";
|
import { useFetchProfile } from "../../../hooks/useFetchProfile";
|
||||||
import { useUserProfileStore } from "../../context/zustand-store/userStore";
|
import { useUserProfileStore } from "../../../context/zustand-store/userStore";
|
||||||
|
|
||||||
type AddAccessProps = {
|
type AddAccessProps = {
|
||||||
getData: () => void;
|
getData: () => void;
|
||||||
@@ -71,7 +71,7 @@ export const AddUser = ({ getData, item }: AddAccessProps) => {
|
|||||||
{
|
{
|
||||||
message: "نام واحد حقوقی نمیتواند خالی باشد",
|
message: "نام واحد حقوقی نمیتواند خالی باشد",
|
||||||
path: ["unit_name"],
|
path: ["unit_name"],
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
.refine(
|
.refine(
|
||||||
(data) => {
|
(data) => {
|
||||||
@@ -83,7 +83,7 @@ export const AddUser = ({ getData, item }: AddAccessProps) => {
|
|||||||
{
|
{
|
||||||
message: "شناسه ملی واحد حقوقی نمیتواند خالی باشد",
|
message: "شناسه ملی واحد حقوقی نمیتواند خالی باشد",
|
||||||
path: ["unit_national_id"],
|
path: ["unit_national_id"],
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
type FormValues = z.infer<typeof schema>;
|
type FormValues = z.infer<typeof schema>;
|
||||||
@@ -398,7 +398,7 @@ export const AddUser = ({ getData, item }: AddAccessProps) => {
|
|||||||
defaultKey={item?.organization?.id}
|
defaultKey={item?.organization?.id}
|
||||||
title="سازمان"
|
title="سازمان"
|
||||||
api={`auth/api/v1/organization/organizations_by_province?province=${getValues(
|
api={`auth/api/v1/organization/organizations_by_province?province=${getValues(
|
||||||
"province"
|
"province",
|
||||||
)}`}
|
)}`}
|
||||||
keyField="id"
|
keyField="id"
|
||||||
valueField="name"
|
valueField="name"
|
||||||
@@ -1,24 +1,28 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { AddOrganization } from "./AddOrganization";
|
import { AddOrganization } from "./AddOrganization";
|
||||||
import AutoComplete from "../../components/AutoComplete/AutoComplete";
|
import AutoComplete from "../../../components/AutoComplete/AutoComplete";
|
||||||
import Table from "../../components/Table/Table";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import Table from "../../../components/Table/Table";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
import { DeleteButtonForPopOver } from "../../../components/PopOverButtons/PopOverButtons";
|
||||||
import { Popover } from "../../components/PopOver/PopOver";
|
import { Tooltip } from "../../../components/Tooltip/Tooltip";
|
||||||
|
import { Popover } from "../../../components/PopOver/PopOver";
|
||||||
import { AddCard } from "./AddCard";
|
import { AddCard } from "./AddCard";
|
||||||
import ShowMoreInfo from "../../components/ShowMoreInfo/ShowMoreInfo";
|
import ShowMoreInfo from "../../../components/ShowMoreInfo/ShowMoreInfo";
|
||||||
import { ShowCardsStringList } from "../../components/ShowCardsStringList/ShowCardsStringList";
|
import { ShowCardsStringList } from "../../../components/ShowCardsStringList/ShowCardsStringList";
|
||||||
import { useUserProfileStore } from "../../context/zustand-store/userStore";
|
import { useUserProfileStore } from "../../../context/zustand-store/userStore";
|
||||||
|
|
||||||
export const OrganizationsList = () => {
|
export const OrganizationsList = () => {
|
||||||
const { openModal } = useModalStore();
|
const { openModal } = useModalStore();
|
||||||
const [selectedProvinceKeys, setSelectedProvinceKeys] = useState<
|
const [selectedProvinceKeys, setSelectedProvinceKeys] = useState<
|
||||||
(string | number)[]
|
(string | number)[]
|
||||||
>([]);
|
>([]);
|
||||||
|
const [selectedOrganizationType, setSelectedOrganizationType] = useState<
|
||||||
|
string | number
|
||||||
|
>("");
|
||||||
const [params, setParams] = useState({ page: 1, page_size: 10 });
|
const [params, setParams] = useState({ page: 1, page_size: 10 });
|
||||||
const [tableData, setTableData] = useState([]);
|
const [tableData, setTableData] = useState([]);
|
||||||
const { profile } = useUserProfileStore();
|
const { profile } = useUserProfileStore();
|
||||||
@@ -32,11 +36,16 @@ export const OrganizationsList = () => {
|
|||||||
|
|
||||||
const { data: apiData, refetch } = useApiRequest({
|
const { data: apiData, refetch } = useApiRequest({
|
||||||
api: selectedProvinceKeys?.length
|
api: selectedProvinceKeys?.length
|
||||||
? `/auth/api/v1/organization/organizations_by_province?province=${selectedProvinceKeys[0]}`
|
? `/auth/api/v1/organization/organizations_by_province?province=${selectedProvinceKeys[0]}${selectedOrganizationType ? `&org_type=${selectedOrganizationType}` : ""}`
|
||||||
: "/auth/api/v1/organization/",
|
: `/auth/api/v1/organization/${selectedOrganizationType ? `?org_type=${selectedOrganizationType}` : ""}`,
|
||||||
method: "get",
|
method: "get",
|
||||||
params: params,
|
params: params,
|
||||||
queryKey: ["organizations", params, selectedProvinceKeys],
|
queryKey: [
|
||||||
|
"organizations",
|
||||||
|
params,
|
||||||
|
selectedProvinceKeys,
|
||||||
|
selectedOrganizationType,
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -50,6 +59,7 @@ export const OrganizationsList = () => {
|
|||||||
`${item?.type?.name}`,
|
`${item?.type?.name}`,
|
||||||
item?.parent_organization?.name,
|
item?.parent_organization?.name,
|
||||||
item?.national_unique_id,
|
item?.national_unique_id,
|
||||||
|
item?.unique_unit_identity || "-",
|
||||||
item?.field_of_activity === "CO"
|
item?.field_of_activity === "CO"
|
||||||
? "کشور"
|
? "کشور"
|
||||||
: item?.field_of_activity === "PR"
|
: item?.field_of_activity === "PR"
|
||||||
@@ -59,7 +69,14 @@ export const OrganizationsList = () => {
|
|||||||
: "نامشخص",
|
: "نامشخص",
|
||||||
item?.province?.name,
|
item?.province?.name,
|
||||||
item?.city?.name,
|
item?.city?.name,
|
||||||
item?.address || "-",
|
<ShowMoreInfo
|
||||||
|
key={`address-${i}`}
|
||||||
|
title="آدرسها"
|
||||||
|
disabled={!item?.addresses?.length}
|
||||||
|
data={item?.addresses}
|
||||||
|
columns={["کد پستی", "آدرس"]}
|
||||||
|
accessKeys={[["postal_code"], ["address"]]}
|
||||||
|
/>,
|
||||||
<ShowMoreInfo
|
<ShowMoreInfo
|
||||||
key={i}
|
key={i}
|
||||||
title="اطلاعات حساب"
|
title="اطلاعات حساب"
|
||||||
@@ -151,6 +168,16 @@ export const OrganizationsList = () => {
|
|||||||
ایجاد سازمان
|
ایجاد سازمان
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<FormApiBasedAutoComplete
|
||||||
|
size="small"
|
||||||
|
title="فیلتر نهاد"
|
||||||
|
api={`auth/api/v1/organization-type`}
|
||||||
|
keyField="id"
|
||||||
|
valueField="name"
|
||||||
|
onChange={(r) => setSelectedOrganizationType(r)}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
{profile?.organization?.type?.org_type_field === "CO" && (
|
{profile?.organization?.type?.org_type_field === "CO" && (
|
||||||
<Grid>
|
<Grid>
|
||||||
<AutoComplete
|
<AutoComplete
|
||||||
@@ -177,6 +204,7 @@ export const OrganizationsList = () => {
|
|||||||
"نهاد",
|
"نهاد",
|
||||||
"سازمان والد",
|
"سازمان والد",
|
||||||
"شناسه کشوری",
|
"شناسه کشوری",
|
||||||
|
"شناسه یکتا واحد",
|
||||||
"حوزه فعالیت",
|
"حوزه فعالیت",
|
||||||
"استان",
|
"استان",
|
||||||
"شهر",
|
"شهر",
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import Table from "../../components/Table/Table";
|
import Table from "../../../components/Table/Table";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
import { DeleteButtonForPopOver } from "../../../components/PopOverButtons/PopOverButtons";
|
||||||
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../../components/Tooltip/Tooltip";
|
||||||
import { Popover } from "../../components/PopOver/PopOver";
|
import { Popover } from "../../../components/PopOver/PopOver";
|
||||||
import { AddOrganizationType } from "./AddOrganizationType";
|
import { AddOrganizationType } from "./AddOrganizationType";
|
||||||
import AutoComplete from "../../components/AutoComplete/AutoComplete";
|
import AutoComplete from "../../../components/AutoComplete/AutoComplete";
|
||||||
|
|
||||||
export const OrganizationsTypes = () => {
|
export const OrganizationsTypes = () => {
|
||||||
const { openModal } = useModalStore();
|
const { openModal } = useModalStore();
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import {
|
import {
|
||||||
zValidateAutoComplete,
|
zValidateAutoComplete,
|
||||||
zValidateAutoCompleteOptional,
|
zValidateAutoCompleteOptional,
|
||||||
zValidateEnglishString,
|
zValidateEnglishString,
|
||||||
zValidateString,
|
zValidateString,
|
||||||
} from "../../data/getFormTypeErrors";
|
} from "../../../data/getFormTypeErrors";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import { useUserProfileStore } from "../../context/zustand-store/userStore";
|
import { useUserProfileStore } from "../../../context/zustand-store/userStore";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
|
|
||||||
type AddPosProps = {
|
type AddPosProps = {
|
||||||
getData: () => void;
|
getData: () => void;
|
||||||
@@ -80,12 +80,12 @@ export const AddPos = ({ getData, item }: AddPosProps) => {
|
|||||||
if (error?.status === 403) {
|
if (error?.status === 403) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "این مورد تکراری است!",
|
error?.response?.data?.message || "این مورد تکراری است!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { zValidateAutoComplete } from "../../data/getFormTypeErrors";
|
import { zValidateAutoComplete } from "../../../data/getFormTypeErrors";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
getData: () => void;
|
getData: () => void;
|
||||||
@@ -59,7 +59,7 @@ export const AllocateAccountToBroker = ({ getData, item }: Props) => {
|
|||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import {
|
import {
|
||||||
zValidateAutoComplete,
|
zValidateAutoComplete,
|
||||||
zValidateString,
|
zValidateString,
|
||||||
zValidateStringOptional,
|
zValidateStringOptional,
|
||||||
} from "../../data/getFormTypeErrors";
|
} from "../../../data/getFormTypeErrors";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
import { RadioGroup } from "../../components/RadioButton/RadioGroup";
|
import { RadioGroup } from "../../../components/RadioButton/RadioGroup";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import Divider from "../../components/Divider/Divider";
|
import Divider from "../../../components/Divider/Divider";
|
||||||
|
|
||||||
type AddPosProps = {
|
type AddPosProps = {
|
||||||
getData: () => void;
|
getData: () => void;
|
||||||
@@ -96,12 +96,12 @@ export const AllocatePos = ({ getData, item }: AddPosProps) => {
|
|||||||
if (error?.status === 403) {
|
if (error?.status === 403) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "این مورد تکراری است!",
|
error?.response?.data?.message || "این مورد تکراری است!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { zValidateAutoComplete } from "../../data/getFormTypeErrors";
|
import { zValidateAutoComplete } from "../../../data/getFormTypeErrors";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
|
|
||||||
type AddPosProps = {
|
type AddPosProps = {
|
||||||
getData: () => void;
|
getData: () => void;
|
||||||
@@ -66,12 +66,12 @@ export const PosAllocateOrganizationAccount = ({
|
|||||||
if (error?.status === 403) {
|
if (error?.status === 403) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "این مورد تکراری است!",
|
error?.response?.data?.message || "این مورد تکراری است!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
235
src/partials/LiveStock/quota/AddIncentivePlan.tsx
Normal file
235
src/partials/LiveStock/quota/AddIncentivePlan.tsx
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
import {
|
||||||
|
zValidateAutoComplete,
|
||||||
|
zValidateString,
|
||||||
|
zValidateStringOptional,
|
||||||
|
} from "../../../data/getFormTypeErrors";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { useToast } from "../../../hooks/useToast";
|
||||||
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
|
import { Controller, useForm } from "react-hook-form";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
|
import Button from "../../../components/Button/Button";
|
||||||
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
|
import { RadioGroup } from "../../../components/RadioButton/RadioGroup";
|
||||||
|
import AutoComplete from "../../../components/AutoComplete/AutoComplete";
|
||||||
|
import DatePicker from "../../../components/date-picker/DatePicker";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
getData: () => void;
|
||||||
|
item?: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
const groupTypes = [
|
||||||
|
{ key: "rural", value: "روستایی", disabled: false },
|
||||||
|
{ key: "industrial", value: "صنعتی", disabled: false },
|
||||||
|
{ key: "nomadic", value: "عشایری", disabled: false },
|
||||||
|
];
|
||||||
|
|
||||||
|
const planTypes = [
|
||||||
|
{ key: "ILQ", value: "افزایش سهمیه دام", disabled: false },
|
||||||
|
{ key: "SM", value: "آماری / پایشی", disabled: true },
|
||||||
|
];
|
||||||
|
|
||||||
|
const limitTimeTypes = [
|
||||||
|
{ label: "دارد", value: true },
|
||||||
|
{
|
||||||
|
label: "ندارد",
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const AddIncentivePlan = ({ getData, item }: Props) => {
|
||||||
|
const showToast = useToast();
|
||||||
|
const { closeModal } = useModalStore();
|
||||||
|
|
||||||
|
const [isTimeUnlimited, setIsTimeUnlimited] = useState(
|
||||||
|
item ? item?.is_time_unlimited : false,
|
||||||
|
);
|
||||||
|
|
||||||
|
const schema = z.object({
|
||||||
|
name: zValidateString("نام طرح"),
|
||||||
|
description: zValidateStringOptional("توضیحات"),
|
||||||
|
plan_type: zValidateAutoComplete("نوع طرح"),
|
||||||
|
group: zValidateAutoComplete("گروه"),
|
||||||
|
// is_time_unlimited: zValidateNumber("شهر"),
|
||||||
|
start_date_limit: isTimeUnlimited
|
||||||
|
? zValidateString("تاریخ شروع محدودیت")
|
||||||
|
: zValidateStringOptional("تاریخ شروع محدودیت"),
|
||||||
|
end_date_limit: isTimeUnlimited
|
||||||
|
? zValidateString("تاریخ اتمام محدودیت")
|
||||||
|
: zValidateStringOptional("تاریخ اتمام محدودیت"),
|
||||||
|
});
|
||||||
|
|
||||||
|
type FormValues = z.infer<typeof schema>;
|
||||||
|
|
||||||
|
const {
|
||||||
|
control,
|
||||||
|
handleSubmit,
|
||||||
|
setValue,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm<FormValues>({
|
||||||
|
resolver: zodResolver(schema),
|
||||||
|
defaultValues: {
|
||||||
|
name: item?.name || "",
|
||||||
|
description: item?.description || "",
|
||||||
|
group: item?.group ? [item?.group] : [],
|
||||||
|
plan_type: item?.plan_type ? [item?.plan_type] : [],
|
||||||
|
start_date_limit: item?.start_date_limit,
|
||||||
|
end_date_limit: item?.end_date_limit,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const mutation = useApiMutation({
|
||||||
|
api: `/product/web/api/v1/incentive_plan/${item ? item?.id + "/" : ""}`,
|
||||||
|
method: item ? "put" : "post",
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = async (data: FormValues) => {
|
||||||
|
try {
|
||||||
|
await mutation.mutateAsync({
|
||||||
|
name: data.name,
|
||||||
|
description: data.description,
|
||||||
|
plan_type: data.plan_type[0],
|
||||||
|
group: data.group[0],
|
||||||
|
is_time_unlimited: isTimeUnlimited,
|
||||||
|
...(isTimeUnlimited
|
||||||
|
? {
|
||||||
|
start_date_limit: data?.start_date_limit,
|
||||||
|
end_date_limit: data?.end_date_limit,
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
|
||||||
|
...(item
|
||||||
|
? { registering_organization: item?.registering_organization }
|
||||||
|
: {}),
|
||||||
|
});
|
||||||
|
showToast(getToastResponse(item, ""), "success");
|
||||||
|
getData();
|
||||||
|
closeModal();
|
||||||
|
} catch (error: any) {
|
||||||
|
if (error?.status === 403) {
|
||||||
|
showToast(
|
||||||
|
error?.response?.data?.message || "این مورد تکراری است!",
|
||||||
|
"error",
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
showToast(
|
||||||
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
|
"error",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<Grid container column className="gap-2">
|
||||||
|
<Controller
|
||||||
|
name="name"
|
||||||
|
control={control}
|
||||||
|
render={({ field }) => (
|
||||||
|
<Textfield
|
||||||
|
fullWidth
|
||||||
|
placeholder="نام طرح "
|
||||||
|
value={field.value}
|
||||||
|
onChange={field.onChange}
|
||||||
|
error={!!errors.name}
|
||||||
|
helperText={errors.name?.message}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Controller
|
||||||
|
name="description"
|
||||||
|
control={control}
|
||||||
|
render={({ field }) => (
|
||||||
|
<Textfield
|
||||||
|
fullWidth
|
||||||
|
placeholder="توضیحات (اختیاری)"
|
||||||
|
value={field.value}
|
||||||
|
onChange={field.onChange}
|
||||||
|
error={!!errors.description}
|
||||||
|
helperText={errors.description?.message}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Controller
|
||||||
|
name="plan_type"
|
||||||
|
control={control}
|
||||||
|
render={({ field }) => (
|
||||||
|
<AutoComplete
|
||||||
|
data={planTypes}
|
||||||
|
selectedKeys={field.value}
|
||||||
|
onChange={(keys: (string | number)[]) => {
|
||||||
|
setValue("plan_type", keys);
|
||||||
|
}}
|
||||||
|
error={!!errors.plan_type}
|
||||||
|
helperText={errors.plan_type?.message}
|
||||||
|
title="نوع طرح"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Controller
|
||||||
|
name="group"
|
||||||
|
control={control}
|
||||||
|
render={({ field }) => (
|
||||||
|
<AutoComplete
|
||||||
|
data={groupTypes}
|
||||||
|
selectedKeys={field.value}
|
||||||
|
onChange={(keys: (string | number)[]) => {
|
||||||
|
setValue("group", keys);
|
||||||
|
}}
|
||||||
|
error={!!errors.group}
|
||||||
|
helperText={errors.group?.message}
|
||||||
|
title="گروه"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
groupTitle="محدودیت زمانی"
|
||||||
|
className="mr-2 mt-2"
|
||||||
|
direction="row"
|
||||||
|
options={limitTimeTypes}
|
||||||
|
name="دریافت تعرفه"
|
||||||
|
value={isTimeUnlimited}
|
||||||
|
onChange={(e) =>
|
||||||
|
e.target.value === "true"
|
||||||
|
? setIsTimeUnlimited(true)
|
||||||
|
: setIsTimeUnlimited(false)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{isTimeUnlimited && (
|
||||||
|
<>
|
||||||
|
<DatePicker
|
||||||
|
value={item?.start_date_limit || ""}
|
||||||
|
label="تاریخ شروع طرح"
|
||||||
|
size="medium"
|
||||||
|
onChange={(r) => {
|
||||||
|
setValue("start_date_limit", r);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DatePicker
|
||||||
|
value={item?.end_date_limit || ""}
|
||||||
|
label="تاریخ اتمام طرح"
|
||||||
|
size="medium"
|
||||||
|
onChange={(r) => {
|
||||||
|
setValue("end_date_limit", r);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Button type="submit">ثبت</Button>
|
||||||
|
</Grid>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import { Stepper } from "../../components/Stepper/Stepper";
|
import { Stepper } from "../../../components/Stepper/Stepper";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { QuotaLevel1 } from "./QuotaLevel1";
|
import { QuotaLevel1 } from "./QuotaLevel1";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { QuotaLevel2 } from "./QuotaLevel2";
|
import { QuotaLevel2 } from "./QuotaLevel2";
|
||||||
import { QuotaLevel3 } from "./QuotaLevel3";
|
import { QuotaLevel3 } from "./QuotaLevel3";
|
||||||
import { QuotaLevel4 } from "./QuotaLevel4";
|
import { QuotaLevel4 } from "./QuotaLevel4";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { useToast, useConfirmToast } from "../../hooks/useToast";
|
import { useToast, useConfirmToast } from "../../../hooks/useToast";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
item?: any;
|
item?: any;
|
||||||
@@ -70,7 +70,7 @@ export const AddQuota = ({ item, getData }: Props) => {
|
|||||||
const handleSubmitForm = async () => {
|
const handleSubmitForm = async () => {
|
||||||
if (item && item?.quota_distributed > 0) {
|
if (item && item?.quota_distributed > 0) {
|
||||||
const confirmed = await showConfirmToast(
|
const confirmed = await showConfirmToast(
|
||||||
"اطلاعات ویرایش شده بر روی تمام توزیع های زیر مجموعه اعمال میشود!"
|
"اطلاعات ویرایش شده بر روی تمام توزیع های زیر مجموعه اعمال میشود!",
|
||||||
);
|
);
|
||||||
if (!confirmed) {
|
if (!confirmed) {
|
||||||
return;
|
return;
|
||||||
@@ -96,15 +96,16 @@ export const AddQuota = ({ item, getData }: Props) => {
|
|||||||
broker_data: formData?.broker_data,
|
broker_data: formData?.broker_data,
|
||||||
pos_sale_type: formData?.pos_sale_type,
|
pos_sale_type: formData?.pos_sale_type,
|
||||||
livestock_allocation_data: formData?.livestockTypes?.filter(
|
livestock_allocation_data: formData?.livestockTypes?.filter(
|
||||||
(opt: { quantity_kg: number }) => opt?.quantity_kg > 0
|
(opt: { quantity_kg: number }) => opt?.quantity_kg > 0,
|
||||||
),
|
),
|
||||||
livestock_age_limitations: formData?.livestock_age_limitations,
|
livestock_age_limitations: formData?.livestock_age_limitations,
|
||||||
pre_sale: formData?.pre_sale,
|
pre_sale: formData?.pre_sale,
|
||||||
free_sale: formData?.free_sale,
|
free_sale: formData?.free_sale,
|
||||||
|
one_time_purchase_limit: formData?.one_time_purchase_limit,
|
||||||
};
|
};
|
||||||
|
|
||||||
let filterEmptyKeys = Object.fromEntries(
|
let filterEmptyKeys = Object.fromEntries(
|
||||||
Object.entries(submitData).filter(([, v]) => v != null)
|
Object.entries(submitData).filter(([, v]) => v != null),
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import Table from "../../components/Table/Table";
|
import Table from "../../../components/Table/Table";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Popover } from "../../components/PopOver/PopOver";
|
import { Popover } from "../../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../../components/Tooltip/Tooltip";
|
||||||
import { AddQuota } from "./AddQuota";
|
import { AddQuota } from "./AddQuota";
|
||||||
import { QuotaView } from "./QuotaView";
|
import { QuotaView } from "./QuotaView";
|
||||||
import { PopoverCustomModalOperation } from "../../components/PopOverCustomModalOperation/PopoverCustomModalOperation";
|
import { PopoverCustomModalOperation } from "../../../components/PopOverCustomModalOperation/PopoverCustomModalOperation";
|
||||||
import {
|
import {
|
||||||
ArrowDownOnSquareIcon,
|
ArrowDownOnSquareIcon,
|
||||||
ArrowUpOnSquareIcon,
|
ArrowUpOnSquareIcon,
|
||||||
@@ -16,14 +16,14 @@ import {
|
|||||||
XMarkIcon,
|
XMarkIcon,
|
||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
import { useNavigate } from "@tanstack/react-router";
|
import { useNavigate } from "@tanstack/react-router";
|
||||||
import { QUOTAS } from "../../routes/paths";
|
import { QUOTAS } from "../../../routes/paths";
|
||||||
import { getQuotaTableColumns, getQuotaTableRowData } from "./quotaTableUtils";
|
import { getQuotaTableColumns, getQuotaTableRowData } from "./quotaTableUtils";
|
||||||
import { QuotaAllocateToStakeHolders } from "./QuotaAllocateToStakeHolders";
|
import { QuotaAllocateToStakeHolders } from "./QuotaAllocateToStakeHolders";
|
||||||
import { QuotaDistributionEntryInventory } from "./QuotaDistributionEntryInventory";
|
import { QuotaDistributionEntryInventory } from "./QuotaDistributionEntryInventory";
|
||||||
import { useUserProfileStore } from "../../context/zustand-store/userStore";
|
import { useUserProfileStore } from "../../../context/zustand-store/userStore";
|
||||||
import { TableButton } from "../../components/TableButton/TableButton";
|
import { TableButton } from "../../../components/TableButton/TableButton";
|
||||||
import { QuotaActivesDashboardDetails } from "./QuotaActivesDashboardDetails";
|
import { QuotaActivesDashboardDetails } from "./QuotaActivesDashboardDetails";
|
||||||
import { PaginationParameters } from "../../components/PaginationParameters/PaginationParameters";
|
import { PaginationParameters } from "../../../components/PaginationParameters/PaginationParameters";
|
||||||
|
|
||||||
export const QuotaActives = () => {
|
export const QuotaActives = () => {
|
||||||
const { openModal } = useModalStore();
|
const { openModal } = useModalStore();
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import Table from "../../components/Table/Table";
|
import Table from "../../../components/Table/Table";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import { ShowWeight } from "../../components/ShowWeight/ShowWeight";
|
import { ShowWeight } from "../../../components/ShowWeight/ShowWeight";
|
||||||
|
|
||||||
interface QuotaDashboardByProduct {
|
interface QuotaDashboardByProduct {
|
||||||
quotas_count: string;
|
quotas_count: string;
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import Table from "../../components/Table/Table";
|
import Table from "../../../components/Table/Table";
|
||||||
import { formatJustDate, formatJustTime } from "../../utils/formatTime";
|
import { formatJustDate, formatJustTime } from "../../../utils/formatTime";
|
||||||
import { ShowWeight } from "../../components/ShowWeight/ShowWeight";
|
import { ShowWeight } from "../../../components/ShowWeight/ShowWeight";
|
||||||
import { Popover } from "../../components/PopOver/PopOver";
|
import { Popover } from "../../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../../components/Tooltip/Tooltip";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { QuotaDistribution } from "./QuotaDistribution";
|
import { QuotaDistribution } from "./QuotaDistribution";
|
||||||
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
import { DeleteButtonForPopOver } from "../../../components/PopOverButtons/PopOverButtons";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { PaginationParameters } from "../../components/PaginationParameters/PaginationParameters";
|
import { PaginationParameters } from "../../../components/PaginationParameters/PaginationParameters";
|
||||||
|
|
||||||
export const QuotaAllDistributions = () => {
|
export const QuotaAllDistributions = () => {
|
||||||
const [params, setParams] = useState({ page: 1, page_size: 10 });
|
const [params, setParams] = useState({ page: 1, page_size: 10 });
|
||||||
@@ -55,7 +55,7 @@ export const QuotaAllDistributions = () => {
|
|||||||
item?.quota?.quota_id,
|
item?.quota?.quota_id,
|
||||||
item?.quota?.product?.product,
|
item?.quota?.product?.product,
|
||||||
`${formatJustDate(item?.create_date)} (${formatJustTime(
|
`${formatJustDate(item?.create_date)} (${formatJustTime(
|
||||||
item?.create_date
|
item?.create_date,
|
||||||
)})`,
|
)})`,
|
||||||
`${item?.assigner_organization?.organization} (${item?.creator_info})`,
|
`${item?.assigner_organization?.organization} (${item?.creator_info})`,
|
||||||
item?.assigned_organization?.organization,
|
item?.assigned_organization?.organization,
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import {
|
import {
|
||||||
zValidateNumber,
|
zValidateNumber,
|
||||||
zValidateStringOptional,
|
zValidateStringOptional,
|
||||||
} from "../../data/getFormTypeErrors";
|
} from "../../../data/getFormTypeErrors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
import Typography from "../../components/Typography/Typography";
|
import Typography from "../../../components/Typography/Typography";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
getData: () => void;
|
getData: () => void;
|
||||||
@@ -31,16 +31,16 @@ export const QuotaAllocateToStakeHolders = ({
|
|||||||
|
|
||||||
const cooperativeValue = isSubmit
|
const cooperativeValue = isSubmit
|
||||||
? item?.quota?.brokers?.find(
|
? item?.quota?.brokers?.find(
|
||||||
(broker: any) => broker?.broker_name === "تعاونی"
|
(broker: any) => broker?.broker_name === "تعاونی",
|
||||||
)?.value
|
)?.value
|
||||||
: item?.quota_distribution?.quota?.brokers?.find(
|
: item?.quota_distribution?.quota?.brokers?.find(
|
||||||
(broker: any) => broker?.broker_name === "تعاونی"
|
(broker: any) => broker?.broker_name === "تعاونی",
|
||||||
)?.value;
|
)?.value;
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
share_amount: zValidateNumber("سهم از تعرفه").max(
|
share_amount: zValidateNumber("سهم از تعرفه").max(
|
||||||
cooperativeValue,
|
cooperativeValue,
|
||||||
`سهم از تعرفه نمیتواند بیشتر از ${cooperativeValue?.toLocaleString()} باشد!`
|
`سهم از تعرفه نمیتواند بیشتر از ${cooperativeValue?.toLocaleString()} باشد!`,
|
||||||
),
|
),
|
||||||
organization: zValidateNumber("سازمان"),
|
organization: zValidateNumber("سازمان"),
|
||||||
assigned_organization: zValidateNumber("سازمان تخصیص دهنده"),
|
assigned_organization: zValidateNumber("سازمان تخصیص دهنده"),
|
||||||
@@ -88,7 +88,7 @@ export const QuotaAllocateToStakeHolders = ({
|
|||||||
await mutation.mutateAsync(payload as any);
|
await mutation.mutateAsync(payload as any);
|
||||||
showToast(
|
showToast(
|
||||||
getToastResponse(isSubmit ? false : true, "تخصیص به زیر مجموعه"),
|
getToastResponse(isSubmit ? false : true, "تخصیص به زیر مجموعه"),
|
||||||
"success"
|
"success",
|
||||||
);
|
);
|
||||||
getData();
|
getData();
|
||||||
closeModal();
|
closeModal();
|
||||||
@@ -96,18 +96,18 @@ export const QuotaAllocateToStakeHolders = ({
|
|||||||
if (error?.status === 400) {
|
if (error?.status === 400) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.detail || error?.response?.data?.message,
|
error?.response?.data?.detail || error?.response?.data?.message,
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
closeModal();
|
closeModal();
|
||||||
} else if (error?.status === 403) {
|
} else if (error?.status === 403) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "این مورد تکراری است!",
|
error?.response?.data?.message || "این مورد تکراری است!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import Table from "../../components/Table/Table";
|
import Table from "../../../components/Table/Table";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import { Popover } from "../../components/PopOver/PopOver";
|
import { Popover } from "../../../components/PopOver/PopOver";
|
||||||
import { PopoverCustomModalOperation } from "../../components/PopOverCustomModalOperation/PopoverCustomModalOperation";
|
import { PopoverCustomModalOperation } from "../../../components/PopOverCustomModalOperation/PopoverCustomModalOperation";
|
||||||
import { ArrowUturnDownIcon } from "@heroicons/react/24/outline";
|
import { ArrowUturnDownIcon } from "@heroicons/react/24/outline";
|
||||||
import { getQuotaTableColumns, getQuotaTableRowData } from "./quotaTableUtils";
|
import { getQuotaTableColumns, getQuotaTableRowData } from "./quotaTableUtils";
|
||||||
import { PaginationParameters } from "../../components/PaginationParameters/PaginationParameters";
|
import { PaginationParameters } from "../../../components/PaginationParameters/PaginationParameters";
|
||||||
|
|
||||||
export const QuotaClosed = () => {
|
export const QuotaClosed = () => {
|
||||||
const [pagesInfo, setPagesInfo] = useState({ page: 1, page_size: 10 });
|
const [pagesInfo, setPagesInfo] = useState({ page: 1, page_size: 10 });
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import {
|
import {
|
||||||
zValidateAutoComplete,
|
zValidateAutoComplete,
|
||||||
zValidateNumber,
|
zValidateNumber,
|
||||||
zValidateStringOptional,
|
zValidateStringOptional,
|
||||||
} from "../../data/getFormTypeErrors";
|
} from "../../../data/getFormTypeErrors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import Typography from "../../components/Typography/Typography";
|
import Typography from "../../../components/Typography/Typography";
|
||||||
import Checkbox from "../../components/CheckBox/CheckBox";
|
import Checkbox from "../../../components/CheckBox/CheckBox";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -100,17 +100,17 @@ export const QuotaDistribution = ({
|
|||||||
if (editPriceComponents) {
|
if (editPriceComponents) {
|
||||||
const currentAttributeSum = Object.values(attributeValues).reduce(
|
const currentAttributeSum = Object.values(attributeValues).reduce(
|
||||||
(sum, val) => sum + val,
|
(sum, val) => sum + val,
|
||||||
0
|
0,
|
||||||
);
|
);
|
||||||
const currentBrokerSum = Object.values(brokerValues).reduce(
|
const currentBrokerSum = Object.values(brokerValues).reduce(
|
||||||
(sum, val) => sum + val,
|
(sum, val) => sum + val,
|
||||||
0
|
0,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (currentAttributeSum !== initialAttributeSum) {
|
if (currentAttributeSum !== initialAttributeSum) {
|
||||||
showToast(
|
showToast(
|
||||||
`مجموع قیمت مولفه های قیمت گذاری باید برابر ${initialAttributeSum.toLocaleString()} باشد. مجموع فعلی: ${currentAttributeSum.toLocaleString()}`,
|
`مجموع قیمت مولفه های قیمت گذاری باید برابر ${initialAttributeSum.toLocaleString()} باشد. مجموع فعلی: ${currentAttributeSum.toLocaleString()}`,
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -118,7 +118,7 @@ export const QuotaDistribution = ({
|
|||||||
if (currentBrokerSum !== initialBrokerSum) {
|
if (currentBrokerSum !== initialBrokerSum) {
|
||||||
showToast(
|
showToast(
|
||||||
`مجموع قیمت کارگزاران باید برابر ${initialBrokerSum.toLocaleString()} باشد. مجموع فعلی: ${currentBrokerSum.toLocaleString()}`,
|
`مجموع قیمت کارگزاران باید برابر ${initialBrokerSum.toLocaleString()} باشد. مجموع فعلی: ${currentBrokerSum.toLocaleString()}`,
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -136,7 +136,7 @@ export const QuotaDistribution = ({
|
|||||||
(key) => ({
|
(key) => ({
|
||||||
attribute: parseInt(key),
|
attribute: parseInt(key),
|
||||||
value: attributeValues[parseInt(key)],
|
value: attributeValues[parseInt(key)],
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
payload.broker_data = Object.keys(brokerValues).map((key) => ({
|
payload.broker_data = Object.keys(brokerValues).map((key) => ({
|
||||||
broker: parseInt(key),
|
broker: parseInt(key),
|
||||||
@@ -152,18 +152,18 @@ export const QuotaDistribution = ({
|
|||||||
if (error?.status === 400) {
|
if (error?.status === 400) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.detail || error?.response?.data?.message,
|
error?.response?.data?.detail || error?.response?.data?.message,
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
closeModal();
|
closeModal();
|
||||||
} else if (error?.status === 403) {
|
} else if (error?.status === 403) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "این مورد تکراری است!",
|
error?.response?.data?.message || "این مورد تکراری است!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -273,7 +273,7 @@ export const QuotaDistribution = ({
|
|||||||
className={
|
className={
|
||||||
Object.values(attributeValues).reduce(
|
Object.values(attributeValues).reduce(
|
||||||
(sum, val) => sum + val,
|
(sum, val) => sum + val,
|
||||||
0
|
0,
|
||||||
) === initialAttributeSum
|
) === initialAttributeSum
|
||||||
? "text-green-500"
|
? "text-green-500"
|
||||||
: "text-red-500"
|
: "text-red-500"
|
||||||
@@ -320,7 +320,7 @@ export const QuotaDistribution = ({
|
|||||||
className={
|
className={
|
||||||
Object.values(brokerValues).reduce(
|
Object.values(brokerValues).reduce(
|
||||||
(sum, val) => sum + val,
|
(sum, val) => sum + val,
|
||||||
0
|
0,
|
||||||
) === initialBrokerSum
|
) === initialBrokerSum
|
||||||
? "text-green-500"
|
? "text-green-500"
|
||||||
: "text-red-500"
|
: "text-red-500"
|
||||||
@@ -1,20 +1,20 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import {
|
import {
|
||||||
zValidateBase64Optional,
|
zValidateBase64Optional,
|
||||||
zValidateNumber,
|
zValidateNumber,
|
||||||
zValidateStringOptional,
|
zValidateStringOptional,
|
||||||
} from "../../data/getFormTypeErrors";
|
} from "../../../data/getFormTypeErrors";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useApiMutation } from "../../utils/useApiRequest";
|
import { useApiMutation } from "../../../utils/useApiRequest";
|
||||||
import { useToast } from "../../hooks/useToast";
|
import { useToast } from "../../../hooks/useToast";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { getToastResponse } from "../../data/getToastResponse";
|
import { getToastResponse } from "../../../data/getToastResponse";
|
||||||
import FileUploader from "../../components/FIleUploader/FileUploader";
|
import FileUploader from "../../../components/FIleUploader/FileUploader";
|
||||||
import Typography from "../../components/Typography/Typography";
|
import Typography from "../../../components/Typography/Typography";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
getData: () => void;
|
getData: () => void;
|
||||||
@@ -81,18 +81,18 @@ export const QuotaDistributionEntryInventory = ({
|
|||||||
if (error?.status === 400) {
|
if (error?.status === 400) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.detail || error?.response?.data?.message,
|
error?.response?.data?.detail || error?.response?.data?.message,
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
closeModal();
|
closeModal();
|
||||||
} else if (error?.status === 403) {
|
} else if (error?.status === 403) {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "این مورد تکراری است!",
|
error?.response?.data?.message || "این مورد تکراری است!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showToast(
|
showToast(
|
||||||
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import {
|
import {
|
||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
DocumentTextIcon,
|
DocumentTextIcon,
|
||||||
TruckIcon,
|
TruckIcon,
|
||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
import { formatJustDate } from "../../utils/formatTime";
|
import { formatJustDate } from "../../../utils/formatTime";
|
||||||
|
|
||||||
const formatWeight = (value: number | string | undefined, unit?: string) => {
|
const formatWeight = (value: number | string | undefined, unit?: string) => {
|
||||||
if (value === null || value === undefined || value === "") return "-";
|
if (value === null || value === undefined || value === "") return "-";
|
||||||
@@ -136,7 +136,7 @@ const DistributionNode = ({
|
|||||||
مانده:{" "}
|
مانده:{" "}
|
||||||
{formatWeight(
|
{formatWeight(
|
||||||
item?.warehouse_balance,
|
item?.warehouse_balance,
|
||||||
item?.sale_unit?.unit
|
item?.sale_unit?.unit,
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
<span className="inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium bg-amber-50 text-amber-700 dark:bg-amber-900/30 dark:text-amber-200">
|
<span className="inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium bg-amber-50 text-amber-700 dark:bg-amber-900/30 dark:text-amber-200">
|
||||||
@@ -155,7 +155,7 @@ const DistributionNode = ({
|
|||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setIsWarehouseEntriesExpanded(
|
setIsWarehouseEntriesExpanded(
|
||||||
!isWarehouseEntriesExpanded
|
!isWarehouseEntriesExpanded,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
className="w-full flex items-center justify-between px-1.5 py-1 rounded text-xs text-gray-600 bg-gray-50 hover:bg-gray-100 transition-colors dark:bg-gray-700/40 dark:text-gray-100 dark:hover:bg-gray-700/60"
|
className="w-full flex items-center justify-between px-1.5 py-1 rounded text-xs text-gray-600 bg-gray-50 hover:bg-gray-100 transition-colors dark:bg-gray-700/40 dark:text-gray-100 dark:hover:bg-gray-700/60"
|
||||||
@@ -222,7 +222,7 @@ const DistributionNode = ({
|
|||||||
وزن:{" "}
|
وزن:{" "}
|
||||||
{formatWeight(
|
{formatWeight(
|
||||||
entry?.weight,
|
entry?.weight,
|
||||||
item?.sale_unit?.unit
|
item?.sale_unit?.unit,
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
{entry?.lading_number && (
|
{entry?.lading_number && (
|
||||||
@@ -249,7 +249,7 @@ const DistributionNode = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
)
|
),
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!isLoadingWarehouseEntries &&
|
{!isLoadingWarehouseEntries &&
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
import { useParams } from "@tanstack/react-router";
|
import { useParams } from "@tanstack/react-router";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import Table from "../../components/Table/Table";
|
import Table from "../../../components/Table/Table";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { QuotaDistribution } from "./QuotaDistribution";
|
import { QuotaDistribution } from "./QuotaDistribution";
|
||||||
import { useModalStore } from "../../context/zustand-store/appStore";
|
import { useModalStore } from "../../../context/zustand-store/appStore";
|
||||||
import { Popover } from "../../components/PopOver/PopOver";
|
import { Popover } from "../../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../../components/Tooltip/Tooltip";
|
||||||
import { formatJustDate, formatJustTime } from "../../utils/formatTime";
|
import { formatJustDate, formatJustTime } from "../../../utils/formatTime";
|
||||||
import { DeleteButtonForPopOver } from "../../components/PopOverButtons/PopOverButtons";
|
import { DeleteButtonForPopOver } from "../../../components/PopOverButtons/PopOverButtons";
|
||||||
import { ShowWeight } from "../../components/ShowWeight/ShowWeight";
|
import { ShowWeight } from "../../../components/ShowWeight/ShowWeight";
|
||||||
import {
|
import {
|
||||||
getQuotaDashboardColumns,
|
getQuotaDashboardColumns,
|
||||||
getQuotaDashboardRowData,
|
getQuotaDashboardRowData,
|
||||||
} from "./quotaTableUtils";
|
} from "./quotaTableUtils";
|
||||||
import { QuotaDistributionOverview } from "./QuotaDistributionOverview";
|
import { QuotaDistributionOverview } from "./QuotaDistributionOverview";
|
||||||
import { useUserProfileStore } from "../../context/zustand-store/userStore";
|
import { useUserProfileStore } from "../../../context/zustand-store/userStore";
|
||||||
|
|
||||||
export const QuotaDistributions = () => {
|
export const QuotaDistributions = () => {
|
||||||
const params = useParams({ strict: false });
|
const params = useParams({ strict: false });
|
||||||
@@ -49,7 +49,7 @@ export const QuotaDistributions = () => {
|
|||||||
: i + pagesInfo.page_size * (pagesInfo.page - 1) + 1,
|
: i + pagesInfo.page_size * (pagesInfo.page - 1) + 1,
|
||||||
item?.distribution_id,
|
item?.distribution_id,
|
||||||
`${formatJustDate(item?.create_date)} (${formatJustTime(
|
`${formatJustDate(item?.create_date)} (${formatJustTime(
|
||||||
item?.create_date
|
item?.create_date,
|
||||||
)})`,
|
)})`,
|
||||||
item?.assigner_organization?.organization +
|
item?.assigner_organization?.organization +
|
||||||
" (" +
|
" (" +
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
import {
|
import {
|
||||||
zValidateAutoComplete,
|
zValidateAutoComplete,
|
||||||
zValidateAutoCompleteOptional,
|
zValidateAutoCompleteOptional,
|
||||||
zValidateNumber,
|
zValidateNumber,
|
||||||
zValidateString,
|
zValidateString,
|
||||||
} from "../../data/getFormTypeErrors";
|
} from "../../../data/getFormTypeErrors";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import AutoComplete from "../../components/AutoComplete/AutoComplete";
|
import AutoComplete from "../../../components/AutoComplete/AutoComplete";
|
||||||
import { getMonthsList } from "../../data/getMonths";
|
import { getMonthsList } from "../../../data/getMonths";
|
||||||
import { RadioGroup } from "../../components/RadioButton/RadioGroup";
|
import { RadioGroup } from "../../../components/RadioButton/RadioGroup";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import ToggleButton from "../../components/ToggleButton/ToggleButton";
|
import ToggleButton from "../../../components/ToggleButton/ToggleButton";
|
||||||
import Typography from "../../components/Typography/Typography";
|
import Typography from "../../../components/Typography/Typography";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
item: any;
|
item: any;
|
||||||
@@ -45,7 +45,7 @@ const posSaleTypes = [
|
|||||||
|
|
||||||
export const QuotaLevel1 = ({ item, onSubmit, setFormRef, visible }: Props) => {
|
export const QuotaLevel1 = ({ item, onSubmit, setFormRef, visible }: Props) => {
|
||||||
const [hasDistributionLimit, setHasDistributionLimit] = useState(
|
const [hasDistributionLimit, setHasDistributionLimit] = useState(
|
||||||
item?.distribution_mode?.length ? true : false
|
item?.distribution_mode?.length ? true : false,
|
||||||
);
|
);
|
||||||
const internalRef = useRef<HTMLFormElement>(null);
|
const internalRef = useRef<HTMLFormElement>(null);
|
||||||
const [livestockTypes, setLivestockTypes] = useState<
|
const [livestockTypes, setLivestockTypes] = useState<
|
||||||
@@ -116,7 +116,7 @@ export const QuotaLevel1 = ({ item, onSubmit, setFormRef, visible }: Props) => {
|
|||||||
(option: any) =>
|
(option: any) =>
|
||||||
option?.livestock_type?.weight_type === allocate?.weight_type &&
|
option?.livestock_type?.weight_type === allocate?.weight_type &&
|
||||||
option?.livestock_group === group &&
|
option?.livestock_group === group &&
|
||||||
option?.livestock_type?.name === allocate?.name
|
option?.livestock_type?.name === allocate?.name,
|
||||||
);
|
);
|
||||||
return result?.quantity_kg || 0;
|
return result?.quantity_kg || 0;
|
||||||
};
|
};
|
||||||
@@ -153,13 +153,13 @@ export const QuotaLevel1 = ({ item, onSubmit, setFormRef, visible }: Props) => {
|
|||||||
const findLivestockIndex = (
|
const findLivestockIndex = (
|
||||||
group: string,
|
group: string,
|
||||||
weightType: string,
|
weightType: string,
|
||||||
fa: string
|
fa: string,
|
||||||
) => {
|
) => {
|
||||||
return livestockTypes.findIndex(
|
return livestockTypes.findIndex(
|
||||||
(item) =>
|
(item) =>
|
||||||
item.livestock_group === group &&
|
item.livestock_group === group &&
|
||||||
item.weight_type === weightType &&
|
item.weight_type === weightType &&
|
||||||
item.fa === fa
|
item.fa === fa,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -394,7 +394,7 @@ export const QuotaLevel1 = ({ item, onSubmit, setFormRef, visible }: Props) => {
|
|||||||
?.filter(
|
?.filter(
|
||||||
(option) =>
|
(option) =>
|
||||||
option.livestock_group === "rural" &&
|
option.livestock_group === "rural" &&
|
||||||
option?.weight_type === "H"
|
option?.weight_type === "H",
|
||||||
)
|
)
|
||||||
.map((item, i) => {
|
.map((item, i) => {
|
||||||
const index = findLivestockIndex("rural", "H", item.fa);
|
const index = findLivestockIndex("rural", "H", item.fa);
|
||||||
@@ -428,7 +428,7 @@ export const QuotaLevel1 = ({ item, onSubmit, setFormRef, visible }: Props) => {
|
|||||||
?.filter(
|
?.filter(
|
||||||
(option) =>
|
(option) =>
|
||||||
option.livestock_group === "rural" &&
|
option.livestock_group === "rural" &&
|
||||||
option?.weight_type === "L"
|
option?.weight_type === "L",
|
||||||
)
|
)
|
||||||
.map((item, i) => {
|
.map((item, i) => {
|
||||||
const index = findLivestockIndex("rural", "L", item.fa);
|
const index = findLivestockIndex("rural", "L", item.fa);
|
||||||
@@ -475,13 +475,13 @@ export const QuotaLevel1 = ({ item, onSubmit, setFormRef, visible }: Props) => {
|
|||||||
?.filter(
|
?.filter(
|
||||||
(option) =>
|
(option) =>
|
||||||
option.livestock_group === "industrial" &&
|
option.livestock_group === "industrial" &&
|
||||||
option?.weight_type === "H"
|
option?.weight_type === "H",
|
||||||
)
|
)
|
||||||
.map((item, i) => {
|
.map((item, i) => {
|
||||||
const index = findLivestockIndex(
|
const index = findLivestockIndex(
|
||||||
"industrial",
|
"industrial",
|
||||||
"H",
|
"H",
|
||||||
item.fa
|
item.fa,
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<Textfield
|
<Textfield
|
||||||
@@ -513,13 +513,13 @@ export const QuotaLevel1 = ({ item, onSubmit, setFormRef, visible }: Props) => {
|
|||||||
?.filter(
|
?.filter(
|
||||||
(option) =>
|
(option) =>
|
||||||
option.livestock_group === "industrial" &&
|
option.livestock_group === "industrial" &&
|
||||||
option?.weight_type === "L"
|
option?.weight_type === "L",
|
||||||
)
|
)
|
||||||
.map((item, i) => {
|
.map((item, i) => {
|
||||||
const index = findLivestockIndex(
|
const index = findLivestockIndex(
|
||||||
"industrial",
|
"industrial",
|
||||||
"L",
|
"L",
|
||||||
item.fa
|
item.fa,
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<Textfield
|
<Textfield
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import Typography from "../../components/Typography/Typography";
|
import Typography from "../../../components/Typography/Typography";
|
||||||
import Checkbox from "../../components/CheckBox/CheckBox";
|
import Checkbox from "../../../components/CheckBox/CheckBox";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
item: any;
|
item: any;
|
||||||
@@ -48,7 +48,7 @@ export const QuotaLevel2 = ({ item, onSubmit, setFormRef, visible }: Props) => {
|
|||||||
if (livestockData) {
|
if (livestockData) {
|
||||||
const d = data?.results?.map((option: PlansProps) => {
|
const d = data?.results?.map((option: PlansProps) => {
|
||||||
const founded = item?.incentive_plan?.find(
|
const founded = item?.incentive_plan?.find(
|
||||||
(itm: PlansProps) => itm?.incentive_plan === option.id
|
(itm: PlansProps) => itm?.incentive_plan === option.id,
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
name: option?.name,
|
name: option?.name,
|
||||||
@@ -56,7 +56,7 @@ export const QuotaLevel2 = ({ item, onSubmit, setFormRef, visible }: Props) => {
|
|||||||
active: founded ? true : false,
|
active: founded ? true : false,
|
||||||
live_stocks: livestockData.results.flatMap((item: any) => {
|
live_stocks: livestockData.results.flatMap((item: any) => {
|
||||||
const foundedLiveStock = founded?.live_stocks?.find(
|
const foundedLiveStock = founded?.live_stocks?.find(
|
||||||
(option: any) => option?.id === item.id
|
(option: any) => option?.id === item.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Checkbox from "../../components/CheckBox/CheckBox";
|
import Checkbox from "../../../components/CheckBox/CheckBox";
|
||||||
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import Typography from "../../components/Typography/Typography";
|
import Typography from "../../../components/Typography/Typography";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
item: any;
|
item: any;
|
||||||
@@ -24,13 +24,17 @@ export const QuotaLevel3 = ({ item, onSubmit, setFormRef, visible }: Props) => {
|
|||||||
const internalRef = useRef<HTMLFormElement>(null);
|
const internalRef = useRef<HTMLFormElement>(null);
|
||||||
|
|
||||||
const [limitByHerdSize, setLimitByHerdSize] = useState(
|
const [limitByHerdSize, setLimitByHerdSize] = useState(
|
||||||
item?.limit_by_herd_size || false
|
item?.limit_by_herd_size || false,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [preSale, setPreSale] = useState(item?.pre_sale || false);
|
const [preSale, setPreSale] = useState(item?.pre_sale || false);
|
||||||
|
|
||||||
const [freeSale, setFreeSale] = useState(item?.free_sale || false);
|
const [freeSale, setFreeSale] = useState(item?.free_sale || false);
|
||||||
|
|
||||||
|
const [oneTimePurchase, setOneTimePurchase] = useState(
|
||||||
|
item?.one_time_purchase_limit || false,
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
setFormRef(internalRef.current);
|
setFormRef(internalRef.current);
|
||||||
@@ -66,7 +70,7 @@ export const QuotaLevel3 = ({ item, onSubmit, setFormRef, visible }: Props) => {
|
|||||||
(option: any) =>
|
(option: any) =>
|
||||||
option?.livestock_type?.weight_type === allocate?.weight_type &&
|
option?.livestock_type?.weight_type === allocate?.weight_type &&
|
||||||
option?.livestock_type?.id === allocate?.id &&
|
option?.livestock_type?.id === allocate?.id &&
|
||||||
option?.livestock_type?.name === allocate?.name
|
option?.livestock_type?.name === allocate?.name,
|
||||||
);
|
);
|
||||||
if (result) {
|
if (result) {
|
||||||
return result.age_month;
|
return result.age_month;
|
||||||
@@ -105,6 +109,7 @@ export const QuotaLevel3 = ({ item, onSubmit, setFormRef, visible }: Props) => {
|
|||||||
}),
|
}),
|
||||||
pre_sale: preSale,
|
pre_sale: preSale,
|
||||||
free_sale: freeSale,
|
free_sale: freeSale,
|
||||||
|
one_time_purchase_limit: oneTimePurchase,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -234,7 +239,7 @@ export const QuotaLevel3 = ({ item, onSubmit, setFormRef, visible }: Props) => {
|
|||||||
const originalIndex = livestockTypes.findIndex(
|
const originalIndex = livestockTypes.findIndex(
|
||||||
(type) =>
|
(type) =>
|
||||||
type.livestock_type === item.livestock_type &&
|
type.livestock_type === item.livestock_type &&
|
||||||
type.weight_type === item.weight_type
|
type.weight_type === item.weight_type,
|
||||||
);
|
);
|
||||||
if (originalIndex !== -1) {
|
if (originalIndex !== -1) {
|
||||||
handleLivestockTypeChange(originalIndex, value);
|
handleLivestockTypeChange(originalIndex, value);
|
||||||
@@ -268,7 +273,7 @@ export const QuotaLevel3 = ({ item, onSubmit, setFormRef, visible }: Props) => {
|
|||||||
const originalIndex = livestockTypes.findIndex(
|
const originalIndex = livestockTypes.findIndex(
|
||||||
(type) =>
|
(type) =>
|
||||||
type.livestock_type === item.livestock_type &&
|
type.livestock_type === item.livestock_type &&
|
||||||
type.weight_type === item.weight_type
|
type.weight_type === item.weight_type,
|
||||||
);
|
);
|
||||||
if (originalIndex !== -1) {
|
if (originalIndex !== -1) {
|
||||||
handleLivestockTypeChange(originalIndex, value);
|
handleLivestockTypeChange(originalIndex, value);
|
||||||
@@ -301,6 +306,16 @@ export const QuotaLevel3 = ({ item, onSubmit, setFormRef, visible }: Props) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
<Grid className="flex gap-2 p-2 border-1 border-gray-200 rounded-xl items-center">
|
||||||
|
<Checkbox
|
||||||
|
label="محدودیت یکبار خرید از سهیمه"
|
||||||
|
checked={oneTimePurchase}
|
||||||
|
onChange={() => {
|
||||||
|
setOneTimePurchase(!oneTimePurchase);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</form>
|
</form>
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import Checkbox from "../../components/CheckBox/CheckBox";
|
import Checkbox from "../../../components/CheckBox/CheckBox";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Textfield from "../../components/Textfeild/Textfeild";
|
import Textfield from "../../../components/Textfeild/Textfeild";
|
||||||
import Typography from "../../components/Typography/Typography";
|
import Typography from "../../../components/Typography/Typography";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import AutoComplete from "../../components/AutoComplete/AutoComplete";
|
import AutoComplete from "../../../components/AutoComplete/AutoComplete";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
item: any;
|
item: any;
|
||||||
@@ -64,7 +64,7 @@ export const QuotaLevel4 = ({
|
|||||||
if (visible) {
|
if (visible) {
|
||||||
const getQuatity = (allocate: any) => {
|
const getQuatity = (allocate: any) => {
|
||||||
const result = item?.attribute_values?.find(
|
const result = item?.attribute_values?.find(
|
||||||
(option: any) => option?.attribute === allocate?.id
|
(option: any) => option?.attribute === allocate?.id,
|
||||||
);
|
);
|
||||||
if (result) {
|
if (result) {
|
||||||
return result.value;
|
return result.value;
|
||||||
@@ -91,7 +91,7 @@ export const QuotaLevel4 = ({
|
|||||||
if (visible) {
|
if (visible) {
|
||||||
const getQuatity = (allocate: any) => {
|
const getQuatity = (allocate: any) => {
|
||||||
const result = item?.brokers?.find(
|
const result = item?.brokers?.find(
|
||||||
(option: any) => option?.broker === allocate?.id
|
(option: any) => option?.broker === allocate?.id,
|
||||||
);
|
);
|
||||||
if (result) {
|
if (result) {
|
||||||
return result.value;
|
return result.value;
|
||||||
@@ -169,7 +169,7 @@ export const QuotaLevel4 = ({
|
|||||||
fixedBrokers.forEach((broker: any) => {
|
fixedBrokers.forEach((broker: any) => {
|
||||||
const existingIndex = next.findIndex(
|
const existingIndex = next.findIndex(
|
||||||
(selection) =>
|
(selection) =>
|
||||||
selection.pricing_type === pt?.id && selection.name === broker.fa
|
selection.pricing_type === pt?.id && selection.name === broker.fa,
|
||||||
);
|
);
|
||||||
if (existingIndex === -1) {
|
if (existingIndex === -1) {
|
||||||
next.push({
|
next.push({
|
||||||
@@ -195,7 +195,7 @@ export const QuotaLevel4 = ({
|
|||||||
return getPriceList()
|
return getPriceList()
|
||||||
?.filter((opt) => {
|
?.filter((opt) => {
|
||||||
const isSelected = selectedItems.some(
|
const isSelected = selectedItems.some(
|
||||||
(item) => item.name === opt.value
|
(item) => item.name === opt.value,
|
||||||
);
|
);
|
||||||
if (!isSelected) return false;
|
if (!isSelected) return false;
|
||||||
const broker = brokersData?.find((b: any) => b.fa === opt.value);
|
const broker = brokersData?.find((b: any) => b.fa === opt.value);
|
||||||
@@ -209,7 +209,7 @@ export const QuotaLevel4 = ({
|
|||||||
|
|
||||||
const handleSubmitForm = () => {
|
const handleSubmitForm = () => {
|
||||||
const allTypesSelected = priceTypesResponse?.results?.every((pt: any) =>
|
const allTypesSelected = priceTypesResponse?.results?.every((pt: any) =>
|
||||||
priceSelections?.some((item) => item.pricing_type === pt?.id)
|
priceSelections?.some((item) => item.pricing_type === pt?.id),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -217,7 +217,7 @@ export const QuotaLevel4 = ({
|
|||||||
!brokersData?.filter((opt: any) => opt.required && opt.value === 0).length
|
!brokersData?.filter((opt: any) => opt.required && opt.value === 0).length
|
||||||
) {
|
) {
|
||||||
const activeBrokersData = brokersData?.filter(
|
const activeBrokersData = brokersData?.filter(
|
||||||
(broker: any) => broker.active
|
(broker: any) => broker.active,
|
||||||
);
|
);
|
||||||
const activeBrokerNames = activeBrokersData?.map((b: any) => b.fa) || [];
|
const activeBrokerNames = activeBrokersData?.map((b: any) => b.fa) || [];
|
||||||
const filteredPriceSelections = priceSelections?.filter((item) => {
|
const filteredPriceSelections = priceSelections?.filter((item) => {
|
||||||
@@ -243,8 +243,8 @@ export const QuotaLevel4 = ({
|
|||||||
...item,
|
...item,
|
||||||
value,
|
value,
|
||||||
}
|
}
|
||||||
: item
|
: item,
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -313,7 +313,7 @@ export const QuotaLevel4 = ({
|
|||||||
});
|
});
|
||||||
if (!newActiveState) {
|
if (!newActiveState) {
|
||||||
setPriceSelections((prev) =>
|
setPriceSelections((prev) =>
|
||||||
prev.filter((selection) => selection.name !== item.fa)
|
prev.filter((selection) => selection.name !== item.fa),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@@ -379,16 +379,16 @@ export const QuotaLevel4 = ({
|
|||||||
onChange={(e: (string | number)[]) => {
|
onChange={(e: (string | number)[]) => {
|
||||||
setPriceSelections((prev) => {
|
setPriceSelections((prev) => {
|
||||||
const filtered = prev.filter(
|
const filtered = prev.filter(
|
||||||
(item) => item.pricing_type !== pt?.id
|
(item) => item.pricing_type !== pt?.id,
|
||||||
);
|
);
|
||||||
const requiredBrokers = item
|
const requiredBrokers = item
|
||||||
? []
|
? []
|
||||||
: brokersData?.filter(
|
: brokersData?.filter(
|
||||||
(broker: any) => broker?.fix_broker_price_state
|
(broker: any) => broker?.fix_broker_price_state,
|
||||||
) || [];
|
) || [];
|
||||||
const newSelections = e.map((selectedKey) => {
|
const newSelections = e.map((selectedKey) => {
|
||||||
const selectedItem = getPriceList().find(
|
const selectedItem = getPriceList().find(
|
||||||
(item) => item.key === selectedKey
|
(item) => item.key === selectedKey,
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -402,7 +402,7 @@ export const QuotaLevel4 = ({
|
|||||||
const existingIndex = merged.findIndex(
|
const existingIndex = merged.findIndex(
|
||||||
(selection) =>
|
(selection) =>
|
||||||
selection.pricing_type === pt?.id &&
|
selection.pricing_type === pt?.id &&
|
||||||
selection.name === broker.fa
|
selection.name === broker.fa,
|
||||||
);
|
);
|
||||||
const brokerValue = broker.value || 0;
|
const brokerValue = broker.value || 0;
|
||||||
if (existingIndex === -1) {
|
if (existingIndex === -1) {
|
||||||
@@ -424,11 +424,11 @@ export const QuotaLevel4 = ({
|
|||||||
selectedKeys={(() => {
|
selectedKeys={(() => {
|
||||||
const filtered =
|
const filtered =
|
||||||
priceSelections?.filter(
|
priceSelections?.filter(
|
||||||
(item) => item.pricing_type === pt?.id
|
(item) => item.pricing_type === pt?.id,
|
||||||
) || [];
|
) || [];
|
||||||
const keys = filtered.map((item) => {
|
const keys = filtered.map((item) => {
|
||||||
const priceItem = getPriceList().find(
|
const priceItem = getPriceList().find(
|
||||||
(p) => p.value === item.name
|
(p) => p.value === item.name,
|
||||||
);
|
);
|
||||||
return priceItem?.key;
|
return priceItem?.key;
|
||||||
});
|
});
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import { useNavigate, useParams } from "@tanstack/react-router";
|
import { useNavigate, useParams } from "@tanstack/react-router";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Table from "../../components/Table/Table";
|
import Table from "../../../components/Table/Table";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Popover } from "../../components/PopOver/PopOver";
|
import { Popover } from "../../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../../components/Tooltip/Tooltip";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { REPORTING } from "../../routes/paths";
|
import { REPORTING } from "../../../routes/paths";
|
||||||
import { getQuotaTableColumns, getQuotaTableRowData } from "./quotaTableUtils";
|
import { getQuotaTableColumns, getQuotaTableRowData } from "./quotaTableUtils";
|
||||||
|
|
||||||
export const QuotaReportingProductDetails = () => {
|
export const QuotaReportingProductDetails = () => {
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import Table from "../../components/Table/Table";
|
import Table from "../../../components/Table/Table";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Button from "../../components/Button/Button";
|
import Button from "../../../components/Button/Button";
|
||||||
import { Popover } from "../../components/PopOver/PopOver";
|
import { Popover } from "../../../components/PopOver/PopOver";
|
||||||
import { Tooltip } from "../../components/Tooltip/Tooltip";
|
import { Tooltip } from "../../../components/Tooltip/Tooltip";
|
||||||
import { useNavigate } from "@tanstack/react-router";
|
import { useNavigate } from "@tanstack/react-router";
|
||||||
import { REPORTING } from "../../routes/paths";
|
import { REPORTING } from "../../../routes/paths";
|
||||||
import { ShowWeight } from "../../components/ShowWeight/ShowWeight";
|
import { ShowWeight } from "../../../components/ShowWeight/ShowWeight";
|
||||||
import { PaginationParameters } from "../../components/PaginationParameters/PaginationParameters";
|
import { PaginationParameters } from "../../../components/PaginationParameters/PaginationParameters";
|
||||||
|
|
||||||
interface QuotaDashboardByProduct {
|
interface QuotaDashboardByProduct {
|
||||||
product_id: string;
|
product_id: string;
|
||||||
@@ -42,7 +42,7 @@ export const QuotaReportingProducts = () => {
|
|||||||
method: "get",
|
method: "get",
|
||||||
params: { ...publicParams },
|
params: { ...publicParams },
|
||||||
queryKey: ["QuotaReportingAllProducts", publicParams],
|
queryKey: ["QuotaReportingAllProducts", publicParams],
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -89,7 +89,7 @@ export const QuotaReportingProducts = () => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Popover>,
|
</Popover>,
|
||||||
];
|
];
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
setPagesTableData(tableData);
|
setPagesTableData(tableData);
|
||||||
} else {
|
} else {
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
import { useParams } from "@tanstack/react-router";
|
import { useParams } from "@tanstack/react-router";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useApiRequest } from "../../utils/useApiRequest";
|
import { useApiRequest } from "../../../utils/useApiRequest";
|
||||||
import Table from "../../components/Table/Table";
|
import Table from "../../../components/Table/Table";
|
||||||
import { formatJustDate, formatJustTime } from "../../utils/formatTime";
|
import { formatJustDate, formatJustTime } from "../../../utils/formatTime";
|
||||||
import { getPersianMonths } from "../../utils/getPersianMonths";
|
import { getPersianMonths } from "../../../utils/getPersianMonths";
|
||||||
import ShowMoreInfo from "../../components/ShowMoreInfo/ShowMoreInfo";
|
import ShowMoreInfo from "../../../components/ShowMoreInfo/ShowMoreInfo";
|
||||||
import Typography from "../../components/Typography/Typography";
|
import Typography from "../../../components/Typography/Typography";
|
||||||
import ShowStringList from "../../components/ShowStringList/ShowStringList";
|
import ShowStringList from "../../../components/ShowStringList/ShowStringList";
|
||||||
import Divider from "../../components/Divider/Divider";
|
import Divider from "../../../components/Divider/Divider";
|
||||||
import { ShowWeight } from "../../components/ShowWeight/ShowWeight";
|
import { ShowWeight } from "../../../components/ShowWeight/ShowWeight";
|
||||||
|
|
||||||
export const QuotaReportingQuotaDistributions = () => {
|
export const QuotaReportingQuotaDistributions = () => {
|
||||||
const params = useParams({ strict: false });
|
const params = useParams({ strict: false });
|
||||||
@@ -39,7 +39,7 @@ export const QuotaReportingQuotaDistributions = () => {
|
|||||||
: i + pagesInfo.page_size * (pagesInfo.page - 1) + 1,
|
: i + pagesInfo.page_size * (pagesInfo.page - 1) + 1,
|
||||||
item?.distribution_id,
|
item?.distribution_id,
|
||||||
`${formatJustDate(item?.create_date)} (${formatJustTime(
|
`${formatJustDate(item?.create_date)} (${formatJustTime(
|
||||||
item?.create_date
|
item?.create_date,
|
||||||
)})`,
|
)})`,
|
||||||
item?.assigner_organization?.organization +
|
item?.assigner_organization?.organization +
|
||||||
" (" +
|
" (" +
|
||||||
@@ -172,7 +172,7 @@ export const QuotaReportingQuotaDistributions = () => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
<ShowStringList
|
<ShowStringList
|
||||||
strings={DashboardData?.limit_by_organizations?.map(
|
strings={DashboardData?.limit_by_organizations?.map(
|
||||||
(opt: { name: string }) => opt?.name
|
(opt: { name: string }) => opt?.name,
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ export const QuotaReportingQuotaDistributions = () => {
|
|||||||
opt?.livestock_type?.weight_type === "L"
|
opt?.livestock_type?.weight_type === "L"
|
||||||
? "سبک"
|
? "سبک"
|
||||||
: "سنگین"
|
: "سنگین"
|
||||||
}) با سن ${opt?.age_month}`
|
}) با سن ${opt?.age_month}`,
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
@@ -250,12 +250,12 @@ export const QuotaReportingQuotaDistributions = () => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
</Grid>
|
</Grid>
|
||||||
)
|
),
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
)
|
),
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</ShowMoreInfo>,
|
</ShowMoreInfo>,
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
import Typography from "../../components/Typography/Typography";
|
import Typography from "../../../components/Typography/Typography";
|
||||||
import { ShowWeight } from "../../components/ShowWeight/ShowWeight";
|
import { ShowWeight } from "../../../components/ShowWeight/ShowWeight";
|
||||||
import ShowStringList from "../../components/ShowStringList/ShowStringList";
|
import ShowStringList from "../../../components/ShowStringList/ShowStringList";
|
||||||
import Divider from "../../components/Divider/Divider";
|
import Divider from "../../../components/Divider/Divider";
|
||||||
import { formatJustDate } from "../../utils/formatTime";
|
import { formatJustDate } from "../../../utils/formatTime";
|
||||||
import { getPersianMonths } from "../../utils/getPersianMonths";
|
import { getPersianMonths } from "../../../utils/getPersianMonths";
|
||||||
|
|
||||||
interface QuotaViewProps {
|
interface QuotaViewProps {
|
||||||
item: any;
|
item: any;
|
||||||
@@ -130,7 +130,7 @@ export const QuotaView: React.FC<QuotaViewProps> = ({ item }) => {
|
|||||||
? "روستایی"
|
? "روستایی"
|
||||||
: group === "industrial"
|
: group === "industrial"
|
||||||
? "صنعتی"
|
? "صنعتی"
|
||||||
: "عشایری"
|
: "عشایری",
|
||||||
)
|
)
|
||||||
.join(", ") || "-"
|
.join(", ") || "-"
|
||||||
}
|
}
|
||||||
@@ -202,8 +202,8 @@ export const QuotaView: React.FC<QuotaViewProps> = ({ item }) => {
|
|||||||
acc[group].push(allocation);
|
acc[group].push(allocation);
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
{} as Record<string, any[]>
|
{} as Record<string, any[]>,
|
||||||
)
|
),
|
||||||
) as [string, any[]][]
|
) as [string, any[]][]
|
||||||
).map(([group, allocations]) => (
|
).map(([group, allocations]) => (
|
||||||
<div key={group} className="space-y-2">
|
<div key={group} className="space-y-2">
|
||||||
@@ -296,6 +296,13 @@ export const QuotaView: React.FC<QuotaViewProps> = ({ item }) => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
<Divider />
|
<Divider />
|
||||||
|
<div>
|
||||||
|
<Typography variant="body1" sign="info" className="mb-2">
|
||||||
|
محدودیت یکبار خرید از سهیمه:{" "}
|
||||||
|
{item?.one_time_purchase_limit ? "دارد" : "ندارد"}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
<Divider />
|
||||||
<div>
|
<div>
|
||||||
<Typography
|
<Typography
|
||||||
variant="body2"
|
variant="body2"
|
||||||
@@ -308,7 +315,7 @@ export const QuotaView: React.FC<QuotaViewProps> = ({ item }) => {
|
|||||||
<ShowStringList
|
<ShowStringList
|
||||||
showSearch={false}
|
showSearch={false}
|
||||||
strings={item?.limit_by_organizations?.map(
|
strings={item?.limit_by_organizations?.map(
|
||||||
(opt: { name: string }) => opt?.name
|
(opt: { name: string }) => opt?.name,
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
@@ -341,7 +348,7 @@ export const QuotaView: React.FC<QuotaViewProps> = ({ item }) => {
|
|||||||
opt?.livestock_type?.weight_type === "L"
|
opt?.livestock_type?.weight_type === "L"
|
||||||
? "سبک"
|
? "سبک"
|
||||||
: "سنگین"
|
: "سنگین"
|
||||||
}) با سن ${opt?.age_month}`
|
}) با سن ${opt?.age_month}`,
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
@@ -423,7 +430,7 @@ export const QuotaView: React.FC<QuotaViewProps> = ({ item }) => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
),
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -453,7 +460,7 @@ export const QuotaView: React.FC<QuotaViewProps> = ({ item }) => {
|
|||||||
pricing_type_name: string;
|
pricing_type_name: string;
|
||||||
name: string;
|
name: string;
|
||||||
value: number;
|
value: number;
|
||||||
}
|
},
|
||||||
) => {
|
) => {
|
||||||
const key = itm.pricing_type_name;
|
const key = itm.pricing_type_name;
|
||||||
if (acc[key]) {
|
if (acc[key]) {
|
||||||
@@ -463,8 +470,8 @@ export const QuotaView: React.FC<QuotaViewProps> = ({ item }) => {
|
|||||||
}
|
}
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
{} as Record<string, any>
|
{} as Record<string, any>,
|
||||||
)
|
),
|
||||||
).map((priceItem: any, priceIndex: number) => (
|
).map((priceItem: any, priceIndex: number) => (
|
||||||
<div
|
<div
|
||||||
key={priceIndex}
|
key={priceIndex}
|
||||||
@@ -499,8 +506,8 @@ export const QuotaView: React.FC<QuotaViewProps> = ({ item }) => {
|
|||||||
acc[key].push(itm);
|
acc[key].push(itm);
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
{} as Record<string, any[]>
|
{} as Record<string, any[]>,
|
||||||
)
|
),
|
||||||
) as [string, any[]][]
|
) as [string, any[]][]
|
||||||
).map(([pricingTypeName, items]) => (
|
).map(([pricingTypeName, items]) => (
|
||||||
<div key={pricingTypeName} className="space-y-2">
|
<div key={pricingTypeName} className="space-y-2">
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { formatJustDate } from "../../utils/formatTime";
|
import { formatJustDate } from "../../../utils/formatTime";
|
||||||
import { ShieldCheckIcon } from "@heroicons/react/24/solid";
|
import { ShieldCheckIcon } from "@heroicons/react/24/solid";
|
||||||
import { ShowWeight } from "../../components/ShowWeight/ShowWeight";
|
import { ShowWeight } from "../../../components/ShowWeight/ShowWeight";
|
||||||
import ShowMoreInfo from "../../components/ShowMoreInfo/ShowMoreInfo";
|
import ShowMoreInfo from "../../../components/ShowMoreInfo/ShowMoreInfo";
|
||||||
import ShowStringList from "../../components/ShowStringList/ShowStringList";
|
import ShowStringList from "../../../components/ShowStringList/ShowStringList";
|
||||||
import { Grid } from "../../components/Grid/Grid";
|
import { Grid } from "../../../components/Grid/Grid";
|
||||||
|
|
||||||
export interface PriceCalculationItem {
|
export interface PriceCalculationItem {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -114,7 +114,7 @@ const getFilteredPriceCalculationData = (
|
|||||||
export const getQuotaTableRowData = (
|
export const getQuotaTableRowData = (
|
||||||
item: any,
|
item: any,
|
||||||
index: number,
|
index: number,
|
||||||
config: QuotaTableConfig
|
config: QuotaTableConfig,
|
||||||
): any[] => {
|
): any[] => {
|
||||||
const rowData: any[] = [];
|
const rowData: any[] = [];
|
||||||
const {
|
const {
|
||||||
@@ -131,7 +131,7 @@ export const getQuotaTableRowData = (
|
|||||||
rowData.push(
|
rowData.push(
|
||||||
pagesInfo.page === 1
|
pagesInfo.page === 1
|
||||||
? index + 1
|
? index + 1
|
||||||
: index + pagesInfo.page_size * (pagesInfo.page - 1) + 1
|
: index + pagesInfo.page_size * (pagesInfo.page - 1) + 1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ export const getQuotaTableRowData = (
|
|||||||
key={index}
|
key={index}
|
||||||
weight={item?.quota_weight}
|
weight={item?.quota_weight}
|
||||||
type={item?.sale_unit?.unit}
|
type={item?.sale_unit?.unit}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// وزن توزیع شده
|
// وزن توزیع شده
|
||||||
@@ -170,7 +170,7 @@ export const getQuotaTableRowData = (
|
|||||||
key={index}
|
key={index}
|
||||||
weight={item?.quota_distributed}
|
weight={item?.quota_distributed}
|
||||||
type={item?.sale_unit?.unit}
|
type={item?.sale_unit?.unit}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// وزن باقیمانده سهمیه
|
// وزن باقیمانده سهمیه
|
||||||
@@ -179,7 +179,7 @@ export const getQuotaTableRowData = (
|
|||||||
key={index}
|
key={index}
|
||||||
weight={item?.remaining_weight}
|
weight={item?.remaining_weight}
|
||||||
type={item?.sale_unit?.unit}
|
type={item?.sale_unit?.unit}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// وزن فروش رفته
|
// وزن فروش رفته
|
||||||
@@ -188,7 +188,7 @@ export const getQuotaTableRowData = (
|
|||||||
key={index}
|
key={index}
|
||||||
weight={item?.been_sold}
|
weight={item?.been_sold}
|
||||||
type={item?.sale_unit?.unit}
|
type={item?.sale_unit?.unit}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// ورود به انبار
|
// ورود به انبار
|
||||||
@@ -197,7 +197,7 @@ export const getQuotaTableRowData = (
|
|||||||
key={index}
|
key={index}
|
||||||
weight={item?.inventory_received}
|
weight={item?.inventory_received}
|
||||||
type={item?.sale_unit?.unit}
|
type={item?.sale_unit?.unit}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// مانده انبار
|
// مانده انبار
|
||||||
@@ -206,7 +206,7 @@ export const getQuotaTableRowData = (
|
|||||||
key={index}
|
key={index}
|
||||||
weight={item?.pre_sale_balance}
|
weight={item?.pre_sale_balance}
|
||||||
type={item?.sale_unit?.unit}
|
type={item?.sale_unit?.unit}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// تاریخ بایگانی
|
// تاریخ بایگانی
|
||||||
@@ -225,9 +225,9 @@ export const getQuotaTableRowData = (
|
|||||||
? "روستایی"
|
? "روستایی"
|
||||||
: group === "industrial"
|
: group === "industrial"
|
||||||
? "صنعتی"
|
? "صنعتی"
|
||||||
: "عشایری"
|
: "عشایری",
|
||||||
)
|
)
|
||||||
.join(", ")
|
.join(", "),
|
||||||
);
|
);
|
||||||
|
|
||||||
// مبدا
|
// مبدا
|
||||||
@@ -270,7 +270,7 @@ export const getQuotaTableRowData = (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
rowData.push(
|
rowData.push(
|
||||||
@@ -286,7 +286,7 @@ export const getQuotaTableRowData = (
|
|||||||
showSearch={false}
|
showSearch={false}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</ShowMoreInfo>
|
</ShowMoreInfo>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// سهمیه و مجوز
|
// سهمیه و مجوز
|
||||||
@@ -418,7 +418,7 @@ export const getQuotaTableRowData = (
|
|||||||
? "بر اساس وزن"
|
? "بر اساس وزن"
|
||||||
: item?.pos_sale_type === "count"
|
: item?.pos_sale_type === "count"
|
||||||
? "بر اساس تعداد راس دام"
|
? "بر اساس تعداد راس دام"
|
||||||
: "-"
|
: "-",
|
||||||
);
|
);
|
||||||
|
|
||||||
// طرح های تشویقی
|
// طرح های تشویقی
|
||||||
@@ -555,7 +555,7 @@ export const getQuotaDashboardRowData = (item: any): any[] => {
|
|||||||
key={item?.id}
|
key={item?.id}
|
||||||
weight={item?.quota_weight}
|
weight={item?.quota_weight}
|
||||||
type={item?.sale_unit?.unit}
|
type={item?.sale_unit?.unit}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// وزن توزیع شده
|
// وزن توزیع شده
|
||||||
@@ -564,7 +564,7 @@ export const getQuotaDashboardRowData = (item: any): any[] => {
|
|||||||
key={item?.id}
|
key={item?.id}
|
||||||
weight={item?.quota_distributed}
|
weight={item?.quota_distributed}
|
||||||
type={item?.sale_unit?.unit}
|
type={item?.sale_unit?.unit}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// وزن باقیمانده سهمیه
|
// وزن باقیمانده سهمیه
|
||||||
@@ -573,7 +573,7 @@ export const getQuotaDashboardRowData = (item: any): any[] => {
|
|||||||
key={item?.id}
|
key={item?.id}
|
||||||
weight={item?.remaining_weight}
|
weight={item?.remaining_weight}
|
||||||
type={item?.sale_unit?.unit}
|
type={item?.sale_unit?.unit}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// وزن فروش رفته
|
// وزن فروش رفته
|
||||||
@@ -582,7 +582,7 @@ export const getQuotaDashboardRowData = (item: any): any[] => {
|
|||||||
key={item?.id}
|
key={item?.id}
|
||||||
weight={item?.been_sold}
|
weight={item?.been_sold}
|
||||||
type={item?.sale_unit?.unit}
|
type={item?.sale_unit?.unit}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// ورود به انبار
|
// ورود به انبار
|
||||||
@@ -591,7 +591,7 @@ export const getQuotaDashboardRowData = (item: any): any[] => {
|
|||||||
key={item?.id}
|
key={item?.id}
|
||||||
weight={item?.inventory_received}
|
weight={item?.inventory_received}
|
||||||
type={item?.sale_unit?.unit}
|
type={item?.sale_unit?.unit}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// مانده انبار
|
// مانده انبار
|
||||||
@@ -600,7 +600,7 @@ export const getQuotaDashboardRowData = (item: any): any[] => {
|
|||||||
key={item?.id}
|
key={item?.id}
|
||||||
weight={item?.pre_sale_balance}
|
weight={item?.pre_sale_balance}
|
||||||
type={item?.sale_unit?.unit}
|
type={item?.sale_unit?.unit}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// واحد فروش
|
// واحد فروش
|
||||||
@@ -614,9 +614,9 @@ export const getQuotaDashboardRowData = (item: any): any[] => {
|
|||||||
? "روستایی"
|
? "روستایی"
|
||||||
: group === "industrial"
|
: group === "industrial"
|
||||||
? "صنعتی"
|
? "صنعتی"
|
||||||
: "عشایری"
|
: "عشایری",
|
||||||
)
|
)
|
||||||
.join(", ")
|
.join(", "),
|
||||||
);
|
);
|
||||||
|
|
||||||
// مبدا
|
// مبدا
|
||||||
@@ -659,7 +659,7 @@ export const getQuotaDashboardRowData = (item: any): any[] => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// توزیع
|
// توزیع
|
||||||
@@ -676,7 +676,7 @@ export const getQuotaDashboardRowData = (item: any): any[] => {
|
|||||||
showSearch={false}
|
showSearch={false}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</ShowMoreInfo>
|
</ShowMoreInfo>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// سهمیه و مجوز
|
// سهمیه و مجوز
|
||||||
@@ -808,7 +808,7 @@ export const getQuotaDashboardRowData = (item: any): any[] => {
|
|||||||
? "بر اساس وزن"
|
? "بر اساس وزن"
|
||||||
: item?.pos_sale_type === "count"
|
: item?.pos_sale_type === "count"
|
||||||
? "بر اساس تعداد راس دام"
|
? "بر اساس تعداد راس دام"
|
||||||
: "-"
|
: "-",
|
||||||
);
|
);
|
||||||
|
|
||||||
// طرح های تشویقی
|
// طرح های تشویقی
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user