From ecd45588e9ae007221df2ae076a09427b7e37235 Mon Sep 17 00:00:00 2001 From: Ovidiu U Date: Thu, 14 May 2026 17:43:53 +0100 Subject: [PATCH] Add legal policy pages and shared layout component - Add Cookie Policy view documenting essential cookies (session, CSRF, remember_me, fa_location) and cookieless Umami analytics - Add Privacy Policy view covering UK GDPR compliance, data categories, lawful bases, processors, retention, and user rights - Add Refund & Cancellation Policy view explaining 14-day cooling-off period under Consumer Contracts Regulations 2013 and express-consent flow - Add Terms of Service view defining account rules, subscription billing, and governing law - Create shared legal layout component with FuelAlert header, footer with cross-links, and consistent typography - Add feature tests covering all four legal pages and their cross-links - All policies include placeholders for ICO registration number, email, and hosting/email providers pending production config --- docs/superpowers/specs/legal-pages-spec.md | 403 ++++++++++++++++++ resources/js/views/Home.vue | 7 +- .../views/components/layouts/legal.blade.php | 53 +++ resources/views/legal/cookies.blade.php | 112 +++++ resources/views/legal/privacy.blade.php | 205 +++++++++ resources/views/legal/refund.blade.php | 110 +++++ resources/views/legal/terms.blade.php | 221 ++++++++++ routes/web.php | 8 + tests/Feature/LegalPagesTest.php | 54 +++ 9 files changed, 1170 insertions(+), 3 deletions(-) create mode 100644 docs/superpowers/specs/legal-pages-spec.md create mode 100644 resources/views/components/layouts/legal.blade.php create mode 100644 resources/views/legal/cookies.blade.php create mode 100644 resources/views/legal/privacy.blade.php create mode 100644 resources/views/legal/refund.blade.php create mode 100644 resources/views/legal/terms.blade.php create mode 100644 tests/Feature/LegalPagesTest.php diff --git a/docs/superpowers/specs/legal-pages-spec.md b/docs/superpowers/specs/legal-pages-spec.md new file mode 100644 index 0000000..0d33d9b --- /dev/null +++ b/docs/superpowers/specs/legal-pages-spec.md @@ -0,0 +1,403 @@ +# FuelAlert — Legal Pages Spec + +## Context for Claude Code + +You are generating four legal pages for **FuelAlert**, a UK consumer subscription web/mobile app that shows real-time UK fuel prices and forecasts. + +### Reference comparable (structural check, NOT for copying) + +A near-identical business already exists and has competent legal pages: **Fuel Finder UK** at https://www.fuel-finder.uk, operated by Scott Benson as a UK sole trader. Same business model, same data sources, same jurisdiction. + +**Use it ONLY as a structural sanity check.** Do not copy any text. Their content is copyrighted and their specific processors / retention periods / business decisions are not FuelAlert's. + +What Fuel Finder UK does well that this spec already incorporates: +- Explicit sole trader disclosure naming the operator +- Named ICO registration number in the Privacy Policy +- Specific named processors (Stripe, hosting provider, email provider, analytics, mapping services) with what data flows to each +- Strong price-accuracy disclaimer in Terms ("prices may not reflect real-time changes, always verify at the pump") +- "AS IS" / "AS AVAILABLE" basis with liability limitations +- ICO complaint route clearly stated +- Account deletion flow that cancels paid subscription first + +What FuelAlert must do BETTER than Fuel Finder UK: +- **Standalone Refund & Cancellation Policy page** — Fuel Finder UK appears to bundle this into Terms. Stripe specifically asks for a refund policy; keep it as a separate page at `/legal/refund`. +- **Express-consent checkbox at subscription checkout** for the 14-day cooling-off period under Consumer Contracts Regulations 2013 (see Refund Policy section below). This is the single most important implementation detail in the entire spec. + +If you find yourself generating content that overlaps verbatim with Fuel Finder UK or any other site, stop and rewrite in your own words. Legal pages are copyrighted works. + +**Business operator (data controller):** +- Name: Ovidiu Ungureanu +- Trading as: FuelAlert +- Status: Sole trader (not a limited company — do not use "Ltd", "Limited", or any corporate form) +- Location: Peterborough, United Kingdom +- Contact email: [hello@fuelalert.co.uk] +- ICO registration number: [PLACEHOLDER: ZAxxxxxxx — Ovidiu to register at ico.org.uk before launch, fee ~£40/yr] + +**Service:** +- UK fuel price comparison and forecasting +- Free tier + two paid subscription tiers: Daily (£0.99/mo) and Smart (£2.49/mo); annual billing also offered +- Data sources: UK government Fuel Finder / Pump Watch open data, ONS Postcode Directory (OGL/Crown Copyright) +- Processes: email address, postcode/location data, account credentials, payment data (via Stripe), usage telemetry + +**Jurisdiction:** +- England and Wales +- Consumer law: Consumer Rights Act 2015, Consumer Contracts (Information, Cancellation and Additional Charges) Regulations 2013 ("CCRs") +- Data protection: UK GDPR + Data Protection Act 2018, PECR for cookies/marketing +- Digital markets: Digital Markets, Competition and Consumers Act 2024 ("DMCC") + +**Tech stack & integration:** +- Laravel + Blade for server-rendered pages (NOT Vue components — these must render in raw HTML for Stripe reviewers and SEO) +- Route prefix: `/legal/*` +- Layout: extend the existing site layout but with a readable prose container (max-width ~720px, generous line-height) +- Each page has a `last_updated` date in front matter — set to today +- All pages must be linkable from the footer and accessible without JavaScript + +### ⚠️ CRITICAL: Server-rendered Blade only, NOT Vue + +The rest of this application is a Vue SPA. **That is irrelevant for these pages.** The legal pages must be server-rendered Blade templates. + +Rules: +- Files live at `resources/views/legal/{name}.blade.php` — never `.vue` +- Body content must be plain HTML with Blade directives (`@extends`, `@section`, `{{ }}`) +- No Vue components anywhere in the page body — no custom tags like ``, no `
`, no Vue mounting points +- No client-side rendering for the legal content itself — Alpine.js is acceptable only for the cookie banner show/hide behaviour, nothing else +- Pages must work fully with JavaScript disabled + +**Verification test (run after generation):** + +```bash +curl -s https://[host]/legal/privacy | grep -i "data controller" +curl -s https://[host]/legal/terms | grep -i "subscription" +curl -s https://[host]/legal/refund | grep -i "14-day" +curl -s https://[host]/legal/cookies | grep -i "essential" +``` + +Each command must return matching lines from the raw HTML response. If any returns empty, the page has been built as a client-rendered component and must be redone as Blade. + +If you find yourself reaching for ` + + diff --git a/resources/views/legal/cookies.blade.php b/resources/views/legal/cookies.blade.php new file mode 100644 index 0000000..e3dc4dc --- /dev/null +++ b/resources/views/legal/cookies.blade.php @@ -0,0 +1,112 @@ +{{-- DRAFT: Generated {{ date('Y-m-d') }}. Review by UK-qualified solicitor recommended before launch. --}} + + +
+

