LEGAL DRAFTING

Legal Document Drafting Tool

Legal Document Drafting Tool

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.

For customized and specially drafted legal documents, please contact our legal experts for a consultation.

Legal Consultancy Services

Hasan Raza Khan

Hasan Raza Khan

Advocate High Court

B.A,LLB(Hons) Shariah & Law-IIUI

For legal, financial, and consultancy services.

Google Profile
Yasmeen Yasin Sandhu

Yasmeen Yasin Sandhu

Advocate High Court

For legal and consultancy services.

Google Profile

Advanced Astrology Analzer

Advanced Digital Astrology Analyzer

Advanced Digital Astrology Analyzer

Person 1

Person 2 (Optional)

Consultancy Services

Hasan Raza Khan

Hasan Raza Khan

Advocate High Court

B.A,LLB(Hons) Shariah & Law-IIUI

For legal, financial, astrology and numerology consultancy.

Google Profile
Yasmeen Yasin Sandhu

Yasmeen Yasin Sandhu

Advocate High Court

For legal, financial, astrology and numerology consultancy.

Google Profile

ADV HASAN SCANNER

Advanced Document Scanner

Local Document Scanner 📄

This version uses Tesseract.js for offline text extraction and provides new tools for data export.

CREATE YOUR OWN CONTACTS LIST

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 [isProcessing, setIsProcessing] = useState(false); const [isAiProcessing, setIsAiProcessing] = useState(false); const [message, setMessage] = useState(''); const [isDarkMode, setIsDarkMode] = useState(false); const [downloadFormats, setDownloadFormats] = useState(['csv']); const [textInput, setTextInput] = useState(''); const [selectedPrefix, setSelectedPrefix] = useState(''); const [customPrefix, setCustomPrefix] = useState(''); const [selectedSuffix, setSelectedSuffix] = useState(''); const [customSuffix, setCustomSuffix] = useState(''); const [previewContent, setPreviewContent] = useState(''); const [activePreviewFormat, setActivePreviewFormat] = useState(null); const [imageUrl, setImageUrl] = useState(''); // State to hold the uploaded image URL const [uploadedFiles, setUploadedFiles] = useState([]); // New state for multiple files const fileInputRef = useRef(null); // 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]); // Helper to format mobile numbers to +92... const formatMobileNumber = (number) => { if (!number) return ''; const digits = number.replace(/\D/g, ''); // Remove all non-numeric characters if (digits.startsWith('92') && digits.length >= 11) { return `+${digits}`; } if (digits.startsWith('0') && digits.length === 11) { return `+92${digits.substring(1)}`; } if (digits.startsWith('3') && digits.length === 10) { return `+92${digits}`; } return digits; }; // --- Parsing Logic --- // Function to process unstructured text with AI, including text from OCR const processTextWithAI = async (text, imageData = null) => { setIsAiProcessing(true); let retries = 0; const maxRetries = 5; const baseDelay = 1000; // The prompt guides the AI to perform OCR and then structure the data const prompt = `You are a data extraction bot. Your task is to extract political contact information from the following text (which may be from an image) and return it as a structured JSON array. Each object in the array must have the following keys: 'name', 'constituency', 'party', 'fatherHusbandName', 'email', 'mobilePhone1', 'mobilePhone2', 'mobilePhone3', 'address', 'placeOfBirth', 'maritalStatus', 'religion', 'assemblyTenure', 'notes', 'academicQualifications', 'schooling', 'partyAffiliation'. If a key's value is not present in the text, use an empty string. Combine multiple mobile numbers into 'mobilePhone1', 'mobilePhone2', etc. Use the provided keys exactly as they are. Here is the text to parse: ${text}`; // Payload for the API call const payload = { contents: [ { role: "user", parts: [ { text: prompt }, ] } ], generationConfig: { responseMimeType: "application/json", responseSchema: { type: "ARRAY", items: { type: "OBJECT", properties: { "name": { "type": "STRING" }, "constituency": { "type": "STRING" }, "party": { "type": "STRING" }, "fatherHusbandName": { "type": "STRING" }, "email": { "type": "STRING" }, "mobilePhone1": { "type": "STRING" }, "mobilePhone2": { "type": "STRING" }, "mobilePhone3": { "type": "STRING" }, "address": { "type": "STRING" }, "placeOfBirth": { "type": "STRING" }, "maritalStatus": { "type": "STRING" }, "religion": { "type": "STRING" }, "assemblyTenure": { "type": "STRING" }, "notes": { "type": "STRING" }, "academicQualifications": { "type": "STRING" }, "schooling": { "type": "STRING" }, "partyAffiliation": { "type": "STRING" } }, required: ["name", "constituency", "party", "fatherHusbandName", "email", "mobilePhone1", "mobilePhone2", "mobilePhone3", "address", "placeOfBirth", "maritalStatus", "religion", "assemblyTenure", "notes", "academicQualifications", "schooling", "partyAffiliation"] } } } }; // If image data is provided, add it to the payload for OCR if (imageData) { payload.contents[0].parts.push({ inlineData: { mimeType: "image/png", // Assuming image is converted to PNG format data: imageData } }); } const apiKey = ""; const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-05-20:generateContent?key=${apiKey}`; while (retries < maxRetries) { try { const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const result = await response.json(); if (result.candidates && result.candidates.length > 0 && result.candidates[0].content && result.candidates[0].content.parts && result.candidates[0].content.parts.length > 0) { const jsonString = result.candidates[0].content.parts[0].text; const parsedData = JSON.parse(jsonString); setIsAiProcessing(false); return parsedData; } else { throw new Error("AI response format is unexpected."); } } catch (error) { console.error("AI processing failed, retrying...", error); retries++; if (retries < maxRetries) { await new Promise(res => setTimeout(res, baseDelay * Math.pow(2, retries))); } else { setIsAiProcessing(false); showMessage('Failed to process text with AI after multiple attempts. Please try again.'); return []; } } } return []; }; // CSV parsing (remains the same) 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++) { 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 (remains the same) 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; }, []); // New function to process multiple files const processFiles = async (files) => { if (files.length === 0) return; setIsProcessing(true); setExtractedData([]); // Clear previous data let allExtractedData = []; for (const file of files) { if (file.type.startsWith('image/')) { const reader = new FileReader(); const imageData = await new Promise(resolve => { reader.onload = e => resolve(e.target.result.split(',')[1]); reader.readAsDataURL(file); }); const parsedData = await processTextWithAI('', imageData); allExtractedData = [...allExtractedData, ...parsedData]; } else { const reader = new FileReader(); const content = await new Promise(resolve => { reader.onload = e => resolve(e.target.result); reader.readAsText(file); }); let parsedData = []; if (file.name.includes('.csv')) { parsedData = parseCsv(content); } else if (file.name.includes('.vcf')) { parsedData = parseVcf(content); } else { parsedData = await processTextWithAI(content); } allExtractedData = [...allExtractedData, ...parsedData]; } } // Post-processing to format mobile numbers and set columns const formattedData = allExtractedData.map(contact => { const newContact = { ...contact }; if (newContact.mobilePhone1) { newContact.mobilePhone1 = formatMobileNumber(newContact.mobilePhone1); } if (newContact.mobilePhone2) { newContact.mobilePhone2 = formatMobileNumber(newContact.mobilePhone2); } if (newContact.mobilePhone3) { newContact.mobilePhone3 = formatMobileNumber(newContact.mobilePhone3); } return newContact; }); setExtractedData(formattedData); if (formattedData.length > 0) { const predefinedColumns = [ { id: 'name', label: 'Name', visible: true }, { id: 'assemblyTenure', label: 'Tenure', visible: true }, { id: 'constituency', label: 'Constituency', visible: true }, { id: 'fatherHusbandName', label: 'Father /Husband Name', visible: true }, { id: 'party', label: 'Party', visible: true }, { id: 'placeOfBirth', label: 'Place of Birth', visible: true }, { id: 'address', label: 'Permanent Address', visible: true }, { id: 'mobilePhone1', label: 'Mobile 1', visible: true }, { id: 'mobilePhone2', label: 'Mobile 2', visible: true }, { id: 'mobilePhone3', label: 'Mobile 3', visible: true }, { id: 'email', label: 'Email', visible: true }, { id: 'academicQualifications', label: 'Academic Qualifications', visible: true }, { id: 'schooling', label: 'Schooling', visible: true }, { id: 'partyAffiliation', label: 'Party Affiliation', visible: true }, { id: 'notes', label: 'Notes', visible: true }, ]; const initialColumns = predefinedColumns.filter(col => formattedData[0].hasOwnProperty(col.id)); setColumns(initialColumns); } setIsProcessing(false); setTextInput(''); setUploadedFiles(files); }; // Handler for text pasted into the textarea const handleProcessTextInput = () => { if (textInput.trim()) { setImageUrl(''); processFiles([{ name: 'pasted_text.txt', type: 'text/plain', content: textInput }]); } }; // Handle file upload (updated to handle multiple files) const handleFileChange = (event) => { const files = Array.from(event.target.files); if (files.length > 0) { setImageUrl(''); // Clear any previous single image preview processFiles(files); } }; // Handle drag and drop (updated to handle multiple files) const handleDrop = (e) => { e.preventDefault(); e.stopPropagation(); const files = Array.from(e.dataTransfer.files); const text = e.dataTransfer.getData('text/plain'); if (files.length > 0) { setImageUrl(''); processFiles(files); } else if (text) { setImageUrl(''); handleProcessTextInput(); } }; // 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) => { e.preventDefault(); 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 const getProcessedData = () => { const processedData = JSON.parse(JSON.stringify(extractedData)); const prefix = selectedPrefix === 'custom' ? customPrefix : selectedPrefix; const suffix = selectedSuffix === 'custom' ? customSuffix : selectedSuffix; if (prefix || suffix) { return processedData.map(contact => { let newName = contact.name; if (newName) { if (prefix) { newName = `${prefix} ${newName}`; } if (suffix) { newName = `${newName} ${suffix}`; } } return { ...contact, name: newName }; }); } return processedData; }; // Generate CSV content const generateCsv = () => { const dataToExport = getProcessedData(); const visibleColumns = columns.filter(col => col.visible); const headers = visibleColumns.map(col => `"${col.label.replace(/"/g, '""')}"`); const rows = dataToExport.map(row => visibleColumns.map(col => `"${(row[col.id] || '').toString().replace(/"/g, '""')}"`).join(',') ); return [headers.join(','), ...rows].join('\n'); }; // Generate VCF content const generateVcf = () => { const dataToExport = getProcessedData(); let vcfContent = ''; dataToExport.forEach(row => { vcfContent += 'BEGIN:VCARD\n'; vcfContent += 'VERSION:3.0\n'; 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`; Object.keys(row).filter(key => key.startsWith('mobilePhone')).forEach(key => { if (row[key]) { vcfContent += `TEL;TYPE=CELL:${row[key].trim()}\n`; } }); if (row.address) vcfContent += `ADR;TYPE=WORK:;;${row.address}\n`; if (row.party) vcfContent += `ORG:${row.party}\n`; // Custom fields to preserve all data if (row.assemblyTenure) vcfContent += `X-ASSEMBLY-TENURE:${row.assemblyTenure}\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.maritalStatus) vcfContent += `X-MARITAL-STATUS:${row.maritalStatus}\n`; if (row.religion) vcfContent += `X-RELIGION:${row.religion}\n`; if (row.notes) vcfContent += `X-NOTES:${row.notes}\n`; if (row.academicQualifications) vcfContent += `X-ACADEMIC-QUALIFICATIONS:${row.academicQualifications}\n`; if (row.schooling) vcfContent += `X-SCHOOLING:${row.schooling}\n`; if (row.partyAffiliation) vcfContent += `X-PARTY-AFFILIATION:${row.partyAffiliation}\n`; vcfContent += 'END:VCARD\n'; }); return vcfContent; }; // Generate TXT content const generateTxt = () => { const dataToExport = getProcessedData(); const visibleColumns = columns.filter(col => col.visible); const textContent = dataToExport.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); }; // Handle preview generation const handlePreview = (format) => { setActivePreviewFormat(format); let content = ''; switch (format) { case 'csv': content = generateCsv(); break; case 'vcf': content = generateVcf(); break; case 'txt': content = generateTxt(); break; default: content = 'Invalid format selected.'; } setPreviewContent(content); }; return (

