'use client'; import { useState, useEffect } from 'react'; import { Globe, Plus, Edit, Trash2, RefreshCw, Check, X, Search, Filter } from 'lucide-react'; const DNSManager = () => { const [domains, setDomains] = useState([]); const [selectedDomain, setSelectedDomain] = useState(''); const [records, setRecords] = useState([]); const [filteredRecords, setFilteredRecords] = useState([]); const [loading, setLoading] = useState(false); const [showAddRecord, setShowAddRecord] = useState(false); const [editingRecord, setEditingRecord] = useState(null); const [selectedRecords, setSelectedRecords] = useState(new Set()); const [searchTerm, setSearchTerm] = useState(''); const [filterType, setFilterType] = useState('all'); const [newRecord, setNewRecord] = useState({ fieldType: 'A', subDomain: '', target: '', ttl: 3600 }); const [bulkUpdate, setBulkUpdate] = useState({ show: false, target: '', type: 'A' }); const fetchDomains = async () => { try { const response = await fetch('/api/domains'); const data = await response.json(); if (data.success && data.domains) { const domainList = data.domains.map(d => typeof d === 'string' ? d : d.domain); setDomains(domainList); if (domainList.length > 0 && !selectedDomain) { setSelectedDomain(domainList[0]); } } } catch (error) { console.error('Error fetching domains:', error); } }; const fetchRecords = async () => { if (!selectedDomain) return; setLoading(true); try { const response = await fetch(`/api/domains/${selectedDomain}/records`); const data = await response.json(); if (data.success) { setRecords(data.records || []); } } catch (error) { console.error('Error fetching records:', error); } setLoading(false); setSelectedRecords(new Set()); }; useEffect(() => { fetchDomains(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { if (selectedDomain) { fetchRecords(); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedDomain]); useEffect(() => { let filtered = records; if (filterType !== 'all') { filtered = filtered.filter(r => r.fieldType === filterType); } if (searchTerm) { filtered = filtered.filter(r => r.subDomain?.toLowerCase().includes(searchTerm.toLowerCase()) || r.target?.toLowerCase().includes(searchTerm.toLowerCase()) ); } setFilteredRecords(filtered); }, [records, searchTerm, filterType]); const handleAddRecord = async () => { try { const response = await fetch(`/api/domains/${selectedDomain}/records`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newRecord) }); if (response.ok) { setShowAddRecord(false); setNewRecord({ fieldType: 'A', subDomain: '', target: '', ttl: 3600 }); fetchRecords(); } } catch (error) { console.error('Error adding record:', error); } }; const handleUpdateRecord = async () => { try { const response = await fetch(`/api/domains/${selectedDomain}/records`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(editingRecord) }); if (response.ok) { setEditingRecord(null); fetchRecords(); } } catch (error) { console.error('Error updating record:', error); } }; const handleDeleteRecord = async (recordId) => { if (!confirm('Are you sure you want to delete this record?')) return; try { const response = await fetch(`/api/domains/${selectedDomain}/records?recordId=${recordId}`, { method: 'DELETE' }); if (response.ok) { fetchRecords(); } } catch (error) { console.error('Error deleting record:', error); } }; const handleBulkUpdate = async () => { if (selectedRecords.size === 0) return; try { const response = await fetch(`/api/domains/${selectedDomain}/bulk-update`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ domain: selectedDomain, recordIds: Array.from(selectedRecords), target: bulkUpdate.target, fieldType: bulkUpdate.type }) }); const data = await response.json(); if (data.success) { setBulkUpdate({ show: false, target: '', type: 'A' }); setSelectedRecords(new Set()); fetchRecords(); } } catch (error) { console.error('Error bulk updating records:', error); } }; const toggleRecordSelection = (recordId) => { const newSelection = new Set(selectedRecords); if (newSelection.has(recordId)) { newSelection.delete(recordId); } else { newSelection.add(recordId); } setSelectedRecords(newSelection); }; const selectAllFiltered = () => { if (selectedRecords.size === filteredRecords.length) { setSelectedRecords(new Set()); } else { setSelectedRecords(new Set(filteredRecords.map(r => r.id))); } }; const refreshDNSZone = async () => { if (!selectedDomain) return; setLoading(true); try { const response = await fetch('/api/dns/refresh', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ domain: selectedDomain }) }); const data = await response.json(); if (data.success) { await fetchRecords(); } } catch (error) { console.error('Error refreshing DNS zone:', error); } setLoading(false); }; const getRecordTypeColor = (type) => { const colors = { 'A': 'bg-blue-500 text-white', 'AAAA': 'bg-purple-500 text-white', 'CNAME': 'bg-green-500 text-white', 'MX': 'bg-orange-500 text-white', 'TXT': 'bg-gray-500 text-white', 'SRV': 'bg-pink-500 text-white', 'NS': 'bg-yellow-500 text-white' }; return colors[type] || 'bg-gray-500 text-white'; }; return (
Manage your domain DNS records
Loading records...
| 0} onChange={selectAllFiltered} className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" /> | Tipo | Nombre | Valor | TTL | Acciones |
|---|---|---|---|---|---|
| toggleRecordSelection(record.id)} className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" /> | {record.fieldType} | {record.subDomain || '@'} | {record.target} | {record.ttl} |
No se encontraron registros DNS
Update {selectedRecords.size} selected record(s)