mirror of
https://github.com/Luchexx/wacrm.git
synced 2026-11-02 17:29:45 +00:00
Merge pull request #27 from ArnasDon/fix/favicon-and-template-language
fix: WaCRM favicon + template language defaults to en_US
This commit is contained in:
commit
5c2f87fd01
45
src/app/icon.tsx
Normal file
45
src/app/icon.tsx
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { ImageResponse } from "next/og";
|
||||||
|
|
||||||
|
// Replaces the default Next.js favicon with the WaCRM mark — emerald
|
||||||
|
// rounded square + white chat-bubble glyph — matching the sidebar
|
||||||
|
// logo in `src/components/layout/sidebar.tsx`. Next.js renders this
|
||||||
|
// at build time and auto-injects <link rel="icon"> into <head>.
|
||||||
|
//
|
||||||
|
// This route takes precedence over src/app/favicon.ico, which is the
|
||||||
|
// Next.js default and can stay on disk harmlessly (or be removed).
|
||||||
|
|
||||||
|
export const runtime = "edge";
|
||||||
|
export const size = { width: 32, height: 32 };
|
||||||
|
export const contentType = "image/png";
|
||||||
|
|
||||||
|
export default function Icon() {
|
||||||
|
return new ImageResponse(
|
||||||
|
(
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
background: "#10b981", // emerald-500
|
||||||
|
borderRadius: 6,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="#ffffff"
|
||||||
|
strokeWidth="2.5"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
{ ...size },
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -53,15 +53,43 @@ interface TemplateFormData {
|
|||||||
footer_text: string;
|
footer_text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Meta's language codes are exact — "en" and "en_US" are distinct and a
|
||||||
|
// template approved under one will be rejected if you send with the other
|
||||||
|
// (Graph API error #132001 "Template name does not exist in the
|
||||||
|
// translation"). Default to en_US to match the DB default on
|
||||||
|
// message_templates.language and the broadcasts sender's fallback.
|
||||||
const emptyForm: TemplateFormData = {
|
const emptyForm: TemplateFormData = {
|
||||||
name: '',
|
name: '',
|
||||||
category: 'Marketing',
|
category: 'Marketing',
|
||||||
language: 'en',
|
language: 'en_US',
|
||||||
body_text: '',
|
body_text: '',
|
||||||
header_type: '',
|
header_type: '',
|
||||||
footer_text: '',
|
footer_text: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Common Meta template language codes. The field still accepts any
|
||||||
|
// string — this just offers autocomplete for the usual suspects. Full
|
||||||
|
// list: https://developers.facebook.com/docs/whatsapp/api/messages/message-templates#supported-languages
|
||||||
|
const COMMON_LANGUAGE_CODES = [
|
||||||
|
'en_US',
|
||||||
|
'en_GB',
|
||||||
|
'en',
|
||||||
|
'es',
|
||||||
|
'es_ES',
|
||||||
|
'es_MX',
|
||||||
|
'fr',
|
||||||
|
'fr_FR',
|
||||||
|
'de',
|
||||||
|
'it',
|
||||||
|
'pt_BR',
|
||||||
|
'pt_PT',
|
||||||
|
'nl',
|
||||||
|
'pl',
|
||||||
|
'ru',
|
||||||
|
'tr',
|
||||||
|
'lt',
|
||||||
|
];
|
||||||
|
|
||||||
export function TemplateManager() {
|
export function TemplateManager() {
|
||||||
const supabase = createClient();
|
const supabase = createClient();
|
||||||
const { user, loading: authLoading } = useAuth();
|
const { user, loading: authLoading } = useAuth();
|
||||||
@ -123,7 +151,7 @@ export function TemplateManager() {
|
|||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
name: form.name.trim(),
|
name: form.name.trim(),
|
||||||
category: form.category,
|
category: form.category,
|
||||||
language: form.language.trim() || 'en',
|
language: form.language.trim() || 'en_US',
|
||||||
body_text: form.body_text.trim(),
|
body_text: form.body_text.trim(),
|
||||||
header_type: form.header_type || null,
|
header_type: form.header_type || null,
|
||||||
footer_text: form.footer_text.trim() || null,
|
footer_text: form.footer_text.trim() || null,
|
||||||
@ -285,11 +313,22 @@ export function TemplateManager() {
|
|||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label className="text-slate-300">Language</Label>
|
<Label className="text-slate-300">Language</Label>
|
||||||
<Input
|
<Input
|
||||||
placeholder="en"
|
list="template-language-codes"
|
||||||
|
placeholder="en_US"
|
||||||
value={form.language}
|
value={form.language}
|
||||||
onChange={(e) => setForm({ ...form, language: e.target.value })}
|
onChange={(e) => setForm({ ...form, language: e.target.value })}
|
||||||
className="bg-slate-800 border-slate-700 text-white placeholder:text-slate-500"
|
className="bg-slate-800 border-slate-700 text-white placeholder:text-slate-500"
|
||||||
/>
|
/>
|
||||||
|
<datalist id="template-language-codes">
|
||||||
|
{COMMON_LANGUAGE_CODES.map((code) => (
|
||||||
|
<option key={code} value={code} />
|
||||||
|
))}
|
||||||
|
</datalist>
|
||||||
|
<p className="text-[11px] text-slate-500">
|
||||||
|
Must match the exact language code the template is approved
|
||||||
|
under on Meta — e.g. <code>en_US</code> and <code>en</code>{' '}
|
||||||
|
are distinct.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user