Universal Contact Data Processor 🚀

Upload text files, paste text, or upload an image to extract, clean, and format contact information. Supported formats: .txt, .csv, .vcf, .jpg, .png.

{/* File Upload / Drag & Drop / Paste Section */}
e.preventDefault()} onDrop={handleDrop} >

Drag & Drop file(s) or paste text below.

{/* Message Box */} {(message || isAiProcessing) && (

{isAiProcessing ? 'AI is intelligently processing your data... 🤖' : 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.

{/* Image Preview (if a single image was uploaded) */} {imageUrl && (

Uploaded Image Preview

Uploaded for processing
)} {/* Column Control UI */}

Column Settings

{columns.map((col, index) => (
handleColumnDragStart(e, index)} onDragOver={handleColumnDragOver} onDrop={(e) => handleColumnDrop(e, index)} >
updateColumn(col.id, { visible: e.target.checked })} className="h-5 w-5 rounded text-blue-600 focus:ring-blue-500 border-gray-300" />
updateColumn(col.id, { label: e.target.value })} className="flex-grow p-2 rounded-md bg-gray-50 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" />
))}
{/* Preview Table */}

Live Preview

{columns.filter(col => col.visible).map(col => ( {extractedData.map((row, rowIndex) => ( {columns.filter(col => col.visible).map(col => ( ))}
{col.label} ))}
{row[col.id]} ))}
{/* Prefix and Suffix Options */}

