Fix falso successo form contatti + conferma UI #25
@ -6,8 +6,8 @@ PUBLIC_SITE_URL=http://localhost:4321
|
||||
|
||||
CONTACT_FORM_MODE=dev
|
||||
CONTACT_FORM_FROM_EMAIL=no-reply@nexstudio.ai
|
||||
CONTACT_FORM_TO_EMAIL=javaxman69@gmail.com
|
||||
CONTACT_FORM_TO_EMAIL_INFO=javaxman69@gmail.com
|
||||
CONTACT_FORM_TO_EMAIL=pro@nexstudio.ai
|
||||
CONTACT_FORM_TO_EMAIL_INFO=
|
||||
CONTACT_FORM_TO_EMAIL_PRIVACY=
|
||||
CONTACT_FORM_TO_EMAIL_CAREERS=
|
||||
CONTACT_TURNSTILE_SECRET_KEY=
|
||||
@ -16,6 +16,6 @@ CONTACT_TURNSTILE_SECRET_KEY=
|
||||
# In produzione: NEWSLETTER_MODE=live (oppure CONTACT_FORM_MODE=live come fallback)
|
||||
NEWSLETTER_MODE=dev
|
||||
NEWSLETTER_FROM_EMAIL=no-reply@nexstudio.ai
|
||||
NEWSLETTER_NOTIFY_TO_EMAIL=javaxman69@gmail.com
|
||||
NEWSLETTER_NOTIFY_TO_EMAIL=pro@nexstudio.ai
|
||||
NEWSLETTER_ADMIN_TOKEN=
|
||||
NEWSLETTER_TURNSTILE_SECRET_KEY=
|
||||
|
||||
@ -19,6 +19,7 @@ const model = {
|
||||
fieldDepartment: cf.fieldDepartment,
|
||||
fieldEmail: cf.fieldEmail,
|
||||
fieldMessage: cf.fieldMessage,
|
||||
successMessage: cf.successMessage,
|
||||
turnstileError: cf.errors.turnstile,
|
||||
configError: cf.errors.config,
|
||||
mailtoFallbackSubject: cf.mailtoFallbackSubject,
|
||||
@ -112,18 +113,6 @@ const fieldClass =
|
||||
<input type="hidden" name="_subject" value={notifySubject} />
|
||||
) : null
|
||||
}
|
||||
{
|
||||
hasFormspree ? (
|
||||
<input
|
||||
type="text"
|
||||
name="_gotcha"
|
||||
tabindex="-1"
|
||||
autocomplete="off"
|
||||
aria-hidden="true"
|
||||
class="pointer-events-none absolute -left-[9999px] h-0 w-0 opacity-0"
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
|
||||
<div>
|
||||
<label class="block text-xs font-medium text-nx-muted" for="nx-cf-name">
|
||||
@ -203,6 +192,13 @@ const fieldClass =
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<p
|
||||
id="nx-contact-form-success"
|
||||
class="hidden text-sm leading-relaxed text-emerald-400/90"
|
||||
role="status"
|
||||
>
|
||||
</p>
|
||||
|
||||
<p
|
||||
id="nx-contact-form-error"
|
||||
class="hidden text-sm leading-relaxed text-red-400/90"
|
||||
|
||||
@ -27,6 +27,7 @@ const ctaByLocale = {
|
||||
emailLabel: 'Email',
|
||||
messageLabel: 'Scrivi qui il tuo messaggio',
|
||||
submitLabel: 'Invia messaggio',
|
||||
successMessage: 'Messaggio inviato. Ti risponderemo al più presto.',
|
||||
actionUrl: contactActionUrl,
|
||||
successRedirect: contactSuccessRedirect,
|
||||
turnstileSiteKey: contactTurnstileSiteKey,
|
||||
@ -78,6 +79,7 @@ const ctaByLocale = {
|
||||
emailLabel: 'Email',
|
||||
messageLabel: 'Write your message',
|
||||
submitLabel: 'Send message',
|
||||
successMessage: 'Message sent. We will get back to you soon.',
|
||||
actionUrl: contactActionUrl,
|
||||
successRedirect: contactSuccessRedirect,
|
||||
turnstileSiteKey: contactTurnstileSiteKey,
|
||||
@ -129,6 +131,7 @@ const ctaByLocale = {
|
||||
emailLabel: 'อีเมล',
|
||||
messageLabel: 'พิมพ์ข้อความของคุณ',
|
||||
submitLabel: 'ส่งข้อความ',
|
||||
successMessage: 'ส่งข้อความแล้ว เราจะติดต่อกลับโดยเร็ว',
|
||||
actionUrl: contactActionUrl,
|
||||
successRedirect: contactSuccessRedirect,
|
||||
turnstileSiteKey: contactTurnstileSiteKey,
|
||||
|
||||
@ -129,14 +129,7 @@ export const POST: APIRoute = async ({ request, url }) => {
|
||||
const turnstileSecret = readEnv('CONTACT_TURNSTILE_SECRET_KEY', runtimeEnv);
|
||||
|
||||
const form = await request.formData();
|
||||
if (required(form.get('_gotcha'))) {
|
||||
const redirectTarget =
|
||||
sanitizeRedirect(required(form.get('_next')), url) ||
|
||||
sanitizeRedirect(request.headers.get('referer') ?? '/', url) ||
|
||||
new URL('/#contatti', url).toString();
|
||||
return succeed(request, redirectTarget);
|
||||
}
|
||||
|
||||
// Honeypot rimosso dal form (Turnstile basta). Se un client legacy lo manda, ignoralo.
|
||||
const redirectTarget =
|
||||
sanitizeRedirect(required(form.get('_next')), url) ||
|
||||
sanitizeRedirect(readEnv('PUBLIC_CONTACT_FORM_SUCCESS_REDIRECT', runtimeEnv), url) ||
|
||||
@ -239,6 +232,14 @@ export const POST: APIRoute = async ({ request, url }) => {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const isProdHost =
|
||||
url.hostname === 'nexstudio.ai' ||
|
||||
url.hostname.endsWith('.nexstudio.ai') ||
|
||||
url.hostname.endsWith('.workers.dev');
|
||||
console.warn('[contact] CONTACT_FORM_MODE is not live', { mode, host: url.hostname });
|
||||
if (isProdHost) {
|
||||
return fail(request, USER_SEND_ERROR, 503);
|
||||
}
|
||||
console.info('[contact:dev] Contact payload received', {
|
||||
name,
|
||||
company,
|
||||
|
||||
@ -5,6 +5,7 @@ interface ContactFormCfg {
|
||||
turnstileSiteKey: string;
|
||||
notifySubject: string;
|
||||
successRedirect: string;
|
||||
successMessage: string;
|
||||
fieldName: string;
|
||||
fieldCompany: string;
|
||||
fieldCountry: string;
|
||||
@ -32,6 +33,7 @@ function readCfg(): ContactFormCfg {
|
||||
turnstileSiteKey: '',
|
||||
notifySubject: '',
|
||||
successRedirect: '',
|
||||
successMessage: 'Message sent.',
|
||||
fieldName: 'name',
|
||||
fieldCompany: 'company',
|
||||
fieldCountry: 'country',
|
||||
@ -53,12 +55,23 @@ function readCfg(): ContactFormCfg {
|
||||
}
|
||||
|
||||
function showError(message: string): void {
|
||||
const ok = document.getElementById('nx-contact-form-success');
|
||||
if (ok) ok.classList.add('hidden');
|
||||
const err = document.getElementById('nx-contact-form-error');
|
||||
if (!err) return;
|
||||
err.textContent = message;
|
||||
err.classList.remove('hidden');
|
||||
}
|
||||
|
||||
function showSuccess(message: string): void {
|
||||
const err = document.getElementById('nx-contact-form-error');
|
||||
if (err) err.classList.add('hidden');
|
||||
const ok = document.getElementById('nx-contact-form-success');
|
||||
if (!ok) return;
|
||||
ok.textContent = message;
|
||||
ok.classList.remove('hidden');
|
||||
}
|
||||
|
||||
/** Dopo un POST fallito il token Turnstile è già consumato: ne serve uno nuovo. */
|
||||
function resetTurnstile(form: HTMLFormElement): void {
|
||||
const widget = form.querySelector<HTMLElement>('.cf-turnstile');
|
||||
@ -89,7 +102,9 @@ function bind(): void {
|
||||
form.addEventListener('submit', async (e) => {
|
||||
const cfg = readCfg();
|
||||
const err = document.getElementById('nx-contact-form-error');
|
||||
const ok = document.getElementById('nx-contact-form-success');
|
||||
if (err) err.classList.add('hidden');
|
||||
if (ok) ok.classList.add('hidden');
|
||||
|
||||
const hasTurnstile =
|
||||
typeof cfg.turnstileSiteKey === 'string' && cfg.turnstileSiteKey.length > 0;
|
||||
@ -125,11 +140,12 @@ function bind(): void {
|
||||
if (hasTurnstile) resetTurnstile(form);
|
||||
return;
|
||||
}
|
||||
const target =
|
||||
(data && typeof data.redirect === 'string' && data.redirect) ||
|
||||
cfg.successRedirect ||
|
||||
`${window.location.pathname}${window.location.search}#contatti`;
|
||||
window.location.assign(target);
|
||||
form.reset();
|
||||
if (hasTurnstile) resetTurnstile(form);
|
||||
showSuccess(
|
||||
cfg.successMessage || 'Messaggio inviato. Ti risponderemo al più presto.',
|
||||
);
|
||||
form.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||
} catch {
|
||||
showError('Errore di rete. Controlla la connessione e riprova.');
|
||||
if (hasTurnstile) resetTurnstile(form);
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
},
|
||||
"vars": {
|
||||
"CONTACT_FORM_FROM_EMAIL": "no-reply@nexstudio.ai",
|
||||
"CONTACT_FORM_TO_EMAIL": "javaxman69@gmail.com"
|
||||
"CONTACT_FORM_TO_EMAIL": "pro@nexstudio.ai"
|
||||
},
|
||||
"d1_databases": [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user