added xl, and doc file allow to upload and getSubscription plan api properly
This commit is contained in:
parent
9648d1a98b
commit
6e89fbd680
@ -75,6 +75,15 @@ const AddPayment = ({ onClose }) => {
|
|||||||
<DatePicker
|
<DatePicker
|
||||||
name="paymentReceivedDate"
|
name="paymentReceivedDate"
|
||||||
control={control}
|
control={control}
|
||||||
|
minDate={
|
||||||
|
data?.clientSubmitedDate
|
||||||
|
? new Date(
|
||||||
|
new Date(data?.clientSubmitedDate).setDate(
|
||||||
|
new Date(data?.clientSubmitedDate).getDate() + 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
}
|
||||||
maxDate={new Date()}
|
maxDate={new Date()}
|
||||||
/>
|
/>
|
||||||
{errors.paymentReceivedDate && (
|
{errors.paymentReceivedDate && (
|
||||||
@ -90,7 +99,7 @@ const AddPayment = ({ onClose }) => {
|
|||||||
className="form-label"
|
className="form-label"
|
||||||
required
|
required
|
||||||
>
|
>
|
||||||
Payment Adjustment Head
|
Payment Adjustment Head
|
||||||
</Label>
|
</Label>
|
||||||
<select
|
<select
|
||||||
className="form-select form-select-sm "
|
className="form-select form-select-sm "
|
||||||
@ -100,12 +109,14 @@ const AddPayment = ({ onClose }) => {
|
|||||||
<option>Loading..</option>
|
<option>Loading..</option>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<option value="" >Select Payment Head</option>
|
<option value="">Select Payment Head</option>
|
||||||
{paymentTypes?.data?.sort((a, b) => a.name.localeCompare(b.name))?.map((type) => (
|
{paymentTypes?.data
|
||||||
<option key={type.id} value={type.id}>
|
?.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
{type.name}
|
?.map((type) => (
|
||||||
</option>
|
<option key={type.id} value={type.id}>
|
||||||
))}
|
{type.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</select>
|
</select>
|
||||||
@ -152,9 +163,9 @@ const AddPayment = ({ onClose }) => {
|
|||||||
<button
|
<button
|
||||||
type="reset"
|
type="reset"
|
||||||
className="btn btn-label-secondary btn-sm mt-3"
|
className="btn btn-label-secondary btn-sm mt-3"
|
||||||
onClick={()=>{
|
onClick={() => {
|
||||||
handleClose()
|
handleClose();
|
||||||
onClose()
|
onClose();
|
||||||
}}
|
}}
|
||||||
disabled={isPending}
|
disabled={isPending}
|
||||||
>
|
>
|
||||||
@ -230,12 +241,12 @@ const AddPayment = ({ onClose }) => {
|
|||||||
<div className="d-flex justify-content-between">
|
<div className="d-flex justify-content-between">
|
||||||
<span>{payment?.paymentAdjustmentHead?.name}</span>
|
<span>{payment?.paymentAdjustmentHead?.name}</span>
|
||||||
<span className="fs-semibold d-none d-md-block">
|
<span className="fs-semibold d-none d-md-block">
|
||||||
{formatFigure(payment.amount, {
|
{formatFigure(payment.amount, {
|
||||||
type: "currency",
|
type: "currency",
|
||||||
currency: "INR",
|
currency: "INR",
|
||||||
})}
|
})}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-tiny m-0 mt-1">
|
<p className="text-tiny m-0 mt-1">
|
||||||
{payment?.comment}
|
{payment?.comment}
|
||||||
</p>
|
</p>
|
||||||
|
@ -164,6 +164,31 @@ const ManageCollection = ({ collectionId, onClose }) => {
|
|||||||
<FormProvider {...methods}>
|
<FormProvider {...methods}>
|
||||||
<form onSubmit={handleSubmit(onSubmit)} className="p-0 text-start">
|
<form onSubmit={handleSubmit(onSubmit)} className="p-0 text-start">
|
||||||
<div className="row px-md-1 px-0">
|
<div className="row px-md-1 px-0">
|
||||||
|
<div className="col-12 col-md-6 mb-2">
|
||||||
|
<Label className="form-label" required>
|
||||||
|
Select Project
|
||||||
|
</Label>
|
||||||
|
<select
|
||||||
|
className="form-select form-select-sm"
|
||||||
|
{...register("projectId")}
|
||||||
|
>
|
||||||
|
<option value="">Select Project</option>
|
||||||
|
{projectLoading ? (
|
||||||
|
<option>Loading...</option>
|
||||||
|
) : (
|
||||||
|
projectNames?.map((project) => (
|
||||||
|
<option key={project.id} value={project.id}>
|
||||||
|
{project.name}
|
||||||
|
</option>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
{errors.projectId && (
|
||||||
|
<small className="danger-text">
|
||||||
|
{errors.projectId.message}
|
||||||
|
</small>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<div className="col-12 col-md-6 mb-2">
|
<div className="col-12 col-md-6 mb-2">
|
||||||
<Label required>Title</Label>
|
<Label required>Title</Label>
|
||||||
<input
|
<input
|
||||||
@ -215,7 +240,7 @@ const ManageCollection = ({ collectionId, onClose }) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="col-12 col-md-6 mb-2">
|
<div className="col-12 col-md-6 mb-2">
|
||||||
<Label required>Expected Date</Label>
|
<Label required>Expected Payment Date</Label>
|
||||||
<DatePicker
|
<DatePicker
|
||||||
name="exceptedPaymentDate"
|
name="exceptedPaymentDate"
|
||||||
control={control}
|
control={control}
|
||||||
@ -240,34 +265,10 @@ const ManageCollection = ({ collectionId, onClose }) => {
|
|||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="col-12 col-md-6 mb-2">
|
|
||||||
<Label className="form-label" required>
|
|
||||||
Select Project
|
|
||||||
</Label>
|
|
||||||
<select
|
|
||||||
className="form-select form-select-sm"
|
|
||||||
{...register("projectId")}
|
|
||||||
>
|
|
||||||
<option value="">Select Project</option>
|
|
||||||
{projectLoading ? (
|
|
||||||
<option>Loading...</option>
|
|
||||||
) : (
|
|
||||||
projectNames?.map((project) => (
|
|
||||||
<option key={project.id} value={project.id}>
|
|
||||||
{project.name}
|
|
||||||
</option>
|
|
||||||
))
|
|
||||||
)}
|
|
||||||
</select>
|
|
||||||
{errors.projectId && (
|
|
||||||
<small className="danger-text">
|
|
||||||
{errors.projectId.message}
|
|
||||||
</small>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="col-12 col-md-6 mb-2">
|
<div className="col-12 col-md-6 mb-2">
|
||||||
<Label htmlFor="basicAmount" className="form-label" required>
|
<Label htmlFor="basicAmount" className="form-label" required>
|
||||||
Amount
|
Basic Amount
|
||||||
</Label>
|
</Label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
@ -336,12 +337,23 @@ const ManageCollection = ({ collectionId, onClose }) => {
|
|||||||
<span className="text-muted d-block">
|
<span className="text-muted d-block">
|
||||||
Click to select or click here to browse
|
Click to select or click here to browse
|
||||||
</span>
|
</span>
|
||||||
<small className="text-muted">(PDF, JPG, PNG, max 5MB)</small>
|
<small className="text-muted">
|
||||||
|
(PDF, JPG, PNG,Doc,docx,xls,xlsx max 5MB)
|
||||||
|
</small>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
id="attachments"
|
id="attachments"
|
||||||
accept=".pdf,.jpg,.jpeg,.png"
|
accept="
|
||||||
|
.pdf,
|
||||||
|
.doc,
|
||||||
|
.docx,
|
||||||
|
.xls,
|
||||||
|
.xlsx,
|
||||||
|
.jpg,
|
||||||
|
.jpeg,
|
||||||
|
.png
|
||||||
|
"
|
||||||
multiple
|
multiple
|
||||||
style={{ display: "none" }}
|
style={{ display: "none" }}
|
||||||
{...register("attachments")}
|
{...register("attachments")}
|
||||||
|
@ -3,11 +3,16 @@ import { z } from "zod";
|
|||||||
const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
|
const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
|
||||||
const ALLOWED_TYPES = [
|
const ALLOWED_TYPES = [
|
||||||
"application/pdf",
|
"application/pdf",
|
||||||
|
"application/doc",
|
||||||
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||||
"image/png",
|
"image/png",
|
||||||
"image/jpg",
|
"image/jpg",
|
||||||
"image/jpeg",
|
"image/jpeg",
|
||||||
|
"application/vnd.ms-excel",
|
||||||
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
export const newCollection = z.object({
|
export const newCollection = z.object({
|
||||||
title: z.string().trim().min(1, { message: "Title is required" }),
|
title: z.string().trim().min(1, { message: "Title is required" }),
|
||||||
projectId: z.string().trim().min(1, { message: "Project is required" }),
|
projectId: z.string().trim().min(1, { message: "Project is required" }),
|
||||||
|
@ -32,6 +32,16 @@ export const useModal = (modalType) => {
|
|||||||
|
|
||||||
return { isOpen, onOpen, onClose, onToggle };
|
return { isOpen, onOpen, onClose, onToggle };
|
||||||
};
|
};
|
||||||
|
export const useSubscription = (frequency) => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["subscriptionPlans", frequency],
|
||||||
|
queryFn: async () => {
|
||||||
|
debugger
|
||||||
|
const resp = await AuthRepository.getSubscription(frequency);
|
||||||
|
return resp.data;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// -------------------APIHook-------------------------------------
|
// -------------------APIHook-------------------------------------
|
||||||
|
|
||||||
@ -85,8 +95,8 @@ export const useAuthModal = () => {
|
|||||||
|
|
||||||
export const useLogout = () => {
|
export const useLogout = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const naviget = useNavigate()
|
const naviget = useNavigate();
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async () => {
|
mutationFn: async () => {
|
||||||
@ -99,12 +109,12 @@ export const useLogout = () => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
queryClient.clear()
|
queryClient.clear();
|
||||||
removeSession();
|
removeSession();
|
||||||
dispatch(cacheProfileData(null))
|
dispatch(cacheProfileData(null));
|
||||||
|
|
||||||
// window.location.href = "/auth/login";
|
// window.location.href = "/auth/login";
|
||||||
naviget("/auth/login",{replace:true})
|
naviget("/auth/login", { replace: true });
|
||||||
if (onSuccessCallBack) onSuccessCallBack();
|
if (onSuccessCallBack) onSuccessCallBack();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -206,8 +206,8 @@ const LandingPage = () => {
|
|||||||
navigation={false}
|
navigation={false}
|
||||||
modules={[EffectFlip, Autoplay, Pagination, Navigation]}
|
modules={[EffectFlip, Autoplay, Pagination, Navigation]}
|
||||||
className="mySwiper"
|
className="mySwiper"
|
||||||
onSlideChange={() => console.log("slide change")}
|
onSlideChange={() => {}}
|
||||||
onSwiper={(swiper) => console.log(swiper)}
|
onSwiper={(swiper) => {}}
|
||||||
>
|
>
|
||||||
<SwiperSlide>
|
<SwiperSlide>
|
||||||
<SwaperSlideContent
|
<SwaperSlideContent
|
||||||
|
@ -2,37 +2,28 @@ import React, { useState, useEffect } from "react";
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import PlanCardSkeleton from "./PlanCardSkeleton";
|
import PlanCardSkeleton from "./PlanCardSkeleton";
|
||||||
|
import { useSubscription } from "../../hooks/useAuth";
|
||||||
|
|
||||||
const SubscriptionPlans = () => {
|
const SubscriptionPlans = () => {
|
||||||
const [plans, setPlans] = useState([]);
|
const [plans, setPlans] = useState([]);
|
||||||
const [frequency, setFrequency] = useState(1);
|
const [frequency, setFrequency] = useState(1);
|
||||||
|
const { data, isLoading, isError, error } = useSubscription(frequency);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const fetchPlans = async () => {
|
|
||||||
try {
|
|
||||||
setLoading(true);
|
|
||||||
const res = await axios.get(
|
|
||||||
`http://localhost:5032/api/market/list/subscription-plan?frequency=${frequency}`,
|
|
||||||
{ headers: { "Content-Type": "application/json" } }
|
|
||||||
);
|
|
||||||
setPlans(res.data?.data || []);
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Error fetching plans:", err);
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
fetchPlans();
|
|
||||||
}, [frequency]);
|
|
||||||
|
|
||||||
const frequencyLabel = (freq) => {
|
const frequencyLabel = (freq) => {
|
||||||
switch (freq) {
|
switch (freq) {
|
||||||
case 0: return "1 mo";
|
case 0:
|
||||||
case 1: return "3 mo";
|
return "1 mo";
|
||||||
case 2: return "6 mo";
|
case 1:
|
||||||
case 3: return "1 yr";
|
return "3 mo";
|
||||||
default: return "mo";
|
case 2:
|
||||||
|
return "6 mo";
|
||||||
|
case 3:
|
||||||
|
return "1 yr";
|
||||||
|
default:
|
||||||
|
return "mo";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -41,38 +32,49 @@ const SubscriptionPlans = () => {
|
|||||||
{/* Frequency Switcher */}
|
{/* Frequency Switcher */}
|
||||||
<div className="text-center mb-4">
|
<div className="text-center mb-4">
|
||||||
<div className="btn-group" role="group" aria-label="Plan frequency">
|
<div className="btn-group" role="group" aria-label="Plan frequency">
|
||||||
{["Monthly", "Quarterly", "Half-Yearly", "Yearly"].map((label, idx) => (
|
{["Monthly", "Quarterly", "Half-Yearly", "Yearly"].map(
|
||||||
<button
|
(label, idx) => (
|
||||||
key={idx}
|
<button
|
||||||
type="button"
|
key={idx}
|
||||||
className={`btn btn-${frequency === idx ? "primary" : "outline-secondary"}`}
|
type="button"
|
||||||
onClick={() => setFrequency(idx)}
|
className={`btn btn-${
|
||||||
>
|
frequency === idx ? "primary" : "outline-secondary"
|
||||||
{label}
|
}`}
|
||||||
</button>
|
onClick={() => setFrequency(idx)}
|
||||||
))}
|
>
|
||||||
|
{label}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Cards */}
|
{/* Cards */}
|
||||||
<div className="row g-4 mt-10">
|
<div className="row g-4 mt-10">
|
||||||
{loading ? (
|
{isLoading ? (
|
||||||
// Show 3 skeletons
|
// Show 3 skeletons
|
||||||
<>
|
<>
|
||||||
<PlanCardSkeleton />
|
<PlanCardSkeleton />
|
||||||
<PlanCardSkeleton />
|
<PlanCardSkeleton />
|
||||||
<PlanCardSkeleton />
|
<PlanCardSkeleton />
|
||||||
</>
|
</>
|
||||||
) : plans.length === 0 ? (
|
) : data.length === 0 ? (
|
||||||
<div className="text-center">No plans found</div>
|
<div className="text-center">No plans found</div>
|
||||||
|
) : isError ? (
|
||||||
|
<div className="text-start bg-light">
|
||||||
|
<p>{error.message}</p>
|
||||||
|
<p>{error.name}</p>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
plans.map((plan) => (
|
data.map((plan) => (
|
||||||
<div key={plan.id} className="col-xl-4 col-lg-6 col-md-6">
|
<div key={plan.id} className="col-xl-4 col-lg-6 col-md-6">
|
||||||
<div className="card h-100 shadow-lg border-0 p-3 text-center p-10">
|
<div className="card h-100 shadow-lg border-0 p-3 text-center p-10">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<i className="bx bxs-package text-primary fs-1 mb-2"></i>
|
<i className="bx bxs-package text-primary fs-1 mb-2"></i>
|
||||||
<p className="card-title fs-3 fw-bold mb-1">{plan.planName}</p>
|
<p className="card-title fs-3 fw-bold mb-1">
|
||||||
|
{plan.planName}
|
||||||
|
</p>
|
||||||
<p className="text-muted mb-0 fs-5">{plan.description}</p>
|
<p className="text-muted mb-0 fs-5">{plan.description}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -80,7 +82,9 @@ const SubscriptionPlans = () => {
|
|||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<h4 className="fw-semibold mt-auto mb-0 fs-3">
|
<h4 className="fw-semibold mt-auto mb-0 fs-3">
|
||||||
{plan.currency?.symbol} {plan.price}
|
{plan.currency?.symbol} {plan.price}
|
||||||
<small className="text-muted ms-1">/ {frequencyLabel(frequency)}</small>
|
<small className="text-muted ms-1">
|
||||||
|
/ {frequencyLabel(frequency)}
|
||||||
|
</small>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -133,7 +137,6 @@ const SubscriptionPlans = () => {
|
|||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -181,7 +181,7 @@ const CollectionPage = () => {
|
|||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
type="success"
|
type="success"
|
||||||
header="Payment Successful Received"
|
header="Payment Successful Received"
|
||||||
message="Your payment has been processed successfully. Do you want to continue?"
|
message="Payment has been recored successfully."
|
||||||
isOpen={processedPayment?.isOpen}
|
isOpen={processedPayment?.isOpen}
|
||||||
loading={isPending}
|
loading={isPending}
|
||||||
onSubmit={() => handleMarkedPayment(processedPayment?.invoiceId)}
|
onSubmit={() => handleMarkedPayment(processedPayment?.invoiceId)}
|
||||||
|
@ -10,6 +10,7 @@ const AuthRepository = {
|
|||||||
verifyOTP: (data) => api.postPublic("/api/auth/login-otp", data),
|
verifyOTP: (data) => api.postPublic("/api/auth/login-otp", data),
|
||||||
register: (data) => api.postPublic("/api/auth/register", data),
|
register: (data) => api.postPublic("/api/auth/register", data),
|
||||||
sendMail: (data) => api.postPublic("/api/auth/sendmail", data),
|
sendMail: (data) => api.postPublic("/api/auth/sendmail", data),
|
||||||
|
getSubscription:(frequency)=> api.getPublic(`/api/market/list/subscription-plan?frequency=${frequency}`),
|
||||||
|
|
||||||
// Protected routes (require auth token)
|
// Protected routes (require auth token)
|
||||||
logout: (data) => api.post("/api/auth/logout", data),
|
logout: (data) => api.post("/api/auth/logout", data),
|
||||||
@ -17,7 +18,9 @@ const AuthRepository = {
|
|||||||
changepassword: (data) => api.post("/api/auth/change-password", data),
|
changepassword: (data) => api.post("/api/auth/change-password", data),
|
||||||
appmenu: () => api.get('/api/appmenu/get/menu'),
|
appmenu: () => api.get('/api/appmenu/get/menu'),
|
||||||
selectTenant: (tenantId) => api.post(`/api/Auth/select-tenant/${tenantId}`),
|
selectTenant: (tenantId) => api.post(`/api/Auth/select-tenant/${tenantId}`),
|
||||||
getTenantList: () => api.get("/api/Auth/get/user/tenants"),
|
getTenantList: () => api.get("/api/Auth/get/user/tenants"),
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,7 +72,9 @@ axiosClient.interceptors.response.use(
|
|||||||
if (status === 401 && !isRefreshRequest) {
|
if (status === 401 && !isRefreshRequest) {
|
||||||
originalRequest._retry = true;
|
originalRequest._retry = true;
|
||||||
|
|
||||||
const refreshToken = localStorage.getItem("refreshToken") || sessionStorage.getItem("refreshToken");
|
const refreshToken =
|
||||||
|
localStorage.getItem("refreshToken") ||
|
||||||
|
sessionStorage.getItem("refreshToken");
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!refreshToken ||
|
!refreshToken ||
|
||||||
@ -87,7 +89,9 @@ axiosClient.interceptors.response.use(
|
|||||||
try {
|
try {
|
||||||
// Refresh token call
|
// Refresh token call
|
||||||
const res = await axiosClient.post("/api/Auth/refresh-token", {
|
const res = await axiosClient.post("/api/Auth/refresh-token", {
|
||||||
token: localStorage.getItem("jwtToken") || sessionStorage.getItem("jwtToken"),
|
token:
|
||||||
|
localStorage.getItem("jwtToken") ||
|
||||||
|
sessionStorage.getItem("jwtToken"),
|
||||||
refreshToken,
|
refreshToken,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -144,6 +148,11 @@ export const api = {
|
|||||||
headers: { ...customHeaders },
|
headers: { ...customHeaders },
|
||||||
authRequired: false,
|
authRequired: false,
|
||||||
}),
|
}),
|
||||||
|
getPublic: (url, data = {}, customHeaders = {}) =>
|
||||||
|
apiRequest("get", url, data, {
|
||||||
|
headers: { ...customHeaders },
|
||||||
|
authRequired: false,
|
||||||
|
}),
|
||||||
|
|
||||||
// Authenticated routes
|
// Authenticated routes
|
||||||
get: (url, params = {}, customHeaders = {}) =>
|
get: (url, params = {}, customHeaders = {}) =>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user