@@ -2,9 +2,11 @@ import { defineConfig } from 'astro/config';
|
|||||||
import tailwindcss from '@tailwindcss/vite';
|
import tailwindcss from '@tailwindcss/vite';
|
||||||
import sitemap from '@astrojs/sitemap';
|
import sitemap from '@astrojs/sitemap';
|
||||||
import react from '@astrojs/react';
|
import react from '@astrojs/react';
|
||||||
|
import node from '@astrojs/node';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
output: 'static',
|
output: 'static',
|
||||||
|
adapter: node({ mode: 'middleware' }),
|
||||||
site: 'https://cachetdeco.com',
|
site: 'https://cachetdeco.com',
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultLocale: 'fr',
|
defaultLocale: 'fr',
|
||||||
|
|||||||
@@ -1,175 +0,0 @@
|
|||||||
interface SoumissionBody {
|
|
||||||
nom: string;
|
|
||||||
courriel: string;
|
|
||||||
telephone: string;
|
|
||||||
type_service: string;
|
|
||||||
adresse?: string;
|
|
||||||
message: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Env {
|
|
||||||
RESEND_API_KEY: string;
|
|
||||||
CONTACT_EMAIL: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const serviceLabels: Record<string, string> = {
|
|
||||||
interieur: 'Peinture intérieure',
|
|
||||||
exterieur: 'Peinture extérieure',
|
|
||||||
commercial: 'Peinture commerciale',
|
|
||||||
decoration: 'Décoration intérieure',
|
|
||||||
autre: 'Autre',
|
|
||||||
};
|
|
||||||
|
|
||||||
function buildEmailHtml(data: SoumissionBody): string {
|
|
||||||
const serviceLabel = serviceLabels[data.type_service] ?? data.type_service;
|
|
||||||
const adresseLine = data.adresse
|
|
||||||
? `<tr><td style="padding:8px 12px;color:#666;font-size:14px;border-bottom:1px solid #eee">Adresse des travaux</td><td style="padding:8px 12px;font-size:14px;border-bottom:1px solid #eee">${data.adresse}</td></tr>`
|
|
||||||
: '';
|
|
||||||
|
|
||||||
return `<!DOCTYPE html>
|
|
||||||
<html lang="fr">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
</head>
|
|
||||||
<body style="margin:0;padding:0;background:#f5f5f5;font-family:system-ui,sans-serif">
|
|
||||||
<div style="max-width:600px;margin:0 auto;padding:40px 20px">
|
|
||||||
<div style="background:#314732;padding:32px;border-radius:8px 8px 0 0;text-align:center">
|
|
||||||
<h1 style="margin:0;color:#ffffff;font-size:22px;font-weight:600">Nouvelle demande de soumission</h1>
|
|
||||||
<p style="margin:8px 0 0;color:rgba(255,255,255,0.7);font-size:14px">Cachet Peintres Décorateurs</p>
|
|
||||||
</div>
|
|
||||||
<div style="background:#ffffff;border-radius:0 0 8px 8px;overflow:hidden">
|
|
||||||
<div style="padding:24px;background:#f0f4ef;border-bottom:2px solid #d6e2d4">
|
|
||||||
<p style="margin:0;font-size:15px;color:#314732;font-weight:600">
|
|
||||||
Vous avez reçu une nouvelle demande de soumission de la part de <strong>${data.nom}</strong>.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<table style="width:100%;border-collapse:collapse">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="padding:8px 12px;color:#666;font-size:14px;border-bottom:1px solid #eee;width:40%">Nom</td>
|
|
||||||
<td style="padding:8px 12px;font-size:14px;border-bottom:1px solid #eee;font-weight:600">${data.nom}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td style="padding:8px 12px;color:#666;font-size:14px;border-bottom:1px solid #eee">Courriel</td>
|
|
||||||
<td style="padding:8px 12px;font-size:14px;border-bottom:1px solid #eee"><a href="mailto:${data.courriel}" style="color:#314732;font-weight:600">${data.courriel}</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td style="padding:8px 12px;color:#666;font-size:14px;border-bottom:1px solid #eee">Téléphone</td>
|
|
||||||
<td style="padding:8px 12px;font-size:14px;border-bottom:1px solid #eee"><a href="tel:${data.telephone.replace(/\D/g, '')}" style="color:#314732;font-weight:600">${data.telephone}</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td style="padding:8px 12px;color:#666;font-size:14px;border-bottom:1px solid #eee">Type de service</td>
|
|
||||||
<td style="padding:8px 12px;font-size:14px;border-bottom:1px solid #eee">${serviceLabel}</td>
|
|
||||||
</tr>
|
|
||||||
${adresseLine}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div style="padding:20px">
|
|
||||||
<p style="margin:0 0 8px;font-size:13px;font-weight:700;color:#666;text-transform:uppercase;letter-spacing:0.05em">Message</p>
|
|
||||||
<div style="background:#f9fafb;border:1px solid #e5e7eb;border-radius:6px;padding:16px;font-size:14px;color:#374151;line-height:1.6;white-space:pre-wrap">${data.message}</div>
|
|
||||||
</div>
|
|
||||||
<div style="padding:16px 20px 24px">
|
|
||||||
<a href="mailto:${data.courriel}?subject=Re: Soumission — Cachet Peintres Décorateurs" style="display:inline-block;padding:10px 24px;background:#314732;color:#fff;text-decoration:none;border-radius:4px;font-size:14px;font-weight:700">Répondre à ${data.nom}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p style="margin:24px 0 0;text-align:center;font-size:11px;color:#999">
|
|
||||||
Cachet Peintres Décorateurs · 9500-5609 Québec Inc · RBQ 5839 8736 01
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function validateBody(body: unknown): body is SoumissionBody {
|
|
||||||
if (typeof body !== 'object' || body === null) return false;
|
|
||||||
const b = body as Record<string, unknown>;
|
|
||||||
return (
|
|
||||||
typeof b.nom === 'string' && b.nom.trim().length > 0 &&
|
|
||||||
typeof b.courriel === 'string' && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(b.courriel) &&
|
|
||||||
typeof b.telephone === 'string' && b.telephone.trim().length > 0 &&
|
|
||||||
typeof b.type_service === 'string' && b.type_service.length > 0 &&
|
|
||||||
typeof b.message === 'string' && b.message.trim().length > 0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const onRequestPost: PagesFunction<Env> = async (context) => {
|
|
||||||
const corsHeaders = {
|
|
||||||
'Access-Control-Allow-Origin': 'https://cachetdeco.com',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
};
|
|
||||||
|
|
||||||
// Rate limiting via CF headers (basic check)
|
|
||||||
const ip = context.request.headers.get('CF-Connecting-IP') ?? 'unknown';
|
|
||||||
|
|
||||||
let body: unknown;
|
|
||||||
try {
|
|
||||||
body = await context.request.json();
|
|
||||||
} catch {
|
|
||||||
return new Response(
|
|
||||||
JSON.stringify({ success: false, error: 'Corps de requête invalide.' }),
|
|
||||||
{ status: 400, headers: corsHeaders }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!validateBody(body)) {
|
|
||||||
return new Response(
|
|
||||||
JSON.stringify({ success: false, error: 'Données manquantes ou invalides.' }),
|
|
||||||
{ status: 422, headers: corsHeaders }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const apiKey = context.env.RESEND_API_KEY;
|
|
||||||
const contactEmail = context.env.CONTACT_EMAIL;
|
|
||||||
|
|
||||||
if (!apiKey || !contactEmail) {
|
|
||||||
console.error('Missing env vars: RESEND_API_KEY or CONTACT_EMAIL');
|
|
||||||
return new Response(
|
|
||||||
JSON.stringify({ success: false, error: 'Configuration serveur manquante.' }),
|
|
||||||
{ status: 500, headers: corsHeaders }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const emailPayload = {
|
|
||||||
from: 'Cachet Peintres Décorateurs <soumission@cachetdeco.com>',
|
|
||||||
to: [contactEmail],
|
|
||||||
reply_to: body.courriel,
|
|
||||||
subject: `Soumission — ${serviceLabels[body.type_service] ?? body.type_service} — ${body.nom}`,
|
|
||||||
html: buildEmailHtml(body),
|
|
||||||
};
|
|
||||||
|
|
||||||
const resendRes = await fetch('https://api.resend.com/emails', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Authorization': `Bearer ${apiKey}`,
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify(emailPayload),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!resendRes.ok) {
|
|
||||||
const resendError = await resendRes.text().catch(() => 'Unknown error');
|
|
||||||
console.error('Resend error:', resendError, 'IP:', ip);
|
|
||||||
return new Response(
|
|
||||||
JSON.stringify({ success: false, error: 'Erreur lors de l\'envoi du courriel.' }),
|
|
||||||
{ status: 502, headers: corsHeaders }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Response(
|
|
||||||
JSON.stringify({ success: true }),
|
|
||||||
{ status: 200, headers: corsHeaders }
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle preflight OPTIONS
|
|
||||||
export const onRequestOptions: PagesFunction = async () => {
|
|
||||||
return new Response(null, {
|
|
||||||
status: 204,
|
|
||||||
headers: {
|
|
||||||
'Access-Control-Allow-Origin': 'https://cachetdeco.com',
|
|
||||||
'Access-Control-Allow-Methods': 'POST, OPTIONS',
|
|
||||||
'Access-Control-Allow-Headers': 'Content-Type',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
90
package-lock.json
generated
@@ -8,6 +8,7 @@
|
|||||||
"name": "cachetdeco",
|
"name": "cachetdeco",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@astrojs/node": "^9.5.5",
|
||||||
"@astrojs/react": "^5.0.0",
|
"@astrojs/react": "^5.0.0",
|
||||||
"@astrojs/sitemap": "^3.2.1",
|
"@astrojs/sitemap": "^3.2.1",
|
||||||
"@fontsource-variable/geist": "^5.2.8",
|
"@fontsource-variable/geist": "^5.2.8",
|
||||||
@@ -21,6 +22,7 @@
|
|||||||
"embla-carousel-autoplay": "^8.6.0",
|
"embla-carousel-autoplay": "^8.6.0",
|
||||||
"embla-carousel-react": "^8.6.0",
|
"embla-carousel-react": "^8.6.0",
|
||||||
"lucide-react": "^0.577.0",
|
"lucide-react": "^0.577.0",
|
||||||
|
"motion": "^12.38.0",
|
||||||
"radix-ui": "^1.4.3",
|
"radix-ui": "^1.4.3",
|
||||||
"react": "^19.2.4",
|
"react": "^19.2.4",
|
||||||
"react-dom": "^19.2.4",
|
"react-dom": "^19.2.4",
|
||||||
@@ -96,6 +98,20 @@
|
|||||||
"vfile": "^6.0.3"
|
"vfile": "^6.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@astrojs/node": {
|
||||||
|
"version": "9.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@astrojs/node/-/node-9.5.5.tgz",
|
||||||
|
"integrity": "sha512-rtU2BGU5u3SfGURpANfMxVzCIoR86MkaN05ncza9rbtuMKJ/XnRJt/BbyVknDbOJ71hoci0SIsJwKcJR8vvi/A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@astrojs/internal-helpers": "0.7.6",
|
||||||
|
"send": "^1.2.1",
|
||||||
|
"server-destroy": "^1.0.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"astro": "^5.17.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@astrojs/prism": {
|
"node_modules/@astrojs/prism": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.3.0.tgz",
|
||||||
@@ -7162,6 +7178,33 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/framer-motion": {
|
||||||
|
"version": "12.38.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.38.0.tgz",
|
||||||
|
"integrity": "sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-dom": "^12.38.0",
|
||||||
|
"motion-utils": "^12.36.0",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "*",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fresh": {
|
"node_modules/fresh": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
|
||||||
@@ -9323,6 +9366,47 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/motion": {
|
||||||
|
"version": "12.38.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion/-/motion-12.38.0.tgz",
|
||||||
|
"integrity": "sha512-uYfXzeHlgThchzwz5Te47dlv5JOUC7OB4rjJ/7XTUgtBZD8CchMN8qEJ4ZVsUmTyYA44zjV0fBwsiktRuFnn+w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"framer-motion": "^12.38.0",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "*",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/motion-dom": {
|
||||||
|
"version": "12.38.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.38.0.tgz",
|
||||||
|
"integrity": "sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-utils": "^12.36.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/motion-utils": {
|
||||||
|
"version": "12.36.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.36.0.tgz",
|
||||||
|
"integrity": "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/mrmime": {
|
"node_modules/mrmime": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
|
||||||
@@ -10764,6 +10848,12 @@
|
|||||||
"url": "https://opencollective.com/express"
|
"url": "https://opencollective.com/express"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/server-destroy": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/setprototypeof": {
|
"node_modules/setprototypeof": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"astro": "astro"
|
"astro": "astro"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@astrojs/node": "^9.5.5",
|
||||||
"@astrojs/react": "^5.0.0",
|
"@astrojs/react": "^5.0.0",
|
||||||
"@astrojs/sitemap": "^3.2.1",
|
"@astrojs/sitemap": "^3.2.1",
|
||||||
"@fontsource-variable/geist": "^5.2.8",
|
"@fontsource-variable/geist": "^5.2.8",
|
||||||
@@ -22,6 +23,7 @@
|
|||||||
"embla-carousel-autoplay": "^8.6.0",
|
"embla-carousel-autoplay": "^8.6.0",
|
||||||
"embla-carousel-react": "^8.6.0",
|
"embla-carousel-react": "^8.6.0",
|
||||||
"lucide-react": "^0.577.0",
|
"lucide-react": "^0.577.0",
|
||||||
|
"motion": "^12.38.0",
|
||||||
"radix-ui": "^1.4.3",
|
"radix-ui": "^1.4.3",
|
||||||
"react": "^19.2.4",
|
"react": "^19.2.4",
|
||||||
"react-dom": "^19.2.4",
|
"react-dom": "^19.2.4",
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ collections:
|
|||||||
i18n: true
|
i18n: true
|
||||||
fields:
|
fields:
|
||||||
- { name: "services", label: "Page Services", widget: "string" }
|
- { name: "services", label: "Page Services", widget: "string" }
|
||||||
- { name: "soumission", label: "Page Soumission", widget: "string" }
|
- { name: "submission", label: "Page Soumission", widget: "string" }
|
||||||
|
|
||||||
- name: "hero"
|
- name: "hero"
|
||||||
label: "Hero (accueil)"
|
label: "Hero (accueil)"
|
||||||
@@ -172,10 +172,10 @@ collections:
|
|||||||
- { name: "button", label: "Bouton", widget: "string" }
|
- { name: "button", label: "Bouton", widget: "string" }
|
||||||
- { name: "breadcrumbHome", label: "Fil d'Ariane — Accueil", widget: "string", i18n: true }
|
- { name: "breadcrumbHome", label: "Fil d'Ariane — Accueil", widget: "string", i18n: true }
|
||||||
|
|
||||||
- name: "soumission"
|
- name: "submission"
|
||||||
label: "Page Soumission & formulaire"
|
label: "Page Soumission & formulaire"
|
||||||
label_singular: "Soumission"
|
label_singular: "Soumission"
|
||||||
folder: "src/content/soumission"
|
folder: "src/content/submission"
|
||||||
format: json
|
format: json
|
||||||
create: false
|
create: false
|
||||||
delete: false
|
delete: false
|
||||||
@@ -191,29 +191,33 @@ collections:
|
|||||||
i18n: true
|
i18n: true
|
||||||
fields:
|
fields:
|
||||||
- { name: "ariaLabel", label: "Aria-label formulaire", widget: "string" }
|
- { name: "ariaLabel", label: "Aria-label formulaire", widget: "string" }
|
||||||
- { name: "nom", label: "Libellé nom", widget: "string" }
|
- { name: "fullNameLabel", label: "Libellé nom complet", widget: "string" }
|
||||||
- { name: "nomPlaceholder", label: "Placeholder nom", widget: "string" }
|
- { name: "fullNamePlaceholder", label: "Placeholder nom", widget: "string" }
|
||||||
- { name: "courriel", label: "Libellé courriel", widget: "string" }
|
- { name: "emailLabel", label: "Libellé courriel", widget: "string" }
|
||||||
- { name: "courrielPlaceholder", label: "Placeholder courriel", widget: "string" }
|
- { name: "emailPlaceholder", label: "Placeholder courriel", widget: "string" }
|
||||||
- { name: "telephone", label: "Libellé téléphone", widget: "string" }
|
- { name: "phoneLabel", label: "Libellé téléphone", widget: "string" }
|
||||||
- { name: "telephonePlaceholder", label: "Placeholder téléphone", widget: "string" }
|
- { name: "phonePlaceholder", label: "Placeholder téléphone", widget: "string" }
|
||||||
- { name: "adresse", label: "Libellé adresse travaux", widget: "string" }
|
- { name: "workAddressLabel", label: "Libellé adresse travaux", widget: "string" }
|
||||||
- { name: "adressePlaceholder", label: "Placeholder adresse", widget: "string" }
|
- { name: "workAddressPlaceholder", label: "Placeholder adresse", widget: "string" }
|
||||||
- { name: "typeService", label: "Libellé type de service", widget: "string" }
|
- { name: "serviceTypeLabel", label: "Libellé type de service", widget: "string" }
|
||||||
- { name: "typeServicePlaceholder", label: "Placeholder sélection", widget: "string" }
|
- { name: "serviceTypePlaceholder", label: "Placeholder sélection", widget: "string" }
|
||||||
- name: "typeServiceOptions"
|
- name: "serviceTypeOptions"
|
||||||
label: "Options type de service"
|
label: "Options type de service"
|
||||||
widget: "object"
|
widget: "object"
|
||||||
fields:
|
fields:
|
||||||
- { name: "interieur", label: "Intérieur", widget: "string" }
|
- { name: "interior", label: "Intérieur", widget: "string" }
|
||||||
- { name: "exterieur", label: "Extérieur", widget: "string" }
|
- { name: "exterior", label: "Extérieur", widget: "string" }
|
||||||
- { name: "commercial", label: "Commercial", widget: "string" }
|
- { name: "commercial", label: "Commercial", widget: "string" }
|
||||||
- { name: "decoration", label: "Décoration", widget: "string" }
|
- { name: "decoration", label: "Décoration", widget: "string" }
|
||||||
- { name: "autre", label: "Autre", widget: "string" }
|
- { name: "other", label: "Autre", widget: "string" }
|
||||||
- { name: "message", label: "Libellé message", widget: "string" }
|
- { name: "messageLabel", label: "Libellé message", widget: "string" }
|
||||||
- { name: "messagePlaceholder", label: "Placeholder message", widget: "text" }
|
- { name: "messagePlaceholder", label: "Placeholder message", widget: "text" }
|
||||||
- { name: "envoyer", label: "Bouton envoyer", widget: "string" }
|
- { name: "attachmentsLabel", label: "Libellé pièces jointes", widget: "string" }
|
||||||
- { name: "sending", label: "État envoi", widget: "string" }
|
- { name: "attachmentsHint", label: "Aide zone dépôt", widget: "string" }
|
||||||
|
- { name: "attachmentsAccepted", label: "Formats acceptés", widget: "string" }
|
||||||
|
- { name: "attachmentsRemove", label: "Retirer fichier (aria)", widget: "string" }
|
||||||
|
- { name: "submitLabel", label: "Bouton envoyer", widget: "string" }
|
||||||
|
- { name: "submittingLabel", label: "État envoi", widget: "string" }
|
||||||
- { name: "successTitle", label: "Succès — titre", widget: "string" }
|
- { name: "successTitle", label: "Succès — titre", widget: "string" }
|
||||||
- { name: "successMessage", label: "Succès — message", widget: "text" }
|
- { name: "successMessage", label: "Succès — message", widget: "text" }
|
||||||
- { name: "errorTitle", label: "Erreur — titre", widget: "string" }
|
- { name: "errorTitle", label: "Erreur — titre", widget: "string" }
|
||||||
@@ -222,11 +226,13 @@ collections:
|
|||||||
label: "Messages validation"
|
label: "Messages validation"
|
||||||
widget: "object"
|
widget: "object"
|
||||||
fields:
|
fields:
|
||||||
- { name: "nom", label: "Nom", widget: "string" }
|
- { name: "fullName", label: "Nom", widget: "string" }
|
||||||
- { name: "courriel", label: "Courriel", widget: "string" }
|
- { name: "email", label: "Courriel", widget: "string" }
|
||||||
- { name: "telephone", label: "Téléphone", widget: "string" }
|
- { name: "phone", label: "Téléphone", widget: "string" }
|
||||||
- { name: "typeService", label: "Type service", widget: "string" }
|
- { name: "serviceType", label: "Type service", widget: "string" }
|
||||||
- { name: "message", label: "Message", widget: "string" }
|
- { name: "message", label: "Message", widget: "string" }
|
||||||
|
- { name: "attachmentsType", label: "Type fichier", widget: "string" }
|
||||||
|
- { name: "attachmentsSize", label: "Taille fichiers", widget: "string" }
|
||||||
- name: "sidebar"
|
- name: "sidebar"
|
||||||
label: "Barre latérale"
|
label: "Barre latérale"
|
||||||
widget: "object"
|
widget: "object"
|
||||||
@@ -356,6 +362,10 @@ collections:
|
|||||||
- { name: "taglineHero", label: "Slogan hero", widget: "string" }
|
- { name: "taglineHero", label: "Slogan hero", widget: "string" }
|
||||||
- { name: "phone", label: "Téléphone", widget: "string" }
|
- { name: "phone", label: "Téléphone", widget: "string" }
|
||||||
- { name: "email", label: "Courriel", widget: "string" }
|
- { name: "email", label: "Courriel", widget: "string" }
|
||||||
|
- { name: "emailFromContact", label: "Expéditeur courriel (formulaire contact, ex. Nom <adresse@domaine>)", widget: "string" }
|
||||||
|
- { name: "emailToContact", label: "Destinataire courriel (formulaire contact)", widget: "string" }
|
||||||
|
- { name: "fromAddressSubmission", label: "Expéditeur courriel (formulaire soumission, ex. Nom <adresse@domaine>)", widget: "string" }
|
||||||
|
- { name: "toAddressSubmission", label: "Destinataire courriel (formulaire soumission)", widget: "string" }
|
||||||
- { name: "address", label: "Adresse", widget: "string" }
|
- { name: "address", label: "Adresse", widget: "string" }
|
||||||
- { name: "serviceArea", label: "Zone de service", widget: "string" }
|
- { name: "serviceArea", label: "Zone de service", widget: "string" }
|
||||||
- { name: "facebook", label: "Lien Facebook", widget: "string" }
|
- { name: "facebook", label: "Lien Facebook", widget: "string" }
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 459 KiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 339 KiB |
|
Before Width: | Height: | Size: 3.0 MiB |
|
Before Width: | Height: | Size: 1.6 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 572 KiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.6 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1020 KiB |
|
Before Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 2.2 MiB |
|
Before Width: | Height: | Size: 2.3 MiB |
|
Before Width: | Height: | Size: 3.4 MiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.9 MiB |
|
Before Width: | Height: | Size: 152 KiB |
|
Before Width: | Height: | Size: 224 KiB |
|
Before Width: | Height: | Size: 258 KiB |
|
Before Width: | Height: | Size: 331 KiB |
|
Before Width: | Height: | Size: 202 KiB |
|
Before Width: | Height: | Size: 178 KiB |
|
Before Width: | Height: | Size: 432 KiB |
|
Before Width: | Height: | Size: 427 KiB |
|
Before Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 153 KiB |
|
Before Width: | Height: | Size: 204 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 210 KiB |
|
Before Width: | Height: | Size: 172 KiB |
|
Before Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 193 KiB |
|
Before Width: | Height: | Size: 126 KiB |
|
Before Width: | Height: | Size: 202 KiB |
|
Before Width: | Height: | Size: 269 KiB |
|
Before Width: | Height: | Size: 188 KiB |
|
Before Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 282 KiB |
|
Before Width: | Height: | Size: 410 KiB |
|
Before Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 196 KiB |
|
Before Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 521 KiB |
|
Before Width: | Height: | Size: 223 KiB |
|
Before Width: | Height: | Size: 298 KiB |
|
Before Width: | Height: | Size: 226 KiB |
|
Before Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 171 KiB |
|
Before Width: | Height: | Size: 227 KiB |
|
Before Width: | Height: | Size: 173 KiB |
|
Before Width: | Height: | Size: 525 KiB |
|
Before Width: | Height: | Size: 287 KiB |
|
Before Width: | Height: | Size: 311 KiB |
|
Before Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 198 KiB |
|
Before Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 434 KiB |
|
Before Width: | Height: | Size: 320 KiB |
|
Before Width: | Height: | Size: 213 KiB |
|
Before Width: | Height: | Size: 734 KiB |
|
Before Width: | Height: | Size: 164 KiB |
|
Before Width: | Height: | Size: 164 KiB |
|
Before Width: | Height: | Size: 157 KiB |
|
Before Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 126 KiB |
|
Before Width: | Height: | Size: 164 KiB |
|
Before Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 152 KiB |