Compare commits

...

11 Commits

Author SHA1 Message Date
f8d2da4f28 version changed to 02.64 2026-02-02 16:34:27 +03:30
bb1d5b3315 update: tag distribution details 2026-02-02 16:34:21 +03:30
d8d415a8f5 fix: remaining number 2026-02-02 14:50:44 +03:30
f58c8e6c58 add: new keys 2026-02-02 14:49:12 +03:30
3a17fcb448 version changed to 02.63 2026-02-02 12:14:52 +03:30
6e219aca1a feat: distribute from distribution 2026-02-02 12:14:48 +03:30
9b74be078f version changed to 02.62 2026-02-02 11:03:09 +03:30
5fd55c4b10 fix: filter error 2026-02-02 11:03:01 +03:30
6b5276ce36 add: new tagging key 2026-02-02 08:40:06 +03:30
e465843eb9 version changed to 02.61 2026-01-28 17:42:11 +03:30
e5402f9037 add: tag dist detail 2026-01-28 17:41:53 +03:30
10 changed files with 521 additions and 32 deletions

View File

@@ -0,0 +1,150 @@
import { useParams } from "@tanstack/react-router";
import { Bars3Icon, CubeIcon, SparklesIcon } from "@heroicons/react/24/outline";
import { useApiRequest } from "../utils/useApiRequest";
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";
const speciesMap: Record<number, string> = {
1: "گاو",
2: "گاومیش",
3: "شتر",
4: "گوسفند",
5: "بز",
};
export default function TagDistribtutionDetails() {
const { id } = useParams({ strict: false });
const { data } = useApiRequest({
api: `/tag/web/api/v1/tag_distribution_batch/${id}/`,
method: "get",
queryKey: ["tagBatchInnerDashboard", id],
enabled: !!id,
});
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>
</Grid>
);
}

View File

