|
@@ -6,13 +6,20 @@ import { Input } from "@/components/ui/input";
|
|
|
import { Label } from "@/components/ui/label";
|
|
import { Label } from "@/components/ui/label";
|
|
|
import { Switch } from "@/components/ui/switch";
|
|
import { Switch } from "@/components/ui/switch";
|
|
|
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
|
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
|
|
-import { Plus, Settings, Store, Bot, PhoneCall, Globe, Zap, ShoppingBag, Loader2, Trash2, Info } from "lucide-react";
|
|
|
|
|
|
|
+import { Plus, Settings, Store, Bot, PhoneCall, Globe, Zap, ShoppingBag, Loader2, Trash2, Info, Shield } from "lucide-react";
|
|
|
import { ShopRenterConnect } from "./ShopRenterConnect";
|
|
import { ShopRenterConnect } from "./ShopRenterConnect";
|
|
|
import { WooCommerceConnect } from "./WooCommerceConnect";
|
|
import { WooCommerceConnect } from "./WooCommerceConnect";
|
|
|
import { ShopifyConnect } from "./ShopifyConnect";
|
|
import { ShopifyConnect } from "./ShopifyConnect";
|
|
|
|
|
+import { DataAccessSettings } from "./DataAccessSettings";
|
|
|
import { API_URL } from "@/lib/config";
|
|
import { API_URL } from "@/lib/config";
|
|
|
import { useToast } from "@/hooks/use-toast";
|
|
import { useToast } from "@/hooks/use-toast";
|
|
|
|
|
|
|
|
|
|
+interface DataAccessPermissions {
|
|
|
|
|
+ allow_customer_access: boolean;
|
|
|
|
|
+ allow_order_access: boolean;
|
|
|
|
|
+ allow_product_access: boolean;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
interface ConnectedStore {
|
|
interface ConnectedStore {
|
|
|
id: string;
|
|
id: string;
|
|
|
store_name: string | null;
|
|
store_name: string | null;
|
|
@@ -25,6 +32,7 @@ interface ConnectedStore {
|
|
|
sync_started_at?: string | null;
|
|
sync_started_at?: string | null;
|
|
|
sync_completed_at?: string | null;
|
|
sync_completed_at?: string | null;
|
|
|
sync_error?: string | null;
|
|
sync_error?: string | null;
|
|
|
|
|
+ data_access_permissions?: DataAccessPermissions;
|
|
|
alt_data?: {
|
|
alt_data?: {
|
|
|
wcVersion?: string;
|
|
wcVersion?: string;
|
|
|
wpVersion?: string;
|
|
wpVersion?: string;
|
|
@@ -47,6 +55,8 @@ export function IntegrationsContent() {
|
|
|
const [showConnectDialog, setShowConnectDialog] = useState(false);
|
|
const [showConnectDialog, setShowConnectDialog] = useState(false);
|
|
|
const [selectedPlatform, setSelectedPlatform] = useState<string | null>(null);
|
|
const [selectedPlatform, setSelectedPlatform] = useState<string | null>(null);
|
|
|
const [syncingStores, setSyncingStores] = useState<Set<string>>(new Set());
|
|
const [syncingStores, setSyncingStores] = useState<Set<string>>(new Set());
|
|
|
|
|
+ const [showPermissionsDialog, setShowPermissionsDialog] = useState(false);
|
|
|
|
|
+ const [selectedStore, setSelectedStore] = useState<ConnectedStore | null>(null);
|
|
|
const { toast } = useToast();
|
|
const { toast } = useToast();
|
|
|
|
|
|
|
|
const fetchStores = async () => {
|
|
const fetchStores = async () => {
|
|
@@ -421,6 +431,58 @@ export function IntegrationsContent() {
|
|
|
);
|
|
);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ const getDataAccessBadges = (shop: ConnectedStore) => {
|
|
|
|
|
+ const permissions = shop.data_access_permissions || {
|
|
|
|
|
+ allow_customer_access: true,
|
|
|
|
|
+ allow_order_access: true,
|
|
|
|
|
+ allow_product_access: true
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div className="flex flex-wrap gap-1">
|
|
|
|
|
+ {permissions.allow_product_access && (
|
|
|
|
|
+ <Badge variant="outline" className="text-xs border-blue-500 text-blue-400">
|
|
|
|
|
+ Products
|
|
|
|
|
+ </Badge>
|
|
|
|
|
+ )}
|
|
|
|
|
+ {permissions.allow_customer_access && (
|
|
|
|
|
+ <Badge variant="outline" className="text-xs border-green-500 text-green-400">
|
|
|
|
|
+ Customers
|
|
|
|
|
+ </Badge>
|
|
|
|
|
+ )}
|
|
|
|
|
+ {permissions.allow_order_access && (
|
|
|
|
|
+ <Badge variant="outline" className="text-xs border-purple-500 text-purple-400">
|
|
|
|
|
+ Orders
|
|
|
|
|
+ </Badge>
|
|
|
|
|
+ )}
|
|
|
|
|
+ {!permissions.allow_customer_access && !permissions.allow_order_access && (
|
|
|
|
|
+ <Badge variant="outline" className="text-xs border-orange-500 text-orange-400">
|
|
|
|
|
+ Limited Access
|
|
|
|
|
+ </Badge>
|
|
|
|
|
+ )}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ );
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handleOpenPermissions = (shop: ConnectedStore) => {
|
|
|
|
|
+ setSelectedStore(shop);
|
|
|
|
|
+ setShowPermissionsDialog(true);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handleClosePermissions = () => {
|
|
|
|
|
+ setShowPermissionsDialog(false);
|
|
|
|
|
+ setSelectedStore(null);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handlePermissionsUpdated = (newPermissions: DataAccessPermissions) => {
|
|
|
|
|
+ // Update the store in the list
|
|
|
|
|
+ setConnectedShops(prev => prev.map(shop =>
|
|
|
|
|
+ shop.id === selectedStore?.id
|
|
|
|
|
+ ? { ...shop, data_access_permissions: newPermissions }
|
|
|
|
|
+ : shop
|
|
|
|
|
+ ));
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
return (
|
|
return (
|
|
|
<div className="flex-1 space-y-6 p-8 bg-slate-900">
|
|
<div className="flex-1 space-y-6 p-8 bg-slate-900">
|
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex items-center justify-between">
|
|
@@ -592,6 +654,7 @@ export function IntegrationsContent() {
|
|
|
<th className="p-4 text-slate-300 font-medium">Store</th>
|
|
<th className="p-4 text-slate-300 font-medium">Store</th>
|
|
|
<th className="p-4 text-slate-300 font-medium">Phone Number</th>
|
|
<th className="p-4 text-slate-300 font-medium">Phone Number</th>
|
|
|
<th className="p-4 text-slate-300 font-medium">Platform</th>
|
|
<th className="p-4 text-slate-300 font-medium">Platform</th>
|
|
|
|
|
+ <th className="p-4 text-slate-300 font-medium">Data Access</th>
|
|
|
<th className="p-4 text-slate-300 font-medium">Sync Status</th>
|
|
<th className="p-4 text-slate-300 font-medium">Sync Status</th>
|
|
|
<th className="p-4 text-slate-300 font-medium">Background Sync</th>
|
|
<th className="p-4 text-slate-300 font-medium">Background Sync</th>
|
|
|
<th className="p-4 text-slate-300 font-medium">Created</th>
|
|
<th className="p-4 text-slate-300 font-medium">Created</th>
|
|
@@ -644,6 +707,20 @@ export function IntegrationsContent() {
|
|
|
{shop.platform_name}
|
|
{shop.platform_name}
|
|
|
</Badge>
|
|
</Badge>
|
|
|
</td>
|
|
</td>
|
|
|
|
|
+ <td className="p-4">
|
|
|
|
|
+ <div className="flex flex-col gap-2">
|
|
|
|
|
+ {getDataAccessBadges(shop)}
|
|
|
|
|
+ <Button
|
|
|
|
|
+ size="sm"
|
|
|
|
|
+ variant="ghost"
|
|
|
|
|
+ className="text-xs text-cyan-400 hover:text-cyan-300 hover:bg-cyan-500/10 h-6 px-2"
|
|
|
|
|
+ onClick={() => handleOpenPermissions(shop)}
|
|
|
|
|
+ >
|
|
|
|
|
+ <Shield className="w-3 h-3 mr-1" />
|
|
|
|
|
+ Configure
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </td>
|
|
|
<td className="p-4">
|
|
<td className="p-4">
|
|
|
<div className="flex flex-col gap-2">
|
|
<div className="flex flex-col gap-2">
|
|
|
{getSyncStatusBadge(shop)}
|
|
{getSyncStatusBadge(shop)}
|
|
@@ -781,6 +858,42 @@ export function IntegrationsContent() {
|
|
|
</CardContent>
|
|
</CardContent>
|
|
|
</Card>
|
|
</Card>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+
|
|
|
|
|
+ {/* Data Access Permissions Dialog */}
|
|
|
|
|
+ <Dialog open={showPermissionsDialog} onOpenChange={setShowPermissionsDialog}>
|
|
|
|
|
+ <DialogContent className="bg-slate-800 border-slate-700 max-w-3xl max-h-[90vh] overflow-y-auto">
|
|
|
|
|
+ <DialogHeader>
|
|
|
|
|
+ <DialogTitle className="text-white text-2xl flex items-center gap-2">
|
|
|
|
|
+ <Shield className="w-6 h-6 text-cyan-500" />
|
|
|
|
|
+ Data Access Permissions
|
|
|
|
|
+ </DialogTitle>
|
|
|
|
|
+ <DialogDescription className="text-slate-400">
|
|
|
|
|
+ {selectedStore && `Configure data access permissions for ${selectedStore.store_name || 'this store'}`}
|
|
|
|
|
+ </DialogDescription>
|
|
|
|
|
+ </DialogHeader>
|
|
|
|
|
+ {selectedStore && (
|
|
|
|
|
+ <DataAccessSettings
|
|
|
|
|
+ storeId={selectedStore.id}
|
|
|
|
|
+ storeName={selectedStore.store_name || 'this store'}
|
|
|
|
|
+ currentPermissions={selectedStore.data_access_permissions || {
|
|
|
|
|
+ allow_customer_access: true,
|
|
|
|
|
+ allow_order_access: true,
|
|
|
|
|
+ allow_product_access: true
|
|
|
|
|
+ }}
|
|
|
|
|
+ onPermissionsUpdated={handlePermissionsUpdated}
|
|
|
|
|
+ />
|
|
|
|
|
+ )}
|
|
|
|
|
+ <div className="flex justify-end pt-4 border-t border-slate-700">
|
|
|
|
|
+ <Button
|
|
|
|
|
+ variant="outline"
|
|
|
|
|
+ onClick={handleClosePermissions}
|
|
|
|
|
+ className="text-slate-400 border-slate-600 hover:bg-slate-700"
|
|
|
|
|
+ >
|
|
|
|
|
+ Close
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </DialogContent>
|
|
|
|
|
+ </Dialog>
|
|
|
</div>
|
|
</div>
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|