Spaces:
Sleeping
Sleeping
| import React, { useState } from 'react'; | |
| import { motion } from 'framer-motion'; | |
| import { | |
| Link2, | |
| Check, | |
| X, | |
| ExternalLink, | |
| Settings, | |
| RefreshCw, | |
| Shield, | |
| Key, | |
| AlertCircle, | |
| CheckCircle, | |
| Linkedin, | |
| Palette, | |
| Zap, | |
| ArrowRight, | |
| Info, | |
| Save | |
| } from 'lucide-react'; | |
| import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; | |
| import { Button } from '@/components/ui/button'; | |
| import { Badge } from '@/components/ui/badge'; | |
| import { Switch } from '@/components/ui/switch'; | |
| import { Label } from '@/components/ui/label'; | |
| import { Input } from '@/components/ui/input'; | |
| import { Separator } from '@/components/ui/separator'; | |
| import { | |
| Dialog, | |
| DialogContent, | |
| DialogHeader, | |
| DialogTitle, | |
| DialogTrigger, | |
| DialogDescription, | |
| } from '@/components/ui/dialog'; | |
| import { | |
| Alert, | |
| AlertDescription, | |
| AlertTitle, | |
| } from '@/components/ui/alert'; | |
| const integrations = [ | |
| { | |
| id: 'linkedin', | |
| name: 'LinkedIn', | |
| description: 'Connect your LinkedIn account to schedule and publish posts directly', | |
| icon: Linkedin, | |
| color: 'blue', | |
| bgColor: 'bg-[#0A66C2]', | |
| connected: true, | |
| account: 'alex.business@company.com', | |
| lastSync: '2 mins ago', | |
| features: [ | |
| 'Schedule posts up to 60 days in advance', | |
| 'Publish carousel, image, and text posts', | |
| 'Track post performance analytics', | |
| 'Manage multiple company pages' | |
| ] | |
| }, | |
| { | |
| id: 'canva', | |
| name: 'Canva', | |
| description: 'Import designs directly from your Canva workspace for post visuals', | |
| icon: Palette, | |
| color: 'purple', | |
| bgColor: 'bg-gradient-to-br from-[#00C4CC] to-[#7B2FF7]', | |
| connected: false, | |
| account: null, | |
| lastSync: null, | |
| features: [ | |
| 'Browse and import Canva designs', | |
| 'Access brand kit assets', | |
| 'Import templates for carousels', | |
| 'Sync design updates automatically' | |
| ] | |
| }, | |
| ]; | |
| export default function Integrations() { | |
| const [linkedInDialogOpen, setLinkedInDialogOpen] = useState(false); | |
| const [canvaDialogOpen, setCanvaDialogOpen] = useState(false); | |
| const [autoPost, setAutoPost] = useState(true); | |
| const [notifications, setNotifications] = useState(true); | |
| return ( | |
| <div className="min-h-screen bg-gradient-to-br from-slate-50 via-white to-blue-50/30"> | |
| <div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-8"> | |
| {/* Header */} | |
| <motion.div | |
| initial={{ opacity: 0, y: -20 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| className="mb-8" | |
| > | |
| <div className="flex flex-col md:flex-row md:items-center md:justify-between gap-4"> | |
| <div> | |
| <h1 className="text-3xl font-bold text-slate-900 tracking-tight"> | |
| Integrations | |
| </h1> | |
| <p className="text-slate-500 mt-1"> | |
| Connect your tools to streamline your content workflow | |
| </p> | |
| </div> | |
| </div> | |
| </motion.div> | |
| {/* Integration Status Banner */} | |
| <motion.div | |
| initial={{ opacity: 0, y: 10 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| className="mb-8" | |
| > | |
| <Alert className="border-blue-200 bg-blue-50"> | |
| <Info className="h-4 w-4 text-blue-600" /> | |
| <AlertTitle className="text-blue-800">Quick Setup</AlertTitle> | |
| <AlertDescription className="text-blue-700"> | |
| Connect both LinkedIn and Canva to unlock the full potential of automated content scheduling. Your designs will flow seamlessly to your LinkedIn audience. | |
| </AlertDescription> | |
| </Alert> | |
| </motion.div> | |
| {/* Integration Cards */} | |
| <div className="space-y-6"> | |
| {integrations.map((integration, index) => ( | |
| <motion.div | |
| key={integration.id} | |
| initial={{ opacity: 0, y: 20 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| transition={{ delay: index * 0.1 }} | |
| > | |
| <Card className="border-0 shadow-lg shadow-slate-200/50 overflow-hidden"> | |
| <CardContent className="p-0"> | |
| <div className="flex flex-col lg:flex-row"> | |
| {/* Left Section - Integration Info */} | |
| <div className="flex-1 p-6"> | |
| <div className="flex items-start gap-4"> | |
| <div className={`w-14 h-14 rounded-xl ${integration.bgColor} flex items-center justify-center shadow-lg`}> | |
| <integration.icon className="w-7 h-7 text-white" /> | |
| </div> | |
| <div className="flex-1"> | |
| <div className="flex items-center gap-3"> | |
| <h3 className="text-xl font-semibold text-slate-900"> | |
| {integration.name} | |
| </h3> | |
| {integration.connected ? ( | |
| <Badge className="bg-emerald-100 text-emerald-700 border-0 gap-1"> | |
| <CheckCircle className="w-3 h-3" /> | |
| Connected | |
| </Badge> | |
| ) : ( | |
| <Badge variant="outline" className="text-slate-500 border-slate-300"> | |
| Not Connected | |
| </Badge> | |
| )} | |
| </div> | |
| <p className="text-slate-500 mt-1"> | |
| {integration.description} | |
| </p> | |
| {integration.connected && ( | |
| <div className="flex items-center gap-4 mt-3"> | |
| <div className="flex items-center gap-2 text-sm"> | |
| <Key className="w-4 h-4 text-slate-400" /> | |
| <span className="text-slate-600">{integration.account}</span> | |
| </div> | |
| <div className="flex items-center gap-2 text-sm"> | |
| <RefreshCw className="w-4 h-4 text-slate-400" /> | |
| <span className="text-slate-500">Synced {integration.lastSync}</span> | |
| </div> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| {/* Features */} | |
| <div className="mt-6"> | |
| <p className="text-sm font-medium text-slate-700 mb-3">Features</p> | |
| <div className="grid sm:grid-cols-2 gap-2"> | |
| {integration.features.map((feature, idx) => ( | |
| <div key={idx} className="flex items-center gap-2 text-sm text-slate-600"> | |
| <Check className="w-4 h-4 text-emerald-500 shrink-0" /> | |
| <span>{feature}</span> | |
| </div> | |
| ))} | |
| </div> | |
| </div> | |
| </div> | |
| {/* Right Section - Actions */} | |
| <div className="lg:w-64 p-6 bg-slate-50 border-t lg:border-t-0 lg:border-l border-slate-100 flex flex-col justify-center"> | |
| {integration.connected ? ( | |
| <div className="space-y-4"> | |
| <Dialog> | |
| <DialogTrigger asChild> | |
| <Button variant="outline" className="w-full gap-2"> | |
| <Settings className="w-4 h-4" /> | |
| Settings | |
| </Button> | |
| </DialogTrigger> | |
| <DialogContent> | |
| <DialogHeader> | |
| <DialogTitle className="flex items-center gap-3"> | |
| <div className={`w-10 h-10 rounded-lg ${integration.bgColor} flex items-center justify-center`}> | |
| <integration.icon className="w-5 h-5 text-white" /> | |
| </div> | |
| {integration.name} Settings | |
| </DialogTitle> | |
| <DialogDescription> | |
| Configure your {integration.name} integration preferences | |
| </DialogDescription> | |
| </DialogHeader> | |
| <div className="space-y-6 pt-4"> | |
| <div className="flex items-center justify-between"> | |
| <div> | |
| <Label className="text-sm font-medium">Auto-post scheduled content</Label> | |
| <p className="text-xs text-slate-500 mt-0.5"> | |
| Automatically publish posts at scheduled times | |
| </p> | |
| </div> | |
| <Switch checked={autoPost} onCheckedChange={setAutoPost} /> | |
| </div> | |
| <Separator /> | |
| <div className="flex items-center justify-between"> | |
| <div> | |
| <Label className="text-sm font-medium">Post notifications</Label> | |
| <p className="text-xs text-slate-500 mt-0.5"> | |
| Get notified when posts are published | |
| </p> | |
| </div> | |
| <Switch checked={notifications} onCheckedChange={setNotifications} /> | |
| </div> | |
| <Separator /> | |
| <div> | |
| <Label className="text-sm font-medium">Connected Account</Label> | |
| <div className="flex items-center gap-3 mt-2 p-3 rounded-lg bg-slate-50"> | |
| <div className={`w-8 h-8 rounded-lg ${integration.bgColor} flex items-center justify-center`}> | |
| <integration.icon className="w-4 h-4 text-white" /> | |
| </div> | |
| <div className="flex-1"> | |
| <p className="text-sm font-medium text-slate-700">{integration.account}</p> | |
| <p className="text-xs text-slate-500">Connected</p> | |
| </div> | |
| <Button variant="ghost" size="sm" className="text-red-600 hover:text-red-700 hover:bg-red-50"> | |
| Disconnect | |
| </Button> | |
| </div> | |
| </div> | |
| </div> | |
| </DialogContent> | |
| </Dialog> | |
| <Button variant="ghost" className="w-full gap-2 text-red-600 hover:text-red-700 hover:bg-red-50"> | |
| <X className="w-4 h-4" /> | |
| Disconnect | |
| </Button> | |
| </div> | |
| ) : ( | |
| <div className="space-y-4"> | |
| <Dialog> | |
| <DialogTrigger asChild> | |
| <Button className={`w-full gap-2 ${ | |
| integration.id === 'linkedin' | |
| ? 'bg-[#0A66C2] hover:bg-[#004182]' | |
| : 'bg-gradient-to-r from-[#00C4CC] to-[#7B2FF7] hover:opacity-90' | |
| }`}> | |
| <Link2 className="w-4 h-4" /> | |
| Connect {integration.name} | |
| </Button> | |
| </DialogTrigger> | |
| <DialogContent> | |
| <DialogHeader> | |
| <DialogTitle className="flex items-center gap-3"> | |
| <div className={`w-10 h-10 rounded-lg ${integration.bgColor} flex items-center justify-center`}> | |
| <integration.icon className="w-5 h-5 text-white" /> | |
| </div> | |
| Connect to {integration.name} | |
| </DialogTitle> | |
| <DialogDescription> | |
| Authorize access to your {integration.name} account | |
| </DialogDescription> | |
| </DialogHeader> | |
| <div className="space-y-6 pt-4"> | |
| <div className="p-4 rounded-xl bg-slate-50 border border-slate-100"> | |
| <div className="flex items-start gap-3"> | |
| <Shield className="w-5 h-5 text-blue-600 mt-0.5" /> | |
| <div> | |
| <p className="text-sm font-medium text-slate-700">Secure Connection</p> | |
| <p className="text-xs text-slate-500 mt-1"> | |
| Your credentials are encrypted and never stored. We only request necessary permissions. | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| <div> | |
| <Label className="text-sm font-medium">Permissions Requested</Label> | |
| <div className="mt-2 space-y-2"> | |
| {integration.id === 'linkedin' ? ( | |
| <> | |
| <div className="flex items-center gap-2 text-sm text-slate-600"> | |
| <Check className="w-4 h-4 text-emerald-500" /> | |
| Read and write posts on your behalf | |
| </div> | |
| <div className="flex items-center gap-2 text-sm text-slate-600"> | |
| <Check className="w-4 h-4 text-emerald-500" /> | |
| Schedule posts for future publishing | |
| </div> | |
| <div className="flex items-center gap-2 text-sm text-slate-600"> | |
| <Check className="w-4 h-4 text-emerald-500" /> | |
| Access post analytics and insights | |
| </div> | |
| </> | |
| ) : ( | |
| <> | |
| <div className="flex items-center gap-2 text-sm text-slate-600"> | |
| <Check className="w-4 h-4 text-emerald-500" /> | |
| View your Canva designs | |
| </div> | |
| <div className="flex items-center gap-2 text-sm text-slate-600"> | |
| <Check className="w-4 h-4 text-emerald-500" /> | |
| Download designs as images | |
| </div> | |
| <div className="flex items-center gap-2 text-sm text-slate-600"> | |
| <Check className="w-4 h-4 text-emerald-500" /> | |
| Access brand kit assets | |
| </div> | |
| </> | |
| )} | |
| </div> | |
| </div> | |
| <Button className={`w-full gap-2 ${ | |
| integration.id === 'linkedin' | |
| ? 'bg-[#0A66C2] hover:bg-[#004182]' | |
| : 'bg-gradient-to-r from-[#00C4CC] to-[#7B2FF7] hover:opacity-90' | |
| }`}> | |
| Continue with {integration.name} | |
| <ExternalLink className="w-4 h-4" /> | |
| </Button> | |
| </div> | |
| </DialogContent> | |
| </Dialog> | |
| <p className="text-xs text-center text-slate-500"> | |
| You'll be redirected to {integration.name} to authorize | |
| </p> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| </motion.div> | |
| ))} | |
| </div> | |
| {/* API Configuration */} | |
| <motion.div | |
| initial={{ opacity: 0, y: 20 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| transition={{ delay: 0.3 }} | |
| className="mt-8" | |
| > | |
| <Card className="border-0 shadow-lg shadow-slate-200/50"> | |
| <CardHeader> | |
| <CardTitle className="text-lg font-semibold flex items-center gap-2"> | |
| <Key className="w-5 h-5 text-amber-500" /> | |
| API Configuration | |
| </CardTitle> | |
| <CardDescription> | |
| For advanced users who want to configure custom API settings | |
| </CardDescription> | |
| </CardHeader> | |
| <CardContent className="space-y-4"> | |
| <div className="grid md:grid-cols-2 gap-4"> | |
| <div> | |
| <Label className="text-sm text-slate-600">LinkedIn Client ID</Label> | |
| <Input | |
| className="mt-1.5" | |
| placeholder="Enter your LinkedIn Client ID" | |
| type="password" | |
| defaultValue="••••••••••••••••" | |
| /> | |
| </div> | |
| <div> | |
| <Label className="text-sm text-slate-600">LinkedIn Client Secret</Label> | |
| <Input | |
| className="mt-1.5" | |
| placeholder="Enter your LinkedIn Client Secret" | |
| type="password" | |
| defaultValue="••••••••••••••••" | |
| /> | |
| </div> | |
| <div> | |
| <Label className="text-sm text-slate-600">Canva API Key</Label> | |
| <Input | |
| className="mt-1.5" | |
| placeholder="Enter your Canva API Key" | |
| type="password" | |
| /> | |
| </div> | |
| <div> | |
| <Label className="text-sm text-slate-600">Webhook URL</Label> | |
| <Input | |
| className="mt-1.5" | |
| placeholder="https://your-webhook-url.com" | |
| /> | |
| </div> | |
| </div> | |
| <div className="flex justify-end"> | |
| <Button variant="outline" className="gap-2"> | |
| <Save className="w-4 h-4" /> | |
| Save Configuration | |
| </Button> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| </motion.div> | |
| </div> | |
| </div> | |
| ); | |
| } | |