@@ -62,14 +62,14 @@ export default function Tagging() {
item?.species_code === 1 item?.species_code === 1
? "گاو" ? "گاو"
: item?.species_code === 2 : item?.species_code === 2
? "گاومیش" ? "گاومیش"
: item?.species_code === 3 : item?.species_code === 3
? "شتر" ? "شتر"
: item?.species_code === 4 : item?.species_code === 4
? "گوسفند" ? "گوسفند"
: item?.species_code === 5 : item?.species_code === 5
? "بز" ? "بز"
: "نامشخص", : "نامشخص",
item?.serial_from || "-", item?.serial_from || "-",
item?.serial_to || "-", item?.serial_to || "-",
item?.total_distributed_tags || 0, item?.total_distributed_tags || 0,
@@ -167,6 +167,7 @@ export default function Tagging() {
columns={[ columns={[
"تعداد گروه پلاک", "تعداد گروه پلاک",
"پلاک‌های تولیدشده", "پلاک‌های تولیدشده",
"گروه پلاک های دارای توزیع",
"پلاک توزیع شده", "پلاک توزیع شده",
"پلاک باقی‌مانده", "پلاک باقی‌مانده",
"جزئیات گونه ها", "جزئیات گونه ها",
@@ -176,6 +177,8 @@ export default function Tagging() {
tagDashboardData?.batch_count?.toLocaleString() || 0, tagDashboardData?.batch_count?.toLocaleString() || 0,
tagDashboardData?.tag_count_created_by_batch?.toLocaleString() || tagDashboardData?.tag_count_created_by_batch?.toLocaleString() ||
0, 0,
tagDashboardData?.has_distributed_batches_number?.toLocaleString() ||
0,
tagDashboardData?.total_distributed_tags?.toLocaleString() || 0, tagDashboardData?.total_distributed_tags?.toLocaleString() || 0,
tagDashboardData?.total_remaining_tags?.toLocaleString() || 0, tagDashboardData?.total_remaining_tags?.toLocaleString() || 0,
<TableButton <TableButton

View File

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

View File

@@ -0,0 +1,254 @@
import { z } from "zod";
import { useEffect, useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Grid } from "../../components/Grid/Grid";
import Button from "../../components/Button/Button";
import Textfield from "../../components/Textfeild/Textfeild";
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
import AutoComplete from "../../components/AutoComplete/AutoComplete";
import { zValidateAutoComplete } from "../../data/getFormTypeErrors";
import { useApiMutation, useApiRequest } from "../../utils/useApiRequest";
import { useToast } from "../../hooks/useToast";
import { useModalStore } from "../../context/zustand-store/appStore";
const schema = z.object({
organization: zValidateAutoComplete("سازمان"),
});
type FormValues = z.infer<typeof schema>;
type ParentDistItem = {
id: number;
dist_identity?: number;
batch_identity: string | number | null;
species_code: number;
maxCount: number;
label?: string;
};
export const DistributeFromDistribution = ({ item, getData }: any) => {
const showToast = useToast();
const { closeModal } = useModalStore();
const [dists, setDists] = useState<ParentDistItem[]>([]);
const [selectedSpeciesKeys, setSelectedSpeciesKeys] = useState<
(string | number)[]
>([]);
const [counts, setCounts] = useState<Record<number, number | "">>({});
const {
control,
handleSubmit,
setValue,
trigger,
formState: { errors },
} = useForm<FormValues>({
resolver: zodResolver(schema),
defaultValues: {
organization: [],
},
});
const { data: batchDetail } = useApiRequest({
api: `/tag/web/api/v1/tag_distribution_batch/${item?.id}/`,
method: "get",
queryKey: ["tagDistributionBatchDetail", item?.id],
enabled: !!item?.id,
});
const mutation = useApiMutation({
api: `/tag/web/api/v1/tag_distribution/${item?.id}/distribute_distribution/`,
method: "post",
});
const { data: speciesData } = useApiRequest({
api: "/livestock/web/api/v1/livestock_species",
method: "get",
params: { page: 1, pageSize: 1000 },
queryKey: ["species"],
});
useEffect(() => {
const sourceDistributions = item?.distributions?.length
? item.distributions
: batchDetail?.distributions;
if (!sourceDistributions?.length) {
setDists([]);
setCounts({});
return;
}
const parentDists: ParentDistItem[] = sourceDistributions.map((d: any) => {
const maxCount = d?.remaining_number || 0;
return {
id: d?.id ?? d?.dist_identity,
dist_identity: d?.dist_identity,
batch_identity: d?.batch_identity ?? null,
species_code: d?.species_code,
maxCount: Number(maxCount) || 0,
label:
d?.serial_from != null && d?.serial_to != null
? `از ${d.serial_from} تا ${d.serial_to}`
: undefined,
};
});
setDists(parentDists);
setCounts({});
setSelectedSpeciesKeys([]);
}, [item?.distributions, batchDetail?.distributions]);
const speciesOptions = () =>
speciesData?.results?.map((opt: any) => ({
key: opt?.value,
value: opt?.name,
})) ?? [];
const getSpeciesName = (speciesCode: number) =>
speciesOptions().find((s: any) => s.key === speciesCode)?.value ?? "نامشخص";
const visibleDists = dists.filter((d) =>
selectedSpeciesKeys.includes(d.species_code),
);
const onSubmit = async (data: FormValues) => {
const distsPayload = visibleDists
.filter((d) => {
const c = counts[d.id];
return c !== "" && c !== undefined && c !== null && Number(c) > 0;
})
.map((d) => {
const fromItem = item?.distributions?.find(
(x: any) => x.id === d.id || x.dist_identity === d.id,
);
const batch_identity =
fromItem != null ? fromItem.batch_identity : d.batch_identity;
return {
parent_tag_distribution: d.id,
batch_identity: batch_identity != null ? batch_identity : null,
species_code: d.species_code,
count: Number(counts[d.id] ?? 0),
};
});
if (distsPayload.length === 0) {
showToast("حداقل یک گونه با تعداد معتبر وارد کنید", "error");
return;
}
try {
await mutation.mutateAsync({
assigned_org: data.organization[0],
parent_distribution_batch: item.id,
dists: distsPayload,
});
showToast("توزیع از توزیع با موفقیت انجام شد", "success");
getData();
closeModal();
} catch (error: any) {
showToast(
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
"error",
);
}
};
const handleCountChange = (distId: number, value: number | "") => {
setCounts((prev) => ({ ...prev, [distId]: value }));
};
const isValidCount = (dist: ParentDistItem) => {
const c = counts[dist.id];
if (c === "" || c === undefined || c === null) return false;
const num = Number(c);
return num > 0 && num <= dist.maxCount;
};
const speciesOptionsFromParent = () => {
const uniqueSpecies = Array.from(
new Map(dists.map((d) => [d.species_code, d])).values(),
);
return uniqueSpecies.map((d) => ({
key: d.species_code,
value: getSpeciesName(d.species_code),
}));
};
const hasValidDists =
visibleDists.length > 0 && visibleDists.every((d) => isValidCount(d));
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Grid container column className="gap-3">
<Controller
name="organization"
control={control}
render={() => (
<FormApiBasedAutoComplete
title="انتخاب سازمان (دریافت‌کننده)"
api={`auth/api/v1/organization/organizations_by_province?exclude=PSP&province=${item?.assigner_org?.province}`}
keyField="id"
valueField="name"
error={!!errors.organization}
errorMessage={errors.organization?.message}
onChange={(r) => {
setValue("organization", [r]);
trigger("organization");
}}
/>
)}
/>
{dists.length > 0 && speciesData?.results && (
<>
<AutoComplete
data={speciesOptionsFromParent()}
multiselect
selectedKeys={selectedSpeciesKeys}
onChange={(keys: (string | number)[]) => {
setSelectedSpeciesKeys(keys);
}}
title="گونه"
/>
{visibleDists.map((dist) => {
const countVal = counts[dist.id];
const numCount =
countVal !== "" && countVal !== undefined && countVal !== null
? Number(countVal)
: null;
const isOverMax = numCount !== null && numCount > dist.maxCount;
const isEmpty = countVal === "" || countVal === undefined;
const helperText = isOverMax
? `تعداد نباید بیشتر از ${dist.maxCount.toLocaleString()} باشد`
: isEmpty
? "لطفا تعداد را وارد کنید"
: undefined;
return (
<Textfield
key={dist.id}
fullWidth
formattedNumber
placeholder={`تعداد ${getSpeciesName(dist.species_code)}${dist.label ? ` (${dist.label})` : ""} — حداکثر: ${dist.maxCount.toLocaleString()}`}
value={counts[dist.id] ?? ""}
onChange={(e) =>
handleCountChange(dist.id, Number(e.target.value))
}
error={isOverMax}
helperText={helperText}
/>
);
})}
</>
)}
<Button disabled={!hasValidDists} type="submit">
ثبت
</Button>
</Grid>
</form>
);
};

View File

@@ -42,7 +42,7 @@ export const SubmitTagDistribution = ({ item, getData }: any) => {
? item?.distribution_type === "random" ? item?.distribution_type === "random"
? "random" ? "random"
: "group" : "group"
: "group" : "group",
); );
const [batches, setBatches] = useState<BatchItem[]>([]); const [batches, setBatches] = useState<BatchItem[]>([]);
@@ -116,25 +116,25 @@ export const SubmitTagDistribution = ({ item, getData }: any) => {
showToast( showToast(
isEdit ? "ویرایش با موفقیت انجام شد" : "ثبت با موفقیت انجام شد", isEdit ? "ویرایش با موفقیت انجام شد" : "ثبت با موفقیت انجام شد",
"success" "success",
); );
getData(); getData();
closeModal(); closeModal();
} catch (error: any) { } catch (error: any) {
showToast( showToast(
error?.response?.data?.message || "خطا در ثبت اطلاعات!", error?.response?.data?.message || "خطا در ثبت اطلاعات!",
"error" "error",
); );
} }
}; };
const speciesOptions = () => { const speciesOptions = () => {
return speciesData?.results?.map((opt: any) => { return (
return { speciesData?.results?.map((opt: any) => ({
key: opt?.value, key: opt?.value,
value: opt?.name, value: opt?.name,
}; })) ?? []
}); );
}; };
return ( return (
@@ -195,14 +195,14 @@ export const SubmitTagDistribution = ({ item, getData }: any) => {
items?.map((r: any) => { items?.map((r: any) => {
const existing = batches.find( const existing = batches.find(
(b) => (b) =>
b.batch_identity === r.key1 && b.species_code === r.key2 b.batch_identity === r.key1 && b.species_code === r.key2,
); );
return { return {
batch_identity: r.key1, batch_identity: r.key1,
species_code: r.key2, species_code: r.key2,
count: existing?.count ?? "", count: existing?.count ?? "",
}; };
}) || [] }) || [],
); );
}} }}
onChangeValue={(labels) => { onChangeValue={(labels) => {
@@ -210,7 +210,7 @@ export const SubmitTagDistribution = ({ item, getData }: any) => {
prev.map((item, index) => ({ prev.map((item, index) => ({
...item, ...item,
label: labels[index], label: labels[index],
})) })),
); );
}} }}
/> />
@@ -229,7 +229,7 @@ export const SubmitTagDistribution = ({ item, getData }: any) => {
species_code: k as number, species_code: k as number,
count: prev?.count ?? "", count: prev?.count ?? "",
}; };
}) }),
); );
}} }}
title="گونه" title="گونه"
@@ -245,12 +245,12 @@ export const SubmitTagDistribution = ({ item, getData }: any) => {
distributionType === "group" distributionType === "group"
? `تعداد ${ ? `تعداد ${
speciesOptions().find( speciesOptions().find(
(s: any) => s.key === batch.species_code (s: any) => s.key === batch.species_code,
)?.value )?.value
} (${batch.label}) ` } (${batch.label}) `
: `تعداد ${ : `تعداد ${
speciesOptions().find( speciesOptions().find(
(s: any) => s.key === batch.species_code (s: any) => s.key === batch.species_code,
)?.value )?.value
}` }`
} }
@@ -271,7 +271,7 @@ export const SubmitTagDistribution = ({ item, getData }: any) => {
b.count === "" || b.count === "" ||
b.count === undefined || b.count === undefined ||
b.count === null || b.count === null ||
Number(b.count) <= 0 Number(b.count) <= 0,
) )
} }
type="submit" type="submit"

