From e51f998a9163d92604d6ca35cbd152f5e2aeba59 Mon Sep 17 00:00:00 2001 From: wixarm Date: Tue, 3 Feb 2026 14:59:54 +0330 Subject: [PATCH] feat: postal inquiry --- src/Pages/PostcodeInquiry.tsx | 290 +++++++++++++++++++++++++++++++ src/config/menuItems.tsx | 5 + src/routes/paths.ts | 1 + src/routes/routeConfigs.ts | 2 + src/utils/checkMenuPermission.ts | 5 +- src/utils/getFaPermissions.ts | 3 + 6 files changed, 304 insertions(+), 2 deletions(-) create mode 100644 src/Pages/PostcodeInquiry.tsx diff --git a/src/Pages/PostcodeInquiry.tsx b/src/Pages/PostcodeInquiry.tsx new file mode 100644 index 0000000..ded5ae0 --- /dev/null +++ b/src/Pages/PostcodeInquiry.tsx @@ -0,0 +1,290 @@ +import React, { useState } from "react"; +import { Grid } from "../components/Grid/Grid"; +import Textfield from "../components/Textfeild/Textfeild"; +import { useApiMutation } from "../utils/useApiRequest"; +import { motion, AnimatePresence } from "framer-motion"; +import Typography from "../components/Typography/Typography"; +import { useToast } from "../hooks/useToast"; +import { + MapPinIcon, + BuildingOfficeIcon, + IdentificationIcon, +} from "@heroicons/react/24/outline"; +import Button from "../components/Button/Button"; + +interface PostcodeInquiryData { + avenue: string; + buildingName: string; + description: string; + floorNo: number | null; + houseNo: string; + houseNoSpecified: boolean; + location: string; + locationCode: string; + locationType: string; + parish: string | null; + postCode: string; + preAvenue: string; + sideFloor: number | null; + state: string; + townShip: string; + village: string; + zone: string; + address: string; + hasError: boolean; + errorMessage: string | null; + errorCode: number; +} + +interface PostcodeInquiryResponse { + status: boolean; + statusCode: number; + data: PostcodeInquiryData; + apiLogId: string; +} + +const PostcodeInquiry: React.FC = () => { + const [postcode, setPostcode] = useState(""); + const [inquiryData, setInquiryData] = useState( + null, + ); + const showToast = useToast(); + + const inquiryMutation = useApiMutation({ + api: "postcode-inquiry", + method: "get", + }); + + const handleSearch = async () => { + const trimmed = postcode.trim(); + + if (!trimmed) { + showToast("لطفا کد پستی را وارد کنید", "error"); + return; + } + + if (trimmed.length !== 10) { + showToast("کد پستی باید 10 رقم باشد", "error"); + return; + } + + try { + const result = await inquiryMutation.mutateAsync({ postcode: trimmed }); + + if (result?.status && result?.data) { + if (result.data.hasError) { + setInquiryData(null); + showToast(result.data.errorMessage || "نتیجه‌ای یافت نشد", "info"); + } else { + setInquiryData(result.data); + } + } else { + setInquiryData(null); + showToast("نتیجه‌ای یافت نشد", "info"); + } + } catch (error: any) { + console.error("Postcode inquiry error:", error); + showToast( + error?.response?.data?.message || "خطا در استعلام کد پستی", + "error", + ); + setInquiryData(null); + } + }; + + const handlePostcodeChange = (e: React.ChangeEvent) => { + const value = e.target.value; + const numericValue = value.replace(/\D/g, "").slice(0, 10); + setPostcode(numericValue); + }; + + const handleKeyPress = (e: React.KeyboardEvent) => { + if (e.key === "Enter") { + handleSearch(); + } + }; + + return ( + + + + + استعلام کد پستی + + + + + + + + + + + + + {inquiryData && ( + +
+ +
+
+
+ +
+
+ + نتیجه استعلام کد پستی + + + کد پستی: {inquiryData.postCode} + +
+
+
+ +
+ {inquiryData.address && ( +
+ +
+ + آدرس + + + {inquiryData.address} + +
+
+ )} + + {inquiryData.buildingName && ( +
+ +
+ + نام ساختمان + + + {inquiryData.buildingName} + +
+
+ )} + + {inquiryData.state && ( +
+ +
+ + استان + + + {inquiryData.state} + +
+
+ )} + + {inquiryData.townShip && ( +
+ +
+ + شهرستان + + + {inquiryData.townShip} + +
+
+ )} + + {inquiryData.locationCode && ( +
+ +
+ + کد شهر + + + {inquiryData.locationCode} + +
+
+ )} +
+
+
+
+ )} +
+
+ ); +}; + +export default PostcodeInquiry; diff --git a/src/config/menuItems.tsx b/src/config/menuItems.tsx index 7aab128..a40237c 100644 --- a/src/config/menuItems.tsx +++ b/src/config/menuItems.tsx @@ -33,6 +33,11 @@ export const getInspectionMenuItems = ( path: "/veterinarytransfer", component: () => import("../Pages/VeterinaryTransfer"), }, + { + name: "postcodeinquiry", + path: "/postcode-inquiry", + component: () => import("../Pages/PostcodeInquiry"), + }, ], }); } diff --git a/src/routes/paths.ts b/src/routes/paths.ts index d1bb4b2..453f117 100644 --- a/src/routes/paths.ts +++ b/src/routes/paths.ts @@ -14,3 +14,4 @@ export const AUTO_LOGIN_WITH_PARAMS = "/autologin/:key/:province"; export const NATIONAL_INFO = "/nationalinfo"; export const LADING_INFO = "/ladinginfo"; export const VETERINARY_TRANSFER = "/veterinarytransfer"; +export const POSTCODE_INQUIRY = "/postcode-inquiry"; diff --git a/src/routes/routeConfigs.ts b/src/routes/routeConfigs.ts index 9434109..e4defbe 100644 --- a/src/routes/routeConfigs.ts +++ b/src/routes/routeConfigs.ts @@ -11,6 +11,7 @@ import AutoLogin from "../Pages/AutoLogin"; import NationalInfo from "../Pages/NationalInfo"; import LadingInfo from "../Pages/LadingInfo"; import VeterinaryTransfer from "../Pages/VeterinaryTransfer"; +import PostcodeInquiry from "../Pages/PostcodeInquiry"; interface Route { path: string; @@ -30,6 +31,7 @@ export const getRoutes = (auth: string | null): Route[] => { { path: R.NATIONAL_INFO, component: NationalInfo }, { path: R.LADING_INFO, component: LadingInfo }, { path: R.VETERINARY_TRANSFER, component: VeterinaryTransfer }, + { path: R.POSTCODE_INQUIRY, component: PostcodeInquiry }, ]; if (checkIsMobile()) { diff --git a/src/utils/checkMenuPermission.ts b/src/utils/checkMenuPermission.ts index e8e3b14..22f45aa 100644 --- a/src/utils/checkMenuPermission.ts +++ b/src/utils/checkMenuPermission.ts @@ -1,6 +1,6 @@ export const checkMenuPermission = ( menuItemName: string, - userPermissions: string[] = [] + userPermissions: string[] = [], ): boolean => { if (userPermissions.includes("admin")) { return true; @@ -24,7 +24,7 @@ export const checkMenuPermission = ( export const checkRoutePermission = ( routePath: string, - userPermissions: string[] = [] + userPermissions: string[] = [], ): boolean => { if (userPermissions.includes("admin")) { return true; @@ -35,6 +35,7 @@ export const checkRoutePermission = ( "/inspections": ["admin", "submit"], "/statics": [], "/nationalinfo": ["admin"], + "/postcode-inquiry": ["admin"], }; const requiredPermissions = routePermissionMap[routePath] || []; diff --git a/src/utils/getFaPermissions.ts b/src/utils/getFaPermissions.ts index b6c91c3..7b51e22 100644 --- a/src/utils/getFaPermissions.ts +++ b/src/utils/getFaPermissions.ts @@ -22,6 +22,9 @@ export function getFaPermissions(permission: string) { case "veterinarytransfer": faPermission = "اطلاعات گواهی حمل"; break; + case "postcodeinquiry": + faPermission = "استعلام کد پستی"; + break; case "main": faPermission = "صفحه اصلی"; break;