455 lines
14 KiB
JavaScript
455 lines
14 KiB
JavaScript
/**
|
|
* Kasico Mobile API Client für React Native
|
|
* Vollständige API-Integration für Mobile App
|
|
*/
|
|
|
|
class KasicoMobileApiClient {
|
|
constructor(baseUrl = '/mobile/api/') {
|
|
this.baseUrl = baseUrl;
|
|
this.deviceToken = null;
|
|
this.sessionId = null;
|
|
this.isAuthenticated = false;
|
|
this.authToken = null;
|
|
|
|
this.init();
|
|
}
|
|
|
|
init() {
|
|
// Load stored data
|
|
this.loadStoredData();
|
|
|
|
// Initialize session
|
|
this.initializeSession();
|
|
}
|
|
|
|
loadStoredData() {
|
|
// Load from localStorage (in web) or AsyncStorage (in React Native)
|
|
if (typeof localStorage !== 'undefined') {
|
|
this.deviceToken = localStorage.getItem('kasico_device_token');
|
|
this.authToken = localStorage.getItem('kasico_auth_token');
|
|
this.sessionId = localStorage.getItem('kasico_session_id');
|
|
}
|
|
}
|
|
|
|
saveStoredData() {
|
|
if (typeof localStorage !== 'undefined') {
|
|
if (this.deviceToken) localStorage.setItem('kasico_device_token', this.deviceToken);
|
|
if (this.authToken) localStorage.setItem('kasico_auth_token', this.authToken);
|
|
if (this.sessionId) localStorage.setItem('kasico_session_id', this.sessionId);
|
|
}
|
|
}
|
|
|
|
async initializeSession() {
|
|
if (!this.sessionId) {
|
|
this.sessionId = this.generateSessionId();
|
|
}
|
|
|
|
await this.startSession();
|
|
}
|
|
|
|
generateSessionId() {
|
|
return 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
|
|
}
|
|
|
|
// Authentication
|
|
async authenticate(username, password) {
|
|
try {
|
|
const response = await fetch('/api/auth/login/', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({ username, password })
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (response.ok) {
|
|
this.authToken = data.token;
|
|
this.isAuthenticated = true;
|
|
this.saveStoredData();
|
|
return data;
|
|
} else {
|
|
throw new Error(data.error || 'Authentication failed');
|
|
}
|
|
} catch (error) {
|
|
console.error('Authentication error:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async logout() {
|
|
try {
|
|
await fetch('/api/auth/logout/', {
|
|
method: 'POST',
|
|
headers: this.getAuthHeaders()
|
|
});
|
|
|
|
this.authToken = null;
|
|
this.isAuthenticated = false;
|
|
this.saveStoredData();
|
|
|
|
await this.endSession();
|
|
} catch (error) {
|
|
console.error('Logout error:', error);
|
|
}
|
|
}
|
|
|
|
// Device Management
|
|
async registerDevice(deviceInfo) {
|
|
try {
|
|
const response = await fetch(this.baseUrl + 'device/register/', {
|
|
method: 'POST',
|
|
headers: this.getAuthHeaders(),
|
|
body: JSON.stringify({
|
|
device_token: deviceInfo.deviceToken,
|
|
device_type: deviceInfo.deviceType || 'web',
|
|
device_name: deviceInfo.deviceName || '',
|
|
device_model: deviceInfo.deviceModel || '',
|
|
os_version: deviceInfo.osVersion || '',
|
|
app_version: deviceInfo.appVersion || ''
|
|
})
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (response.ok) {
|
|
this.deviceToken = deviceInfo.deviceToken;
|
|
this.saveStoredData();
|
|
return data;
|
|
} else {
|
|
throw new Error(data.error || 'Device registration failed');
|
|
}
|
|
} catch (error) {
|
|
console.error('Device registration error:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async unregisterDevice() {
|
|
if (!this.deviceToken) return;
|
|
|
|
try {
|
|
await fetch(`${this.baseUrl}device/unregister/${this.deviceToken}/`, {
|
|
method: 'DELETE',
|
|
headers: this.getAuthHeaders()
|
|
});
|
|
|
|
this.deviceToken = null;
|
|
this.saveStoredData();
|
|
} catch (error) {
|
|
console.error('Device unregistration error:', error);
|
|
}
|
|
}
|
|
|
|
// Session Management
|
|
async startSession() {
|
|
if (!this.deviceToken) return;
|
|
|
|
try {
|
|
const response = await fetch(this.baseUrl + 'session/start/', {
|
|
method: 'POST',
|
|
headers: this.getAuthHeaders(),
|
|
body: JSON.stringify({
|
|
session_id: this.sessionId,
|
|
device_token: this.deviceToken,
|
|
app_version: '1.0.0',
|
|
device_info: this.getDeviceInfo()
|
|
})
|
|
});
|
|
|
|
const data = await response.json();
|
|
return data;
|
|
} catch (error) {
|
|
console.error('Session start error:', error);
|
|
}
|
|
}
|
|
|
|
async endSession() {
|
|
if (!this.sessionId) return;
|
|
|
|
try {
|
|
await fetch(`${this.baseUrl}session/end/${this.sessionId}/`, {
|
|
method: 'POST',
|
|
headers: this.getAuthHeaders()
|
|
});
|
|
} catch (error) {
|
|
console.error('Session end error:', error);
|
|
}
|
|
}
|
|
|
|
// Analytics
|
|
async trackEvent(eventType, eventData = {}, screenName = '') {
|
|
if (!this.deviceToken) return;
|
|
|
|
try {
|
|
await fetch(this.baseUrl + 'analytics/track/', {
|
|
method: 'POST',
|
|
headers: this.getAuthHeaders(),
|
|
body: JSON.stringify({
|
|
event_type: eventType,
|
|
event_data: eventData,
|
|
session_id: this.sessionId,
|
|
screen_name: screenName,
|
|
device_token: this.deviceToken
|
|
})
|
|
});
|
|
} catch (error) {
|
|
console.error('Analytics tracking error:', error);
|
|
}
|
|
}
|
|
|
|
// Error Reporting
|
|
async reportError(errorLevel, errorType, errorMessage, stackTrace = '') {
|
|
if (!this.deviceToken) return;
|
|
|
|
try {
|
|
await fetch(this.baseUrl + 'error/report/', {
|
|
method: 'POST',
|
|
headers: this.getAuthHeaders(),
|
|
body: JSON.stringify({
|
|
error_level: errorLevel,
|
|
error_type: errorType,
|
|
error_message: errorMessage,
|
|
stack_trace: stackTrace,
|
|
app_version: '1.0.0',
|
|
os_version: this.getOSVersion(),
|
|
device_info: this.getDeviceInfo(),
|
|
session_id: this.sessionId
|
|
})
|
|
});
|
|
} catch (error) {
|
|
console.error('Error reporting failed:', error);
|
|
}
|
|
}
|
|
|
|
// Mobile-optimierte Produkt-API
|
|
async getMobileProducts(page = 1, perPage = 20) {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}products/?page=${page}&per_page=${perPage}`, {
|
|
headers: this.getAuthHeaders()
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (response.ok) {
|
|
// Track analytics
|
|
this.trackEvent('products_viewed', { page, per_page: perPage });
|
|
return data;
|
|
} else {
|
|
throw new Error(data.error || 'Failed to fetch products');
|
|
}
|
|
} catch (error) {
|
|
console.error('Get products error:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// Mobile-optimierte Auction-API
|
|
async getMobileAuctions(page = 1, perPage = 10) {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}auctions/?page=${page}&per_page=${perPage}`, {
|
|
headers: this.getAuthHeaders()
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (response.ok) {
|
|
// Track analytics
|
|
this.trackEvent('auctions_viewed', { page, per_page: perPage });
|
|
return data;
|
|
} else {
|
|
throw new Error(data.error || 'Failed to fetch auctions');
|
|
}
|
|
} catch (error) {
|
|
console.error('Get auctions error:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// Offline Sync
|
|
async syncOfflineData(syncType, syncData) {
|
|
if (!this.deviceToken) return;
|
|
|
|
try {
|
|
const response = await fetch(this.baseUrl + 'sync/', {
|
|
method: 'POST',
|
|
headers: this.getAuthHeaders(),
|
|
body: JSON.stringify({
|
|
sync_type: syncType,
|
|
data: syncData,
|
|
device_token: this.deviceToken
|
|
})
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (response.ok) {
|
|
this.trackEvent('offline_sync', { sync_type: syncType });
|
|
return data;
|
|
} else {
|
|
throw new Error(data.error || 'Sync failed');
|
|
}
|
|
} catch (error) {
|
|
console.error('Offline sync error:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// Cache Management
|
|
async getCache(cacheType, cacheKey = 'default') {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}cache/${cacheType}/?key=${cacheKey}`, {
|
|
headers: this.getAuthHeaders()
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (response.ok) {
|
|
return data;
|
|
} else {
|
|
return null;
|
|
}
|
|
} catch (error) {
|
|
console.error('Get cache error:', error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
async updateCache(cacheType, cacheKey, cacheData, expiresIn = 3600) {
|
|
try {
|
|
const response = await fetch(`${this.baseUrl}cache/${cacheType}/update/`, {
|
|
method: 'POST',
|
|
headers: this.getAuthHeaders(),
|
|
body: JSON.stringify({
|
|
key: cacheKey,
|
|
data: cacheData,
|
|
expires_in: expiresIn
|
|
})
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (response.ok) {
|
|
return data;
|
|
} else {
|
|
throw new Error(data.error || 'Cache update failed');
|
|
}
|
|
} catch (error) {
|
|
console.error('Update cache error:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// Push Notifications
|
|
async sendPushNotification(userId, notificationType, title, message, data = {}) {
|
|
try {
|
|
const response = await fetch(this.baseUrl + 'notifications/send/', {
|
|
method: 'POST',
|
|
headers: this.getAuthHeaders(),
|
|
body: JSON.stringify({
|
|
user_id: userId,
|
|
notification_type: notificationType,
|
|
title: title,
|
|
message: message,
|
|
data: data
|
|
})
|
|
});
|
|
|
|
const responseData = await response.json();
|
|
|
|
if (response.ok) {
|
|
return responseData;
|
|
} else {
|
|
throw new Error(responseData.error || 'Failed to send notification');
|
|
}
|
|
} catch (error) {
|
|
console.error('Send notification error:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// Utility Methods
|
|
getAuthHeaders() {
|
|
const headers = {
|
|
'Content-Type': 'application/json',
|
|
};
|
|
|
|
if (this.authToken) {
|
|
headers['Authorization'] = `Token ${this.authToken}`;
|
|
}
|
|
|
|
return headers;
|
|
}
|
|
|
|
getDeviceInfo() {
|
|
return {
|
|
userAgent: navigator.userAgent,
|
|
platform: navigator.platform,
|
|
language: navigator.language,
|
|
screenWidth: screen.width,
|
|
screenHeight: screen.height,
|
|
windowWidth: window.innerWidth,
|
|
windowHeight: window.innerHeight
|
|
};
|
|
}
|
|
|
|
getOSVersion() {
|
|
const userAgent = navigator.userAgent;
|
|
if (userAgent.includes('Windows')) return 'Windows';
|
|
if (userAgent.includes('Mac')) return 'macOS';
|
|
if (userAgent.includes('Linux')) return 'Linux';
|
|
if (userAgent.includes('Android')) return 'Android';
|
|
if (userAgent.includes('iOS')) return 'iOS';
|
|
return 'Unknown';
|
|
}
|
|
|
|
// Event Tracking Helpers
|
|
trackScreenView(screenName) {
|
|
this.trackEvent('screen_view', {}, screenName);
|
|
}
|
|
|
|
trackProductView(productId, productName) {
|
|
this.trackEvent('product_view', { product_id: productId, product_name: productName });
|
|
}
|
|
|
|
trackAuctionView(auctionId, auctionTitle) {
|
|
this.trackEvent('auction_view', { auction_id: auctionId, auction_title: auctionTitle });
|
|
}
|
|
|
|
trackPurchase(orderId, total) {
|
|
this.trackEvent('purchase', { order_id: orderId, total: total });
|
|
}
|
|
|
|
trackAddToCart(productId, quantity) {
|
|
this.trackEvent('add_to_cart', { product_id: productId, quantity: quantity });
|
|
}
|
|
|
|
trackSearch(query, resultsCount) {
|
|
this.trackEvent('search', { query: query, results_count: resultsCount });
|
|
}
|
|
|
|
// Error Handling
|
|
handleError(error, context = '') {
|
|
console.error(`Error in ${context}:`, error);
|
|
|
|
this.reportError(
|
|
'error',
|
|
'api_error',
|
|
error.message,
|
|
error.stack
|
|
);
|
|
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// Mobile API Client initialisieren
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
window.kasicoMobileApi = new KasicoMobileApiClient();
|
|
});
|
|
|
|
// Export für React Native
|
|
if (typeof module !== 'undefined' && module.exports) {
|
|
module.exports = KasicoMobileApiClient;
|
|
}
|