Många situationer i trafiken eller på parkeringen är enklare att lösa
@@ -126,12 +122,17 @@ const highlights = [
}
.about__lead {
- margin: 0;
+ margin: 0 0 var(--space-lg) 0;
font-size: 1.0625rem;
line-height: 1.75;
color: var(--color-muted);
}
+.about__prose {
+ padding-top: var(--space-lg);
+ border-top: 1px solid var(--color-border);
+}
+
.about__section {
margin-bottom: var(--space-2xl);
}
From bce24472383e5f6ab5faccd3eebfd7c0f29c2bcb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Joakim=20M=C3=B6rling?=
Date: Fri, 22 May 2026 13:51:20 +0200
Subject: [PATCH 3/6] Rework contact page emails and simplify mailto actions.
- Add support@bilhej.se for orders and technical issues
- Move complaints to klagomal@bilhej.se instead of personal Gmail
- Show one mailto chip per card instead of duplicate link and button
- Update ContactPage tests and production email checklist for all @bilhej.se addresses
Co-authored-by: Cursor
---
docs/production-email-checklist.md | 16 ++++--
frontend/src/__tests__/ContactPage.spec.ts | 21 +++++---
frontend/src/pages/ContactPage.vue | 60 +++++++++++++---------
3 files changed, 62 insertions(+), 35 deletions(-)
diff --git a/docs/production-email-checklist.md b/docs/production-email-checklist.md
index aed77fa..fa4580f 100644
--- a/docs/production-email-checklist.md
+++ b/docs/production-email-checklist.md
@@ -55,23 +55,29 @@ Fallback: reset links still log when `MAIL_HOST` is empty.
Keep using Mailpit (`docker compose up`, http://localhost:8025). Do not point local Docker at
Resend unless you intend to send real mail.
-## 5. Contact email (`kontakt@bilhej.se`)
+## 5. Inbound email on bilhej.se
Inbound mail uses **Resend Receiving** on the root domain `bilhej.se`. No mailbox is created in
-Strato; the MX record routes all `@bilhej.se` addresses to Resend.
+Strato; the MX record routes all `@bilhej.se` addresses to Resend. You do not create each address
+separately in Resend.
**Setup (done once):**
1. Resend → **Domains** → `bilhej.se` → enable **Receiving**
2. Strato → **DNS** → add the receiving MX record (e.g. `inbound-smtp.eu-west-1.amazonaws.com`)
3. Wait until Resend shows receiving as **Verified**
-4. Send a test mail to `kontakt@bilhej.se` and confirm it appears under **Emails → Receiving**
+4. Send test mail to `support@bilhej.se` and `kontakt@bilhej.se`; confirm both appear under **Emails → Receiving**
**Reading mail:** open the [Resend Receiving inbox](https://resend.com/emails/receiving). There is
no automatic forward to Gmail unless you add a webhook handler later.
| Address | Purpose | Where mail goes |
|---------|---------|-----------------|
-| `kontakt@bilhej.se` | General questions (site, orders, support) | Resend dashboard |
-| `jcamorling@gmail.com` | Complaints (shown on `/kontakt` only) | Gmail directly |
+| `support@bilhej.se` | Orders, Swish, status, technical issues | Resend dashboard |
+| `kontakt@bilhej.se` | General contact, printed letter footer | Resend dashboard |
+| `klagomal@bilhej.se` | Complaints (shown on `/kontakt`) | Resend dashboard |
| `noreply@bilhej.se` | Outbound only (password reset) | Not an inbox |
+
+**Optional later (same Resend inbox, no extra DNS):** `abuse@bilhej.se` if you want a published
+address for misuse reports; `privacy@bilhej.se` if integritetspolicy asks for a dedicated
+data-protection contact.
diff --git a/frontend/src/__tests__/ContactPage.spec.ts b/frontend/src/__tests__/ContactPage.spec.ts
index 86f39f2..30e922b 100644
--- a/frontend/src/__tests__/ContactPage.spec.ts
+++ b/frontend/src/__tests__/ContactPage.spec.ts
@@ -9,17 +9,26 @@ describe('ContactPage', () => {
expect(wrapper.text()).toContain('klagomål')
})
- it('renders general support email', () => {
+ it('renders support email', () => {
const wrapper = mount(ContactPage)
- const link = wrapper.find('a[href="mailto:kontakt@bilhej.se"]')
- expect(link.exists()).toBe(true)
- expect(link.text()).toBe('kontakt@bilhej.se')
+ expect(wrapper.text()).toContain('support@bilhej.se')
+ })
+
+ it('renders general contact email', () => {
+ const wrapper = mount(ContactPage)
+ expect(wrapper.text()).toContain('kontakt@bilhej.se')
})
it('renders complaints email', () => {
const wrapper = mount(ContactPage)
- const link = wrapper.find('a[href="mailto:jcamorling@gmail.com"]')
+ expect(wrapper.text()).toContain('klagomal@bilhej.se')
+ })
+
+ it('links support to mailto', () => {
+ const wrapper = mount(ContactPage)
+ const link = wrapper.find('a[href="mailto:support@bilhej.se"]')
expect(link.exists()).toBe(true)
- expect(wrapper.text()).toContain('jcamorling@gmail.com')
+ expect(link.text()).toBe('support@bilhej.se')
+ expect(link.attributes('aria-label')).toBe('Skicka till support: support@bilhej.se')
})
})
diff --git a/frontend/src/pages/ContactPage.vue b/frontend/src/pages/ContactPage.vue
index e3ba60e..462fed1 100644
--- a/frontend/src/pages/ContactPage.vue
+++ b/frontend/src/pages/ContactPage.vue
@@ -1,19 +1,27 @@
+
+
+
+
+ Integritet
+ Integritetspolicy
+
+ Här beskriver vi hur Bilhej behandlar personuppgifter när du skickar brev
+ via tjänsten, och vilka rättigheter du har.
+
+ Senast uppdaterad: 22 maj 2026
+
+
+
+ {{ section.title }}
+
+
+
+
+
+
Frågor om integritet?
+
+ Hör av dig via
+ kontakt@bilhej.se
+ eller vår
+ kontaktsida.
+
+
+
+
+
+
+
From ec62ba7673aa449d6364734752fad5eb8e44c85d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Joakim=20M=C3=B6rling?=
Date: Fri, 22 May 2026 13:51:20 +0200
Subject: [PATCH 5/6] =?UTF-8?q?Add=20anv=C3=A4ndarvillkor=20page=20for=20B?=
=?UTF-8?q?ilhej=20service=20terms.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Create TermsOfServicePage covering Swish payment, letter content rules, and liability
- Describe edit/cancel before payment and refund expectations after posting
- Link to integritetspolicy and support contact in footer CTA
- Add TermsOfServicePage unit tests
Co-authored-by: Cursor
---
.../src/__tests__/TermsOfServicePage.spec.ts | 58 ++++
frontend/src/pages/TermsOfServicePage.vue | 258 ++++++++++++++++++
2 files changed, 316 insertions(+)
create mode 100644 frontend/src/__tests__/TermsOfServicePage.spec.ts
create mode 100644 frontend/src/pages/TermsOfServicePage.vue
diff --git a/frontend/src/__tests__/TermsOfServicePage.spec.ts b/frontend/src/__tests__/TermsOfServicePage.spec.ts
new file mode 100644
index 0000000..c21e0b2
--- /dev/null
+++ b/frontend/src/__tests__/TermsOfServicePage.spec.ts
@@ -0,0 +1,58 @@
+import { describe, it, expect } from 'vitest'
+import { mount } from '@vue/test-utils'
+import { createRouter, createMemoryHistory } from 'vue-router'
+import TermsOfServicePage from '@/pages/TermsOfServicePage.vue'
+
+function createTestRouter() {
+ return createRouter({
+ history: createMemoryHistory(),
+ routes: [
+ {
+ path: '/villkor',
+ name: 'terms',
+ component: TermsOfServicePage,
+ },
+ {
+ path: '/integritetspolicy',
+ name: 'privacy',
+ component: { template: 'Integritet
' },
+ },
+ {
+ path: '/kontakt',
+ name: 'contact',
+ component: { template: 'Kontakt
' },
+ },
+ ],
+ })
+}
+
+describe('TermsOfServicePage', () => {
+ it('renders title and lead', () => {
+ const router = createTestRouter()
+ const wrapper = mount(TermsOfServicePage, {
+ global: { plugins: [router] },
+ })
+ expect(wrapper.text()).toContain('Användarvillkor')
+ expect(wrapper.text()).toContain('49 kr')
+ })
+
+ it('describes payment and order rules', () => {
+ const router = createTestRouter()
+ const wrapper = mount(TermsOfServicePage, {
+ global: { plugins: [router] },
+ })
+ expect(wrapper.text()).toContain('Swish')
+ expect(wrapper.text()).toContain('Obetalda beställningar kan redigeras')
+ })
+
+ it('links to privacy policy and support email', () => {
+ const router = createTestRouter()
+ const wrapper = mount(TermsOfServicePage, {
+ global: { plugins: [router] },
+ })
+ expect(wrapper.find('a[href="/integritetspolicy"]').exists()).toBe(true)
+ expect(wrapper.find('a[href="mailto:support@bilhej.se"]').exists()).toBe(
+ true,
+ )
+ })
+})
diff --git a/frontend/src/pages/TermsOfServicePage.vue b/frontend/src/pages/TermsOfServicePage.vue
new file mode 100644
index 0000000..505eeb6
--- /dev/null
+++ b/frontend/src/pages/TermsOfServicePage.vue
@@ -0,0 +1,258 @@
+
+
+
+
+
+ Villkor
+ Användarvillkor
+
+ Villkor för att använda Bilhej när du beställer utskick av brev till
+ fordonsägare.
+
+ Senast uppdaterad: 22 maj 2026
+
+
+
+ {{ section.title }}
+
+
+ Vi behandlar personuppgifter enligt vår
+ integritetspolicy.
+
+
+ {{ paragraph }}
+
+
+
+
+
+
+
Frågor om villkoren?
+
+ Hör av dig via
+ support@bilhej.se
+ eller vår
+ kontaktsida.
+
+
+
+
+
+
+
From a12e07ec1c210c049bd5321f7ca4be7821c365cc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Joakim=20M=C3=B6rling?=
Date: Fri, 22 May 2026 13:51:20 +0200
Subject: [PATCH 6/6] Register routes for integritetspolicy and villkor legal
pages.
- Add /integritetspolicy and /villkor to Vue Router
- Add Router tests confirming both public legal routes resolve
Co-authored-by: Cursor
---
frontend/src/__tests__/Router.spec.ts | 12 ++++++++++++
frontend/src/router/index.ts | 12 ++++++++++++
2 files changed, 24 insertions(+)
diff --git a/frontend/src/__tests__/Router.spec.ts b/frontend/src/__tests__/Router.spec.ts
index 257431a..3a5f1de 100644
--- a/frontend/src/__tests__/Router.spec.ts
+++ b/frontend/src/__tests__/Router.spec.ts
@@ -32,6 +32,18 @@ describe('Router', () => {
expect(router.currentRoute.value.name).toBe('forgot-password')
})
+ it('resolves /integritetspolicy to PrivacyPolicyPage', async () => {
+ await router.push('/integritetspolicy')
+ await router.isReady()
+ expect(router.currentRoute.value.name).toBe('privacy')
+ })
+
+ it('resolves /villkor to TermsOfServicePage', async () => {
+ await router.push('/villkor')
+ await router.isReady()
+ expect(router.currentRoute.value.name).toBe('terms')
+ })
+
it('resolves /aterstall-losenord to ResetPasswordPage', async () => {
await router.push('/aterstall-losenord?token=abc')
await router.isReady()
diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts
index 86fa1d2..3ec2a98 100644
--- a/frontend/src/router/index.ts
+++ b/frontend/src/router/index.ts
@@ -3,6 +3,8 @@ import HomePage from '@/pages/HomePage.vue'
import ComposePage from '@/pages/ComposePage.vue'
import AboutPage from '@/pages/AboutPage.vue'
import ContactPage from '@/pages/ContactPage.vue'
+import PrivacyPolicyPage from '@/pages/PrivacyPolicyPage.vue'
+import TermsOfServicePage from '@/pages/TermsOfServicePage.vue'
import RegisterPage from '@/pages/RegisterPage.vue'
import LoginPage from '@/pages/LoginPage.vue'
import ForgotPasswordPage from '@/pages/ForgotPasswordPage.vue'
@@ -97,6 +99,16 @@ const router = createRouter({
name: 'contact',
component: ContactPage,
},
+ {
+ path: '/integritetspolicy',
+ name: 'privacy',
+ component: PrivacyPolicyPage,
+ },
+ {
+ path: '/villkor',
+ name: 'terms',
+ component: TermsOfServicePage,
+ },
],
})