sync profile api
This commit is contained in:
@@ -59,17 +59,58 @@ export const AuthProvider = ({ children }) => {
|
||||
const userData = await AsyncStorage.getItem('user_data');
|
||||
|
||||
if (token && userData) {
|
||||
const user = JSON.parse(userData);
|
||||
console.log('🔄 Found cached auth data, loading user...');
|
||||
console.log('🎫 Token:', `${token.slice(0, 20)}...`);
|
||||
console.log('👤 Cached user:', user);
|
||||
|
||||
dispatch({
|
||||
type: 'LOGIN_SUCCESS',
|
||||
payload: {
|
||||
token,
|
||||
user: JSON.parse(userData),
|
||||
},
|
||||
payload: { token, user },
|
||||
});
|
||||
|
||||
// Try to refresh profile data in background
|
||||
console.log('🔄 Refreshing profile in background...');
|
||||
try {
|
||||
const freshProfileData = await authService.getProfile();
|
||||
console.log('👤 Fresh profile data:', freshProfileData);
|
||||
|
||||
// Validate fresh data
|
||||
if (freshProfileData.name && freshProfileData.phone) {
|
||||
// Update cached data
|
||||
await AsyncStorage.setItem('user_data', JSON.stringify(freshProfileData));
|
||||
|
||||
console.log('✅ Profile refreshed successfully on app startup');
|
||||
|
||||
// Update state with fresh data
|
||||
dispatch({
|
||||
type: 'LOGIN_SUCCESS',
|
||||
payload: { token, user: freshProfileData },
|
||||
});
|
||||
} else {
|
||||
console.warn('⚠️ Fresh profile data is invalid, keeping cached data');
|
||||
}
|
||||
} catch (profileError) {
|
||||
console.warn('⚠️ Could not refresh profile on startup:', profileError.message);
|
||||
|
||||
// Check if it's a token expiration error
|
||||
if (profileError.message.includes('Session expired')) {
|
||||
console.log('🔓 Token expired, clearing auth data');
|
||||
await AsyncStorage.removeItem('auth_token');
|
||||
await AsyncStorage.removeItem('user_data');
|
||||
dispatch({ type: 'LOGOUT' });
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, continue with cached data
|
||||
console.log('📦 Using cached user data');
|
||||
}
|
||||
} else {
|
||||
console.log('🔍 No cached auth data found');
|
||||
dispatch({ type: 'LOADING', payload: false });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('💥 Error checking auth status:', error.message);
|
||||
dispatch({ type: 'LOADING', payload: false });
|
||||
}
|
||||
};
|
||||
@@ -117,23 +158,47 @@ export const AuthProvider = ({ children }) => {
|
||||
}
|
||||
|
||||
dispatch({ type: 'LOADING', payload: true });
|
||||
const response = await authService.verify(state.pendingVerification.phone, code);
|
||||
|
||||
// Assuming the API returns a token after successful verification
|
||||
// You might need to adjust this based on your actual API response
|
||||
const token = response.token || 'dummy_token_for_demo';
|
||||
const user = response.user || { phone: state.pendingVerification.phone };
|
||||
// Step 1: Verify the code and get the token
|
||||
const verificationResponse = await authService.verify(state.pendingVerification.phone, code);
|
||||
|
||||
// Store auth data
|
||||
console.log('🔍 Verification Response:', verificationResponse);
|
||||
|
||||
// Extract data from your API response structure
|
||||
if (!verificationResponse.success) {
|
||||
dispatch({ type: 'LOADING', payload: false });
|
||||
return { success: false, error: verificationResponse.message || 'Verification failed' };
|
||||
}
|
||||
|
||||
const token = verificationResponse.token;
|
||||
const basicUserData = verificationResponse.user;
|
||||
|
||||
if (!token) {
|
||||
dispatch({ type: 'LOADING', payload: false });
|
||||
return { success: false, error: 'No access token received from verification' };
|
||||
}
|
||||
|
||||
console.log('✅ Token received:', `${token.slice(0, 20)}...`);
|
||||
console.log('👤 Basic user data:', basicUserData);
|
||||
|
||||
// Step 2: Cache auth data (token and user data from verification)
|
||||
await AsyncStorage.setItem('auth_token', token);
|
||||
await AsyncStorage.setItem('user_data', JSON.stringify(user));
|
||||
await AsyncStorage.setItem('user_data', JSON.stringify(basicUserData));
|
||||
|
||||
console.log('✅ Auth data cached successfully');
|
||||
console.log('🎫 Token stored:', `${token.slice(0, 20)}...`);
|
||||
console.log('👤 User data cached:', basicUserData);
|
||||
|
||||
dispatch({
|
||||
type: 'LOGIN_SUCCESS',
|
||||
payload: { token, user },
|
||||
payload: { token, user: basicUserData },
|
||||
});
|
||||
|
||||
return { success: true, message: response.message };
|
||||
return {
|
||||
success: true,
|
||||
message: verificationResponse.message,
|
||||
user: basicUserData
|
||||
};
|
||||
} catch (error) {
|
||||
dispatch({ type: 'LOADING', payload: false });
|
||||
return { success: false, error: error.message };
|
||||
@@ -154,6 +219,66 @@ export const AuthProvider = ({ children }) => {
|
||||
dispatch({ type: 'CLEAR_PENDING_VERIFICATION' });
|
||||
};
|
||||
|
||||
const updateUserProfile = async (profileData) => {
|
||||
try {
|
||||
const response = await authService.updateProfile(profileData);
|
||||
const updatedUser = { ...state.user, ...profileData };
|
||||
|
||||
// Update AsyncStorage
|
||||
await AsyncStorage.setItem('user_data', JSON.stringify(updatedUser));
|
||||
|
||||
// Update state
|
||||
dispatch({
|
||||
type: 'LOGIN_SUCCESS',
|
||||
payload: {
|
||||
token: state.token,
|
||||
user: updatedUser,
|
||||
},
|
||||
});
|
||||
|
||||
return { success: true, message: response.message };
|
||||
} catch (error) {
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
};
|
||||
|
||||
const fetchUserProfile = async () => {
|
||||
try {
|
||||
console.log('🔄 Manually fetching user profile...');
|
||||
const profileData = await authService.getProfile();
|
||||
console.log('👤 Fetched profile data:', profileData);
|
||||
|
||||
// Validate profile data structure
|
||||
if (!profileData.name || !profileData.phone) {
|
||||
throw new Error('Invalid profile data structure received');
|
||||
}
|
||||
|
||||
// Update AsyncStorage
|
||||
await AsyncStorage.setItem('user_data', JSON.stringify(profileData));
|
||||
|
||||
// Update state
|
||||
dispatch({
|
||||
type: 'LOGIN_SUCCESS',
|
||||
payload: {
|
||||
token: state.token,
|
||||
user: profileData,
|
||||
},
|
||||
});
|
||||
|
||||
console.log('✅ Profile updated successfully');
|
||||
return { success: true, user: profileData };
|
||||
} catch (error) {
|
||||
console.error('💥 Failed to fetch profile:', error.message);
|
||||
|
||||
// If unauthorized, logout user
|
||||
if (error.message.includes('Session expired')) {
|
||||
console.log('🔓 Session expired during profile fetch, logging out');
|
||||
await logout();
|
||||
}
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
};
|
||||
|
||||
const value = {
|
||||
...state,
|
||||
login,
|
||||
@@ -161,6 +286,8 @@ export const AuthProvider = ({ children }) => {
|
||||
verify,
|
||||
logout,
|
||||
clearPendingVerification,
|
||||
updateUserProfile,
|
||||
fetchUserProfile,
|
||||
};
|
||||
|
||||
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
@@ -7,14 +7,47 @@ import {
|
||||
ScrollView,
|
||||
TouchableOpacity,
|
||||
Alert,
|
||||
ActivityIndicator,
|
||||
RefreshControl,
|
||||
} from 'react-native';
|
||||
import { StatusBar } from 'expo-status-bar';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { useAuth } from '../../contexts/AuthContext';
|
||||
import apiService from '../../services/apiService';
|
||||
import { COLORS } from '../../constants/colors';
|
||||
|
||||
const ProfileScreen = () => {
|
||||
const { user, logout } = useAuth();
|
||||
const { user, logout, fetchUserProfile } = useAuth();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isRefreshing, setIsRefreshing] = useState(false);
|
||||
const [profileData, setProfileData] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
loadProfileData();
|
||||
}, []);
|
||||
|
||||
const loadProfileData = async () => {
|
||||
if (isLoading) return;
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
// Fetch fresh profile data from API
|
||||
const result = await fetchUserProfile();
|
||||
if (result.success) {
|
||||
setProfileData(result.user);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading profile:', error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleRefresh = async () => {
|
||||
setIsRefreshing(true);
|
||||
await loadProfileData();
|
||||
setIsRefreshing(false);
|
||||
};
|
||||
|
||||
const profileSections = [
|
||||
{
|
||||
@@ -53,8 +86,100 @@ const ProfileScreen = () => {
|
||||
];
|
||||
|
||||
const handleProfileItemPress = (item) => {
|
||||
console.log('Profile item pressed:', item.title);
|
||||
// Handle navigation or action here
|
||||
switch (item.id) {
|
||||
case 1: // Personal Information
|
||||
handleEditPersonalInfo();
|
||||
break;
|
||||
case 2: // Contact Information
|
||||
handleEditContactInfo();
|
||||
break;
|
||||
case 3: // Change Password
|
||||
handleChangePassword();
|
||||
break;
|
||||
case 4: // Notifications
|
||||
handleNotificationSettings();
|
||||
break;
|
||||
case 5: // Security
|
||||
handleSecuritySettings();
|
||||
break;
|
||||
default:
|
||||
Alert.alert('Üns beriň', 'Bu funksiýa entek işlenok');
|
||||
}
|
||||
};
|
||||
|
||||
const handleEditPersonalInfo = () => {
|
||||
// Navigate to edit personal info screen
|
||||
Alert.alert('Şahsy maglumatlar', 'Şahsy maglumatlar sahypasy açylýar...');
|
||||
};
|
||||
|
||||
const handleEditContactInfo = () => {
|
||||
// Navigate to edit contact info screen
|
||||
Alert.alert('Aragatnaşyk', 'Aragatnaşyk maglumatlar sahypasy açylýar...');
|
||||
};
|
||||
|
||||
const handleChangePassword = () => {
|
||||
Alert.prompt(
|
||||
'Paroly üýtget',
|
||||
'Häzirki parolyňyzy giriziň',
|
||||
[
|
||||
{ text: 'Ýatyr', style: 'cancel' },
|
||||
{
|
||||
text: 'Dowam et',
|
||||
onPress: (currentPassword) => {
|
||||
if (currentPassword) {
|
||||
promptForNewPassword(currentPassword);
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
'secure-text'
|
||||
);
|
||||
};
|
||||
|
||||
const promptForNewPassword = (currentPassword) => {
|
||||
Alert.prompt(
|
||||
'Täze parol',
|
||||
'Täze parolyňyzy giriziň',
|
||||
[
|
||||
{ text: 'Ýatyr', style: 'cancel' },
|
||||
{
|
||||
text: 'Üýtget',
|
||||
onPress: (newPassword) => {
|
||||
if (newPassword && newPassword.length >= 6) {
|
||||
changePassword(currentPassword, newPassword);
|
||||
} else {
|
||||
Alert.alert('Ýalňyşlyk', 'Parol azyndan 6 harp bolmaly');
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
'secure-text'
|
||||
);
|
||||
};
|
||||
|
||||
const changePassword = async (currentPassword, newPassword) => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const result = await apiService.changePassword(currentPassword, newPassword);
|
||||
|
||||
if (result.success) {
|
||||
Alert.alert('Üstünlik', 'Parol üstünlikli üýtgedildi');
|
||||
} else {
|
||||
Alert.alert('Ýalňyşlyk', result.error || 'Paroly üýtgetmek amala aşmady');
|
||||
}
|
||||
} catch (error) {
|
||||
Alert.alert('Ýalňyşlyk', error.message || 'Paroly üýtgetmek amala aşmady');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleNotificationSettings = () => {
|
||||
Alert.alert('Bildirişler', 'Bildiriş sazlamalary sahypasy açylýar...');
|
||||
};
|
||||
|
||||
const handleSecuritySettings = () => {
|
||||
Alert.alert('Howpsuzlyk', 'Howpsuzlyk sazlamalary sahypasy açylýar...');
|
||||
};
|
||||
|
||||
const handleLogout = () => {
|
||||
@@ -78,9 +203,12 @@ const ProfileScreen = () => {
|
||||
const formatPhoneNumber = (phone) => {
|
||||
if (!phone) return '';
|
||||
const phoneStr = phone.toString();
|
||||
return `+993 ${phoneStr.slice(0, 2)} ${phoneStr.slice(2, 5)} ${phoneStr.slice(5)}`;
|
||||
return `+993 ${phoneStr.slice(0, 2)} ${phoneStr.slice(2, 4)}-${phoneStr.slice(4, 6)}-${phoneStr.slice(6)}`;
|
||||
};
|
||||
|
||||
// Use profile data from API or fallback to cached user data
|
||||
const currentUser = profileData || user;
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<StatusBar style="dark" />
|
||||
@@ -89,19 +217,36 @@ const ProfileScreen = () => {
|
||||
<Text style={styles.headerTitle}>Profil</Text>
|
||||
</View>
|
||||
|
||||
<ScrollView style={styles.scrollView} showsVerticalScrollIndicator={false}>
|
||||
<ScrollView
|
||||
style={styles.scrollView}
|
||||
showsVerticalScrollIndicator={false}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={isRefreshing}
|
||||
onRefresh={handleRefresh}
|
||||
colors={[COLORS.primary]}
|
||||
tintColor={COLORS.primary}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{/* User Info Card */}
|
||||
<View style={styles.userCard}>
|
||||
<View style={styles.userAvatar}>
|
||||
<Text style={styles.userInitials}>
|
||||
{user?.name ? user.name.split(' ').map(n => n[0]).join('').toUpperCase() : 'U'}
|
||||
{currentUser?.name ? currentUser.name.split(' ').map(n => n[0]).join('').toUpperCase() : 'U'}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.userInfo}>
|
||||
<Text style={styles.userName}>{user?.name || 'Ulanyjy'}</Text>
|
||||
<Text style={styles.userPhone}>{formatPhoneNumber(user?.phone)}</Text>
|
||||
<Text style={styles.userName}>
|
||||
{currentUser?.name || 'Ulanyjy'}
|
||||
{isLoading && <ActivityIndicator size="small" color={COLORS.primary} style={{ marginLeft: 8 }} />}
|
||||
</Text>
|
||||
<Text style={styles.userPhone}>{formatPhoneNumber(currentUser?.phone)}</Text>
|
||||
{currentUser?.email && (
|
||||
<Text style={styles.userEmail}>{currentUser.email}</Text>
|
||||
)}
|
||||
</View>
|
||||
<TouchableOpacity style={styles.editButton}>
|
||||
<TouchableOpacity style={styles.editButton} onPress={handleEditPersonalInfo}>
|
||||
<Ionicons name="pencil" size={20} color={COLORS.primary} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
@@ -219,6 +364,11 @@ const styles = StyleSheet.create({
|
||||
fontSize: 16,
|
||||
color: COLORS.textSecondary,
|
||||
},
|
||||
userEmail: {
|
||||
fontSize: 14,
|
||||
color: COLORS.textSecondary,
|
||||
marginTop: 2,
|
||||
},
|
||||
editButton: {
|
||||
padding: 8,
|
||||
},
|
||||
|
||||
82
src/services/apiService.js
Normal file
82
src/services/apiService.js
Normal file
@@ -0,0 +1,82 @@
|
||||
import authService from './authService';
|
||||
|
||||
class ApiService {
|
||||
// Profile methods
|
||||
async getProfile() {
|
||||
return authService.getProfile();
|
||||
}
|
||||
|
||||
async updateProfile(data) {
|
||||
return authService.updateProfile(data);
|
||||
}
|
||||
|
||||
async changePassword(currentPassword, newPassword) {
|
||||
return authService.changePassword(currentPassword, newPassword);
|
||||
}
|
||||
|
||||
async deleteAccount() {
|
||||
return authService.deleteAccount();
|
||||
}
|
||||
|
||||
// Balance and transactions
|
||||
async getBalance() {
|
||||
return authService.getBalance();
|
||||
}
|
||||
|
||||
async getTransactions(page = 1, limit = 20) {
|
||||
return authService.getTransactions(page, limit);
|
||||
}
|
||||
|
||||
// Transfer and payments
|
||||
async transferMoney(data) {
|
||||
return authService.transferMoney(data);
|
||||
}
|
||||
|
||||
async payBill(data) {
|
||||
return authService.payBill(data);
|
||||
}
|
||||
|
||||
// Cards management
|
||||
async getCards() {
|
||||
return authService.getCards();
|
||||
}
|
||||
|
||||
async addCard(data) {
|
||||
return authService.addCard(data);
|
||||
}
|
||||
|
||||
async blockCard(cardId) {
|
||||
return authService.blockCard(cardId);
|
||||
}
|
||||
|
||||
async unblockCard(cardId) {
|
||||
return authService.unblockCard(cardId);
|
||||
}
|
||||
|
||||
// Utility methods for common operations
|
||||
async getUserDashboardData() {
|
||||
try {
|
||||
const [balance, transactions, cards] = await Promise.all([
|
||||
this.getBalance().catch(() => ({ balance: 0 })),
|
||||
this.getTransactions(1, 5).catch(() => ({ transactions: [] })),
|
||||
this.getCards().catch(() => ({ cards: [] }))
|
||||
]);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
balance: balance.balance || 0,
|
||||
recentTransactions: transactions.transactions || [],
|
||||
cards: cards.cards || []
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: error.message
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new ApiService();
|
||||
@@ -1,30 +1,87 @@
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import { API_CONFIG } from '../constants/api';
|
||||
|
||||
class AuthService {
|
||||
async makeRequest(endpoint, data, token = null) {
|
||||
async getStoredToken() {
|
||||
try {
|
||||
return await AsyncStorage.getItem('auth_token');
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async makeRequest(endpoint, data, requiresAuth = false, method = 'POST') {
|
||||
const fullUrl = `${API_CONFIG.BASE_URL}${endpoint}`;
|
||||
const requestId = Math.random().toString(36).substr(2, 9);
|
||||
|
||||
try {
|
||||
const headers = {
|
||||
...API_CONFIG.HEADERS,
|
||||
};
|
||||
|
||||
if (token) {
|
||||
headers.Authorization = `Bearer ${token}`;
|
||||
// Auto-include token for authenticated requests
|
||||
if (requiresAuth) {
|
||||
const token = await this.getStoredToken();
|
||||
if (token) {
|
||||
headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
}
|
||||
|
||||
const response = await fetch(`${API_CONFIG.BASE_URL}${endpoint}`, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: JSON.stringify(data),
|
||||
// Log request details
|
||||
console.log(`\n🚀 [${requestId}] API REQUEST`);
|
||||
console.log(`📍 URL: ${method} ${fullUrl}`);
|
||||
console.log(`🔐 Auth Required: ${requiresAuth}`);
|
||||
console.log(`📝 Headers:`, {
|
||||
...headers,
|
||||
Authorization: headers.Authorization ? `Bearer ${headers.Authorization.slice(-10)}...` : 'None'
|
||||
});
|
||||
if (data) {
|
||||
console.log(`📦 Body:`, data);
|
||||
}
|
||||
console.log(`⏰ Time: ${new Date().toISOString()}`);
|
||||
|
||||
const startTime = Date.now();
|
||||
|
||||
const response = await fetch(fullUrl, {
|
||||
method,
|
||||
headers,
|
||||
body: data ? JSON.stringify(data) : undefined,
|
||||
});
|
||||
|
||||
const endTime = Date.now();
|
||||
const duration = endTime - startTime;
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
// Log response details
|
||||
console.log(`\n✅ [${requestId}] API RESPONSE`);
|
||||
console.log(`📊 Status: ${response.status} ${response.statusText}`);
|
||||
console.log(`⏱️ Duration: ${duration}ms`);
|
||||
console.log(`📄 Response:`, result);
|
||||
|
||||
if (!response.ok) {
|
||||
console.log(`❌ [${requestId}] API ERROR`);
|
||||
console.log(`🔴 Status: ${response.status}`);
|
||||
console.log(`💬 Error Message:`, result.message || 'Unknown error');
|
||||
|
||||
// Handle token expiration
|
||||
if (response.status === 401 && requiresAuth) {
|
||||
console.log(`🔓 [${requestId}] TOKEN EXPIRED - Clearing storage`);
|
||||
await AsyncStorage.removeItem('auth_token');
|
||||
await AsyncStorage.removeItem('user_data');
|
||||
throw new Error('Session expired. Please login again.');
|
||||
}
|
||||
throw new Error(result.message || 'An error occurred');
|
||||
}
|
||||
|
||||
console.log(`✨ [${requestId}] REQUEST COMPLETED SUCCESSFULLY\n`);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.log(`\n💥 [${requestId}] API REQUEST FAILED`);
|
||||
console.log(`📍 URL: ${method} ${fullUrl}`);
|
||||
console.log(`🔴 Error:`, error.message);
|
||||
console.log(`📅 Time: ${new Date().toISOString()}\n`);
|
||||
|
||||
throw new Error(error.message || 'Network error');
|
||||
}
|
||||
}
|
||||
@@ -50,6 +107,58 @@ class AuthService {
|
||||
code: parseInt(code),
|
||||
});
|
||||
}
|
||||
|
||||
// Authenticated API methods
|
||||
async getProfile() {
|
||||
return this.makeRequest('/profile', null, true, 'GET');
|
||||
}
|
||||
|
||||
async updateProfile(data) {
|
||||
return this.makeRequest('/profile', data, true, 'PUT');
|
||||
}
|
||||
|
||||
async getTransactions(page = 1, limit = 20) {
|
||||
return this.makeRequest(`/user/transactions?page=${page}&limit=${limit}`, null, true, 'GET');
|
||||
}
|
||||
|
||||
async getBalance() {
|
||||
return this.makeRequest('/user/balance', null, true, 'GET');
|
||||
}
|
||||
|
||||
async transferMoney(data) {
|
||||
return this.makeRequest('/user/transfer', data, true);
|
||||
}
|
||||
|
||||
async payBill(data) {
|
||||
return this.makeRequest('/user/pay-bill', data, true);
|
||||
}
|
||||
|
||||
async getCards() {
|
||||
return this.makeRequest('/user/cards', null, true, 'GET');
|
||||
}
|
||||
|
||||
async addCard(data) {
|
||||
return this.makeRequest('/user/cards', data, true);
|
||||
}
|
||||
|
||||
async blockCard(cardId) {
|
||||
return this.makeRequest(`/user/cards/${cardId}/block`, null, true);
|
||||
}
|
||||
|
||||
async unblockCard(cardId) {
|
||||
return this.makeRequest(`/user/cards/${cardId}/unblock`, null, true);
|
||||
}
|
||||
|
||||
async changePassword(currentPassword, newPassword) {
|
||||
return this.makeRequest('/user/change-password', {
|
||||
current_password: currentPassword,
|
||||
new_password: newPassword,
|
||||
}, true);
|
||||
}
|
||||
|
||||
async deleteAccount() {
|
||||
return this.makeRequest('/user/delete-account', null, true, 'DELETE');
|
||||
}
|
||||
}
|
||||
|
||||
export default new AuthService();
|
||||
Reference in New Issue
Block a user