fix: resolve layout, pdf datasheets data generation and excel 404 routing
This commit is contained in:
@@ -499,9 +499,14 @@ export default async function ProductPage({ params }: ProductPageProps) {
|
|||||||
</h2>
|
</h2>
|
||||||
<div className="h-1.5 w-24 bg-accent rounded-full" />
|
<div className="h-1.5 w-24 bg-accent rounded-full" />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-4 max-w-2xl">
|
<div className="flex flex-row flex-wrap items-center gap-4 max-w-2xl">
|
||||||
<DatasheetDownload datasheetPath={datasheetPath} className="mt-0" />
|
<DatasheetDownload
|
||||||
{excelPath && <ExcelDownload excelPath={excelPath} className="mt-0" />}
|
datasheetPath={datasheetPath}
|
||||||
|
className="mt-0 w-full sm:w-auto"
|
||||||
|
/>
|
||||||
|
{excelPath && (
|
||||||
|
<ExcelDownload excelPath={excelPath} className="mt-0 w-full sm:w-auto" />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -23,6 +23,14 @@ export async function requestBrochureAction(formData: FormData) {
|
|||||||
const email = formData.get('email') as string;
|
const email = formData.get('email') as string;
|
||||||
const locale = (formData.get('locale') as string) || 'en';
|
const locale = (formData.get('locale') as string) || 'en';
|
||||||
|
|
||||||
|
// Anti-spam Honeypot Check
|
||||||
|
const honeypot = formData.get('company_website') as string;
|
||||||
|
if (honeypot) {
|
||||||
|
logger.warn('Spam detected via honeypot in brochure request', { email });
|
||||||
|
// Silently succeed to fool the bot without doing actual work
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
|
||||||
if (!email) {
|
if (!email) {
|
||||||
logger.warn('Missing email in brochure request');
|
logger.warn('Missing email in brochure request');
|
||||||
return { success: false, error: 'Missing email address' };
|
return { success: false, error: 'Missing email address' };
|
||||||
@@ -77,7 +85,7 @@ export async function requestBrochureAction(formData: FormData) {
|
|||||||
|
|
||||||
const html = await render(
|
const html = await render(
|
||||||
React.createElement(BrochureDeliveryEmail, {
|
React.createElement(BrochureDeliveryEmail, {
|
||||||
email,
|
_email: email,
|
||||||
brochureUrl,
|
brochureUrl,
|
||||||
locale: locale as 'en' | 'de',
|
locale: locale as 'en' | 'de',
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -25,6 +25,14 @@ export async function sendContactFormAction(formData: FormData) {
|
|||||||
// Track attempt
|
// Track attempt
|
||||||
services.analytics.track('contact-form-attempt');
|
services.analytics.track('contact-form-attempt');
|
||||||
|
|
||||||
|
// Anti-spam Honeypot Check
|
||||||
|
const honeypot = formData.get('company_website') as string;
|
||||||
|
if (honeypot) {
|
||||||
|
logger.warn('Spam detected via honeypot in contact request', { email: formData.get('email') });
|
||||||
|
// Silently succeed to fool the bot without doing actual work
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
|
||||||
const name = formData.get('name') as string;
|
const name = formData.get('name') as string;
|
||||||
const email = formData.get('email') as string;
|
const email = formData.get('email') as string;
|
||||||
const message = formData.get('message') as string;
|
const message = formData.get('message') as string;
|
||||||
|
|||||||
@@ -139,6 +139,15 @@ export default function ContactForm() {
|
|||||||
{t('form.title')}
|
{t('form.title')}
|
||||||
</Heading>
|
</Heading>
|
||||||
<form onSubmit={handleSubmit} className="grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-8">
|
<form onSubmit={handleSubmit} className="grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-8">
|
||||||
|
{/* Anti-spam Honeypot */}
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="company_website"
|
||||||
|
tabIndex={-1}
|
||||||
|
autoComplete="off"
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
<div className="space-y-1 md:space-y-2">
|
<div className="space-y-1 md:space-y-2">
|
||||||
<Label htmlFor="contact-name">{t('form.name')}</Label>
|
<Label htmlFor="contact-name">{t('form.name')}</Label>
|
||||||
<Input
|
<Input
|
||||||
|
|||||||
@@ -93,6 +93,16 @@ export default function FooterBrochureForm({ className }: Props) {
|
|||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="w-full md:w-auto flex flex-col sm:flex-row gap-3"
|
className="w-full md:w-auto flex flex-col sm:flex-row gap-3"
|
||||||
>
|
>
|
||||||
|
{/* Anti-spam Honeypot */}
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="company_website"
|
||||||
|
tabIndex={-1}
|
||||||
|
autoComplete="off"
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="relative w-full sm:w-64">
|
<div className="relative w-full sm:w-64">
|
||||||
<input
|
<input
|
||||||
name="email"
|
name="email"
|
||||||
|
|||||||
@@ -165,6 +165,16 @@ export default function RequestQuoteForm({ productName }: RequestQuoteFormProps)
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit} className="space-y-3 !mt-0">
|
<form onSubmit={handleSubmit} className="space-y-3 !mt-0">
|
||||||
|
{/* Anti-spam Honeypot */}
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="company_website"
|
||||||
|
tabIndex={-1}
|
||||||
|
autoComplete="off"
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="space-y-2 !mt-0">
|
<div className="space-y-2 !mt-0">
|
||||||
<div className="space-y-1 !mt-0">
|
<div className="space-y-1 !mt-0">
|
||||||
<label htmlFor={emailId} className="sr-only">
|
<label htmlFor={emailId} className="sr-only">
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ export default async function middleware(request: NextRequest) {
|
|||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
matcher: [
|
matcher: [
|
||||||
'/((?!api|_next/static|_next/image|favicon.ico|admin|manifest.webmanifest|.*\\.(?:svg|png|jpg|jpeg|gif|webp|pdf|txt|vcf|xml|webm|mp4|map)$).*)',
|
'/((?!api|_next/static|_next/image|favicon.ico|admin|manifest.webmanifest|.*\\.(?:svg|png|jpg|jpeg|gif|webp|pdf|xlsx|txt|vcf|xml|webm|mp4|map)$).*)',
|
||||||
'/(de|en)/:path*',
|
'/(de|en)/:path*',
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,6 +25,18 @@ const nextConfig = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
...(isProd ? { output: 'standalone' } : {}),
|
...(isProd ? { output: 'standalone' } : {}),
|
||||||
|
async rewrites() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
source: '/:locale/datasheets/:path*',
|
||||||
|
destination: '/datasheets/:path*',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: '/:locale/brochure/:path*',
|
||||||
|
destination: '/brochure/:path*',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
async headers() {
|
async headers() {
|
||||||
const isProd = process.env.NODE_ENV === 'production';
|
const isProd = process.env.NODE_ENV === 'production';
|
||||||
const umamiDomain = new URL(process.env.UMAMI_API_ENDPOINT || 'https://analytics.infra.mintel.me').origin;
|
const umamiDomain = new URL(process.env.UMAMI_API_ENDPOINT || 'https://analytics.infra.mintel.me').origin;
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user