diff --git a/Makefile b/Makefile index f2254f0..4ae4b20 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,7 @@ help: install: @echo "Installing dependencies..." + $(PIP) install -e . $(PIP) install -r requirements.txt @echo "Dependencies installed successfully" diff --git a/requirements.txt b/requirements.txt index 73fc17a..7235046 100644 --- a/requirements.txt +++ b/requirements.txt @@ -92,7 +92,6 @@ pytz==2025.2 PyYAML==6.0.3 qrcode==8.2 RapidFuzz==3.14.3 --e git+https://retoor.molodetz.nl/retoor/rbox.git@1e5a6dbd5f5007c248368da57684aef075f75070#egg=rbox redis==7.0.1 requests==2.32.5 requests-toolbelt==1.0.0 diff --git a/static/css/billing.css b/static/css/billing.css index 089a354..7f05cc8 100644 --- a/static/css/billing.css +++ b/static/css/billing.css @@ -1,5 +1,5 @@ .billing-dashboard { - padding: 2rem; + padding: calc(var(--spacing-unit) * 3); max-width: 1400px; margin: 0 auto; } @@ -8,7 +8,7 @@ display: flex; justify-content: space-between; align-items: center; - margin-bottom: 2rem; + margin-bottom: calc(var(--spacing-unit) * 3); } .subscription-badge { @@ -31,16 +31,16 @@ .billing-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); - gap: 1.5rem; - margin-bottom: 2rem; + gap: calc(var(--spacing-unit) * 2.25); + margin-bottom: calc(var(--spacing-unit) * 3); } .billing-card { - background: white; - border: 1px solid #e5e7eb; + background: var(--accent-color); + border: 1px solid var(--border-color); border-radius: 8px; - padding: 1.5rem; - box-shadow: 0 1px 3px rgba(0,0,0,0.1); + padding: calc(var(--spacing-unit) * 2.25); + box-shadow: 0 1px 3px var(--shadow-color); } .billing-card h3 { @@ -131,11 +131,11 @@ } .invoices-section { - background: white; - border: 1px solid #e5e7eb; + background: var(--accent-color); + border: 1px solid var(--border-color); border-radius: 8px; - padding: 1.5rem; - margin-bottom: 2rem; + padding: calc(var(--spacing-unit) * 2.25); + margin-bottom: calc(var(--spacing-unit) * 3); } .invoices-table { @@ -190,49 +190,13 @@ } .payment-methods-section { - background: white; - border: 1px solid #e5e7eb; + background: var(--accent-color); + border: 1px solid var(--border-color); border-radius: 8px; - padding: 1.5rem; + padding: calc(var(--spacing-unit) * 2.25); } -.btn-primary { - background: #2563eb; - color: white; - border: none; - padding: 0.75rem 1.5rem; - border-radius: 6px; - font-weight: 600; - cursor: pointer; - transition: background 0.2s; -} -.btn-primary:hover { - background: #1d4ed8; -} - -.btn-secondary { - background: #6b7280; - color: white; - border: none; - padding: 0.75rem 1.5rem; - border-radius: 6px; - font-weight: 600; - cursor: pointer; - transition: background 0.2s; -} - -.btn-secondary:hover { - background: #4b5563; -} - -.btn-link { - background: none; - border: none; - color: #2563eb; - cursor: pointer; - text-decoration: underline; -} .modal { position: fixed; @@ -240,20 +204,41 @@ left: 0; width: 100%; height: 100%; - background: rgba(0, 0, 0, 0.5); + background-color: rgba(0, 0, 0, 0.5); display: flex; - justify-content: center; align-items: center; + justify-content: center; z-index: 1000; } .modal-content { - background: white; - padding: 2rem; + background-color: var(--accent-color); border-radius: 8px; + padding: calc(var(--spacing-unit) * 3); max-width: 800px; - max-height: 90vh; - overflow-y: auto; + width: 90%; + max-height: 85vh; + display: flex; + flex-direction: column; + overflow: hidden; + box-shadow: 0 4px 20px var(--shadow-color); +} + +.close-button { + align-self: flex-end; + background: none; + border: none; + font-size: 2rem; + cursor: pointer; + color: var(--text-color-light); + padding: 0; + width: 32px; + height: 32px; + margin-bottom: var(--spacing-unit); +} + +.close-button:hover { + color: var(--secondary-color); } .invoice-total { @@ -267,7 +252,7 @@ } .admin-billing { - padding: 2rem; + padding: calc(var(--spacing-unit) * 3); max-width: 1400px; margin: 0 auto; } @@ -275,16 +260,16 @@ .stats-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); - gap: 1.5rem; - margin-bottom: 2rem; + gap: calc(var(--spacing-unit) * 2.25); + margin-bottom: calc(var(--spacing-unit) * 3); } .stat-card { - background: white; - border: 1px solid #e5e7eb; + background: var(--accent-color); + border: 1px solid var(--border-color); border-radius: 8px; - padding: 1.5rem; - box-shadow: 0 1px 3px rgba(0,0,0,0.1); + padding: calc(var(--spacing-unit) * 2.25); + box-shadow: 0 1px 3px var(--shadow-color); } .stat-card h3 { @@ -301,11 +286,11 @@ } .pricing-config-section { - background: white; - border: 1px solid #e5e7eb; + background: var(--accent-color); + border: 1px solid var(--border-color); border-radius: 8px; - padding: 1.5rem; - margin-bottom: 2rem; + padding: calc(var(--spacing-unit) * 2.25); + margin-bottom: calc(var(--spacing-unit) * 3); } .pricing-table { @@ -342,10 +327,10 @@ } .invoice-generation-section { - background: white; - border: 1px solid #e5e7eb; + background: var(--accent-color); + border: 1px solid var(--border-color); border-radius: 8px; - padding: 1.5rem; + padding: calc(var(--spacing-unit) * 2.25); } .invoice-gen-form { diff --git a/static/css/style.css b/static/css/style.css index 12f66bd..3bb2f73 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -699,11 +699,15 @@ body.dark-mode { } .photo-gallery { + background-color: var(--accent-color); + border-radius: 8px; padding: calc(var(--spacing-unit) * 2); } .gallery-header { margin-bottom: calc(var(--spacing-unit) * 3); + border-bottom: 1px solid var(--border-color); + padding-bottom: calc(var(--spacing-unit) * 2); } .gallery-header h2 { @@ -762,6 +766,9 @@ body.dark-mode { padding: calc(var(--spacing-unit) * 4); color: var(--text-color-light); font-size: 1.1rem; + grid-column: 1 / -1; + width: 100%; + background-color: var(--accent-color); } .empty-state::before { @@ -979,3 +986,15 @@ body.dark-mode { border-color: var(--primary-color); background-color: rgba(0, 51, 153, 0.05); } +-e +.shared-items-container { + background-color: var(--accent-color); + border-radius: 8px; + padding: calc(var(--spacing-unit) * 2); +} + +.section-header { + border-bottom: 1px solid var(--border-color); + padding-bottom: calc(var(--spacing-unit) * 2); + margin-bottom: calc(var(--spacing-unit) * 2); +} diff --git a/static/js/components/admin-dashboard.js b/static/js/components/admin-dashboard.js index f71580c..8519aea 100644 --- a/static/js/components/admin-dashboard.js +++ b/static/js/components/admin-dashboard.js @@ -42,18 +42,18 @@ export class AdminDashboard extends HTMLElement { - `; @@ -394,7 +394,7 @@ class BillingDashboard extends HTMLElement {
Total: ${this.formatCurrency(invoice.total)}
- + `; document.body.appendChild(modal); diff --git a/static/js/components/file-list.js b/static/js/components/file-list.js index 0e02de2..b8c29cc 100644 --- a/static/js/components/file-list.js +++ b/static/js/components/file-list.js @@ -112,8 +112,8 @@ export class FileList extends HTMLElement { ` : ''} + ${totalItems === 0 ? '

No files found.

' : ''}
- ${totalItems === 0 ? '

No files found.

' : ''} ${this.folders.map(folder => this.renderFolder(folder)).join('')} ${this.files.map(file => this.renderFile(file)).join('')}
diff --git a/static/js/components/login-view.js b/static/js/components/login-view.js index d1bf091..1a3e0fb 100644 --- a/static/js/components/login-view.js +++ b/static/js/components/login-view.js @@ -39,6 +39,9 @@ export class LoginView extends HTMLElement { `; + + this.querySelector('#login-error').style.display = 'none'; + this.querySelector('#register-error').style.display = 'none'; } attachListeners() { @@ -76,6 +79,9 @@ export class LoginView extends HTMLElement { const password = formData.get('password'); const errorDiv = this.querySelector('#login-error'); + errorDiv.style.display = 'none'; + errorDiv.textContent = ''; + try { logger.info('Login attempt started', { username }); await api.login(username, password); @@ -84,6 +90,7 @@ export class LoginView extends HTMLElement { } catch (error) { logger.error('Login failed', { username, error: error.message }); errorDiv.textContent = error.message; + errorDiv.style.display = 'block'; } } @@ -96,6 +103,9 @@ export class LoginView extends HTMLElement { const password = formData.get('password'); const errorDiv = this.querySelector('#register-error'); + errorDiv.style.display = 'none'; + errorDiv.textContent = ''; + try { logger.info('Registration attempt started', { username, email }); await api.register(username, email, password); @@ -104,6 +114,7 @@ export class LoginView extends HTMLElement { } catch (error) { logger.error('Registration failed', { username, email, error: error.message }); errorDiv.textContent = error.message; + errorDiv.style.display = 'block'; } } } diff --git a/static/js/components/photo-gallery.js b/static/js/components/photo-gallery.js index c0735c5..17c1db0 100644 --- a/static/js/components/photo-gallery.js +++ b/static/js/components/photo-gallery.js @@ -30,10 +30,19 @@ class PhotoGallery extends HTMLElement { async renderPhotos() { const grid = this.querySelector('.gallery-grid'); if (this.photos.length === 0) { - grid.innerHTML = '

No photos found.

'; + grid.innerHTML = ''; + const header = this.querySelector('.gallery-header'); + const empty = document.createElement('p'); + empty.className = 'empty-state'; + empty.textContent = 'No photos found.'; + header.insertAdjacentElement('afterend', empty); return; } + // Remove any existing empty-state + const existingEmpty = this.querySelector('.empty-state'); + if (existingEmpty) existingEmpty.remove(); + grid.innerHTML = this.photos.map(photo => `
-

Shared Items

+
+

Shared Items

+

No shared items found.

`; @@ -41,7 +43,9 @@ export class SharedItems extends HTMLElement { this.innerHTML = `
-

Shared Items

+
+

Shared Items

+
${this.myShares.map(share => this.renderShare(share)).join('')}