From 84285335a446ff7c8e53eb2ea51ffc3910c361c4 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 17 May 2026 08:53:19 -0400 Subject: [PATCH] remove company website pages --- .env.docker.dev | 6 +- Dockerfile.production | 8 +- apps/admin/package.json | 4 +- .../companies/[id]/HomepageLayoutEditor.tsx | 232 ---- .../src/app/dashboard/companies/[id]/page.tsx | 773 ------------ apps/admin/src/app/dashboard/layout.tsx | 2 +- apps/admin/src/app/login/page.tsx | 2 +- apps/admin/src/lib/appUrls.ts | 5 +- apps/dashboard/package.json | 4 +- .../src/app/sign-in/[[...sign-in]]/page.tsx | 2 +- apps/dashboard/src/lib/appUrls.ts | 5 +- apps/dashboard/src/lib/urls.ts | 2 +- apps/marketplace/next.config.js | 1 - apps/marketplace/package.json | 4 +- apps/marketplace/src/app/HomeContent.tsx | 2 +- .../src/app/branded-website/page.tsx | 5 - .../src/app/pricing/PricingClient.tsx | 2 +- .../src/app/renter/sign-in/page.tsx | 2 +- .../src/app/renter/sign-up/page.tsx | 2 +- .../src/components/MarketplaceShell.tsx | 6 +- .../src/components/WorkspaceFrame.tsx | 11 +- .../src/components/WorkspaceTabs.tsx | 2 +- apps/marketplace/src/lib/appUrls.ts | 5 +- apps/public-site/next-env.d.ts | 5 - apps/public-site/next.config.js | 22 - apps/public-site/package.json | 32 - apps/public-site/postcss.config.js | 6 - apps/public-site/public/rentalcardrive.png | Bin 1172463 -> 0 bytes apps/public-site/src/app/about/page.tsx | 96 -- apps/public-site/src/app/blog/page.tsx | 44 - apps/public-site/src/app/book/BookClient.tsx | 789 ------------ .../src/app/book/confirmation/page.tsx | 141 --- apps/public-site/src/app/book/page.tsx | 36 - apps/public-site/src/app/contact/page.tsx | 30 - apps/public-site/src/app/globals.css | 98 -- apps/public-site/src/app/layout.tsx | 154 --- apps/public-site/src/app/offers/page.tsx | 49 - apps/public-site/src/app/page.tsx | 307 ----- apps/public-site/src/app/pricing/page.tsx | 139 --- .../src/app/vehicles/VehicleFilters.tsx | 127 -- .../src/app/vehicles/[id]/page.tsx | 96 -- apps/public-site/src/app/vehicles/page.tsx | 155 --- .../src/components/PublicLanguageSwitcher.tsx | 59 - .../src/components/PublicThemeSwitcher.tsx | 68 -- apps/public-site/src/lib/api.ts | 32 - apps/public-site/src/lib/i18n.server.ts | 11 - apps/public-site/src/lib/i18n.ts | 1063 ----------------- apps/public-site/src/lib/pageSections.ts | 29 - apps/public-site/src/lib/preferences.ts | 103 -- apps/public-site/src/middleware.ts | 63 - apps/public-site/tailwind.config.ts | 16 - apps/public-site/tsconfig.json | 23 - deploy_dev.txt | 45 + docker-compose.dev.yml | 17 - docker-compose.production.yml | 41 +- packages/types/src/index.ts | 2 - packages/types/src/public-homepage-layout.ts | 87 -- packages/types/src/public-site-sections.ts | 99 -- 58 files changed, 106 insertions(+), 5065 deletions(-) delete mode 100644 apps/admin/src/app/dashboard/companies/[id]/HomepageLayoutEditor.tsx delete mode 100644 apps/marketplace/src/app/branded-website/page.tsx delete mode 100644 apps/public-site/next-env.d.ts delete mode 100644 apps/public-site/next.config.js delete mode 100644 apps/public-site/package.json delete mode 100644 apps/public-site/postcss.config.js delete mode 100644 apps/public-site/public/rentalcardrive.png delete mode 100644 apps/public-site/src/app/about/page.tsx delete mode 100644 apps/public-site/src/app/blog/page.tsx delete mode 100644 apps/public-site/src/app/book/BookClient.tsx delete mode 100644 apps/public-site/src/app/book/confirmation/page.tsx delete mode 100644 apps/public-site/src/app/book/page.tsx delete mode 100644 apps/public-site/src/app/contact/page.tsx delete mode 100644 apps/public-site/src/app/globals.css delete mode 100644 apps/public-site/src/app/layout.tsx delete mode 100644 apps/public-site/src/app/offers/page.tsx delete mode 100644 apps/public-site/src/app/page.tsx delete mode 100644 apps/public-site/src/app/pricing/page.tsx delete mode 100644 apps/public-site/src/app/vehicles/VehicleFilters.tsx delete mode 100644 apps/public-site/src/app/vehicles/[id]/page.tsx delete mode 100644 apps/public-site/src/app/vehicles/page.tsx delete mode 100644 apps/public-site/src/components/PublicLanguageSwitcher.tsx delete mode 100644 apps/public-site/src/components/PublicThemeSwitcher.tsx delete mode 100644 apps/public-site/src/lib/api.ts delete mode 100644 apps/public-site/src/lib/i18n.server.ts delete mode 100644 apps/public-site/src/lib/i18n.ts delete mode 100644 apps/public-site/src/lib/pageSections.ts delete mode 100644 apps/public-site/src/lib/preferences.ts delete mode 100644 apps/public-site/src/middleware.ts delete mode 100644 apps/public-site/tailwind.config.ts delete mode 100644 apps/public-site/tsconfig.json create mode 100644 deploy_dev.txt delete mode 100644 packages/types/src/public-homepage-layout.ts delete mode 100644 packages/types/src/public-site-sections.ts diff --git a/.env.docker.dev b/.env.docker.dev index a651df8..b69ad02 100644 --- a/.env.docker.dev +++ b/.env.docker.dev @@ -4,11 +4,9 @@ API_PORT=4000 API_URL=http://localhost:4000 API_INTERNAL_URL=http://api:4000/api/v1 NEXT_PUBLIC_API_URL=http://localhost:4000/api/v1 -NEXT_PUBLIC_MARKETING_URL=http://localhost:3003 -NEXT_PUBLIC_MARKETPLACE_URL=http://localhost:3000/marketplace +NEXT_PUBLIC_MARKETPLACE_URL=http://localhost:3000 NEXT_PUBLIC_DASHBOARD_URL=http://localhost:3001/dashboard NEXT_PUBLIC_ADMIN_URL=http://localhost:3002/admin -NEXT_PUBLIC_PUBLIC_SITE_DOMAIN=localhost:3003 DASHBOARD_URL=http://localhost:3001/dashboard ADMIN_URL=http://localhost:3002/admin JWT_SECRET=dev-secret @@ -21,7 +19,7 @@ ADMIN_SEED_LAST_NAME=Admin NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY= CLERK_SECRET_KEY= NODE_ENV=development -CORS_ORIGINS=http://localhost:3000,http://localhost:3001,http://localhost:3002,http://localhost:3003 +CORS_ORIGINS=http://localhost:3000,http://localhost:3001,http://localhost:3002,http://localhost:3003,http://localhost:4000 # Email - disable Resend (placeholder), use SMTP instead RESEND_API_KEY=re_... diff --git a/Dockerfile.production b/Dockerfile.production index ed81395..ee6ed6b 100644 --- a/Dockerfile.production +++ b/Dockerfile.production @@ -10,17 +10,13 @@ COPY packages ./packages # NEXT_PUBLIC_* vars must be present at build time — they are inlined into JS bundles ARG NEXT_PUBLIC_API_URL -ARG NEXT_PUBLIC_MARKETING_URL ARG NEXT_PUBLIC_MARKETPLACE_URL ARG NEXT_PUBLIC_DASHBOARD_URL ARG NEXT_PUBLIC_ADMIN_URL -ARG NEXT_PUBLIC_PUBLIC_SITE_DOMAIN ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL \ - NEXT_PUBLIC_MARKETING_URL=$NEXT_PUBLIC_MARKETING_URL \ NEXT_PUBLIC_MARKETPLACE_URL=$NEXT_PUBLIC_MARKETPLACE_URL \ NEXT_PUBLIC_DASHBOARD_URL=$NEXT_PUBLIC_DASHBOARD_URL \ - NEXT_PUBLIC_ADMIN_URL=$NEXT_PUBLIC_ADMIN_URL \ - NEXT_PUBLIC_PUBLIC_SITE_DOMAIN=$NEXT_PUBLIC_PUBLIC_SITE_DOMAIN + NEXT_PUBLIC_ADMIN_URL=$NEXT_PUBLIC_ADMIN_URL RUN npm install RUN npm run db:generate @@ -39,6 +35,6 @@ COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/apps ./apps COPY --from=builder /app/packages ./packages -EXPOSE 3000 4000 +EXPOSE 3000 3001 3002 4000 CMD ["npm", "run", "start", "--workspace", "@rentaldrivego/api"] diff --git a/apps/admin/package.json b/apps/admin/package.json index 0503036..80668f9 100644 --- a/apps/admin/package.json +++ b/apps/admin/package.json @@ -4,11 +4,11 @@ "private": true, "scripts": { "predev": "npm run build --workspace @rentaldrivego/types", - "dev": "next dev -p 3003", + "dev": "next dev -p 3002", "prebuild": "npm run build --workspace @rentaldrivego/types", "build": "next build", "prestart": "npm run build --workspace @rentaldrivego/types", - "start": "next start -p 3003", + "start": "next start -p 3002", "type-check": "tsc --noEmit" }, "dependencies": { diff --git a/apps/admin/src/app/dashboard/companies/[id]/HomepageLayoutEditor.tsx b/apps/admin/src/app/dashboard/companies/[id]/HomepageLayoutEditor.tsx deleted file mode 100644 index ec37300..0000000 --- a/apps/admin/src/app/dashboard/companies/[id]/HomepageLayoutEditor.tsx +++ /dev/null @@ -1,232 +0,0 @@ -'use client' - -import { useEffect, useRef, useState } from 'react' -import { - PUBLIC_HOMEPAGE_GRID_COLUMNS, - PUBLIC_HOMEPAGE_GRID_ROWS, - getPublicHomepageSectionLimits, - type PublicHomepageLayout, - type PublicHomepageLayoutItem, - type PublicHomepageSectionType, -} from '@rentaldrivego/types' - -type Props = { - layout: PublicHomepageLayout - availableSections: PublicHomepageSectionType[] - onChange: (layout: PublicHomepageLayout) => void - onAddSection: (type: PublicHomepageSectionType) => void - onRemoveSection: (type: PublicHomepageSectionType) => void -} - -type Interaction = { - itemId: string - mode: 'move' | 'resize' - startX: number - startY: number - origin: PublicHomepageLayoutItem -} - -const ROW_HEIGHT = 52 - -const SECTION_META: Record = { - hero: { label: 'Hero', tint: 'from-sky-500 to-cyan-400', description: 'Headline, CTA buttons, and brand media.' }, - offers: { label: 'Offers', tint: 'from-emerald-500 to-lime-400', description: 'Promotions and campaign cards.' }, - vehicles: { label: 'Vehicles', tint: 'from-amber-500 to-orange-400', description: 'Published fleet grid.' }, - pricing: { label: 'Pricing', tint: 'from-fuchsia-500 to-rose-400', description: 'Plans and pricing content.' }, -} - -function clamp(value: number, min: number, max: number) { - return Math.min(Math.max(value, min), max) -} - -export function HomepageLayoutEditor({ layout, availableSections, onChange, onAddSection, onRemoveSection }: Props) { - const canvasRef = useRef(null) - const [interaction, setInteraction] = useState(null) - - useEffect(() => { - if (!interaction) return - const snap = interaction - - function handlePointerMove(event: PointerEvent) { - const canvas = canvasRef.current - if (!canvas) return - const rect = canvas.getBoundingClientRect() - const colWidth = rect.width / PUBLIC_HOMEPAGE_GRID_COLUMNS - const deltaCols = Math.round((event.clientX - snap.startX) / colWidth) - const deltaRows = Math.round((event.clientY - snap.startY) / ROW_HEIGHT) - const limits = getPublicHomepageSectionLimits(snap.origin.type) - - onChange({ - items: layout.items.map((item) => { - if (item.id !== snap.itemId) return item - if (snap.mode === 'move') { - return { - ...item, - x: clamp(snap.origin.x + deltaCols, 1, PUBLIC_HOMEPAGE_GRID_COLUMNS - snap.origin.w + 1), - y: clamp(snap.origin.y + deltaRows, 1, PUBLIC_HOMEPAGE_GRID_ROWS - snap.origin.h + 1), - } - } - - const nextW = clamp( - snap.origin.w + deltaCols, - limits.minW, - Math.min(limits.maxW, PUBLIC_HOMEPAGE_GRID_COLUMNS - snap.origin.x + 1), - ) - const nextH = clamp( - snap.origin.h + deltaRows, - limits.minH, - Math.min(limits.maxH, PUBLIC_HOMEPAGE_GRID_ROWS - snap.origin.y + 1), - ) - - return { - ...item, - w: nextW, - h: nextH, - } - }), - }) - } - - function handlePointerUp() { - setInteraction(null) - } - - window.addEventListener('pointermove', handlePointerMove) - window.addEventListener('pointerup', handlePointerUp) - return () => { - window.removeEventListener('pointermove', handlePointerMove) - window.removeEventListener('pointerup', handlePointerUp) - } - }, [interaction, layout.items, onChange]) - - return ( -
-
-
-

