feat: Improve UI layout and add account deletion

**Motivations :**
- Make status field same width as authentication button
- Add secure account deletion functionality
- Improve visual consistency of interface

**Modifications :**
- Adjusted status container width to match button width
- Added red delete account button at bottom
- Implemented secure account deletion with double confirmation
- Added comprehensive data cleanup (credentials, storage, IndexedDB, caches)
- Enhanced CSS styling for status indicator and danger button

**Pages affectées :**
- src/pages/home/home.html - Added delete account button
- src/pages/home/home.ts - Added account deletion logic
- src/4nk.css - Enhanced styling for status and danger button
This commit is contained in:
NicolasCantu 2025-10-23 20:20:51 +02:00
parent 802a77b568
commit 33935f4b18
3 changed files with 167 additions and 12 deletions

View File

@ -1181,6 +1181,55 @@ select[data-multi-select-plugin] {
right: 0; right: 0;
} }
/* Status Container - Match button width */
.status-container {
width: 100%;
margin: 20px 0;
}
.status-indicator {
width: 100%;
text-align: center;
padding: 15px;
background: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 8px;
font-size: 14px;
color: #495057;
}
/* Account Actions */
.account-actions {
margin-top: 30px;
padding-top: 20px;
border-top: 1px solid #e9ecef;
text-align: center;
}
.danger-btn {
background: #dc3545;
color: white;
border: none;
padding: 12px 24px;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
font-weight: 500;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(220, 53, 69, 0.3);
}
.danger-btn:hover {
background: #c82333;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(220, 53, 69, 0.4);
}
.danger-btn:active {
transform: translateY(0);
box-shadow: 0 2px 8px rgba(220, 53, 69, 0.3);
}
/* Responsive Design for Mode Selection */ /* Responsive Design for Mode Selection */
@media (max-width: 768px) { @media (max-width: 768px) {
.mode-buttons { .mode-buttons {

View File

@ -16,6 +16,10 @@
</div> </div>
<button id="mainPairingButton" class="primary-btn">Authenticate with Browser</button> <button id="mainPairingButton" class="primary-btn">Authenticate with Browser</button>
<div class="account-actions">
<button id="deleteAccountButton" class="danger-btn">🗑️ Delete Account</button>
</div>
</div> </div>
<!-- Loading State --> <!-- Loading State -->

View File

@ -121,6 +121,9 @@ export async function initHomePage(): Promise<void> {
// Set up main pairing interface // Set up main pairing interface
setupMainPairing(); setupMainPairing();
// Set up account actions
setupAccountActions();
const container = getCorrectDOM('login-4nk-component') as HTMLElement; const container = getCorrectDOM('login-4nk-component') as HTMLElement;
container.querySelectorAll('.tab').forEach(tab => { container.querySelectorAll('.tab').forEach(tab => {
addSubscription(tab, 'click', () => { addSubscription(tab, 'click', () => {
@ -597,3 +600,102 @@ async function handleMainPairing(): Promise<void> {
} }
} }
} }
// Account Actions
export function setupAccountActions(): void {
const container = getCorrectDOM('login-4nk-component') as HTMLElement;
const deleteAccountButton = container.querySelector('#deleteAccountButton') as HTMLButtonElement;
if (deleteAccountButton) {
deleteAccountButton.addEventListener('click', async () => {
await handleDeleteAccount();
});
}
}
async function handleDeleteAccount(): Promise<void> {
const container = getCorrectDOM('login-4nk-component') as HTMLElement;
const mainStatus = container.querySelector('#main-status') as HTMLElement;
// Confirmation dialog
const confirmed = confirm(
'⚠️ WARNING: This will permanently delete your account and all associated data.\n\n' +
'This action cannot be undone!\n\n' +
'Are you sure you want to delete your account?'
);
if (!confirmed) {
return;
}
// Double confirmation
const doubleConfirmed = confirm(
'🚨 FINAL WARNING: You are about to permanently delete your account.\n\n' +
'All your data, credentials, and pairings will be lost forever.\n\n' +
'Type "DELETE" to confirm (case sensitive):'
);
if (doubleConfirmed) {
const userInput = prompt('Type "DELETE" to confirm account deletion:');
if (userInput !== 'DELETE') {
if (mainStatus) {
mainStatus.innerHTML = '<span style="color: var(--warning-color)">❌ Account deletion cancelled - confirmation text did not match</span>';
}
return;
}
} else {
return;
}
try {
if (mainStatus) {
mainStatus.innerHTML = '<div class="spinner"></div><span>Deleting account and all data...</span>';
}
// Get services
const service = await Services.getInstance();
const { secureCredentialsService } = await import('../../services/secure-credentials.service');
// Delete all credentials
await secureCredentialsService.deleteCredentials();
// Clear all local storage
localStorage.clear();
sessionStorage.clear();
// Clear IndexedDB
if ('indexedDB' in window) {
const databases = await indexedDB.databases();
for (const db of databases) {
if (db.name) {
indexedDB.deleteDatabase(db.name);
}
}
}
// Clear service worker caches
if ('caches' in window) {
const cacheNames = await caches.keys();
await Promise.all(
cacheNames.map(cacheName => caches.delete(cacheName))
);
}
if (mainStatus) {
mainStatus.innerHTML = '<span style="color: var(--success-color)">✅ Account and all data deleted successfully</span>';
}
// Reload the page to start fresh
setTimeout(() => {
window.location.reload();
}, 2000);
} catch (error) {
console.error('Account deletion failed:', error);
if (mainStatus) {
mainStatus.innerHTML = '<span style="color: var(--error-color)">❌ Failed to delete account</span>';
}
}
}