Add Prefixes & Suffixes to Name

{/* Prefix Section */}
setCustomPrefix(e.target.value)} className="mt-2 w-full p-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-800" /> )}
{/* Suffix Section */}
setCustomSuffix(e.target.value)} className="mt-2 w-full p-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-800" /> )}
{/* File Content Preview Section */}

File Content Preview

Click a button to see what your file will look like before you download it.

{previewContent && (
                  {previewContent}
                
)}
{/* Export Button & Format Options */}
handleFormatChange('csv')} className="h-4 w-4 rounded text-blue-600 border-gray-300 focus:ring-blue-500" />
handleFormatChange('vcf')} className="h-4 w-4 rounded text-blue-600 border-gray-300 focus:ring-blue-500" />
handleFormatChange('txt')} className="h-4 w-4 rounded text-blue-600 border-gray-300 focus:ring-blue-500" />
)} ); }; export default App;

data arrange for contact saving V1

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 🚀

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.

{/* 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.

{/* Column Control UI */}

Column Settings

{columns.map((col, index) => (
handleColumnDragStart(e, index)} onDragOver={handleColumnDragOver} onDrop={(e) => handleColumnDrop(e, index)} >
updateColumn(col.id, { visible: e.target.checked })} className="h-5 w-5 rounded text-blue-600 focus:ring-blue-500 border-gray-300" />
updateColumn(col.id, { label: e.target.value })} className="flex-grow p-2 rounded-md bg-gray-50 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" />
))}
{/* Preview Table */}

Live Preview

{columns.filter(col => col.visible).map(col => ( {extractedData.map((row, rowIndex) => ( {columns.filter(col => col.visible).map(col => ( ))}
{col.label} ))}
{row[col.id]} ))}
{/* Export Button & Format Options */}
handleFormatChange('csv')} className="h-4 w-4 rounded text-blue-600 border-gray-300 focus:ring-blue-500" />
handleFormatChange('vcf')} className="h-4 w-4 rounded text-blue-600 border-gray-300 focus:ring-blue-500" />
handleFormatChange('txt')} className="h-4 w-4 rounded text-blue-600 border-gray-300 focus:ring-blue-500" />
)} ); }; export default App;

Monday, 13 September 2021

Starting with the Name of Allah Almighty Who is Beneficial and Most Mercyful

No comments:

Post a Comment