Add Google Calendar integration via Supabase Edge Functions

- Create new create-google-meet-event edge function
- Use service account authentication (no OAuth needed)
- Add google_service_account_json field to platform_settings
- Add admin UI for service account JSON configuration
- Include test connection button in Integrasi tab
- Add comprehensive setup documentation
- Keep n8n workflows as alternative option

Features:
- Direct Google Calendar API integration
- JWT authentication with service account
- Auto-create Google Meet links
- No external dependencies needed
- Simple configuration via admin panel

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
dwindown
2025-12-23 01:32:23 +07:00
parent dfda71053c
commit 631dc9a083
12 changed files with 1258 additions and 2 deletions

View File

@@ -3,6 +3,7 @@ import { supabase } from '@/integrations/supabase/client';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { Label } from '@/components/ui/label';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Alert, AlertDescription } from '@/components/ui/alert';
@@ -16,6 +17,7 @@ interface IntegrationSettings {
integration_whatsapp_number: string;
integration_whatsapp_url: string;
integration_google_calendar_id: string;
integration_google_service_account_json?: string;
integration_email_provider: string;
integration_email_api_base_url: string;
integration_privacy_url: string;
@@ -74,6 +76,7 @@ export function IntegrasiTab() {
integration_whatsapp_number: platformData.integration_whatsapp_number || '',
integration_whatsapp_url: platformData.integration_whatsapp_url || '',
integration_google_calendar_id: platformData.integration_google_calendar_id || '',
integration_google_service_account_json: platformData.integration_google_service_account_json || '',
integration_email_provider: platformData.integration_email_provider || 'mailketing',
integration_email_api_base_url: platformData.integration_email_api_base_url || '',
integration_privacy_url: platformData.integration_privacy_url || '/privacy',
@@ -99,6 +102,7 @@ export function IntegrasiTab() {
integration_whatsapp_number: settings.integration_whatsapp_number,
integration_whatsapp_url: settings.integration_whatsapp_url,
integration_google_calendar_id: settings.integration_google_calendar_id,
integration_google_service_account_json: settings.integration_google_service_account_json,
integration_email_provider: settings.integration_email_provider,
integration_email_api_base_url: settings.integration_email_api_base_url,
integration_privacy_url: settings.integration_privacy_url,
@@ -305,9 +309,69 @@ export function IntegrasiTab() {
className="border-2"
/>
<p className="text-sm text-muted-foreground">
Backend/n8n akan menggunakan ID ini untuk membuat event
Backend akan menggunakan ID ini untuk membuat event
</p>
</div>
<div className="space-y-2">
<Label className="flex items-center gap-2">
<Key className="w-4 h-4" />
Google Service Account JSON
</Label>
<Textarea
value={settings.integration_google_service_account_json || ''}
onChange={(e) => setSettings({ ...settings, integration_google_service_account_json: e.target.value })}
placeholder='{"type": "service_account", "project_id": "...", "private_key": "...", "client_email": "..."}'
className="min-h-[120px] font-mono text-sm border-2"
/>
<p className="text-sm text-muted-foreground">
Paste entire service account JSON from Google Cloud Console. Calendar must be shared with the service account email.
</p>
{settings.integration_google_service_account_json && (
<Alert>
<AlertTriangle className="w-4 h-4" />
<AlertDescription>
Service account configured. Calendar ID: {settings.integration_google_calendar_id || 'Not set'}
</AlertDescription>
</Alert>
)}
</div>
<Button
variant="outline"
onClick={async () => {
if (!settings.integration_google_calendar_id || !settings.integration_google_service_account_json) {
toast({ title: "Error", description: "Lengkapi Calendar ID dan Service Account JSON", variant: "destructive" });
return;
}
try {
const { data, error } = await supabase.functions.invoke('create-google-meet-event', {
body: {
slot_id: 'test-connection',
date: new Date().toISOString().split('T')[0],
start_time: '14:00:00',
end_time: '15:00:00',
client_name: 'Test Connection',
client_email: 'test@example.com',
topic: 'Connection Test',
},
});
if (error) throw error;
if (data?.success) {
toast({ title: "Berhasil", description: "Google Calendar API berfungsi! Event test dibuat." });
} else {
throw new Error(data?.message || 'Connection failed');
}
} catch (err: any) {
toast({ title: "Error", description: err.message, variant: "destructive" });
}
}}
className="w-full border-2"
>
Test Google Calendar Connection
</Button>
</CardContent>
</Card>