diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 87fa40e..74bf10b 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -6,7 +6,24 @@ on: types: [opened, synchronize, reopened] jobs: - test-and-build: + lint: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "24" + cache: "npm" + + - name: Install dependencies + run: npm ci + - name: Run linting + run: npm run lint + check: runs-on: ubuntu-latest steps: @@ -24,9 +41,21 @@ jobs: - name: Run type checking run: npm run check + tests: + runs-on: ubuntu-latest - - name: Run linting - run: npm run lint + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "24" + cache: "npm" + + - name: Install dependencies + run: npm ci - name: Run unit tests run: npm run test:unit -- --run @@ -41,6 +70,22 @@ jobs: SMTP_FROM_EMAIL: "noreply@example.com" JWT_SECRET: "test" + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "24" + cache: "npm" + + - name: Install dependencies + run: npm ci + - name: Build application run: npm run build env: diff --git a/package-lock.json b/package-lock.json index 04e0610..9bd8578 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,7 +33,7 @@ "@eslint/compat": "^1.3.0", "@eslint/js": "^9.29.0", "@inlang/paraglide-js": "2.3.2", - "@internationalized/date": "^3.8.2", + "@internationalized/date": "^3.10.1", "@lucide/svelte": "^0.544.0", "@playwright/test": "^1.56.1", "@sveltejs/adapter-auto": "^6.1.0", @@ -46,7 +46,7 @@ "@types/dotenv": "^6.1.1", "@types/node": "^24", "@types/nodemailer": "^6.4.17", - "bits-ui": "^2.11.4", + "bits-ui": "^2.15.4", "clsx": "^2.1.1", "drizzle-kit": "^0.31.1", "eslint": "^9.29.0", @@ -1673,9 +1673,9 @@ } }, "node_modules/@internationalized/date": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.8.2.tgz", - "integrity": "sha512-/wENk7CbvLbkUvX1tu0mwq49CVkkWpkXubGel6birjRPyo6uQ4nQpnq5xZu823zRCwwn82zgHrvgF1vZyvmVgA==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.10.1.tgz", + "integrity": "sha512-oJrXtQiAXLvT9clCf1K4kxp3eKsQhIaZqxEyowkBcsvZDdZkbWrVmnGknxs5flTD0VGsxrxKgBCZty1EzoiMzA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -3674,17 +3674,17 @@ "license": "MIT" }, "node_modules/bits-ui": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-2.11.4.tgz", - "integrity": "sha512-OlVBJhNUMDHbIAf8oDAyPchIrU8b1S5NAMm6enMZSKx5HKcf/QPI485/BL1r4EPlv4O3m45e59hBRCETtYFdxg==", + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-2.15.4.tgz", + "integrity": "sha512-7H9YUfp03KOk1LVDh8wPYSRPxlZgG/GRWLNSA8QC73/8Z8ytun+DWJhIuibyFyz7A0cP/RANVcB4iDrbY8q+Og==", "dev": true, "license": "MIT", "dependencies": { "@floating-ui/core": "^1.7.1", "@floating-ui/dom": "^1.7.1", "esm-env": "^1.1.2", - "runed": "^0.31.1", - "svelte-toolbelt": "^0.10.4", + "runed": "^0.35.1", + "svelte-toolbelt": "^0.10.6", "tabbable": "^6.2.0" }, "engines": { @@ -3699,9 +3699,9 @@ } }, "node_modules/bits-ui/node_modules/runed": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/runed/-/runed-0.31.1.tgz", - "integrity": "sha512-v3czcTnO+EJjiPvD4dwIqfTdHLZ8oH0zJheKqAHh9QMViY7Qb29UlAMRpX7ZtHh7AFqV60KmfxaJ9QMy+L1igQ==", + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/runed/-/runed-0.35.1.tgz", + "integrity": "sha512-2F4Q/FZzbeJTFdIS/PuOoPRSm92sA2LhzTnv6FXhCoENb3huf5+fDuNOg1LNvGOouy3u/225qxmuJvcV3IZK5Q==", "dev": true, "funding": [ "https://github.com/sponsors/huntabyte", @@ -3709,23 +3709,31 @@ ], "license": "MIT", "dependencies": { - "esm-env": "^1.0.0" + "dequal": "^2.0.3", + "esm-env": "^1.0.0", + "lz-string": "^1.5.0" }, "peerDependencies": { + "@sveltejs/kit": "^2.21.0", "svelte": "^5.7.0" + }, + "peerDependenciesMeta": { + "@sveltejs/kit": { + "optional": true + } } }, "node_modules/bits-ui/node_modules/svelte-toolbelt": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/svelte-toolbelt/-/svelte-toolbelt-0.10.5.tgz", - "integrity": "sha512-8e+eWTgxw1aiLxhDE8Rb1X6AoLitqpJz+WhAul2W7W58C8KoLoJQf1TgQdFPBiCPJ0Jg5y0Zi1uyua9em4VS0w==", + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/svelte-toolbelt/-/svelte-toolbelt-0.10.6.tgz", + "integrity": "sha512-YWuX+RE+CnWYx09yseAe4ZVMM7e7GRFZM6OYWpBKOb++s+SQ8RBIMMe+Bs/CznBMc0QPLjr+vDBxTAkozXsFXQ==", "dev": true, "funding": [ "https://github.com/sponsors/huntabyte" ], "dependencies": { "clsx": "^2.1.1", - "runed": "^0.29.0", + "runed": "^0.35.1", "style-to-object": "^1.0.8" }, "engines": { @@ -3736,23 +3744,6 @@ "svelte": "^5.30.2" } }, - "node_modules/bits-ui/node_modules/svelte-toolbelt/node_modules/runed": { - "version": "0.29.2", - "resolved": "https://registry.npmjs.org/runed/-/runed-0.29.2.tgz", - "integrity": "sha512-0cq6cA6sYGZwl/FvVqjx9YN+1xEBu9sDDyuWdDW1yWX7JF2wmvmVKfH+hVCZs+csW+P3ARH92MjI3H9QTagOQA==", - "dev": true, - "funding": [ - "https://github.com/sponsors/huntabyte", - "https://github.com/sponsors/tglide" - ], - "license": "MIT", - "dependencies": { - "esm-env": "^1.0.0" - }, - "peerDependencies": { - "svelte": "^5.7.0" - } - }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", diff --git a/package.json b/package.json index 35895dc..b37f9dd 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "@eslint/compat": "^1.3.0", "@eslint/js": "^9.29.0", "@inlang/paraglide-js": "2.3.2", - "@internationalized/date": "^3.8.2", + "@internationalized/date": "^3.10.1", "@lucide/svelte": "^0.544.0", "@playwright/test": "^1.56.1", "@sveltejs/adapter-auto": "^6.1.0", @@ -54,7 +54,7 @@ "@types/dotenv": "^6.1.1", "@types/node": "^24", "@types/nodemailer": "^6.4.17", - "bits-ui": "^2.11.4", + "bits-ui": "^2.15.4", "clsx": "^2.1.1", "drizzle-kit": "^0.31.1", "eslint": "^9.29.0", diff --git a/project.inlang/messages/de.json b/project.inlang/messages/de.json index 88f5c18..40b11e4 100644 --- a/project.inlang/messages/de.json +++ b/project.inlang/messages/de.json @@ -844,7 +844,8 @@ "description": "Nur Sie und {name} können diese Informationen sehen. Die Daten sind Ende-zu-Ende verschlüsselt." }, "email": { - "description": "Wir senden Ihnen eine Bestätigungs-E-Mail mit den Termindetails." + "notifyMe": "Benachrichtigen Sie mich über Änderungen per E-Mail", + "tooltip": "Wenn aktiviert, wird Ihre Mail vorübergehend im Logbuch des Mailservers auftauchen. Wenn deaktiviert müssen Sie sich auf dieser Seite Einloggen, um Änderungen einzusehen." }, "phone": { "description": "Format: +491234567890. {name} kontaktiert Sie ggf. telefonisch, falls es Fragen/Änderungen zu Ihrem Termin gibt.", diff --git a/project.inlang/messages/en.json b/project.inlang/messages/en.json index 824b680..2c6a877 100644 --- a/project.inlang/messages/en.json +++ b/project.inlang/messages/en.json @@ -853,7 +853,8 @@ "description": "Only you and {name} will be able to access this information. It is end-to-end encrypted." }, "email": { - "description": "We will use this to send you the appointment details." + "notifyMe": "Notify me of changes by e-mail", + "tooltip": "If enabled, your e-mail address will appear temporarily in server logs of the mailserver. If disabled, you will have to login on this page to check for updates." }, "phone": { "description": "Format: +1234567890. {name} may contact you by phone, if there are questions or changes regarding your appointment.", diff --git a/src/lib/client/appointment-crypto.ts b/src/lib/client/appointment-crypto.ts index 246d2c9..968a4e5 100644 --- a/src/lib/client/appointment-crypto.ts +++ b/src/lib/client/appointment-crypto.ts @@ -71,6 +71,7 @@ interface EncryptedData { export interface AppointmentData { name: string; email: string; + shareEmail: boolean; phone?: string; } @@ -319,7 +320,7 @@ export class UnifiedAppointmentCrypto { appointmentDate, duration, emailHash: this.emailHash, - clientEmail: appointmentData.email, + clientEmail: appointmentData.shareEmail ? appointmentData.email : undefined, clientLanguage, clientPublicKey: this.clientKeyPair?.publicKey, privateKeyShare: await this.getPrivateKeyShare(), @@ -336,7 +337,7 @@ export class UnifiedAppointmentCrypto { channelId, appointmentDate, duration, - clientEmail: appointmentData.email, + clientEmail: appointmentData.shareEmail ? appointmentData.email : undefined, clientLanguage, encryptedAppointment, }; diff --git a/src/lib/components/ui/checkbox-with-label/checkbox-with-label.svelte b/src/lib/components/ui/checkbox-with-label/checkbox-with-label.svelte index bcc9b61..86c2920 100644 --- a/src/lib/components/ui/checkbox-with-label/checkbox-with-label.svelte +++ b/src/lib/components/ui/checkbox-with-label/checkbox-with-label.svelte @@ -1,31 +1,50 @@ -