feat: i18n infrastructure — EN route, DeepL endpoint, locale switcher, calculator localized fields

This commit is contained in:
Jeffrey 2026-02-24 15:02:56 +01:00
parent 791ad8dbc0
commit f48b60bb5d
12 changed files with 69311 additions and 21 deletions

View File

@ -0,0 +1,87 @@
import type { Metadata } from 'next'
import { PayloadRedirects } from '@/components/PayloadRedirects'
import configPromise from '@payload-config'
import { getPayload, type RequiredDataFromCollectionSlug } from 'payload'
import { draftMode } from 'next/headers'
import React, { cache } from 'react'
import { RenderBlocks } from '@/blocks/RenderBlocks'
import type { Page } from '@/payload-types'
import { generateMeta } from '@/utilities/generateMeta'
import PageClient from '../../[slug]/page.client'
import { LivePreviewListener } from '@/components/LivePreviewListener'
export const dynamic = 'force-dynamic'
export const dynamicParams = true
type Args = {
params: Promise<{
slug?: string
}>
}
export default async function PageEN({ params: paramsPromise }: Args) {
const { isEnabled: draft } = await draftMode()
const { slug = 'home' } = await paramsPromise
const decodedSlug = decodeURIComponent(slug)
const url = '/en/' + decodedSlug
const page = await queryPageBySlugEN({ slug: decodedSlug })
if (!page) {
return <PayloadRedirects url={url} />
}
const { layout } = page as Page
return (
<article>
<PageClient />
<PayloadRedirects disableNotFound url={url} />
{draft && <LivePreviewListener />}
<RenderBlocks blocks={layout} />
</article>
)
}
export async function generateMetadata({ params: paramsPromise }: Args): Promise<Metadata> {
const { slug = 'home' } = await paramsPromise
const decodedSlug = decodeURIComponent(slug)
const page = await queryPageBySlugEN({ slug: decodedSlug })
return generateMeta({ doc: page })
}
export async function generateStaticParams() {
const payload = await getPayload({ config: configPromise })
const pages = await payload.find({
collection: 'pages',
draft: false,
limit: 1000,
pagination: false,
overrideAccess: false,
select: { slug: true },
locale: 'en',
})
return pages.docs?.map(({ slug }) => ({ slug })) ?? []
}
const queryPageBySlugEN = cache(async ({ slug }: { slug: string }) => {
const { isEnabled: draft } = await draftMode()
const payload = await getPayload({ config: configPromise })
const result = await payload.find({
collection: 'pages',
draft,
limit: 1,
pagination: false,
overrideAccess: draft,
locale: 'en', // ← only difference from the sv route
fallbackLocale: 'sv', // ← if en field is empty, fall back to Swedish
where: {
slug: {
equals: slug,
},
},
})
return result.docs?.[0] || null
})

View File

@ -0,0 +1,211 @@
/**
* POST /api/translate
*
* Server-side DeepL translation endpoint.
* Fetches a page in Swedish, extracts all localizable text fields,
* sends them to DeepL in one batch request, and saves results back
* with locale: 'en'.
*
* Security: Admin-only via Payload auth check.
* Privacy: Content is sent to DeepL's EU API endpoint under their
* GDPR-compliant Data Processing Agreement.
* RichText fields are excluded translate those manually
* in the Payload admin for accuracy.
*
* Usage: POST /api/translate
* Body: { pageId: string, collection: 'pages' | 'posts' }
*
* Required env: DEEPL_API_KEY (add to .env.local and server .env)
* DEEPL_API_URL (optional, defaults to EU free tier)
*/
import { NextRequest, NextResponse } from 'next/server'
import { getPayload } from 'payload'
import configPromise from '@payload-config'
const DEEPL_API_URL =
process.env.DEEPL_API_URL ?? 'https://api-free.deepl.com/v1/translate'
// Fields that should NOT be auto-translated:
// - URLs, slugs, links (would break routing)
// - Numbers, selects, booleans (not text)
// - RichText (complex structure, do manually for accuracy)
const SKIP_FIELD_NAMES = new Set([
'slug',
'url',
'href',
'link',
'orderCtaLink',
'contactCtaLink',
'anchorId',
'id',
])
/**
* Recursively walks a Payload document and extracts all string
* values from fields that have localized: true.
* Returns a flat map of dotPath value for batch translation.
*/
function extractStrings(
obj: Record<string, any>,
path = '',
result: Record<string, string> = {},
): Record<string, string> {
if (!obj || typeof obj !== 'object') return result
for (const [key, value] of Object.entries(obj)) {
const fullPath = path ? `${path}.${key}` : key
if (SKIP_FIELD_NAMES.has(key)) continue
// Skip richtext (lexical) nodes — they have a 'root' property
if (value && typeof value === 'object' && 'root' in value) continue
if (typeof value === 'string' && value.trim() !== '') {
result[fullPath] = value
} else if (Array.isArray(value)) {
value.forEach((item, i) => {
if (typeof item === 'object' && item !== null) {
extractStrings(item, `${fullPath}.${i}`, result)
}
})
} else if (typeof value === 'object' && value !== null) {
extractStrings(value, fullPath, result)
}
}
return result
}
/**
* Batch translate strings via DeepL EU API.
* Sends all strings in one request to minimise API calls.
*/
async function translateBatch(
strings: string[],
apiKey: string,
): Promise<string[]> {
const params = new URLSearchParams()
params.append('auth_key', apiKey)
params.append('source_lang', 'SV')
params.append('target_lang', 'EN-GB')
params.append('preserve_formatting', '1')
strings.forEach((s) => params.append('text', s))
const res = await fetch(DEEPL_API_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: params.toString(),
})
if (!res.ok) {
const err = await res.text()
throw new Error(`DeepL API error ${res.status}: ${err}`)
}
const data = await res.json()
return data.translations.map((t: { text: string }) => t.text)
}
/**
* Rebuilds the update object from dotPaths translated values.
* Handles nested paths like 'layout.0.heading' correctly.
*/
function applyTranslations(
paths: string[],
translations: string[],
): Record<string, any> {
const result: Record<string, any> = {}
paths.forEach((path, i) => {
const parts = path.split('.')
let cursor = result
parts.forEach((part, j) => {
if (j === parts.length - 1) {
cursor[part] = translations[i]
} else {
cursor[part] = cursor[part] ?? (isNaN(Number(parts[j + 1])) ? {} : [])
cursor = cursor[part]
}
})
})
return result
}
export async function POST(req: NextRequest) {
try {
const payload = await getPayload({ config: configPromise })
// ── Auth check ──────────────────────────────────────────────────────────
const { user } = await payload.auth({ headers: req.headers })
if (!user || user.collection !== 'users') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
// ── Validate env ────────────────────────────────────────────────────────
const apiKey = process.env.DEEPL_API_KEY
if (!apiKey) {
return NextResponse.json(
{ error: 'DEEPL_API_KEY is not set in environment' },
{ status: 500 },
)
}
// ── Parse request ────────────────────────────────────────────────────────
const body = await req.json()
const { pageId, collection = 'pages' } = body as {
pageId: string
collection?: 'pages' | 'posts'
}
if (!pageId) {
return NextResponse.json({ error: 'pageId is required' }, { status: 400 })
}
// ── Fetch Swedish source ─────────────────────────────────────────────────
const doc = await payload.findByID({
collection,
id: pageId,
locale: 'sv',
depth: 10,
})
if (!doc) {
return NextResponse.json({ error: 'Document not found' }, { status: 404 })
}
// ── Extract & translate ──────────────────────────────────────────────────
const stringMap = extractStrings(doc as Record<string, any>)
const paths = Object.keys(stringMap)
const sourceStrings = Object.values(stringMap)
if (paths.length === 0) {
return NextResponse.json({ message: 'No translatable strings found', translated: 0 })
}
const translatedStrings = await translateBatch(sourceStrings, apiKey)
// ── Save English translations ────────────────────────────────────────────
const updateData = applyTranslations(paths, translatedStrings)
await payload.update({
collection,
id: pageId,
locale: 'en',
data: updateData,
})
return NextResponse.json({
message: `Translated ${paths.length} fields from Swedish to English`,
translated: paths.length,
fields: paths, // useful for debugging
})
} catch (err: any) {
console.error('[translate endpoint]', err)
return NextResponse.json(
{ error: err.message ?? 'Internal server error' },
{ status: 500 },
)
}
}

