Skip to content

Commit cce983f

Browse files
Refine integration section
Update integration section header with a more suitable phrase and add a connection status indicator. This will display the connected site name and integration method (script or plugin) for improved user experience and clarity.
1 parent 5964412 commit cce983f

5 files changed

Lines changed: 168 additions & 1 deletion

File tree

src/components/CampaignIntegrationSettings.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { useAuth } from '@/hooks/useAuth';
55
import { IntegrationTypeSelector } from './campaign-integration/IntegrationTypeSelector';
66
import { CodeIntegration } from './campaign-integration/CodeIntegration';
77
import { PluginIntegration } from './campaign-integration/PluginIntegration';
8+
import { IntegrationStatusCard } from './campaign-integration/IntegrationStatusCard';
89
import { TabsContent } from '@/components/ui/tabs';
910

1011
interface CampaignIntegrationSettingsProps {
@@ -17,6 +18,11 @@ export const CampaignIntegrationSettings = ({ campaign }: CampaignIntegrationSet
1718

1819
return (
1920
<div className="space-y-6">
21+
<IntegrationStatusCard
22+
campaignId={campaign.id}
23+
activeIntegrationType={integrationType}
24+
/>
25+
2026
<IntegrationTypeSelector
2127
activeType={integrationType}
2228
onTypeChange={setIntegrationType}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import { useState, useEffect } from 'react';
2+
import { Card, CardContent } from '@/components/ui/card';
3+
import { Badge } from '@/components/ui/badge';
4+
import { CheckCircle, AlertCircle, Code, Globe, ShoppingBag } from 'lucide-react';
5+
import { collection, query, where, getDocs } from 'firebase/firestore';
6+
import { db } from '@/lib/firebase';
7+
8+
interface IntegrationStatusCardProps {
9+
campaignId: string;
10+
activeIntegrationType: 'code' | 'plugin';
11+
}
12+
13+
interface IntegrationStatus {
14+
hasCodeIntegration: boolean;
15+
hasPluginIntegration: boolean;
16+
pluginConfigs: Array<{
17+
id: string;
18+
type: 'wordpress' | 'shopify';
19+
domain: string;
20+
active: boolean;
21+
}>;
22+
}
23+
24+
export const IntegrationStatusCard = ({ campaignId, activeIntegrationType }: IntegrationStatusCardProps) => {
25+
const [status, setStatus] = useState<IntegrationStatus>({
26+
hasCodeIntegration: false,
27+
hasPluginIntegration: false,
28+
pluginConfigs: []
29+
});
30+
const [loading, setLoading] = useState(true);
31+
32+
useEffect(() => {
33+
const loadIntegrationStatus = async () => {
34+
try {
35+
// Vérifier les plugins configurés
36+
const pluginQuery = query(
37+
collection(db, 'plugin_configs'),
38+
where('campaignId', '==', campaignId)
39+
);
40+
41+
const pluginSnapshot = await getDocs(pluginQuery);
42+
const plugins = pluginSnapshot.docs.map(doc => ({
43+
id: doc.id,
44+
...doc.data()
45+
})) as Array<{
46+
id: string;
47+
type: 'wordpress' | 'shopify';
48+
domain: string;
49+
active: boolean;
50+
}>;
51+
52+
// Pour l'intégration par code, on considère qu'elle est toujours disponible
53+
// car elle ne nécessite pas de configuration côté serveur
54+
setStatus({
55+
hasCodeIntegration: true,
56+
hasPluginIntegration: plugins.length > 0,
57+
pluginConfigs: plugins
58+
});
59+
} catch (error) {
60+
console.error('Erreur lors du chargement du statut:', error);
61+
} finally {
62+
setLoading(false);
63+
}
64+
};
65+
66+
loadIntegrationStatus();
67+
}, [campaignId]);
68+
69+
if (loading) {
70+
return (
71+
<Card className="mb-6">
72+
<CardContent className="p-4">
73+
<div className="flex items-center gap-3">
74+
<div className="h-4 w-4 animate-pulse bg-muted rounded-full" />
75+
<div className="h-4 w-32 animate-pulse bg-muted rounded" />
76+
</div>
77+
</CardContent>
78+
</Card>
79+
);
80+
}
81+
82+
const getStatusForCurrentType = () => {
83+
if (activeIntegrationType === 'code') {
84+
return {
85+
isConnected: status.hasCodeIntegration,
86+
title: 'Intégration par code',
87+
description: 'Scripts prêts à être intégrés sur votre site',
88+
icon: <Code className="h-4 w-4" />
89+
};
90+
} else {
91+
const activePlugins = status.pluginConfigs.filter(p => p.active);
92+
return {
93+
isConnected: activePlugins.length > 0,
94+
title: `Plugin${activePlugins.length > 1 ? 's' : ''} configuré${activePlugins.length > 1 ? 's' : ''}`,
95+
description: activePlugins.length > 0
96+
? `${activePlugins.length} site${activePlugins.length > 1 ? 's' : ''} connecté${activePlugins.length > 1 ? 's' : ''}`
97+
: 'Aucun plugin configuré',
98+
icon: activePlugins.length > 0 ? (
99+
activePlugins[0].type === 'wordpress' ? <Globe className="h-4 w-4" /> : <ShoppingBag className="h-4 w-4" />
100+
) : <AlertCircle className="h-4 w-4" />,
101+
connectedSites: activePlugins
102+
};
103+
}
104+
};
105+
106+
const currentStatus = getStatusForCurrentType();
107+
108+
return (
109+
<Card className="mb-6 border-l-4" style={{ borderLeftColor: currentStatus.isConnected ? 'hsl(var(--success))' : 'hsl(var(--warning))' }}>
110+
<CardContent className="p-4">
111+
<div className="flex items-start justify-between">
112+
<div className="flex items-center gap-3">
113+
{currentStatus.isConnected ? (
114+
<CheckCircle className="h-5 w-5 text-success" />
115+
) : (
116+
<AlertCircle className="h-5 w-5 text-warning" />
117+
)}
118+
<div>
119+
<div className="flex items-center gap-2 mb-1">
120+
{currentStatus.icon}
121+
<h4 className="font-medium text-foreground">{currentStatus.title}</h4>
122+
</div>
123+
<p className="text-sm text-muted-foreground">{currentStatus.description}</p>
124+
125+
{activeIntegrationType === 'plugin' && currentStatus.connectedSites && currentStatus.connectedSites.length > 0 && (
126+
<div className="flex flex-wrap gap-2 mt-2">
127+
{currentStatus.connectedSites.map((site) => (
128+
<Badge key={site.id} variant="secondary" className="text-xs">
129+
{site.type === 'wordpress' ? <Globe className="h-3 w-3 mr-1" /> : <ShoppingBag className="h-3 w-3 mr-1" />}
130+
{site.domain}
131+
</Badge>
132+
))}
133+
</div>
134+
)}
135+
</div>
136+
</div>
137+
138+
<Badge variant={currentStatus.isConnected ? "default" : "secondary"}>
139+
{currentStatus.isConnected ? "Configuré" : "Non configuré"}
140+
</Badge>
141+
</div>
142+
</CardContent>
143+
</Card>
144+
);
145+
};

src/components/campaign-settings/CampaignSettingsHeader.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export const CampaignSettingsHeader = ({ activeTab }: CampaignSettingsHeaderProp
2424
case 'general':
2525
return 'Configurez les informations de base de votre campagne';
2626
case 'integration':
27-
return 'Scripts à intégrer sur votre site marchand';
27+
return 'Configurez le tracking d\'affiliation sur votre site';
2828
case 'payment':
2929
return 'Gérez votre méthode de paiement pour les commissions';
3030
case 'affiliates':

src/index.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
--accent-foreground: 222.2 84% 4.9%;
2424
--destructive: 0 84.2% 60.2%;
2525
--destructive-foreground: 210 40% 98%;
26+
--success: 142.1 76.2% 36.3%;
27+
--success-foreground: 355.7 100% 97.3%;
28+
--warning: 32.6 94.6% 43.7%;
29+
--warning-foreground: 210 40% 98%;
2630
--border: 214.3 31.8% 91.4%;
2731
--input: 214.3 31.8% 91.4%;
2832
--ring: 221.2 83.2% 53.3%;
@@ -46,6 +50,10 @@
4650
--accent-foreground: 210 40% 98%;
4751
--destructive: 0 62.8% 30.6%;
4852
--destructive-foreground: 210 40% 98%;
53+
--success: 142.1 70.6% 45.3%;
54+
--success-foreground: 144.9 80.4% 10%;
55+
--warning: 32.6 80.3% 51%;
56+
--warning-foreground: 60 9.1% 97.8%;
4957
--border: 217.2 32.6% 17.5%;
5058
--input: 217.2 32.6% 17.5%;
5159
--ring: 224.3 76.3% 94.1%;

tailwind.config.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ export default {
4141
DEFAULT: 'hsl(var(--destructive))',
4242
foreground: 'hsl(var(--destructive-foreground))'
4343
},
44+
success: {
45+
DEFAULT: 'hsl(var(--success))',
46+
foreground: 'hsl(var(--success-foreground))'
47+
},
48+
warning: {
49+
DEFAULT: 'hsl(var(--warning))',
50+
foreground: 'hsl(var(--warning-foreground))'
51+
},
4452
muted: {
4553
DEFAULT: 'hsl(var(--muted))',
4654
foreground: 'hsl(var(--muted-foreground))'

0 commit comments

Comments
 (0)