add images and redesign hompeage into sections, fix the dark color
Build & Deploy / Build & Push Docker Image (push) Failing after 48s
Build & Deploy / Deploy to VPS (push) Has been skipped
Test / API Unit Tests (push) Failing after 5m2s
Test / Marketplace Unit Tests (push) Failing after 4m55s
Test / Admin Unit Tests (push) Successful in 9m37s
Test / Dashboard Unit Tests (push) Successful in 9m37s
Test / API Integration Tests (push) Successful in 9m54s
Build & Deploy / Build & Push Docker Image (push) Failing after 48s
Build & Deploy / Deploy to VPS (push) Has been skipped
Test / API Unit Tests (push) Failing after 5m2s
Test / Marketplace Unit Tests (push) Failing after 4m55s
Test / Admin Unit Tests (push) Successful in 9m37s
Test / Dashboard Unit Tests (push) Successful in 9m37s
Test / API Integration Tests (push) Successful in 9m54s
This commit is contained in:
@@ -1,16 +1,21 @@
|
||||
import type { ApprovedIconName } from '@/components/foundation/Icon';
|
||||
import type { PreviewRow } from '@/components/marketing/ProductPreview';
|
||||
import type { HomepageMessages, ShellMessages } from '@/lib/localization/messages';
|
||||
import type { Locale } from '@/lib/localization/config';
|
||||
import { accountCreateUrl } from '@/lib/account-urls';
|
||||
import {
|
||||
fleetBandIds,
|
||||
pricingPlanIds,
|
||||
type FleetBandId,
|
||||
type PricingPlanId,
|
||||
} from '@/content/pricing-config';
|
||||
import { existsSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
|
||||
export interface HomepageAction {
|
||||
label: string;
|
||||
disabledReason: string;
|
||||
href?: string;
|
||||
disabledReason?: string;
|
||||
}
|
||||
|
||||
export interface TitledDescription {
|
||||
@@ -43,6 +48,13 @@ export interface HomepagePricingPlan {
|
||||
cta: string;
|
||||
}
|
||||
|
||||
export interface HomepageImageAsset {
|
||||
src: string;
|
||||
alt: string;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface HomepageContent {
|
||||
hero: {
|
||||
eyebrow: string;
|
||||
@@ -56,6 +68,7 @@ export interface HomepageContent {
|
||||
illustrativeLabel: string;
|
||||
rows: PreviewRow[];
|
||||
};
|
||||
image: HomepageImageAsset;
|
||||
};
|
||||
trust: {
|
||||
eyebrow: string;
|
||||
@@ -71,12 +84,14 @@ export interface HomepageContent {
|
||||
beforeItems: string[];
|
||||
afterTitle: string;
|
||||
afterItems: string[];
|
||||
image: HomepageImageAsset;
|
||||
};
|
||||
workflow: {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
body: string;
|
||||
steps: HomepageWorkflowStep[];
|
||||
image: HomepageImageAsset;
|
||||
};
|
||||
roles: {
|
||||
eyebrow: string;
|
||||
@@ -88,6 +103,7 @@ export interface HomepageContent {
|
||||
title: string;
|
||||
body: string;
|
||||
items: TitledDescription[];
|
||||
image: HomepageImageAsset;
|
||||
};
|
||||
results: {
|
||||
eyebrow: string;
|
||||
@@ -96,6 +112,7 @@ export interface HomepageContent {
|
||||
metrics: TitledDescription[];
|
||||
methodTitle: string;
|
||||
method: string[];
|
||||
image: HomepageImageAsset;
|
||||
};
|
||||
integrations: {
|
||||
eyebrow: string;
|
||||
@@ -147,6 +164,7 @@ export interface HomepageContent {
|
||||
body: string;
|
||||
primary: HomepageAction;
|
||||
secondary: HomepageAction;
|
||||
image: HomepageImageAsset;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -156,6 +174,42 @@ const moduleIcons: ApprovedIconName[] = ['calendar', 'car', 'check', 'search', '
|
||||
const resultIcons: ApprovedIconName[] = ['calendar', 'settings', 'car', 'warning'];
|
||||
const securityIcons: ApprovedIconName[] = ['settings', 'search', 'globe', 'warning'];
|
||||
|
||||
const homepagePublicPath = join(process.cwd(), 'public');
|
||||
const homepagePublicFallbackPath = join(process.cwd(), 'apps/homepage/public');
|
||||
const localeAssetSuffix: Record<Locale, string> = {
|
||||
en: 'EN',
|
||||
fr: 'FR',
|
||||
ar: 'AR',
|
||||
};
|
||||
|
||||
function publicAssetExists(fileName: string): boolean {
|
||||
return existsSync(join(homepagePublicPath, fileName)) || existsSync(join(homepagePublicFallbackPath, fileName));
|
||||
}
|
||||
|
||||
function localizedImage(
|
||||
subject: string,
|
||||
locale: Locale,
|
||||
extension: 'jpeg' | 'png',
|
||||
dimensions: Pick<HomepageImageAsset, 'width' | 'height'>,
|
||||
alt: string,
|
||||
): HomepageImageAsset {
|
||||
const localizedFile = `${subject}_${localeAssetSuffix[locale]}.${extension}`;
|
||||
const hyphenLocalizedFile = `${subject}-${locale}.${extension}`;
|
||||
const defaultFile = `${subject}.${extension}`;
|
||||
const fileName = publicAssetExists(localizedFile)
|
||||
? localizedFile
|
||||
: publicAssetExists(hyphenLocalizedFile)
|
||||
? hyphenLocalizedFile
|
||||
: defaultFile;
|
||||
|
||||
return {
|
||||
src: `/${fileName}`,
|
||||
alt,
|
||||
width: dimensions.width,
|
||||
height: dimensions.height,
|
||||
};
|
||||
}
|
||||
|
||||
function pair(value: readonly string[], context: string): { title: string; description: string } {
|
||||
const title = value[0];
|
||||
const description = value[1];
|
||||
@@ -211,6 +265,7 @@ function mapPairs(
|
||||
export function buildHomepageContent(
|
||||
homepage: HomepageMessages,
|
||||
shell: ShellMessages,
|
||||
locale: Locale = 'en',
|
||||
): HomepageContent {
|
||||
const pendingReason = shell.states.pendingBody;
|
||||
|
||||
@@ -219,7 +274,7 @@ export function buildHomepageContent(
|
||||
eyebrow: homepage.hero.eyebrow,
|
||||
title: homepage.hero.title,
|
||||
body: homepage.hero.body,
|
||||
primary: { label: homepage.hero.primary, disabledReason: shell.header.demoUnavailable },
|
||||
primary: { label: homepage.hero.primary, href: accountCreateUrl(locale) },
|
||||
secondary: { label: homepage.hero.secondary, disabledReason: pendingReason },
|
||||
preview: {
|
||||
title: homepage.preview.title,
|
||||
@@ -242,6 +297,13 @@ export function buildHomepageContent(
|
||||
},
|
||||
],
|
||||
},
|
||||
image: localizedImage(
|
||||
'dashboard1',
|
||||
locale,
|
||||
'png',
|
||||
{ width: 1672, height: 941 },
|
||||
homepage.preview.title,
|
||||
),
|
||||
},
|
||||
trust: {
|
||||
eyebrow: homepage.trust.eyebrow,
|
||||
@@ -257,6 +319,13 @@ export function buildHomepageContent(
|
||||
beforeItems: homepage.comparison.beforeItems,
|
||||
afterTitle: homepage.comparison.afterTitle,
|
||||
afterItems: homepage.comparison.afterItems,
|
||||
image: localizedImage(
|
||||
'benefit1',
|
||||
locale,
|
||||
'png',
|
||||
{ width: 1672, height: 941 },
|
||||
homepage.comparison.title,
|
||||
),
|
||||
},
|
||||
workflow: {
|
||||
eyebrow: homepage.workflow.eyebrow,
|
||||
@@ -266,6 +335,13 @@ export function buildHomepageContent(
|
||||
id: `workflow-${index + 1}`,
|
||||
...triple(value, `workflow.steps[${index}]`),
|
||||
})),
|
||||
image: localizedImage(
|
||||
'workflow1',
|
||||
locale,
|
||||
'png',
|
||||
{ width: 1672, height: 941 },
|
||||
homepage.workflow.title,
|
||||
),
|
||||
},
|
||||
roles: {
|
||||
eyebrow: homepage.roles.eyebrow,
|
||||
@@ -277,6 +353,13 @@ export function buildHomepageContent(
|
||||
title: homepage.modules.title,
|
||||
body: homepage.modules.body,
|
||||
items: mapPairs(homepage.modules.items, 'module', moduleIcons),
|
||||
image: localizedImage(
|
||||
'oilchange1',
|
||||
locale,
|
||||
'png',
|
||||
{ width: 1254, height: 1254 },
|
||||
homepage.modules.title,
|
||||
),
|
||||
},
|
||||
results: {
|
||||
eyebrow: homepage.results.eyebrow,
|
||||
@@ -285,6 +368,13 @@ export function buildHomepageContent(
|
||||
metrics: mapPairs(homepage.results.metrics, 'measurement', resultIcons),
|
||||
methodTitle: homepage.results.methodTitle,
|
||||
method: homepage.results.method,
|
||||
image: localizedImage(
|
||||
'dashboard2',
|
||||
locale,
|
||||
'png',
|
||||
{ width: 1672, height: 941 },
|
||||
homepage.results.title,
|
||||
),
|
||||
},
|
||||
integrations: {
|
||||
eyebrow: homepage.integrations.eyebrow,
|
||||
@@ -346,8 +436,15 @@ export function buildHomepageContent(
|
||||
eyebrow: homepage.final.eyebrow,
|
||||
title: homepage.final.title,
|
||||
body: homepage.final.body,
|
||||
primary: { label: homepage.final.primary, disabledReason: shell.header.demoUnavailable },
|
||||
primary: { label: homepage.final.primary, href: accountCreateUrl(locale) },
|
||||
secondary: { label: homepage.final.secondary, disabledReason: pendingReason },
|
||||
image: localizedImage(
|
||||
'rentaldrivego',
|
||||
locale,
|
||||
'jpeg',
|
||||
{ width: 1220, height: 1167 },
|
||||
'RentalDriveGo',
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user