Created
September 17, 2024 14:42
-
-
Save aberba/a703857a6fc474122c9ebdfed6c7b3a8 to your computer and use it in GitHub Desktop.
Sapier clone
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// pages/api/execute-zap.ts | |
import { NextApiRequest, NextApiResponse } from 'next' | |
// Simulated service actions | |
const serviceActions = { | |
gmail: { | |
'Send Email': async (data: any) => { | |
// Simulate sending an email | |
await new Promise(resolve => setTimeout(resolve, 1000)) | |
return { success: true, message: `Email sent to ${data.to}` } | |
}, | |
'Create Draft': async (data: any) => { | |
// Simulate creating a draft | |
await new Promise(resolve => setTimeout(resolve, 800)) | |
return { success: true, message: `Draft created with subject: ${data.subject}` } | |
} | |
}, | |
slack: { | |
'Send Message': async (data: any) => { | |
// Simulate sending a Slack message | |
await new Promise(resolve => setTimeout(resolve, 1200)) | |
return { success: true, message: `Message sent to channel: ${data.channel}` } | |
}, | |
'Create Channel': async (data: any) => { | |
// Simulate creating a Slack channel | |
await new Promise(resolve => setTimeout(resolve, 1500)) | |
return { success: true, message: `Channel created: ${data.name}` } | |
} | |
}, | |
trello: { | |
'Create Card': async (data: any) => { | |
// Simulate creating a Trello card | |
await new Promise(resolve => setTimeout(resolve, 900)) | |
return { success: true, message: `Card created: ${data.title}` } | |
}, | |
'Move Card': async (data: any) => { | |
// Simulate moving a Trello card | |
await new Promise(resolve => setTimeout(resolve, 700)) | |
return { success: true, message: `Card moved to list: ${data.listName}` } | |
} | |
} | |
} | |
export default async function handler(req: NextApiRequest, res: NextApiResponse) { | |
if (req.method === 'POST') { | |
const { action } = req.body | |
if (!action || !action.service || !action.event) { | |
return res.status(400).json({ success: false, message: 'Invalid action data' }) | |
} | |
try { | |
const serviceAction = serviceActions[action.service][action.event] | |
if (!serviceAction) { | |
return res.status(400).json({ success: false, message: 'Action not found' }) | |
} | |
const result = await serviceAction(action.data || {}) | |
res.status(200).json(result) | |
} catch (error) { | |
console.error('Error executing zap:', error) | |
res.status(500).json({ success: false, message: 'Error executing zap' }) | |
} | |
} else { | |
res.setHeader('Allow', ['POST']) | |
res.status(405).end(`Method ${req.method} Not Allowed`) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState } from 'react' | |
import { Button } from "@/components/ui/button" | |
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card" | |
import { CheckCircleIcon, XCircleIcon, LoaderIcon, MessageSquareIcon } from 'lucide-react' | |
import { Input } from "@/components/ui/input" | |
interface WorkflowStep { | |
id: number | |
name: string | |
status: 'pending' | 'in-progress' | 'completed' | 'failed' | |
duration: number | |
} | |
const initialWorkflow: WorkflowStep[] = [ | |
{ id: 1, name: "Content Creation", status: 'pending', duration: 3000 }, | |
{ id: 2, name: "AI-powered Proofreading", status: 'pending', duration: 2000 }, | |
{ id: 3, name: "Human Review", status: 'pending', duration: 4000 }, | |
{ id: 4, name: "Approval", status: 'pending', duration: 2000 }, | |
{ id: 5, name: "SEO Optimization", status: 'pending', duration: 3000 }, | |
{ id: 6, name: "Publish to CMS", status: 'pending', duration: 2000 }, | |
{ id: 7, name: "Send SMS Notification", status: 'pending', duration: 1500 }, | |
] | |
export default function AutomationWorkflow() { | |
const [workflow, setWorkflow] = useState<WorkflowStep[]>(initialWorkflow) | |
const [isRunning, setIsRunning] = useState(false) | |
const [phoneNumber, setPhoneNumber] = useState('') | |
const runWorkflow = async () => { | |
setIsRunning(true) | |
setWorkflow(initialWorkflow) | |
for (const step of workflow) { | |
setWorkflow(current => | |
current.map(s => s.id === step.id ? { ...s, status: 'in-progress' } : s) | |
) | |
if (step.name === "Send SMS Notification") { | |
try { | |
const response = await fetch('/api/send-sms', { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
}, | |
body: JSON.stringify({ | |
to: phoneNumber, | |
body: 'Your content has been published successfully!', | |
}), | |
}); | |
const result = await response.json(); | |
if (result.success) { | |
setWorkflow(current => | |
current.map(s => s.id === step.id ? { ...s, status: 'completed' } : s) | |
) | |
} else { | |
throw new Error(result.error); | |
} | |
} catch (error) { | |
console.error('Error sending SMS:', error); | |
setWorkflow(current => | |
current.map(s => s.id === step.id ? { ...s, status: 'failed' } : s) | |
) | |
} | |
} else { | |
await new Promise<void>((resolve) => { | |
setTimeout(() => { | |
setWorkflow(current => | |
current.map(s => s.id === step.id ? { ...s, status: Math.random() > 0.2 ? 'completed' : 'failed' } : s) | |
) | |
resolve() | |
}, step.duration) | |
}) | |
} | |
if (step.status === 'failed') break | |
} | |
setIsRunning(false) | |
} | |
const getStatusIcon = (status: WorkflowStep['status'], name: string) => { | |
switch (status) { | |
case 'completed': | |
return <CheckCircleIcon className="h-5 w-5 text-green-500" /> | |
case 'failed': | |
return <XCircleIcon className="h-5 w-5 text-red-500" /> | |
case 'in-progress': | |
return <LoaderIcon className="h-5 w-5 text-blue-500 animate-spin" /> | |
default: | |
return name === "Send SMS Notification" ? | |
<MessageSquareIcon className="h-5 w-5 text-gray-400" /> : null | |
} | |
} | |
return ( | |
<div className="container mx-auto p-4"> | |
<h1 className="text-2xl font-bold mb-4">Content Publishing Automation Workflow</h1> | |
<div className="mb-4"> | |
<Input | |
type="tel" | |
placeholder="Enter phone number for SMS" | |
value={phoneNumber} | |
onChange={(e) => setPhoneNumber(e.target.value)} | |
className="mb-2" | |
/> | |
<Button onClick={runWorkflow} disabled={isRunning || !phoneNumber}> | |
{isRunning ? 'Workflow Running...' : 'Start Workflow'} | |
</Button> | |
</div> | |
<div className="space-y-4"> | |
{workflow.map((step) => ( | |
<Card key={step.id} className={`${step.status === 'failed' ? 'border-red-500' : ''}`}> | |
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> | |
<CardTitle className="text-sm font-medium"> | |
Step {step.id}: {step.name} | |
</CardTitle> | |
{getStatusIcon(step.status, step.name)} | |
</CardHeader> | |
<CardContent> | |
<div className="text-xs text-muted-foreground"> | |
Status: {step.status.charAt(0).toUpperCase() + step.status.slice(1)} | |
</div> | |
{step.name === "Send SMS Notification" && step.status === 'completed' && ( | |
<div className="text-xs text-green-600 mt-1"> | |
SMS sent successfully! | |
</div> | |
)} | |
</CardContent> | |
</Card> | |
))} | |
</div> | |
</div> | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment