Compare commits
6 commits
081a1f90d3
...
a12e07ec1c
| Author | SHA1 | Date | |
|---|---|---|---|
| a12e07ec1c | |||
| ec62ba7673 | |||
| 258f6f5a17 | |||
| bce2447238 | |||
| c0c32b718b | |||
| 255095e6bd |
11 changed files with 718 additions and 36 deletions
|
|
@ -446,7 +446,7 @@ Gross margin: 14 SEK
|
|||
| Is a license plate personal data? | Yes (it directly identifies a vehicle owner). |
|
||||
| Is an address personal data? | Yes. |
|
||||
| What if we only process address transiently? | Data minimization is a GDPR principle (Art. 5(1)(c)). Transient processing with immediate deletion is a strong compliance posture. |
|
||||
| Do we need to inform the recipient? | Yes, GDPR Art. 14 requires informing the data subject. The letter itself can serve this purpose — include a footer like: _"Detta brev skickades via BilHej.se. Din adress hämtades från Transportstyrelsens fordonsregister och har raderats efter utskick. För frågor: hej@bilhalsning.se"_ |
|
||||
| Do we need to inform the recipient? | Yes, GDPR Art. 14 requires informing the data subject. The letter itself can serve this purpose — include a footer like: _"Detta brev skickades via BilHej.se. Din adress hämtades från Transportstyrelsens fordonsregister och har raderats efter utskick. För frågor: kontakt@bilhej.se"_ |
|
||||
|
||||
### 11.2 Transportstyrelsen Access
|
||||
|
||||
|
|
|
|||
|
|
@ -54,3 +54,30 @@ 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. 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. 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 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 |
|
||||
|---------|---------|-----------------|
|
||||
| `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.
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
})
|
||||
})
|
||||
|
|
|
|||
54
frontend/src/__tests__/PrivacyPolicyPage.spec.ts
Normal file
54
frontend/src/__tests__/PrivacyPolicyPage.spec.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
import { describe, it, expect } from 'vitest'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { createRouter, createMemoryHistory } from 'vue-router'
|
||||
import PrivacyPolicyPage from '@/pages/PrivacyPolicyPage.vue'
|
||||
|
||||
function createTestRouter() {
|
||||
return createRouter({
|
||||
history: createMemoryHistory(),
|
||||
routes: [
|
||||
{
|
||||
path: '/integritetspolicy',
|
||||
name: 'privacy',
|
||||
component: PrivacyPolicyPage,
|
||||
},
|
||||
{
|
||||
path: '/kontakt',
|
||||
name: 'contact',
|
||||
component: { template: '<div>Kontakt</div>' },
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
describe('PrivacyPolicyPage', () => {
|
||||
it('renders title and lead', () => {
|
||||
const router = createTestRouter()
|
||||
const wrapper = mount(PrivacyPolicyPage, {
|
||||
global: { plugins: [router] },
|
||||
})
|
||||
expect(wrapper.text()).toContain('Integritetspolicy')
|
||||
expect(wrapper.text()).toContain('personuppgifter')
|
||||
})
|
||||
|
||||
it('describes sender and recipient data handling', () => {
|
||||
const router = createTestRouter()
|
||||
const wrapper = mount(PrivacyPolicyPage, {
|
||||
global: { plugins: [router] },
|
||||
})
|
||||
expect(wrapper.text()).toContain('Mottagarens postadress')
|
||||
expect(wrapper.text()).toContain('sparas inte efter utskick')
|
||||
expect(wrapper.text()).toContain('varken vi eller obehöriga')
|
||||
})
|
||||
|
||||
it('links to contact email and contact page', () => {
|
||||
const router = createTestRouter()
|
||||
const wrapper = mount(PrivacyPolicyPage, {
|
||||
global: { plugins: [router] },
|
||||
})
|
||||
expect(wrapper.find('a[href="mailto:kontakt@bilhej.se"]').exists()).toBe(
|
||||
true,
|
||||
)
|
||||
expect(wrapper.find('a.policy__link').attributes('href')).toBe('/kontakt')
|
||||
})
|
||||
})
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
58
frontend/src/__tests__/TermsOfServicePage.spec.ts
Normal file
58
frontend/src/__tests__/TermsOfServicePage.spec.ts
Normal file
|
|
@ -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: '<div>Integritet</div>' },
|
||||
},
|
||||
{
|
||||
path: '/kontakt',
|
||||
name: 'contact',
|
||||
component: { template: '<div>Kontakt</div>' },
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
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,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
@ -29,10 +29,6 @@ const highlights = [
|
|||
Bilhej gör det enkelt att nå en bilägare med ett fysiskt brev. Du
|
||||
skriver meddelandet, vi sköter utskick och post.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="about__section">
|
||||
<h2 class="about__section-title">Vad vi gör</h2>
|
||||
<div class="about__prose">
|
||||
<p>
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,27 @@
|
|||
<script setup lang="ts">
|
||||
const contactChannels = [
|
||||
{
|
||||
variant: 'general',
|
||||
title: 'Frågor om tjänsten',
|
||||
variant: 'support',
|
||||
title: 'Support',
|
||||
description:
|
||||
'Beställningar, betalning, tekniska problem eller allmänna frågor om hur Bilhej fungerar.',
|
||||
'Beställningar, betalning via Swish, tekniska problem eller frågor om status och spårning.',
|
||||
email: 'support@bilhej.se',
|
||||
label: 'Skicka till support',
|
||||
},
|
||||
{
|
||||
variant: 'general',
|
||||
title: 'Allmän kontakt',
|
||||
description:
|
||||
'Övriga frågor om tjänsten, synpunkter som inte är klagomål, eller om du är osäker på vilken adress du ska använda.',
|
||||
email: 'kontakt@bilhej.se',
|
||||
label: 'Skicka e-post',
|
||||
},
|
||||
{
|
||||
variant: 'complaints',
|
||||
title: 'Klagomål och synpunkter',
|
||||
title: 'Klagomål',
|
||||
description:
|
||||
'Om något gått fel eller du vill lämna ett klagomål direkt till oss som driver tjänsten.',
|
||||
email: 'jcamorling@gmail.com',
|
||||
email: 'klagomal@bilhej.se',
|
||||
label: 'Skicka klagomål',
|
||||
},
|
||||
]
|
||||
|
|
@ -25,8 +33,8 @@ const contactChannels = [
|
|||
<p class="contact__eyebrow">Kontakt</p>
|
||||
<h1 class="contact__title">Kontakta oss</h1>
|
||||
<p class="contact__lead">
|
||||
Vi svarar så snart vi kan. Välj rätt adress beroende på om det gäller en
|
||||
vanlig fråga eller ett klagomål.
|
||||
Vi svarar så snart vi kan. Använd support för beställningar och tekniska
|
||||
frågor, kontakt för övrigt, eller klagomål-adressen om något gått fel.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
|
@ -40,14 +48,12 @@ const contactChannels = [
|
|||
>
|
||||
<h2>{{ channel.title }}</h2>
|
||||
<p>{{ channel.description }}</p>
|
||||
<a class="contact__email" :href="`mailto:${channel.email}`">
|
||||
{{ channel.email }}
|
||||
</a>
|
||||
<a
|
||||
class="btn btn--ghost contact__btn"
|
||||
class="contact__mailto"
|
||||
:href="`mailto:${channel.email}`"
|
||||
:aria-label="`${channel.label}: ${channel.email}`"
|
||||
>
|
||||
{{ channel.label }}
|
||||
{{ channel.email }}
|
||||
</a>
|
||||
</article>
|
||||
</div>
|
||||
|
|
@ -155,6 +161,10 @@ const contactChannels = [
|
|||
background: var(--contact-accent);
|
||||
}
|
||||
|
||||
.contact__card--support {
|
||||
--contact-accent: linear-gradient(90deg, #0f766e, #2dd4bf);
|
||||
}
|
||||
|
||||
.contact__card--general {
|
||||
--contact-accent: linear-gradient(90deg, #1d4ed8, #60a5fa);
|
||||
}
|
||||
|
|
@ -176,22 +186,24 @@ const contactChannels = [
|
|||
color: var(--color-muted);
|
||||
}
|
||||
|
||||
.contact__email {
|
||||
display: inline-block;
|
||||
margin-bottom: var(--space-md);
|
||||
.contact__mailto {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0.65rem 1rem;
|
||||
font-family: var(--font-sans);
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-primary);
|
||||
word-break: break-all;
|
||||
color: var(--color-primary-dark);
|
||||
background: var(--color-primary-soft);
|
||||
border: 1px solid #bfdbfe;
|
||||
border-radius: var(--radius-md);
|
||||
transition: background var(--transition-fast), border-color var(--transition-fast);
|
||||
}
|
||||
|
||||
.contact__email:hover {
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
.contact__btn {
|
||||
display: inline-flex;
|
||||
.contact__mailto:hover {
|
||||
background: #dbeafe;
|
||||
border-color: #93c5fd;
|
||||
color: var(--color-primary-dark);
|
||||
}
|
||||
|
||||
.contact__tips {
|
||||
|
|
|
|||
239
frontend/src/pages/PrivacyPolicyPage.vue
Normal file
239
frontend/src/pages/PrivacyPolicyPage.vue
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
<script setup lang="ts">
|
||||
import { RouterLink } from 'vue-router'
|
||||
|
||||
const sections = [
|
||||
{
|
||||
id: 'ansvarig',
|
||||
title: 'Personuppgiftsansvarig',
|
||||
paragraphs: [
|
||||
'Bilhej (bilhej.se) är personuppgiftsansvarig för den behandling som sker när du använder tjänsten som avsändare.',
|
||||
'Frågor om integritet: kontakt@bilhej.se. Klagomål som rör tjänsten: klagomal@bilhej.se.',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'vilka-uppgifter',
|
||||
title: 'Vilka uppgifter behandlar vi?',
|
||||
paragraphs: [
|
||||
'Kontouppgifter: e-postadress och lösenord. Lösenordet lagras så att varken vi eller obehöriga kan läsa det.',
|
||||
'Beställningar: registreringsnummer, brevtext, status, betalningsbelopp och eventuellt spårningsnummer kopplat till utskick.',
|
||||
'Fordonsuppgifter: märke och modell för att du ska kunna verifiera nummerplåten. Vi lagrar inte mottagarens namn eller adress i tjänsten.',
|
||||
'Mottagarens postadress används enbart för att posta brevet och sparas inte efter utskick.',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'varfor',
|
||||
title: 'Varför behandlar vi uppgifterna?',
|
||||
paragraphs: [
|
||||
'För att tillhandahålla tjänsten: konto, beställning, betalning och utskick av brev.',
|
||||
'För att uppfylla rättsliga skyldigheter, till exempel bokföring av betalningar där så krävs.',
|
||||
'För att skicka nödvändiga meddelanden till dig, till exempel återställning av lösenord.',
|
||||
'Mottagaren informeras i brevets fot om att brevet skickats via Bilhej och hur hen kan kontakta oss.',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'delning',
|
||||
title: 'Vem delar vi uppgifter med?',
|
||||
paragraphs: [
|
||||
'Leverantörer som hjälper oss att skicka e-post, ta emot supportmail och driva webbplatsen.',
|
||||
'Behörig myndighet och postoperatör i den utsträckning som krävs för att posta brevet till rätt mottagare.',
|
||||
'Offentliga fordonsregister när du verifierar registreringsnummer (endast fordonsdata, inte ägaruppgifter).',
|
||||
'Vi säljer inte personuppgifter och visar inte mottagarens identitet eller adress för dig som avsändare.',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'lagring',
|
||||
title: 'Hur länge sparar vi uppgifterna?',
|
||||
paragraphs: [
|
||||
'Kontouppgifter sparas tills du ber oss radera kontot.',
|
||||
'Beställningshistorik (nummerplåt, brevtext, status) sparas så att du kan se Mina beställningar och så att vi kan hantera support.',
|
||||
'Mottagarens adress sparas inte efter utskick.',
|
||||
'Lösenordsåterställning gäller under begränsad tid och upphör efter användning.',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'rattigheter',
|
||||
title: 'Dina rättigheter',
|
||||
paragraphs: [
|
||||
'Du kan begära tillgång till, rättelse eller radering av dina uppgifter, begränsa behandling eller invända mot viss behandling.',
|
||||
'Du kan begära radering av ditt konto genom att kontakta oss.',
|
||||
'Du har rätt att lämna klagomål till Integritetsskyddsmyndigheten (IMY), imy.se.',
|
||||
'Kontakta kontakt@bilhej.se för att utöva dina rättigheter. Vi svarar inom en månad om inte något annat anges.',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'mottagare',
|
||||
title: 'Om du fått ett brev via Bilhej',
|
||||
paragraphs: [
|
||||
'Din adress användes en gång för att posta brevet och ska ha raderats hos oss efter utskick.',
|
||||
'För frågor eller invändning mot att få brev via tjänsten: kontakt@bilhej.se. Ange registreringsnummer om du kan.',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'andringar',
|
||||
title: 'Ändringar',
|
||||
paragraphs: [
|
||||
'Vi kan uppdatera denna policy när tjänsten utvecklas. Datum för senaste version anges nedan.',
|
||||
],
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="policy">
|
||||
<section class="policy__hero">
|
||||
<p class="policy__eyebrow">Integritet</p>
|
||||
<h1 class="policy__title">Integritetspolicy</h1>
|
||||
<p class="policy__lead">
|
||||
Här beskriver vi hur Bilhej behandlar personuppgifter när du skickar brev
|
||||
via tjänsten, och vilka rättigheter du har.
|
||||
</p>
|
||||
<p class="policy__updated">Senast uppdaterad: 22 maj 2026</p>
|
||||
</section>
|
||||
|
||||
<section
|
||||
v-for="section in sections"
|
||||
:key="section.id"
|
||||
:id="section.id"
|
||||
class="policy__section"
|
||||
>
|
||||
<h2 class="policy__section-title">{{ section.title }}</h2>
|
||||
<div class="policy__prose">
|
||||
<p v-for="(paragraph, index) in section.paragraphs" :key="index">
|
||||
{{ paragraph }}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="policy__section policy__section--cta">
|
||||
<div class="policy__cta-box">
|
||||
<h2 class="policy__cta-title">Frågor om integritet?</h2>
|
||||
<p class="policy__cta-text">
|
||||
Hör av dig via
|
||||
<a class="policy__mailto" href="mailto:kontakt@bilhej.se"
|
||||
>kontakt@bilhej.se</a
|
||||
>
|
||||
eller vår
|
||||
<RouterLink to="/kontakt" class="policy__link">kontaktsida</RouterLink>.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.policy {
|
||||
max-width: 48rem;
|
||||
margin: 0 auto;
|
||||
padding: var(--space-3xl) var(--space-lg) var(--space-3xl);
|
||||
}
|
||||
|
||||
.policy__hero {
|
||||
margin-bottom: var(--space-2xl);
|
||||
padding: var(--space-2xl);
|
||||
background: linear-gradient(
|
||||
145deg,
|
||||
var(--color-surface) 0%,
|
||||
#f8faff 55%,
|
||||
var(--color-paper) 100%
|
||||
);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-xl);
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.policy__eyebrow {
|
||||
display: inline-block;
|
||||
margin: 0 0 var(--space-md) 0;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
color: var(--color-primary-dark);
|
||||
background: var(--color-primary-soft);
|
||||
border: 1px solid #bfdbfe;
|
||||
padding: 0.35rem 0.75rem;
|
||||
border-radius: var(--radius-full);
|
||||
}
|
||||
|
||||
.policy__title {
|
||||
margin: 0 0 var(--space-md) 0;
|
||||
font-size: clamp(1.75rem, 4vw, 2.25rem);
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.02em;
|
||||
color: var(--color-ink);
|
||||
}
|
||||
|
||||
.policy__lead {
|
||||
margin: 0 0 var(--space-md) 0;
|
||||
font-size: 1.0625rem;
|
||||
line-height: 1.75;
|
||||
color: var(--color-muted);
|
||||
}
|
||||
|
||||
.policy__updated {
|
||||
margin: 0;
|
||||
font-size: 0.8125rem;
|
||||
color: var(--color-soft);
|
||||
}
|
||||
|
||||
.policy__section {
|
||||
margin-bottom: var(--space-2xl);
|
||||
scroll-margin-top: var(--space-lg);
|
||||
}
|
||||
|
||||
.policy__section-title {
|
||||
margin: 0 0 var(--space-md) 0;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
color: var(--color-ink);
|
||||
}
|
||||
|
||||
.policy__prose p {
|
||||
margin: 0 0 var(--space-md) 0;
|
||||
font-size: 0.9375rem;
|
||||
line-height: 1.75;
|
||||
color: var(--color-muted);
|
||||
}
|
||||
|
||||
.policy__prose p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.policy__cta-box {
|
||||
padding: var(--space-xl);
|
||||
text-align: center;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
var(--color-primary-soft) 0%,
|
||||
#eef2ff 100%
|
||||
);
|
||||
border: 1px solid #bfdbfe;
|
||||
border-radius: var(--radius-xl);
|
||||
}
|
||||
|
||||
.policy__cta-title {
|
||||
margin: 0 0 var(--space-sm) 0;
|
||||
font-size: 1.25rem;
|
||||
color: var(--color-primary-dark);
|
||||
}
|
||||
|
||||
.policy__cta-text {
|
||||
margin: 0;
|
||||
font-size: 0.9375rem;
|
||||
line-height: 1.65;
|
||||
color: var(--color-primary-dark);
|
||||
}
|
||||
|
||||
.policy__mailto,
|
||||
.policy__link {
|
||||
font-weight: 600;
|
||||
color: var(--color-primary);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
.policy__mailto:hover,
|
||||
.policy__link:hover {
|
||||
color: var(--color-primary-dark);
|
||||
}
|
||||
</style>
|
||||
258
frontend/src/pages/TermsOfServicePage.vue
Normal file
258
frontend/src/pages/TermsOfServicePage.vue
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
<script setup lang="ts">
|
||||
import { RouterLink } from 'vue-router'
|
||||
|
||||
const sections = [
|
||||
{
|
||||
id: 'tjansten',
|
||||
title: 'Tjänsten',
|
||||
paragraphs: [
|
||||
'Bilhej (bilhej.se) är en tjänst där du som avsändare kan beställa utskick av ett fysiskt brev till en fordonsägare via registreringsnummer. Vi är mellanhand för att posta brevet. Vi är inte part i innehållet mellan dig och mottagaren.',
|
||||
'Genom att skapa konto, beställa eller betala accepterar du dessa villkor.',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'konto',
|
||||
title: 'Konto',
|
||||
paragraphs: [
|
||||
'Du ansvarar för att uppgifterna i ditt konto stämmer och att ditt lösenord hålls hemligt.',
|
||||
'Du måste vara minst 18 år, eller ha målsmans tillstånd, för att använda tjänsten.',
|
||||
'Vi får stänga av eller avsluta konton som bryter mot villkoren eller missbrukar tjänsten.',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'bestallning',
|
||||
title: 'Beställning och betalning',
|
||||
paragraphs: [
|
||||
'Priset för ett brev framgår i tjänsten (för närvarande 49 kr). Betalning sker via Swish enligt instruktionerna i beställningsflödet.',
|
||||
'Du ser hela brevet innan du betalar. Kontrollera registreringsnummer och text noga.',
|
||||
'Obetalda beställningar kan redigeras eller avbrytas i Mina beställningar. Efter betalning behandlas beställningen för utskick.',
|
||||
'Vi kan avvisa eller stoppa beställningar med olagligt, kränkande, hotfullt eller uppenbart missbrukande innehåll. Betald avgift återbetalas i så fall om utskick inte hunnit ske.',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'innehåll',
|
||||
title: 'Innehåll i brevet',
|
||||
paragraphs: [
|
||||
'Du ansvarar själv för texten du skickar. Brevet ska vara respektfullt och följa svensk lag.',
|
||||
'Du får inte använda tjänsten för trakasserier, hot, olaglig reklam, spridning av personuppgifter om tredje man, eller annat otillbörligt innehåll.',
|
||||
'Om du anger kontaktuppgifter i brevet kan mottagaren svara dig direkt. Annars är avsändaren anonym gentemot mottagaren.',
|
||||
'Du garanterar att du har rätt att skicka innehållet och ger oss rätt att skriva ut och posta brevet en gång för att fullgöra beställningen.',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'utskick',
|
||||
title: 'Utskick och leverans',
|
||||
paragraphs: [
|
||||
'Efter betalning hanterar vi utskick av brevet. Det sker normalt inom några vardagar, men exakt tid kan variera.',
|
||||
'Vi garanterar inte att mottagaren läser eller svarar på brevet.',
|
||||
'När spårning finns tillgänglig visas den i Mina beställningar. Postens leveranstider ligger utanför vår kontroll.',
|
||||
'Om registreringsnumret är felaktigt eller mottagaren inte kan nås kan utskick misslyckas. Kontakta support@bilhej.se så hjälper vi dig.',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'reklamation',
|
||||
title: 'Reklamation och återbetalning',
|
||||
paragraphs: [
|
||||
'Har något blivit fel? Kontakta support@bilhej.se så snart som möjligt och ange beställnings-ID.',
|
||||
'Om brevet inte skickats kan vi i normalfallet återbetala eller korrigera beställningen.',
|
||||
'Efter att brevet postats kan återbetalning normalt inte ske, eftersom tjänsten då är utförd.',
|
||||
'Som konsument har du enligt lag rätt att reklamera fel i tjänsten inom tre år. Kontakta oss först så löser vi det i god tro.',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'ansvar',
|
||||
title: 'Ansvar',
|
||||
paragraphs: [
|
||||
'Tjänsten tillhandahålls i befintligt skick. Vi ansvarar inte för indirekta skador, utebliven vinst eller följder av innehållet i brev du skrivit.',
|
||||
'Vårt ansvar gentemot dig som konsument begränsas inte i strid med tvingande lag.',
|
||||
'Du håller Bilhej skadeslöst från krav från tredje part som beror på ditt innehåll eller ditt brott mot dessa villkor, i den utsträckning lagen tillåter.',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'integritet',
|
||||
title: 'Personuppgifter',
|
||||
paragraphs: [],
|
||||
},
|
||||
{
|
||||
id: 'andringar',
|
||||
title: 'Ändringar av villkoren',
|
||||
paragraphs: [
|
||||
'Vi kan uppdatera villkoren när tjänsten ändras. Fortsatt användning efter att ändringar publicerats innebär att du accepterar de uppdaterade villkoren.',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'tvist',
|
||||
title: 'Tillämplig lag och kontakt',
|
||||
paragraphs: [
|
||||
'Svensk lag gäller för dessa villkor. Tvister ska i första hand lösas i samförstånd. Konsument kan vända sig till Allmänna reklamationsnämnden (arn.se).',
|
||||
'Frågor om tjänsten: support@bilhej.se. Allmän kontakt: kontakt@bilhej.se. Klagomål: klagomal@bilhej.se.',
|
||||
],
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="terms">
|
||||
<section class="terms__hero">
|
||||
<p class="terms__eyebrow">Villkor</p>
|
||||
<h1 class="terms__title">Användarvillkor</h1>
|
||||
<p class="terms__lead">
|
||||
Villkor för att använda Bilhej när du beställer utskick av brev till
|
||||
fordonsägare.
|
||||
</p>
|
||||
<p class="terms__updated">Senast uppdaterad: 22 maj 2026</p>
|
||||
</section>
|
||||
|
||||
<section
|
||||
v-for="section in sections"
|
||||
:key="section.id"
|
||||
:id="section.id"
|
||||
class="terms__section"
|
||||
>
|
||||
<h2 class="terms__section-title">{{ section.title }}</h2>
|
||||
<div class="terms__prose">
|
||||
<p v-if="section.id === 'integritet'">
|
||||
Vi behandlar personuppgifter enligt vår
|
||||
<RouterLink to="/integritetspolicy" class="terms__link"
|
||||
>integritetspolicy</RouterLink
|
||||
>.
|
||||
</p>
|
||||
<p v-for="(paragraph, index) in section.paragraphs" :key="index">
|
||||
{{ paragraph }}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="terms__section terms__section--cta">
|
||||
<div class="terms__cta-box">
|
||||
<h2 class="terms__cta-title">Frågor om villkoren?</h2>
|
||||
<p class="terms__cta-text">
|
||||
Hör av dig via
|
||||
<a class="terms__mailto" href="mailto:support@bilhej.se"
|
||||
>support@bilhej.se</a
|
||||
>
|
||||
eller vår
|
||||
<RouterLink to="/kontakt" class="terms__link">kontaktsida</RouterLink>.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.terms {
|
||||
max-width: 48rem;
|
||||
margin: 0 auto;
|
||||
padding: var(--space-3xl) var(--space-lg) var(--space-3xl);
|
||||
}
|
||||
|
||||
.terms__hero {
|
||||
margin-bottom: var(--space-2xl);
|
||||
padding: var(--space-2xl);
|
||||
background: linear-gradient(
|
||||
145deg,
|
||||
var(--color-surface) 0%,
|
||||
#f8faff 55%,
|
||||
var(--color-paper) 100%
|
||||
);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-xl);
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.terms__eyebrow {
|
||||
display: inline-block;
|
||||
margin: 0 0 var(--space-md) 0;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
color: var(--color-primary-dark);
|
||||
background: var(--color-primary-soft);
|
||||
border: 1px solid #bfdbfe;
|
||||
padding: 0.35rem 0.75rem;
|
||||
border-radius: var(--radius-full);
|
||||
}
|
||||
|
||||
.terms__title {
|
||||
margin: 0 0 var(--space-md) 0;
|
||||
font-size: clamp(1.75rem, 4vw, 2.25rem);
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.02em;
|
||||
color: var(--color-ink);
|
||||
}
|
||||
|
||||
.terms__lead {
|
||||
margin: 0 0 var(--space-md) 0;
|
||||
font-size: 1.0625rem;
|
||||
line-height: 1.75;
|
||||
color: var(--color-muted);
|
||||
}
|
||||
|
||||
.terms__updated {
|
||||
margin: 0;
|
||||
font-size: 0.8125rem;
|
||||
color: var(--color-soft);
|
||||
}
|
||||
|
||||
.terms__section {
|
||||
margin-bottom: var(--space-2xl);
|
||||
scroll-margin-top: var(--space-lg);
|
||||
}
|
||||
|
||||
.terms__section-title {
|
||||
margin: 0 0 var(--space-md) 0;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
color: var(--color-ink);
|
||||
}
|
||||
|
||||
.terms__prose p {
|
||||
margin: 0 0 var(--space-md) 0;
|
||||
font-size: 0.9375rem;
|
||||
line-height: 1.75;
|
||||
color: var(--color-muted);
|
||||
}
|
||||
|
||||
.terms__prose p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.terms__cta-box {
|
||||
padding: var(--space-xl);
|
||||
text-align: center;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
var(--color-primary-soft) 0%,
|
||||
#eef2ff 100%
|
||||
);
|
||||
border: 1px solid #bfdbfe;
|
||||
border-radius: var(--radius-xl);
|
||||
}
|
||||
|
||||
.terms__cta-title {
|
||||
margin: 0 0 var(--space-sm) 0;
|
||||
font-size: 1.25rem;
|
||||
color: var(--color-primary-dark);
|
||||
}
|
||||
|
||||
.terms__cta-text {
|
||||
margin: 0;
|
||||
font-size: 0.9375rem;
|
||||
line-height: 1.65;
|
||||
color: var(--color-primary-dark);
|
||||
}
|
||||
|
||||
.terms__mailto,
|
||||
.terms__link {
|
||||
font-weight: 600;
|
||||
color: var(--color-primary);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
.terms__mailto:hover,
|
||||
.terms__link:hover {
|
||||
color: var(--color-primary-dark);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -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,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue