feat: tag batch otp auth

This commit is contained in:
2026-02-18 12:25:09 +03:30
parent d9aed4d215
commit 4245dce136
3 changed files with 93 additions and 18 deletions

View File

@@ -12,7 +12,7 @@ export const OtpAuthModal = ({ item, getData }: any) => {
const [selectedUser, setSelectedUser] = useState<(string | number)[]>([]); const [selectedUser, setSelectedUser] = useState<(string | number)[]>([]);
const { data: usersData } = useApiRequest({ const { data: usersData } = useApiRequest({
api: `/auth/api/v1/organization/${item?.id}/org_users/`, api: `/auth/api/v1/organization/${item?.assigned_org?.id}/org_users/`,
method: "get", method: "get",
queryKey: ["orgUsers", item?.id], queryKey: ["orgUsers", item?.id],
}); });
@@ -23,7 +23,7 @@ export const OtpAuthModal = ({ item, getData }: any) => {
}); });
const usersOptions = const usersOptions =
usersData?.results?.map((user: any) => ({ usersData?.map((user: any) => ({
key: user?.user_receiver, key: user?.user_receiver,
value: `${user?.first_name} ${user?.last_name} - ${user?.mobile}`, value: `${user?.first_name} ${user?.last_name} - ${user?.mobile}`,
})) ?? []; })) ?? [];
@@ -31,7 +31,7 @@ export const OtpAuthModal = ({ item, getData }: any) => {
const onSubmit = async () => { const onSubmit = async () => {
if (selectedUser.length === 0) return; if (selectedUser.length === 0) return;
const selected = usersData?.results?.find( const selected = usersData?.find(
(u: any) => u.user_receiver === selectedUser[0], (u: any) => u.user_receiver === selectedUser[0],
); );

View File

@@ -0,0 +1,46 @@
import { useState } from "react";
import { Grid } from "../../components/Grid/Grid";
import Button from "../../components/Button/Button";
import Textfield from "../../components/Textfeild/Textfeild";
import { useApiMutation } from "../../utils/useApiRequest";
import { useToast } from "../../hooks/useToast";
import { useModalStore } from "../../context/zustand-store/appStore";
export const OtpVerifyModal = ({ item, getData }: any) => {
const showToast = useToast();
const { closeModal } = useModalStore();
const [code, setCode] = useState("");
const mutation = useApiMutation({
api: `/tag/web/api/v1/tag_distribution_batch/${item?.id}/otp_auth/?otp_type=check`,
method: "post",
});
const onSubmit = async () => {
if (!code) return;
try {
await mutation.mutateAsync({ code: String(code) });
showToast("احراز با موفقیت انجام شد", "success");
getData();
closeModal();
} catch (error: any) {
showToast(error?.response?.data?.message || "خطا در احراز!", "error");
}
};
return (
<Grid container column className="gap-3">
<Textfield
fullWidth
placeholder="کد احراز"
value={code}
onChange={(e) => setCode(e.target.value)}
/>
<Button disabled={!code} onClick={onSubmit}>
تایید
</Button>
</Grid>
);
};

View File

@@ -2,6 +2,7 @@ import { useEffect, useState } from "react";
import { import {
Bars3Icon, Bars3Icon,
CheckBadgeIcon, CheckBadgeIcon,
ClockIcon,
CubeIcon, CubeIcon,
SparklesIcon, SparklesIcon,
StopCircleIcon, StopCircleIcon,
@@ -24,6 +25,7 @@ import { BooleanQuestion } from "../../components/BooleanQuestion/BooleanQuestio
import { TableButton } from "../../components/TableButton/TableButton"; import { TableButton } from "../../components/TableButton/TableButton";
import { DistributionSpeciesModal } from "./DistributionSpeciesModal"; import { DistributionSpeciesModal } from "./DistributionSpeciesModal";
import { OtpAuthModal } from "./OtpAuthModal"; import { OtpAuthModal } from "./OtpAuthModal";
import { OtpVerifyModal } from "./OtpVerifyModal";
import { useNavigate } from "@tanstack/react-router"; import { useNavigate } from "@tanstack/react-router";
import { TAG_DISTRIBUTION } from "../../routes/paths"; import { TAG_DISTRIBUTION } from "../../routes/paths";
import { DocumentOperation } from "../../components/DocumentOperation/DocumentOperation"; import { DocumentOperation } from "../../components/DocumentOperation/DocumentOperation";
@@ -224,29 +226,56 @@ export default function TagActiveDistributions() {
تایید سند خروج تایید سند خروج
</Button> </Button>
), ),
item?.otp_status ? ( item?.otp_status === "accept" ? (
<span className="flex items-center gap-1 text-green-600 dark:text-green-400"> <span className="flex items-center gap-1 text-green-600 dark:text-green-400">
احراز شده
<CheckBadgeIcon className="w-5 h-5" /> <CheckBadgeIcon className="w-5 h-5" />
احراز شده
</span>
) : item?.otp_status === "pending" ? (
<span className="flex items-center gap-1 text-yellow-500 dark:text-yellow-400">
<ClockIcon className="w-5 h-5" />
ارسال شده
</span> </span>
) : ( ) : (
<span className="flex items-center gap-1 text-red-500 dark:text-red-400"> <span className="flex items-center gap-1 text-red-500 dark:text-red-400">
احراز نشده
<XCircleIcon className="w-5 h-5" /> <XCircleIcon className="w-5 h-5" />
ارسال نشده
</span> </span>
), ),
<Button item?.otp_status !== "accept" ? (
key={`otp-${item?.id}`} <Grid key={`otp-${item?.id}`} container className="gap-2">
size="small" <Button
onClick={() => { size="small"
openModal({ onClick={() => {
title: "ارسال پیامک احراز", openModal({
content: <OtpAuthModal item={item} getData={handleUpdate} />, title: "ارسال پیامک احراز",
}); content: (
}} <OtpAuthModal item={item} getData={handleUpdate} />
> ),
ارسال کد });
</Button>, }}
>
{item?.otp_status === "unsend" ? "ارسال کد" : "ارسال مجدد"}
</Button>
{item?.otp_status === "pending" && (
<Button
size="small"
onClick={() => {
openModal({
title: "ورود کد احراز",
content: (
<OtpVerifyModal item={item} getData={handleUpdate} />
),
});
}}
>
ورود کد احراز
</Button>
)}
</Grid>
) : (
"احراز شده"
),
<Popover key={index}> <Popover key={index}>
<Tooltip title="جزئیات توزیع" position="right"> <Tooltip title="جزئیات توزیع" position="right">
<Button <Button