Files
loyaly_cutomerweb/src/features/settings/components/IntegrationsGrid.tsx
2026-09-28 16:35:34 +05:30

155 lines
5.1 KiB
TypeScript

'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';
import {SAMPLE_INTEGRATIONS} from '@/shared/mocks/sampleData';
export interface IntegrationApp {
id: string;
name: string;
category: string;
description: string;
status: 'connected' | 'disconnected' | 'syncing';
apiKeyLabel?: string;
lastSync?: string;
}
export function IntegrationsGrid() {
const toast = useToast();
const [apps, setApps] = useState<IntegrationApp[]>(SAMPLE_INTEGRATIONS);
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>
);
}