feat(TopUpAgent): add , edit, delete , toggle ,...
This commit is contained in:
@@ -5,13 +5,12 @@
|
||||
// Individual APIs are now in separate files for better organization
|
||||
|
||||
export * from './authAPI';
|
||||
export { paymentsAPI } from './paymentsAPI';
|
||||
export { rolesAPI } from './rolesAPI';
|
||||
export { usersAPI } from './usersAPI';
|
||||
export { currencyAPI } from './currencyAPI';
|
||||
|
||||
export { countryAPI } from './countryAPI';
|
||||
export { provinceAPI } from './provinceAPI';
|
||||
export { cityAPI } from './cityAPI';
|
||||
export { issuerAPI } from './issuerAPI';
|
||||
export { listPermissions } from './permissionsAPI';
|
||||
export { generalAPI } from './generalAPI';
|
||||
export { paymentsAPI } from './paymentsAPI';
|
||||
export { currencyAPI } from './currencyAPI';
|
||||
export { topUpAgentAPI } from './topUpAgentAPI';
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useAuthStore } from "../store/authStore";
|
||||
// تنظیم BASE_URL
|
||||
// -----------------------------
|
||||
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL ||
|
||||
(import.meta.env.DEV ? "/" : "https://khalijpay-core.qaserver.ir");
|
||||
(import.meta.env.DEV ? "/" : "https://khalijpay-issuer.qaserver.ir");
|
||||
|
||||
// -----------------------------
|
||||
// ایجاد instance از axios
|
||||
@@ -43,38 +43,27 @@ if (typeof window !== 'undefined') {
|
||||
// Request interceptor
|
||||
// -----------------------------
|
||||
api.interceptors.request.use(config => {
|
||||
console.log("🔵 Request interceptor:", {
|
||||
url: config.url,
|
||||
fullUrl: config.baseURL + config.url,
|
||||
skipAuthRedirect: config?.skipAuthRedirect,
|
||||
method: config.method,
|
||||
data: config.data,
|
||||
headers: config.headers
|
||||
});
|
||||
|
||||
const skipAuthRedirect = config?.skipAuthRedirect === true;
|
||||
if (skipAuthRedirect) {
|
||||
// بررسی اینکه آیا درخواست به endpoint احراز هویت است یا نه
|
||||
const isAuthEndpoint = config.url?.includes('/Auth/SignIn') ||
|
||||
config.url?.includes('/Auth/SignOut') ||
|
||||
config.url?.includes('/Auth/ForgotPassword');
|
||||
|
||||
console.log("🔵 Auth endpoint check:", { isAuthEndpoint, url: config.url });
|
||||
config.url?.includes('/Auth/ForgotPassword') ||
|
||||
config.url?.includes('/Auth/User/Issuers') ||
|
||||
config.url?.includes('/Auth/Issuers');
|
||||
|
||||
// اگر endpoint احراز هویت است، اجازه ارسال درخواست را بدهیم (حتی اگر کاربر لاگین نباشد)
|
||||
// برای سایر endpointها با skipAuthRedirect، اگر کاربر لاگین نباشد، درخواست را cancel میکنیم
|
||||
// چون این endpointها نیاز به احراز هویت دارند
|
||||
if (!isAuthEndpoint) {
|
||||
const authState = useAuthStore.getState();
|
||||
console.log("🔵 Auth state:", { isLoggedIn: authState?.isLoggedIn });
|
||||
if (!authState?.isLoggedIn) {
|
||||
console.warn("⚠️ Canceling request - user not logged in");
|
||||
const CancelToken = axios.CancelToken;
|
||||
const source = CancelToken.source();
|
||||
source.cancel('User not logged in');
|
||||
config.cancelToken = source.token;
|
||||
config._skipRequest = true;
|
||||
}
|
||||
} else {
|
||||
console.log("✅ Allowing auth endpoint request");
|
||||
}
|
||||
}
|
||||
return config;
|
||||
@@ -84,57 +73,10 @@ api.interceptors.request.use(config => {
|
||||
// Response interceptor
|
||||
// -----------------------------
|
||||
api.interceptors.response.use(
|
||||
response => {
|
||||
console.log("🟢 Response interceptor - Success:", {
|
||||
url: response.config?.url,
|
||||
status: response.status,
|
||||
data: response.data
|
||||
});
|
||||
return response;
|
||||
},
|
||||
response => response,
|
||||
error => {
|
||||
console.log("🔴 Response interceptor - Error:", {
|
||||
url: error.config?.url,
|
||||
isSilent: error?.isSilent,
|
||||
isCancel: axios.isCancel(error),
|
||||
status: error?.response?.status,
|
||||
message: error?.message
|
||||
});
|
||||
|
||||
// لاگ کامل error.response
|
||||
console.log("🔴 Full error.response:", error.response);
|
||||
console.log("🔴 error.response exists:", !!error.response);
|
||||
|
||||
if (error.response) {
|
||||
console.log("🔴 error.response.status:", error.response.status);
|
||||
console.log("🔴 error.response.statusText:", error.response.statusText);
|
||||
console.log("🔴 error.response.headers:", error.response.headers);
|
||||
console.log("🔴 error.response.data exists:", !!error.response.data);
|
||||
console.log("🔴 error.response.data:", error.response.data);
|
||||
console.log("🔴 error.response.data type:", typeof error.response.data);
|
||||
|
||||
// بررسی اینکه آیا data یک string است
|
||||
if (typeof error.response.data === 'string') {
|
||||
console.log("🔴 Response data is string:", error.response.data);
|
||||
}
|
||||
|
||||
// بررسی اینکه آیا data یک object است
|
||||
if (error.response.data && typeof error.response.data === 'object') {
|
||||
console.log("🔴 Response data keys:", Object.keys(error.response.data));
|
||||
try {
|
||||
console.log("🔴 Response data (JSON):", JSON.stringify(error.response.data, null, 2));
|
||||
} catch (e) {
|
||||
console.log("🔴 Cannot stringify response.data:", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log("🔴 No error.response object");
|
||||
console.log("🔴 Full error object:", error);
|
||||
}
|
||||
|
||||
if (error?.isSilent) return Promise.reject(error);
|
||||
if (axios.isCancel(error)) {
|
||||
console.warn("⚠️ Request was canceled");
|
||||
return Promise.reject({ isSilent: true, isCancel: true, response: { status: 401, data: { message: 'Unauthorized' } }, config: error.config || {} });
|
||||
}
|
||||
|
||||
|
||||
@@ -4,12 +4,60 @@ import { useAuthStore } from "../store/authStore";
|
||||
// -----------------------------
|
||||
// Auth API
|
||||
// -----------------------------
|
||||
export async function login(email, password) {
|
||||
try {
|
||||
const res = await api.post("/api/v1/Auth/SignIn", { email: email, password }, { skipAuthRedirect: true });
|
||||
const data = res.data;
|
||||
|
||||
console.log("data login", data);
|
||||
// Get user issuers
|
||||
export async function getUserIssuers(email, password) {
|
||||
try {
|
||||
console.log("🔵 Requesting issuers from:", "/api/v1/Auth/User/Issuers");
|
||||
const res = await api.post("/api/v1/Auth/User/Issuers", { email, password }, { skipAuthRedirect: true });
|
||||
console.log("🟢 Response received:", res);
|
||||
const data = res.data;
|
||||
|
||||
// بررسی اینکه آیا پاسخ موفقیتآمیز است یا نه (پشتیبانی از isSuccess و IsSuccess)
|
||||
if (data && (data.isSuccess === false || data.IsSuccess === false)) {
|
||||
const errorMessage = data.message || data.Message || 'Failed to get issuers';
|
||||
const error = new Error(errorMessage);
|
||||
error.response = {
|
||||
...res,
|
||||
data: data,
|
||||
status: data.statusCode || data.StatusCode || 409
|
||||
};
|
||||
throw error;
|
||||
}
|
||||
|
||||
// استخراج لیست issuers از response
|
||||
// ممکن است پاسخ به صورت مستقیم array باشد یا در data باشد
|
||||
const issuers = Array.isArray(data) ? data : (data?.data || data || []);
|
||||
return Array.isArray(issuers) ? issuers : [];
|
||||
} catch (error) {
|
||||
// اگر خطای 404 است، پیام مناسب نمایش دهیم
|
||||
if (error?.response?.status === 404) {
|
||||
const customError = new Error('Endpoint not found. Please check the API configuration.');
|
||||
customError.response = error.response;
|
||||
throw customError;
|
||||
}
|
||||
|
||||
if (error.response) {
|
||||
const errorData = error.response.data || {};
|
||||
const errorMessage = errorData.message || errorData.Message || error.message || 'خطا در ارتباط با سرور';
|
||||
const customError = new Error(errorMessage);
|
||||
customError.response = error.response;
|
||||
throw customError;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Sign in with issuer
|
||||
export async function login(email, password, issuerId) {
|
||||
try {
|
||||
const requestBody = { email, password };
|
||||
if (issuerId) {
|
||||
requestBody.issuerId = issuerId;
|
||||
}
|
||||
|
||||
const res = await api.post("/api/v1/Auth/SignIn", requestBody, { skipAuthRedirect: true });
|
||||
const data = res.data;
|
||||
|
||||
// بررسی اینکه آیا پاسخ موفقیتآمیز است یا نه (پشتیبانی از isSuccess و IsSuccess)
|
||||
if (data && (data.isSuccess === false || data.IsSuccess === false)) {
|
||||
@@ -26,8 +74,6 @@ export async function login(email, password) {
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
|
||||
|
||||
// اگر خطا از سمت سرور است (500, 400, etc.)، آن را throw کنیم
|
||||
if (error.response) {
|
||||
const errorData = error.response.data || {};
|
||||
|
||||
@@ -17,15 +17,11 @@ export const cityAPI = {
|
||||
requestParams.provinceId = provinceId;
|
||||
}
|
||||
|
||||
console.log('🔵 City API - list request:', { params: requestParams });
|
||||
|
||||
const res = await api.get('/api/v1/City', {
|
||||
params: requestParams,
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
|
||||
console.log('🟢 City API - list response:', res?.data);
|
||||
|
||||
// پاسخ به صورت { data: { data: [...], filterSummary: {...} } } است
|
||||
return res?.data?.data?.data || [];
|
||||
},
|
||||
@@ -49,7 +45,6 @@ export const cityAPI = {
|
||||
ProvinceId: city?.provinceId || '',
|
||||
CityName: String(city?.cityName || '').trim(),
|
||||
};
|
||||
console.log('City API Update:', { cityId, payload });
|
||||
try {
|
||||
const res = await api.put(`/api/v1/City/${encodeURIComponent(cityId)}`, payload, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
|
||||
@@ -19,7 +19,6 @@ export const countryAPI = {
|
||||
try {
|
||||
const res = await api.get('/api/v1/Country/All', { skipAuthRedirect: true });
|
||||
// پاسخ به صورت { data: [...], statusCode: 200, isSuccess: true, ... } است
|
||||
console.log('🔵 Country API - listAll response:', res?.data);
|
||||
return res?.data?.data || [];
|
||||
} catch (error) {
|
||||
console.error('🔴 Country API - listAll error:', error);
|
||||
@@ -35,7 +34,6 @@ export const countryAPI = {
|
||||
CurrencyCode: String(country?.currencyCode || ''),
|
||||
TimeZone: String(country?.timeZoneName || country?.timeZone || ''),
|
||||
};
|
||||
console.log('🔵 Country API - create payload:', payload);
|
||||
const res = await api.post('/api/v1/Country', payload, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
},
|
||||
@@ -54,7 +52,6 @@ export const countryAPI = {
|
||||
};
|
||||
|
||||
const url = `/api/v1/Country/${encodeURIComponent(countryId)}`;
|
||||
console.log('🔵 Country API - update payload:', { url, countryId, payload });
|
||||
|
||||
try {
|
||||
const res = await api.put(url, payload, { skipAuthRedirect: true });
|
||||
|
||||
@@ -4,54 +4,84 @@ import api from './apiClient';
|
||||
// Currency API
|
||||
// -----------------------------
|
||||
export const currencyAPI = {
|
||||
// GET /api/v1/Currency
|
||||
async list() {
|
||||
const res = await api.get('/api/v1/Currency', { skipAuthRedirect: true });
|
||||
return res?.data?.data || [];
|
||||
// GET /api/v1/Currency (with pagination)
|
||||
async list(params = {}) {
|
||||
try {
|
||||
const queryParams = {
|
||||
currentPage: params.currentPage || 1,
|
||||
pageSize: params.pageSize || 1000,
|
||||
...params
|
||||
};
|
||||
|
||||
const res = await api.get('/api/v1/Currency', {
|
||||
params: queryParams,
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
|
||||
// Response might be: { data: [...], statusCode: 200, ... }
|
||||
// Or direct array: [...]
|
||||
const currencies = Array.isArray(res?.data)
|
||||
? res.data
|
||||
: (res?.data?.data || []);
|
||||
|
||||
return currencies;
|
||||
} catch (error) {
|
||||
console.error('🔴 Currency API - list error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// GET /api/v1/Currency/{id}
|
||||
async getById(id) {
|
||||
try {
|
||||
const res = await api.get(`/api/v1/Currency/${encodeURIComponent(id)}`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data?.data || res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 Currency API - getById error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// POST /api/v1/Currency
|
||||
async create(currencyCode) {
|
||||
const payload = { currencyCode: String(currencyCode || '') };
|
||||
const res = await api.post('/api/v1/Currency', payload, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
async create(data) {
|
||||
try {
|
||||
const res = await api.post('/api/v1/Currency', data, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data?.data || res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 Currency API - create error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// PATCH /api/v1/Currency/{currencyCode}/ToggleActivation
|
||||
async toggleActivation(currencyCode) {
|
||||
const res = await api.patch(`/api/v1/Currency/${encodeURIComponent(currencyCode)}/ToggleActivation`, null, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
// PUT /api/v1/Currency/{id}
|
||||
async update(id, data) {
|
||||
try {
|
||||
const res = await api.put(`/api/v1/Currency/${encodeURIComponent(id)}`, data, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data?.data || res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 Currency API - update error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// PATCH /api/v1/Currency/{currencyCode}/Maintenance/Enable
|
||||
async enableMaintenance(currencyCode, maintenanceMessage = null) {
|
||||
const payload = maintenanceMessage ? { maintenanceMessage } : {};
|
||||
const res = await api.patch(`/api/v1/Currency/${encodeURIComponent(currencyCode)}/Maintenance/Enable`, payload, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
},
|
||||
|
||||
// PATCH /api/v1/Currency/{currencyCode}/Maintenance/Disable
|
||||
async disableMaintenance(currencyCode) {
|
||||
const res = await api.patch(`/api/v1/Currency/${encodeURIComponent(currencyCode)}/Maintenance/Disable`, null, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
},
|
||||
|
||||
// PUT /api/v1/Currency/{currencyCode}/Permissions
|
||||
async updatePermissions(currencyCode, permissions) {
|
||||
const res = await api.put(`/api/v1/Currency/${encodeURIComponent(currencyCode)}/Permissions`, permissions, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
},
|
||||
|
||||
// PUT /api/v1/Currency/{currencyCode}/Limits
|
||||
async updateLimits(currencyCode, limits) {
|
||||
const res = await api.put(`/api/v1/Currency/${encodeURIComponent(currencyCode)}/Limits`, limits, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
},
|
||||
|
||||
// PUT /api/v1/Currency/{currencyCode}/Fees
|
||||
async updateFees(currencyCode, fees) {
|
||||
const res = await api.put(`/api/v1/Currency/${encodeURIComponent(currencyCode)}/Fees`, fees, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
// DELETE /api/v1/Currency/{id}
|
||||
async remove(id) {
|
||||
try {
|
||||
const res = await api.delete(`/api/v1/Currency/${encodeURIComponent(id)}`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data?.data || res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 Currency API - remove error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,582 +0,0 @@
|
||||
import api from './apiClient';
|
||||
|
||||
// -----------------------------
|
||||
// Issuer API
|
||||
// -----------------------------
|
||||
export const issuerAPI = {
|
||||
// GET /api/v1/Issuer (with pagination and filters)
|
||||
async list(params = {}) {
|
||||
const { currentPage = 1, pageSize = 100, isActive, supportCurrencyCode, supportCapabilities, ...otherParams } = params;
|
||||
const requestParams = { currentPage, pageSize, ...otherParams };
|
||||
|
||||
// اگر فیلترها وجود دارند، آنها را به params اضافه کن
|
||||
if (isActive !== undefined && isActive !== null && isActive !== '') {
|
||||
requestParams.isActive = isActive;
|
||||
}
|
||||
if (supportCurrencyCode) {
|
||||
requestParams.supportCurrencyCode = supportCurrencyCode;
|
||||
}
|
||||
if (supportCapabilities) {
|
||||
requestParams.supportCapabilities = supportCapabilities;
|
||||
}
|
||||
|
||||
console.log('🔵 Issuer API - list request:', { params: requestParams });
|
||||
|
||||
const res = await api.get('/api/v1/Issuer', {
|
||||
params: requestParams,
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
|
||||
console.log('🟢 Issuer API - list response:', res?.data);
|
||||
|
||||
// پاسخ به صورت { data: { data: [...], filterSummary: {...} } } است
|
||||
return res?.data?.data?.data || [];
|
||||
},
|
||||
|
||||
// GET /api/v1/Issuer/{id}
|
||||
async getById(id) {
|
||||
const res = await api.get(`/api/v1/Issuer/${encodeURIComponent(id)}`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
console.log('Full API response:', res?.data);
|
||||
console.log('API response data:', res?.data?.data);
|
||||
return res?.data?.data;
|
||||
},
|
||||
|
||||
// POST /api/v1/Issuer
|
||||
async create(issuer) {
|
||||
// Build payload according to AddIssuerCommand structure:
|
||||
// name (required), supportEmail (required), title (nullable), cityId (Guid nullable), postalCode, addressDetails (nullable)
|
||||
const payload = {
|
||||
name: String(issuer?.name || '').trim(),
|
||||
supportEmail: String(issuer?.supportEmail || '').trim(),
|
||||
postalCode: String(issuer?.postalCode || '').trim()
|
||||
};
|
||||
|
||||
// Add title only if provided (nullable field - don't send if empty)
|
||||
if (issuer?.title && String(issuer.title).trim()) {
|
||||
payload.title = String(issuer.title).trim();
|
||||
}
|
||||
|
||||
// Add addressDetails only if provided (nullable field - don't send if empty)
|
||||
const addressValue = String(issuer?.addressDetails || issuer?.address || '').trim();
|
||||
if (addressValue) {
|
||||
payload.addressDetails = addressValue;
|
||||
}
|
||||
|
||||
// Include cityId only if valid GUID (nullable Guid - don't send if null/empty)
|
||||
if (issuer?.cityId && issuer.cityId !== '' && issuer.cityId !== 'null' && issuer.cityId !== null) {
|
||||
// Validate GUID format (basic check)
|
||||
const guidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
||||
if (guidPattern.test(issuer.cityId)) {
|
||||
payload.cityId = issuer.cityId;
|
||||
} else {
|
||||
console.warn('⚠️ Invalid cityId GUID format:', issuer.cityId);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('🔵 Issuer Create Payload:', JSON.stringify(payload, null, 2));
|
||||
console.log('🔵 Issuer Create Payload (original):', issuer);
|
||||
|
||||
try {
|
||||
const res = await api.post('/api/v1/Issuer', payload, { skipAuthRedirect: true });
|
||||
console.log('🟢 Issuer Create Response:', res?.data);
|
||||
return res?.data;
|
||||
} catch (err) {
|
||||
console.error('🔴 Issuer Create Error:', {
|
||||
status: err?.response?.status,
|
||||
statusText: err?.response?.statusText,
|
||||
data: err?.response?.data,
|
||||
errors: err?.response?.data?.errors,
|
||||
message: err?.response?.data?.message,
|
||||
payload: payload
|
||||
});
|
||||
console.error('🔴 Full error.response:', err?.response);
|
||||
console.error('🔴 Full error.response.data:', err?.response?.data);
|
||||
console.error('🔴 Error response data type:', typeof err?.response?.data);
|
||||
if (err?.response?.data) {
|
||||
try {
|
||||
console.error('🔴 Error response data stringified:', JSON.stringify(err?.response?.data, null, 2));
|
||||
} catch (e) {
|
||||
console.error('🔴 Error response data (could not stringify):', err?.response?.data);
|
||||
console.error('🔴 Error response data toString:', String(err?.response?.data));
|
||||
}
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
|
||||
// PUT /api/v1/Issuer/{id}
|
||||
async update(id, issuer) {
|
||||
// Build payload according to UpdateIssuerCommand structure (similar to AddIssuerCommand)
|
||||
const payload = {
|
||||
name: String(issuer?.name || '').trim(),
|
||||
supportEmail: String(issuer?.supportEmail || '').trim(),
|
||||
postalCode: String(issuer?.postalCode || '').trim()
|
||||
};
|
||||
|
||||
// Add title if provided (nullable field)
|
||||
if (issuer?.title && String(issuer.title).trim()) {
|
||||
payload.title = String(issuer.title).trim();
|
||||
}
|
||||
|
||||
// Add addressDetails if provided (nullable field)
|
||||
const addressValue = String(issuer?.addressDetails || issuer?.address || '').trim();
|
||||
if (addressValue) {
|
||||
payload.addressDetails = addressValue;
|
||||
}
|
||||
|
||||
// Include cityId - validate GUID format
|
||||
if (issuer?.cityId && issuer.cityId !== '' && issuer.cityId !== 'null' && issuer.cityId !== null) {
|
||||
// Validate GUID format (basic check)
|
||||
const guidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
||||
if (guidPattern.test(issuer.cityId)) {
|
||||
payload.cityId = issuer.cityId;
|
||||
} else {
|
||||
console.warn('⚠️ Invalid cityId GUID format:', issuer.cityId);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('🔵 Issuer Update Payload:', JSON.stringify(payload, null, 2));
|
||||
|
||||
try {
|
||||
const res = await api.put(`/api/v1/Issuer/${encodeURIComponent(id)}`, payload, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
console.log('🟢 Issuer Update Response:', res?.data);
|
||||
return res?.data;
|
||||
} catch (err) {
|
||||
console.error('🔴 Issuer Update Error:', {
|
||||
status: err?.response?.status,
|
||||
statusText: err?.response?.statusText,
|
||||
data: err?.response?.data,
|
||||
errors: err?.response?.data?.errors,
|
||||
message: err?.response?.data?.message,
|
||||
payload: payload
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
|
||||
// DELETE /api/v1/Issuer/{id}
|
||||
async remove(id) {
|
||||
const res = await api.delete(`/api/v1/Issuer/${encodeURIComponent(id)}`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data;
|
||||
},
|
||||
|
||||
// PATCH /api/v1/Issuer/{id}/ToggleActivation
|
||||
async toggleActivation(id) {
|
||||
const res = await api.patch(`/api/v1/Issuer/${encodeURIComponent(id)}/ToggleActivation`, null, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data;
|
||||
},
|
||||
|
||||
// GET /api/v1/Issuer/{issuerId}/Capabilities
|
||||
async getCapabilities(issuerId) {
|
||||
try {
|
||||
console.log('🔵 Getting capabilities for issuer:', issuerId);
|
||||
const res = await api.get(`/api/v1/Issuer/${encodeURIComponent(issuerId)}/Capabilities`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
// Response structure: { data: [...], statusCode, isSuccess, ... }
|
||||
// Or direct array: [...]
|
||||
const capabilities = Array.isArray(res?.data) ? res.data : (res?.data?.data || []);
|
||||
console.log('🟢 Capabilities from API:', capabilities);
|
||||
return capabilities;
|
||||
} catch (err) {
|
||||
console.error('🔴 Error getting capabilities:', {
|
||||
status: err?.response?.status,
|
||||
data: err?.response?.data
|
||||
});
|
||||
// Handle 404 gracefully - endpoint might not exist for some issuers
|
||||
if (err?.response?.status === 404) {
|
||||
console.warn('⚠️ Capabilities endpoint not found (404), returning empty array');
|
||||
return [];
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
|
||||
// PUT /api/v1/Issuer/{issuerId}/Capabilities
|
||||
// Payload: IssuerManageCapabilitiesCommand { capabilities: List<IssuerCapabilityDto> }
|
||||
async updateCapabilities(issuerId, capabilities) {
|
||||
// Build IssuerCapabilityDto array from input
|
||||
// Each IssuerCapabilityDto should have: capability, capabilityName, hasCapability (or similar fields)
|
||||
const validCapabilities = Array.isArray(capabilities) ? capabilities
|
||||
.filter(cap => {
|
||||
// Filter out invalid capabilities
|
||||
if (typeof cap === 'string') {
|
||||
return cap && String(cap).trim() !== '';
|
||||
}
|
||||
if (typeof cap === 'object' && cap !== null) {
|
||||
const capabilityValue = cap.capability || cap.capabilityName || '';
|
||||
return capabilityValue && String(capabilityValue).trim() !== '';
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.map(cap => {
|
||||
// Convert to IssuerCapabilityDto format
|
||||
if (typeof cap === 'string') {
|
||||
return {
|
||||
capability: String(cap).trim(),
|
||||
capabilityName: String(cap).trim(),
|
||||
hasCapability: true
|
||||
};
|
||||
}
|
||||
|
||||
// If it's an object, ensure it has the required fields
|
||||
const capabilityValue = cap.capability || cap.capabilityName || '';
|
||||
const capabilityName = cap.capabilityName || cap.capability || String(capabilityValue).trim();
|
||||
const hasCapability = cap.hasCapability !== undefined ? Boolean(cap.hasCapability) : true;
|
||||
|
||||
return {
|
||||
capability: String(capabilityValue).trim(),
|
||||
capabilityName: String(capabilityName).trim() || String(capabilityValue).trim(),
|
||||
hasCapability: hasCapability
|
||||
};
|
||||
})
|
||||
.filter(cap => cap.capability && cap.capability.trim() !== '') : [];
|
||||
|
||||
// Wrap in IssuerManageCapabilitiesCommand structure
|
||||
const payload = {
|
||||
capabilities: validCapabilities
|
||||
};
|
||||
|
||||
console.log('🔵 Update Capabilities Payload:', JSON.stringify(payload, null, 2));
|
||||
console.log('🔵 Issuer ID:', issuerId);
|
||||
console.log('🔵 Valid capabilities count:', validCapabilities.length);
|
||||
|
||||
try {
|
||||
const res = await api.put(`/api/v1/Issuer/${encodeURIComponent(issuerId)}/Capabilities`, payload, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
console.log('🟢 Capabilities Update Response:', res?.data);
|
||||
return res?.data;
|
||||
} catch (err) {
|
||||
console.error('🔴 Capabilities update error:', {
|
||||
status: err?.response?.status,
|
||||
statusText: err?.response?.statusText,
|
||||
data: err?.response?.data,
|
||||
errors: err?.response?.data?.errors,
|
||||
message: err?.response?.data?.message,
|
||||
payload: payload
|
||||
});
|
||||
if (err?.response?.data) {
|
||||
try {
|
||||
console.error('🔴 Error response data stringified:', JSON.stringify(err?.response?.data, null, 2));
|
||||
} catch (e) {
|
||||
console.error('🔴 Error response data (could not stringify):', err?.response?.data);
|
||||
}
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
|
||||
// GET /api/v1/Issuer/{issuerId}/AllowedCurrencies
|
||||
// Response: { data: [{ currencyCode, currencyEnglishName, allowed }, ...], statusCode, ... }
|
||||
async getAllowedCurrencies(issuerId) {
|
||||
try {
|
||||
console.log('🔵 Getting allowed currencies for issuer:', issuerId);
|
||||
const res = await api.get(`/api/v1/Issuer/${encodeURIComponent(issuerId)}/AllowedCurrencies`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
// Response structure: { data: [{ currencyCode, currencyEnglishName, allowed }, ...], statusCode, ... }
|
||||
// Or direct array: [{ currencyCode, currencyEnglishName, allowed }, ...]
|
||||
const currencies = Array.isArray(res?.data) ? res.data : (res?.data?.data || []);
|
||||
console.log('🟢 Allowed Currencies from API:', currencies);
|
||||
return currencies;
|
||||
} catch (err) {
|
||||
console.error('🔴 Error getting allowed currencies:', {
|
||||
status: err?.response?.status,
|
||||
data: err?.response?.data
|
||||
});
|
||||
// Handle 404 gracefully - endpoint might not exist for some issuers
|
||||
if (err?.response?.status === 404) {
|
||||
console.warn('⚠️ AllowedCurrencies endpoint not found (404), returning empty array');
|
||||
return [];
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
|
||||
// PUT /api/v1/Issuer/{issuerId}/AllowedCurrencies
|
||||
// Payload: { allowedCurrencies: List<IssuerAllowedCurrencyDto> }
|
||||
async updateAllowedCurrencies(issuerId, allowedCurrencies) {
|
||||
// Build IssuerAllowedCurrencyDto array from input
|
||||
// Each should have: currencyCode, currencyEnglishName, allowed
|
||||
const currencyMap = new Map(); // Use Map to avoid duplicates
|
||||
|
||||
if (Array.isArray(allowedCurrencies)) {
|
||||
allowedCurrencies.forEach(curr => {
|
||||
const currencyCode = String(curr.currencyCode || curr.code || '').trim();
|
||||
if (!currencyCode) return; // Skip invalid currencies
|
||||
|
||||
// Use currencyCode as key to avoid duplicates
|
||||
if (!currencyMap.has(currencyCode)) {
|
||||
const currencyEnglishName = String(curr.currencyEnglishName || curr.name || '').trim();
|
||||
const allowed = curr.allowed !== undefined ? Boolean(curr.allowed) : true;
|
||||
|
||||
currencyMap.set(currencyCode, {
|
||||
currencyCode: currencyCode,
|
||||
currencyEnglishName: currencyEnglishName || currencyCode,
|
||||
allowed: allowed
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Convert Map to array
|
||||
const validCurrencies = Array.from(currencyMap.values());
|
||||
|
||||
// Wrap in command structure
|
||||
const payload = {
|
||||
allowedCurrencies: validCurrencies
|
||||
};
|
||||
|
||||
console.log('🔵 Update Allowed Currencies Payload:', JSON.stringify(payload, null, 2));
|
||||
console.log('🔵 Issuer ID:', issuerId);
|
||||
console.log('🔵 Valid currencies count:', validCurrencies.length);
|
||||
console.log('🔵 Currencies with allowed=true:', validCurrencies.filter(c => c.allowed).length);
|
||||
console.log('🔵 Currencies with allowed=false:', validCurrencies.filter(c => !c.allowed).length);
|
||||
console.log('🔵 Duplicate check - unique currency codes:', [...currencyMap.keys()]);
|
||||
|
||||
try {
|
||||
const res = await api.put(`/api/v1/Issuer/${encodeURIComponent(issuerId)}/AllowedCurrencies`, payload, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
console.log('🟢 Allowed Currencies Update Response:', res?.data);
|
||||
return res?.data;
|
||||
} catch (err) {
|
||||
console.error('🔴 Allowed Currencies update error:', {
|
||||
status: err?.response?.status,
|
||||
statusText: err?.response?.statusText,
|
||||
data: err?.response?.data,
|
||||
errors: err?.response?.data?.errors,
|
||||
message: err?.response?.data?.message,
|
||||
code: err?.response?.data?.code,
|
||||
payload: payload
|
||||
});
|
||||
console.error('🔴 Full error.response:', err?.response);
|
||||
if (err?.response?.data) {
|
||||
try {
|
||||
console.error('🔴 Error response data stringified:', JSON.stringify(err?.response?.data, null, 2));
|
||||
} catch (e) {
|
||||
console.error('🔴 Error response data (could not stringify):', err?.response?.data);
|
||||
console.error('🔴 Error response data toString:', String(err?.response?.data));
|
||||
}
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
|
||||
// ========== TopUpAgentManagement API ==========
|
||||
|
||||
// GET /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement
|
||||
async getTopUpAgentManagement(issuerId) {
|
||||
try {
|
||||
const res = await api.get(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data?.data || { maxAgents: 0, isActive: false };
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgentManagement GET error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// PUT /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement
|
||||
async updateTopUpAgentManagement(issuerId, maxAgents) {
|
||||
try {
|
||||
const payload = { maxAgents: Number(maxAgents) || 0 };
|
||||
const res = await api.put(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement`, payload, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgentManagement PUT error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// GET /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement/Currency
|
||||
async getTopUpAgentManagementCurrencies(issuerId) {
|
||||
try {
|
||||
const res = await api.get(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement/Currency`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return Array.isArray(res?.data?.data) ? res?.data?.data : [];
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgentManagement Currencies GET error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// GET /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement/Currency/{currencyCode}
|
||||
async getTopUpAgentManagementCurrency(issuerId, currencyCode) {
|
||||
try {
|
||||
const res = await api.get(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement/Currency/${encodeURIComponent(currencyCode)}`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data?.data || null;
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgentManagement Currency GET error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// POST /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement/Currency/{currencyCode}
|
||||
async createTopUpAgentManagementCurrency(issuerId, currencyCode, currencyData) {
|
||||
try {
|
||||
const payload = {
|
||||
voucherGeneratingFee: {
|
||||
percent: Number(currencyData.voucherGeneratingFee?.percent) || 0,
|
||||
fixed: Number(currencyData.voucherGeneratingFee?.fixed) || 0,
|
||||
minAmount: Number(currencyData.voucherGeneratingFee?.minAmount) || 0,
|
||||
maxAmount: Number(currencyData.voucherGeneratingFee?.maxAmount) || 0
|
||||
},
|
||||
agentMarketingFee: {
|
||||
percent: Number(currencyData.agentMarketingFee?.percent) || 0,
|
||||
fixed: Number(currencyData.agentMarketingFee?.fixed) || 0,
|
||||
minAmount: Number(currencyData.agentMarketingFee?.minAmount) || 0,
|
||||
maxAmount: Number(currencyData.agentMarketingFee?.maxAmount) || 0
|
||||
},
|
||||
agentWalletMaxBalanceLimit: {
|
||||
min: Number(currencyData.agentWalletMaxBalanceLimit?.min) || 0,
|
||||
max: Number(currencyData.agentWalletMaxBalanceLimit?.max) || 0
|
||||
},
|
||||
agentWalletDepositMonthlyLimit: {
|
||||
amount: Number(currencyData.agentWalletDepositMonthlyLimit?.amount) || 0
|
||||
}
|
||||
};
|
||||
const res = await api.post(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement/Currency/${encodeURIComponent(currencyCode)}`, payload, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgentManagement Currency POST error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// PUT /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement/Currency/{currencyCode}
|
||||
async updateTopUpAgentManagementCurrency(issuerId, currencyCode, currencyData) {
|
||||
try {
|
||||
const payload = {
|
||||
voucherGeneratingFee: {
|
||||
percent: Number(currencyData.voucherGeneratingFee?.percent) || 0,
|
||||
fixed: Number(currencyData.voucherGeneratingFee?.fixed) || 0,
|
||||
minAmount: Number(currencyData.voucherGeneratingFee?.minAmount) || 0,
|
||||
maxAmount: Number(currencyData.voucherGeneratingFee?.maxAmount) || 0
|
||||
},
|
||||
agentMarketingFee: {
|
||||
percent: Number(currencyData.agentMarketingFee?.percent) || 0,
|
||||
fixed: Number(currencyData.agentMarketingFee?.fixed) || 0,
|
||||
minAmount: Number(currencyData.agentMarketingFee?.minAmount) || 0,
|
||||
maxAmount: Number(currencyData.agentMarketingFee?.maxAmount) || 0
|
||||
},
|
||||
agentWalletMaxBalanceLimit: {
|
||||
min: Number(currencyData.agentWalletMaxBalanceLimit?.min) || 0,
|
||||
max: Number(currencyData.agentWalletMaxBalanceLimit?.max) || 0
|
||||
},
|
||||
agentWalletDepositMonthlyLimit: {
|
||||
amount: Number(currencyData.agentWalletDepositMonthlyLimit?.amount) || 0
|
||||
}
|
||||
};
|
||||
const res = await api.put(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement/Currency/${encodeURIComponent(currencyCode)}`, payload, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgentManagement Currency PUT error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// DELETE /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement/Currency/{currencyCode}
|
||||
async deleteTopUpAgentManagementCurrency(issuerId, currencyCode) {
|
||||
try {
|
||||
const res = await api.delete(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement/Currency/${encodeURIComponent(currencyCode)}`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgentManagement Currency DELETE error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// ========== TopUpAgentManagement Wallet API ==========
|
||||
|
||||
// GET /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement/Currency/{currencyCode}/Wallet/Balance
|
||||
async getTopUpAgentManagementWalletBalance(issuerId, currencyCode) {
|
||||
try {
|
||||
const res = await api.get(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement/Currency/${encodeURIComponent(currencyCode)}/Wallet/Balance`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data?.data || null;
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgentManagement Wallet Balance GET error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// POST /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement/Currency/{currencyCode}/Wallet/Deposit
|
||||
async depositTopUpAgentManagementWallet(issuerId, currencyCode, amount) {
|
||||
try {
|
||||
const payload = { amount: Number(amount) || 0 };
|
||||
const res = await api.post(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement/Currency/${encodeURIComponent(currencyCode)}/Wallet/Deposit`, payload, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgentManagement Wallet Deposit POST error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// GET /api/v1/issuer/{issuerId}/Capability/TopUpAgentManagement/Currency/{currencyCode}/Wallet/Transactions
|
||||
async getTopUpAgentManagementWalletTransactions(issuerId, currencyCode) {
|
||||
try {
|
||||
const res = await api.get(`/api/v1/issuer/${encodeURIComponent(issuerId)}/Capability/TopUpAgentManagement/Currency/${encodeURIComponent(currencyCode)}/Wallet/Transactions`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return Array.isArray(res?.data?.data) ? res?.data?.data : [];
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgentManagement Wallet Transactions GET error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// ========== Issuer Admin API ==========
|
||||
|
||||
// GET /api/v1/Issuer/{issuerId}/Admin
|
||||
async getAdmins(issuerId) {
|
||||
try {
|
||||
const res = await api.get(`/api/v1/Issuer/${encodeURIComponent(issuerId)}/Admin`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
// Response structure: { data: { data: [...], filterSummary: {...} }, statusCode, ... }
|
||||
return res?.data?.data?.data || [];
|
||||
} catch (error) {
|
||||
console.error('🔴 Issuer Admin GET error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// POST /api/v1/Issuer/{issuerId}/Admin
|
||||
async addAdmin(issuerId, adminData) {
|
||||
try {
|
||||
const res = await api.post(`/api/v1/Issuer/${encodeURIComponent(issuerId)}/Admin`, adminData, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 Issuer Admin POST error:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,28 +1,44 @@
|
||||
// -----------------------------
|
||||
// Payments API (mock data)
|
||||
// -----------------------------
|
||||
const mockData = {
|
||||
stats: { total: 1247, success: 1189, failed: 58 },
|
||||
payments: [
|
||||
{ id: 'TXN-001', user: 'John Doe', amount: 299.99, status: 'success', date: '2024-01-15T10:30:00Z', currency: 'USD' },
|
||||
{ id: 'TXN-002', user: 'Jane Smith', amount: 150.00, status: 'pending', date: '2024-01-15T11:45:00Z', currency: 'USD' },
|
||||
{ id: 'TXN-003', user: 'Bob Johnson', amount: 75.50, status: 'failed', date: '2024-01-15T12:15:00Z', currency: 'USD' },
|
||||
{ id: 'TXN-004', user: 'Alice Brown', amount: 450.00, status: 'success', date: '2024-01-15T13:20:00Z', currency: 'USD' },
|
||||
{ id: 'TXN-005', user: 'Charlie Wilson', amount: 89.99, status: 'success', date: '2024-01-15T14:30:00Z', currency: 'USD' }
|
||||
],
|
||||
chartData: [
|
||||
{ date: '2024-01-09', amount: 1200 },
|
||||
{ date: '2024-01-10', amount: 1900 },
|
||||
{ date: '2024-01-11', amount: 3000 },
|
||||
{ date: '2024-01-12', amount: 2800 },
|
||||
{ date: '2024-01-13', amount: 1890 },
|
||||
{ date: '2024-01-14', amount: 2390 },
|
||||
{ date: '2024-01-15', amount: 3490 }
|
||||
]
|
||||
};
|
||||
import api from './apiClient';
|
||||
|
||||
// -----------------------------
|
||||
// Payments API
|
||||
// -----------------------------
|
||||
export const paymentsAPI = {
|
||||
async getStats() { return mockData.stats; },
|
||||
async getChartData() { return mockData.chartData; },
|
||||
// GET /api/v1/Payments/Stats
|
||||
async getStats() {
|
||||
try {
|
||||
const res = await api.get('/api/v1/Payments/Stats', { skipAuthRedirect: true });
|
||||
// پاسخ ممکن است به صورت { data: {...}, statusCode: 200 } باشد
|
||||
return res?.data?.data || res?.data || {
|
||||
total: 0,
|
||||
success: 0,
|
||||
failed: 0
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('🔴 Payments API - getStats error:', error);
|
||||
// در صورت خطا، دادههای پیشفرض برگردان
|
||||
return {
|
||||
total: 0,
|
||||
success: 0,
|
||||
failed: 0
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// GET /api/v1/Payments/ChartData
|
||||
async getChartData() {
|
||||
try {
|
||||
const res = await api.get('/api/v1/Payments/ChartData', { skipAuthRedirect: true });
|
||||
// پاسخ ممکن است به صورت { data: [...], statusCode: 200 } باشد
|
||||
const data = res?.data?.data || res?.data || [];
|
||||
// اطمینان از اینکه دادهها به فرمت مورد نیاز هستند
|
||||
return Array.isArray(data) ? data : [];
|
||||
} catch (error) {
|
||||
console.error('🔴 Payments API - getChartData error:', error);
|
||||
// در صورت خطا، آرایه خالی برگردان
|
||||
return [];
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -14,15 +14,11 @@ export const provinceAPI = {
|
||||
requestParams.countryId = countryId;
|
||||
}
|
||||
|
||||
console.log('🔵 Province API - list request:', { params: requestParams });
|
||||
|
||||
const res = await api.get('/api/v1/Province', {
|
||||
params: requestParams,
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
|
||||
console.log('🟢 Province API - list response:', res?.data);
|
||||
|
||||
// پاسخ به صورت { data: { data: [...], filterSummary: {...} } } است
|
||||
return res?.data?.data?.data || [];
|
||||
},
|
||||
@@ -46,7 +42,6 @@ export const provinceAPI = {
|
||||
CountryId: province?.countryId || '',
|
||||
ProvinceName: String(province?.provinceName || '').trim(),
|
||||
};
|
||||
console.log('Province API Update:', { provinceId, payload });
|
||||
try {
|
||||
const res = await api.put(`/api/v1/Province/${encodeURIComponent(provinceId)}`, payload, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
import api from './apiClient';
|
||||
import { useAuthStore } from "../store/authStore";
|
||||
|
||||
// -----------------------------
|
||||
// Roles API
|
||||
// -----------------------------
|
||||
const ROLES_STORAGE_KEY = 'app_roles_v1';
|
||||
function readRolesFromStorage() { try { const raw = localStorage.getItem(ROLES_STORAGE_KEY); return raw ? JSON.parse(raw) : []; } catch { return []; } }
|
||||
function writeRolesToStorage(roles) { localStorage.setItem(ROLES_STORAGE_KEY, JSON.stringify(roles)); }
|
||||
function ensureSeedRoles() { if (readRolesFromStorage().length === 0) writeRolesToStorage([
|
||||
{ id: crypto.randomUUID(), name: 'Admin', permissions: ['read','write','delete'], userType: 'internal' },
|
||||
{ id: crypto.randomUUID(), name: 'Editor', permissions: ['read','write'], userType: 'internal' },
|
||||
{ id: crypto.randomUUID(), name: 'Viewer', permissions: ['read'], userType: 'external' },
|
||||
]); }
|
||||
|
||||
export const rolesAPI = {
|
||||
async list(queryOrOptions='') {
|
||||
const opts = typeof queryOrOptions === 'string' ? { nameQuery: queryOrOptions, currentPage:1, pageSize:100 } : { nameQuery: queryOrOptions?.nameQuery||'', currentPage: queryOrOptions?.currentPage||1, pageSize: queryOrOptions?.pageSize||100 };
|
||||
if (!useAuthStore.getState()?.isLoggedIn) { ensureSeedRoles(); return readRolesFromStorage().filter(r=>r.name.toLowerCase().includes((opts.nameQuery||'').toLowerCase())); }
|
||||
try {
|
||||
const res = await api.get('/api/v1/Role', { params: opts, skipAuthRedirect: true });
|
||||
const items = Array.isArray(res?.data?.data?.data) ? res.data.data.data : [];
|
||||
writeRolesToStorage(items.map(r => ({ id: r.id||crypto.randomUUID(), ...r })));
|
||||
return items;
|
||||
} catch { ensureSeedRoles(); return readRolesFromStorage(); }
|
||||
},
|
||||
|
||||
async create(role) {
|
||||
const payload = { name: String(role?.name||''), permissions: Array.isArray(role?.permissions)?role.permissions:[] };
|
||||
let created = payload;
|
||||
if (useAuthStore.getState()?.isLoggedIn) {
|
||||
try { const res = await api.post('/api/v1/Role', payload, { skipAuthRedirect:true }); created = res?.data||payload; } catch {}
|
||||
}
|
||||
const roles = readRolesFromStorage(); const newRole = { id: crypto.randomUUID(), ...created }; roles.push(newRole); writeRolesToStorage(roles); return newRole;
|
||||
},
|
||||
|
||||
async remove(id) {
|
||||
if (useAuthStore.getState()?.isLoggedIn) { try { await api.delete(`/api/v1/Role/${encodeURIComponent(id)}`, { skipAuthRedirect:true }); } catch {} }
|
||||
const roles = readRolesFromStorage(); writeRolesToStorage(roles.filter(r=>r.id!==id)); return { success:true };
|
||||
},
|
||||
|
||||
async update(id, role) {
|
||||
const payload = { name: String(role?.name||''), permissions: Array.isArray(role?.permissions)?role.permissions:[], userType: role?.userType||undefined };
|
||||
if (useAuthStore.getState()?.isLoggedIn) { try { await api.put(`/api/v1/Role/${encodeURIComponent(id)}`, payload, { skipAuthRedirect:true }); } catch {} }
|
||||
const roles = readRolesFromStorage(); const idx = roles.findIndex(r=>r.id===id); if(idx!==-1){ roles[idx]={...roles[idx], ...payload}; writeRolesToStorage(roles); return roles[idx]; }
|
||||
const updated={id,...payload}; roles.push(updated); writeRolesToStorage(roles); return updated;
|
||||
},
|
||||
};
|
||||
|
||||
209
src/services/topUpAgentAPI.js
Normal file
209
src/services/topUpAgentAPI.js
Normal file
@@ -0,0 +1,209 @@
|
||||
import api from './apiClient';
|
||||
|
||||
// -----------------------------
|
||||
// TopUpAgent API
|
||||
// -----------------------------
|
||||
export const topUpAgentAPI = {
|
||||
// GET /api/v1/TopUpAgent (with pagination)
|
||||
async list(params = {}) {
|
||||
const { currentPage = 1, pageSize = 10, ...otherParams } = params;
|
||||
const res = await api.get('/api/v1/TopUpAgent', {
|
||||
params: { currentPage, pageSize, ...otherParams },
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
|
||||
// بررسی ساختار response
|
||||
// ممکن است به صورت { data: { data: { data: [...] } } } باشد
|
||||
// یا { data: { data: [...] } } باشد
|
||||
// یا { data: [...] } باشد
|
||||
if (res?.data?.data?.data) {
|
||||
return Array.isArray(res.data.data.data) ? res.data.data.data : [];
|
||||
}
|
||||
if (res?.data?.data) {
|
||||
return Array.isArray(res.data.data) ? res.data.data : [];
|
||||
}
|
||||
if (res?.data) {
|
||||
return Array.isArray(res.data) ? res.data : [];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
|
||||
// GET /api/v1/TopUpAgent/{topUpAgentId}
|
||||
async getById(topUpAgentId) {
|
||||
try {
|
||||
const res = await api.get(`/api/v1/TopUpAgent/${encodeURIComponent(topUpAgentId)}`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data?.data || res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgent API - getById error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// POST /api/v1/TopUpAgent
|
||||
async create(topUpAgent) {
|
||||
const payload = {
|
||||
name: String(topUpAgent?.name || ''),
|
||||
supportEmail: String(topUpAgent?.supportEmail || ''),
|
||||
cityId: topUpAgent?.cityId || '',
|
||||
postalCode: String(topUpAgent?.postalCode || ''),
|
||||
addressDetails: String(topUpAgent?.addressDetails || ''),
|
||||
};
|
||||
const res = await api.post('/api/v1/TopUpAgent', payload, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
},
|
||||
|
||||
// PUT /api/v1/TopUpAgent/{topUpAgentId}
|
||||
async update(topUpAgentId, topUpAgent) {
|
||||
if (!topUpAgentId) {
|
||||
throw new Error('TopUpAgent ID is required');
|
||||
}
|
||||
const payload = {
|
||||
name: String(topUpAgent?.name || '').trim(),
|
||||
supportEmail: String(topUpAgent?.supportEmail || '').trim(),
|
||||
cityId: topUpAgent?.cityId || '',
|
||||
postalCode: String(topUpAgent?.postalCode || '').trim(),
|
||||
addressDetails: String(topUpAgent?.addressDetails || '').trim(),
|
||||
};
|
||||
const url = `/api/v1/TopUpAgent/${encodeURIComponent(topUpAgentId)}`;
|
||||
try {
|
||||
const res = await api.put(url, payload, { skipAuthRedirect: true });
|
||||
return res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgent API - update error:', {
|
||||
url,
|
||||
topUpAgentId,
|
||||
payload,
|
||||
error: error?.response?.data || error?.message || error
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// DELETE /api/v1/TopUpAgent/{topUpAgentId}
|
||||
async remove(topUpAgentId) {
|
||||
try {
|
||||
const res = await api.delete(`/api/v1/TopUpAgent/${encodeURIComponent(topUpAgentId)}`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgent API - remove error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// PATCH /api/v1/TopUpAgent/{topUpAgentId}/ToggleActivation
|
||||
async toggleActivation(topUpAgentId) {
|
||||
try {
|
||||
const res = await api.patch(`/api/v1/TopUpAgent/${encodeURIComponent(topUpAgentId)}/ToggleActivation`, null, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgent API - toggleActivation error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// POST /api/v1/TopUpAgent/{topUpAgentId}/Currency
|
||||
async addCurrency(topUpAgentId, currency) {
|
||||
const payload = {
|
||||
currencyCode: String(currency?.currencyCode || ''),
|
||||
voucherGenerationCommission: Number(currency?.voucherGenerationCommission || 0),
|
||||
};
|
||||
const res = await api.post(`/api/v1/TopUpAgent/${encodeURIComponent(topUpAgentId)}/Currency`, payload, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data;
|
||||
},
|
||||
|
||||
// GET /api/v1/TopUpAgent/{topUpAgentId}/Currency
|
||||
async getCurrencies(topUpAgentId) {
|
||||
try {
|
||||
const res = await api.get(`/api/v1/TopUpAgent/${encodeURIComponent(topUpAgentId)}/Currency`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data?.data || [];
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgent API - getCurrencies error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// GET /api/v1/TopUpAgent/{topUpAgentId}/Currency/{currencyCode}
|
||||
async getCurrency(topUpAgentId, currencyCode) {
|
||||
try {
|
||||
const res = await api.get(`/api/v1/TopUpAgent/${encodeURIComponent(topUpAgentId)}/Currency/${encodeURIComponent(currencyCode)}`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data?.data || res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgent API - getCurrency error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// PUT /api/v1/TopUpAgent/{topUpAgentId}/Currency/{currencyCode}
|
||||
async updateCurrency(topUpAgentId, currencyCode, currency) {
|
||||
const payload = {
|
||||
voucherGenerationCommission: Number(currency?.voucherGenerationCommission || 0),
|
||||
};
|
||||
const res = await api.put(`/api/v1/TopUpAgent/${encodeURIComponent(topUpAgentId)}/Currency/${encodeURIComponent(currencyCode)}`, payload, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data;
|
||||
},
|
||||
|
||||
// DELETE /api/v1/TopUpAgent/{topUpAgentId}/Currency/{currencyCode}
|
||||
async removeCurrency(topUpAgentId, currencyCode) {
|
||||
try {
|
||||
const res = await api.delete(`/api/v1/TopUpAgent/${encodeURIComponent(topUpAgentId)}/Currency/${encodeURIComponent(currencyCode)}`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgent API - removeCurrency error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// GET /api/v1/TopUpAgent/{topUpAgentId}/Wallet
|
||||
async getWallet(topUpAgentId) {
|
||||
try {
|
||||
const res = await api.get(`/api/v1/TopUpAgent/${encodeURIComponent(topUpAgentId)}/Wallet`, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data?.data || res?.data;
|
||||
} catch (error) {
|
||||
console.error('🔴 TopUpAgent API - getWallet error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// POST /api/v1/TopUpAgent/{topUpAgentId}/Wallet/{walletId}/Deposit
|
||||
async depositWallet(topUpAgentId, walletId, amount) {
|
||||
const payload = {
|
||||
amount: {
|
||||
amount: Number(amount?.amount || 0),
|
||||
currencyCode: String(amount?.currencyCode || ''),
|
||||
},
|
||||
};
|
||||
const res = await api.post(`/api/v1/TopUpAgent/${encodeURIComponent(topUpAgentId)}/Wallet/${encodeURIComponent(walletId)}/Deposit`, payload, {
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data;
|
||||
},
|
||||
|
||||
// GET /api/v1/TopUpAgent/{topUpAgentId}/Wallet/{walletId}/Transaction
|
||||
async getWalletTransactions(topUpAgentId, walletId, params = {}) {
|
||||
const { currentPage = 1, pageSize = 10, ...otherParams } = params;
|
||||
const res = await api.get(`/api/v1/TopUpAgent/${encodeURIComponent(topUpAgentId)}/Wallet/${encodeURIComponent(walletId)}/Transaction`, {
|
||||
params: { currentPage, pageSize, ...otherParams },
|
||||
skipAuthRedirect: true
|
||||
});
|
||||
return res?.data?.data?.data || [];
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
import api from './apiClient';
|
||||
|
||||
// -----------------------------
|
||||
// Users API با رولها
|
||||
// -----------------------------
|
||||
const USERS_STORAGE_KEY = 'app_users_v1';
|
||||
function readUsersFromStorage(){ try{ const raw = localStorage.getItem(USERS_STORAGE_KEY); return raw?JSON.parse(raw):[]; } catch{return [];} }
|
||||
function writeUsersToStorage(users){ localStorage.setItem(USERS_STORAGE_KEY, JSON.stringify(users)); }
|
||||
|
||||
export const usersAPI = {
|
||||
async list({searchQuery='',currentPage=1,pageSize=100}={}) {
|
||||
try {
|
||||
// اطمینان از اینکه params همیشه object است
|
||||
const params = {
|
||||
searchQuery: searchQuery || '',
|
||||
currentPage: currentPage || 1,
|
||||
pageSize: pageSize || 100
|
||||
};
|
||||
|
||||
console.log('🔵 Users API - list request:', {
|
||||
url: '/api/v1/User',
|
||||
method: 'GET',
|
||||
params
|
||||
});
|
||||
|
||||
const res = await api.get('/api/v1/User',{
|
||||
params,
|
||||
skipAuthRedirect:true
|
||||
});
|
||||
|
||||
console.log('🟢 Users API - list response:', res?.data);
|
||||
|
||||
return res?.data?.data?.data||[];
|
||||
} catch (error) {
|
||||
console.error('🔴 Users API - list error:', error);
|
||||
console.error('🔴 Error details:', {
|
||||
url: error.config?.url,
|
||||
method: error.config?.method,
|
||||
params: error.config?.params,
|
||||
data: error.config?.data,
|
||||
response: error.response?.data
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
async get(id){
|
||||
if (!id) throw new Error('User ID is required');
|
||||
const res = await api.get(`/api/v1/User/${encodeURIComponent(id)}`, { skipAuthRedirect: true });
|
||||
return res?.data?.data || res?.data;
|
||||
},
|
||||
async create(user){
|
||||
const payload = { firstName:String(user?.firstName||''), lastName:String(user?.lastName||''), email:String(user?.email||''), mobile:String(user?.mobile||''), isActive:!!user?.isActive };
|
||||
const res = await api.post('/api/v1/User',payload,{skipAuthRedirect:true});
|
||||
return res?.data;
|
||||
},
|
||||
async update(id,user){
|
||||
const payload = { firstName:String(user?.firstName||''), lastName:String(user?.lastName||''), email:String(user?.email||''), mobile:String(user?.mobile||''), isActive:!!user?.isActive };
|
||||
const res = await api.put(`/api/v1/User/${encodeURIComponent(id)}`,payload,{skipAuthRedirect:true});
|
||||
return res?.data;
|
||||
},
|
||||
async remove(id){
|
||||
const res = await api.delete(`/api/v1/User/Delete/${encodeURIComponent(id)}/Role`,{skipAuthRedirect:true});
|
||||
return res?.data;
|
||||
},
|
||||
async toggleActivation(id){ const res = await api.patch(`/api/v1/User/${encodeURIComponent(id)}/ToggleActivation`,null,{skipAuthRedirect:true}); return res?.data; },
|
||||
async resetPassword(id){ const res = await api.patch(`/api/v1/User/${encodeURIComponent(id)}/ResetPassword`,null,{skipAuthRedirect:true}); return res?.data; },
|
||||
async getRoles(userId){
|
||||
try {
|
||||
const res = await api.get(`/api/v1/User/${encodeURIComponent(userId)}/Role`, { skipAuthRedirect: true });
|
||||
return res?.data?.data || [];
|
||||
} catch(err) {
|
||||
console.error(err);
|
||||
return [];
|
||||
}
|
||||
},
|
||||
async removeRole(userId,roleId){ try{ const res = await api.delete(`/api/v1/User/${encodeURIComponent(userId)}/Role/${encodeURIComponent(roleId)}`,{skipAuthRedirect:true}); return res?.data; } catch(err){ console.error(err); return null; } },
|
||||
async updateRoles(userId,roleIds=[]){
|
||||
try{
|
||||
const res = await api.put(`/api/v1/User/${encodeURIComponent(userId)}/Role`,{roleIds},{skipAuthRedirect:true});
|
||||
return res?.data;
|
||||
} catch(err){
|
||||
console.error(err);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user