diff --git a/frontend/src/i18n/locales/de.json b/frontend/src/i18n/locales/de.json index 2f3f3cda..6be29353 100644 --- a/frontend/src/i18n/locales/de.json +++ b/frontend/src/i18n/locales/de.json @@ -2226,7 +2226,16 @@ "mutedTextColor": "Fußzeilentext", "mutedTextColorHelp": "Fußzeilentext und Copyright-Zeile. Entspricht Branding → Sekundärer Text.", "buttonTextColor": "Button-Text", - "buttonTextColorHelp": "Textfarbe auf gefüllten Buttons. Sollte klar gegen die Primärfarbe kontrastieren. Kein Branding-Äquivalent — meistens weiß." + "buttonTextColorHelp": "Textfarbe auf gefüllten Buttons. Sollte klar gegen die Primärfarbe kontrastieren. Kein Branding-Äquivalent — meistens weiß.", + "categories": { + "core": "Kern", + "customers": "Kunden", + "calendar": "Kalender", + "quotes": "Angebote", + "billing": "Rechnungen" + }, + "featureOff": "Funktion aus", + "featureOffTooltip": "Die zugehörige Funktion ist derzeit deaktiviert. Du kannst die Vorlage trotzdem bearbeiten — sie wird verwendet, sobald die Funktion wieder aktiviert ist." }, "cms": { "title": "CMS-Seiten", diff --git a/frontend/src/i18n/locales/en.json b/frontend/src/i18n/locales/en.json index 079b5644..2f12b31a 100644 --- a/frontend/src/i18n/locales/en.json +++ b/frontend/src/i18n/locales/en.json @@ -1880,7 +1880,16 @@ "mutedTextColor": "Footer text", "mutedTextColorHelp": "Footer text and copyright line. Maps to Branding → Secondary text.", "buttonTextColor": "Button text", - "buttonTextColorHelp": "Text colour on filled buttons. Should contrast cleanly against the Primary colour. No Branding equivalent — usually white." + "buttonTextColorHelp": "Text colour on filled buttons. Should contrast cleanly against the Primary colour. No Branding equivalent — usually white.", + "categories": { + "core": "Core", + "customers": "Customers", + "calendar": "Calendar", + "quotes": "Quotes", + "billing": "Billing" + }, + "featureOff": "Feature off", + "featureOffTooltip": "The feature this template belongs to is currently disabled. You can still edit the template — it will be used once the feature is re-enabled." }, "cms": { "title": "CMS Pages", diff --git a/frontend/src/i18n/locales/fr.json b/frontend/src/i18n/locales/fr.json index fe92cd25..136ed739 100644 --- a/frontend/src/i18n/locales/fr.json +++ b/frontend/src/i18n/locales/fr.json @@ -1826,7 +1826,16 @@ "enterUrl": "Saisir une URL…", "addLink": "Ajouter", "cancel": "Annuler" - } + }, + "categories": { + "core": "Principal", + "customers": "Clients", + "calendar": "Calendrier", + "quotes": "Devis", + "billing": "Facturation" + }, + "featureOff": "Fonction désactivée", + "featureOffTooltip": "La fonctionnalité à laquelle appartient ce modèle est actuellement désactivée. Vous pouvez toujours modifier le modèle — il sera utilisé une fois la fonctionnalité réactivée." }, "cms": { "title": "Pages CMS", diff --git a/frontend/src/i18n/locales/nl.json b/frontend/src/i18n/locales/nl.json index 01af8d6b..3a6d59b3 100644 --- a/frontend/src/i18n/locales/nl.json +++ b/frontend/src/i18n/locales/nl.json @@ -1880,7 +1880,16 @@ "mutedTextColor": "Voetteksttekst", "mutedTextColorHelp": "Voetteksttekst en copyrightregel. Komt overeen met Huisstijl → Secundaire tekst.", "buttonTextColor": "Knoptekst", - "buttonTextColorHelp": "Tekstkleur op gevulde knoppen. Moet goed contrasteren met de primaire kleur. Doorgaans wit." + "buttonTextColorHelp": "Tekstkleur op gevulde knoppen. Moet goed contrasteren met de primaire kleur. Doorgaans wit.", + "categories": { + "core": "Kern", + "customers": "Klanten", + "calendar": "Agenda", + "quotes": "Offertes", + "billing": "Facturatie" + }, + "featureOff": "Functie uit", + "featureOffTooltip": "De functie waar deze sjabloon bij hoort, is momenteel uitgeschakeld. U kunt de sjabloon nog steeds bewerken — deze wordt gebruikt zodra de functie weer is ingeschakeld." }, "cms": { "title": "CMS-pagina's", diff --git a/frontend/src/i18n/locales/pt.json b/frontend/src/i18n/locales/pt.json index 80268c69..58b99a8d 100644 --- a/frontend/src/i18n/locales/pt.json +++ b/frontend/src/i18n/locales/pt.json @@ -1905,7 +1905,16 @@ "mutedTextColor": "Texto do rodapé", "mutedTextColorHelp": "Texto do rodapé e linha de copyright. Corresponde a Identidade Visual → Texto secundário.", "buttonTextColor": "Texto dos botões", - "buttonTextColorHelp": "Cor do texto em botões preenchidos. Deve contrastar bem com a cor primária. Geralmente branco." + "buttonTextColorHelp": "Cor do texto em botões preenchidos. Deve contrastar bem com a cor primária. Geralmente branco.", + "categories": { + "core": "Principal", + "customers": "Clientes", + "calendar": "Calendário", + "quotes": "Orçamentos", + "billing": "Faturamento" + }, + "featureOff": "Recurso desativado", + "featureOffTooltip": "O recurso ao qual este modelo pertence está atualmente desativado. Você ainda pode editar o modelo — ele será usado assim que o recurso for reativado." }, "cms": { "title": "Páginas CMS", diff --git a/frontend/src/i18n/locales/ru.json b/frontend/src/i18n/locales/ru.json index 6a157dad..e8f5744a 100644 --- a/frontend/src/i18n/locales/ru.json +++ b/frontend/src/i18n/locales/ru.json @@ -1930,7 +1930,16 @@ "mutedTextColor": "Текст подвала", "mutedTextColorHelp": "Текст подвала и строка авторского права. Соответствует Брендинг → Дополнительный текст.", "buttonTextColor": "Текст кнопок", - "buttonTextColorHelp": "Цвет текста на заполненных кнопках. Должен хорошо контрастировать с основным цветом. Обычно белый." + "buttonTextColorHelp": "Цвет текста на заполненных кнопках. Должен хорошо контрастировать с основным цветом. Обычно белый.", + "categories": { + "core": "Основное", + "customers": "Клиенты", + "calendar": "Календарь", + "quotes": "Сметы", + "billing": "Счета" + }, + "featureOff": "Функция выключена", + "featureOffTooltip": "Связанная функция в данный момент отключена. Вы по-прежнему можете редактировать шаблон — он будет использоваться после повторного включения функции." }, "cms": { "title": "Страницы CMS", diff --git a/frontend/src/pages/admin/EmailConfigPage.tsx b/frontend/src/pages/admin/EmailConfigPage.tsx index e7d06a6b..aa39412f 100644 --- a/frontend/src/pages/admin/EmailConfigPage.tsx +++ b/frontend/src/pages/admin/EmailConfigPage.tsx @@ -24,6 +24,22 @@ import { emailService, type EmailConfig, type EmailTemplate, type EmailTemplateT import { settingsService } from '../../services/settings.service'; import { useTranslation } from 'react-i18next'; import { SUPPORTED_LANGUAGES } from "../../components/common/LanguageSelector.tsx"; +import { useFeatureFlags, type FeatureKey } from '../../contexts/FeatureFlagsContext'; + +/** + * Template categorisation (migration 098). Order matters — sidebar + * sections render in this sequence. Empty categories are hidden + * automatically. New categories: add the key here, give it an i18n + * label below, set `feature_flag` on templates that should chip + * out when the matching flag is off. No other UI changes required. + */ +const CATEGORY_ORDER: readonly string[] = [ + 'core', + 'customers', + 'calendar', + 'quotes', + 'billing', +] as const; const defaultTemplateKeys = [ { @@ -117,6 +133,7 @@ export const EmailConfigPage: React.FC = () => { const [emailMutedTextColor, setEmailMutedTextColor] = useState('#666666'); const [emailButtonTextColor, setEmailButtonTextColor] = useState('#ffffff'); const queryClient = useQueryClient(); + const { flags: featureFlags } = useFeatureFlags(); // SMTP Configuration state const [smtpConfig, setSmtpConfig] = useState({ @@ -714,39 +731,83 @@ export const EmailConfigPage: React.FC = () => {

{t('email.templates')}

-
- {templates.map(template => { - const templateInfo = defaultTemplateKeys.find(t => t.key === template.template_key); - const translationCount = getTranslationCount(template); - const enTranslation = template.translations?.en; - return ( - + ); + })} +
-

- {enTranslation?.subject || ''} -

- - ); - })} - + ))} + + ); + })()}