diff --git a/admin-spa/src/components/settings/GenericGatewayForm.tsx b/admin-spa/src/components/settings/GenericGatewayForm.tsx new file mode 100644 index 0000000..71915ce --- /dev/null +++ b/admin-spa/src/components/settings/GenericGatewayForm.tsx @@ -0,0 +1,330 @@ +import React, { useState } from 'react'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { Textarea } from '@/components/ui/textarea'; +import { Checkbox } from '@/components/ui/checkbox'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import { Alert, AlertDescription } from '@/components/ui/alert'; +import { ExternalLink, AlertTriangle } from 'lucide-react'; + +interface GatewayField { + id: string; + type: string; + title: string; + description: string; + default: string | boolean; + placeholder?: string; + required: boolean; + options?: Record; + custom_attributes?: Record; +} + +interface GatewaySettings { + basic: Record; + api: Record; + advanced: Record; +} + +interface GenericGatewayFormProps { + gateway: { + id: string; + title: string; + settings: GatewaySettings; + wc_settings_url: string; + }; + onSave: (settings: Record) => Promise; + onCancel: () => void; +} + +// Supported field types (outside component to avoid re-renders) +const SUPPORTED_FIELD_TYPES = ['text', 'password', 'checkbox', 'select', 'textarea', 'number', 'email', 'url']; + +export function GenericGatewayForm({ gateway, onSave, onCancel }: GenericGatewayFormProps) { + const [formData, setFormData] = useState>({}); + const [isSaving, setIsSaving] = useState(false); + const [unsupportedFields, setUnsupportedFields] = useState([]); + + // Check for unsupported fields + React.useEffect(() => { + const unsupported: string[] = []; + + const categories: Record[] = [ + gateway.settings.basic, + gateway.settings.api, + gateway.settings.advanced, + ]; + + categories.forEach((category) => { + Object.values(category).forEach((field) => { + if (!SUPPORTED_FIELD_TYPES.includes(field.type)) { + unsupported.push(field.title || field.id); + } + }); + }); + + setUnsupportedFields(unsupported); + }, [gateway]); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setIsSaving(true); + + try { + await onSave(formData); + } finally { + setIsSaving(false); + } + }; + + const handleFieldChange = (fieldId: string, value: unknown) => { + setFormData((prev) => ({ + ...prev, + [fieldId]: value, + })); + }; + + const renderField = (field: GatewayField) => { + const value = formData[field.id] ?? field.default; + + // Unsupported field type + if (!SUPPORTED_FIELD_TYPES.includes(field.type)) { + return null; + } + + switch (field.type) { + case 'checkbox': + return ( +
+ handleFieldChange(field.id, checked)} + /> +
+ + {field.description && ( +

{field.description}

+ )} +
+
+ ); + + case 'select': + return ( +
+ + {field.description && ( +

{field.description}

+ )} + +
+ ); + + case 'textarea': + return ( +
+ + {field.description && ( +

{field.description}

+ )} +