diff --git a/.env.alpha b/.env.alpha new file mode 100644 index 0000000..255f919 --- /dev/null +++ b/.env.alpha @@ -0,0 +1,15 @@ +APP_NAME=Lean 101 Clients API +CLIENT_NAME=Hunter Premium Produce +CLIENT_EMAIL=alex@lean-101.com +CLIENT_PASSWORD=JBBwVCDqmPA7 +CLIENT_TENANT_ID=hunter-premium-produce +ADMIN_NAME=Lean 101 +ADMIN_EMAIL=matt@lean-101.com +ADMIN_PASSWORD=XgHvUju6BYQZ +AUTH_SECRET=735895b72fcc87b601b1e68bb614b65c876cf7b4516c9a3872b0cc7a98dbde5f +ORIGIN=https://clients.lean-101.com.au +PUBLIC_API_BASE_URL=https://clients.lean-101.com.au +INTERNAL_API_BASE_URL=http://backend:8000 +CORS_ALLOW_ORIGINS=https://clients.lean-101.com.au +CLIENTS_APP_PORT=808 +DATABASE_URL=sqlite:////data/data_entry_app.db diff --git a/.env.alpha.example b/.env.alpha.example index 0f130c0..a230ba5 100644 --- a/.env.alpha.example +++ b/.env.alpha.example @@ -7,9 +7,9 @@ ADMIN_NAME=Lean 101 ADMIN_EMAIL=admin@lean101.local ADMIN_PASSWORD=lean101-admin AUTH_SECRET=replace-with-a-long-random-secret -ORIGIN=https://clients.lean-101.com -PUBLIC_API_BASE_URL=https://clients.lean-101.com +ORIGIN=https://clients.lean-101.com.au +PUBLIC_API_BASE_URL=https://clients.lean-101.com.au INTERNAL_API_BASE_URL=http://backend:8000 -CORS_ALLOW_ORIGINS=https://clients.lean-101.com +CORS_ALLOW_ORIGINS=https://clients.lean-101.com.au CLIENTS_APP_PORT=8081 DATABASE_URL=sqlite:////data/data_entry_app.db diff --git a/README.md b/README.md index fb7e000..968bbba 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ The frontend now supports: - `PUBLIC_API_BASE_URL` for browser requests - `INTERNAL_API_BASE_URL` for server-side SvelteKit requests inside Docker -This is important for a same-domain deployment such as `https://clients.lean-101.com`, where the browser should call the public domain while the frontend container should call the backend container directly. +This is important for a same-domain deployment such as `https://clients.lean-101.com.au`, where the browser should call the public domain while the frontend container should call the backend container directly. ### Example `/srv` deploy @@ -56,7 +56,7 @@ This follows the same external pattern as your website container: - one compose project under `/srv/lean101-clients` - one host-facing port, `8081`, for the app -- your existing public reverse proxy forwards `clients.lean-101.com` to `127.0.0.1:8081` +- your existing public reverse proxy forwards `clients.lean-101.com.au` to `127.0.0.1:8081` If your server already has a host-level nginx handling domains and TLS, use `deploy/nginx/clients.lean-101.proxy.conf` as the upstream template and point the domain at `http://127.0.0.1:8081`. diff --git a/deploy/nginx/clients.lean-101.proxy.conf b/deploy/nginx/clients.lean-101.proxy.conf index aa3e0e7..fd580bd 100644 --- a/deploy/nginx/clients.lean-101.proxy.conf +++ b/deploy/nginx/clients.lean-101.proxy.conf @@ -1,6 +1,6 @@ server { listen 80; - server_name clients.lean-101.com; + server_name clients.lean-101.com.au; location / { proxy_pass http://127.0.0.1:8081; diff --git a/docker-compose.alpha.yml b/docker-compose.alpha.yml index 615f486..bb283fb 100644 --- a/docker-compose.alpha.yml +++ b/docker-compose.alpha.yml @@ -16,7 +16,7 @@ services: ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@lean101.local} ADMIN_PASSWORD: ${ADMIN_PASSWORD:-lean101-admin} AUTH_SECRET: ${AUTH_SECRET:-change-me-in-production} - CORS_ALLOW_ORIGINS: ${CORS_ALLOW_ORIGINS:-https://clients.lean-101.com} + CORS_ALLOW_ORIGINS: ${CORS_ALLOW_ORIGINS:-https://clients.lean-101.com.au} volumes: - clients_app_data:/data healthcheck: @@ -33,10 +33,10 @@ services: dockerfile: frontend/Dockerfile restart: unless-stopped environment: - ORIGIN: ${ORIGIN:-https://clients.lean-101.com} + ORIGIN: ${ORIGIN:-https://clients.lean-101.com.au} PORT: 3000 HOST: 0.0.0.0 - PUBLIC_API_BASE_URL: ${PUBLIC_API_BASE_URL:-https://clients.lean-101.com} + PUBLIC_API_BASE_URL: ${PUBLIC_API_BASE_URL:-https://clients.lean-101.com.au} INTERNAL_API_BASE_URL: ${INTERNAL_API_BASE_URL:-http://backend:8000} PUBLIC_API_PORT: ${PUBLIC_API_PORT:-8000} depends_on: diff --git a/docker-compose.yml b/docker-compose.yml index 615f486..bb283fb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,7 +16,7 @@ services: ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@lean101.local} ADMIN_PASSWORD: ${ADMIN_PASSWORD:-lean101-admin} AUTH_SECRET: ${AUTH_SECRET:-change-me-in-production} - CORS_ALLOW_ORIGINS: ${CORS_ALLOW_ORIGINS:-https://clients.lean-101.com} + CORS_ALLOW_ORIGINS: ${CORS_ALLOW_ORIGINS:-https://clients.lean-101.com.au} volumes: - clients_app_data:/data healthcheck: @@ -33,10 +33,10 @@ services: dockerfile: frontend/Dockerfile restart: unless-stopped environment: - ORIGIN: ${ORIGIN:-https://clients.lean-101.com} + ORIGIN: ${ORIGIN:-https://clients.lean-101.com.au} PORT: 3000 HOST: 0.0.0.0 - PUBLIC_API_BASE_URL: ${PUBLIC_API_BASE_URL:-https://clients.lean-101.com} + PUBLIC_API_BASE_URL: ${PUBLIC_API_BASE_URL:-https://clients.lean-101.com.au} INTERNAL_API_BASE_URL: ${INTERNAL_API_BASE_URL:-http://backend:8000} PUBLIC_API_PORT: ${PUBLIC_API_PORT:-8000} depends_on: diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 06f285f..be2682e 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -32,6 +32,7 @@ let password = $state('changeme'); let isLoggingIn = $state(false); let loginError = $state(''); + let passwordInput: HTMLInputElement | null = null; const currentYear = new Date().getFullYear(); const appVersion = `v${packageInfo.version}`; const releaseStage = 'Alpha'; @@ -48,11 +49,37 @@ clientSession.set(session); } catch (error) { loginError = error instanceof Error ? error.message : 'Unable to sign in'; + triggerPasswordShake(); } finally { isLoggingIn = false; } } + function triggerPasswordShake() { + if (typeof window === 'undefined' || !passwordInput) { + return; + } + + if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { + return; + } + + passwordInput.animate( + [ + { transform: 'translateX(0)' }, + { transform: 'translateX(-8px)' }, + { transform: 'translateX(8px)' }, + { transform: 'translateX(-6px)' }, + { transform: 'translateX(6px)' }, + { transform: 'translateX(0)' } + ], + { + duration: 360, + easing: 'cubic-bezier(0.36, 0.07, 0.19, 0.97)' + } + ); + } + function currency(value: number | null | undefined, digits = 2) { if (value === null || value === undefined) { return 'N/A'; @@ -325,9 +352,15 @@ -