Quickly generate legal documents by filling out the details below. This tool is for informational purposes only and is not a substitute for professional legal advice.
Generated Document
For customized and specially drafted legal documents, please contact our legal experts for a consultation.
import React, { useState, useRef, useEffect, useCallback } from 'react';
// Main App Component
const App = () => {
const [fileContent, setFileContent] = useState('');
const [extractedData, setExtractedData] = useState([]);
const [columns, setColumns] = useState([]);
const [downloadLinks, setDownloadLinks] = useState({});
const [isProcessing, setIsProcessing] = useState(false);
const [message, setMessage] = useState('');
const [isDarkMode, setIsDarkMode] = useState(false);
const [downloadFormats, setDownloadFormats] = useState(['csv']); // New state for multiple download formats
const [textInput, setTextInput] = useState(''); // New state for text input
const fileInputRef = useRef(null);
const fileReader = new FileReader();
// Show a temporary message
const showMessage = (text, duration = 3000) => {
setMessage(text);
setTimeout(() => setMessage(''), duration);
};
// Toggle dark mode
const toggleDarkMode = () => {
setIsDarkMode(prevMode => !prevMode);
};
useEffect(() => {
if (isDarkMode) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
}, [isDarkMode]);
// --- Parsing Logic ---
// Regex-based parsing for raw unstructured text
const parseRawText = useCallback((text) => {
const data = [];
const entries = text.split(/(?=Assembly Tenure:)/).filter(Boolean);
entries.forEach(entry => {
const entryData = {};
// General-purpose regex for key-value pairs
const kvRegex = /(?:^|\n)([^:\n]+):\s*(.+)/g;
let match;
while ((match = kvRegex.exec(entry)) !== null) {
const key = match[1].trim();
const value = match[2].trim();
entryData[key] = value;
}
// Specific handling for permanent address, which can be multi-line
const permanentAddressMatch = entry.match(/Permanent (?:Contact|Address):(?:\s|\n)*([\s\S]*?)(?=\n(?:0|Email:|Academic Qualifications:))/i);
if (permanentAddressMatch && permanentAddressMatch[1]) {
entryData.permanentAddress = permanentAddressMatch[1].trim().replace(/\n/g, ' ').replace(/\s+/g, ' ');
}
// Extract all mobile numbers
const mobileRegex = /(\d{4}\s*\d{7}|\d{3}[-.\s]?\d{7})/g;
let mobileMatch;
let mobileNumbers = [];
while ((mobileMatch = mobileRegex.exec(entry)) !== null) {
mobileNumbers.push(mobileMatch[0].replace(/[-.\s]/g, ''));
}
mobileNumbers.forEach((num, index) => {
entryData[`mobile_${index + 1}`] = num;
});
// Map the keys from the raw data to the desired keys
const mappedData = {};
mappedData.name = entryData['Name'] || '';
mappedData.tenure = entryData['Assembly Tenure'] || '';
mappedData.fatherHusbandName = entryData['Father /Husband Name'] || '';
mappedData.constituency = entryData['Constituency'] || '';
mappedData.party = entryData['Party Affiliation ~'] || entryData['Party Affiliation'] || '';
mappedData.placeOfBirth = entryData['Place of Birth'] || '';
mappedData.email = entryData['Email'] || '';
mappedData.academicQualifications = entryData['Academic Qualifications'] || '';
mappedData.schooling = entryData['Schooling'] || '';
mappedData.permanentAddress = entryData.permanentAddress || '';
// Add mobile numbers
mobileNumbers.forEach((num, index) => {
mappedData[`mobile_${index + 1}`] = num;
});
data.push(mappedData);
});
return data;
}, []);
// CSV parsing
const parseCsv = useCallback((text) => {
const rows = text.split('\n').filter(row => row.trim() !== '');
if (rows.length === 0) return [];
const headers = rows[0].split(',').map(h => h.trim().replace(/^"|"$/g, ''));
const data = [];
for (let i = 1; i < rows.length; i++) {
// Split row by comma, respecting quotes
const values = rows[i].split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/).map(v => v.trim().replace(/^"|"$/g, ''));
if (values.length === headers.length) {
const rowObject = {};
headers.forEach((header, index) => {
rowObject[header] = values[index];
});
data.push(rowObject);
}
}
return data;
}, []);
// VCF parsing
const parseVcf = useCallback((text) => {
const data = [];
const vcards = text.split('BEGIN:VCARD').filter(v => v.trim() !== '');
vcards.forEach(vcard => {
const contact = {};
const lines = vcard.split('\n').filter(l => l.trim() !== '');
lines.forEach(line => {
const [key, ...valueParts] = line.split(':');
const value = valueParts.join(':').trim();
if (key && value) {
if (key.startsWith('FN')) contact.name = value;
if (key.startsWith('N')) {
const parts = value.split(';');
contact.name = parts[0];
}
if (key.startsWith('TEL')) {
if (!contact.mobile) contact.mobile = [];
contact.mobile.push(value);
}
if (key.startsWith('EMAIL')) contact.email = value;
if (key.startsWith('ADR')) contact.address = value.split(';').pop().trim();
if (key.startsWith('ORG')) contact.party = value;
}
});
data.push(contact);
});
return data;
}, []);
// Handler to process content from various sources (file, paste)
const handleContentProcessing = (content, filename = 'pasted_data.txt') => {
setIsProcessing(true);
setFileContent(content);
let parsedData = [];
if (filename.includes('.csv')) {
parsedData = parseCsv(content);
} else if (filename.includes('.vcf')) {
parsedData = parseVcf(content);
} else {
parsedData = parseRawText(content);
}
setExtractedData(parsedData);
if (parsedData.length > 0) {
const initialColumns = Object.keys(parsedData[0]).map(key => ({
id: key,
label: key.startsWith('mobile_') ? `Mobile ${key.split('_')[1]}` : (key.charAt(0).toUpperCase() + key.slice(1)),
visible: true,
}));
setColumns(initialColumns);
}
setIsProcessing(false);
setTextInput(''); // Clear the text input after processing
};
// Handle file upload
const handleFileChange = (event) => {
const file = event.target.files[0];
if (file) {
fileReader.onload = (e) => {
handleContentProcessing(e.target.result, file.name);
};
fileReader.readAsText(file);
}
};
// Handle drag and drop
const handleDrop = (e) => {
e.preventDefault();
e.stopPropagation();
const files = e.dataTransfer.files;
const text = e.dataTransfer.getData('text/plain');
if (files.length > 0) {
// Process file drop
const file = files[0];
fileReader.onload = (event) => {
handleContentProcessing(event.target.result, file.name);
};
fileReader.readAsText(file);
} else if (text) {
// Process text drop
handleContentProcessing(text);
}
};
// Update a column's label or visibility
const updateColumn = (id, newValues) => {
setColumns(prevColumns =>
prevColumns.map(col =>
col.id === id ? { ...col, ...newValues } : col
)
);
};
// Drag and drop functionality for columns
const handleColumnDragStart = (e, index) => {
e.dataTransfer.setData('colIndex', index);
};
const handleColumnDragOver = (e) => {
e.preventDefault();
};
const handleColumnDrop = (e, newIndex) => {
const oldIndex = e.dataTransfer.getData('colIndex');
const newColumns = [...columns];
const [movedColumn] = newColumns.splice(oldIndex, 1);
newColumns.splice(newIndex, 0, movedColumn);
setColumns(newColumns);
};
// --- Export Logic for different formats ---
// Generate CSV content
const generateCsv = () => {
const visibleColumns = columns.filter(col => col.visible);
const headers = visibleColumns.map(col => `"${col.label.replace(/"/g, '""')}"`);
const rows = extractedData.map(row =>
visibleColumns.map(col => `"${(row[col.id] || '').toString().replace(/"/g, '""')}"`).join(',')
);
return [headers.join(','), ...rows].join('\n');
};
// Generate VCF content
const generateVcf = () => {
let vcfContent = '';
extractedData.forEach(row => {
vcfContent += 'BEGIN:VCARD\n';
vcfContent += 'VERSION:3.0\n';
// Standard VCF fields
if (row.name) vcfContent += `FN:${row.name}\n`;
if (row.name) vcfContent += `N:${row.name};;;;\n`;
if (row.email) vcfContent += `EMAIL;TYPE=INTERNET:${row.email}\n`;
// Iterate through all mobile fields
Object.keys(row).filter(key => key.startsWith('mobile_')).forEach(key => {
vcfContent += `TEL;TYPE=CELL:${row[key].trim()}\n`;
});
if (row.permanentAddress) vcfContent += `ADR;TYPE=WORK:;;${row.permanentAddress}\n`;
if (row.party) vcfContent += `ORG:${row.party}\n`;
// Custom fields to preserve all data
if (row.tenure) vcfContent += `X-TENURE:${row.tenure}\n`;
if (row.fatherHusbandName) vcfContent += `X-FATHER-HUSBAND-NAME:${row.fatherHusbandName}\n`;
if (row.constituency) vcfContent += `X-CONSTITUENCY:${row.constituency}\n`;
if (row.placeOfBirth) vcfContent += `X-PLACE-OF-BIRTH:${row.placeOfBirth}\n`;
if (row.academicQualifications) vcfContent += `X-ACADEMIC-QUALIFICATIONS:${row.academicQualifications}\n`;
if (row.schooling) vcfContent += `X-SCHOOLING:${row.schooling}\n`;
vcfContent += 'END:VCARD\n';
});
return vcfContent;
};
// Generate TXT content
const generateTxt = () => {
const visibleColumns = columns.filter(col => col.visible);
const textContent = extractedData.map(row =>
visibleColumns.map(col => `${col.label}: ${row[col.id] || 'N/A'}`).join('\n')
).join('\n\n' + '='.repeat(40) + '\n\n');
return textContent;
};
// Handle the export based on selected format
const handleExport = () => {
const visibleColumns = columns.filter(col => col.visible);
if (visibleColumns.length === 0) {
showMessage('Please select at least one field to export.');
return;
}
if (downloadFormats.length === 0) {
showMessage('Please select at least one download format.');
return;
}
downloadFormats.forEach(format => {
let fileContent;
let fileName;
let mimeType;
switch (format) {
case 'csv':
fileContent = generateCsv();
fileName = 'formatted_contacts.csv';
mimeType = 'text/csv';
break;
case 'vcf':
fileContent = generateVcf();
fileName = 'formatted_contacts.vcf';
mimeType = 'text/vcard';
break;
case 'txt':
fileContent = generateTxt();
fileName = 'formatted_contacts.txt';
mimeType = 'text/plain';
break;
default:
showMessage(`Invalid download format: ${format}`);
return;
}
const blob = new Blob([fileContent], { type: `${mimeType};charset=utf-8;` });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.setAttribute('href', url);
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
});
showMessage(`Successfully downloaded as ${downloadFormats.join(', ').toUpperCase()} files!`);
};
// Handle checkbox change for formats
const handleFormatChange = (format) => {
setDownloadFormats(prevFormats =>
prevFormats.includes(format)
? prevFormats.filter(f => f !== format)
: [...prevFormats, format]
);
};
const handleTextInputChange = (e) => {
setTextInput(e.target.value);
};
const handleProcessTextInput = () => {
if (textInput.trim()) {
handleContentProcessing(textInput, 'pasted_text.txt');
}
};
return (
Intelligent Contact Data Processor 🚀
{isDarkMode ? '☀️' : '🌙'}
Upload text-based files to extract, clean, and format contact information.
Supported formats: .txt, .csv, .vcf.
Note: For `.docx` or `.xls` files, please convert them to a plain text format first.
{/* File Upload / Drag & Drop / Paste Section */}
e.preventDefault()}
onDrop={handleDrop}
>
Drag & Drop a file or paste text below.
Process Text
{/* Message Box */}
{message && (
{message}
)}
{/* Data Preview and Controls */}
{extractedData.length > 0 && (
Formatting & Arrangement
Use the controls below to customize your data. Drag and drop the labels to reorder columns.