first commit
This commit is contained in:
213
src/features/settings/components/IntegrationsGrid.tsx
Normal file
213
src/features/settings/components/IntegrationsGrid.tsx
Normal file
@@ -0,0 +1,213 @@
|
||||
'use client';
|
||||
|
||||
import {useState} from 'react';
|
||||
import {VStack, HStack} from '@astryxdesign/core/Layout';
|
||||
import {Grid} from '@astryxdesign/core/Grid';
|
||||
import {Card} from '@astryxdesign/core/Card';
|
||||
import {Text, Heading} from '@astryxdesign/core/Text';
|
||||
import {Badge} from '@astryxdesign/core/Badge';
|
||||
import {Button} from '@astryxdesign/core/Button';
|
||||
import {TextInput} from '@astryxdesign/core/TextInput';
|
||||
import {useToast} from '@astryxdesign/core/Toast';
|
||||
import {StaticPanel} from '@/shared/components/patterns/PanelCard';
|
||||
|
||||
export interface IntegrationApp {
|
||||
id: string;
|
||||
name: string;
|
||||
category: string;
|
||||
description: string;
|
||||
status: 'connected' | 'disconnected' | 'syncing';
|
||||
apiKeyLabel?: string;
|
||||
lastSync?: string;
|
||||
}
|
||||
|
||||
const INITIAL_APPS: IntegrationApp[] = [
|
||||
{
|
||||
id: 'shopify',
|
||||
name: 'Shopify Storefront',
|
||||
category: 'E-commerce POS',
|
||||
description: 'Sync online customer orders, cart totals and auto-issue LYT points.',
|
||||
status: 'connected',
|
||||
apiKeyLabel: 'myshopify-store.myshopify.com',
|
||||
lastSync: '5 mins ago',
|
||||
},
|
||||
{
|
||||
id: 'woocommerce',
|
||||
name: 'WooCommerce',
|
||||
category: 'E-commerce POS',
|
||||
description: 'WordPress store integration for online checkout redemption.',
|
||||
status: 'disconnected',
|
||||
},
|
||||
{
|
||||
id: 'razorpay',
|
||||
name: 'Razorpay PG',
|
||||
category: 'Payment Gateway',
|
||||
description: 'Automated settlement reconciliation and online UPI payment sync.',
|
||||
status: 'connected',
|
||||
apiKeyLabel: 'rzp_live_••••••••8841',
|
||||
lastSync: 'Just now',
|
||||
},
|
||||
{
|
||||
id: 'stripe',
|
||||
name: 'Stripe Billing',
|
||||
category: 'Payment Gateway',
|
||||
description: 'International cards and subscription recurring billing handler.',
|
||||
status: 'disconnected',
|
||||
},
|
||||
{
|
||||
id: 'whatsapp',
|
||||
name: 'WhatsApp Business API',
|
||||
category: 'Messaging Channel',
|
||||
description: 'Send instant transaction receipts, reward expiry notices and OTPs.',
|
||||
status: 'connected',
|
||||
apiKeyLabel: '+91 98450 12345 (Verified)',
|
||||
lastSync: '2 mins ago',
|
||||
},
|
||||
{
|
||||
id: 'google',
|
||||
name: 'Google Business Profile',
|
||||
category: 'Local Search & Maps',
|
||||
description: 'Sync branch operating hours, store locations and customer reviews.',
|
||||
status: 'connected',
|
||||
apiKeyLabel: '5 locations synced',
|
||||
lastSync: '1 hour ago',
|
||||
},
|
||||
{
|
||||
id: 'meta',
|
||||
name: 'Meta Ads & Conversions',
|
||||
category: 'Marketing & Ads',
|
||||
description: 'Track ad attribution, return on ad spend (ROAS) and retargeting.',
|
||||
status: 'disconnected',
|
||||
},
|
||||
];
|
||||
|
||||
export function IntegrationsGrid() {
|
||||
const toast = useToast();
|
||||
const [apps, setApps] = useState<IntegrationApp[]>(INITIAL_APPS);
|
||||
const [selectedApp, setSelectedApp] = useState<IntegrationApp | null>(null);
|
||||
const [apiKeyInput, setApiKeyInput] = useState('');
|
||||
|
||||
const toggleConnection = (app: IntegrationApp) => {
|
||||
if (app.status === 'connected') {
|
||||
setApps((prev) =>
|
||||
prev.map((a) =>
|
||||
a.id === app.id ? {...a, status: 'disconnected', lastSync: undefined} : a,
|
||||
),
|
||||
);
|
||||
toast({body: `Disconnected ${app.name}`});
|
||||
} else {
|
||||
setSelectedApp(app);
|
||||
setApiKeyInput('');
|
||||
}
|
||||
};
|
||||
|
||||
const handleConfirmConnect = () => {
|
||||
if (!selectedApp) return;
|
||||
setApps((prev) =>
|
||||
prev.map((a) =>
|
||||
a.id === selectedApp.id
|
||||
? {
|
||||
...a,
|
||||
status: 'connected',
|
||||
apiKeyLabel: apiKeyInput || 'Configured',
|
||||
lastSync: 'Just now',
|
||||
}
|
||||
: a,
|
||||
),
|
||||
);
|
||||
toast({body: `Successfully connected ${selectedApp.name}`});
|
||||
setSelectedApp(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<VStack gap={5}>
|
||||
<StaticPanel
|
||||
title="Third-Party Integrations & Connectors"
|
||||
subtitle="Connect E-commerce storefronts, payment gateways, messaging services and advertising platforms."
|
||||
>
|
||||
<VStack gap={4}>
|
||||
{selectedApp ? (
|
||||
<Card variant="muted">
|
||||
<VStack gap={3}>
|
||||
<Heading level={3}>Connect {selectedApp.name}</Heading>
|
||||
<Text size="sm" color="secondary">
|
||||
{selectedApp.description}
|
||||
</Text>
|
||||
<TextInput
|
||||
label="API Key / Store URL / Identifier"
|
||||
value={apiKeyInput}
|
||||
onChange={setApiKeyInput}
|
||||
placeholder="Paste live secret key or domain URL"
|
||||
/>
|
||||
<HStack gap={2}>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
label="Establish Connection"
|
||||
onClick={handleConfirmConnect}
|
||||
/>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
label="Cancel"
|
||||
onClick={() => setSelectedApp(null)}
|
||||
/>
|
||||
</HStack>
|
||||
</VStack>
|
||||
</Card>
|
||||
) : null}
|
||||
|
||||
<Grid columns={{minWidth: 320, max: 2, repeat: 'fit'}} gap={4}>
|
||||
{apps.map((app) => {
|
||||
const isConn = app.status === 'connected';
|
||||
return (
|
||||
<Card key={app.id}>
|
||||
<VStack gap={3}>
|
||||
<HStack hAlign="between" vAlign="start">
|
||||
<VStack gap={0.5}>
|
||||
<Text weight="medium" size="sm">
|
||||
{app.name}
|
||||
</Text>
|
||||
<Text size="sm" color="secondary">
|
||||
{app.category}
|
||||
</Text>
|
||||
</VStack>
|
||||
<Badge
|
||||
variant={isConn ? 'success' : 'neutral'}
|
||||
label={isConn ? 'Connected' : 'Disconnected'}
|
||||
/>
|
||||
</HStack>
|
||||
|
||||
<Text size="sm" color="secondary">
|
||||
{app.description}
|
||||
</Text>
|
||||
|
||||
{isConn && app.apiKeyLabel ? (
|
||||
<HStack hAlign="between" vAlign="center">
|
||||
<Text size="sm" color="secondary">
|
||||
{app.apiKeyLabel}
|
||||
</Text>
|
||||
{app.lastSync ? (
|
||||
<Text size="sm" color="secondary">
|
||||
Synced {app.lastSync}
|
||||
</Text>
|
||||
) : null}
|
||||
</HStack>
|
||||
) : null}
|
||||
|
||||
<Button
|
||||
variant={isConn ? 'secondary' : 'primary'}
|
||||
size="sm"
|
||||
label={isConn ? 'Disconnect' : 'Connect & Configure'}
|
||||
onClick={() => toggleConnection(app)}
|
||||
/>
|
||||
</VStack>
|
||||
</Card>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
</VStack>
|
||||
</StaticPanel>
|
||||
</VStack>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user