|
|
@@ -7,38 +7,212 @@ import { Textarea } from "@/components/ui/textarea";
|
|
|
import { Switch } from "@/components/ui/switch";
|
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
|
import { Badge } from "@/components/ui/badge";
|
|
|
-import { Mic, MessageSquare, Brain, Zap, Store, ChevronDown } from "lucide-react";
|
|
|
-import { useState } from "react";
|
|
|
-
|
|
|
-const webshops = [
|
|
|
- {
|
|
|
- id: 1,
|
|
|
- name: "Fashion Forward",
|
|
|
- platform: "Shopify",
|
|
|
- country: "United States",
|
|
|
- phoneNumber: "+1 (555) 123-4567",
|
|
|
- status: "Active"
|
|
|
- },
|
|
|
- {
|
|
|
- id: 2,
|
|
|
- name: "Tech Gadgets Pro",
|
|
|
- platform: "WooCommerce",
|
|
|
- country: "United States",
|
|
|
- phoneNumber: "+1 (555) 987-6543",
|
|
|
- status: "Active"
|
|
|
- },
|
|
|
- {
|
|
|
- id: 3,
|
|
|
- name: "Home & Garden UK",
|
|
|
- platform: "Shopify",
|
|
|
- country: "United Kingdom",
|
|
|
- phoneNumber: "+44 20 7946 0958",
|
|
|
- status: "Active"
|
|
|
- }
|
|
|
-];
|
|
|
+import { Mic, MessageSquare, Brain, Zap, Store, ChevronDown, Loader2 } from "lucide-react";
|
|
|
+import { useState, useEffect } from "react";
|
|
|
+import { API_URL } from "@/lib/config";
|
|
|
+import { useToast } from "@/hooks/use-toast";
|
|
|
+
|
|
|
+interface StoreData {
|
|
|
+ id: string;
|
|
|
+ store_name: string | null;
|
|
|
+ platform_name: string;
|
|
|
+ store_url: string | null;
|
|
|
+ phone_number: string | null;
|
|
|
+ is_active: boolean | null;
|
|
|
+ alt_data?: {
|
|
|
+ [key: string]: any;
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+interface AIConfig {
|
|
|
+ voice_type: string;
|
|
|
+ speaking_speed: string;
|
|
|
+ accent_language: string;
|
|
|
+ greeting_message: string;
|
|
|
+ business_hours_mode: boolean;
|
|
|
+ local_currency_support: boolean;
|
|
|
+ escalation_policy: string;
|
|
|
+}
|
|
|
|
|
|
export function AIConfigContent() {
|
|
|
- const [selectedWebshop, setSelectedWebshop] = useState(webshops[0]);
|
|
|
+ const { toast } = useToast();
|
|
|
+ const [stores, setStores] = useState<StoreData[]>([]);
|
|
|
+ const [selectedStore, setSelectedStore] = useState<StoreData | null>(null);
|
|
|
+ const [loading, setLoading] = useState(true);
|
|
|
+ const [saving, setSaving] = useState(false);
|
|
|
+ const [aiConfig, setAiConfig] = useState<AIConfig>({
|
|
|
+ voice_type: "sarah",
|
|
|
+ speaking_speed: "normal",
|
|
|
+ accent_language: "us-english",
|
|
|
+ greeting_message: "",
|
|
|
+ business_hours_mode: true,
|
|
|
+ local_currency_support: true,
|
|
|
+ escalation_policy: "medium"
|
|
|
+ });
|
|
|
+
|
|
|
+ // Get shop parameter from URL
|
|
|
+ useEffect(() => {
|
|
|
+ const params = new URLSearchParams(window.location.search);
|
|
|
+ const shopId = params.get('shop');
|
|
|
+
|
|
|
+ const fetchStores = async () => {
|
|
|
+ try {
|
|
|
+ const sessionData = localStorage.getItem('session_data');
|
|
|
+ if (!sessionData) {
|
|
|
+ throw new Error('No session data found');
|
|
|
+ }
|
|
|
+
|
|
|
+ const session = JSON.parse(sessionData);
|
|
|
+ const response = await fetch(`${API_URL}/api/stores`, {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${session.session.access_token}`,
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!response.ok) {
|
|
|
+ throw new Error('Failed to fetch stores');
|
|
|
+ }
|
|
|
+
|
|
|
+ const data = await response.json();
|
|
|
+ if (data.success) {
|
|
|
+ const storesList = data.stores || [];
|
|
|
+ setStores(storesList);
|
|
|
+
|
|
|
+ // Select the store from URL parameter or first store
|
|
|
+ if (shopId) {
|
|
|
+ const store = storesList.find((s: StoreData) => s.id === shopId);
|
|
|
+ if (store) {
|
|
|
+ setSelectedStore(store);
|
|
|
+ loadAIConfig(store);
|
|
|
+ } else if (storesList.length > 0) {
|
|
|
+ setSelectedStore(storesList[0]);
|
|
|
+ loadAIConfig(storesList[0]);
|
|
|
+ }
|
|
|
+ } else if (storesList.length > 0) {
|
|
|
+ setSelectedStore(storesList[0]);
|
|
|
+ loadAIConfig(storesList[0]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Error fetching stores:', error);
|
|
|
+ toast({
|
|
|
+ title: "Error",
|
|
|
+ description: "Failed to load stores. Please try again.",
|
|
|
+ variant: "destructive"
|
|
|
+ });
|
|
|
+ } finally {
|
|
|
+ setLoading(false);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ fetchStores();
|
|
|
+ }, [toast]);
|
|
|
+
|
|
|
+ const loadAIConfig = (store: StoreData) => {
|
|
|
+ // Load AI config from store's alt_data or use defaults
|
|
|
+ const config = store.alt_data?.ai_config || {};
|
|
|
+
|
|
|
+ setAiConfig({
|
|
|
+ voice_type: config.voice_type || "sarah",
|
|
|
+ speaking_speed: config.speaking_speed || "normal",
|
|
|
+ accent_language: config.accent_language || "us-english",
|
|
|
+ greeting_message: config.greeting_message || `Hello! Thank you for calling ${store.store_name || 'our store'}. I'm your AI assistant, and I'm here to help you with any questions about your order or our products. How can I assist you today?`,
|
|
|
+ business_hours_mode: config.business_hours_mode !== undefined ? config.business_hours_mode : true,
|
|
|
+ local_currency_support: config.local_currency_support !== undefined ? config.local_currency_support : true,
|
|
|
+ escalation_policy: config.escalation_policy || "medium"
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleStoreChange = (storeId: string) => {
|
|
|
+ const store = stores.find(s => s.id === storeId);
|
|
|
+ if (store) {
|
|
|
+ setSelectedStore(store);
|
|
|
+ loadAIConfig(store);
|
|
|
+ // Update URL
|
|
|
+ window.history.replaceState({}, '', `/ai-config?shop=${storeId}`);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleSaveConfig = async () => {
|
|
|
+ if (!selectedStore) return;
|
|
|
+
|
|
|
+ setSaving(true);
|
|
|
+ try {
|
|
|
+ const sessionData = localStorage.getItem('session_data');
|
|
|
+ if (!sessionData) {
|
|
|
+ throw new Error('No session data found');
|
|
|
+ }
|
|
|
+
|
|
|
+ const session = JSON.parse(sessionData);
|
|
|
+
|
|
|
+ // Update store's alt_data with AI config
|
|
|
+ const response = await fetch(`${API_URL}/api/stores/${selectedStore.id}/ai-config`, {
|
|
|
+ method: 'PUT',
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${session.session.access_token}`,
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ },
|
|
|
+ body: JSON.stringify({ ai_config: aiConfig })
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!response.ok) {
|
|
|
+ throw new Error('Failed to save configuration');
|
|
|
+ }
|
|
|
+
|
|
|
+ toast({
|
|
|
+ title: "Success",
|
|
|
+ description: "AI configuration saved successfully.",
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Error saving config:', error);
|
|
|
+ toast({
|
|
|
+ title: "Error",
|
|
|
+ description: "Failed to save configuration. Please try again.",
|
|
|
+ variant: "destructive"
|
|
|
+ });
|
|
|
+ } finally {
|
|
|
+ setSaving(false);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ if (loading) {
|
|
|
+ return (
|
|
|
+ <div className="flex-1 flex items-center justify-center min-h-screen bg-slate-900">
|
|
|
+ <Loader2 className="w-8 h-8 text-cyan-500 animate-spin" />
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ if (stores.length === 0) {
|
|
|
+ return (
|
|
|
+ <div className="flex-1 space-y-6 p-8 bg-slate-900">
|
|
|
+ <div className="flex items-center justify-center min-h-[60vh]">
|
|
|
+ <div className="text-center">
|
|
|
+ <Store className="w-16 h-16 text-slate-600 mx-auto mb-4" />
|
|
|
+ <h3 className="text-lg font-semibold text-white mb-2">No Stores Connected</h3>
|
|
|
+ <p className="text-slate-400 mb-6">
|
|
|
+ Please connect a store first before configuring AI settings.
|
|
|
+ </p>
|
|
|
+ <Button
|
|
|
+ className="bg-cyan-500 hover:bg-cyan-600 text-white"
|
|
|
+ onClick={() => window.location.href = '/webshops'}
|
|
|
+ >
|
|
|
+ Go to Webshops
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!selectedStore) {
|
|
|
+ return (
|
|
|
+ <div className="flex-1 flex items-center justify-center min-h-screen bg-slate-900">
|
|
|
+ <p className="text-slate-400">No store selected</p>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
return (
|
|
|
<div className="flex-1 space-y-6 p-8 bg-slate-900">
|
|
|
@@ -48,11 +222,19 @@ export function AIConfigContent() {
|
|
|
<p className="text-slate-400">Configure AI behavior and responses per webshop</p>
|
|
|
</div>
|
|
|
<div className="flex gap-3">
|
|
|
- <Button variant="outline" className="text-cyan-500 border-cyan-500 hover:bg-cyan-500/10">
|
|
|
- Copy from Another Shop
|
|
|
- </Button>
|
|
|
- <Button className="bg-cyan-500 hover:bg-cyan-600 text-white">
|
|
|
- Save Configuration
|
|
|
+ <Button
|
|
|
+ className="bg-cyan-500 hover:bg-cyan-600 text-white"
|
|
|
+ onClick={handleSaveConfig}
|
|
|
+ disabled={saving}
|
|
|
+ >
|
|
|
+ {saving ? (
|
|
|
+ <>
|
|
|
+ <Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
|
|
+ Saving...
|
|
|
+ </>
|
|
|
+ ) : (
|
|
|
+ "Save Configuration"
|
|
|
+ )}
|
|
|
</Button>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -67,36 +249,40 @@ export function AIConfigContent() {
|
|
|
<p className="text-slate-400">Choose which webshop to configure</p>
|
|
|
</CardHeader>
|
|
|
<CardContent>
|
|
|
- <Select value={selectedWebshop.id.toString()} onValueChange={(value) => {
|
|
|
- const shop = webshops.find(s => s.id === parseInt(value));
|
|
|
- if (shop) setSelectedWebshop(shop);
|
|
|
- }}>
|
|
|
+ <Select value={selectedStore.id} onValueChange={handleStoreChange}>
|
|
|
<SelectTrigger className="bg-slate-700 border-slate-600 text-white">
|
|
|
<SelectValue />
|
|
|
</SelectTrigger>
|
|
|
<SelectContent className="bg-slate-700 border-slate-600">
|
|
|
- {webshops.map((shop) => (
|
|
|
- <SelectItem key={shop.id} value={shop.id.toString()}>
|
|
|
+ {stores.map((store) => (
|
|
|
+ <SelectItem key={store.id} value={store.id}>
|
|
|
<div className="flex items-center gap-3">
|
|
|
<div>
|
|
|
- <div className="text-white font-medium">{shop.name}</div>
|
|
|
- <div className="text-slate-400 text-sm">{shop.platform} • {shop.country}</div>
|
|
|
+ <div className="text-white font-medium">{store.store_name || 'Unnamed Store'}</div>
|
|
|
+ <div className="text-slate-400 text-sm capitalize">{store.platform_name}</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</SelectItem>
|
|
|
))}
|
|
|
</SelectContent>
|
|
|
</Select>
|
|
|
-
|
|
|
+
|
|
|
{/* Current Shop Info */}
|
|
|
<div className="mt-4 p-4 bg-slate-700/50 rounded-lg">
|
|
|
<div className="flex items-center justify-between">
|
|
|
<div>
|
|
|
- <h4 className="text-white font-medium">{selectedWebshop.name}</h4>
|
|
|
- <p className="text-slate-400 text-sm">{selectedWebshop.platform} • {selectedWebshop.country}</p>
|
|
|
- <p className="text-slate-300 text-sm font-mono">{selectedWebshop.phoneNumber}</p>
|
|
|
+ <h4 className="text-white font-medium">{selectedStore.store_name || 'Unnamed Store'}</h4>
|
|
|
+ <p className="text-slate-400 text-sm capitalize">{selectedStore.platform_name}</p>
|
|
|
+ {selectedStore.store_url && (
|
|
|
+ <p className="text-slate-500 text-xs mt-1">{selectedStore.store_url}</p>
|
|
|
+ )}
|
|
|
+ {selectedStore.phone_number && (
|
|
|
+ <p className="text-slate-300 text-sm font-mono mt-1">{selectedStore.phone_number}</p>
|
|
|
+ )}
|
|
|
</div>
|
|
|
- <Badge className="bg-green-500 text-white">{selectedWebshop.status}</Badge>
|
|
|
+ <Badge className={`${selectedStore.is_active ? "bg-green-500" : "bg-red-500"} text-white`}>
|
|
|
+ {selectedStore.is_active ? "Active" : "Inactive"}
|
|
|
+ </Badge>
|
|
|
</div>
|
|
|
</div>
|
|
|
</CardContent>
|
|
|
@@ -109,13 +295,13 @@ export function AIConfigContent() {
|
|
|
<Mic className="w-6 h-6 text-cyan-500" />
|
|
|
<CardTitle className="text-white">Voice & Speech Settings</CardTitle>
|
|
|
</div>
|
|
|
- <p className="text-slate-400">Configure voice characteristics for {selectedWebshop.name}</p>
|
|
|
+ <p className="text-slate-400">Configure voice characteristics for {selectedStore.store_name || 'your store'}</p>
|
|
|
</CardHeader>
|
|
|
<CardContent className="space-y-6">
|
|
|
<div className="grid gap-6 md:grid-cols-2">
|
|
|
<div className="space-y-2">
|
|
|
<Label className="text-slate-300">Voice Type</Label>
|
|
|
- <Select defaultValue="sarah">
|
|
|
+ <Select value={aiConfig.voice_type} onValueChange={(value) => setAiConfig({ ...aiConfig, voice_type: value })}>
|
|
|
<SelectTrigger className="bg-slate-700 border-slate-600 text-white">
|
|
|
<SelectValue />
|
|
|
</SelectTrigger>
|
|
|
@@ -128,7 +314,7 @@ export function AIConfigContent() {
|
|
|
</div>
|
|
|
<div className="space-y-2">
|
|
|
<Label className="text-slate-300">Speaking Speed</Label>
|
|
|
- <Select defaultValue="normal">
|
|
|
+ <Select value={aiConfig.speaking_speed} onValueChange={(value) => setAiConfig({ ...aiConfig, speaking_speed: value })}>
|
|
|
<SelectTrigger className="bg-slate-700 border-slate-600 text-white">
|
|
|
<SelectValue />
|
|
|
</SelectTrigger>
|
|
|
@@ -142,7 +328,7 @@ export function AIConfigContent() {
|
|
|
</div>
|
|
|
<div className="space-y-2">
|
|
|
<Label className="text-slate-300">Accent & Language</Label>
|
|
|
- <Select defaultValue={selectedWebshop.country === "United Kingdom" ? "uk-english" : "us-english"}>
|
|
|
+ <Select value={aiConfig.accent_language} onValueChange={(value) => setAiConfig({ ...aiConfig, accent_language: value })}>
|
|
|
<SelectTrigger className="bg-slate-700 border-slate-600 text-white">
|
|
|
<SelectValue />
|
|
|
</SelectTrigger>
|
|
|
@@ -162,37 +348,46 @@ export function AIConfigContent() {
|
|
|
<MessageSquare className="w-6 h-6 text-cyan-500" />
|
|
|
<CardTitle className="text-white">Conversation Behavior</CardTitle>
|
|
|
</div>
|
|
|
- <p className="text-slate-400">Define how the AI interacts with {selectedWebshop.name} customers</p>
|
|
|
+ <p className="text-slate-400">Define how the AI interacts with {selectedStore.store_name || 'your store'} customers</p>
|
|
|
</CardHeader>
|
|
|
<CardContent className="space-y-6">
|
|
|
<div className="space-y-2">
|
|
|
<Label className="text-slate-300">Greeting Message</Label>
|
|
|
- <Textarea
|
|
|
+ <Textarea
|
|
|
className="bg-slate-700 border-slate-600 text-white min-h-[100px]"
|
|
|
- defaultValue={`Hello! Thank you for calling ${selectedWebshop.name}. I'm your AI assistant, and I'm here to help you with any questions about your order or our products. How can I assist you today?`}
|
|
|
+ value={aiConfig.greeting_message}
|
|
|
+ onChange={(e) => setAiConfig({ ...aiConfig, greeting_message: e.target.value })}
|
|
|
/>
|
|
|
</div>
|
|
|
-
|
|
|
+
|
|
|
<div className="grid gap-6 md:grid-cols-2">
|
|
|
<div className="flex items-center justify-between">
|
|
|
<div className="space-y-1">
|
|
|
<Label className="text-slate-300">Business Hours Mode</Label>
|
|
|
<p className="text-sm text-slate-400">Adjust behavior based on store hours</p>
|
|
|
</div>
|
|
|
- <Switch defaultChecked className="data-[state=checked]:bg-cyan-500" />
|
|
|
+ <Switch
|
|
|
+ checked={aiConfig.business_hours_mode}
|
|
|
+ onCheckedChange={(checked) => setAiConfig({ ...aiConfig, business_hours_mode: checked })}
|
|
|
+ className="data-[state=checked]:bg-cyan-500"
|
|
|
+ />
|
|
|
</div>
|
|
|
<div className="flex items-center justify-between">
|
|
|
<div className="space-y-1">
|
|
|
<Label className="text-slate-300">Local Currency Support</Label>
|
|
|
<p className="text-sm text-slate-400">Auto-detect customer location</p>
|
|
|
</div>
|
|
|
- <Switch defaultChecked className="data-[state=checked]:bg-cyan-500" />
|
|
|
+ <Switch
|
|
|
+ checked={aiConfig.local_currency_support}
|
|
|
+ onCheckedChange={(checked) => setAiConfig({ ...aiConfig, local_currency_support: checked })}
|
|
|
+ className="data-[state=checked]:bg-cyan-500"
|
|
|
+ />
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div className="space-y-2">
|
|
|
<Label className="text-slate-300">Escalation Policy</Label>
|
|
|
- <Select defaultValue="medium">
|
|
|
+ <Select value={aiConfig.escalation_policy} onValueChange={(value) => setAiConfig({ ...aiConfig, escalation_policy: value })}>
|
|
|
<SelectTrigger className="bg-slate-700 border-slate-600 text-white">
|
|
|
<SelectValue />
|
|
|
</SelectTrigger>
|
|
|
@@ -212,45 +407,54 @@ export function AIConfigContent() {
|
|
|
<Brain className="w-6 h-6 text-cyan-500" />
|
|
|
<CardTitle className="text-white">Knowledge Base</CardTitle>
|
|
|
</div>
|
|
|
- <p className="text-slate-400">Training data specific to {selectedWebshop.name}</p>
|
|
|
+ <p className="text-slate-400">Training data specific to {selectedStore.store_name || 'your store'}</p>
|
|
|
</CardHeader>
|
|
|
<CardContent className="space-y-6">
|
|
|
<div className="grid gap-4 md:grid-cols-3">
|
|
|
<div className="p-4 bg-slate-700/50 rounded-lg">
|
|
|
<div className="flex items-center justify-between mb-2">
|
|
|
<h4 className="text-white font-medium">Product Catalog</h4>
|
|
|
- <Badge className="bg-green-500 text-white">Synced</Badge>
|
|
|
+ <Badge className={`${selectedStore.sync_status === 'completed' ? 'bg-green-500' : 'bg-slate-500'} text-white`}>
|
|
|
+ {selectedStore.sync_status === 'completed' ? 'Synced' : 'Not Synced'}
|
|
|
+ </Badge>
|
|
|
</div>
|
|
|
- <p className="text-slate-400 text-sm">1,247 products</p>
|
|
|
- <p className="text-slate-500 text-xs">Auto-sync from {selectedWebshop.platform}</p>
|
|
|
+ <p className="text-slate-400 text-sm">
|
|
|
+ {selectedStore.alt_data?.last_sync_stats?.products?.synced || 0} products
|
|
|
+ </p>
|
|
|
+ <p className="text-slate-500 text-xs capitalize">Auto-sync from {selectedStore.platform_name}</p>
|
|
|
</div>
|
|
|
<div className="p-4 bg-slate-700/50 rounded-lg">
|
|
|
<div className="flex items-center justify-between mb-2">
|
|
|
- <h4 className="text-white font-medium">Store Policies</h4>
|
|
|
- <Badge className="bg-green-500 text-white">Updated</Badge>
|
|
|
+ <h4 className="text-white font-medium">Orders</h4>
|
|
|
+ <Badge className={`${selectedStore.sync_status === 'completed' ? 'bg-green-500' : 'bg-slate-500'} text-white`}>
|
|
|
+ {selectedStore.sync_status === 'completed' ? 'Synced' : 'Not Synced'}
|
|
|
+ </Badge>
|
|
|
</div>
|
|
|
- <p className="text-slate-400 text-sm">Return, shipping, etc.</p>
|
|
|
- <p className="text-slate-500 text-xs">Country-specific policies</p>
|
|
|
+ <p className="text-slate-400 text-sm">
|
|
|
+ {selectedStore.alt_data?.last_sync_stats?.orders?.synced || 0} orders
|
|
|
+ </p>
|
|
|
+ <p className="text-slate-500 text-xs">Order history</p>
|
|
|
</div>
|
|
|
<div className="p-4 bg-slate-700/50 rounded-lg">
|
|
|
<div className="flex items-center justify-between mb-2">
|
|
|
- <h4 className="text-white font-medium">FAQ Database</h4>
|
|
|
- <Badge className="bg-yellow-500 text-white">Needs Review</Badge>
|
|
|
+ <h4 className="text-white font-medium">Customers</h4>
|
|
|
+ <Badge className={`${selectedStore.sync_status === 'completed' ? 'bg-green-500' : 'bg-slate-500'} text-white`}>
|
|
|
+ {selectedStore.sync_status === 'completed' ? 'Synced' : 'Not Synced'}
|
|
|
+ </Badge>
|
|
|
</div>
|
|
|
- <p className="text-slate-400 text-sm">89 Q&As</p>
|
|
|
- <p className="text-slate-500 text-xs">Regional customization needed</p>
|
|
|
+ <p className="text-slate-400 text-sm">
|
|
|
+ {selectedStore.alt_data?.last_sync_stats?.customers?.synced || 0} customers
|
|
|
+ </p>
|
|
|
+ <p className="text-slate-500 text-xs">Customer database</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
-
|
|
|
+
|
|
|
<div className="flex gap-3">
|
|
|
- <Button className="bg-cyan-500 hover:bg-cyan-600 text-white">
|
|
|
- Sync Store Data
|
|
|
- </Button>
|
|
|
- <Button variant="outline" className="text-cyan-500 border-cyan-500 hover:bg-cyan-500/10">
|
|
|
- Upload Custom Knowledge
|
|
|
- </Button>
|
|
|
- <Button variant="outline" className="text-cyan-500 border-cyan-500 hover:bg-cyan-500/10">
|
|
|
- Test Configuration
|
|
|
+ <Button
|
|
|
+ className="bg-cyan-500 hover:bg-cyan-600 text-white"
|
|
|
+ onClick={() => window.location.href = '/webshops'}
|
|
|
+ >
|
|
|
+ Manage Store Data
|
|
|
</Button>
|
|
|
</div>
|
|
|
</CardContent>
|