Homepage layout

-

Add sections, drag them anywhere on the grid, and resize them from the bottom-right handle.

-
-
- {availableSections.map((type) => ( - - ))} -
-
- -
- {layout.items.map((item) => { - const meta = SECTION_META[item.type] - return ( -
- - -
-

{meta.description}

-
- x{item.x} y{item.y} - -
-
- - -
- ) - })} -
- -
- {layout.items.map((item) => { - const meta = SECTION_META[item.type] - return ( -
-
-
-

{meta.label}

-

{meta.description}

-
- -
-

Desktop drag canvas is available on larger screens.

-
- ) - })} -
-
- ) -} diff --git a/apps/admin/src/app/dashboard/companies/[id]/page.tsx b/apps/admin/src/app/dashboard/companies/[id]/page.tsx index 54fb5e4..a4606f7 100644 --- a/apps/admin/src/app/dashboard/companies/[id]/page.tsx +++ b/apps/admin/src/app/dashboard/companies/[id]/page.tsx @@ -3,15 +3,6 @@ import { useEffect, useState } from 'react' import { useParams, useRouter } from 'next/navigation' import Link from 'next/link' -import { - clonePublicHomepageLayout, - clonePublicSitePageSections, - resolvePublicHomepageLayout, - type PublicHomepageLayout, - type PublicHomepageSectionType, - type PublicSitePageSections, -} from '@rentaldrivego/types' -import { HomepageLayoutEditor } from './HomepageLayoutEditor' const API_BASE = '/api/v1' @@ -51,42 +42,6 @@ interface CompanyDetail { defaultLocale: string defaultCurrency: string isListedOnMarketplace: boolean - homePageConfig: { - heroTitle: string | null - heroDescription: string | null - viewOffersLabel: string | null - viewPricingLabel: string | null - contactCompanyLabel: string | null - activeOffersTitle: string | null - seeAllOffersLabel: string | null - noActiveOffersLabel: string | null - publishedVehiclesTitle: string | null - viewVehicleLabel: string | null - pricingEyebrow: string | null - pricingTitle: string | null - pricingDescription: string | null - showOffers: boolean - showVehicles: boolean - showPricing: boolean - layout?: PublicHomepageLayout | null - } | null - menuConfig: { - aboutLabel: string | null - vehiclesLabel: string | null - offersLabel: string | null - pricingLabel: string | null - blogLabel: string | null - contactLabel: string | null - bookCarLabel: string | null - siteNavigationLabel: string | null - showAbout: boolean - showVehicles: boolean - showOffers: boolean - showPricing: boolean - showBlog: boolean - showContact: boolean - pageSections?: PublicSitePageSections | null - } | null } | null contractSettings: { legalName: string | null @@ -159,42 +114,6 @@ interface FormState { defaultLocale: string defaultCurrency: string isListedOnMarketplace: boolean - homePageConfig: { - heroTitle: string - heroDescription: string - viewOffersLabel: string - viewPricingLabel: string - contactCompanyLabel: string - activeOffersTitle: string - seeAllOffersLabel: string - noActiveOffersLabel: string - publishedVehiclesTitle: string - viewVehicleLabel: string - pricingEyebrow: string - pricingTitle: string - pricingDescription: string - showOffers: boolean - showVehicles: boolean - showPricing: boolean - layout: PublicHomepageLayout - } - menuConfig: { - aboutLabel: string - vehiclesLabel: string - offersLabel: string - pricingLabel: string - blogLabel: string - contactLabel: string - bookCarLabel: string - siteNavigationLabel: string - showAbout: boolean - showVehicles: boolean - showOffers: boolean - showPricing: boolean - showBlog: boolean - showContact: boolean - pageSections: PublicSitePageSections - } } contractSettings: { legalName: string @@ -218,8 +137,6 @@ interface FormState { } } -type CompanyHomePageConfig = NonNullable['homePageConfig'] - const STATUS_COLORS: Record = { ACTIVE: 'text-emerald-400', TRIALING: 'text-sky-400', @@ -229,31 +146,6 @@ const STATUS_COLORS: Record = { PAST_DUE: 'text-orange-400', } -const PREVIEW_PRICING_PLANS = [ - { name: 'Starter', price: 'MAD 499', cadence: '/month' }, - { name: 'Growth', price: 'MAD 999', cadence: '/month', highlighted: true }, - { name: 'Pro', price: 'Custom', cadence: '' }, -] - -const HOMEPAGE_SECTION_ORDER: PublicHomepageSectionType[] = ['hero', 'offers', 'vehicles', 'pricing'] - -const PAGE_SECTION_GROUPS: Array<{ - page: keyof PublicSitePageSections - label: string - sections: Array<{ key: string; label: string }> -}> = [ - { page: 'home', label: 'Homepage', sections: [{ key: 'hero', label: 'Hero' }, { key: 'offers', label: 'Offers' }, { key: 'vehicles', label: 'Vehicles' }, { key: 'pricing', label: 'Pricing' }] }, - { page: 'about', label: 'About', sections: [{ key: 'hero', label: 'Hero' }, { key: 'highlights', label: 'Highlights' }, { key: 'details', label: 'Details' }] }, - { page: 'offers', label: 'Offers', sections: [{ key: 'header', label: 'Header' }, { key: 'grid', label: 'Offers grid' }] }, - { page: 'pricing', label: 'Pricing', sections: [{ key: 'hero', label: 'Hero' }, { key: 'plans', label: 'Plans' }, { key: 'payments', label: 'Payments' }, { key: 'faq', label: 'FAQ' }] }, - { page: 'vehicles', label: 'Vehicles', sections: [{ key: 'header', label: 'Header' }, { key: 'filters', label: 'Filters' }, { key: 'grid', label: 'Vehicle grid' }] }, - { page: 'vehicleDetail', label: 'Vehicle detail', sections: [{ key: 'gallery', label: 'Gallery' }, { key: 'summary', label: 'Summary card' }] }, - { page: 'blog', label: 'Blog', sections: [{ key: 'hero', label: 'Hero' }, { key: 'posts', label: 'Posts' }] }, - { page: 'contact', label: 'Contact', sections: [{ key: 'content', label: 'Content card' }] }, - { page: 'booking', label: 'Booking', sections: [{ key: 'content', label: 'Booking form' }] }, - { page: 'bookingConfirmation', label: 'Booking confirmation', sections: [{ key: 'hero', label: 'Confirmation header' }, { key: 'summary', label: 'Booking summary' }, { key: 'actions', label: 'Action buttons' }] }, -] - const INPUT_CLASS = 'mt-1 w-full rounded-xl border border-zinc-700 bg-zinc-900 px-3 py-2 text-sm text-zinc-100 outline-none focus:border-emerald-500' const LABEL_CLASS = 'text-xs font-medium uppercase tracking-wide text-zinc-500' @@ -270,52 +162,6 @@ function toNullable(value: string) { return trimmed ? trimmed : null } -function resolvePreviewText(value: string, fallback: string) { - const trimmed = value.trim() - return trimmed ? trimmed : fallback -} - -function resolveLegacyHomepageVisibility( - config: CompanyHomePageConfig | null | undefined, - type: Exclude, -) { - if (type === 'offers') return config?.showOffers ?? true - if (type === 'vehicles') return config?.showVehicles ?? true - return config?.showPricing ?? true -} - -function buildHomepageLayout(company: CompanyDetail): PublicHomepageLayout { - const pageSections = mergePageSectionsConfig(company.brand?.menuConfig?.pageSections) - const visibleTypes = HOMEPAGE_SECTION_ORDER.filter((type) => { - if (!pageSections.home[type]) return false - if (type === 'hero') return true - return resolveLegacyHomepageVisibility(company.brand?.homePageConfig ?? null, type) - }) - - return resolvePublicHomepageLayout(company.brand?.homePageConfig?.layout, visibleTypes) -} - -function mergePageSectionsConfig(config?: PublicSitePageSections | null): PublicSitePageSections { - const defaults = clonePublicSitePageSections() - return { - ...defaults, - ...(config ?? {}), - home: { ...defaults.home, ...(config?.home ?? {}) }, - about: { ...defaults.about, ...(config?.about ?? {}) }, - offers: { ...defaults.offers, ...(config?.offers ?? {}) }, - pricing: { ...defaults.pricing, ...(config?.pricing ?? {}) }, - vehicles: { ...defaults.vehicles, ...(config?.vehicles ?? {}) }, - vehicleDetail: { ...defaults.vehicleDetail, ...(config?.vehicleDetail ?? {}) }, - blog: { ...defaults.blog, ...(config?.blog ?? {}) }, - contact: { ...defaults.contact, ...(config?.contact ?? {}) }, - booking: { ...defaults.booking, ...(config?.booking ?? {}) }, - bookingConfirmation: { - ...defaults.bookingConfirmation, - ...(config?.bookingConfirmation ?? {}), - }, - } -} - function createFormState(company: CompanyDetail): FormState { return { company: { @@ -352,42 +198,6 @@ function createFormState(company: CompanyDetail): FormState { defaultLocale: company.brand?.defaultLocale ?? 'en', defaultCurrency: company.brand?.defaultCurrency ?? 'MAD', isListedOnMarketplace: company.brand?.isListedOnMarketplace ?? true, - homePageConfig: { - heroTitle: company.brand?.homePageConfig?.heroTitle ?? '', - heroDescription: company.brand?.homePageConfig?.heroDescription ?? '', - viewOffersLabel: company.brand?.homePageConfig?.viewOffersLabel ?? '', - viewPricingLabel: company.brand?.homePageConfig?.viewPricingLabel ?? '', - contactCompanyLabel: company.brand?.homePageConfig?.contactCompanyLabel ?? '', - activeOffersTitle: company.brand?.homePageConfig?.activeOffersTitle ?? '', - seeAllOffersLabel: company.brand?.homePageConfig?.seeAllOffersLabel ?? '', - noActiveOffersLabel: company.brand?.homePageConfig?.noActiveOffersLabel ?? '', - publishedVehiclesTitle: company.brand?.homePageConfig?.publishedVehiclesTitle ?? '', - viewVehicleLabel: company.brand?.homePageConfig?.viewVehicleLabel ?? '', - pricingEyebrow: company.brand?.homePageConfig?.pricingEyebrow ?? '', - pricingTitle: company.brand?.homePageConfig?.pricingTitle ?? '', - pricingDescription: company.brand?.homePageConfig?.pricingDescription ?? '', - showOffers: company.brand?.homePageConfig?.showOffers ?? true, - showVehicles: company.brand?.homePageConfig?.showVehicles ?? true, - showPricing: company.brand?.homePageConfig?.showPricing ?? true, - layout: buildHomepageLayout(company), - }, - menuConfig: { - aboutLabel: company.brand?.menuConfig?.aboutLabel ?? '', - vehiclesLabel: company.brand?.menuConfig?.vehiclesLabel ?? '', - offersLabel: company.brand?.menuConfig?.offersLabel ?? '', - pricingLabel: company.brand?.menuConfig?.pricingLabel ?? '', - blogLabel: company.brand?.menuConfig?.blogLabel ?? '', - contactLabel: company.brand?.menuConfig?.contactLabel ?? '', - bookCarLabel: company.brand?.menuConfig?.bookCarLabel ?? '', - siteNavigationLabel: company.brand?.menuConfig?.siteNavigationLabel ?? '', - showAbout: company.brand?.menuConfig?.showAbout ?? true, - showVehicles: company.brand?.menuConfig?.showVehicles ?? true, - showOffers: company.brand?.menuConfig?.showOffers ?? true, - showPricing: company.brand?.menuConfig?.showPricing ?? true, - showBlog: company.brand?.menuConfig?.showBlog ?? true, - showContact: company.brand?.menuConfig?.showContact ?? true, - pageSections: mergePageSectionsConfig(company.brand?.menuConfig?.pageSections), - }, }, contractSettings: { legalName: company.contractSettings?.legalName ?? '', @@ -452,154 +262,6 @@ export default function AdminCompanyDetailPage() { setForm((current) => current ? { ...current, [section]: { ...current[section], ...patch } } : current) } - function updateBrandConfig( - section: K, - patch: Partial, - ) { - setForm((current) => current ? { - ...current, - brand: { - ...current.brand, - [section]: { - ...current.brand[section], - ...patch, - }, - }, - } : current) - } - - function updateHomepageLayout(layout: PublicHomepageLayout) { - setForm((current) => current ? { - ...current, - brand: { - ...current.brand, - homePageConfig: { - ...current.brand.homePageConfig, - layout, - }, - }, - } : current) - } - - function addHomepageSection(type: PublicHomepageSectionType) { - setForm((current) => { - if (!current) return current - if (current.brand.homePageConfig.layout.items.some((item) => item.type === type)) return current - const fallback = clonePublicHomepageLayout().items.find((item) => item.type === type) - if (!fallback) return current - - return { - ...current, - brand: { - ...current.brand, - homePageConfig: { - ...current.brand.homePageConfig, - showOffers: type === 'offers' ? true : current.brand.homePageConfig.showOffers, - showVehicles: type === 'vehicles' ? true : current.brand.homePageConfig.showVehicles, - showPricing: type === 'pricing' ? true : current.brand.homePageConfig.showPricing, - layout: { - items: [...current.brand.homePageConfig.layout.items, fallback], - }, - }, - menuConfig: { - ...current.brand.menuConfig, - pageSections: { - ...current.brand.menuConfig.pageSections, - home: { - ...current.brand.menuConfig.pageSections.home, - [type]: true, - }, - }, - }, - }, - } - }) - } - - function removeHomepageSection(type: PublicHomepageSectionType) { - setForm((current) => current ? { - ...current, - brand: { - ...current.brand, - homePageConfig: { - ...current.brand.homePageConfig, - showOffers: type === 'offers' ? false : current.brand.homePageConfig.showOffers, - showVehicles: type === 'vehicles' ? false : current.brand.homePageConfig.showVehicles, - showPricing: type === 'pricing' ? false : current.brand.homePageConfig.showPricing, - layout: { - items: current.brand.homePageConfig.layout.items.filter((item) => item.type !== type), - }, - }, - menuConfig: { - ...current.brand.menuConfig, - pageSections: { - ...current.brand.menuConfig.pageSections, - home: { - ...current.brand.menuConfig.pageSections.home, - [type]: false, - }, - }, - }, - }, - } : current) - } - - function updatePageSection< - P extends keyof PublicSitePageSections, - S extends keyof PublicSitePageSections[P] - >(page: P, section: S, value: boolean) { - setForm((current) => { - if (!current) return current - - const next = { - ...current, - brand: { - ...current.brand, - menuConfig: { - ...current.brand.menuConfig, - pageSections: { - ...current.brand.menuConfig.pageSections, - [page]: { - ...current.brand.menuConfig.pageSections[page], - [section]: value, - }, - }, - }, - }, - } - - if (page !== 'home') return next - - const homepageSection = section as PublicHomepageSectionType - const nextItems = value - ? next.brand.homePageConfig.layout.items.some((item) => item.type === homepageSection) - ? next.brand.homePageConfig.layout.items - : [...next.brand.homePageConfig.layout.items, clonePublicHomepageLayout().items.find((item) => item.type === homepageSection)!] - : next.brand.homePageConfig.layout.items.filter((item) => item.type !== homepageSection) - - return { - ...next, - brand: { - ...next.brand, - homePageConfig: { - ...next.brand.homePageConfig, - showOffers: homepageSection === 'offers' ? value : next.brand.homePageConfig.showOffers, - showVehicles: homepageSection === 'vehicles' ? value : next.brand.homePageConfig.showVehicles, - showPricing: homepageSection === 'pricing' ? value : next.brand.homePageConfig.showPricing, - layout: { items: nextItems }, - }, - }, - } - }) - } - - function getPageSectionValue< - P extends keyof PublicSitePageSections, - S extends keyof PublicSitePageSections[P] - >(page: P, section: S) { - return form?.brand.menuConfig.pageSections[page][section] ?? false - } - async function saveChanges() { if (!form) return setSaving(true) @@ -644,42 +306,6 @@ export default function AdminCompanyDetailPage() { defaultLocale: form.brand.defaultLocale, defaultCurrency: form.brand.defaultCurrency, isListedOnMarketplace: form.brand.isListedOnMarketplace, - homePageConfig: { - heroTitle: toNullable(form.brand.homePageConfig.heroTitle), - heroDescription: toNullable(form.brand.homePageConfig.heroDescription), - viewOffersLabel: toNullable(form.brand.homePageConfig.viewOffersLabel), - viewPricingLabel: toNullable(form.brand.homePageConfig.viewPricingLabel), - contactCompanyLabel: toNullable(form.brand.homePageConfig.contactCompanyLabel), - activeOffersTitle: toNullable(form.brand.homePageConfig.activeOffersTitle), - seeAllOffersLabel: toNullable(form.brand.homePageConfig.seeAllOffersLabel), - noActiveOffersLabel: toNullable(form.brand.homePageConfig.noActiveOffersLabel), - publishedVehiclesTitle: toNullable(form.brand.homePageConfig.publishedVehiclesTitle), - viewVehicleLabel: toNullable(form.brand.homePageConfig.viewVehicleLabel), - pricingEyebrow: toNullable(form.brand.homePageConfig.pricingEyebrow), - pricingTitle: toNullable(form.brand.homePageConfig.pricingTitle), - pricingDescription: toNullable(form.brand.homePageConfig.pricingDescription), - showOffers: form.brand.homePageConfig.showOffers, - showVehicles: form.brand.homePageConfig.showVehicles, - showPricing: form.brand.homePageConfig.showPricing, - layout: form.brand.homePageConfig.layout, - }, - menuConfig: { - aboutLabel: toNullable(form.brand.menuConfig.aboutLabel), - vehiclesLabel: toNullable(form.brand.menuConfig.vehiclesLabel), - offersLabel: toNullable(form.brand.menuConfig.offersLabel), - pricingLabel: toNullable(form.brand.menuConfig.pricingLabel), - blogLabel: toNullable(form.brand.menuConfig.blogLabel), - contactLabel: toNullable(form.brand.menuConfig.contactLabel), - bookCarLabel: toNullable(form.brand.menuConfig.bookCarLabel), - siteNavigationLabel: toNullable(form.brand.menuConfig.siteNavigationLabel), - showAbout: form.brand.menuConfig.showAbout, - showVehicles: form.brand.menuConfig.showVehicles, - showOffers: form.brand.menuConfig.showOffers, - showPricing: form.brand.menuConfig.showPricing, - showBlog: form.brand.menuConfig.showBlog, - showContact: form.brand.menuConfig.showContact, - pageSections: form.brand.menuConfig.pageSections, - }, }, contractSettings: { legalName: toNullable(form.contractSettings.legalName), @@ -761,158 +387,6 @@ export default function AdminCompanyDetailPage() { customers: company._count?.customers ?? company.customers?.length ?? 0, reservations: company._count?.reservations ?? company.reservations?.length ?? 0, } - const previewCompanyName = form.brand.displayName.trim() || form.company.name.trim() || company.name - const previewTagline = resolvePreviewText( - form.brand.tagline, - 'This company uses RentalDriveGo to publish vehicles, run bookings, and accept direct rental payments.', - ) - const previewHeroTitle = resolvePreviewText(form.brand.homePageConfig.heroTitle, previewTagline) - const previewHeroDescription = resolvePreviewText( - form.brand.homePageConfig.heroDescription, - 'Manage direct bookings, highlight active offers, and turn your fleet into a modern rental storefront.', - ) - const previewOffersLabel = resolvePreviewText(form.brand.homePageConfig.viewOffersLabel, 'View offers') - const previewPricingLabel = resolvePreviewText(form.brand.homePageConfig.viewPricingLabel, 'View pricing') - const previewContactLabel = resolvePreviewText(form.brand.homePageConfig.contactCompanyLabel, 'Contact company') - const previewOffersTitle = resolvePreviewText(form.brand.homePageConfig.activeOffersTitle, 'Active offers') - const previewSeeAllOffersLabel = resolvePreviewText(form.brand.homePageConfig.seeAllOffersLabel, 'See all offers') - const previewNoOffersLabel = resolvePreviewText(form.brand.homePageConfig.noActiveOffersLabel, 'No active offers right now') - const previewVehiclesTitle = resolvePreviewText(form.brand.homePageConfig.publishedVehiclesTitle, 'Published vehicles') - const previewViewVehicleLabel = resolvePreviewText(form.brand.homePageConfig.viewVehicleLabel, 'View vehicle') - const previewPricingEyebrow = resolvePreviewText(form.brand.homePageConfig.pricingEyebrow, 'Pricing') - const previewPricingTitle = resolvePreviewText(form.brand.homePageConfig.pricingTitle, 'Plans for every fleet size') - const previewPricingDescription = resolvePreviewText( - form.brand.homePageConfig.pricingDescription, - 'Showcase transparent pricing and make it easy for renters to understand the value of booking direct.', - ) - const previewBookCarLabel = resolvePreviewText(form.brand.menuConfig.bookCarLabel, 'Book car') - const previewFooterLabel = resolvePreviewText(form.brand.menuConfig.siteNavigationLabel, 'Site navigation') - const homepageLayout = resolvePublicHomepageLayout( - form.brand.homePageConfig.layout, - form.brand.homePageConfig.layout.items.map((item) => item.type), - ) - const availableHomepageSections = HOMEPAGE_SECTION_ORDER.filter( - (type) => !homepageLayout.items.some((item) => item.type === type), - ) - const previewMenuItems = [ - { label: resolvePreviewText(form.brand.menuConfig.aboutLabel, 'About'), visible: form.brand.menuConfig.showAbout }, - { label: resolvePreviewText(form.brand.menuConfig.vehiclesLabel, 'Vehicles'), visible: form.brand.menuConfig.showVehicles }, - { label: resolvePreviewText(form.brand.menuConfig.offersLabel, 'Offers'), visible: form.brand.menuConfig.showOffers }, - { label: resolvePreviewText(form.brand.menuConfig.pricingLabel, 'Pricing'), visible: form.brand.menuConfig.showPricing }, - { label: resolvePreviewText(form.brand.menuConfig.blogLabel, 'Blog'), visible: form.brand.menuConfig.showBlog }, - { label: resolvePreviewText(form.brand.menuConfig.contactLabel, 'Contact'), visible: form.brand.menuConfig.showContact }, - ].filter((item) => item.visible) - - function renderHomepagePreviewSection(type: PublicHomepageSectionType) { - if (type === 'hero') { - return ( -
-
-

{previewCompanyName}

-

{previewHeroTitle}

-

{previewHeroDescription}

-
- {previewOffersLabel} - {previewPricingLabel} - {previewContactLabel} -
-
-
- Hero image preview area. -
- Published brand media will render here on the public site. -
-
- ) - } - - if (type === 'offers') { - return ( -
-
-

{previewOffersTitle}

- {previewSeeAllOffersLabel} -
-
-
-

Sample offer

-
Weekend escape
-

15%

-
-
- {previewNoOffersLabel} -
-
-
- ) - } - - if (type === 'vehicles') { - return ( -
-
-

{previewVehiclesTitle}

-

{counts.vehicles} published vehicles

-
-
- {[1, 2].map((index) => ( -
-
-
-
Vehicle {index}
-

Category

-
-

MAD 850/day

- {previewViewVehicleLabel} -
-
-
- ))} -
-
- ) - } - - return ( -
-
-
-

{previewPricingEyebrow}

-

{previewPricingTitle}

-

{previewPricingDescription}

-
- - {previewPricingLabel} - -
- -
- {PREVIEW_PRICING_PLANS.slice(0, 2).map((plan) => ( -
-
-
-
{plan.name}
-

Pricing copy preview for the public homepage.

-
- {plan.highlighted ? ( - - Popular - - ) : null} -
-
- {plan.price} - {plan.cadence ? {plan.cadence} : null} -
-
- ))} -
-
- ) - } return (
@@ -1108,253 +582,6 @@ export default function AdminCompanyDetailPage() {
-
-
-
-

Public site homepage and menu

-

Blank text fields fall back to the default localized copy on the public site.

-
-
- -
-
-

Homepage content

-
- -