View File

@@ -16,15 +16,19 @@ import Button from "../../components/Button/Button";
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 { SubmitTagDistribution } from "./SubmitTagDistribution"; import { SubmitTagDistribution } from "./SubmitTagDistribution";
import { DistributeFromDistribution } from "./DistributeFromDistribution";
import Table from "../../components/Table/Table"; import Table from "../../components/Table/Table";
import { BooleanQuestion } from "../../components/BooleanQuestion/BooleanQuestion"; import { BooleanQuestion } from "../../components/BooleanQuestion/BooleanQuestion";
import { TableButton } from "../../components/TableButton/TableButton"; import { TableButton } from "../../components/TableButton/TableButton";
import { DistributionSpeciesModal } from "./DistributionSpeciesModal"; import { DistributionSpeciesModal } from "./DistributionSpeciesModal";
import { useNavigate } from "@tanstack/react-router";
import { TAG_DISTRIBUTION } from "../../routes/paths";
export default function TagActiveDistributions() { export default function TagActiveDistributions() {
const { openModal } = useModalStore(); const { openModal } = useModalStore();
const [tableInfo, setTableInfo] = useState({ page: 1, page_size: 10 }); const [tableInfo, setTableInfo] = useState({ page: 1, page_size: 10 });
const [tagsTableData, setTagsTableData] = useState([]); const [tagsTableData, setTagsTableData] = useState([]);
const navigate = useNavigate();
const { data: tagsData, refetch } = useApiRequest({ const { data: tagsData, refetch } = useApiRequest({
api: "/tag/web/api/v1/tag_distribution_batch", api: "/tag/web/api/v1/tag_distribution_batch",
@@ -71,6 +75,8 @@ export default function TagActiveDistributions() {
item?.assigner_org?.name, item?.assigner_org?.name,
item?.assigned_org?.name, item?.assigned_org?.name,
item?.total_tag_count, item?.total_tag_count,
item?.total_distributed_tag_count,
item?.remaining_tag_count,
item?.distribution_type === "batch" ? "توزیع گروهی" : "توزیع تصادفی", item?.distribution_type === "batch" ? "توزیع گروهی" : "توزیع تصادفی",
<ShowMoreInfo key={item?.id} title="جزئیات توزیع"> <ShowMoreInfo key={item?.id} title="جزئیات توزیع">
<Grid container column className="gap-4 w-full"> <Grid container column className="gap-4 w-full">
@@ -81,6 +87,19 @@ export default function TagActiveDistributions() {
column column
className="gap-3 w-full rounded-xl border border-gray-200 dark:border-gray-700 p-4" 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 && ( {item?.distribution_type === "batch" && opt?.serial_from && (
<Grid container className="gap-2 items-center"> <Grid container className="gap-2 items-center">
<Bars3Icon className="w-5 h-5 text-gray-500 dark:text-gray-300" /> <Bars3Icon className="w-5 h-5 text-gray-500 dark:text-gray-300" />
@@ -105,20 +124,31 @@ export default function TagActiveDistributions() {
variant="body2" variant="body2"
className="text-gray-700 dark:text-gray-300" className="text-gray-700 dark:text-gray-300"
> >
{opt?.distributed_number?.toLocaleString()} {opt?.total_tag_count?.toLocaleString()}
</Typography> </Typography>
</Grid> </Grid>
<Grid container className="gap-2 items-center"> <Grid container className="gap-2 items-center">
<SparklesIcon className="w-5 h-5 text-gray-500 dark:text-gray-300" /> <CubeIcon className="w-5 h-5 text-gray-500 dark:text-gray-300" />
<Typography variant="body2" className="font-medium"> <Typography variant="body2" className="font-medium">
گونه: پلاک های توزیع شده:
</Typography> </Typography>
<Typography <Typography
variant="body2" variant="body2"
className="text-gray-700 dark:text-gray-300" className="text-gray-700 dark:text-gray-300"
> >
{speciesMap[opt?.species_code] ?? "-"} {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> </Typography>
</Grid> </Grid>
</Grid> </Grid>
@@ -126,6 +156,22 @@ export default function TagActiveDistributions() {
</Grid> </Grid>
</ShowMoreInfo>, </ShowMoreInfo>,
<Popover key={index}> <Popover key={index}>
<Tooltip title="جزيٓیات توزیع" position="right">
<Button
variant="detail"
page="tag_distribution_detail"
access="Show-Tag-Distribution-Detail"
onClick={() => {
const path =
TAG_DISTRIBUTION +
"/" +
item?.dist_batch_identity +
"/" +
item?.id;
navigate({ to: path });
}}
/>
</Tooltip>
<Tooltip title="ویرایش توزیع" position="right"> <Tooltip title="ویرایش توزیع" position="right">
<Button <Button
variant="edit" variant="edit"
@@ -144,6 +190,24 @@ export default function TagActiveDistributions() {
}} }}
/> />
</Tooltip> </Tooltip>
<Tooltip title="توزیع مجدد" position="right">
<Button
variant="share"
page="tag_distribution"
access="Distribute-From-Distribution"
onClick={() => {
openModal({
title: "توزیع مجدد",
content: (
<DistributeFromDistribution
getData={handleUpdate}
item={item}
/>
),
});
}}
/>
</Tooltip>
<Tooltip title={"لغو توزیع"} position="right"> <Tooltip title={"لغو توزیع"} position="right">
<Button <Button
page="tag_distribution" page="tag_distribution"
@@ -253,6 +317,8 @@ export default function TagActiveDistributions() {
"توزیع کننده", "توزیع کننده",
"دریافت کننده", "دریافت کننده",
"تعداد کل پلاک", "تعداد کل پلاک",
"پلاک های توزیع شده",
"پلاک های باقیمانده",
"نوع توزیع", "نوع توزیع",
"جزئیات توزیع", "جزئیات توزیع",
"عملیات", "عملیات",

View File

@@ -54,4 +54,5 @@ export const UNITS_SETTINGS = "/unit-settings";
export const TAGGING = "/tagging"; export const TAGGING = "/tagging";
export const TAGS = "/tags"; export const TAGS = "/tags";
export const TAG_DISTRIBUTION = "/tag-distribution"; export const TAG_DISTRIBUTION = "/tag-distribution";
export const TAG_DISTRIBUTION_DETAIL = "/tag-distribution/$identity/$id";
export const TAGS_BATCH = "/tags/$id/$from/$to"; export const TAGS_BATCH = "/tags/$id/$from/$to";

View File

@@ -25,6 +25,7 @@ import SettingsOfUnits from "../Pages/SettingsOfUnits";
import Tagging from "../Pages/Tagging"; import Tagging from "../Pages/Tagging";
import Tags from "../Pages/Tags"; import Tags from "../Pages/Tags";
import TagDistribtution from "../Pages/TagDistribution"; import TagDistribtution from "../Pages/TagDistribution";
import TagDistribtutionDetails from "../Pages/TagDistributionDetails";
export const managementCategoryItems = [ export const managementCategoryItems = [
{ {
@@ -188,6 +189,11 @@ export const taggingCategoryItems = [
path: R.TAG_DISTRIBUTION, path: R.TAG_DISTRIBUTION,
component: TagDistribtution, component: TagDistribtution,
}, },
{
name: "tag_distribution_detail",
path: R.TAG_DISTRIBUTION_DETAIL,
component: TagDistribtutionDetails,
},
]; ];
export const posCategoryItems = [ export const posCategoryItems = [

View File

@@ -103,6 +103,9 @@ export function getFaPermissions(permission: string) {
case "tag_distribution": case "tag_distribution":
faPermission = "توزیع پلاک"; faPermission = "توزیع پلاک";
break; break;
case "tag_distribution_detail":
faPermission = "جزئیات توزیع پلاک";
break;
default: default:
break; break;
} }

View File

@@ -1 +1 @@
02.60 02.64