refactor(terminology): 统一术语标准并优化代码类型安全
- 将B2B统一为TOB术语 - 将状态值统一为大写格式 - 优化类型声明,避免使用any - 将float类型替换为decimal以提高精度 - 新增术语标准化文档 - 优化路由结构和菜单分类 - 添加TypeORM实体类 - 增强加密模块安全性 - 重构前端路由结构 - 完善任务模板和验收标准
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -138,7 +138,7 @@ const Pricing: React.FC = () => {
|
||||
))}
|
||||
</div>
|
||||
<Button
|
||||
type={plan.buttonType as any}
|
||||
type={plan.buttonType as 'primary' | 'default' | 'dashed' | 'text' | 'link'}
|
||||
size="large"
|
||||
className="plan-button"
|
||||
onClick={plan.onClick}
|
||||
|
||||
191
dashboard/src/services/crossBorderIntegrationDataSource.ts
Normal file
191
dashboard/src/services/crossBorderIntegrationDataSource.ts
Normal file
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* [MOCK-CROSS-BORDER] Cross Border Integration DataSource
|
||||
*/
|
||||
|
||||
export interface PlatformIntegration {
|
||||
id: string;
|
||||
platform: 'sellbrite' | 'shoplazza' | 'salesmartly' | 'amazon' | 'ebay' | 'shopify';
|
||||
credentials: Record<string, any>;
|
||||
status: 'connected' | 'disconnected' | 'error';
|
||||
lastSyncAt?: string;
|
||||
}
|
||||
|
||||
export interface InventorySyncRecord {
|
||||
id: string;
|
||||
productId: string;
|
||||
platform: string;
|
||||
platformSku: string;
|
||||
quantity: number;
|
||||
syncStatus: 'success' | 'failed' | 'pending';
|
||||
syncError?: string;
|
||||
syncedAt: string;
|
||||
}
|
||||
|
||||
export interface MarketingIntegration {
|
||||
id: string;
|
||||
platform: string;
|
||||
campaignId: string;
|
||||
config: Record<string, any>;
|
||||
metrics: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface ICrossBorderIntegrationDataSource {
|
||||
integrateSellbrite(credentials: { apiKey: string; accountId: string }): Promise<PlatformIntegration>;
|
||||
integrateShoplazza(credentials: { apiKey: string; storeId: string }): Promise<PlatformIntegration>;
|
||||
integrateSaleSmartly(credentials: { apiKey: string; workspaceId: string }): Promise<PlatformIntegration>;
|
||||
syncInventory(inventoryData: Array<{ productId: string; sku: string; quantity: number }>): Promise<InventorySyncRecord[]>;
|
||||
integrateMarketing(params: { platform: string; campaignId: string; config: Record<string, any> }): Promise<MarketingIntegration>;
|
||||
getIntegrationStatus(platform?: string): Promise<PlatformIntegration[]>;
|
||||
disconnectPlatform(platform: string): Promise<{ success: boolean; message: string }>;
|
||||
}
|
||||
|
||||
class MockCrossBorderIntegrationDataSource implements ICrossBorderIntegrationDataSource {
|
||||
private integrations: Map<string, PlatformIntegration> = new Map();
|
||||
|
||||
async integrateSellbrite(credentials: { apiKey: string; accountId: string }): Promise<PlatformIntegration> {
|
||||
const integration: PlatformIntegration = {
|
||||
id: `int_sellbrite_${Date.now()}`,
|
||||
platform: 'sellbrite',
|
||||
credentials,
|
||||
status: 'connected',
|
||||
lastSyncAt: new Date().toISOString(),
|
||||
};
|
||||
this.integrations.set('sellbrite', integration);
|
||||
return integration;
|
||||
}
|
||||
|
||||
async integrateShoplazza(credentials: { apiKey: string; storeId: string }): Promise<PlatformIntegration> {
|
||||
const integration: PlatformIntegration = {
|
||||
id: `int_shoplazza_${Date.now()}`,
|
||||
platform: 'shoplazza',
|
||||
credentials,
|
||||
status: 'connected',
|
||||
lastSyncAt: new Date().toISOString(),
|
||||
};
|
||||
this.integrations.set('shoplazza', integration);
|
||||
return integration;
|
||||
}
|
||||
|
||||
async integrateSaleSmartly(credentials: { apiKey: string; workspaceId: string }): Promise<PlatformIntegration> {
|
||||
const integration: PlatformIntegration = {
|
||||
id: `int_salesmartly_${Date.now()}`,
|
||||
platform: 'salesmartly',
|
||||
credentials,
|
||||
status: 'connected',
|
||||
lastSyncAt: new Date().toISOString(),
|
||||
};
|
||||
this.integrations.set('salesmartly', integration);
|
||||
return integration;
|
||||
}
|
||||
|
||||
async syncInventory(inventoryData: Array<{ productId: string; sku: string; quantity: number }>): Promise<InventorySyncRecord[]> {
|
||||
return inventoryData.map((item) => ({
|
||||
id: `sync_${Date.now()}_${item.productId}`,
|
||||
productId: item.productId,
|
||||
platform: 'amazon',
|
||||
platformSku: item.sku,
|
||||
quantity: item.quantity,
|
||||
syncStatus: 'success' as const,
|
||||
syncedAt: new Date().toISOString(),
|
||||
}));
|
||||
}
|
||||
|
||||
async integrateMarketing(params: { platform: string; campaignId: string; config: Record<string, any> }): Promise<MarketingIntegration> {
|
||||
return {
|
||||
id: `mkt_${Date.now()}`,
|
||||
platform: params.platform,
|
||||
campaignId: params.campaignId,
|
||||
config: params.config,
|
||||
metrics: {},
|
||||
};
|
||||
}
|
||||
|
||||
async getIntegrationStatus(platform?: string): Promise<PlatformIntegration[]> {
|
||||
if (platform) {
|
||||
const integration = this.integrations.get(platform);
|
||||
return integration ? [integration] : [];
|
||||
}
|
||||
return Array.from(this.integrations.values());
|
||||
}
|
||||
|
||||
async disconnectPlatform(platform: string): Promise<{ success: boolean; message: string }> {
|
||||
const integration = this.integrations.get(platform);
|
||||
if (integration) {
|
||||
integration.status = 'disconnected';
|
||||
return { success: true, message: `Platform ${platform} disconnected` };
|
||||
}
|
||||
return { success: false, message: `Platform ${platform} not found` };
|
||||
}
|
||||
}
|
||||
|
||||
class ApiCrossBorderIntegrationDataSource implements ICrossBorderIntegrationDataSource {
|
||||
private baseUrl = '/api/omnichannel';
|
||||
|
||||
async integrateSellbrite(credentials: { apiKey: string; accountId: string }): Promise<PlatformIntegration> {
|
||||
const res = await fetch(`${this.baseUrl}/cross-border/sellbrite`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ credentials }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async integrateShoplazza(credentials: { apiKey: string; storeId: string }): Promise<PlatformIntegration> {
|
||||
const res = await fetch(`${this.baseUrl}/cross-border/shoplazza`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ credentials }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async integrateSaleSmartly(credentials: { apiKey: string; workspaceId: string }): Promise<PlatformIntegration> {
|
||||
const res = await fetch(`${this.baseUrl}/cross-border/salesmartly`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ credentials }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async syncInventory(inventoryData: Array<{ productId: string; sku: string; quantity: number }>): Promise<InventorySyncRecord[]> {
|
||||
const res = await fetch(`${this.baseUrl}/cross-border/inventory/sync`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ inventoryData }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async integrateMarketing(params: { platform: string; campaignId: string; config: Record<string, any> }): Promise<MarketingIntegration> {
|
||||
const res = await fetch(`${this.baseUrl}/cross-border/marketing`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async getIntegrationStatus(platform?: string): Promise<PlatformIntegration[]> {
|
||||
const query = platform ? `?platform=${platform}` : '';
|
||||
const res = await fetch(`${this.baseUrl}/cross-border/integration${query}`);
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async disconnectPlatform(platform: string): Promise<{ success: boolean; message: string }> {
|
||||
const res = await fetch(`${this.baseUrl}/cross-border/integration/${platform}`, { method: 'DELETE' });
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
}
|
||||
|
||||
const useMock = process.env.REACT_APP_USE_MOCK === 'true';
|
||||
export const crossBorderIntegrationDataSource: ICrossBorderIntegrationDataSource = useMock
|
||||
? new MockCrossBorderIntegrationDataSource()
|
||||
: new ApiCrossBorderIntegrationDataSource();
|
||||
128
dashboard/src/services/omnichannelCommunicationDataSource.ts
Normal file
128
dashboard/src/services/omnichannelCommunicationDataSource.ts
Normal file
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* [MOCK-COMMUNICATION] Omnichannel Communication DataSource
|
||||
*/
|
||||
|
||||
export interface OmnichannelMessage {
|
||||
id: string;
|
||||
channelId: string;
|
||||
channelType: 'email' | 'chat' | 'social' | 'phone' | 'sms';
|
||||
customerId: string;
|
||||
customerName: string;
|
||||
content: string;
|
||||
direction: 'inbound' | 'outbound';
|
||||
status: 'pending' | 'processing' | 'completed' | 'failed';
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface CustomerProfile {
|
||||
id: string;
|
||||
customerId: string;
|
||||
channels: string[];
|
||||
tags: string[];
|
||||
preferences: Record<string, any>;
|
||||
lastInteractionAt?: string;
|
||||
totalInteractions: number;
|
||||
}
|
||||
|
||||
export interface TeamTask {
|
||||
id: string;
|
||||
assignedTo: string;
|
||||
customerId: string;
|
||||
taskType: 'inquiry' | 'complaint' | 'follow_up' | 'escalation';
|
||||
priority: 'low' | 'medium' | 'high' | 'urgent';
|
||||
status: 'pending' | 'in_progress' | 'completed';
|
||||
description: string;
|
||||
dueDate?: string;
|
||||
}
|
||||
|
||||
export interface IOmnichannelCommunicationDataSource {
|
||||
aggregateMessages(channels: Array<{ type: string; id: string }>): Promise<OmnichannelMessage[]>;
|
||||
autoReply(customerId: string, question: string, context: Record<string, any>): Promise<string>;
|
||||
createTeamTask(task: Omit<TeamTask, 'id'>): Promise<TeamTask>;
|
||||
updateCustomerProfile(customerId: string, updates: Partial<CustomerProfile>): Promise<CustomerProfile>;
|
||||
translateMessage(content: string, targetLanguage: string): Promise<string>;
|
||||
}
|
||||
|
||||
class MockOmnichannelCommunicationDataSource implements IOmnichannelCommunicationDataSource {
|
||||
async aggregateMessages(channels: Array<{ type: string; id: string }>): Promise<OmnichannelMessage[]> {
|
||||
return [
|
||||
{ id: 'msg_001', channelId: 'ch_001', channelType: 'email', customerId: 'cust_001', customerName: 'John Doe', content: 'I have a question about my order', direction: 'inbound', status: 'pending', createdAt: new Date().toISOString() },
|
||||
{ id: 'msg_002', channelId: 'ch_002', channelType: 'chat', customerId: 'cust_002', customerName: 'Jane Smith', content: 'When will my order arrive?', direction: 'inbound', status: 'pending', createdAt: new Date().toISOString() },
|
||||
];
|
||||
}
|
||||
|
||||
async autoReply(customerId: string, question: string, context: Record<string, any>): Promise<string> {
|
||||
return 'Thank you for your inquiry. Our customer service team will assist you shortly.';
|
||||
}
|
||||
|
||||
async createTeamTask(task: Omit<TeamTask, 'id'>): Promise<TeamTask> {
|
||||
return { ...task, id: `task_${Date.now()}` };
|
||||
}
|
||||
|
||||
async updateCustomerProfile(customerId: string, updates: Partial<CustomerProfile>): Promise<CustomerProfile> {
|
||||
return { id: `profile_${customerId}`, customerId, channels: [], tags: [], preferences: {}, totalInteractions: 0, ...updates };
|
||||
}
|
||||
|
||||
async translateMessage(content: string, targetLanguage: string): Promise<string> {
|
||||
return `[Translated to ${targetLanguage}]: ${content}`;
|
||||
}
|
||||
}
|
||||
|
||||
class ApiOmnichannelCommunicationDataSource implements IOmnichannelCommunicationDataSource {
|
||||
private baseUrl = '/api/omnichannel';
|
||||
|
||||
async aggregateMessages(channels: Array<{ type: string; id: string }>): Promise<OmnichannelMessage[]> {
|
||||
const res = await fetch(`${this.baseUrl}/communication/aggregate`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ channels }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async autoReply(customerId: string, question: string, context: Record<string, any>): Promise<string> {
|
||||
const res = await fetch(`${this.baseUrl}/communication/auto-reply`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ customerId, question, context }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data.reply;
|
||||
}
|
||||
|
||||
async createTeamTask(task: Omit<TeamTask, 'id'>): Promise<TeamTask> {
|
||||
const res = await fetch(`${this.baseUrl}/communication/team-task`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(task),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async updateCustomerProfile(customerId: string, updates: Partial<CustomerProfile>): Promise<CustomerProfile> {
|
||||
const res = await fetch(`${this.baseUrl}/communication/customer/${customerId}/profile`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(updates),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async translateMessage(content: string, targetLanguage: string): Promise<string> {
|
||||
const res = await fetch(`${this.baseUrl}/communication/translate`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ content, targetLanguage }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data.translated;
|
||||
}
|
||||
}
|
||||
|
||||
const useMock = process.env.REACT_APP_USE_MOCK === 'true';
|
||||
export const omnichannelCommunicationDataSource: IOmnichannelCommunicationDataSource = useMock
|
||||
? new MockOmnichannelCommunicationDataSource()
|
||||
: new ApiOmnichannelCommunicationDataSource();
|
||||
137
dashboard/src/services/omnichannelMarketingDataSource.ts
Normal file
137
dashboard/src/services/omnichannelMarketingDataSource.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* [MOCK-MARKETING-INTEGRATION] Omnichannel Marketing DataSource
|
||||
*/
|
||||
|
||||
export interface MarketingChannel {
|
||||
id: string;
|
||||
name: string;
|
||||
type: 'email' | 'social' | 'sms' | 'push' | 'ads';
|
||||
config: Record<string, any>;
|
||||
status: 'active' | 'inactive';
|
||||
}
|
||||
|
||||
export interface MarketingCampaign {
|
||||
id: string;
|
||||
name: string;
|
||||
channels: string[];
|
||||
targetAudience: Record<string, any>;
|
||||
content: Record<string, any>;
|
||||
schedule?: string;
|
||||
status: 'draft' | 'scheduled' | 'running' | 'completed' | 'paused';
|
||||
metrics?: CampaignMetrics;
|
||||
}
|
||||
|
||||
export interface CampaignMetrics {
|
||||
impressions: number;
|
||||
clicks: number;
|
||||
conversions: number;
|
||||
revenue: number;
|
||||
cost: number;
|
||||
}
|
||||
|
||||
export interface AutomationRule {
|
||||
id: string;
|
||||
name: string;
|
||||
trigger: {
|
||||
type: 'user_action' | 'time_based' | 'event';
|
||||
conditions: Record<string, any>;
|
||||
};
|
||||
actions: Array<{
|
||||
type: string;
|
||||
config: Record<string, any>;
|
||||
}>;
|
||||
status: 'active' | 'inactive';
|
||||
}
|
||||
|
||||
export interface ABTestResult {
|
||||
winner: string;
|
||||
results: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface IOmnichannelMarketingDataSource {
|
||||
integrateChannels(channels: Array<{ name: string; type: string; config: Record<string, any> }>): Promise<MarketingChannel[]>;
|
||||
createAutomation(rule: Omit<AutomationRule, 'id'>): Promise<AutomationRule>;
|
||||
analyzeCampaign(campaignId: string, timeRange: { start: string; end: string }): Promise<CampaignMetrics>;
|
||||
runABTest(params: { name: string; variants: Array<{ id: string; content: Record<string, any> }>; trafficSplit: number[] }): Promise<ABTestResult>;
|
||||
}
|
||||
|
||||
class MockOmnichannelMarketingDataSource implements IOmnichannelMarketingDataSource {
|
||||
async integrateChannels(channels: Array<{ name: string; type: string; config: Record<string, any> }>): Promise<MarketingChannel[]> {
|
||||
return channels.map((ch, i) => ({
|
||||
id: `ch_${Date.now()}_${i}`,
|
||||
name: ch.name,
|
||||
type: ch.type as MarketingChannel['type'],
|
||||
config: ch.config,
|
||||
status: 'active' as const,
|
||||
}));
|
||||
}
|
||||
|
||||
async createAutomation(rule: Omit<AutomationRule, 'id'>): Promise<AutomationRule> {
|
||||
return { ...rule, id: `rule_${Date.now()}` };
|
||||
}
|
||||
|
||||
async analyzeCampaign(campaignId: string, timeRange: { start: string; end: string }): Promise<CampaignMetrics> {
|
||||
return {
|
||||
impressions: 10000,
|
||||
clicks: 500,
|
||||
conversions: 50,
|
||||
revenue: 5000,
|
||||
cost: 500,
|
||||
};
|
||||
}
|
||||
|
||||
async runABTest(params: { name: string; variants: Array<{ id: string; content: Record<string, any> }>; trafficSplit: number[] }): Promise<ABTestResult> {
|
||||
return {
|
||||
winner: params.variants[0].id,
|
||||
results: {
|
||||
[params.variants[0].id]: { impressions: 500, conversions: 25, conversionRate: 0.05 },
|
||||
[params.variants[1]?.id || 'variant_b']: { impressions: 500, conversions: 20, conversionRate: 0.04 },
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class ApiOmnichannelMarketingDataSource implements IOmnichannelMarketingDataSource {
|
||||
private baseUrl = '/api/omnichannel';
|
||||
|
||||
async integrateChannels(channels: Array<{ name: string; type: string; config: Record<string, any> }>): Promise<MarketingChannel[]> {
|
||||
const res = await fetch(`${this.baseUrl}/marketing/channels`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ channels }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async createAutomation(rule: Omit<AutomationRule, 'id'>): Promise<AutomationRule> {
|
||||
const res = await fetch(`${this.baseUrl}/marketing/automation`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(rule),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async analyzeCampaign(campaignId: string, timeRange: { start: string; end: string }): Promise<CampaignMetrics> {
|
||||
const res = await fetch(`${this.baseUrl}/marketing/campaign/${campaignId}/analyze?start=${timeRange.start}&end=${timeRange.end}`);
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async runABTest(params: { name: string; variants: Array<{ id: string; content: Record<string, any> }>; trafficSplit: number[] }): Promise<ABTestResult> {
|
||||
const res = await fetch(`${this.baseUrl}/marketing/ab-test`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
}
|
||||
|
||||
const useMock = process.env.REACT_APP_USE_MOCK === 'true';
|
||||
export const omnichannelMarketingDataSource: IOmnichannelMarketingDataSource = useMock
|
||||
? new MockOmnichannelMarketingDataSource()
|
||||
: new ApiOmnichannelMarketingDataSource();
|
||||
@@ -247,7 +247,7 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
|
||||
const updatedOrder: Order = {
|
||||
...existingOrder,
|
||||
status: status as any,
|
||||
status: status as 'pending' | 'processing' | 'shipped' | 'completed' | 'cancelled',
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
|
||||
295
dashboard/src/services/storeCreationDataSource.ts
Normal file
295
dashboard/src/services/storeCreationDataSource.ts
Normal file
@@ -0,0 +1,295 @@
|
||||
/**
|
||||
* [MOCK-STORE-CREATION] Store Creation DataSource
|
||||
*/
|
||||
|
||||
export interface WebsiteTemplate {
|
||||
id: string;
|
||||
name: string;
|
||||
category: 'ecommerce' | 'blog' | 'portfolio' | 'landing';
|
||||
layout: Record<string, any>;
|
||||
styles: Record<string, any>;
|
||||
components: string[];
|
||||
status: 'draft' | 'published';
|
||||
}
|
||||
|
||||
export interface PageConfig {
|
||||
id: string;
|
||||
websiteId: string;
|
||||
name: string;
|
||||
path: string;
|
||||
components: PageComponent[];
|
||||
seoConfig: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface PageComponent {
|
||||
id: string;
|
||||
type: string;
|
||||
props: Record<string, any>;
|
||||
position: { x: number; y: number; w: number; h: number };
|
||||
}
|
||||
|
||||
export interface BrandConfig {
|
||||
id: string;
|
||||
name: string;
|
||||
logo?: string;
|
||||
colors: Record<string, string>;
|
||||
fonts: Record<string, string>;
|
||||
story?: string;
|
||||
values: string[];
|
||||
}
|
||||
|
||||
export interface MultilingualConfig {
|
||||
id: string;
|
||||
websiteId: string;
|
||||
defaultLanguage: string;
|
||||
supportedLanguages: string[];
|
||||
translations: Record<string, Record<string, string>>;
|
||||
}
|
||||
|
||||
export interface IStoreCreationDataSource {
|
||||
createTemplate(params: { name: string; category: string; designParams: Record<string, any> }): Promise<WebsiteTemplate>;
|
||||
updatePageComponents(websiteId: string, pageId: string, components: PageComponent[]): Promise<PageConfig>;
|
||||
adaptResponsiveLayout(websiteId: string, pageId: string, deviceType: 'desktop' | 'tablet' | 'mobile'): Promise<PageComponent[]>;
|
||||
setupMultilingual(websiteId: string, languages: string[]): Promise<MultilingualConfig>;
|
||||
createBrand(params: { name: string; designAssets: Record<string, any> }): Promise<BrandConfig>;
|
||||
manageContent(brandId: string, contentData: { type: string; content: string }): Promise<{ success: boolean; message: string }>;
|
||||
integrateEcommerce(websiteId: string, features: string[]): Promise<{ success: boolean; config: Record<string, any> }>;
|
||||
integrateMarketing(websiteId: string, params: Record<string, any>): Promise<{ success: boolean; config: Record<string, any> }>;
|
||||
configureShipping(websiteId: string, params: Record<string, any>): Promise<{ success: boolean; config: Record<string, any> }>;
|
||||
generateAnalytics(websiteId: string, params: { metrics: string[]; timeRange: { start: string; end: string } }): Promise<Record<string, any>>;
|
||||
optimizeSEO(websiteId: string, params: Record<string, any>): Promise<{ success: boolean; suggestions: string[] }>;
|
||||
integrateSocialMedia(websiteId: string, accounts: Array<{ platform: string; accountId: string }>): Promise<{ success: boolean; config: Record<string, any> }>;
|
||||
manageContentMarketing(websiteId: string, contentData: Record<string, any>): Promise<{ success: boolean; contentId: string }>;
|
||||
spreadBrandStory(brandId: string, params: { channels: string[]; schedule?: string }): Promise<{ success: boolean; reach: number }>;
|
||||
}
|
||||
|
||||
class MockStoreCreationDataSource implements IStoreCreationDataSource {
|
||||
async createTemplate(params: { name: string; category: string; designParams: Record<string, any> }): Promise<WebsiteTemplate> {
|
||||
return {
|
||||
id: `tpl_${Date.now()}`,
|
||||
name: params.name,
|
||||
category: params.category as WebsiteTemplate['category'],
|
||||
layout: params.designParams.layout || {},
|
||||
styles: params.designParams.styles || {},
|
||||
components: params.designParams.components || [],
|
||||
status: 'draft',
|
||||
};
|
||||
}
|
||||
|
||||
async updatePageComponents(websiteId: string, pageId: string, components: PageComponent[]): Promise<PageConfig> {
|
||||
return { id: pageId, websiteId, name: 'Page', path: '/page', components, seoConfig: {} };
|
||||
}
|
||||
|
||||
async adaptResponsiveLayout(websiteId: string, pageId: string, deviceType: 'desktop' | 'tablet' | 'mobile'): Promise<PageComponent[]> {
|
||||
return [];
|
||||
}
|
||||
|
||||
async setupMultilingual(websiteId: string, languages: string[]): Promise<MultilingualConfig> {
|
||||
return { id: `lang_${Date.now()}`, websiteId, defaultLanguage: languages[0] || 'en', supportedLanguages: languages, translations: {} };
|
||||
}
|
||||
|
||||
async createBrand(params: { name: string; designAssets: Record<string, any> }): Promise<BrandConfig> {
|
||||
return {
|
||||
id: `brand_${Date.now()}`,
|
||||
name: params.name,
|
||||
logo: params.designAssets.logo,
|
||||
colors: params.designAssets.colors || {},
|
||||
fonts: params.designAssets.fonts || {},
|
||||
story: params.designAssets.story,
|
||||
values: params.designAssets.values || [],
|
||||
};
|
||||
}
|
||||
|
||||
async manageContent(brandId: string, contentData: { type: string; content: string }): Promise<{ success: boolean; message: string }> {
|
||||
return { success: true, message: 'Content updated' };
|
||||
}
|
||||
|
||||
async integrateEcommerce(websiteId: string, features: string[]): Promise<{ success: boolean; config: Record<string, any> }> {
|
||||
const config: Record<string, any> = {};
|
||||
for (const feature of features) {
|
||||
config[feature] = { enabled: true, settings: {} };
|
||||
}
|
||||
return { success: true, config };
|
||||
}
|
||||
|
||||
async integrateMarketing(websiteId: string, params: Record<string, any>): Promise<{ success: boolean; config: Record<string, any> }> {
|
||||
return { success: true, config: params };
|
||||
}
|
||||
|
||||
async configureShipping(websiteId: string, params: Record<string, any>): Promise<{ success: boolean; config: Record<string, any> }> {
|
||||
return { success: true, config: params };
|
||||
}
|
||||
|
||||
async generateAnalytics(websiteId: string, params: { metrics: string[]; timeRange: { start: string; end: string } }): Promise<Record<string, any>> {
|
||||
const report: Record<string, any> = {};
|
||||
for (const metric of params.metrics) {
|
||||
report[metric] = { value: Math.floor(Math.random() * 10000), trend: 'up', change: '+5%' };
|
||||
}
|
||||
return report;
|
||||
}
|
||||
|
||||
async optimizeSEO(websiteId: string, params: Record<string, any>): Promise<{ success: boolean; suggestions: string[] }> {
|
||||
return { success: true, suggestions: ['Add meta description', 'Optimize images'] };
|
||||
}
|
||||
|
||||
async integrateSocialMedia(websiteId: string, accounts: Array<{ platform: string; accountId: string }>): Promise<{ success: boolean; config: Record<string, any> }> {
|
||||
const config: Record<string, any> = {};
|
||||
for (const account of accounts) {
|
||||
config[account.platform] = { accountId: account.accountId, connected: true };
|
||||
}
|
||||
return { success: true, config };
|
||||
}
|
||||
|
||||
async manageContentMarketing(websiteId: string, contentData: Record<string, any>): Promise<{ success: boolean; contentId: string }> {
|
||||
return { success: true, contentId: `content_${Date.now()}` };
|
||||
}
|
||||
|
||||
async spreadBrandStory(brandId: string, params: { channels: string[]; schedule?: string }): Promise<{ success: boolean; reach: number }> {
|
||||
return { success: true, reach: Math.floor(Math.random() * 100000) + 1000 };
|
||||
}
|
||||
}
|
||||
|
||||
class ApiStoreCreationDataSource implements IStoreCreationDataSource {
|
||||
private baseUrl = '/api/omnichannel';
|
||||
|
||||
async createTemplate(params: { name: string; category: string; designParams: Record<string, any> }): Promise<WebsiteTemplate> {
|
||||
const res = await fetch(`${this.baseUrl}/store/template`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async updatePageComponents(websiteId: string, pageId: string, components: PageComponent[]): Promise<PageConfig> {
|
||||
const res = await fetch(`${this.baseUrl}/store/website/${websiteId}/page/${pageId}/components`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ components }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async adaptResponsiveLayout(websiteId: string, pageId: string, deviceType: 'desktop' | 'tablet' | 'mobile'): Promise<PageComponent[]> {
|
||||
const res = await fetch(`${this.baseUrl}/store/website/${websiteId}/page/${pageId}/adapt?deviceType=${deviceType}`);
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async setupMultilingual(websiteId: string, languages: string[]): Promise<MultilingualConfig> {
|
||||
const res = await fetch(`${this.baseUrl}/store/website/${websiteId}/multilingual`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ languages }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async createBrand(params: { name: string; designAssets: Record<string, any> }): Promise<BrandConfig> {
|
||||
const res = await fetch(`${this.baseUrl}/store/brand`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async manageContent(brandId: string, contentData: { type: string; content: string }): Promise<{ success: boolean; message: string }> {
|
||||
const res = await fetch(`${this.baseUrl}/store/brand/${brandId}/content`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(contentData),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async integrateEcommerce(websiteId: string, features: string[]): Promise<{ success: boolean; config: Record<string, any> }> {
|
||||
const res = await fetch(`${this.baseUrl}/store/website/${websiteId}/ecommerce`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ features }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async integrateMarketing(websiteId: string, params: Record<string, any>): Promise<{ success: boolean; config: Record<string, any> }> {
|
||||
const res = await fetch(`${this.baseUrl}/store/website/${websiteId}/marketing`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ params }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async configureShipping(websiteId: string, params: Record<string, any>): Promise<{ success: boolean; config: Record<string, any> }> {
|
||||
const res = await fetch(`${this.baseUrl}/store/website/${websiteId}/shipping`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ params }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async generateAnalytics(websiteId: string, params: { metrics: string[]; timeRange: { start: string; end: string } }): Promise<Record<string, any>> {
|
||||
const res = await fetch(`${this.baseUrl}/store/website/${websiteId}/analytics`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async optimizeSEO(websiteId: string, params: Record<string, any>): Promise<{ success: boolean; suggestions: string[] }> {
|
||||
const res = await fetch(`${this.baseUrl}/store/website/${websiteId}/seo`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ params }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async integrateSocialMedia(websiteId: string, accounts: Array<{ platform: string; accountId: string }>): Promise<{ success: boolean; config: Record<string, any> }> {
|
||||
const res = await fetch(`${this.baseUrl}/store/website/${websiteId}/social`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ accounts }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async manageContentMarketing(websiteId: string, contentData: Record<string, any>): Promise<{ success: boolean; contentId: string }> {
|
||||
const res = await fetch(`${this.baseUrl}/store/website/${websiteId}/content-marketing`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ contentData }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async spreadBrandStory(brandId: string, params: { channels: string[]; schedule?: string }): Promise<{ success: boolean; reach: number }> {
|
||||
const res = await fetch(`${this.baseUrl}/store/brand/${brandId}/spread`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
}
|
||||
|
||||
const useMock = process.env.REACT_APP_USE_MOCK === 'true';
|
||||
export const storeCreationDataSource: IStoreCreationDataSource = useMock
|
||||
? new MockStoreCreationDataSource()
|
||||
: new ApiStoreCreationDataSource();
|
||||
153
dashboard/src/services/unifiedFulfillmentDataSource.ts
Normal file
153
dashboard/src/services/unifiedFulfillmentDataSource.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* [MOCK-FULFILLMENT] Unified Fulfillment DataSource
|
||||
*/
|
||||
|
||||
export interface UnifiedOrder {
|
||||
id: string;
|
||||
platformOrderId: string;
|
||||
platform: string;
|
||||
customerId: string;
|
||||
items: OrderItem[];
|
||||
totalAmount: number;
|
||||
currency: string;
|
||||
status: 'pending' | 'confirmed' | 'processing' | 'shipped' | 'delivered' | 'cancelled';
|
||||
shippingAddress: Record<string, any>;
|
||||
fulfillmentStatus: 'unfulfilled' | 'partial' | 'fulfilled';
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface OrderItem {
|
||||
productId: string;
|
||||
skuId: string;
|
||||
quantity: number;
|
||||
unitPrice: number;
|
||||
}
|
||||
|
||||
export interface FulfillmentRoute {
|
||||
orderId: string;
|
||||
warehouseId: string;
|
||||
priority: number;
|
||||
estimatedShipDate: string;
|
||||
estimatedDeliveryDate: string;
|
||||
cost: number;
|
||||
}
|
||||
|
||||
export interface FulfillmentStatus {
|
||||
orderId: string;
|
||||
status: 'pending' | 'picked' | 'packed' | 'shipped' | 'delivered';
|
||||
trackingNumber?: string;
|
||||
carrier?: string;
|
||||
events: FulfillmentEvent[];
|
||||
}
|
||||
|
||||
export interface FulfillmentEvent {
|
||||
timestamp: string;
|
||||
status: string;
|
||||
location?: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export interface IUnifiedFulfillmentDataSource {
|
||||
unifyOrders(platformOrders: Array<{ platform: string; orderId: string; data: Record<string, any> }>): Promise<UnifiedOrder[]>;
|
||||
routeOrder(orderId: string, inventoryData: Array<{ warehouseId: string; available: number }>): Promise<FulfillmentRoute>;
|
||||
manageFulfillment(orderId: string, action: 'pick' | 'pack' | 'ship' | 'deliver', params: Record<string, any>): Promise<FulfillmentStatus>;
|
||||
syncStatus(orderId: string, status: string): Promise<{ success: boolean; message: string }>;
|
||||
}
|
||||
|
||||
class MockUnifiedFulfillmentDataSource implements IUnifiedFulfillmentDataSource {
|
||||
async unifyOrders(platformOrders: Array<{ platform: string; orderId: string; data: Record<string, any> }>): Promise<UnifiedOrder[]> {
|
||||
return platformOrders.map((po, i) => ({
|
||||
id: `order_${Date.now()}_${i}`,
|
||||
platformOrderId: po.orderId,
|
||||
platform: po.platform,
|
||||
customerId: `cust_${i}`,
|
||||
items: po.data.items || [],
|
||||
totalAmount: po.data.totalAmount || 100,
|
||||
currency: 'USD',
|
||||
status: 'pending' as const,
|
||||
shippingAddress: po.data.shippingAddress || {},
|
||||
fulfillmentStatus: 'unfulfilled' as const,
|
||||
createdAt: new Date().toISOString(),
|
||||
}));
|
||||
}
|
||||
|
||||
async routeOrder(orderId: string, inventoryData: Array<{ warehouseId: string; available: number }>): Promise<FulfillmentRoute> {
|
||||
return {
|
||||
orderId,
|
||||
warehouseId: inventoryData[0]?.warehouseId || 'default_warehouse',
|
||||
priority: 0,
|
||||
estimatedShipDate: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
|
||||
estimatedDeliveryDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
cost: 5.99,
|
||||
};
|
||||
}
|
||||
|
||||
async manageFulfillment(orderId: string, action: 'pick' | 'pack' | 'ship' | 'deliver', params: Record<string, any>): Promise<FulfillmentStatus> {
|
||||
const statusMap: Record<string, FulfillmentStatus['status']> = {
|
||||
pick: 'picked',
|
||||
pack: 'packed',
|
||||
ship: 'shipped',
|
||||
deliver: 'delivered',
|
||||
};
|
||||
return {
|
||||
orderId,
|
||||
status: statusMap[action],
|
||||
trackingNumber: params.trackingNumber,
|
||||
carrier: params.carrier,
|
||||
events: [{ timestamp: new Date().toISOString(), status: statusMap[action], description: `Order ${action}ed` }],
|
||||
};
|
||||
}
|
||||
|
||||
async syncStatus(orderId: string, status: string): Promise<{ success: boolean; message: string }> {
|
||||
return { success: true, message: `Status synced to ${status}` };
|
||||
}
|
||||
}
|
||||
|
||||
class ApiUnifiedFulfillmentDataSource implements IUnifiedFulfillmentDataSource {
|
||||
private baseUrl = '/api/omnichannel';
|
||||
|
||||
async unifyOrders(platformOrders: Array<{ platform: string; orderId: string; data: Record<string, any> }>): Promise<UnifiedOrder[]> {
|
||||
const res = await fetch(`${this.baseUrl}/fulfillment/orders/unify`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ platformOrders }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async routeOrder(orderId: string, inventoryData: Array<{ warehouseId: string; available: number }>): Promise<FulfillmentRoute> {
|
||||
const res = await fetch(`${this.baseUrl}/fulfillment/order/${orderId}/route`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ inventoryData }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async manageFulfillment(orderId: string, action: 'pick' | 'pack' | 'ship' | 'deliver', params: Record<string, any>): Promise<FulfillmentStatus> {
|
||||
const res = await fetch(`${this.baseUrl}/fulfillment/order/${orderId}/manage`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action, params }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
|
||||
async syncStatus(orderId: string, status: string): Promise<{ success: boolean; message: string }> {
|
||||
const res = await fetch(`${this.baseUrl}/fulfillment/order/${orderId}/sync-status`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ status }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.data;
|
||||
}
|
||||
}
|
||||
|
||||
const useMock = process.env.REACT_APP_USE_MOCK === 'true';
|
||||
export const unifiedFulfillmentDataSource: IUnifiedFulfillmentDataSource = useMock
|
||||
? new MockUnifiedFulfillmentDataSource()
|
||||
: new ApiUnifiedFulfillmentDataSource();
|
||||
@@ -190,7 +190,7 @@ export class UserDataSourceImpl implements UserDataSource {
|
||||
|
||||
const updatedUser: User = {
|
||||
...existingUser,
|
||||
status: status as any,
|
||||
status: status as 'active' | 'inactive' | 'suspended',
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user