sync bank card api and complete it

This commit is contained in:
Alihaghighattalab
2024-08-13 17:50:42 +03:30
parent 25b09cf7b1
commit 3bbf577093
20 changed files with 130 additions and 100 deletions
+2 -1
View File
@@ -6,7 +6,8 @@ type Props = {
title: string
type?: "reset" | "button" | "submit" | undefined,
pending?: boolean,
theme?: "primary" | "secondary" | "glass" | "light"
theme?: "primary" | "secondary" | "glass" | "light",
onClick?: () => void
}
export const ButtonComponent: FC<Props> = ({ title, type = "button", pending = false, theme = "primary" }) => {
@@ -1,19 +1,17 @@
import { useQuery } from "@tanstack/react-query"
import { installationReportsCol } from "../../utility/reports"
import { Table } from "../common/table"
import { getReportsList } from "../../services/api/reports"
import { useState } from "react"
import { SortingState } from "@tanstack/react-table"
export const InstallationReports = () => {
const [sorting, setSorting] = useState<SortingState>([])
const { data, isLoading } = useQuery({
queryKey: ["installation-reports-list"],
queryFn: getReportsList
})
// const { data, isLoading } = useQuery({
// queryKey: ["installation-reports-list"],
// queryFn: getReportsList
// })
if (isLoading) return <p>LODING .....</p>
// if (isLoading) return <p>LODING .....</p>
return (
<Table columns={installationReportsCol} data={data?.data} sorting={sorting} setSorting={setSorting} />
<Table columns={installationReportsCol} data={[]} sorting={sorting} setSorting={setSorting} />
)
}
@@ -2,34 +2,40 @@ import { CardAdd } from "iconsax-react"
import { DialogComponent } from "../common/dialog"
import { FC } from "react"
import { Input } from "../common/input"
import { Button } from "@headlessui/react"
import { bankCarts, findBankByPAN } from "../../utility/cart"
import { Controller, SubmitHandler, useForm } from "react-hook-form"
import { AddNewCartInterface } from "../../types"
import { yupResolver } from "@hookform/resolvers/yup"
import { AddNewCardSchema } from "../../schema"
import { ErrorComponent } from "../common/error"
import { useMutation } from "@tanstack/react-query"
import { createNewCardMutation } from "../../services/api/bank-card"
import toast from "react-hot-toast"
import { ButtonComponent } from "../common/button"
type Props = {
isOpen: boolean,
close: () => void
}
export const AddNewCardDialog: FC<Props> = ({ isOpen, close }) => {
const { mutate, isPending } = useMutation({
mutationFn: createNewCardMutation
})
const { handleSubmit, formState: { errors }, control } = useForm<AddNewCartInterface>({
resolver: yupResolver(AddNewCardSchema)
})
const createNewCard: SubmitHandler<AddNewCartInterface> = async (data) => {
const finalData: any = {
id: bankCarts?.length + 1,
bankName: findBankByPAN(data.cartNumber).name,
bankPersianName: findBankByPAN(data.cartNumber).name_farsi,
cartNumber: data?.cartNumber.toString(),
cartOwner: `${data.name} ${data?.family}`,
shabaNumber: data?.shabaNumber,
}
console.log("final-data =>", finalData)
bankCarts.push(finalData)
close()
mutate({
holderName: `${data?.name} ${data?.family}`,
PAN: data?.PAN,
IBAN: data?.IBAN,
}, {
onSuccess: () => {
toast.success("کارت با موفقیت اضافه شد")
},
onError: () => {
toast.error("کارت با موفقیت اضافه نشد")
}
})
}
return (
<DialogComponent isOpen={isOpen} close={close} title="ایجاد حساب بانکی جدید" subTitle="لطفا اطلاعات را با دقت وارد نمایید" icon={<CardAdd color="#11212D" className="size-[50px]" />}>
@@ -47,22 +53,22 @@ export const AddNewCardDialog: FC<Props> = ({ isOpen, close }) => {
<ErrorComponent show={errors.family} message={errors.family?.message} />
</div>
)} />
<Controller control={control} name="cartNumber" render={({ field }) => (
<Controller control={control} name="PAN" render={({ field }) => (
<div>
<Input field={field} placeholder="شماره کارت" className="bg-auth-form" />
<ErrorComponent show={errors.cartNumber} message={errors.cartNumber?.message} />
<ErrorComponent show={errors.PAN} message={errors.PAN?.message} />
</div>
)} />
<Controller control={control} name="shabaNumber" render={({ field }) => (
<Controller control={control} name="IBAN" render={({ field }) => (
<div>
<Input field={field} placeholder="شماره شبا" className="bg-auth-form" />
<ErrorComponent show={errors.shabaNumber} message={errors.shabaNumber?.message} />
<ErrorComponent show={errors.IBAN} message={errors.IBAN?.message} />
</div>
)} />
</div>
<div className="flex flex-col gap-[6px]">
<Button type="submit" className="w-full bg-primary-color text-white">ایجاد حساب</Button>
<Button onClick={close} className="w-full bg-transparent text-primary-color">لغو</Button>
<ButtonComponent title="افزودن کارت" pending={isPending} type="submit" />
<ButtonComponent title="لغو" pending={isPending} type="button" theme="glass" onClick={close} />
</div>
</form>
</DialogComponent>
@@ -5,10 +5,11 @@ import { findBankByPAN, formatCartNumber } from "../../utility/cart"
type Props = {
item: BankCartInterface,
handleOpenDeleteDialog: () => void
handleOpenDeleteDialog: () => void,
setSelectedCard: (value: string | number | null) => void,
}
export const BankCart: FC<Props> = ({ item, handleOpenDeleteDialog }) => {
export const BankCart: FC<Props> = ({ item, handleOpenDeleteDialog, setSelectedCard }) => {
return (
<div className={`w-full flex flex-col justify-between rounded-[40px] bg-auth-form p-[18px] cursor-pointer bank-bg min-h-[226px]`} style={{ backgroundImage: `url('/svgs/banks/${item?.bankName}.svg')` }}>
<div className="flex flex-row justify-between items-center">
@@ -18,7 +19,7 @@ export const BankCart: FC<Props> = ({ item, handleOpenDeleteDialog }) => {
</div>
<div className="flex flex-row gap-3 items-center">
<Trash color="#777577" onClick={handleOpenDeleteDialog} />
<Edit color="#777577" />
<Edit color="#777577" onClick={() => setSelectedCard(item?.id)} />
</div>
</div>
<p className="font-medium text-2xl text-primary-text-color text-center" style={{ direction: "ltr" }}>{formatCartNumber(item?.cartNumber)}</p>
@@ -1,19 +1,34 @@
import { FC } from "react"
import { DialogComponent } from "../common/dialog"
import { Trash } from "iconsax-react"
import { Button } from "@headlessui/react"
import { useMutation } from "@tanstack/react-query"
import { deleteCardMutation } from "../../services/api/bank-card"
import toast from "react-hot-toast"
import { ButtonComponent } from "../common/button"
type Props = {
isOpen: boolean,
close: () => void
close: () => void,
id: string | number | null
}
export const DeleteCardDialog: FC<Props> = ({ isOpen, close }) => {
export const DeleteCardDialog: FC<Props> = ({ isOpen, close, id }) => {
const { mutate, isPending } = useMutation({
mutationFn: deleteCardMutation
})
const handleDeleteSelectedCard = async () => {
await mutate({
id
}, {
onSuccess: () => toast.success("کارت مورد نظر با موفقیت حذف شد"),
onError: () => toast.error("حذف کارت نا موفق")
})
}
return (
<DialogComponent isOpen={isOpen} close={close} title="حذف حساب بانکی" subTitle="از حذف حساب بانکی مربوطه اطمینان دارید؟" icon={<Trash color="#11212D" className="size-[50px]" />}>
<div className="flex flex-col gap-[6px] mt-10">
<Button className="w-full bg-primary-color text-white">حذف</Button>
<Button onClick={close} className="w-full bg-transparent text-primary-color">لغو</Button>
<ButtonComponent title="حذف" onClick={handleDeleteSelectedCard} pending={isPending} />
<ButtonComponent title="لغو" onClick={close} theme="glass" />
</div>
</DialogComponent>
)
@@ -1,6 +1,5 @@
import { useEffect, useState } from "react"
import { BankCartInterface } from "../../types"
import { bankCarts } from "../../utility/cart"
import { BankCart } from "./bank-cart"
import { CreateNewCart } from "./create-new-cart"
import { AddNewCardDialog } from "./add-new-cart-dialog"
@@ -9,6 +8,7 @@ import { useQuery } from "@tanstack/react-query"
import { getUserCardsList } from "../../services/api/bank-card"
export const ManagementBankAccounts = () => {
const [selectedCard, setSelectedCard] = useState<string | number | null>(null)
const { data, isLoading } = useQuery({
queryKey: ["bank-card"],
queryFn: getUserCardsList
@@ -29,10 +29,10 @@ export const ManagementBankAccounts = () => {
<>
<div className="w-full grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3 gap-6">
<CreateNewCart handleOpenDialog={handleOpenDialog} />
{bankCarts?.map((item: BankCartInterface) => <BankCart key={item?.id} item={item} handleOpenDeleteDialog={handleOpenDeleteDialog} />)}
{data?.data?.map((item: BankCartInterface) => <BankCart key={item?.id} item={item} handleOpenDeleteDialog={handleOpenDeleteDialog} setSelectedCard={setSelectedCard} />)}
</div>
<AddNewCardDialog isOpen={showDialog} close={handleCloseDialog} />
<DeleteCardDialog isOpen={showDeleteDialog} close={handleCloseDeleteDialog} />
<DeleteCardDialog isOpen={showDeleteDialog} close={handleCloseDeleteDialog} id={selectedCard} />
</>
)
}
+6 -8
View File
@@ -2,19 +2,17 @@ import { useState } from "react"
import { Table } from "../common/table"
import { SortingState } from "@tanstack/react-table"
import { scoresCol } from "../../utility/score"
import { useQuery } from "@tanstack/react-query"
import { getScoreList } from "../../services/api/score"
export const Score = () => {
const [sorting, setSorting] = useState<SortingState>([])
const { data, isLoading } = useQuery({
queryKey: ["score-list"],
queryFn: getScoreList
})
// const { data, isLoading } = useQuery({
// queryKey: ["score-list"],
// queryFn: getScoreList
// })
if (isLoading) return <p>LOADING ...</p>
// if (isLoading) return <p>LOADING ...</p>
return (
<Table sorting={sorting} setSorting={setSorting} columns={scoresCol} data={data?.data} tableStatus={true} />
<Table sorting={sorting} setSorting={setSorting} columns={scoresCol} data={[]} tableStatus={true} />
)
}
+6 -8
View File
@@ -2,17 +2,15 @@ import { useState } from "react"
import { Table } from "../common/table"
import { SortingState } from "@tanstack/react-table"
import { subscriptionsCol } from "../../utility/subscription"
import { useQuery } from "@tanstack/react-query"
import { getSubscriptionsList } from "../../services/api/subscription"
export const SubscriptionReport = () => {
const [sorting, setSorting] = useState<SortingState>([])
const { data, isLoading } = useQuery({
queryKey: ["suscriptions-list"],
queryFn: getSubscriptionsList
})
if (isLoading) return <p>LOADIN...</p>
// const { data, isLoading } = useQuery({
// queryKey: ["suscriptions-list"],
// queryFn: getSubscriptionsList
// })
// if (isLoading) return <p>LOADIN...</p>
return (
<Table sorting={sorting} setSorting={setSorting} columns={subscriptionsCol} data={data?.data} />
<Table sorting={sorting} setSorting={setSorting} columns={subscriptionsCol} data={[]} />
)
}
+6 -8
View File
@@ -2,19 +2,17 @@ import { useState } from "react"
import { Table } from "../common/table"
import { SortingState } from "@tanstack/react-table"
import { transactionsCol } from "../../utility/transactions"
import { useQuery } from "@tanstack/react-query"
import { getTransactionsList } from "../../services/api/transactions"
export const Transactions = () => {
const [sorting, setSorting] = useState<SortingState>([])
const { data, isLoading } = useQuery({
queryKey: ["transactions-list"],
queryFn: getTransactionsList
})
// const { data, isLoading } = useQuery({
// queryKey: ["transactions-list"],
// queryFn: getTransactionsList
// })
if (isLoading) return <p>LOADING ....</p>
// if (isLoading) return <p>LOADING ....</p>
return (
<Table sorting={sorting} setSorting={setSorting} columns={transactionsCol} data={data?.data} />
<Table sorting={sorting} setSorting={setSorting} columns={transactionsCol} data={[]} />
)
}
+5 -5
View File
@@ -100,14 +100,14 @@ export const MyAccountSchema = yup.object({
export const AddNewCardSchema = yup.object({
name: yup.string().required("وارد کردن نام الزامی میباشد").min(3, "نام نمیتواند کمتر از 3 کاراکتر باشد").max(20, "نام نمیتواند بیشتر از 20 کاراکتر باشد"),
family: yup.string().required("وارد کردن نام خانوادگی الزامی میباشد").min(3, "نام خانوادگی نمیتواند کمتر از 3 کاراکتر باشد").max(25, "نام خانوادگی نمیتواند بیشتر از 25 کاراکتر باشد"),
cartNumber: yup.string()
PAN: yup.string()
.required("وارد کردن شماره کارت الزامی میباشد")
.min(16, "شماره کارت نمیتوند کمتر از 16 رقم باشد")
.max(16, " شماره کارت نمیتواند بیشتر از 16 رقم باشد")
.matches(/^[0-9]{16}$/, "شماره کارت نامعتبر"),
shabaNumber: yup.string()
IBAN: yup.string()
.required("وارد کردن شماره شبا الزامی میباشد")
.min(24, "شماره شبا نمیتوند کمتر از 24 رقم باشد")
.max(24, " شماره شبا نمیتواند بیشتر از 24 رقم باشد")
.matches(/^[0-9]{24}$/, "شماره شبا نامعتبر"),
.min(26, "شماره شبا نمیتوند کمتر از 26 رقم باشد")
.max(26, " شماره شبا نمیتواند بیشتر از 26 رقم باشد")
.matches(/^IR[0-9]{24}$/, "شماره شبا نامعتبر"),
})
+1 -1
View File
@@ -1,3 +1,3 @@
import { axiosInstance } from "../axios";
import axiosInstance from "../axios";
export const loginMutation = (payload: any) => axiosInstance.post<any>("/auth/gps/login", payload)
+14 -3
View File
@@ -1,4 +1,15 @@
import { LoginFormInterface } from "../../types";
import { axiosInstance } from "../axios";
import axiosInstance from "../axios";
export const getUserCardsList = () => axiosInstance.get<LoginFormInterface>("/gps/bank-card")
type CreateNewCard = {
holderName: string,
PAN: string,
IBAN: string
}
type DeleteCard = {
id: string | number | null
}
export const createNewCardMutation = (payload: CreateNewCard) => axiosInstance.post<any>("/gps/bank-card", payload)
export const deleteCardMutation = (payload: DeleteCard) => axiosInstance.delete<any>(`/gps/bank-card/:${payload?.id}`)
export const getUserCardsList = () => axiosInstance.get<any>("/gps/bank-card")
-4
View File
@@ -1,4 +0,0 @@
import { installationReportsInterface } from "../../types";
import { axiosInstance } from "../axios";
export const getReportsList = () => axiosInstance.get<installationReportsInterface>("/reports")
-4
View File
@@ -1,4 +0,0 @@
import { ScoreInterface } from "../../types";
import { axiosInstance } from "../axios";
export const getScoreList = () => axiosInstance.get<ScoreInterface>("/score")
-4
View File
@@ -1,4 +0,0 @@
import { SubscriptionReportInterface } from "../../types";
import { axiosInstance } from "../axios";
export const getSubscriptionsList = () => axiosInstance.get<SubscriptionReportInterface>("/subscriptions")
-4
View File
@@ -1,4 +0,0 @@
import { TransactionsInterface } from "../../types";
import { axiosInstance } from "../axios";
export const getTransactionsList = () => axiosInstance.get<TransactionsInterface>("/transactions")
-10
View File
@@ -1,10 +0,0 @@
import axios, { AxiosRequestConfig } from "axios";
const axiosParam: AxiosRequestConfig = {
baseURL: "https://asan-service.com/api/",
headers: {
Authorization: `Bearer ${window.localStorage.getItem("token") && window.localStorage.getItem("token")}`,
}
}
export const axiosInstance = axios.create(axiosParam)
+16
View File
@@ -0,0 +1,16 @@
import axios from "axios";
const axiosInstance = axios.create({
baseURL: process.env.REACT_APP_API_Address,
});
axiosInstance.interceptors.request.use(async function (config) {
const search = window.location.search;
const params = new URLSearchParams(search)
const token = localStorage.getItem("token") ? localStorage.getItem("token") : params.get('token')
config.headers.Authorization = 'Bearer ' + token
return config;
});
export default axiosInstance;
+14
View File
@@ -0,0 +1,14 @@
import { create } from "zustand";
type UserType = {
token: string | null
}
const useUserStore = create<UserType>((set) => ({
token: '',
setToken: (token: string | null) => {
set({ token: token });
},
}));
export default useUserStore;
+2 -2
View File
@@ -101,8 +101,8 @@ export interface BanksInterface {
export interface AddNewCartInterface {
name: string
family: string
cartNumber: string
shabaNumber: string
PAN: string
IBAN: string
}
export interface installationReportsInterface {