View File

@ -2,7 +2,7 @@ import type { Block } from 'payload'
import { anchorField } from '@/fields/anchorField'
export const FDServiceCalculatorBlock: Block = {
slug: 'fdServiceCalculator',
slug: 'fdServiceCalc',
imageURL: '/block-thumbnails/fd-vps-calculator.png',
imageAltText: 'FD Tjänstekalkylator',
interfaceName: 'FDServiceCalculatorBlock',
@ -14,41 +14,46 @@ export const FDServiceCalculatorBlock: Block = {
type: 'text',
label: 'Rubrik',
defaultValue: 'Beräkna din kostnad',
localized: true,
},
{
name: 'description',
type: 'text',
label: 'Beskrivning (valfri)',
localized: true,
},
{
name: 'summaryHeading',
type: 'text',
label: 'Rubrik — kostnadsöversikt',
defaultValue: 'Kostnadsöversikt',
localized: true,
},
{
name: 'totalLabel',
type: 'text',
label: 'Total-etikett',
defaultValue: 'Totalt per månad',
localized: true,
},
{
name: 'totalSuffix',
type: 'text',
label: 'Suffix under totalen',
defaultValue: 'exkl. moms',
localized: true,
},
{
type: 'row',
fields: [
{ name: 'orderCtaText', type: 'text', label: 'Beställ-knapp text', defaultValue: 'Beställ' },
{ name: 'orderCtaText', type: 'text', label: 'Beställ-knapp text', defaultValue: 'Beställ', localized: true },
{ name: 'orderCtaLink', type: 'text', label: 'Beställ-länk', defaultValue: '/kontakt' },
],
},
{
type: 'row',
fields: [
{ name: 'contactCtaText', type: 'text', label: 'Kontakt-knapp text', defaultValue: 'Frågor? Kontakta oss' },
{ name: 'contactCtaText', type: 'text', label: 'Kontakt-knapp text', defaultValue: 'Frågor? Kontakta oss', localized: true },
{ name: 'contactCtaLink', type: 'text', label: 'Kontakt-länk', defaultValue: '/kontakt' },
],
},
@ -73,14 +78,14 @@ export const FDServiceCalculatorBlock: Block = {
description: 'T.ex. "Operativsystem" med Linux/Windows, eller "Nivå" med Standard/Premium. Visas som knappar.',
},
fields: [
{ name: 'groupLabel', type: 'text', label: 'Gruppnamn', required: true },
{ name: 'groupLabel', type: 'text', label: 'Gruppnamn', required: true, localized: true },
{
name: 'options',
type: 'array',
label: 'Alternativ',
minRows: 2,
fields: [
{ name: 'label', type: 'text', label: 'Alternativtext', required: true },
{ name: 'label', type: 'text', label: 'Alternativtext', required: true, localized: true },
{
name: 'price',
type: 'number',
@ -105,8 +110,8 @@ export const FDServiceCalculatorBlock: Block = {
{
type: 'row',
fields: [
{ name: 'label', type: 'text', label: 'Namn', required: true },
{ name: 'unit', type: 'text', label: 'Enhet', required: true, defaultValue: 'GB', admin: { width: '25%' } },
{ name: 'label', type: 'text', label: 'Namn', required: true, localized: true },
{ name: 'unit', type: 'text', label: 'Enhet', required: true, defaultValue: 'GB', localized: true, admin: { width: '25%' } },
],
},
{
@ -128,6 +133,7 @@ export const FDServiceCalculatorBlock: Block = {
name: 'summaryTemplate',
type: 'text',
label: 'Sammanfattningsmall (valfri)',
localized: true,
admin: {
description: 'Använd {value} och {unit} som variabler. T.ex. "SSD NVMe ({value} {unit})".',
},
@ -144,12 +150,13 @@ export const FDServiceCalculatorBlock: Block = {
description: 'Kunden kan slå på/av dessa med en toggle.',
},
fields: [
{ name: 'label', type: 'text', label: 'Tjänstnamn', required: true },
{ name: 'label', type: 'text', label: 'Tjänstnamn', required: true, localized: true },
{ name: 'price', type: 'number', label: 'Pris (kr/mån)', required: true },
{
name: 'description',
type: 'text',
label: 'Kort beskrivning (valfri)',
localized: true,
},
],
},
@ -163,7 +170,7 @@ export const FDServiceCalculatorBlock: Block = {
description: 'Alltid inkluderade i totalen. Kunden kan inte välja bort dessa.',
},
fields: [
{ name: 'label', type: 'text', label: 'Avgiftsnamn', required: true },
{ name: 'label', type: 'text', label: 'Avgiftsnamn', required: true, localized: true },
{ name: 'amount', type: 'number', label: 'Belopp (kr/mån)', required: true },
],
},
@ -186,6 +193,7 @@ export const FDServiceCalculatorBlock: Block = {
name: 'discountLabel',
type: 'text',
label: 'Rabattetikett (visas som badge)',
localized: true,
admin: {
description: 'T.ex. "{percent}% rabatt på alla resurser". Använd {percent} som variabel.',
condition: (_, siblingData) => (siblingData?.discountPercent ?? 0) > 0,

View File

@ -9,19 +9,19 @@ export const FDVpsCalculatorBlock: Block = {
labels: { singular: 'FD VPS-kalkylator', plural: 'FD VPS-kalkylatorer' },
fields: [
// ─── Presentation ──────────────────────────────────────────────────────
{ name: 'heading', type: 'text', label: 'Rubrik', defaultValue: 'Virtuell server — kalkylator' },
{ name: 'description', type: 'text', label: 'Beskrivning' },
{ name: 'heading', type: 'text', label: 'Rubrik', defaultValue: 'Virtuell server — kalkylator', localized: true },
{ name: 'description', type: 'text', label: 'Beskrivning', localized: true },
{
type: 'row',
fields: [
{ name: 'orderCtaText', type: 'text', label: 'Beställ-knapp text', defaultValue: 'Beställ' },
{ name: 'orderCtaText', type: 'text', label: 'Beställ-knapp text', defaultValue: 'Beställ', localized: true },
{ name: 'orderCtaLink', type: 'text', label: 'Beställ-länk', defaultValue: '/kontakt?subject=vps-bestallning' },
],
},
{
type: 'row',
fields: [
{ name: 'contactCtaText', type: 'text', label: 'Kontakt-knapp text', defaultValue: 'Frågor? Kontakta oss' },
{ name: 'contactCtaText', type: 'text', label: 'Kontakt-knapp text', defaultValue: 'Frågor? Kontakta oss', localized: true },
{ name: 'contactCtaLink', type: 'text', label: 'Kontakt-länk', defaultValue: '/kontakt' },
],
},
@ -117,7 +117,7 @@ export const FDVpsCalculatorBlock: Block = {
description: 'Kunden kan slå på/av dessa i kalkylatorn. Visas under "Tillvalstjänster".',
},
fields: [
{ name: 'label', type: 'text', label: 'Tjänstnamn', required: true },
{ name: 'label', type: 'text', label: 'Tjänstnamn', required: true, localized: true },
{
name: 'price',
type: 'number',

View File

@ -69,7 +69,7 @@ const blockComponents: Record<string, React.FC<any>> = {
fdCtaBanner: FDCtaBannerBlockComponent,
fdTestimonial: FDTestimonialBlockComponent,
fdTeam: FDTeamBlockComponent,
fdServiceCalculator: FDServiceCalculatorBlockComponent,
fdServiceCalc: FDServiceCalculatorBlockComponent,
}
/**

View File

@ -0,0 +1,55 @@
'use client'
/**
* LocaleSwitcher
*
* Simple SV / EN text switcher with fade transition.
* NOT wired into nav yet import when EN content is ready.
*
* Usage in Nav/index.tsx when ready:
* import { LocaleSwitcher } from '@/components/LocaleSwitcher'
* <LocaleSwitcher />
*/
import { usePathname } from 'next/navigation'
import Link from 'next/link'
export function LocaleSwitcher() {
const pathname = usePathname()
const isEN = pathname.startsWith('/en')
const alternatePath = isEN
? pathname.replace(/^\/en/, '') || '/'
: `/en${pathname === '/' ? '' : pathname}`
return (
<Link
href={alternatePath}
className="
relative inline-flex items-center
font-joey-medium text-sm tracking-wide
text-fd-navy dark:text-white
hover:text-fd-yellow dark:hover:text-fd-yellow
transition-colors duration-200
"
aria-label={isEN ? 'Byt till svenska' : 'Switch to English'}
>
<span
className={`
transition-opacity duration-200
${isEN ? 'opacity-100' : 'opacity-0 absolute'}
`}
>
SV
</span>
<span
className={`
transition-opacity duration-200
${!isEN ? 'opacity-100' : 'opacity-0 absolute'}
`}
>
EN
</span>
</Link>
)
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,588 @@
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
await db.execute(sql`
CREATE TYPE "public"."enum_pages_blocks_fd_service_calc_section_background" AS ENUM('white', 'gray', 'navy');
CREATE TYPE "public"."enum__pages_v_blocks_fd_service_calc_section_background" AS ENUM('white', 'gray', 'navy');
CREATE TABLE "pages_blocks_fd_service_calc_option_groups_options" (
"_order" integer NOT NULL,
"_parent_id" varchar NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"price" numeric DEFAULT 0
);
CREATE TABLE "pages_blocks_fd_service_calc_option_groups_options_locales" (
"label" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
CREATE TABLE "pages_blocks_fd_service_calc_option_groups" (
"_order" integer NOT NULL,
"_parent_id" varchar NOT NULL,
"id" varchar PRIMARY KEY NOT NULL
);
CREATE TABLE "pages_blocks_fd_service_calc_option_groups_locales" (
"group_label" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
CREATE TABLE "pages_blocks_fd_service_calc_resources" (
"_order" integer NOT NULL,
"_parent_id" varchar NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"price_per_unit" numeric,
"default_value" numeric DEFAULT 0,
"min" numeric DEFAULT 0,
"max" numeric DEFAULT 1000,
"step" numeric DEFAULT 1
);
CREATE TABLE "pages_blocks_fd_service_calc_resources_locales" (
"label" varchar,
"unit" varchar DEFAULT 'GB',
"summary_template" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
CREATE TABLE "pages_blocks_fd_service_calc_addons" (
"_order" integer NOT NULL,
"_parent_id" varchar NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"price" numeric
);
CREATE TABLE "pages_blocks_fd_service_calc_addons_locales" (
"label" varchar,
"description" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
CREATE TABLE "pages_blocks_fd_service_calc_fixed_fees" (
"_order" integer NOT NULL,
"_parent_id" varchar NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"amount" numeric
);
CREATE TABLE "pages_blocks_fd_service_calc_fixed_fees_locales" (
"label" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
CREATE TABLE "pages_blocks_fd_service_calc" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"_path" text NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"order_cta_link" varchar DEFAULT '/kontakt',
"contact_cta_link" varchar DEFAULT '/kontakt',
"section_background" "enum_pages_blocks_fd_service_calc_section_background" DEFAULT 'white',
"discount_percent" numeric,
"anchor_id" varchar,
"block_name" varchar
);
CREATE TABLE "pages_blocks_fd_service_calc_locales" (
"heading" varchar DEFAULT 'Beräkna din kostnad',
"description" varchar,
"summary_heading" varchar DEFAULT 'Kostnadsöversikt',
"total_label" varchar DEFAULT 'Totalt per månad',
"total_suffix" varchar DEFAULT 'exkl. moms',
"order_cta_text" varchar DEFAULT 'Beställ',
"contact_cta_text" varchar DEFAULT 'Frågor? Kontakta oss',
"discount_label" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
CREATE TABLE "_pages_v_blocks_fd_service_calc_option_groups_options" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"id" serial PRIMARY KEY NOT NULL,
"price" numeric DEFAULT 0,
"_uuid" varchar
);
CREATE TABLE "_pages_v_blocks_fd_service_calc_option_groups_options_locales" (
"label" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" integer NOT NULL
);
CREATE TABLE "_pages_v_blocks_fd_service_calc_option_groups" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"id" serial PRIMARY KEY NOT NULL,
"_uuid" varchar
);
CREATE TABLE "_pages_v_blocks_fd_service_calc_option_groups_locales" (
"group_label" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" integer NOT NULL
);
CREATE TABLE "_pages_v_blocks_fd_service_calc_resources" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"id" serial PRIMARY KEY NOT NULL,
"price_per_unit" numeric,
"default_value" numeric DEFAULT 0,
"min" numeric DEFAULT 0,
"max" numeric DEFAULT 1000,
"step" numeric DEFAULT 1,
"_uuid" varchar
);
CREATE TABLE "_pages_v_blocks_fd_service_calc_resources_locales" (
"label" varchar,
"unit" varchar DEFAULT 'GB',
"summary_template" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" integer NOT NULL
);
CREATE TABLE "_pages_v_blocks_fd_service_calc_addons" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"id" serial PRIMARY KEY NOT NULL,
"price" numeric,
"_uuid" varchar
);
CREATE TABLE "_pages_v_blocks_fd_service_calc_addons_locales" (
"label" varchar,
"description" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" integer NOT NULL
);
CREATE TABLE "_pages_v_blocks_fd_service_calc_fixed_fees" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"id" serial PRIMARY KEY NOT NULL,
"amount" numeric,
"_uuid" varchar
);
CREATE TABLE "_pages_v_blocks_fd_service_calc_fixed_fees_locales" (
"label" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" integer NOT NULL
);
CREATE TABLE "_pages_v_blocks_fd_service_calc" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"_path" text NOT NULL,
"id" serial PRIMARY KEY NOT NULL,
"order_cta_link" varchar DEFAULT '/kontakt',
"contact_cta_link" varchar DEFAULT '/kontakt',
"section_background" "enum__pages_v_blocks_fd_service_calc_section_background" DEFAULT 'white',
"discount_percent" numeric,
"anchor_id" varchar,
"_uuid" varchar,
"block_name" varchar
);
CREATE TABLE "_pages_v_blocks_fd_service_calc_locales" (
"heading" varchar DEFAULT 'Beräkna din kostnad',
"description" varchar,
"summary_heading" varchar DEFAULT 'Kostnadsöversikt',
"total_label" varchar DEFAULT 'Totalt per månad',
"total_suffix" varchar DEFAULT 'exkl. moms',
"order_cta_text" varchar DEFAULT 'Beställ',
"contact_cta_text" varchar DEFAULT 'Frågor? Kontakta oss',
"discount_label" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" integer NOT NULL
);
ALTER TABLE "pages_blocks_fd_service_calc_option_groups_options" ADD CONSTRAINT "pages_blocks_fd_service_calc_option_groups_options_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calc_option_groups"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calc_option_groups_options_locales" ADD CONSTRAINT "pages_blocks_fd_service_calc_option_groups_options_locale_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calc_option_groups_options"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calc_option_groups" ADD CONSTRAINT "pages_blocks_fd_service_calc_option_groups_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calc"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calc_option_groups_locales" ADD CONSTRAINT "pages_blocks_fd_service_calc_option_groups_locales_parent_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calc_option_groups"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calc_resources" ADD CONSTRAINT "pages_blocks_fd_service_calc_resources_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calc"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calc_resources_locales" ADD CONSTRAINT "pages_blocks_fd_service_calc_resources_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calc_resources"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calc_addons" ADD CONSTRAINT "pages_blocks_fd_service_calc_addons_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calc"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calc_addons_locales" ADD CONSTRAINT "pages_blocks_fd_service_calc_addons_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calc_addons"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calc_fixed_fees" ADD CONSTRAINT "pages_blocks_fd_service_calc_fixed_fees_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calc"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calc_fixed_fees_locales" ADD CONSTRAINT "pages_blocks_fd_service_calc_fixed_fees_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calc_fixed_fees"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calc" ADD CONSTRAINT "pages_blocks_fd_service_calc_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calc_locales" ADD CONSTRAINT "pages_blocks_fd_service_calc_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calc"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calc_option_groups_options" ADD CONSTRAINT "_pages_v_blocks_fd_service_calc_option_groups_options_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calc_option_groups"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calc_option_groups_options_locales" ADD CONSTRAINT "_pages_v_blocks_fd_service_calc_option_groups_options_loc_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calc_option_groups_options"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calc_option_groups" ADD CONSTRAINT "_pages_v_blocks_fd_service_calc_option_groups_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calc"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calc_option_groups_locales" ADD CONSTRAINT "_pages_v_blocks_fd_service_calc_option_groups_locales_par_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calc_option_groups"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calc_resources" ADD CONSTRAINT "_pages_v_blocks_fd_service_calc_resources_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calc"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calc_resources_locales" ADD CONSTRAINT "_pages_v_blocks_fd_service_calc_resources_locales_parent__fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calc_resources"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calc_addons" ADD CONSTRAINT "_pages_v_blocks_fd_service_calc_addons_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calc"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calc_addons_locales" ADD CONSTRAINT "_pages_v_blocks_fd_service_calc_addons_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calc_addons"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calc_fixed_fees" ADD CONSTRAINT "_pages_v_blocks_fd_service_calc_fixed_fees_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calc"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calc_fixed_fees_locales" ADD CONSTRAINT "_pages_v_blocks_fd_service_calc_fixed_fees_locales_parent_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calc_fixed_fees"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calc" ADD CONSTRAINT "_pages_v_blocks_fd_service_calc_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calc_locales" ADD CONSTRAINT "_pages_v_blocks_fd_service_calc_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calc"("id") ON DELETE cascade ON UPDATE no action;
CREATE INDEX "pages_blocks_fd_service_calc_option_groups_options_order_idx" ON "pages_blocks_fd_service_calc_option_groups_options" USING btree ("_order");
CREATE INDEX "pages_blocks_fd_service_calc_option_groups_options_parent_id_idx" ON "pages_blocks_fd_service_calc_option_groups_options" USING btree ("_parent_id");
CREATE UNIQUE INDEX "pages_blocks_fd_service_calc_option_groups_options_locales_l" ON "pages_blocks_fd_service_calc_option_groups_options_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "pages_blocks_fd_service_calc_option_groups_order_idx" ON "pages_blocks_fd_service_calc_option_groups" USING btree ("_order");
CREATE INDEX "pages_blocks_fd_service_calc_option_groups_parent_id_idx" ON "pages_blocks_fd_service_calc_option_groups" USING btree ("_parent_id");
CREATE UNIQUE INDEX "pages_blocks_fd_service_calc_option_groups_locales_locale_pa" ON "pages_blocks_fd_service_calc_option_groups_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "pages_blocks_fd_service_calc_resources_order_idx" ON "pages_blocks_fd_service_calc_resources" USING btree ("_order");
CREATE INDEX "pages_blocks_fd_service_calc_resources_parent_id_idx" ON "pages_blocks_fd_service_calc_resources" USING btree ("_parent_id");
CREATE UNIQUE INDEX "pages_blocks_fd_service_calc_resources_locales_locale_parent" ON "pages_blocks_fd_service_calc_resources_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "pages_blocks_fd_service_calc_addons_order_idx" ON "pages_blocks_fd_service_calc_addons" USING btree ("_order");
CREATE INDEX "pages_blocks_fd_service_calc_addons_parent_id_idx" ON "pages_blocks_fd_service_calc_addons" USING btree ("_parent_id");
CREATE UNIQUE INDEX "pages_blocks_fd_service_calc_addons_locales_locale_parent_id" ON "pages_blocks_fd_service_calc_addons_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "pages_blocks_fd_service_calc_fixed_fees_order_idx" ON "pages_blocks_fd_service_calc_fixed_fees" USING btree ("_order");
CREATE INDEX "pages_blocks_fd_service_calc_fixed_fees_parent_id_idx" ON "pages_blocks_fd_service_calc_fixed_fees" USING btree ("_parent_id");
CREATE UNIQUE INDEX "pages_blocks_fd_service_calc_fixed_fees_locales_locale_paren" ON "pages_blocks_fd_service_calc_fixed_fees_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "pages_blocks_fd_service_calc_order_idx" ON "pages_blocks_fd_service_calc" USING btree ("_order");
CREATE INDEX "pages_blocks_fd_service_calc_parent_id_idx" ON "pages_blocks_fd_service_calc" USING btree ("_parent_id");
CREATE INDEX "pages_blocks_fd_service_calc_path_idx" ON "pages_blocks_fd_service_calc" USING btree ("_path");
CREATE UNIQUE INDEX "pages_blocks_fd_service_calc_locales_locale_parent_id_unique" ON "pages_blocks_fd_service_calc_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "_pages_v_blocks_fd_service_calc_option_groups_options_order_idx" ON "_pages_v_blocks_fd_service_calc_option_groups_options" USING btree ("_order");
CREATE INDEX "_pages_v_blocks_fd_service_calc_option_groups_options_parent_id_idx" ON "_pages_v_blocks_fd_service_calc_option_groups_options" USING btree ("_parent_id");
CREATE UNIQUE INDEX "_pages_v_blocks_fd_service_calc_option_groups_options_locale" ON "_pages_v_blocks_fd_service_calc_option_groups_options_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "_pages_v_blocks_fd_service_calc_option_groups_order_idx" ON "_pages_v_blocks_fd_service_calc_option_groups" USING btree ("_order");
CREATE INDEX "_pages_v_blocks_fd_service_calc_option_groups_parent_id_idx" ON "_pages_v_blocks_fd_service_calc_option_groups" USING btree ("_parent_id");
CREATE UNIQUE INDEX "_pages_v_blocks_fd_service_calc_option_groups_locales_locale" ON "_pages_v_blocks_fd_service_calc_option_groups_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "_pages_v_blocks_fd_service_calc_resources_order_idx" ON "_pages_v_blocks_fd_service_calc_resources" USING btree ("_order");
CREATE INDEX "_pages_v_blocks_fd_service_calc_resources_parent_id_idx" ON "_pages_v_blocks_fd_service_calc_resources" USING btree ("_parent_id");
CREATE UNIQUE INDEX "_pages_v_blocks_fd_service_calc_resources_locales_locale_par" ON "_pages_v_blocks_fd_service_calc_resources_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "_pages_v_blocks_fd_service_calc_addons_order_idx" ON "_pages_v_blocks_fd_service_calc_addons" USING btree ("_order");
CREATE INDEX "_pages_v_blocks_fd_service_calc_addons_parent_id_idx" ON "_pages_v_blocks_fd_service_calc_addons" USING btree ("_parent_id");
CREATE UNIQUE INDEX "_pages_v_blocks_fd_service_calc_addons_locales_locale_parent" ON "_pages_v_blocks_fd_service_calc_addons_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "_pages_v_blocks_fd_service_calc_fixed_fees_order_idx" ON "_pages_v_blocks_fd_service_calc_fixed_fees" USING btree ("_order");
CREATE INDEX "_pages_v_blocks_fd_service_calc_fixed_fees_parent_id_idx" ON "_pages_v_blocks_fd_service_calc_fixed_fees" USING btree ("_parent_id");
CREATE UNIQUE INDEX "_pages_v_blocks_fd_service_calc_fixed_fees_locales_locale_pa" ON "_pages_v_blocks_fd_service_calc_fixed_fees_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "_pages_v_blocks_fd_service_calc_order_idx" ON "_pages_v_blocks_fd_service_calc" USING btree ("_order");
CREATE INDEX "_pages_v_blocks_fd_service_calc_parent_id_idx" ON "_pages_v_blocks_fd_service_calc" USING btree ("_parent_id");
CREATE INDEX "_pages_v_blocks_fd_service_calc_path_idx" ON "_pages_v_blocks_fd_service_calc" USING btree ("_path");
CREATE UNIQUE INDEX "_pages_v_blocks_fd_service_calc_locales_locale_parent_id_uni" ON "_pages_v_blocks_fd_service_calc_locales" USING btree ("_locale","_parent_id");
`)
}
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
await db.execute(sql`
CREATE TYPE "public"."enum_pages_blocks_fd_service_calculator_section_background" AS ENUM('white', 'gray', 'navy');
CREATE TYPE "public"."enum__pages_v_blocks_fd_service_calculator_section_background" AS ENUM('white', 'gray', 'navy');
CREATE TABLE "pages_blocks_fd_service_calculator_option_groups_options" (
"_order" integer NOT NULL,
"_parent_id" varchar NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"price" numeric DEFAULT 0
);
CREATE TABLE "pages_blocks_fd_service_calculator_option_groups_options_locales" (
"label" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
CREATE TABLE "pages_blocks_fd_service_calculator_option_groups" (
"_order" integer NOT NULL,
"_parent_id" varchar NOT NULL,
"id" varchar PRIMARY KEY NOT NULL
);
CREATE TABLE "pages_blocks_fd_service_calculator_option_groups_locales" (
"group_label" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
CREATE TABLE "pages_blocks_fd_service_calculator_resources" (
"_order" integer NOT NULL,
"_parent_id" varchar NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"price_per_unit" numeric,
"default_value" numeric DEFAULT 0,
"min" numeric DEFAULT 0,
"max" numeric DEFAULT 1000,
"step" numeric DEFAULT 1
);
CREATE TABLE "pages_blocks_fd_service_calculator_resources_locales" (
"label" varchar,
"unit" varchar DEFAULT 'GB',
"summary_template" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
CREATE TABLE "pages_blocks_fd_service_calculator_addons" (
"_order" integer NOT NULL,
"_parent_id" varchar NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"price" numeric
);
CREATE TABLE "pages_blocks_fd_service_calculator_addons_locales" (
"label" varchar,
"description" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
CREATE TABLE "pages_blocks_fd_service_calculator_fixed_fees" (
"_order" integer NOT NULL,
"_parent_id" varchar NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"amount" numeric
);
CREATE TABLE "pages_blocks_fd_service_calculator_fixed_fees_locales" (
"label" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
CREATE TABLE "pages_blocks_fd_service_calculator" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"_path" text NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"order_cta_link" varchar DEFAULT '/kontakt',
"contact_cta_link" varchar DEFAULT '/kontakt',
"section_background" "enum_pages_blocks_fd_service_calculator_section_background" DEFAULT 'white',
"discount_percent" numeric,
"anchor_id" varchar,
"block_name" varchar
);
CREATE TABLE "pages_blocks_fd_service_calculator_locales" (
"heading" varchar DEFAULT 'Beräkna din kostnad',
"description" varchar,
"summary_heading" varchar DEFAULT 'Kostnadsöversikt',
"total_label" varchar DEFAULT 'Totalt per månad',
"total_suffix" varchar DEFAULT 'exkl. moms',
"order_cta_text" varchar DEFAULT 'Beställ',
"contact_cta_text" varchar DEFAULT 'Frågor? Kontakta oss',
"discount_label" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
CREATE TABLE "_pages_v_blocks_fd_service_calculator_option_groups_options" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"id" serial PRIMARY KEY NOT NULL,
"price" numeric DEFAULT 0,
"_uuid" varchar
);
CREATE TABLE "_pages_v_blocks_fd_service_calculator_option_groups_options_locales" (
"label" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" integer NOT NULL
);
CREATE TABLE "_pages_v_blocks_fd_service_calculator_option_groups" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"id" serial PRIMARY KEY NOT NULL,
"_uuid" varchar
);
CREATE TABLE "_pages_v_blocks_fd_service_calculator_option_groups_locales" (
"group_label" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" integer NOT NULL
);
CREATE TABLE "_pages_v_blocks_fd_service_calculator_resources" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"id" serial PRIMARY KEY NOT NULL,
"price_per_unit" numeric,
"default_value" numeric DEFAULT 0,
"min" numeric DEFAULT 0,
"max" numeric DEFAULT 1000,
"step" numeric DEFAULT 1,
"_uuid" varchar
);
CREATE TABLE "_pages_v_blocks_fd_service_calculator_resources_locales" (
"label" varchar,
"unit" varchar DEFAULT 'GB',
"summary_template" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" integer NOT NULL
);
CREATE TABLE "_pages_v_blocks_fd_service_calculator_addons" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"id" serial PRIMARY KEY NOT NULL,
"price" numeric,
"_uuid" varchar
);
CREATE TABLE "_pages_v_blocks_fd_service_calculator_addons_locales" (
"label" varchar,
"description" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" integer NOT NULL
);
CREATE TABLE "_pages_v_blocks_fd_service_calculator_fixed_fees" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"id" serial PRIMARY KEY NOT NULL,
"amount" numeric,
"_uuid" varchar
);
CREATE TABLE "_pages_v_blocks_fd_service_calculator_fixed_fees_locales" (
"label" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" integer NOT NULL
);
CREATE TABLE "_pages_v_blocks_fd_service_calculator" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"_path" text NOT NULL,
"id" serial PRIMARY KEY NOT NULL,
"order_cta_link" varchar DEFAULT '/kontakt',
"contact_cta_link" varchar DEFAULT '/kontakt',
"section_background" "enum__pages_v_blocks_fd_service_calculator_section_background" DEFAULT 'white',
"discount_percent" numeric,
"anchor_id" varchar,
"_uuid" varchar,
"block_name" varchar
);
CREATE TABLE "_pages_v_blocks_fd_service_calculator_locales" (
"heading" varchar DEFAULT 'Beräkna din kostnad',
"description" varchar,
"summary_heading" varchar DEFAULT 'Kostnadsöversikt',
"total_label" varchar DEFAULT 'Totalt per månad',
"total_suffix" varchar DEFAULT 'exkl. moms',
"order_cta_text" varchar DEFAULT 'Beställ',
"contact_cta_text" varchar DEFAULT 'Frågor? Kontakta oss',
"discount_label" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" integer NOT NULL
);
DROP TABLE "pages_blocks_fd_service_calc_option_groups_options" CASCADE;
DROP TABLE "pages_blocks_fd_service_calc_option_groups_options_locales" CASCADE;
DROP TABLE "pages_blocks_fd_service_calc_option_groups" CASCADE;
DROP TABLE "pages_blocks_fd_service_calc_option_groups_locales" CASCADE;
DROP TABLE "pages_blocks_fd_service_calc_resources" CASCADE;
DROP TABLE "pages_blocks_fd_service_calc_resources_locales" CASCADE;
DROP TABLE "pages_blocks_fd_service_calc_addons" CASCADE;
DROP TABLE "pages_blocks_fd_service_calc_addons_locales" CASCADE;
DROP TABLE "pages_blocks_fd_service_calc_fixed_fees" CASCADE;
DROP TABLE "pages_blocks_fd_service_calc_fixed_fees_locales" CASCADE;
DROP TABLE "pages_blocks_fd_service_calc" CASCADE;
DROP TABLE "pages_blocks_fd_service_calc_locales" CASCADE;
DROP TABLE "_pages_v_blocks_fd_service_calc_option_groups_options" CASCADE;
DROP TABLE "_pages_v_blocks_fd_service_calc_option_groups_options_locales" CASCADE;
DROP TABLE "_pages_v_blocks_fd_service_calc_option_groups" CASCADE;
DROP TABLE "_pages_v_blocks_fd_service_calc_option_groups_locales" CASCADE;
DROP TABLE "_pages_v_blocks_fd_service_calc_resources" CASCADE;
DROP TABLE "_pages_v_blocks_fd_service_calc_resources_locales" CASCADE;
DROP TABLE "_pages_v_blocks_fd_service_calc_addons" CASCADE;
DROP TABLE "_pages_v_blocks_fd_service_calc_addons_locales" CASCADE;
DROP TABLE "_pages_v_blocks_fd_service_calc_fixed_fees" CASCADE;
DROP TABLE "_pages_v_blocks_fd_service_calc_fixed_fees_locales" CASCADE;
DROP TABLE "_pages_v_blocks_fd_service_calc" CASCADE;
DROP TABLE "_pages_v_blocks_fd_service_calc_locales" CASCADE;
ALTER TABLE "pages_blocks_fd_service_calculator_option_groups_options" ADD CONSTRAINT "pages_blocks_fd_service_calculator_option_groups_options_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calculator_option_groups"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calculator_option_groups_options_locales" ADD CONSTRAINT "pages_blocks_fd_service_calculator_option_groups_options__fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calculator_option_groups_options"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calculator_option_groups" ADD CONSTRAINT "pages_blocks_fd_service_calculator_option_groups_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calculator"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calculator_option_groups_locales" ADD CONSTRAINT "pages_blocks_fd_service_calculator_option_groups_locales__fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calculator_option_groups"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calculator_resources" ADD CONSTRAINT "pages_blocks_fd_service_calculator_resources_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calculator"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calculator_resources_locales" ADD CONSTRAINT "pages_blocks_fd_service_calculator_resources_locales_pare_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calculator_resources"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calculator_addons" ADD CONSTRAINT "pages_blocks_fd_service_calculator_addons_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calculator"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calculator_addons_locales" ADD CONSTRAINT "pages_blocks_fd_service_calculator_addons_locales_parent__fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calculator_addons"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calculator_fixed_fees" ADD CONSTRAINT "pages_blocks_fd_service_calculator_fixed_fees_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calculator"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calculator_fixed_fees_locales" ADD CONSTRAINT "pages_blocks_fd_service_calculator_fixed_fees_locales_par_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calculator_fixed_fees"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calculator" ADD CONSTRAINT "pages_blocks_fd_service_calculator_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_fd_service_calculator_locales" ADD CONSTRAINT "pages_blocks_fd_service_calculator_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_fd_service_calculator"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calculator_option_groups_options" ADD CONSTRAINT "_pages_v_blocks_fd_service_calculator_option_groups_options_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calculator_option_groups"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calculator_option_groups_options_locales" ADD CONSTRAINT "_pages_v_blocks_fd_service_calculator_option_groups_optio_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calculator_option_groups_options"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calculator_option_groups" ADD CONSTRAINT "_pages_v_blocks_fd_service_calculator_option_groups_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calculator"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calculator_option_groups_locales" ADD CONSTRAINT "_pages_v_blocks_fd_service_calculator_option_groups_local_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calculator_option_groups"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calculator_resources" ADD CONSTRAINT "_pages_v_blocks_fd_service_calculator_resources_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calculator"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calculator_resources_locales" ADD CONSTRAINT "_pages_v_blocks_fd_service_calculator_resources_locales_p_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calculator_resources"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calculator_addons" ADD CONSTRAINT "_pages_v_blocks_fd_service_calculator_addons_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calculator"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calculator_addons_locales" ADD CONSTRAINT "_pages_v_blocks_fd_service_calculator_addons_locales_pare_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calculator_addons"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calculator_fixed_fees" ADD CONSTRAINT "_pages_v_blocks_fd_service_calculator_fixed_fees_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calculator"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calculator_fixed_fees_locales" ADD CONSTRAINT "_pages_v_blocks_fd_service_calculator_fixed_fees_locales__fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calculator_fixed_fees"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calculator" ADD CONSTRAINT "_pages_v_blocks_fd_service_calculator_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "_pages_v_blocks_fd_service_calculator_locales" ADD CONSTRAINT "_pages_v_blocks_fd_service_calculator_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."_pages_v_blocks_fd_service_calculator"("id") ON DELETE cascade ON UPDATE no action;
CREATE INDEX "pages_blocks_fd_service_calculator_option_groups_options_order_idx" ON "pages_blocks_fd_service_calculator_option_groups_options" USING btree ("_order");
CREATE INDEX "pages_blocks_fd_service_calculator_option_groups_options_parent_id_idx" ON "pages_blocks_fd_service_calculator_option_groups_options" USING btree ("_parent_id");
CREATE UNIQUE INDEX "pages_blocks_fd_service_calculator_option_groups_options_loc" ON "pages_blocks_fd_service_calculator_option_groups_options_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "pages_blocks_fd_service_calculator_option_groups_order_idx" ON "pages_blocks_fd_service_calculator_option_groups" USING btree ("_order");
CREATE INDEX "pages_blocks_fd_service_calculator_option_groups_parent_id_idx" ON "pages_blocks_fd_service_calculator_option_groups" USING btree ("_parent_id");
CREATE UNIQUE INDEX "pages_blocks_fd_service_calculator_option_groups_locales_loc" ON "pages_blocks_fd_service_calculator_option_groups_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "pages_blocks_fd_service_calculator_resources_order_idx" ON "pages_blocks_fd_service_calculator_resources" USING btree ("_order");
CREATE INDEX "pages_blocks_fd_service_calculator_resources_parent_id_idx" ON "pages_blocks_fd_service_calculator_resources" USING btree ("_parent_id");
CREATE UNIQUE INDEX "pages_blocks_fd_service_calculator_resources_locales_locale_" ON "pages_blocks_fd_service_calculator_resources_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "pages_blocks_fd_service_calculator_addons_order_idx" ON "pages_blocks_fd_service_calculator_addons" USING btree ("_order");
CREATE INDEX "pages_blocks_fd_service_calculator_addons_parent_id_idx" ON "pages_blocks_fd_service_calculator_addons" USING btree ("_parent_id");
CREATE UNIQUE INDEX "pages_blocks_fd_service_calculator_addons_locales_locale_par" ON "pages_blocks_fd_service_calculator_addons_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "pages_blocks_fd_service_calculator_fixed_fees_order_idx" ON "pages_blocks_fd_service_calculator_fixed_fees" USING btree ("_order");
CREATE INDEX "pages_blocks_fd_service_calculator_fixed_fees_parent_id_idx" ON "pages_blocks_fd_service_calculator_fixed_fees" USING btree ("_parent_id");
CREATE UNIQUE INDEX "pages_blocks_fd_service_calculator_fixed_fees_locales_locale" ON "pages_blocks_fd_service_calculator_fixed_fees_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "pages_blocks_fd_service_calculator_order_idx" ON "pages_blocks_fd_service_calculator" USING btree ("_order");
CREATE INDEX "pages_blocks_fd_service_calculator_parent_id_idx" ON "pages_blocks_fd_service_calculator" USING btree ("_parent_id");
CREATE INDEX "pages_blocks_fd_service_calculator_path_idx" ON "pages_blocks_fd_service_calculator" USING btree ("_path");
CREATE UNIQUE INDEX "pages_blocks_fd_service_calculator_locales_locale_parent_id_" ON "pages_blocks_fd_service_calculator_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "_pages_v_blocks_fd_service_calculator_option_groups_options_order_idx" ON "_pages_v_blocks_fd_service_calculator_option_groups_options" USING btree ("_order");
CREATE INDEX "_pages_v_blocks_fd_service_calculator_option_groups_options_parent_id_idx" ON "_pages_v_blocks_fd_service_calculator_option_groups_options" USING btree ("_parent_id");
CREATE UNIQUE INDEX "_pages_v_blocks_fd_service_calculator_option_groups_options_" ON "_pages_v_blocks_fd_service_calculator_option_groups_options_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "_pages_v_blocks_fd_service_calculator_option_groups_order_idx" ON "_pages_v_blocks_fd_service_calculator_option_groups" USING btree ("_order");
CREATE INDEX "_pages_v_blocks_fd_service_calculator_option_groups_parent_id_idx" ON "_pages_v_blocks_fd_service_calculator_option_groups" USING btree ("_parent_id");
CREATE UNIQUE INDEX "_pages_v_blocks_fd_service_calculator_option_groups_locales_" ON "_pages_v_blocks_fd_service_calculator_option_groups_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "_pages_v_blocks_fd_service_calculator_resources_order_idx" ON "_pages_v_blocks_fd_service_calculator_resources" USING btree ("_order");
CREATE INDEX "_pages_v_blocks_fd_service_calculator_resources_parent_id_idx" ON "_pages_v_blocks_fd_service_calculator_resources" USING btree ("_parent_id");
CREATE UNIQUE INDEX "_pages_v_blocks_fd_service_calculator_resources_locales_loca" ON "_pages_v_blocks_fd_service_calculator_resources_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "_pages_v_blocks_fd_service_calculator_addons_order_idx" ON "_pages_v_blocks_fd_service_calculator_addons" USING btree ("_order");
CREATE INDEX "_pages_v_blocks_fd_service_calculator_addons_parent_id_idx" ON "_pages_v_blocks_fd_service_calculator_addons" USING btree ("_parent_id");
CREATE UNIQUE INDEX "_pages_v_blocks_fd_service_calculator_addons_locales_locale_" ON "_pages_v_blocks_fd_service_calculator_addons_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "_pages_v_blocks_fd_service_calculator_fixed_fees_order_idx" ON "_pages_v_blocks_fd_service_calculator_fixed_fees" USING btree ("_order");
CREATE INDEX "_pages_v_blocks_fd_service_calculator_fixed_fees_parent_id_idx" ON "_pages_v_blocks_fd_service_calculator_fixed_fees" USING btree ("_parent_id");
CREATE UNIQUE INDEX "_pages_v_blocks_fd_service_calculator_fixed_fees_locales_loc" ON "_pages_v_blocks_fd_service_calculator_fixed_fees_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "_pages_v_blocks_fd_service_calculator_order_idx" ON "_pages_v_blocks_fd_service_calculator" USING btree ("_order");
CREATE INDEX "_pages_v_blocks_fd_service_calculator_parent_id_idx" ON "_pages_v_blocks_fd_service_calculator" USING btree ("_parent_id");
CREATE INDEX "_pages_v_blocks_fd_service_calculator_path_idx" ON "_pages_v_blocks_fd_service_calculator" USING btree ("_path");
CREATE UNIQUE INDEX "_pages_v_blocks_fd_service_calculator_locales_locale_parent_" ON "_pages_v_blocks_fd_service_calculator_locales" USING btree ("_locale","_parent_id");
DROP TYPE "public"."enum_pages_blocks_fd_service_calc_section_background";
DROP TYPE "public"."enum__pages_v_blocks_fd_service_calc_section_background";`)
}

View File

@ -1,9 +1,15 @@
import * as migration_20260224_091812_add_anchor_links from './20260224_091812_add_anchor_links';
import * as migration_20260224_133833 from './20260224_133833';
export const migrations = [
{
up: migration_20260224_091812_add_anchor_links.up,
down: migration_20260224_091812_add_anchor_links.down,
name: '20260224_091812_add_anchor_links'
name: '20260224_091812_add_anchor_links',
},
{
up: migration_20260224_133833.up,
down: migration_20260224_133833.down,
name: '20260224_133833'
},
];

View File

@ -1261,7 +1261,7 @@ export interface FDServiceCalculatorBlock {
anchorId?: string | null;
id?: string | null;
blockName?: string | null;
blockType: 'fdServiceCalculator';
blockType: 'fdServiceCalc';
}
/**
* This interface was referenced by `Config`'s JSON-Schema
@ -1873,7 +1873,7 @@ export interface PagesSelect<T extends boolean = true> {
fdServiceChooser?: T | FDServiceChooserBlockSelect<T>;
fdDataTable?: T | FDDataTableBlockSelect<T>;
fdVpsCalculator?: T | FDVpsCalculatorBlockSelect<T>;
fdServiceCalculator?: T | FDServiceCalculatorBlockSelect<T>;
fdServiceCalc?: T | FDServiceCalculatorBlockSelect<T>;
fdTags?: T | FDTagsBlockSelect<T>;
fdText?: T | FDTextBlockSelect<T>;
fdCodeEmbed?: T | FDCodeEmbedBlockSelect<T>;

View File

@ -5,16 +5,17 @@ import { unstable_cache } from 'next/cache'
type Global = keyof Config['globals']
async function getGlobal(slug: Global, depth = 0) {
async function getGlobal(slug: Global, depth = 0, locale = 'sv') {
const payload = await getPayload({ config: configPromise })
const global = await payload.findGlobal({
slug,
depth,
locale: locale as 'sv' | 'en',
})
return global
}
export const getCachedGlobal = (slug: Global, depth = 0) =>
unstable_cache(async () => getGlobal(slug, depth), [slug], {
export const getCachedGlobal = (slug: Global, depth = 0, locale = 'sv') =>
unstable_cache(async () => getGlobal(slug, depth, locale), [slug, locale], {
tags: [`global_${slug}`],
})