<!DOCTYPE
html>
<html
lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0,
user-scalable=no">
<title>My Dispute
Manager</title>
<!-- Tailwind
CSS for styling (Mobile App Look) -->
<script src="https://cdn.tailwindcss.com"></script>
<style>
body { font-family:
-apple-system, BlinkMacSystemFont, "Segoe
UI", Roboto, Helvetica, Arial, sans-serif; background-color: #f3f4f6; -webkit-tap-highlight-color: transparent;
}
.tab-content {
display: none; padding-bottom: 80px; }
.tab-content.active { display:
block; }
.bottom-nav { padding-bottom: env(safe-area-inset-bottom); }
/* Print Styles for PDF Generation */
@media print {
body * {
visibility: hidden; }
#print-area, #print-area * { visibility: visible; }
#print-area {
position: absolute; left: 0; top: 0; width: 100%; padding: 20px;
font-size: 14px; background: white; }
.no-print {
display: none !important; }
}
</style>
</head>
<body
class="text-gray-800">
<!-- LOGIN
SCREEN -->
<div id="login-screen"
class="min-h-screen flex flex-col items-center justify-center p-6 bg-white">
<h1 class="text-3xl font-bold
text-blue-600 mb-2">🛡️ Dispute Manager</h1>
<p class="text-gray-500 mb-8
text-center" id="login-text">Create a 4-digit PIN to lock
your app.</p>
<input type="password"
id="pin-input" class="border-2 border-gray-300 text-center
text-3xl tracking-[0.5em] w-48 py-3 rounded-xl focus:border-blue-500
outline-none mb-6" maxlength="4"
pattern="\d*">
<button onclick="checkPin()"
class="bg-blue-600 text-white font-bold py-3 px-8 rounded-xl w-full
shadow-lg text-lg">Unlock / Set PIN</button>
</div>
<!-- MAIN APP
SCREEN -->
<div id="app-screen"
class="hidden min-h-screen relative">
<!-- Header
-->
<header class="bg-blue-600
text-white p-4 pt-10 text-center font-bold text-lg shadow-md sticky top-0 z-10">
My Dispute Manager
</header>
<!-- TAB 1:
Dashboard & Items -->
<main id="tab-disputes"
class="tab-content active p-4">
<button onclick="toggleModal('add-modal')" class="w-full
bg-blue-600 text-white font-bold py-3 rounded-xl mb-6 shadow-md">+ Add
Negative Item</button>
<h2 class="font-bold
text-gray-700 mb-3 text-lg">Your Disputes</h2>
<div id="items-list"
class="space-y-4"></div>
</main>
<!-- TAB 2:
Generate Letters -->
<main id="tab-letters"
class="tab-content p-4">
<h2 class="font-bold
text-xl mb-2">Generate Letters</h2>
<p class="text-sm text-gray-500 mb-6">Choose an action below to
generate a printable PDF or send a dispute via Gmail.</p>
<button onclick="generateLetter('Experian')" class="w-full
bg-blue-100 text-blue-800 border border-blue-300 font-bold py-4 rounded-xl mb-3
shadow-sm">Print Experian
Letter</button>
<button onclick="generateLetter('Equifax')" class="w-full
bg-orange-100 text-orange-800 border border-orange-300 font-bold py-4
rounded-xl mb-3 shadow-sm">Print Equifax
Letter</button>
<button onclick="generateLetter('TransUnion')" class="w-full
bg-teal-100 text-teal-800 border border-teal-300 font-bold py-4 rounded-xl mb-6
shadow-sm">Print TransUnion
Letter</button>
<h2 class="font-bold
text-xl mb-2">Email Integration</h2>
<button onclick="sendViaGmail()"
class="w-full bg-red-600 text-white font-bold py-4 rounded-xl mb-3
shadow-md">Compose via Gmail (CFPB Complaint)</button>
</main>
<!-- TAB 3:
CFPB Freeze List -->
<main id="tab-cfpb" class="tab-content p-4">
<h2 class="font-bold
text-xl mb-2">CFPB Freeze List</h2>
<p class="text-sm text-gray-600 mb-4">Official list of consumer
reporting companies from the Consumer Financial Protection Bureau (CFPB) that
you should request file disclosures from or place security freezes on.</p>
<div
class="space-y-4">
<div class="bg-white p-4 rounded-xl shadow-sm
border border-gray-200">
<h3
class="font-bold text-lg text-blue-700">Innovis</h3>
<p class="text-sm text-gray-500 mb-2">Credit reporting agency
often used alongside the big three.</p>
<a href="https://www.innovis.com"
target="_blank" class="text-blue-500 underline text-sm">innovis.com</a> |
<span>800-540-2505</span>
</div>
<div class="bg-white p-4 rounded-xl shadow-sm
border border-gray-200">
<h3
class="font-bold text-lg text-blue-700">LexisNexis</h3>
<p class="text-sm text-gray-500 mb-2">Collects public records,
bankruptcies, and judgements.</p>
<a href="https://consumer.risk.lexisnexis.com"
target="_blank" class="text-blue-500 underline text-sm">consumer.risk.lexisnexis.com</a> |
<span>800-456-6004</span>
</div>
<div class="bg-white p-4 rounded-xl shadow-sm
border border-gray-200">
<h3
class="font-bold text-lg text-blue-700">ChexSystems</h3>
<p class="text-sm text-gray-500 mb-2">Checking/banking account
screening agency.</p>
<a href="https://www.chexsystems.com"
target="_blank" class="text-blue-500 underline text-sm">chexsystems.com</a> |
<span>800-428-9623</span>
</div>
<div class="bg-white p-4 rounded-xl shadow-sm
border border-gray-200">
<h3
class="font-bold text-lg text-blue-700">CoreLogic</h3>
<p class="text-sm text-gray-500 mb-2">Property, tenant, and
eviction screening.</p>
<a href="https://credco.corelogic.com"
target="_blank" class="text-blue-500 underline text-sm">corelogic.com</a> |
<span>877-532-8778</span>
</div>
</div>
</main>
<!-- TAB 4:
Profile & Settings -->
<main id="tab-profile"
class="tab-content p-4">
<h2 class="font-bold
text-xl mb-4">Your Private Profile</h2>
<p class="text-sm text-red-500 mb-4 font-semibold">Saved locally
on this phone ONLY. Never sent to a server.</p>
<label class="block text-sm font-bold text-gray-700 mb-1">Full
Name</label>
<input type="text"
id="prof-name" class="w-full p-3 border rounded-xl mb-4 bg-white">
<label class="block text-sm font-bold text-gray-700 mb-1">Mailing
Address</label>
<input type="text"
id="prof-address" class="w-full p-3 border rounded-xl mb-4 bg-white" placeholder="123 Main St, City, ST
12345">
<label class="block text-sm font-bold text-gray-700 mb-1">Date of
Birth</label>
<input type="text"
id="prof-dob" class="w-full p-3 border rounded-xl mb-4 bg-white" placeholder="MM/DD/YYYY">
<label class="block text-sm font-bold text-gray-700 mb-1">SSN (Last 4 Only)</label>
<input type="text"
id="prof-ssn" class="w-full p-3 border
rounded-xl mb-6 bg-white" maxlength="4">
<button onclick="saveProfile()"
class="w-full bg-green-600 text-white font-bold py-3 rounded-xl
shadow-md">Save Profile</button>
</main>
<!-- BOTTOM
NAVIGATION -->
<nav class="bottom-nav fixed
bottom-0 w-full bg-white border-t border-gray-200
flex justify-around text-xs font-medium text-gray-500
pt-3 pb-2 z-20">
<button onclick="switchTab('disputes')" class="flex flex-col
items-center flex-1 text-blue-600" id="nav-disputes">
<span class="text-xl
mb-1">📝</span>
Disputes
</button>
<button onclick="switchTab('letters')" class="flex flex-col
items-center flex-1" id="nav-letters">
<span class="text-xl
mb-1">🖨️</span>
Letters
</button>
<button onclick="switchTab('cfpb')"
class="flex flex-col items-center flex-1" id="nav-cfpb">
<span class="text-xl
mb-1">🏛️</span> CFPB
List
</button>
<button onclick="switchTab('profile')" class="flex flex-col
items-center flex-1" id="nav-profile">
<span class="text-xl
mb-1">⚙️</span>
Profile
</button>
</nav>
<!-- ADD
ITEM MODAL -->
<div id="add-modal"
class="hidden fixed inset-0 bg-black
bg-opacity-50 z-30 flex justify-center items-end">
<div class="bg-white w-full rounded-t-3xl p-6 pb-12">
<h2 class="text-xl
font-bold mb-4">Add Negative Item</h2>
<input type="text"
id="item-creditor" placeholder="Creditor Name (e.g. Chase)"
class="w-full p-3 border rounded-xl mb-3">
<input type="text"
id="item-account" placeholder="Account # (Optional)"
class="w-full p-3 border rounded-xl mb-3">
<select
id="item-bureau" class="w-full p-3 border rounded-xl mb-3 bg-white">
<option
value="Experian">Experian</option>
<option
value="Equifax">Equifax</option>
<option
value="TransUnion">TransUnion</option>
</select>
<textarea
id="item-reason" placeholder="Reason (e.g. Not my account)"
class="w-full p-3 border rounded-xl mb-4 h-24"></textarea>
<button onclick="saveItem()"
class="w-full bg-blue-600 text-white font-bold py-3 rounded-xl
mb-2">Save Disputable Item</button>
<button onclick="toggleModal('add-modal')" class="w-full
bg-gray-200 text-gray-700 font-bold py-3
rounded-xl">Cancel</button>
</div>
</div>
</div>
<!-- PRINTABLE
AREA (Hidden until Generate Letter is clicked) -->
<div id="print-area"
class="hidden"></div>
<!-- JAVASCRIPT
LOGIC -->
<script>
let items = JSON.parse(localStorage.getItem('disputeItems'))
|| [];
// --- AUTHENTICATION ---
function checkPin() {
const input = document.getElementById('pin-input').value;
if(input.length !== 4) return alert('Enter
a 4-digit PIN');
const savedPin = localStorage.getItem('appPin');
if(!savedPin) {
localStorage.setItem('appPin', input);
startApp();
} else if (input === savedPin) {
startApp();
} else {
alert('Incorrect
PIN');
document.getElementById('pin-input').value = '';
}
}
window.onload
= function() {
if(localStorage.getItem('appPin')) {
document.getElementById('login-text').innerText = "Enter your
4-digit PIN to unlock.";
}
loadProfile();
}
function startApp() {
document.getElementById('login-screen').classList.add('hidden');
document.getElementById('app-screen').classList.remove('hidden');
renderItems();
}
// --- NAVIGATION ---
function switchTab(tabId) {
document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active'));
document.getElementById('tab-' + tabId).classList.add('active');
// Update bottom nav colors
const navs
= ['disputes', 'letters', 'cfpb', 'profile'];
navs.forEach(nav => {
document.getElementById('nav-' + nav).classList.remove('text-blue-600');
if(nav
=== tabId) document.getElementById('nav-'
+ nav).classList.add('text-blue-600');
});
}
function toggleModal(id)
{
const modal = document.getElementById(id);
modal.classList.toggle('hidden');
}
// --- DATA MANAGEMENT ---
function saveItem() {
const creditor = document.getElementById('item-creditor').value;
if(!creditor)
return alert('Creditor is required');
const newItem
= {
id: Date.now(),
creditor,
account: document.getElementById('item-account').value ||
'Unknown',
bureau: document.getElementById('item-bureau').value,
reason: document.getElementById('item-reason').value ||
'Inaccurate information'
};
items.push(newItem);
localStorage.setItem('disputeItems', JSON.stringify(items));
renderItems();
toggleModal('add-modal');
// Clear form
document.getElementById('item-creditor').value = '';
document.getElementById('item-account').value = '';
document.getElementById('item-reason').value = '';
}
function deleteItem(id)
{
if(confirm('Delete
this item permanently?')) {
items = items.filter(i => i.id !== id);
localStorage.setItem('disputeItems', JSON.stringify(items));
renderItems();
}
}
function renderItems() {
const list = document.getElementById('items-list');
list.innerHTML = '';
if(items.length === 0) {
list.innerHTML = '<p class="text-gray-500
text-center mt-6">No negative items added yet.</p>';
return;
}
items.forEach(item => {
list.innerHTML += `
<div class="bg-white p-4 rounded-xl shadow-sm
border border-gray-200">
<div
class="flex justify-between items-start mb-2">
<h3
class="font-bold text-lg">${item.creditor}</h3>
<button
onclick="deleteItem(${item.id})"
class="text-red-500 text-sm">Delete</button>
</div>
<p class="text-sm
text-gray-600"><strong>Bureau:</strong> ${item.bureau}</p>
<p class="text-sm text-gray-600"><strong>Account
#:</strong> ${item.account}</p>
<p class="text-sm text-gray-600 mt-1 bg-gray-50 p-2
rounded"><strong>Dispute:</strong> ${item.reason}</p>
</div>
`;
});
}
function saveProfile() {
const profile = {
name: document.getElementById('prof-name').value,
address: document.getElementById('prof-address').value,
dob: document.getElementById('prof-dob').value,
ssn: document.getElementById('prof-ssn').value,
};
localStorage.setItem('userProfile', JSON.stringify(profile));
alert('Profile
Saved Successfully!');
}
function loadProfile() {
const p = JSON.parse(localStorage.getItem('userProfile'));
if(p) {
document.getElementById('prof-name').value = p.name
|| '';
document.getElementById('prof-address').value = p.address || '';
document.getElementById('prof-dob').value = p.dob || '';
document.getElementById('prof-ssn').value = p.ssn || '';
}
}
// --- LETTER GENERATION & GMAIL
---
function generateLetter(bureau)
{
const p = JSON.parse(localStorage.getItem('userProfile'))
|| {};
const targetItems
= items.filter(i => i.bureau
=== bureau);
if(targetItems.length === 0) return alert('No
pending items for ' + bureau);
if(!p.name
|| !p.address)
return alert('Please fill out your Profile first!');
let accountsHTML
= targetItems.map(i => `
<div
style="margin-bottom:10px;">
<strong>Creditor:</strong> ${i.creditor}<br>
<strong>Account
Number:</strong> ${i.account}<br>
<strong>Reason for
Investigation:</strong> ${i.reason}
</div>
`).join('');
const date = new Date().toLocaleDateString();
const letterHTML
= `
<div style="max-width:
800px; margin: 0 auto; line-height: 1.6;">
<p>
${p.name}<br>
${p.address}<br>
SSN: XXX-XX-${p.ssn || 'XXXX'}<br>
DOB: ${p.dob || 'XX/XX/XXXX'}
</p>
<p>${date}</p>
<p><strong>To:
${bureau} Credit Bureau</strong></p>
<p><strong>Subject: Formal Notice of Dispute (FCRA § 611)</strong></p>
<p>Dear Dispute Department,</p>
<p>I am writing to
formally dispute the inaccurate information contained in my credit report.
Under the Fair Credit Reporting Act, Section 611 (15 U.S.C. § 1681i), you are
required to conduct a reasonable investigation and delete unverified items
within 30 days.</p>
<hr
style="margin:20px 0;">
${accountsHTML}
<hr
style="margin:20px 0;">
<p>Please
re-investigate these items with the furnishers. If they cannot provide strict,
verified documentation proving the accuracy of these accounts, please remove
them immediately and send me an updated copy of my credit report.</p>
<br><br>
<p>Sincerely,</p>
<p>___________________________<br>${p.name}</p>
</div>
`;
// Setup Print Area
const printArea
= document.getElementById('print-area');
printArea.innerHTML
= letterHTML;
printArea.classList.remove('hidden');
// Use Native iOS/Android Print
Dialog (Allows saving to PDF)
window.print();
// Hide after printing
setTimeout(() => { printArea.classList.add('hidden'); }, 1000);
}
function sendViaGmail() {
const p = JSON.parse(localStorage.getItem('userProfile'))
|| {};
const emailBody
= `
To Whom It May
Concern,
I am submitting a
formal dispute regarding inaccurate information on my credit profile. Under the
FCRA, I request an immediate investigation.
Name: ${p.name ||
'[Your Name]'}
Address: ${p.address || '[Your Address]'}
Please see the
attached/below details regarding my disputed accounts.
Thank you.
`;
const encodedBody
= encodeURIComponent(emailBody.trim());
const subject = encodeURIComponent("FCRA
Consumer Dispute Request");
// This opens the Gmail App
natively on an iPhone if installed, otherwise opens mailer
window.location.href = `mailto:?subject=${subject}&body=${encodedBody}`;
}
</script>
</body>
</html>