1. What cookies are

+

+ Cookies are small text files placed on your device by websites you visit. They allow a + site to remember things between visits (for example, that you're signed in) and to + measure how the site is used. This policy explains how FuelAlert uses cookies and + similar technologies, and how you can manage them. +

+
+ +
+

2. Cookies we use

+

+ FuelAlert uses only essential cookies — cookies that are strictly + necessary to deliver the service you've asked for. Under the Privacy and Electronic + Communications Regulations (PECR), these do not require your consent, but we list them + here for transparency. +

+

+ For aggregated usage metrics we run our own self-hosted instance of + Umami Analytics, which is cookieless — it does + not set any cookies, does not use device fingerprinting, and does not track you across + sites. Because no personal data is collected, no consent is required. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NamePurposeDurationType
fuel_alert_sessionKeeps you signed in and maintains your session state.SessionEssential
XSRF-TOKENProtects against cross-site request forgery attacks on forms and account actions.SessionEssential
remember_web_*"Remember me" — keeps you signed in across browser restarts if you tick the box at login.Up to 5 yearsEssential
fa_locationStores your most recent postcode search so we can show local prices on return visits without re-querying.30 daysEssential
+
+ +

+ [PLACEHOLDER: Update the table above if any cookie names change. If a + marketing tool is added in future, a Marketing row will be added here and consent will + be requested before it loads.] +

+
+ +
+

3. Your choices

+

+ Because we currently only use essential cookies, there is nothing to opt in or out of + on FuelAlert at this time. If we add non-essential cookies in future (for example, + analytics or marketing), we will present a consent banner and you will be able to + accept, reject, or customise your choice. We will not set non-essential cookies before + you have given consent. +

+

+ All major browsers also let you view, block, or delete cookies. The ICO publishes + guidance on managing cookies in your browser: + ico.org.uk · managing cookies. + Note that blocking essential cookies will prevent you from signing in. +

+
+ +
+

4. Changes to this policy

+

+ We may update this policy if we add new cookies, change our providers, or in response to + legal or guidance changes. Material changes will be highlighted by an updated + "Last updated" date at the top of this page. +

+
+ +
+

5. Contact

+

+ Questions about cookies? Email + [PLACEHOLDER: hello@fuelalert.co.uk]. +

+
+
diff --git a/resources/views/legal/privacy.blade.php b/resources/views/legal/privacy.blade.php new file mode 100644 index 0000000..dd08c7c --- /dev/null +++ b/resources/views/legal/privacy.blade.php @@ -0,0 +1,205 @@ +{{-- DRAFT: Generated {{ date('Y-m-d') }}. Review by UK-qualified solicitor recommended before launch. --}} + + +
+

1. Who we are

+

+ FuelAlert is a trading name of Ovidiu Ungureanu, a sole trader based in + Peterborough, United Kingdom. For the purposes of UK data protection law, Ovidiu Ungureanu + is the data controller for personal data collected through this service. +

+

+ We are registered with the UK Information Commissioner's Office (ICO). + Our registration number is [PLACEHOLDER: ICO registration number ZAxxxxxxx]. +

+

+ If you have any questions about this policy or how we handle your personal data, contact us at + [PLACEHOLDER: hello@fuelalert.co.uk]. +

+
+ +
+

2. What data we collect

+ +

Account data

+

Your email address, a hashed password, and the date you created your account.

+ +

Location data

+

+ Postcodes or place names you search for. With your permission, your device's precise + location to find nearby stations. Derived approximate location used to query our database. +

+ +

Payment data

+

+ Payment card details are collected and processed by Stripe, our payment + processor. FuelAlert does not see, store, or otherwise have access to your card numbers. + We retain only your Stripe customer ID and subscription metadata (plan, billing cycle, + renewal date). +

+ +

Usage data

+

+ Features you use, queries you make, and alerts you configure — used to deliver the + service and improve it. +

+ +

Technical data

+

+ IP address, browser type and version, device type, and operating system — used for + security, fraud prevention, and basic analytics. +

+ +

Marketing preferences

+

Only collected if you opt in to marketing communications.

+
+ +
+

3. Lawful basis for processing

+

We process your personal data under the following bases of UK GDPR Article 6:

+
    +
  • Account creation and service delivery — contract (Art. 6(1)(b)).
  • +
  • Payment processing — contract (Art. 6(1)(b)).
  • +
  • Security and fraud prevention — legitimate interests (Art. 6(1)(f)).
  • +
  • Analytics and product improvement — legitimate interests, with opt-out via our cookie banner where applicable.
  • +
  • Marketing emails — consent (Art. 6(1)(a)). You can withdraw consent at any time.
  • +
+
+ +
+

4. How we use your data

+
    +
  • To create and operate your account (contract).
  • +
  • To deliver fuel price information and alerts you have configured (contract).
  • +
  • To process subscription payments via Stripe (contract).
  • +
  • To keep our service secure and prevent abuse (legitimate interests).
  • +
  • To understand which features are used and improve the product (legitimate interests).
  • +
  • To respond to your support enquiries (contract / legitimate interests).
  • +
  • To send marketing emails if you have opted in (consent).
  • +
+
+ +
+

5. Who we share data with

+

We use the following processors to deliver the service. We do not sell your data to anyone.

+
    +
  • + Stripe — payment processing. Card details, billing address, + and subscription events flow to Stripe. See + Stripe's privacy policy. +
  • +
  • [PLACEHOLDER: Hosting provider] — infrastructure where our application and database run.
  • +
  • [PLACEHOLDER: Transactional email provider] — sends account, billing and alert emails on our behalf.
  • +
  • + Umami Analytics — we run our own self-hosted Umami instance to + collect aggregated, cookieless usage metrics (pages viewed, referrer, country, device + type). No personal data is collected and no analytics data is shared with third + parties. +
  • +
  • [PLACEHOLDER: Notification providers] — if you opt in to push, WhatsApp, or SMS alerts, the chosen provider will be named here.
  • +
+
+ +
+

6. International transfers

+

+ Some of our processors (notably Stripe) operate outside the UK and EEA, including in the + United States. Where personal data is transferred internationally, we rely on appropriate + safeguards under UK GDPR: the UK International Data Transfer Addendum to the EU Standard + Contractual Clauses, or an equivalent mechanism. +

+
+ +
+

7. How long we keep data

+
    +
  • Active account data: for as long as your account is open, plus 12 months after closure.
  • +
  • Payment records: 6 years, to meet HMRC requirements for self-employed traders.
  • +
  • Marketing data: until you withdraw consent.
  • +
  • Logs and analytics: a maximum of 24 months.
  • +
+
+ +
+

8. Your rights under UK GDPR

+

You have the following rights in relation to your personal data:

+
    +
  • Right of access — ask for a copy of the data we hold about you.
  • +
  • Right to rectification — ask us to correct inaccurate data.
  • +
  • Right to erasure ("right to be forgotten") — ask us to delete your data.
  • +
  • Right to restrict processing — ask us to pause processing in certain circumstances.
  • +
  • Right to data portability — receive your data in a machine-readable format.
  • +
  • Right to object — object to processing based on legitimate interests.
  • +
  • Rights related to automated decision-making — we do not make solely automated decisions with legal or similarly significant effects on you.
  • +
  • Right to withdraw consent — where we rely on consent (e.g. marketing).
  • +
+

+ To exercise any of these rights, email + [PLACEHOLDER: hello@fuelalert.co.uk]. + We will respond within one month. +

+
+ +
+

9. Cookies

+

+ We use a small number of cookies to operate the service. Full details — including + categories and how to change your choices — are in our + Cookie Policy. +

+
+ +
+

10. Security

+

+ All traffic between your device and our service is encrypted with HTTPS. Passwords are + stored as one-way hashes — we never see your plaintext password. Sensitive fields in + our database are protected by access controls, and our infrastructure receives regular + security updates. No system is ever 100% secure; if a breach occurs that affects you, we + will notify you and the ICO as required by law. +

+
+ +
+

11. Children

+

+ FuelAlert is not directed at children. We do not knowingly collect data from anyone under + 16. If you believe a child has provided us with personal data, contact us and we will + delete it. +

+
+ +
+

12. Complaints

+

+ We hope you'll contact us first if you have a complaint, so we can try to put it right. + You also have the right to lodge a complaint with the UK Information Commissioner's Office + at any time. +

+

+ ICO website: ico.org.uk + · ICO helpline: 0303 123 1113. +

+
+ +
+

13. Changes to this policy

+

+ We may update this policy from time to time. If we make material changes we will notify + registered users by email. Non-material changes will be shown by an updated "Last updated" + date at the top of this page. +

+
+ +
+

14. Contact

+

+ For any privacy queries, email + [PLACEHOLDER: hello@fuelalert.co.uk]. +

+
+
diff --git a/resources/views/legal/refund.blade.php b/resources/views/legal/refund.blade.php new file mode 100644 index 0000000..1bc5973 --- /dev/null +++ b/resources/views/legal/refund.blade.php @@ -0,0 +1,110 @@ +{{-- DRAFT: Generated {{ date('Y-m-d') }}. Review by UK-qualified solicitor recommended before launch. --}} + + +
+

1. Your 14-day right to cancel

+

+ Under the Consumer Contracts (Information, Cancellation and Additional Charges) + Regulations 2013, you have 14 days from the date you subscribe + to a paid plan to cancel without giving a reason. This is sometimes called the + "cooling-off period". +

+

+ This 14-day right applies to new subscribers only. It does not apply to + subsequent automatic renewals of an existing subscription. +

+
+ +
+

2. Express consent to start the service immediately

+

+ When you subscribe, we ask you to choose whether the paid features should be available + to you immediately. If you tick the consent box and start using paid features within the + 14-day window, you expressly acknowledge that: +

+
    +
  • The service is being supplied to you straight away;
  • +
  • + You will lose your right to cancel under the Consumer Contracts Regulations + 2013 once the service has been fully supplied (i.e. once you have used the + paid features during the cooling-off period). +
  • +
+

+ If you do not tick the express-consent box, your subscription is still + created but paid features remain inactive until the cooling-off period ends, or until + you change your mind and confirm consent. +

+

+ If you cancel within the 14-day window before using any paid features, + you receive a full refund. If you cancel within the window after using + some paid features, we may reduce the refund proportionally to reflect usage, as + permitted by the Regulations. +

+
+ +
+

3. How to cancel

+

You can cancel a subscription in either of these ways:

+ +

+ Unless you are exercising the 14-day right above, cancellation takes effect at the end + of the current billing period. You keep access to paid features until that date. +

+
+ +
+

4. Refunds outside the 14-day period

+

+ Outside the 14-day cooling-off window, subscription fees are non-refundable + for the remainder of the period you have paid for. You keep access to paid features + until the end of that period; the subscription simply does not renew. +

+

+ We may issue discretionary refunds where there has been a service failure on our side or + where required by law. +

+
+ +
+

5. Annual subscriptions

+

+ The 14-day cooling-off right applies to annual subscriptions in the same way as monthly + subscriptions. After the 14 days, annual fees are non-refundable; we do not issue + pro-rata refunds for unused months of an annual plan. +

+
+ +
+

6. Failed payments and involuntary cancellation

+

+ If a renewal payment fails, we and Stripe will retry the payment over a short period and + email you. Paid features are suspended after the final unsuccessful retry. Your account + itself is not deleted; you can resume by updating your payment method. +

+
+ +
+

7. How long refunds take

+

+ Approved refunds are issued to the original payment method via Stripe and typically + arrive in your account within 5–10 business days, depending on your bank or card + provider. +

+
+ +
+

8. Contact

+

+ For refund or cancellation queries, email + [PLACEHOLDER: hello@fuelalert.co.uk]. +

+
+
diff --git a/resources/views/legal/terms.blade.php b/resources/views/legal/terms.blade.php new file mode 100644 index 0000000..887610d --- /dev/null +++ b/resources/views/legal/terms.blade.php @@ -0,0 +1,221 @@ +{{-- DRAFT: Generated {{ date('Y-m-d') }}. Review by UK-qualified solicitor recommended before launch. --}} + + +
+

1. About these terms

+

+ FuelAlert is a trading name of Ovidiu Ungureanu, a sole trader based in + Peterborough, United Kingdom ("we", "us", "our"). These terms form a legally binding + contract between you and Ovidiu Ungureanu trading as FuelAlert. +

+

+ By creating an account or using the service, you confirm that you have read, understood + and accepted these terms. If you do not accept them, please do not use the service. +

+

These terms are governed by the laws of England and Wales.

+
+ +
+

2. The service

+

+ FuelAlert provides UK fuel price comparison and forecasting. We aggregate publicly + available UK fuel price data and surface it through a web app, alerts and forecasts. +

+

+ We offer a free tier and one or more paid subscription plans. The current list of plans + and prices is available on our pricing page. +

+

+ We may add, remove, or change features over time. Where changes materially reduce the + paid service, we will give you reasonable notice and, where appropriate, a way to cancel. +

+
+ +
+

3. Your account

+
    +
  • You must be at least 18 years old and resident in the United Kingdom to create an account.
  • +
  • The information you provide must be accurate and kept up to date.
  • +
  • One account per person. You are responsible for keeping your login credentials secure.
  • +
  • You are responsible for activity that takes place under your account.
  • +
  • We may suspend or close accounts where these terms are seriously or repeatedly breached.
  • +
+
+ +
+

4. Subscriptions, billing and payment

+

+ Paid plans are billed in advance, either monthly or annually. The current price for each + plan is shown on the pricing page at the time you subscribe. +

+

+ Auto-renewal. Subscriptions renew automatically at the end of each + billing period at the then-current price, unless you cancel before the renewal date. By + subscribing you authorise FuelAlert — through our payment processor Stripe — + to charge your nominated payment method at each renewal. +

+

+ Failed payments. If a payment fails, we and Stripe will retry the + payment over the following days. We will email you when this happens. Persistent failure + will cause your paid features to be suspended; your account itself is not deleted. +

+

+ Price changes. If we change the price of your plan, we will give you at + least 30 days' notice by email before the new price takes effect on your next renewal. + You may cancel before the change takes effect. +

+

+ VAT. Prices include UK VAT where applicable. + [PLACEHOLDER: verify before launch — FuelAlert is currently below the UK VAT registration threshold and therefore does not charge VAT.] +

+
+ +
+

5. Cancellation and refunds

+

+ You can cancel your subscription at any time from your account settings. Cancellation + stops the next renewal; you keep access to paid features until the end of the current + billing period. +

+

+ New subscribers have a 14-day right to cancel under the Consumer + Contracts Regulations 2013. Important details — including the express-consent + mechanism that affects this right — are set out in our + Refund & Cancellation Policy. +

+
+ +
+

6. Acceptable use

+

You agree not to:

+
    +
  • Scrape, reverse-engineer, or bulk-extract data from the service.
  • +
  • Resell or redistribute fuel price data taken from FuelAlert.
  • +
  • Use the service for any unlawful purpose.
  • +
  • Attempt to circumvent or compromise our security measures.
  • +
  • Use automated tools to make queries beyond what a single human user would reasonably make.
  • +
+
+ +
+

7. Accuracy of price data

+

+ Fuel prices shown on FuelAlert are sourced from official UK government data feeds + (including the Pump Watch / Fuel Finder transparency schemes) and refreshed + periodically. Stations can change prices at any time, and there is usually a delay + between a forecourt change and the feed update. +

+

+ We make reasonable efforts to display accurate prices but we cannot guarantee + that the price shown will match the price at the pump when you arrive. + Always confirm the price at the pump before fuelling. +

+

+ We are not liable for any loss arising from inaccurate, delayed, or missing price data, + including the cost of a wasted journey or any difference between the price shown and the + price charged. +

+
+ +
+

8. Forecasts and predictions

+

+ FuelAlert may show forecasts and recommendations (e.g. "fill up now" or "wait"). These + are informational only, are not financial advice, and should not be + relied upon as a guarantee of future prices. Past trends do not guarantee future prices. + We do not warrant the accuracy of any forecast. +

+
+ +
+

9. Intellectual property

+

+ The FuelAlert name, logo, software, and original content are owned by Ovidiu Ungureanu. + You receive a limited, non-exclusive, revocable licence to use the service for personal, + non-commercial purposes. +

+

+ Underlying fuel price data is owned by the respective fuel retailers and published under + UK government open data schemes. Postcode and geographic data is sourced from the ONS + Postcode Directory, © Crown Copyright, used under the Open Government Licence v3.0. +

+
+ +
+

10. Third-party services

+

+ We use Stripe to process payments. Your use of Stripe is also subject + to Stripe's own terms and privacy policy. We may use other third-party processors to + run the service; these are named in our + Privacy Policy. +

+
+ +
+

11. Limitation of liability

+

+ Nothing in these terms excludes or limits our liability for death or personal injury + caused by our negligence, fraud or fraudulent misrepresentation, or any other liability + that cannot be excluded under UK consumer law. Your statutory rights as a consumer are + not affected. +

+

Subject to the paragraph above:

+
    +
  • We exclude liability for indirect, consequential, or business losses.
  • +
  • + For paying subscribers, our total liability to you in any 12-month period is capped + at the total amount you paid in subscription fees during that period. +
  • +
  • + We do not accept liability for issues caused by third-party services we rely on, + including but not limited to outages or errors at our payment processor, hosting + provider, or upstream data sources. +
  • +
+
+ +
+

12. Termination

+

+ You may stop using the service and close your account at any time. We may terminate or + suspend access for serious breach of these terms, with reasonable notice where the + breach is capable of being put right. +

+

+ Sections that by their nature should survive termination (including sections 7 to 11) + will continue to apply after your account is closed. +

+
+ +
+

13. Changes to these terms

+

+ We may update these terms. Material changes will be notified to registered users by + email at least 14 days before they take effect. Continued use of the service after the + change date means you accept the new terms. +

+
+ +
+

14. Disputes

+

+ Please contact us first if you have a complaint — we will try to resolve it + directly. These terms are governed by the laws of England and Wales, and the courts of + England and Wales have non-exclusive jurisdiction over any dispute. If you live + elsewhere in the United Kingdom, you keep the right to bring proceedings in the courts + of your country of residence. +

+
+ +
+

15. Contact

+

+ For questions about these terms, email + [PLACEHOLDER: hello@fuelalert.co.uk]. +

+
+
diff --git a/routes/web.php b/routes/web.php index 74e2a13..f6e7bc1 100644 --- a/routes/web.php +++ b/routes/web.php @@ -24,5 +24,13 @@ Route::middleware(['auth'])->prefix('billing')->name('billing.')->group(function Route::get('/cancel', [BillingController::class, 'cancel'])->name('cancel'); }); +// Server-rendered legal pages — must be registered before the SPA catch-all +Route::prefix('legal')->name('legal.')->group(function () { + Route::view('/privacy', 'legal.privacy')->name('privacy'); + Route::view('/terms', 'legal.terms')->name('terms'); + Route::view('/refund', 'legal.refund')->name('refund'); + Route::view('/cookies', 'legal.cookies')->name('cookies'); +}); + // SPA catch-all — must be last Route::get('/{any?}', fn () => view('app'))->where('any', '.*')->name('home'); diff --git a/tests/Feature/LegalPagesTest.php b/tests/Feature/LegalPagesTest.php new file mode 100644 index 0000000..be56674 --- /dev/null +++ b/tests/Feature/LegalPagesTest.php @@ -0,0 +1,54 @@ +get('/legal/privacy'); + + $response->assertStatus(200); + $response->assertSeeText('Privacy Policy'); + $response->assertSeeText('data controller'); + $response->assertSeeText('UK GDPR'); + $response->assertSeeText('Last updated:'); +}); + +it('serves the terms of service with required content', function (): void { + $response = $this->get('/legal/terms'); + + $response->assertStatus(200); + $response->assertSeeText('Terms of Service'); + $response->assertSeeText('subscription'); + $response->assertSeeText('England and Wales'); +}); + +it('serves the refund policy with cooling-off content', function (): void { + $response = $this->get('/legal/refund'); + + $response->assertStatus(200); + $response->assertSeeText('Refund'); + $response->assertSeeText('14-day'); + $response->assertSeeText('Consumer Contracts'); +}); + +it('serves the cookie policy with essential-cookie content', function (): void { + $response = $this->get('/legal/cookies'); + + $response->assertStatus(200); + $response->assertSeeText('Cookie Policy'); + $response->assertSeeText('essential'); +}); + +it('does not render the SPA mount point on legal pages', function (string $path): void { + $response = $this->get($path); + + $response->assertStatus(200); + $response->assertDontSee('
', false); +})->with([ + '/legal/privacy', + '/legal/terms', + '/legal/refund', + '/legal/cookies', +]); + +it('cross-links between legal pages', function (): void { + $this->get('/legal/privacy')->assertSee(route('legal.cookies'), false); + $this->get('/legal/terms')->assertSee(route('legal.refund'), false); +});