diff --git a/src/decs.d.ts b/src/decs.d.ts deleted file mode 100644 index d137c88..0000000 --- a/src/decs.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -declare class AccountComponent extends HTMLElement { - _callback: any; - constructor(); - connectedCallback(): void; - fetchData(): Promise; - set callback(fn: any); - get callback(): any; - render(): void; -} -export { AccountComponent }; diff --git a/src/main.ts b/src/main.ts index b0f47a4..3c59392 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,10 +2,7 @@ import { SignatureComponent } from './pages/signature/signature-component'; import { SignatureElement } from './pages/signature/signature'; /*import { ChatComponent } from './pages/chat/chat-component'; import { ChatElement } from './pages/chat/chat';*/ -import { AccountComponent } from './pages/account/account-component'; -import { AccountElement } from './pages/account/account'; - -export { SignatureComponent, SignatureElement, AccountComponent, AccountElement }; +export { SignatureComponent, SignatureElement }; declare global { interface HTMLElementTagNameMap { @@ -13,8 +10,6 @@ declare global { 'signature-element': SignatureElement; /*'chat-component': ChatComponent; 'chat-element': ChatElement;*/ - 'account-component': AccountComponent; - 'account-element': AccountElement; } } @@ -25,6 +20,4 @@ if ((import.meta as any).env.VITE_IS_INDEPENDANT_LIB) { customElements.define('signature-element', SignatureElement); /*customElements.define('chat-component', ChatComponent); customElements.define('chat-element', ChatElement);*/ - customElements.define('account-component', AccountComponent); - customElements.define('account-element', AccountElement); } diff --git a/src/mocks/mock-account/constAccountMock.ts b/src/mocks/mock-account/constAccountMock.ts deleted file mode 100644 index 34adaa4..0000000 --- a/src/mocks/mock-account/constAccountMock.ts +++ /dev/null @@ -1,272 +0,0 @@ -export const ALLOWED_ROLES = ['User', 'Member', 'Peer', 'Payment', 'Deposit', 'Artefact', 'Resolve', 'Backup']; - -export const STORAGE_KEYS = { - pairing: 'pairingRows', - wallet: 'walletRows', - process: 'processRows', - data: 'dataRows', -}; - -// Initialiser le stockage des lignes par défaut dans le localStorage -export const defaultRows = [ - { - column1: 'sprt1qqwtvg5q5vcz0reqvmld98u7va3av6gakwe9yxw9yhnpj5djcunn4squ68tuzn8dz78dg4adfv0dekx8hg9sy0t6s9k5em7rffgxmrsfpyy7gtyrz', - column2: '🎊😑🎄😩', - column3: 'Laptop', - }, - { - column1: 'sprt1qqwtvg5q5vcz0reqvmld98u7va3av6gakwe9yxw9yhnpj5djcunn4squ68tuzn8dz78dg4adfv0dekx8hg9sy0t6s9k5em7rffgxmrsfpyy7gtyrx', - column2: '🎏🎕😧🌥', - column3: 'Phone', - }, -]; - -export const mockNotifications: { [key: string]: Notification[] } = {}; - -export const notificationMessages = ['CPU usage high', 'Memory threshold reached', 'New update available', 'Backup completed', 'Security check required', 'Performance optimization needed', 'System alert', 'Network connectivity issue', 'Storage space low', 'Process checkpoint reached']; - -export const mockDataRows = [ - { - column1: 'User Project', - column2: 'private', - column3: 'User', - column4: '6 months', - column5: 'NDA signed', - column6: 'Contract #123', - processName: 'User Process', - zone: 'A', - }, - { - column1: 'Process Project', - column2: 'private', - column3: 'Process', - column4: '1 year', - column5: 'Terms accepted', - column6: 'Contract #456', - processName: 'Process Management', - zone: 'B', - }, - { - column1: 'Member Project', - column2: 'private', - column3: 'Member', - column4: '3 months', - column5: 'GDPR compliant', - column6: 'Contract #789', - processName: 'Member Process', - zone: 'C', - }, - { - column1: 'Peer Project', - column2: 'public', - column3: 'Peer', - column4: '2 years', - column5: 'IP rights', - column6: 'Contract #101', - processName: 'Peer Process', - zone: 'D', - }, - { - column1: 'Payment Project', - column2: 'confidential', - column3: 'Payment', - column4: '1 year', - column5: 'NDA signed', - column6: 'Contract #102', - processName: 'Payment Process', - zone: 'E', - }, - { - column1: 'Deposit Project', - column2: 'private', - column3: 'Deposit', - column4: '6 months', - column5: 'Terms accepted', - column6: 'Contract #103', - processName: 'Deposit Process', - zone: 'F', - }, - { - column1: 'Artefact Project', - column2: 'public', - column3: 'Artefact', - column4: '1 year', - column5: 'GDPR compliant', - column6: 'Contract #104', - processName: 'Artefact Process', - zone: 'G', - }, - { - column1: 'Resolve Project', - column2: 'private', - column3: 'Resolve', - column4: '2 years', - column5: 'IP rights', - column6: 'Contract #105', - processName: 'Resolve Process', - zone: 'H', - }, - { - column1: 'Backup Project', - column2: 'public', - column3: 'Backup', - column4: '1 year', - column5: 'NDA signed', - column6: 'Contract #106', - processName: 'Backup Process', - zone: 'I', - }, -]; - -export const mockProcessRows = [ - { - process: 'User Project', - role: 'User', - notification: { - messages: [ - { id: 1, read: false, date: '2024-03-10', message: 'New user joined the project' }, - { id: 2, read: false, date: '2024-03-09', message: 'Project milestone reached' }, - { id: 3, read: false, date: '2024-03-08', message: 'Security update required' }, - { id: 4, read: true, date: '2024-03-07', message: 'Weekly report available' }, - { id: 5, read: true, date: '2024-03-06', message: 'Team meeting scheduled' }, - ], - }, - }, - { - process: 'Member Project', - role: 'Member', - notification: { - messages: [ - { id: 6, read: true, date: '2024-03-10', message: 'Member access granted' }, - { id: 7, read: true, date: '2024-03-09', message: 'Documentation updated' }, - { id: 8, read: true, date: '2024-03-08', message: 'Project status: on track' }, - ], - }, - }, - { - process: 'Peer Project', - role: 'Peer', - notification: { - unread: 2, - total: 4, - messages: [ - { id: 9, read: false, date: '2024-03-10', message: 'New peer project added' }, - { id: 10, read: false, date: '2024-03-09', message: 'Project milestone reached' }, - { id: 11, read: false, date: '2024-03-08', message: 'Security update required' }, - { id: 12, read: true, date: '2024-03-07', message: 'Weekly report available' }, - { id: 13, read: true, date: '2024-03-06', message: 'Team meeting scheduled' }, - ], - }, - }, - { - process: 'Deposit Project', - role: 'Deposit', - notification: { - unread: 1, - total: 10, - messages: [ - { id: 14, read: false, date: '2024-03-10', message: 'Deposit milestone reached' }, - { id: 15, read: false, date: '2024-03-09', message: 'Security update required' }, - { id: 16, read: false, date: '2024-03-08', message: 'Weekly report available' }, - { id: 17, read: true, date: '2024-03-07', message: 'Team meeting scheduled' }, - { id: 18, read: true, date: '2024-03-06', message: 'Project status: on track' }, - ], - }, - }, - { - process: 'Artefact Project', - role: 'Artefact', - notification: { - unread: 0, - total: 3, - messages: [ - { id: 19, read: false, date: '2024-03-10', message: 'New artefact added' }, - { id: 20, read: false, date: '2024-03-09', message: 'Security update required' }, - { id: 21, read: false, date: '2024-03-08', message: 'Weekly report available' }, - { id: 22, read: true, date: '2024-03-07', message: 'Team meeting scheduled' }, - { id: 23, read: true, date: '2024-03-06', message: 'Project status: on track' }, - ], - }, - }, - { - process: 'Resolve Project', - role: 'Resolve', - notification: { - unread: 5, - total: 12, - messages: [ - { id: 24, read: false, date: '2024-03-10', message: 'New issue reported' }, - { id: 25, read: false, date: '2024-03-09', message: 'Security update required' }, - { id: 26, read: false, date: '2024-03-08', message: 'Weekly report available' }, - { id: 27, read: true, date: '2024-03-07', message: 'Team meeting scheduled' }, - { id: 28, read: true, date: '2024-03-06', message: 'Project status: on track' }, - ], - }, - }, -]; - -export const mockContracts = { - 'Contract #123': { - title: 'User Project Agreement', - date: '2024-01-15', - parties: ['Company XYZ', 'User Team'], - terms: ['Data Protection', 'User Privacy', 'Access Rights', 'Service Level Agreement'], - content: 'This agreement establishes the terms and conditions for user project management.', - }, - 'Contract #456': { - title: 'Process Management Contract', - date: '2024-02-01', - parties: ['Company XYZ', 'Process Team'], - terms: ['Process Workflow', 'Quality Standards', 'Performance Metrics', 'Monitoring Procedures'], - content: 'This contract defines the process management standards and procedures.', - }, - 'Contract #789': { - title: 'Member Access Agreement', - date: '2024-03-15', - parties: ['Company XYZ', 'Member Team'], - terms: ['Member Rights', 'Access Levels', 'Security Protocol', 'Confidentiality Agreement'], - content: 'This agreement outlines the terms for member access and privileges.', - }, - 'Contract #101': { - title: 'Peer Collaboration Agreement', - date: '2024-04-01', - parties: ['Company XYZ', 'Peer Network'], - terms: ['Collaboration Rules', 'Resource Sharing', 'Dispute Resolution', 'Network Protocol'], - content: 'This contract establishes peer collaboration and networking guidelines.', - }, - 'Contract #102': { - title: 'Payment Processing Agreement', - date: '2024-05-01', - parties: ['Company XYZ', 'Payment Team'], - terms: ['Transaction Protocol', 'Security Measures', 'Fee Structure', 'Service Availability'], - content: 'This agreement defines payment processing terms and conditions.', - }, - 'Contract #103': { - title: 'Deposit Management Contract', - date: '2024-06-01', - parties: ['Company XYZ', 'Deposit Team'], - terms: ['Deposit Rules', 'Storage Protocol', 'Access Control', 'Security Standards'], - content: 'This contract outlines deposit management procedures and security measures.', - }, - 'Contract #104': { - title: 'Artefact Handling Agreement', - date: '2024-07-01', - parties: ['Company XYZ', 'Artefact Team'], - terms: ['Handling Procedures', 'Storage Guidelines', 'Access Protocol', 'Preservation Standards'], - content: 'This agreement establishes artefact handling and preservation guidelines.', - }, - 'Contract #105': { - title: 'Resolution Protocol Agreement', - date: '2024-08-01', - parties: ['Company XYZ', 'Resolution Team'], - terms: ['Resolution Process', 'Time Constraints', 'Escalation Protocol', 'Documentation Requirements'], - content: 'This contract defines the resolution process and protocol standards.', - }, - 'Contract #106': { - title: 'Backup Service Agreement', - date: '2024-09-01', - parties: ['Company XYZ', 'Backup Team'], - terms: ['Backup Schedule', 'Data Protection', 'Recovery Protocol', 'Service Reliability'], - content: 'This agreement outlines backup service terms and recovery procedures.', - }, -}; diff --git a/src/mocks/mock-account/interfacesAccountMock.ts b/src/mocks/mock-account/interfacesAccountMock.ts deleted file mode 100644 index 1c409ba..0000000 --- a/src/mocks/mock-account/interfacesAccountMock.ts +++ /dev/null @@ -1,45 +0,0 @@ -export interface Row { - column1: string; - column2: string; - column3: string; -} - -// Types supplémentaires nécessaires -export interface Contract { - title: string; - date: string; - parties: string[]; - terms: string[]; - content: string; -} - -export interface WalletRow { - column1: string; // Label - column2: string; // Wallet - column3: string; // Type -} - -export interface DataRow { - column1: string; // Name - column2: string; // Visibility - column3: string; // Role - column4: string; // Duration - column5: string; // Legal - column6: string; // Contract - processName: string; - zone: string; -} - -export interface Notification { - message: string; - timestamp: string; - isRead: boolean; -} - -// Déplacer l'interface en dehors de la classe, au début du fichier -export interface NotificationMessage { - id: number; - read: boolean; - date: string; - message: string; -} diff --git a/src/pages/account/account-component.ts b/src/pages/account/account-component.ts deleted file mode 100644 index db8f193..0000000 --- a/src/pages/account/account-component.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { AccountElement } from './account'; -import accountCss from '../../../public/style/account.css?raw'; -import Services from '../../services/service.js'; - -class AccountComponent extends HTMLElement { - _callback: any; - accountElement: AccountElement | null = null; - - constructor() { - super(); - console.log('INIT'); - this.attachShadow({ mode: 'open' }); - - this.accountElement = this.shadowRoot?.querySelector('account-element') || null; - } - - connectedCallback() { - console.log('CALLBACKs'); - this.render(); - this.fetchData(); - - if (!customElements.get('account-element')) { - customElements.define('account-element', AccountElement); - } - } - - async fetchData() { - if ((import.meta as any).env.VITE_IS_INDEPENDANT_LIB === false) { - const data = await (window as any).myService?.getProcesses(); - } else { - const service = await Services.getInstance(); - const data = await service.getProcesses(); - } - } - - set callback(fn) { - if (typeof fn === 'function') { - this._callback = fn; - } else { - console.error('Callback is not a function'); - } - } - - get callback() { - return this._callback; - } - - render() { - if (this.shadowRoot && !this.shadowRoot.querySelector('account-element')) { - const style = document.createElement('style'); - style.textContent = accountCss; - - const accountElement = document.createElement('account-element'); - - this.shadowRoot.appendChild(style); - this.shadowRoot.appendChild(accountElement); - } - } -} - -export { AccountComponent }; -customElements.define('account-component', AccountComponent); diff --git a/src/pages/account/account.ts b/src/pages/account/account.ts deleted file mode 100755 index 3e05daa..0000000 --- a/src/pages/account/account.ts +++ /dev/null @@ -1,1587 +0,0 @@ -declare global { - interface Window { - initAccount: () => void; - showContractPopup: (contractId: string) => void; - showPairing: () => Promise; - showWallet: () => void; - showData: () => void; - addWalletRow: () => void; - confirmWalletRow: () => void; - cancelWalletRow: () => void; - openAvatarPopup: () => void; - closeAvatarPopup: () => void; - editDeviceName: (cell: HTMLTableCellElement) => void; - showNotifications: (processName: string) => void; - closeNotificationPopup: (event: Event) => void; - markAsRead: (processName: string, messageId: number, element: HTMLElement) => void; - exportRecovery: () => void; - confirmDeleteAccount: () => void; - deleteAccount: () => void; - updateNavbarBanner: (bannerUrl: string) => void; - saveBannerToLocalStorage: (bannerUrl: string) => void; - loadSavedBanner: () => void; - cancelAddRowPairing: () => void; - saveName: (cell: HTMLElement, input: HTMLInputElement) => void; - showProcessNotifications: (processName: string) => void; - handleLogout: () => void; - initializeEventListeners: () => void; - showProcess: () => void; - showProcessCreation: () => void; - showDocumentValidation: () => void; - updateNavbarName: (name: string) => void; - updateNavbarLastName: (lastName: string) => void; - showAlert: (title: string, text?: string, icon?: string) => void; - addRowPairing: () => void; - confirmRowPairing: () => void; - cancelRowPairing: () => void; - deleteRowPairing: (button: HTMLButtonElement) => void; - generateRecoveryWords: () => string[]; - exportUserData: () => void; - updateActionButtons: () => void; - showQRCodeModal: (pairingId: string) => void; - } -} - -import Swal from 'sweetalert2'; -import { STORAGE_KEYS, defaultRows, mockProcessRows, mockNotifications, notificationMessages, mockDataRows, mockContracts, ALLOWED_ROLES } from '../../mocks/mock-account/constAccountMock'; -import { Row, WalletRow, DataRow, Notification, Contract, NotificationMessage } from '../../mocks/mock-account/interfacesAccountMock'; -import { addressToEmoji } from '../../utils/sp-address.utils'; -import { getCorrectDOM } from '../../utils/document.utils'; -import accountStyle from '../../../public/style/account.css?inline'; -import Services from '../../services/service'; -import { getProcessCreation } from './process-creation'; -import { getDocumentValidation } from './document-validation'; -import { createProcessTab } from './process'; - -let isAddingRow = false; -let currentRow: HTMLTableRowElement | null = null; -let currentMode: keyof typeof STORAGE_KEYS = 'pairing'; - -interface Process { - states: Array<{ - committed_in: string; - keys: {}; - pcd_commitment: { - counter: string; - }; - public_data: { - memberPublicName?: string; - }; - roles: { - pairing?: {}; - }; - state_id: string; - validation_tokens: Array; - }>; -} - -class AccountElement extends HTMLElement { - private dom: Node; - - constructor() { - super(); - this.attachShadow({ mode: 'open' }); - this.dom = getCorrectDOM('account-element'); - - // Ajouter Font Awesome - const fontAwesome = document.createElement('link'); - fontAwesome.rel = 'stylesheet'; - fontAwesome.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css'; - this.shadowRoot!.appendChild(fontAwesome); - - const style = document.createElement('style'); - style.textContent = accountStyle; - this.shadowRoot!.appendChild(style); - - this.shadowRoot!.innerHTML = ` - - - - - - -
- -
-
    - -
    -
    - Banner -
    -
    - Avatar - -
    -
    - - - - - -
-
    Pairing 🔗
- -
    Process ⚙️
-
    Process Creation
-
    Document Validation
- -
- - -
-
-
- -
-
-
- -
-
-
- `; - - - window.showPairing = () => this.showPairing(); - window.showWallet = () => this.showWallet(); - window.showProcess = () => this.showProcess(); - window.showProcessCreation = () => this.showProcessCreation(); - window.showDocumentValidation = () => this.showDocumentValidation(); - window.showData = () => this.showData(); - window.addWalletRow = () => this.addWalletRow(); - window.confirmWalletRow = () => this.confirmWalletRow(); - window.cancelWalletRow = () => this.cancelWalletRow(); - window.editDeviceName = (cell: HTMLTableCellElement) => this.editDeviceName(cell); - window.showProcessNotifications = (processName: string) => this.showProcessNotifications(processName); - window.handleLogout = () => this.handleLogout(); - window.confirmDeleteAccount = () => this.confirmDeleteAccount(); - window.showContractPopup = (contractId: string) => this.showContractPopup(contractId); - window.addRowPairing = () => this.addRowPairing(); - window.deleteRowPairing = (button: HTMLButtonElement) => this.deleteRowPairing(button); - window.confirmRowPairing = () => this.confirmRowPairing(); - window.cancelRowPairing = () => this.cancelRowPairing(); - window.updateNavbarBanner = (bannerUrl: string) => this.updateNavbarBanner(bannerUrl); - window.saveBannerToLocalStorage = (bannerUrl: string) => this.saveBannerToLocalStorage(bannerUrl); - window.loadSavedBanner = () => this.loadSavedBanner(); - window.closeNotificationPopup = (event: Event) => this.closeNotificationPopup(event); - window.markAsRead = (processName: string, messageId: number, element: HTMLElement) => this.markAsRead(processName, messageId, element); - window.exportRecovery = () => this.exportRecovery(); - window.generateRecoveryWords = () => this.generateRecoveryWords(); - window.exportUserData = () => this.exportUserData(); - window.updateActionButtons = () => this.updateActionButtons(); - window.openAvatarPopup = () => this.openAvatarPopup(); - window.closeAvatarPopup = () => this.closeAvatarPopup(); - window.showQRCodeModal = (pairingId: string) => this.showQRCodeModal(pairingId); - - if (!localStorage.getItem('rows')) { - localStorage.setItem('rows', JSON.stringify(defaultRows)); - } - } - - connectedCallback() { - this.initializeEventListeners(); - this.loadSavedBanner(); - this.loadUserInfo(); - - const savedAvatar = localStorage.getItem('userAvatar'); - const savedBanner = localStorage.getItem('userBanner'); - const savedName = localStorage.getItem('userName'); - const savedLastName = localStorage.getItem('userLastName'); - - if (savedAvatar) { - const navAvatar = this.shadowRoot?.querySelector('.avatar') as HTMLImageElement; - if (navAvatar) navAvatar.src = savedAvatar; - } - - if (savedBanner) { - const navBanner = this.shadowRoot?.querySelector('.banner-image') as HTMLImageElement; - if (navBanner) navBanner.src = savedBanner; - } - - if (savedName) { - this.updateNavbarName(savedName); - } - if (savedLastName) { - this.updateNavbarLastName(savedLastName); - } - } - - private showAlert(message: string): void { - // Créer la popup si elle n'existe pas - let alertPopup = this.shadowRoot?.querySelector('.alert-popup'); - if (!alertPopup) { - alertPopup = document.createElement('div'); - alertPopup.className = 'alert-popup'; - this.shadowRoot?.appendChild(alertPopup); - } - - // Définir le message et afficher la popup - alertPopup.textContent = message; - (alertPopup as HTMLElement).style.display = 'block'; - - // Cacher la popup après 3 secondes - setTimeout(() => { - (alertPopup as HTMLElement).style.display = 'none'; - }, 3000); - } - - - // Fonctions de gestion des comptes et de l'interface utilisateur - private confirmDeleteAccount(): void { - const modal = document.createElement('div'); - modal.className = 'confirm-delete-modal'; - modal.innerHTML = ` -

Delete Account

-

Are you sure you want to delete your account? This action cannot be undone.

-
- - -
- `; - - this.shadowRoot?.appendChild(modal); - modal.style.display = 'block'; - - const cancelBtn = modal.querySelector('.cancel-btn'); - const confirmBtn = modal.querySelector('.confirm-btn'); - - cancelBtn?.addEventListener('click', () => { - modal.remove(); - }); - - confirmBtn?.addEventListener('click', () => { - this.deleteAccount(); - modal.remove(); - }); -} - -private deleteAccount(): void { - localStorage.clear(); - window.location.href = '/login.html'; -} - -private updateNavbarBanner(imageUrl: string): void { - const navbarSection = this.shadowRoot?.querySelector('.nav-wrapper .avatar-section'); - if (!navbarSection) return; - - let bannerImg = navbarSection.querySelector('.banner-image'); - - if (!bannerImg) { - bannerImg = document.createElement('img'); - bannerImg.className = 'banner-image'; - navbarSection.insertBefore(bannerImg, navbarSection.firstChild); - } - - bannerImg.src = imageUrl; -} - -private saveBannerToLocalStorage(dataUrl: string): void { - localStorage.setItem('userBanner', dataUrl); -} - -private loadSavedBanner(): void { - const savedBanner = localStorage.getItem('userBanner'); - if (savedBanner) { - const bannerImg = this.shadowRoot?.getElementById('popup-banner-img') as HTMLImageElement; - if (bannerImg) { - bannerImg.src = savedBanner; - } - this.updateNavbarBanner(savedBanner); - } -} - - -private closeNotificationPopup(event: Event): void { - const target = event.target as HTMLElement; - const isOverlay = target.classList.contains('notification-popup-overlay'); - const isCloseButton = target.classList.contains('close-popup'); - if (!isOverlay && !isCloseButton) return; - - const popup = this.shadowRoot?.querySelector('.notification-popup-overlay'); - if (popup) popup.remove(); -} - -private markAsRead(processName: string, messageId: number, element: HTMLElement): void { - const process = mockProcessRows.find(p => p.process === processName); - if (!process) return; - - const message = process.notification.messages.find(m => m.id === messageId); - if (!message || message.read) return; - - message.read = true; - - element.classList.remove('unread'); - element.classList.add('read'); - - const statusIcon = element.querySelector('.notification-status'); - if (statusIcon) { - statusIcon.innerHTML = ` - - - `; - } - - const notifCount = this.calculateNotifications(process.notification.messages); - const countElement = this.shadowRoot?.querySelector(`.notification-count[data-process="${processName}"]`); - if (countElement) { - countElement.textContent = `${notifCount.unread}/${notifCount.total}`; - - const bellContainer = countElement.closest('.notification-container'); - const bell = bellContainer?.querySelector('svg'); // Changé de .fa-bell à svg - if (bell && bellContainer && notifCount.unread === 0) { - bellContainer.classList.remove('has-unread'); - (bell as SVGElement).style.fill = '#666'; // Utiliser fill au lieu de color pour SVG - } - } -} - -// Fonctions de gestion des données et de l'interface -private calculateNotifications(messages: NotificationMessage[]): { unread: number; total: number } { - const total = messages.length; - const unread = messages.filter(msg => !msg.read).length; - return { unread, total }; -} - -// Fonctions de récupération -private exportRecovery(): void { - Swal.fire({ - title: 'Recovery Words Export', - text: '4 words will be displayed. We strongly recommend writing them down on paper before exporting the account. Do you want to continue?', - icon: 'warning', - showCancelButton: true, - confirmButtonText: 'Confirm', - cancelButtonText: 'Cancel', - confirmButtonColor: '#C89666', - cancelButtonColor: '#6c757d', - // Ajouter des styles personnalisés - customClass: { - container: 'recovery-popup-container', - popup: 'recovery-popup' - } - }).then((result) => { - if (result.isConfirmed) { - const recoveryWords = this.generateRecoveryWords(); - localStorage.setItem('recoveryWords', JSON.stringify(recoveryWords)); - - Swal.fire({ - title: 'Your Recovery Words', - html: ` -
- ${recoveryWords.map((word, index) => ` -
- ${index + 1}. - ${word} -
- `).join('')} -
-
- Please write these words down carefully. They will be needed to recover your account. -
- `, - showCancelButton: false, - confirmButtonText: 'I confirm the export', - confirmButtonColor: '#C89666', - allowOutsideClick: false, - allowEscapeKey: false, - customClass: { - container: 'recovery-popup-container', - popup: 'recovery-popup' - } - }).then((result) => { - if (result.isConfirmed) { - // Stocker l'état du bouton dans le localStorage - localStorage.setItem('recoveryExported', 'true'); - - const exportRecoveryBtn = this.shadowRoot?.querySelector('.recovery-btn') as HTMLButtonElement; - if (exportRecoveryBtn) { - exportRecoveryBtn.disabled = true; - exportRecoveryBtn.style.opacity = '0.5'; - exportRecoveryBtn.style.cursor = 'not-allowed'; - } - } - }); - } - }); -} - -private generateRecoveryWords(): string[] { - const wordsList = [ - 'apple', 'banana', 'orange', 'grape', 'kiwi', 'mango', 'peach', 'plum', - 'lemon', 'lime', 'cherry', 'melon', 'pear', 'fig', 'date', 'berry' - ]; - const recoveryWords: string[] = []; - while (recoveryWords.length < 4) { - const randomWord = wordsList[Math.floor(Math.random() * wordsList.length)]; - if (!recoveryWords.includes(randomWord)) { - recoveryWords.push(randomWord); - } - } - return recoveryWords; -} - -private exportUserData(): void { - const data: { [key: string]: string | null } = {}; - for (let i = 0; i < localStorage.length; i++) { - const key = localStorage.key(i); - if (key) { - const value = localStorage.getItem(key); - data[key] = value; - } - } - - const jsonData = JSON.stringify(data, null, 2); - const blob = new Blob([jsonData], { type: 'application/json' }); - const url = URL.createObjectURL(blob); - const a = document.createElement('a'); - a.href = url; - a.download = 'user_data.json'; - this.shadowRoot?.appendChild(a); - a.click(); - this.shadowRoot?.removeChild(a); - URL.revokeObjectURL(url); -} - -private updateActionButtons(): void { - const buttonContainer = this.shadowRoot?.querySelector('.button-container'); - if (!buttonContainer) return; - - buttonContainer.innerHTML = ` -
- - -
- `; -} - -private getConfirmFunction(): string { - switch (currentMode) { - case 'wallet': - return 'window.confirmWalletRow()'; - case 'process': - return 'window.confirmProcessRow()'; - default: - return 'window.confirmRowPairing()'; - } -} - -private getCancelFunction(): string { - switch (currentMode) { - case 'wallet': - return 'window.cancelWalletRow()'; - case 'process': - return 'window.cancelProcessRow()'; - default: - return 'window.cancelRowPairing()'; - } -} - -// Fonctions de gestion des tableaux -private async addRowPairing(): Promise { - if (isAddingRow) return; - isAddingRow = true; - - // Créer la popup - const modal = document.createElement('div'); - modal.className = 'pairing-modal'; - modal.innerHTML = ` -
-

Add New Device

-
-
- - -
-
- - -
-
- - -
-
- - -
-
-
- `; - - this.shadowRoot?.appendChild(modal); - - // Ajouter les event listeners - const spAddressInput = modal.querySelector('#sp-address') as HTMLInputElement; - const spEmojisInput = modal.querySelector('#sp-emojis') as HTMLInputElement; - const deviceNameInput = modal.querySelector('#device-name') as HTMLInputElement; - const confirmButton = modal.querySelector('.confirm-button'); - const cancelButton = modal.querySelector('.cancel-button'); - - // Mettre à jour les emojis automatiquement - spAddressInput?.addEventListener('input', async () => { - const emojis = await addressToEmoji(spAddressInput.value); - if (spEmojisInput) spEmojisInput.value = emojis; - }); - - // Gérer la confirmation - confirmButton?.addEventListener('click', () => { - const spAddress = spAddressInput?.value.trim(); - const deviceName = deviceNameInput?.value.trim(); - const spEmojis = spEmojisInput?.value.trim(); - - if (!spAddress || !deviceName) { - this.showAlert('Please fill in all required fields'); - return; - } - - //if (spAddress.length !== 118) { - // this.showAlert('SP Address must be exactly 118 characters long'); - // return; - //} - - const newRow: Row = { - column1: spAddress, - column2: deviceName, - column3: spEmojis || '' - }; - - const storageKey = STORAGE_KEYS[currentMode]; - const rows: Row[] = JSON.parse(localStorage.getItem(storageKey) || '[]'); - rows.push(newRow); - localStorage.setItem(storageKey, JSON.stringify(rows)); - - this.updateTableContent(rows); - modal.remove(); - isAddingRow = false; - }); - - // Gérer l'annulation - cancelButton?.addEventListener('click', () => { - modal.remove(); - isAddingRow = false; - }); -} - -// Fonctions de mise à jour de l'interface -private updateTableContent(rows: Row[]): void { - const tbody = this.shadowRoot?.querySelector('#pairing-table tbody'); - if (!tbody) return; - - tbody.innerHTML = rows.map(row => ` - - ${row.column2} - ${row.column3} - - QR Code - - - - - - `).join(''); -} - - - -private confirmRowPairing(): void { - if (!currentRow) return; - - const inputs = currentRow.getElementsByTagName('input'); - const values: string[] = Array.from(inputs).map(input => input.value.trim()); - - // Vérification des champs vides - if (values.some(value => value === '')) { - this.showAlert('Please fill in all fields'); - return; - } - - // Vérification de la longueur de l'adresse SP - if (values[0].length !== 118) { - this.showAlert('SP Address must be exactly 118 characters long'); - return; - } - - const newRow: Row = { - column1: values[0], - column2: values[1], - column3: values[2] - }; - - const storageKey = STORAGE_KEYS[currentMode]; - const rows: Row[] = JSON.parse(localStorage.getItem(storageKey) || '[]'); - rows.push(newRow); - localStorage.setItem(storageKey, JSON.stringify(rows)); - - isAddingRow = false; - currentRow = null; - - this.resetButtonContainer(); - this.updateTableContent(rows); -} - -private cancelRowPairing(): void { - if (!currentRow) return; - - currentRow.remove(); - isAddingRow = false; - currentRow = null; - - this.resetButtonContainer(); -} - -private resetButtonContainer(): void { - const buttonContainer = this.shadowRoot?.querySelector('.button-container'); - if (!buttonContainer) return; - - buttonContainer.innerHTML = ` - - `; -} - -private deleteRowPairing(button: HTMLButtonElement): void { - const row = button.closest('tr'); - if (!row) return; - - const table = row.closest('tbody'); - if (!table) return; - - const remainingRows = table.getElementsByTagName('tr').length; - if (remainingRows <= 2) { - this.showAlert('You must keep at least 2 devices paired'); - return; - } - - // Créer la modal de confirmation - const modal = document.createElement('div'); - modal.className = 'confirm-delete-modal'; - modal.innerHTML = ` -
-

Confirm Deletion

-

Are you sure you want to delete this device?

-
- - -
-
- `; - - this.shadowRoot?.appendChild(modal); - - // Gérer les boutons de la modal - const confirmBtn = modal.querySelector('.confirm-btn'); - const cancelBtn = modal.querySelector('.cancel-btn'); - - confirmBtn?.addEventListener('click', () => { - // Calculer l'index AVANT de supprimer la ligne du DOM - const index = Array.from(table.children).indexOf(row); - const storageKey = STORAGE_KEYS[currentMode]; - const rows = JSON.parse(localStorage.getItem(storageKey) || '[]'); - - // Supprimer du localStorage - if (index > -1) { - rows.splice(index, 1); - localStorage.setItem(storageKey, JSON.stringify(rows)); - } - - // Animation et suppression du DOM - row.style.transition = 'opacity 0.3s, transform 0.3s'; - row.style.opacity = '0'; - row.style.transform = 'translateX(-100%)'; - - setTimeout(() => { - row.remove(); - }, 300); - - modal.remove(); - }); - - cancelBtn?.addEventListener('click', () => { - modal.remove(); - }); -} - -private editDeviceName(cell: HTMLTableCellElement): void { - if (cell.classList.contains('editing')) return; - - const currentValue = cell.textContent || ''; - const input = document.createElement('input'); - input.type = 'text'; - input.value = currentValue; - input.className = 'edit-input'; - - input.addEventListener('blur', () => this.finishEditing(cell, input)); - input.addEventListener('keypress', (e: KeyboardEvent) => { - if (e.key === 'Enter') { - this.finishEditing(cell, input); - } - }); - - cell.textContent = ''; - cell.appendChild(input); - cell.classList.add('editing'); - input.focus(); -} - -private async finishEditing(cell: HTMLTableCellElement, input: HTMLInputElement): Promise { - const newValue = input.value.trim(); - if (newValue === '') { - cell.textContent = cell.getAttribute('data-original-value') || ''; - cell.classList.remove('editing'); - return; - } - - try { - const service = await Services.getInstance(); - const pairingProcessId = service.getPairingProcessId(); - const process = await service.getProcess(pairingProcessId); - - // Mettre à jour le nom via le service - await service.updateMemberPublicName(process, newValue); - - // Mettre à jour l'interface - cell.textContent = newValue; - cell.classList.remove('editing'); - } catch (error) { - console.error('Failed to update name:', error); - // Restaurer l'ancienne valeur en cas d'erreur - cell.textContent = cell.getAttribute('data-original-value') || ''; - cell.classList.remove('editing'); - } -} - -// Fonction pour gérer le téléchargement de l'avatar -private handleAvatarUpload(event: Event): void { - const input = event.target as HTMLInputElement; - const file = input.files?.[0]; - - if (file) { - const reader = new FileReader(); - reader.onload = (e: ProgressEvent) => { - const result = e.target?.result as string; - const popupAvatar = this.shadowRoot?.getElementById('popup-avatar-img') as HTMLImageElement; - const navAvatar = this.shadowRoot?.querySelector('.nav-wrapper .avatar') as HTMLImageElement; - - if (popupAvatar) popupAvatar.src = result; - if (navAvatar) navAvatar.src = result; - - localStorage.setItem('userAvatar', result); - }; - reader.readAsDataURL(file); - } -} - -private async showProcessCreation(): Promise { - this.hideAllContent(); - const container = this.shadowRoot?.getElementById('process-creation-content'); - if (container) { - getProcessCreation(container); - } -} - -private async showDocumentValidation(): Promise { - this.hideAllContent(); - const container = this.shadowRoot?.getElementById('document-validation-content'); - if (container) { - getDocumentValidation(container); - } -} - -private async showProcess(): Promise { - this.hideAllContent(); - const container = this.shadowRoot?.getElementById('process-content'); - if (container) { - const service = await Services.getInstance(); - const myProcesses = await service.getMyProcesses(); - if (myProcesses && myProcesses.length != 0) { - const myProcessesDataUnfiltered: { name: string, publicData: Record }[] = await Promise.all(myProcesses.map(async processId => { - const process = await service.getProcess(processId); - const lastState = service.getLastCommitedState(process); - if (!lastState) { - return { - name: '', - publicData: {} - }; - } - const description = await service.decryptAttribute(processId, lastState, 'description'); - const name = description ? description : 'N/A'; - const publicData = await service.getPublicData(process); - if (!publicData) { - return { - name: '', - publicData: {} - }; - } - return { - name: name, - publicData: publicData - }; - })); - const myProcessesData = myProcessesDataUnfiltered.filter( - (p) => p.name !== '' && Object.keys(p.publicData).length != 0 - ); - - createProcessTab(container, myProcessesData); - } else { - createProcessTab(container, []); - } - } -} - -private showProcessNotifications(processName: string): void { - const process = mockProcessRows.find(p => p.process === processName); - if (!process) return; - - const modal = document.createElement('div'); - modal.className = 'notifications-modal'; - - let notificationsList = process.notification.messages.map(msg => ` -
-
- ${msg.read ? - ` - - ` : - ` - - ` - } -
-
- ${msg.message} - ${msg.date} -
-
- `).join(''); - - if (process.notification.messages.length === 0) { - notificationsList = '

No notifications

'; - } - - modal.innerHTML = ` -
-

${processName} Notifications

-
- ${notificationsList} -
- -
- `; - - this.shadowRoot?.appendChild(modal); - - // Mettre à jour le compteur de notifications - const countElement = this.shadowRoot?.querySelector(`.notification-count[data-process="${processName}"]`); - if (countElement) { - const notifCount = this.calculateNotifications(process.notification.messages); - countElement.textContent = `${notifCount.unread}/${notifCount.total}`; - } - - const closeButton = modal.querySelector('.close-notifications'); - closeButton?.addEventListener('click', () => { - modal.remove(); - this.showProcess(); // Rafraîchir l'affichage pour mettre à jour les compteurs - }); -} - - -private handleLogout(): void { - localStorage.clear(); - window.location.href = '../login/login.html'; -} - - -// Fonctions de gestion des contrats -private showContractPopup(contractId: string, event?: Event) { - if (event) { - event.preventDefault(); - } - - // Check if the contract exists in mockContracts - const contract = mockContracts[contractId as keyof typeof mockContracts]; - if (!contract) { - console.error('Contract not found:', contractId); - return; - } - - const popup = document.createElement('div'); - popup.className = 'contract-popup-overlay'; - popup.innerHTML = ` -
- -

${contract.title}

-
-

Date: ${contract.date}

-

Parties: ${contract.parties.join(', ')}

-

Terms:

-
    - ${contract.terms.map(term => `
  • ${term}
  • `).join('')} -
-

Content: ${contract.content}

-
-
- `; - - this.shadowRoot?.appendChild(popup); - - const closeBtn = popup.querySelector('.close-contract-popup'); - const closePopup = () => popup.remove(); - - closeBtn?.addEventListener('click', closePopup); - popup.addEventListener('click', (e) => { - if (e.target === popup) closePopup(); - }); -} - -// Fonction utilitaire pour cacher tous les contenus -private hideAllContent(): void { - const contents = ['pairing-content', 'wallet-content', 'process-content', 'process-creation-content', 'data-content', 'document-validation-content']; - contents.forEach(id => { - const element = this.shadowRoot?.getElementById(id); - if (element) { - element.style.display = 'none'; - } - }); -} - -// Fonctions d'affichage des sections -private async showPairing(): Promise { - const service = await Services.getInstance(); - const spAddress = await service.getDeviceAddress(); - - isAddingRow = false; - currentRow = null; - currentMode = 'pairing'; - - this.hideAllContent(); - - const headerElement = this.shadowRoot?.getElementById('parameter-header'); - if (headerElement) { - headerElement.textContent = 'Pairing'; - } - - const pairingContent = this.shadowRoot?.getElementById('pairing-content'); - if (pairingContent) { - pairingContent.style.display = 'block'; - pairingContent.innerHTML = ` -
Pairing
-
- - - - - - - - - - -
Device NameSP EmojisQR CodeActions
-
- -
-
- `; - - let rows = JSON.parse(localStorage.getItem(STORAGE_KEYS.pairing) || '[]'); - - const deviceExists = rows.some((row: Row) => row.column1 === spAddress); - - if (!deviceExists && spAddress) { - const emojis = await addressToEmoji(spAddress); - - try { - // Déboguer le processus de pairing - const pairingProcessId = await service.getPairingProcessId(); - console.log('Pairing Process ID:', pairingProcessId); - - const pairingProcess = await service.getProcess(pairingProcessId); - console.log('Pairing Process:', pairingProcess); - - const userName = pairingProcess?.states?.[0]?.public_data?.memberPublicName - || localStorage.getItem('userName') - - console.log('Username found:', userName); - - const newRow = { - column1: spAddress, - column2: userName, - column3: emojis - }; - rows = [newRow, ...rows]; - localStorage.setItem(STORAGE_KEYS.pairing, JSON.stringify(rows)); - } catch (error) { - console.error('Error getting pairing process:', error); - const newRow = { - column1: spAddress, - column2: 'This Device', - column3: emojis - }; - rows = [newRow, ...rows]; - localStorage.setItem(STORAGE_KEYS.pairing, JSON.stringify(rows)); - } - } - - this.updateTableContent(rows); - } -} - -private showWallet(): void { - isAddingRow = false; - currentRow = null; - - currentMode = 'wallet'; - this.hideAllContent(); - - // Mettre à jour le titre - const headerTitle = this.shadowRoot?.getElementById('header-title'); - if (headerTitle) headerTitle.textContent = 'Wallet'; - - const walletContent = this.shadowRoot?.getElementById('wallet-content'); - if (!walletContent) return; - walletContent.style.display = 'block'; - walletContent.innerHTML = ` -
Wallet
-
- - - - - - - - - -
LabelWalletType
-
- -
-
- `; - - const rows = JSON.parse(localStorage.getItem(STORAGE_KEYS.wallet) || '[]'); - this.updateWalletTableContent(rows); -} - - -private updateWalletTableContent(rows: WalletRow[]): void { - const tbody = this.shadowRoot?.querySelector('#wallet-table tbody'); - if (!tbody) return; - - tbody.innerHTML = rows.map(row => ` - - ${row.column1} - ${row.column2} - ${row.column3} - - `).join(''); -} - -private showData(): void { - //console.log("showData called"); - currentMode = 'data'; - this.hideAllContent(); - - const headerTitle = this.shadowRoot?.getElementById('header-title'); - if (headerTitle) headerTitle.textContent = 'Data'; - - const dataContent = this.shadowRoot?.getElementById('data-content'); - if (dataContent) { - dataContent.style.display = 'block'; - dataContent.innerHTML = ` -
Data
-
- - - - - - - - - - - - -
NameVisibilityRoleDurationLegalContract
-
- `; - - const rows = mockDataRows || JSON.parse(localStorage.getItem(STORAGE_KEYS.data) || '[]'); - this.updateDataTableContent(rows); - } -} - -// Fonctions de gestion du wallet -private addWalletRow(): void { - if (isAddingRow) return; - isAddingRow = true; - - const table = this.shadowRoot?.getElementById('wallet-table')?.getElementsByTagName('tbody')[0]; - if (!table) return; - - currentRow = table.insertRow(); - const placeholders = ['Label', 'Wallet', 'Type']; - - placeholders.forEach(placeholder => { - const cell = currentRow!.insertCell(); - const input = document.createElement('input'); - input.type = 'text'; - input.placeholder = placeholder; - input.className = 'edit-input'; - cell.appendChild(input); - }); - - // Remplacer le bouton "Add a line" par les boutons de confirmation/annulation - const buttonContainer = this.shadowRoot?.querySelector('#wallet-content .button-container'); - if (!buttonContainer) return; - - buttonContainer.innerHTML = ` -
- - -
- `; - - this.updateActionButtons(); -} - -private confirmWalletRow(): void { - if (!currentRow) return; - - const inputs = Array.from(currentRow.getElementsByTagName('input')); - const allFieldsFilled = inputs.every(input => input.value.trim() !== ''); - - if (allFieldsFilled) { - const newRow: WalletRow = { - column1: inputs[0].value.trim(), - column2: inputs[1].value.trim(), - column3: inputs[2].value.trim() - }; - - const rows = JSON.parse(localStorage.getItem(STORAGE_KEYS.wallet) || '[]'); - rows.push(newRow); - localStorage.setItem(STORAGE_KEYS.wallet, JSON.stringify(rows)); - - isAddingRow = false; - currentRow = null; - this.showWallet(); - } else { - this.showAlert('Please complete all fields before confirming.'); - } -} - -private cancelWalletRow(): void { - if (!currentRow) return; - - currentRow.remove(); - isAddingRow = false; - currentRow = null; - - // Réinitialiser le conteneur de boutons avec le bouton "Add a line" - const buttonContainer = this.shadowRoot?.querySelector('#wallet-content .button-container'); - if (!buttonContainer) return; - - buttonContainer.innerHTML = ` - - `; - - -} - -private updateDataTableContent(rows: DataRow[]): void { - const tbody = this.shadowRoot?.querySelector('#data-table tbody'); - if (!tbody) return; - - tbody.innerHTML = rows.map(row => ` - - ${row.column1} - ${row.column2} - ${row.column3} - ${row.column4} - ${row.column5} - - ${row.column6} - - - `).join(''); -} - -// Fonctions de gestion de l'avatar et de la bannière -private openAvatarPopup(): void { - const popup = this.shadowRoot?.getElementById('avatar-popup'); - if (!popup) return; - - // Récuprer les valeurs stockées - const savedName = localStorage.getItem('userName'); - const savedLastName = localStorage.getItem('userLastName'); - const savedAvatar = localStorage.getItem('userAvatar') || 'https://via.placeholder.com/150'; - const savedBanner = localStorage.getItem('userBanner') || 'https://via.placeholder.com/800x200'; - const savedAddress = localStorage.getItem('userAddress') || '🏠 🌍 🗽🎊😩-🎊😑😩'; - - popup.innerHTML = ` - - `; - - popup.style.display = 'block'; - this.setupEventListeners(popup); - - // Ajouter le gestionnaire d'événements pour la bannière - const bannerImg = popup.querySelector('#popup-banner-img'); - const bannerInput = popup.querySelector('#banner-upload') as HTMLInputElement; - - if (bannerImg && bannerInput) { - bannerImg.addEventListener('click', () => { - bannerInput.click(); - }); - } - - const recoveryExported = localStorage.getItem('recoveryExported') === 'true'; - if (recoveryExported) { - const exportRecoveryBtn = popup.querySelector('.recovery-btn') as HTMLButtonElement; - if (exportRecoveryBtn) { - exportRecoveryBtn.disabled = true; - exportRecoveryBtn.style.opacity = '0.5'; - exportRecoveryBtn.style.cursor = 'not-allowed'; - } - } -} - -private setupEventListeners(popup: HTMLElement): void { - // Gestionnaire pour la fermeture - const closeBtn = popup.querySelector('.close-popup'); - if (closeBtn) { - closeBtn.addEventListener('click', () => { - popup.style.display = 'none'; - }); - } - - // Gestionnaire pour l'upload d'avatar - const avatarUpload = popup.querySelector('#avatar-upload') as HTMLInputElement; - if (avatarUpload) { - avatarUpload.addEventListener('change', (e: Event) => { - const file = (e.target as HTMLInputElement).files?.[0]; - if (file) { - const reader = new FileReader(); - reader.onload = (e: ProgressEvent) => { - const result = e.target?.result as string; - // Mise à jour de l'avatar dans la preview et le popup - const popupAvatar = this.shadowRoot?.getElementById('popup-avatar-img') as HTMLImageElement; - const previewAvatar = this.shadowRoot?.querySelector('.preview-avatar') as HTMLImageElement; - - if (popupAvatar) popupAvatar.src = result; - if (previewAvatar) previewAvatar.src = result; - - localStorage.setItem('userAvatar', result); - }; - reader.readAsDataURL(file); - } - }); - } - - // Gestionnaire pour l'upload de bannière - const bannerUpload = popup.querySelector('#banner-upload') as HTMLInputElement; - if (bannerUpload) { - bannerUpload.addEventListener('change', (e: Event) => { - const file = (e.target as HTMLInputElement).files?.[0]; - if (file) { - const reader = new FileReader(); - reader.onload = (e: ProgressEvent) => { - const result = e.target?.result as string; - // Mise à jour de la bannière dans la preview et le popup - const popupBanner = this.shadowRoot?.getElementById('popup-banner-img') as HTMLImageElement; - const previewBanner = this.shadowRoot?.querySelector('.preview-banner-img') as HTMLImageElement; - - if (popupBanner) popupBanner.src = result; - if (previewBanner) previewBanner.src = result; - - localStorage.setItem('userBanner', result); - }; - reader.readAsDataURL(file); - } - }); - } - - // Gestionnaires pour les champs de texte - const nameInput = popup.querySelector('#userName') as HTMLInputElement; - const lastNameInput = popup.querySelector('#userLastName') as HTMLInputElement; - - if (nameInput) { - nameInput.addEventListener('input', () => { - const newName = nameInput.value; - localStorage.setItem('userName', newName); - // Mise à jour du nom dans la preview - const previewName = this.shadowRoot?.querySelector('.preview-name'); - if (previewName) previewName.textContent = newName; - }); - } - - if (lastNameInput) { - lastNameInput.addEventListener('input', () => { - const newLastName = lastNameInput.value; - localStorage.setItem('userLastName', newLastName); - // Mise à jour du nom de famille dans la preview - const previewLastName = this.shadowRoot?.querySelector('.preview-lastname'); - if (previewLastName) previewLastName.textContent = newLastName; - }); - } -} - -private closeAvatarPopup(): void { - const popup = this.shadowRoot?.querySelector('.avatar-popup'); - if (popup) popup.remove(); -} - -private loadAvatar(): void { - const savedAvatar = localStorage.getItem('userAvatar'); - if (savedAvatar) { - const avatarImg = this.shadowRoot?.querySelector('.avatar') as HTMLImageElement; - if (avatarImg) { - avatarImg.src = savedAvatar; - } - } -} - -private loadUserInfo(): void { - const savedName = localStorage.getItem('userName'); - const savedLastName = localStorage.getItem('userLastName'); - const savedAvatar = localStorage.getItem('userAvatar'); - const savedBanner = localStorage.getItem('userBanner'); - - // Mise à jour du nom dans la preview - if (savedName) { - const previewName = this.shadowRoot?.querySelector('.preview-name'); - if (previewName) { - previewName.textContent = savedName; - } - } - - // Mise à jour du nom de famille dans la preview - if (savedLastName) { - const previewLastName = this.shadowRoot?.querySelector('.preview-lastname'); - if (previewLastName) { - previewLastName.textContent = savedLastName; - } - } - - // Mise à jour de l'avatar dans la preview - if (savedAvatar) { - const previewAvatar = this.shadowRoot?.querySelector('.preview-avatar') as HTMLImageElement; - if (previewAvatar) { - previewAvatar.src = savedAvatar; - } - } - - // Mise à jour de la bannière dans la preview - if (savedBanner) { - const previewBanner = this.shadowRoot?.querySelector('.preview-banner-img') as HTMLImageElement; - if (previewBanner) { - previewBanner.src = savedBanner; - } - } -} - -private updateNavbarName(name: string): void { - const nameElement = this.shadowRoot?.querySelector('.nav-wrapper .user-name'); - if (nameElement) { - nameElement.textContent = name; - } -} - -private updateNavbarLastName(lastName: string): void { - const lastNameElement = this.shadowRoot?.querySelector('.nav-wrapper .user-lastname'); - if (lastNameElement) { - lastNameElement.textContent = lastName; - } -} - -private updateProfilePreview(data: { - avatar?: string, - banner?: string, - name?: string, - lastName?: string -}): void { - if (data.avatar) { - const previewAvatar = this.shadowRoot?.querySelector('.preview-avatar') as HTMLImageElement; - if (previewAvatar) previewAvatar.src = data.avatar; - } - - if (data.banner) { - const previewBanner = this.shadowRoot?.querySelector('.preview-banner-img') as HTMLImageElement; - if (previewBanner) previewBanner.src = data.banner; - } - - if (data.name) { - const previewName = this.shadowRoot?.querySelector('.preview-name'); - if (previewName) previewName.textContent = data.name; - } - - if (data.lastName) { - const previewLastName = this.shadowRoot?.querySelector('.preview-lastname'); - if (previewLastName) previewLastName.textContent = data.lastName; - } -} - -private initializeEventListeners() { - this.shadowRoot?.addEventListener('DOMContentLoaded', () => { - this.showPairing(); - }); - - const editableFields = this.shadowRoot?.querySelectorAll('.editable'); - if (editableFields) { - editableFields.forEach(field => { - field.addEventListener('click', () => { - if (!field.classList.contains('editing')) { - const currentValue = field.textContent || ''; - const input = document.createElement('input'); - input.type = 'text'; - input.value = currentValue; - input.className = 'edit-input'; - - field.textContent = ''; - field.appendChild(input); - field.classList.add('editing'); - input.focus(); - } - }); - }); - } - - const avatarInput = this.shadowRoot?.getElementById('avatar-upload') as HTMLInputElement; - if (avatarInput) { - avatarInput.addEventListener('change', this.handleAvatarUpload.bind(this)); - } -} - -private showQRCodeModal(pairingId: string): void { - const modal = document.createElement('div'); - modal.className = 'qr-modal'; - modal.innerHTML = ` -
- × - QR Code Large -
${decodeURIComponent(pairingId)}
-
- `; - - this.shadowRoot?.appendChild(modal); - - const closeBtn = modal.querySelector('.close-qr-modal'); - closeBtn?.addEventListener('click', () => modal.remove()); - modal.addEventListener('click', (e) => { - if (e.target === modal) modal.remove(); - }); -} -} - -customElements.define('account-element', AccountElement); -export { AccountElement }; diff --git a/src/router.ts b/src/router.ts index fcc8dfc..6e7d965 100755 --- a/src/router.ts +++ b/src/router.ts @@ -91,15 +91,7 @@ async function handleLocation(path: string) { break; case 'account': - const { AccountComponent } = await import('./pages/account/account-component'); - const accountContainer = document.querySelector('.parameter-list'); - if (accountContainer) { - if (!customElements.get('account-component')) { - customElements.define('account-component', AccountComponent); - } - const accountComponent = document.createElement('account-component'); - accountContainer.appendChild(accountComponent); - } + // Account page now uses device-management component directly break; /*case 'chat':