From 2347dccafe3f5b3ab9a71a0a2e5a4b9f49aae69b Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Mon, 16 Mar 2026 23:42:28 +0100 Subject: [PATCH] feat(memberTransferService, trainingStatsService, i18n): enhance member transfer logic and update localization files - Updated the member transfer service to only load active members with `testMembership = false`, improving data accuracy during transfers. - Introduced new functions in the training stats service to count missed training weeks, enhancing training participation tracking. - Expanded localization files for multiple languages, adding new keys and translations for member management features, improving user experience across the application. --- backend/services/memberTransferService.js | 6 +- backend/services/trainingStatsService.js | 48 + frontend/src/i18n/locales/de-CH.json | 93 ++ frontend/src/i18n/locales/de-extended.json | 93 +- frontend/src/i18n/locales/de.json | 103 +- frontend/src/i18n/locales/en-AU.json | 93 ++ frontend/src/i18n/locales/en-GB.json | 103 ++ frontend/src/i18n/locales/en-US.json | 93 ++ frontend/src/i18n/locales/es.json | 93 ++ frontend/src/i18n/locales/fil.json | 93 ++ frontend/src/i18n/locales/fr.json | 93 ++ frontend/src/i18n/locales/it.json | 93 ++ frontend/src/i18n/locales/ja.json | 93 ++ frontend/src/i18n/locales/pl.json | 93 ++ frontend/src/i18n/locales/th.json | 93 ++ frontend/src/i18n/locales/tl.json | 93 ++ frontend/src/i18n/locales/zh.json | 93 ++ frontend/src/views/MembersView.vue | 1627 +++++++++++++++++--- 18 files changed, 2903 insertions(+), 193 deletions(-) diff --git a/backend/services/memberTransferService.js b/backend/services/memberTransferService.js index 1e70c981..cd67b725 100644 --- a/backend/services/memberTransferService.js +++ b/backend/services/memberTransferService.js @@ -7,7 +7,7 @@ import { devLog, infoLog, errorLog } from '../utils/logger.js'; class MemberTransferService { /** - * Überträgt alle Mitglieder mit testMembership = false an einen externen Endpoint + * Überträgt alle aktiven Mitglieder mit testMembership = false an einen externen Endpoint * * @param {string} userToken - User Token für Authentifizierung * @param {number} clubId - Club ID @@ -26,10 +26,11 @@ class MemberTransferService { try { await checkAccess(userToken, clubId); - // 1. Alle Mitglieder mit testMembership = false laden + // 1. Alle aktiven Mitglieder mit testMembership = false laden const members = await Member.findAll({ where: { clubId: clubId, + active: true, testMembership: false } }); @@ -1008,4 +1009,3 @@ class MemberTransferService { } export default new MemberTransferService(); - diff --git a/backend/services/trainingStatsService.js b/backend/services/trainingStatsService.js index ed3ffe1e..24a6cc9e 100644 --- a/backend/services/trainingStatsService.js +++ b/backend/services/trainingStatsService.js @@ -1,6 +1,41 @@ import { DiaryDate, Member, Participant } from '../models/index.js'; import { Op } from 'sequelize'; +function getIsoWeekKey(dateLike) { + const date = new Date(dateLike); + if (Number.isNaN(date.getTime())) { + return null; + } + + const utcDate = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())); + const dayNum = utcDate.getUTCDay() || 7; + utcDate.setUTCDate(utcDate.getUTCDate() + 4 - dayNum); + const yearStart = new Date(Date.UTC(utcDate.getUTCFullYear(), 0, 1)); + const weekNum = Math.ceil((((utcDate - yearStart) / 86400000) + 1) / 7); + return `${utcDate.getUTCFullYear()}-${String(weekNum).padStart(2, '0')}`; +} + +function countMissedTrainingWeeks(trainingDates, lastTrainingDate) { + const lastTrainingTs = lastTrainingDate ? new Date(lastTrainingDate).getTime() : null; + const weeks = new Set(); + + for (const trainingDate of trainingDates) { + const ts = new Date(trainingDate).getTime(); + if (Number.isNaN(ts)) { + continue; + } + if (lastTrainingTs !== null && ts <= lastTrainingTs) { + continue; + } + const key = getIsoWeekKey(trainingDate); + if (key) { + weeks.add(key); + } + } + + return weeks.size; +} + class TrainingStatsService { async getTrainingStats(clubIdRaw) { const clubId = parseInt(clubIdRaw, 10); @@ -33,6 +68,15 @@ class TrainingStatsService { }); const stats = []; + const trainingDates12Months = await DiaryDate.findAll({ + where: { + clubId, + date: { [Op.gte]: twelveMonthsAgo } + }, + attributes: ['date'], + order: [['date', 'DESC']] + }); + const trainingDateValues12Months = trainingDates12Months.map(entry => entry.date); for (const member of members) { const participation12Months = await Participant.count({ @@ -89,6 +133,8 @@ class TrainingStatsService { const lastTrainingDate = trainingDetails.length ? trainingDetails[0].diaryDate.date : null; const lastTrainingTs = lastTrainingDate ? new Date(lastTrainingDate).getTime() : 0; + const missedTrainingWeeks = countMissedTrainingWeeks(trainingDateValues12Months, lastTrainingDate); + const notInTraining = missedTrainingWeeks >= 6; stats.push({ id: member.id, @@ -100,6 +146,8 @@ class TrainingStatsService { participationTotal, lastTraining: lastTrainingDate, lastTrainingTs, + missedTrainingWeeks, + notInTraining, trainingDetails: formattedTrainingDetails }); } diff --git a/frontend/src/i18n/locales/de-CH.json b/frontend/src/i18n/locales/de-CH.json index ba263334..a9fe0e31 100644 --- a/frontend/src/i18n/locales/de-CH.json +++ b/frontend/src/i18n/locales/de-CH.json @@ -357,5 +357,98 @@ "stageFlowReadinessReady": "Übergang ist fachlich startklar", "stageFlowQualifiedPreviewTitle": "Aktuell qualifiziert", "stageFlowQualifiedPreviewEntry": "G{group} · Platz {position} · {name}" + }, + "members": { + "subtitle": "Mitglieder suchen, filtern und direkt bearbeiten.", + "closeEditor": "Editor schließen", + "visibleMembers": "Sichtbare Mitglieder", + "search": "Suche", + "searchPlaceholder": "Name, Ort, Telefon oder E-Mail suchen", + "memberScope": "Mitgliedsbereich", + "scopeAll": "Alle", + "scopeActive": "Aktiv", + "scopeTest": "Probe", + "scopeNeedsForm": "Formular ungeprüft", + "scopeInactive": "Inaktiv", + "resultsVisible": "Mitglieder sichtbar", + "editHint": "Ein Klick auf eine Zeile öffnet den Editor.", + "editorCreateHint": "Neues Mitglied anlegen und Kontaktdaten direkt erfassen.", + "editorEditHint": "Daten von {name} bearbeiten.", + "transferSuccessTitle": "Übertragung erfolgreich", + "transferErrorTitle": "Fehler bei der Übertragung", + "clickTtRequestPending": "Click-TT-Antrag läuft", + "clickTtRequestAction": "Spielberechtigung in click-TT beantragen", + "clickTtRequestTitle": "Click-TT-Antrag starten", + "clickTtRequestConfirm": "Soll für {name} der automatisierte Click-TT-Antrag gestartet werden?", + "clickTtRequestHint": "Der Antrag wird im Backend automatisiert durch den Click-TT-Workflow geführt.", + "clickTtRequestSuccess": "Bitte loggen Sie sich noch auf click-tt ein und senden Sie den Antrag ab.", + "clickTtRequestError": "Der Click-TT-Antrag konnte nicht eingereicht werden.", + "clickTtRequestFailedLog": "Click-TT-Antrag fehlgeschlagen", + "deleteImageTitle": "Bild löschen", + "deleteImageConfirm": "Möchten Sie dieses Bild wirklich löschen?", + "parentFallback": "Elternteil", + "loadingMembers": "Lade Mitglieder...", + "errorLoadingMembers": "Laden der Mitgliederliste fehlgeschlagen.", + "scopeNotTraining": "Nicht mehr im Training", + "notInTrainingTooltip": "Seit {weeks} Trainingswochen ohne Teilnahme", + "status": "Status", + "contact": "Kontakt", + "noPhoneShort": "Kein Telefon", + "noEmailShort": "Keine E-Mail", + "noAddressShort": "Keine Adresse", + "clickTtSubmitted": "Click-TT gestellt", + "markRegular": "Als regulär markieren", + "markFormReceived": "Formular geprüft", + "clickTtRequestShort": "Click-TT", + "clickTtRequestPendingShort": "Läuft ...", + "memberDetails": "Mitgliedsdetails", + "previewLastTraining": "Letztes Training", + "previewNoLastTraining": "Noch keine Teilnahme", + "phoneListForSelection": "Telefonliste für Auswahl", + "markFormsForSelection": "Formulare für Auswahl prüfen", + "markRegularForSelection": "Auswahl als regulär markieren", + "phoneListSelectionFile": "Telefonliste-Auswahl.pdf", + "batchFormsMarkedSuccess": "{count} Formular(e) als geprüft markiert.", + "batchFormsMarkedEmpty": "In der aktuellen Auswahl gibt es keine ungeprüften Formulare.", + "batchMarkedRegularSuccess": "{count} Probe-Mitglied(er) als regulär markiert.", + "batchMarkedRegularEmpty": "In der aktuellen Auswahl gibt es keine Probe-Mitglieder.", + "batchPartialFailure": "{success} erfolgreich, {failed} fehlgeschlagen.", + "sortBy": "Sortieren nach", + "sortLastName": "Nachname", + "sortFirstName": "Vorname", + "sortBirthday": "Geburtstag", + "sortAge": "Alter", + "age": "Alter", + "openTasks": "Offene Aufgaben", + "noOpenTasks": "Keine offenen Aufgaben", + "taskVerifyForm": "Formular prüfen", + "taskReviewTrialStatus": "Probe-Status prüfen", + "taskCheckTrainingStatus": "Trainingsstatus prüfen", + "taskCheckClickTt": "Click-TT-Spielberechtigung prüfen", + "taskActionVerify": "Prüfen", + "taskActionMarkRegular": "Regulär setzen", + "taskActionRequest": "Anfragen", + "toggleSortDirection": "Sortierrichtung wechseln", + "sortLastTraining": "Letztes Training", + "sortOpenTasks": "Offene Aufgaben", + "exportPreview": "Exportvorschau", + "exportMembersSelected": "Mitglieder aktuell ausgewählt", + "exportPhones": "Telefon", + "exportReachableByPhone": "mit Telefonnummer", + "exportEmails": "E-Mail", + "exportReachableByEmail": "mit E-Mail-Adresse", + "exportPreviewNames": "Vorschau", + "exportPreviewEmpty": "Keine Mitglieder in der aktuellen Auswahl", + "exportCsv": "CSV exportieren", + "exportCsvFile": "mitglieder-auswahl.csv", + "copyPhones": "Telefone kopieren", + "copyEmails": "E-Mails kopieren", + "copyPhonesSuccess": "Telefonliste in die Zwischenablage kopiert.", + "copyPhonesEmpty": "In der aktuellen Auswahl gibt es keine Telefonnummern.", + "copyEmailsSuccess": "E-Mail-Liste in die Zwischenablage kopiert.", + "copyEmailsEmpty": "In der aktuellen Auswahl gibt es keine E-Mail-Adressen.", + "composeEmail": "E-Mail vorbereiten", + "copyContactSummary": "Kontaktübersicht kopieren", + "copyContactSummarySuccess": "Kontaktübersicht in die Zwischenablage kopiert." } } diff --git a/frontend/src/i18n/locales/de-extended.json b/frontend/src/i18n/locales/de-extended.json index 78dbf902..e0275a6b 100644 --- a/frontend/src/i18n/locales/de-extended.json +++ b/frontend/src/i18n/locales/de-extended.json @@ -201,7 +201,98 @@ "picsInInternetAllowed": "Pics in Internet erlaubt", "testMembership": "Testmitgliedschaft", "memberFormHandedOver": "Mitgliedsformular ausgehändigt", - "trainingGroups": "Trainingsgruppen" + "trainingGroups": "Trainingsgruppen", + "subtitle": "Mitglieder suchen, filtern und direkt bearbeiten.", + "closeEditor": "Editor schließen", + "visibleMembers": "Sichtbare Mitglieder", + "search": "Suche", + "searchPlaceholder": "Name, Ort, Telefon oder E-Mail suchen", + "memberScope": "Mitgliedsbereich", + "scopeAll": "Alle", + "scopeActive": "Aktiv", + "scopeTest": "Probe", + "scopeNeedsForm": "Formular ungeprüft", + "scopeInactive": "Inaktiv", + "resultsVisible": "Mitglieder sichtbar", + "editHint": "Ein Klick auf eine Zeile öffnet den Editor.", + "editorCreateHint": "Neues Mitglied anlegen und Kontaktdaten direkt erfassen.", + "editorEditHint": "Daten von {name} bearbeiten.", + "transferSuccessTitle": "Übertragung erfolgreich", + "transferErrorTitle": "Fehler bei der Übertragung", + "clickTtRequestPending": "Click-TT-Antrag läuft", + "clickTtRequestAction": "Spielberechtigung in click-TT beantragen", + "clickTtRequestTitle": "Click-TT-Antrag starten", + "clickTtRequestConfirm": "Soll für {name} der automatisierte Click-TT-Antrag gestartet werden?", + "clickTtRequestHint": "Der Antrag wird im Backend automatisiert durch den Click-TT-Workflow geführt.", + "clickTtRequestSuccess": "Bitte loggen Sie sich noch auf click-tt ein und senden Sie den Antrag ab.", + "clickTtRequestError": "Der Click-TT-Antrag konnte nicht eingereicht werden.", + "clickTtRequestFailedLog": "Click-TT-Antrag fehlgeschlagen", + "deleteImageTitle": "Bild löschen", + "deleteImageConfirm": "Möchten Sie dieses Bild wirklich löschen?", + "parentFallback": "Elternteil", + "loadingMembers": "Lade Mitglieder...", + "errorLoadingMembers": "Laden der Mitgliederliste fehlgeschlagen.", + "scopeNotTraining": "Nicht mehr im Training", + "notInTrainingTooltip": "Seit {weeks} Trainingswochen ohne Teilnahme", + "status": "Status", + "contact": "Kontakt", + "noPhoneShort": "Kein Telefon", + "noEmailShort": "Keine E-Mail", + "noAddressShort": "Keine Adresse", + "clickTtSubmitted": "Click-TT gestellt", + "markRegular": "Als regulär markieren", + "markFormReceived": "Formular geprüft", + "clickTtRequestShort": "Click-TT", + "clickTtRequestPendingShort": "Läuft ...", + "memberDetails": "Mitgliedsdetails", + "previewLastTraining": "Letztes Training", + "previewNoLastTraining": "Noch keine Teilnahme", + "phoneListForSelection": "Telefonliste für Auswahl", + "markFormsForSelection": "Formulare für Auswahl prüfen", + "markRegularForSelection": "Auswahl als regulär markieren", + "phoneListSelectionFile": "Telefonliste-Auswahl.pdf", + "batchFormsMarkedSuccess": "{count} Formular(e) als geprüft markiert.", + "batchFormsMarkedEmpty": "In der aktuellen Auswahl gibt es keine ungeprüften Formulare.", + "batchMarkedRegularSuccess": "{count} Probe-Mitglied(er) als regulär markiert.", + "batchMarkedRegularEmpty": "In der aktuellen Auswahl gibt es keine Probe-Mitglieder.", + "batchPartialFailure": "{success} erfolgreich, {failed} fehlgeschlagen.", + "sortBy": "Sortieren nach", + "sortLastName": "Nachname", + "sortFirstName": "Vorname", + "sortBirthday": "Geburtstag", + "sortAge": "Alter", + "age": "Alter", + "openTasks": "Offene Aufgaben", + "noOpenTasks": "Keine offenen Aufgaben", + "taskVerifyForm": "Formular prüfen", + "taskReviewTrialStatus": "Probe-Status prüfen", + "taskCheckTrainingStatus": "Trainingsstatus prüfen", + "taskCheckClickTt": "Click-TT-Spielberechtigung prüfen", + "taskActionVerify": "Prüfen", + "taskActionMarkRegular": "Regulär setzen", + "taskActionRequest": "Anfragen", + "toggleSortDirection": "Sortierrichtung wechseln", + "sortLastTraining": "Letztes Training", + "sortOpenTasks": "Offene Aufgaben", + "exportPreview": "Exportvorschau", + "exportMembersSelected": "Mitglieder aktuell ausgewählt", + "exportPhones": "Telefon", + "exportReachableByPhone": "mit Telefonnummer", + "exportEmails": "E-Mail", + "exportReachableByEmail": "mit E-Mail-Adresse", + "exportPreviewNames": "Vorschau", + "exportPreviewEmpty": "Keine Mitglieder in der aktuellen Auswahl", + "exportCsv": "CSV exportieren", + "exportCsvFile": "mitglieder-auswahl.csv", + "copyPhones": "Telefone kopieren", + "copyEmails": "E-Mails kopieren", + "copyPhonesSuccess": "Telefonliste in die Zwischenablage kopiert.", + "copyPhonesEmpty": "In der aktuellen Auswahl gibt es keine Telefonnummern.", + "copyEmailsSuccess": "E-Mail-Liste in die Zwischenablage kopiert.", + "copyEmailsEmpty": "In der aktuellen Auswahl gibt es keine E-Mail-Adressen.", + "composeEmail": "E-Mail vorbereiten", + "copyContactSummary": "Kontaktübersicht kopieren", + "copyContactSummarySuccess": "Kontaktübersicht in die Zwischenablage kopiert." }, "diary": { "title": "Trainingstagebuch", diff --git a/frontend/src/i18n/locales/de.json b/frontend/src/i18n/locales/de.json index 6a2b7683..834c9905 100644 --- a/frontend/src/i18n/locales/de.json +++ b/frontend/src/i18n/locales/de.json @@ -282,7 +282,108 @@ "phoneList": "Telefonliste.pdf", "errorLoadingTrainingParticipations": "Fehler beim Laden der Trainingsteilnahmen", "errorUpdatingRatings": "Fehler beim Aktualisieren der TTR/QTTR-Werte", - "errorTransfer": "Fehler bei der Übertragung" + "errorTransfer": "Fehler bei der Übertragung", + "subtitle": "Mitglieder suchen, filtern und direkt bearbeiten.", + "closeEditor": "Editor schließen", + "visibleMembers": "Sichtbare Mitglieder", + "search": "Suche", + "searchPlaceholder": "Name, Ort, Telefon oder E-Mail suchen", + "memberScope": "Mitgliedsbereich", + "scopeAll": "Alle", + "scopeActive": "Aktiv", + "scopeTest": "Probe", + "scopeNeedsForm": "Formular ungeprüft", + "scopeDataIncomplete": "Daten unvollständig", + "scopeInactive": "Inaktiv", + "resultsVisible": "Mitglieder sichtbar", + "editHint": "Ein Klick auf eine Zeile öffnet den Editor.", + "editorCreateHint": "Neues Mitglied anlegen und Kontaktdaten direkt erfassen.", + "editorEditHint": "Daten von {name} bearbeiten.", + "transferSuccessTitle": "Übertragung erfolgreich", + "transferErrorTitle": "Fehler bei der Übertragung", + "clickTtRequestPending": "Click-TT-Antrag läuft", + "clickTtRequestAction": "Spielberechtigung in click-TT beantragen", + "clickTtRequestTitle": "Click-TT-Antrag starten", + "clickTtRequestConfirm": "Soll für {name} der automatisierte Click-TT-Antrag gestartet werden?", + "clickTtRequestHint": "Der Antrag wird im Backend automatisiert durch den Click-TT-Workflow geführt.", + "clickTtRequestSuccess": "Bitte loggen Sie sich noch auf click-tt ein und senden Sie den Antrag ab.", + "clickTtRequestError": "Der Click-TT-Antrag konnte nicht eingereicht werden.", + "clickTtRequestFailedLog": "Click-TT-Antrag fehlgeschlagen", + "deleteImageTitle": "Bild löschen", + "deleteImageConfirm": "Möchten Sie dieses Bild wirklich löschen?", + "parentFallback": "Elternteil", + "loadingMembers": "Lade Mitglieder...", + "errorLoadingMembers": "Laden der Mitgliederliste fehlgeschlagen.", + "scopeNotTraining": "Nicht mehr im Training", + "notInTrainingTooltip": "Seit {weeks} Trainingswochen ohne Teilnahme", + "status": "Status", + "contact": "Kontakt", + "noPhoneShort": "Kein Telefon", + "noEmailShort": "Keine E-Mail", + "noAddressShort": "Keine Adresse", + "clickTtSubmitted": "Click-TT gestellt", + "markRegular": "Als regulär markieren", + "markFormReceived": "Formular geprüft", + "clickTtRequestShort": "Click-TT", + "clickTtRequestPendingShort": "Läuft ...", + "memberDetails": "Mitgliedsdetails", + "previewLastTraining": "Letztes Training", + "previewNoLastTraining": "Noch keine Teilnahme", + "phoneListForSelection": "Telefonliste für Auswahl", + "markFormsForSelection": "Formulare für Auswahl prüfen", + "markRegularForSelection": "Auswahl als regulär markieren", + "phoneListSelectionFile": "Telefonliste-Auswahl.pdf", + "batchFormsMarkedSuccess": "{count} Formular(e) als geprüft markiert.", + "batchFormsMarkedEmpty": "In der aktuellen Auswahl gibt es keine ungeprüften Formulare.", + "batchMarkedRegularSuccess": "{count} Probe-Mitglied(er) als regulär markiert.", + "batchMarkedRegularEmpty": "In der aktuellen Auswahl gibt es keine Probe-Mitglieder.", + "batchPartialFailure": "{success} erfolgreich, {failed} fehlgeschlagen.", + "sortBy": "Sortieren nach", + "sortLastName": "Nachname", + "sortFirstName": "Vorname", + "sortBirthday": "Geburtstag", + "sortAge": "Alter", + "age": "Alter", + "dataQuality": "Datenqualität", + "dataQualityComplete": "Daten vollständig", + "dataIssueBirthdate": "Geburtsdatum fehlt", + "dataIssuePhone": "Telefon fehlt", + "dataIssueEmail": "E-Mail fehlt", + "dataIssueAddress": "Adresse fehlt", + "dataIssueGender": "Geschlecht ungeklärt", + "openTasks": "Offene Aufgaben", + "noOpenTasks": "Keine offenen Aufgaben", + "taskVerifyForm": "Formular prüfen", + "taskReviewTrialStatus": "Probe-Status prüfen", + "taskCheckTrainingStatus": "Trainingsstatus prüfen", + "taskCheckDataQuality": "Datenqualität prüfen", + "taskCheckClickTt": "Click-TT-Spielberechtigung prüfen", + "taskActionVerify": "Prüfen", + "taskActionMarkRegular": "Regulär setzen", + "taskActionReview": "Öffnen", + "taskActionRequest": "Anfragen", + "toggleSortDirection": "Sortierrichtung wechseln", + "sortLastTraining": "Letztes Training", + "sortOpenTasks": "Offene Aufgaben", + "exportPreview": "Exportvorschau", + "exportMembersSelected": "Mitglieder aktuell ausgewählt", + "exportPhones": "Telefon", + "exportReachableByPhone": "mit Telefonnummer", + "exportEmails": "E-Mail", + "exportReachableByEmail": "mit E-Mail-Adresse", + "exportPreviewNames": "Vorschau", + "exportPreviewEmpty": "Keine Mitglieder in der aktuellen Auswahl", + "exportCsv": "CSV exportieren", + "exportCsvFile": "mitglieder-auswahl.csv", + "copyPhones": "Telefone kopieren", + "copyEmails": "E-Mails kopieren", + "copyPhonesSuccess": "Telefonliste in die Zwischenablage kopiert.", + "copyPhonesEmpty": "In der aktuellen Auswahl gibt es keine Telefonnummern.", + "copyEmailsSuccess": "E-Mail-Liste in die Zwischenablage kopiert.", + "copyEmailsEmpty": "In der aktuellen Auswahl gibt es keine E-Mail-Adressen.", + "composeEmail": "E-Mail vorbereiten", + "copyContactSummary": "Kontaktübersicht kopieren", + "copyContactSummarySuccess": "Kontaktübersicht in die Zwischenablage kopiert." }, "diary": { "title": "Trainingstagebuch", diff --git a/frontend/src/i18n/locales/en-AU.json b/frontend/src/i18n/locales/en-AU.json index 7a3eaada..5e3f36ed 100644 --- a/frontend/src/i18n/locales/en-AU.json +++ b/frontend/src/i18n/locales/en-AU.json @@ -357,5 +357,98 @@ "stageFlowReadinessReady": "Transition is ready to start", "stageFlowQualifiedPreviewTitle": "Currently qualified", "stageFlowQualifiedPreviewEntry": "G{group} · Place {position} · {name}" + }, + "members": { + "subtitle": "Search, filter and edit members directly.", + "closeEditor": "Close editor", + "visibleMembers": "Visible members", + "search": "Search", + "searchPlaceholder": "Search by name, city, phone or email", + "memberScope": "Member scope", + "scopeAll": "All", + "scopeActive": "Active", + "scopeTest": "Trial", + "scopeNeedsForm": "Form unverified", + "scopeInactive": "Inactive", + "resultsVisible": "members visible", + "editHint": "Click a row to open the editor.", + "editorCreateHint": "Create a new member and capture contact details directly.", + "editorEditHint": "Edit the details for {name}.", + "transferSuccessTitle": "Transfer successful", + "transferErrorTitle": "Transfer error", + "clickTtRequestPending": "Click-TT request in progress", + "clickTtRequestAction": "Request click-TT eligibility", + "clickTtRequestTitle": "Start Click-TT request", + "clickTtRequestConfirm": "Start the automated Click-TT request for {name}?", + "clickTtRequestHint": "The request is processed automatically by the backend Click-TT workflow.", + "clickTtRequestSuccess": "Please sign in to click-tt and submit the request there.", + "clickTtRequestError": "The Click-TT request could not be submitted.", + "clickTtRequestFailedLog": "Click-TT request failed", + "deleteImageTitle": "Delete image", + "deleteImageConfirm": "Do you really want to delete this image?", + "parentFallback": "Parent", + "loadingMembers": "Loading members...", + "errorLoadingMembers": "Failed to load the member list.", + "scopeNotTraining": "No longer training", + "notInTrainingTooltip": "No participation for {weeks} training weeks", + "status": "Status", + "contact": "Contact", + "noPhoneShort": "No phone", + "noEmailShort": "No email", + "noAddressShort": "No address", + "clickTtSubmitted": "Click-TT submitted", + "markRegular": "Mark regular", + "markFormReceived": "Mark form verified", + "clickTtRequestShort": "Click-TT", + "clickTtRequestPendingShort": "Pending ...", + "memberDetails": "Member details", + "previewLastTraining": "Last training", + "previewNoLastTraining": "No participation yet", + "phoneListForSelection": "Phone list for selection", + "markFormsForSelection": "Verify forms for selection", + "markRegularForSelection": "Mark selection regular", + "phoneListSelectionFile": "phone-list-selection.pdf", + "batchFormsMarkedSuccess": "Marked {count} form(s) as verified.", + "batchFormsMarkedEmpty": "There are no unverified forms in the current selection.", + "batchMarkedRegularSuccess": "Marked {count} trial member(s) as regular.", + "batchMarkedRegularEmpty": "There are no trial members in the current selection.", + "batchPartialFailure": "{success} succeeded, {failed} failed.", + "sortBy": "Sort by", + "sortLastName": "Last name", + "sortFirstName": "First name", + "sortBirthday": "Birthday", + "sortAge": "Age", + "age": "Age", + "openTasks": "Open tasks", + "noOpenTasks": "No open tasks", + "taskVerifyForm": "Verify form", + "taskReviewTrialStatus": "Review trial status", + "taskCheckTrainingStatus": "Review training status", + "taskCheckClickTt": "Review Click-TT eligibility", + "taskActionVerify": "Verify", + "taskActionMarkRegular": "Mark regular", + "taskActionRequest": "Request", + "toggleSortDirection": "Toggle sort direction", + "sortLastTraining": "Last training", + "sortOpenTasks": "Open tasks", + "exportPreview": "Export preview", + "exportMembersSelected": "members currently selected", + "exportPhones": "Phone", + "exportReachableByPhone": "with phone number", + "exportEmails": "Email", + "exportReachableByEmail": "with email address", + "exportPreviewNames": "Preview", + "exportPreviewEmpty": "No members in the current selection", + "exportCsv": "Export CSV", + "exportCsvFile": "member-selection.csv", + "copyPhones": "Copy phones", + "copyEmails": "Copy emails", + "copyPhonesSuccess": "Phone list copied to clipboard.", + "copyPhonesEmpty": "There are no phone numbers in the current selection.", + "copyEmailsSuccess": "Email list copied to clipboard.", + "copyEmailsEmpty": "There are no email addresses in the current selection.", + "composeEmail": "Compose email", + "copyContactSummary": "Copy contact summary", + "copyContactSummarySuccess": "Contact summary copied to clipboard." } } diff --git a/frontend/src/i18n/locales/en-GB.json b/frontend/src/i18n/locales/en-GB.json index 782baa0a..c6cc908f 100644 --- a/frontend/src/i18n/locales/en-GB.json +++ b/frontend/src/i18n/locales/en-GB.json @@ -363,5 +363,108 @@ "statusActionCreate": "Create", "statusActionGenerate": "Generate", "statusActionStart": "Start" + }, + "members": { + "subtitle": "Search, filter and edit members directly.", + "closeEditor": "Close editor", + "visibleMembers": "Visible members", + "search": "Search", + "searchPlaceholder": "Search by name, city, phone or email", + "memberScope": "Member scope", + "scopeAll": "All", + "scopeActive": "Active", + "scopeTest": "Trial", + "scopeNeedsForm": "Form unverified", + "scopeDataIncomplete": "Data incomplete", + "scopeInactive": "Inactive", + "resultsVisible": "members visible", + "editHint": "Click a row to open the editor.", + "editorCreateHint": "Create a new member and capture contact details directly.", + "editorEditHint": "Edit the details for {name}.", + "transferSuccessTitle": "Transfer successful", + "transferErrorTitle": "Transfer error", + "clickTtRequestPending": "Click-TT request in progress", + "clickTtRequestAction": "Request click-TT eligibility", + "clickTtRequestTitle": "Start Click-TT request", + "clickTtRequestConfirm": "Start the automated Click-TT request for {name}?", + "clickTtRequestHint": "The request is processed automatically by the backend Click-TT workflow.", + "clickTtRequestSuccess": "Please sign in to click-tt and submit the request there.", + "clickTtRequestError": "The Click-TT request could not be submitted.", + "clickTtRequestFailedLog": "Click-TT request failed", + "deleteImageTitle": "Delete image", + "deleteImageConfirm": "Do you really want to delete this image?", + "parentFallback": "Parent", + "loadingMembers": "Loading members...", + "errorLoadingMembers": "Failed to load the member list.", + "scopeNotTraining": "No longer training", + "notInTrainingTooltip": "No participation for {weeks} training weeks", + "status": "Status", + "contact": "Contact", + "noPhoneShort": "No phone", + "noEmailShort": "No email", + "noAddressShort": "No address", + "clickTtSubmitted": "Click-TT submitted", + "markRegular": "Mark regular", + "markFormReceived": "Mark form verified", + "clickTtRequestShort": "Click-TT", + "clickTtRequestPendingShort": "Pending ...", + "memberDetails": "Member details", + "previewLastTraining": "Last training", + "previewNoLastTraining": "No participation yet", + "phoneListForSelection": "Phone list for selection", + "markFormsForSelection": "Verify forms for selection", + "markRegularForSelection": "Mark selection regular", + "phoneListSelectionFile": "phone-list-selection.pdf", + "batchFormsMarkedSuccess": "Marked {count} form(s) as verified.", + "batchFormsMarkedEmpty": "There are no unverified forms in the current selection.", + "batchMarkedRegularSuccess": "Marked {count} trial member(s) as regular.", + "batchMarkedRegularEmpty": "There are no trial members in the current selection.", + "batchPartialFailure": "{success} succeeded, {failed} failed.", + "sortBy": "Sort by", + "sortLastName": "Last name", + "sortFirstName": "First name", + "sortBirthday": "Birthday", + "sortAge": "Age", + "age": "Age", + "dataQuality": "Data quality", + "dataQualityComplete": "Data complete", + "dataIssueBirthdate": "Birthdate missing", + "dataIssuePhone": "Phone missing", + "dataIssueEmail": "Email missing", + "dataIssueAddress": "Address missing", + "dataIssueGender": "Gender unclear", + "openTasks": "Open tasks", + "noOpenTasks": "No open tasks", + "taskVerifyForm": "Verify form", + "taskReviewTrialStatus": "Review trial status", + "taskCheckTrainingStatus": "Review training status", + "taskCheckDataQuality": "Review data quality", + "taskCheckClickTt": "Review Click-TT eligibility", + "taskActionVerify": "Verify", + "taskActionMarkRegular": "Mark regular", + "taskActionReview": "Open", + "taskActionRequest": "Request", + "toggleSortDirection": "Toggle sort direction", + "sortLastTraining": "Last training", + "sortOpenTasks": "Open tasks", + "exportPreview": "Export preview", + "exportMembersSelected": "members currently selected", + "exportPhones": "Phone", + "exportReachableByPhone": "with phone number", + "exportEmails": "Email", + "exportReachableByEmail": "with email address", + "exportPreviewNames": "Preview", + "exportPreviewEmpty": "No members in the current selection", + "exportCsv": "Export CSV", + "exportCsvFile": "member-selection.csv", + "copyPhones": "Copy phones", + "copyEmails": "Copy emails", + "copyPhonesSuccess": "Phone list copied to clipboard.", + "copyPhonesEmpty": "There are no phone numbers in the current selection.", + "copyEmailsSuccess": "Email list copied to clipboard.", + "copyEmailsEmpty": "There are no email addresses in the current selection.", + "composeEmail": "Compose email", + "copyContactSummary": "Copy contact summary", + "copyContactSummarySuccess": "Contact summary copied to clipboard." } } diff --git a/frontend/src/i18n/locales/en-US.json b/frontend/src/i18n/locales/en-US.json index 878748fe..a2c48d3e 100644 --- a/frontend/src/i18n/locales/en-US.json +++ b/frontend/src/i18n/locales/en-US.json @@ -357,5 +357,98 @@ "stageFlowReadinessReady": "Transition is ready to start", "stageFlowQualifiedPreviewTitle": "Currently qualified", "stageFlowQualifiedPreviewEntry": "G{group} · Place {position} · {name}" + }, + "members": { + "subtitle": "Search, filter and edit members directly.", + "closeEditor": "Close editor", + "visibleMembers": "Visible members", + "search": "Search", + "searchPlaceholder": "Search by name, city, phone or email", + "memberScope": "Member scope", + "scopeAll": "All", + "scopeActive": "Active", + "scopeTest": "Trial", + "scopeNeedsForm": "Form unverified", + "scopeInactive": "Inactive", + "resultsVisible": "members visible", + "editHint": "Click a row to open the editor.", + "editorCreateHint": "Create a new member and capture contact details directly.", + "editorEditHint": "Edit the details for {name}.", + "transferSuccessTitle": "Transfer successful", + "transferErrorTitle": "Transfer error", + "clickTtRequestPending": "Click-TT request in progress", + "clickTtRequestAction": "Request click-TT eligibility", + "clickTtRequestTitle": "Start Click-TT request", + "clickTtRequestConfirm": "Start the automated Click-TT request for {name}?", + "clickTtRequestHint": "The request is processed automatically by the backend Click-TT workflow.", + "clickTtRequestSuccess": "Please sign in to click-tt and submit the request there.", + "clickTtRequestError": "The Click-TT request could not be submitted.", + "clickTtRequestFailedLog": "Click-TT request failed", + "deleteImageTitle": "Delete image", + "deleteImageConfirm": "Do you really want to delete this image?", + "parentFallback": "Parent", + "loadingMembers": "Loading members...", + "errorLoadingMembers": "Failed to load the member list.", + "scopeNotTraining": "No longer training", + "notInTrainingTooltip": "No participation for {weeks} training weeks", + "status": "Status", + "contact": "Contact", + "noPhoneShort": "No phone", + "noEmailShort": "No email", + "noAddressShort": "No address", + "clickTtSubmitted": "Click-TT submitted", + "markRegular": "Mark regular", + "markFormReceived": "Mark form verified", + "clickTtRequestShort": "Click-TT", + "clickTtRequestPendingShort": "Pending ...", + "memberDetails": "Member details", + "previewLastTraining": "Last training", + "previewNoLastTraining": "No participation yet", + "phoneListForSelection": "Phone list for selection", + "markFormsForSelection": "Verify forms for selection", + "markRegularForSelection": "Mark selection regular", + "phoneListSelectionFile": "phone-list-selection.pdf", + "batchFormsMarkedSuccess": "Marked {count} form(s) as verified.", + "batchFormsMarkedEmpty": "There are no unverified forms in the current selection.", + "batchMarkedRegularSuccess": "Marked {count} trial member(s) as regular.", + "batchMarkedRegularEmpty": "There are no trial members in the current selection.", + "batchPartialFailure": "{success} succeeded, {failed} failed.", + "sortBy": "Sort by", + "sortLastName": "Last name", + "sortFirstName": "First name", + "sortBirthday": "Birthday", + "sortAge": "Age", + "age": "Age", + "openTasks": "Open tasks", + "noOpenTasks": "No open tasks", + "taskVerifyForm": "Verify form", + "taskReviewTrialStatus": "Review trial status", + "taskCheckTrainingStatus": "Review training status", + "taskCheckClickTt": "Review Click-TT eligibility", + "taskActionVerify": "Verify", + "taskActionMarkRegular": "Mark regular", + "taskActionRequest": "Request", + "toggleSortDirection": "Toggle sort direction", + "sortLastTraining": "Last training", + "sortOpenTasks": "Open tasks", + "exportPreview": "Export preview", + "exportMembersSelected": "members currently selected", + "exportPhones": "Phone", + "exportReachableByPhone": "with phone number", + "exportEmails": "Email", + "exportReachableByEmail": "with email address", + "exportPreviewNames": "Preview", + "exportPreviewEmpty": "No members in the current selection", + "exportCsv": "Export CSV", + "exportCsvFile": "member-selection.csv", + "copyPhones": "Copy phones", + "copyEmails": "Copy emails", + "copyPhonesSuccess": "Phone list copied to clipboard.", + "copyPhonesEmpty": "There are no phone numbers in the current selection.", + "copyEmailsSuccess": "Email list copied to clipboard.", + "copyEmailsEmpty": "There are no email addresses in the current selection.", + "composeEmail": "Compose email", + "copyContactSummary": "Copy contact summary", + "copyContactSummarySuccess": "Contact summary copied to clipboard." } } diff --git a/frontend/src/i18n/locales/es.json b/frontend/src/i18n/locales/es.json index 20377c1f..60fd8683 100644 --- a/frontend/src/i18n/locales/es.json +++ b/frontend/src/i18n/locales/es.json @@ -329,5 +329,98 @@ "stageFlowReadinessReady": "Transition is ready to start", "stageFlowQualifiedPreviewTitle": "Currently qualified", "stageFlowQualifiedPreviewEntry": "G{group} · Place {position} · {name}" + }, + "members": { + "subtitle": "Search, filter and edit members directly.", + "closeEditor": "Close editor", + "visibleMembers": "Visible members", + "search": "Search", + "searchPlaceholder": "Search by name, city, phone or email", + "memberScope": "Member scope", + "scopeAll": "All", + "scopeActive": "Active", + "scopeTest": "Trial", + "scopeNeedsForm": "Form unverified", + "scopeInactive": "Inactive", + "resultsVisible": "members visible", + "editHint": "Click a row to open the editor.", + "editorCreateHint": "Create a new member and capture contact details directly.", + "editorEditHint": "Edit the details for {name}.", + "transferSuccessTitle": "Transfer successful", + "transferErrorTitle": "Transfer error", + "clickTtRequestPending": "Click-TT request in progress", + "clickTtRequestAction": "Request click-TT eligibility", + "clickTtRequestTitle": "Start Click-TT request", + "clickTtRequestConfirm": "Start the automated Click-TT request for {name}?", + "clickTtRequestHint": "The request is processed automatically by the backend Click-TT workflow.", + "clickTtRequestSuccess": "Please sign in to click-tt and submit the request there.", + "clickTtRequestError": "The Click-TT request could not be submitted.", + "clickTtRequestFailedLog": "Click-TT request failed", + "deleteImageTitle": "Delete image", + "deleteImageConfirm": "Do you really want to delete this image?", + "parentFallback": "Parent", + "loadingMembers": "Loading members...", + "errorLoadingMembers": "Failed to load the member list.", + "scopeNotTraining": "No longer training", + "notInTrainingTooltip": "No participation for {weeks} training weeks", + "status": "Status", + "contact": "Contact", + "noPhoneShort": "No phone", + "noEmailShort": "No email", + "noAddressShort": "No address", + "clickTtSubmitted": "Click-TT submitted", + "markRegular": "Mark regular", + "markFormReceived": "Mark form verified", + "clickTtRequestShort": "Click-TT", + "clickTtRequestPendingShort": "Pending ...", + "memberDetails": "Member details", + "previewLastTraining": "Last training", + "previewNoLastTraining": "No participation yet", + "phoneListForSelection": "Phone list for selection", + "markFormsForSelection": "Verify forms for selection", + "markRegularForSelection": "Mark selection regular", + "phoneListSelectionFile": "phone-list-selection.pdf", + "batchFormsMarkedSuccess": "Marked {count} form(s) as verified.", + "batchFormsMarkedEmpty": "There are no unverified forms in the current selection.", + "batchMarkedRegularSuccess": "Marked {count} trial member(s) as regular.", + "batchMarkedRegularEmpty": "There are no trial members in the current selection.", + "batchPartialFailure": "{success} succeeded, {failed} failed.", + "sortBy": "Sort by", + "sortLastName": "Last name", + "sortFirstName": "First name", + "sortBirthday": "Birthday", + "sortAge": "Age", + "age": "Age", + "openTasks": "Open tasks", + "noOpenTasks": "No open tasks", + "taskVerifyForm": "Verify form", + "taskReviewTrialStatus": "Review trial status", + "taskCheckTrainingStatus": "Review training status", + "taskCheckClickTt": "Review Click-TT eligibility", + "taskActionVerify": "Verify", + "taskActionMarkRegular": "Mark regular", + "taskActionRequest": "Request", + "toggleSortDirection": "Toggle sort direction", + "sortLastTraining": "Last training", + "sortOpenTasks": "Open tasks", + "exportPreview": "Export preview", + "exportMembersSelected": "members currently selected", + "exportPhones": "Phone", + "exportReachableByPhone": "with phone number", + "exportEmails": "Email", + "exportReachableByEmail": "with email address", + "exportPreviewNames": "Preview", + "exportPreviewEmpty": "No members in the current selection", + "exportCsv": "Export CSV", + "exportCsvFile": "member-selection.csv", + "copyPhones": "Copy phones", + "copyEmails": "Copy emails", + "copyPhonesSuccess": "Phone list copied to clipboard.", + "copyPhonesEmpty": "There are no phone numbers in the current selection.", + "copyEmailsSuccess": "Email list copied to clipboard.", + "copyEmailsEmpty": "There are no email addresses in the current selection.", + "composeEmail": "Compose email", + "copyContactSummary": "Copy contact summary", + "copyContactSummarySuccess": "Contact summary copied to clipboard." } } diff --git a/frontend/src/i18n/locales/fil.json b/frontend/src/i18n/locales/fil.json index f1f0a083..e6bf5dc6 100644 --- a/frontend/src/i18n/locales/fil.json +++ b/frontend/src/i18n/locales/fil.json @@ -329,5 +329,98 @@ "stageFlowReadinessReady": "Transition is ready to start", "stageFlowQualifiedPreviewTitle": "Currently qualified", "stageFlowQualifiedPreviewEntry": "G{group} · Place {position} · {name}" + }, + "members": { + "subtitle": "Search, filter and edit members directly.", + "closeEditor": "Close editor", + "visibleMembers": "Visible members", + "search": "Search", + "searchPlaceholder": "Search by name, city, phone or email", + "memberScope": "Member scope", + "scopeAll": "All", + "scopeActive": "Active", + "scopeTest": "Trial", + "scopeNeedsForm": "Form unverified", + "scopeInactive": "Inactive", + "resultsVisible": "members visible", + "editHint": "Click a row to open the editor.", + "editorCreateHint": "Create a new member and capture contact details directly.", + "editorEditHint": "Edit the details for {name}.", + "transferSuccessTitle": "Transfer successful", + "transferErrorTitle": "Transfer error", + "clickTtRequestPending": "Click-TT request in progress", + "clickTtRequestAction": "Request click-TT eligibility", + "clickTtRequestTitle": "Start Click-TT request", + "clickTtRequestConfirm": "Start the automated Click-TT request for {name}?", + "clickTtRequestHint": "The request is processed automatically by the backend Click-TT workflow.", + "clickTtRequestSuccess": "Please sign in to click-tt and submit the request there.", + "clickTtRequestError": "The Click-TT request could not be submitted.", + "clickTtRequestFailedLog": "Click-TT request failed", + "deleteImageTitle": "Delete image", + "deleteImageConfirm": "Do you really want to delete this image?", + "parentFallback": "Parent", + "loadingMembers": "Loading members...", + "errorLoadingMembers": "Failed to load the member list.", + "scopeNotTraining": "No longer training", + "notInTrainingTooltip": "No participation for {weeks} training weeks", + "status": "Status", + "contact": "Contact", + "noPhoneShort": "No phone", + "noEmailShort": "No email", + "noAddressShort": "No address", + "clickTtSubmitted": "Click-TT submitted", + "markRegular": "Mark regular", + "markFormReceived": "Mark form verified", + "clickTtRequestShort": "Click-TT", + "clickTtRequestPendingShort": "Pending ...", + "memberDetails": "Member details", + "previewLastTraining": "Last training", + "previewNoLastTraining": "No participation yet", + "phoneListForSelection": "Phone list for selection", + "markFormsForSelection": "Verify forms for selection", + "markRegularForSelection": "Mark selection regular", + "phoneListSelectionFile": "phone-list-selection.pdf", + "batchFormsMarkedSuccess": "Marked {count} form(s) as verified.", + "batchFormsMarkedEmpty": "There are no unverified forms in the current selection.", + "batchMarkedRegularSuccess": "Marked {count} trial member(s) as regular.", + "batchMarkedRegularEmpty": "There are no trial members in the current selection.", + "batchPartialFailure": "{success} succeeded, {failed} failed.", + "sortBy": "Sort by", + "sortLastName": "Last name", + "sortFirstName": "First name", + "sortBirthday": "Birthday", + "sortAge": "Age", + "age": "Age", + "openTasks": "Open tasks", + "noOpenTasks": "No open tasks", + "taskVerifyForm": "Verify form", + "taskReviewTrialStatus": "Review trial status", + "taskCheckTrainingStatus": "Review training status", + "taskCheckClickTt": "Review Click-TT eligibility", + "taskActionVerify": "Verify", + "taskActionMarkRegular": "Mark regular", + "taskActionRequest": "Request", + "toggleSortDirection": "Toggle sort direction", + "sortLastTraining": "Last training", + "sortOpenTasks": "Open tasks", + "exportPreview": "Export preview", + "exportMembersSelected": "members currently selected", + "exportPhones": "Phone", + "exportReachableByPhone": "with phone number", + "exportEmails": "Email", + "exportReachableByEmail": "with email address", + "exportPreviewNames": "Preview", + "exportPreviewEmpty": "No members in the current selection", + "exportCsv": "Export CSV", + "exportCsvFile": "member-selection.csv", + "copyPhones": "Copy phones", + "copyEmails": "Copy emails", + "copyPhonesSuccess": "Phone list copied to clipboard.", + "copyPhonesEmpty": "There are no phone numbers in the current selection.", + "copyEmailsSuccess": "Email list copied to clipboard.", + "copyEmailsEmpty": "There are no email addresses in the current selection.", + "composeEmail": "Compose email", + "copyContactSummary": "Copy contact summary", + "copyContactSummarySuccess": "Contact summary copied to clipboard." } } diff --git a/frontend/src/i18n/locales/fr.json b/frontend/src/i18n/locales/fr.json index 1260c36d..02752059 100644 --- a/frontend/src/i18n/locales/fr.json +++ b/frontend/src/i18n/locales/fr.json @@ -329,5 +329,98 @@ "stageFlowReadinessReady": "Transition is ready to start", "stageFlowQualifiedPreviewTitle": "Currently qualified", "stageFlowQualifiedPreviewEntry": "G{group} · Place {position} · {name}" + }, + "members": { + "subtitle": "Search, filter and edit members directly.", + "closeEditor": "Close editor", + "visibleMembers": "Visible members", + "search": "Search", + "searchPlaceholder": "Search by name, city, phone or email", + "memberScope": "Member scope", + "scopeAll": "All", + "scopeActive": "Active", + "scopeTest": "Trial", + "scopeNeedsForm": "Form unverified", + "scopeInactive": "Inactive", + "resultsVisible": "members visible", + "editHint": "Click a row to open the editor.", + "editorCreateHint": "Create a new member and capture contact details directly.", + "editorEditHint": "Edit the details for {name}.", + "transferSuccessTitle": "Transfer successful", + "transferErrorTitle": "Transfer error", + "clickTtRequestPending": "Click-TT request in progress", + "clickTtRequestAction": "Request click-TT eligibility", + "clickTtRequestTitle": "Start Click-TT request", + "clickTtRequestConfirm": "Start the automated Click-TT request for {name}?", + "clickTtRequestHint": "The request is processed automatically by the backend Click-TT workflow.", + "clickTtRequestSuccess": "Please sign in to click-tt and submit the request there.", + "clickTtRequestError": "The Click-TT request could not be submitted.", + "clickTtRequestFailedLog": "Click-TT request failed", + "deleteImageTitle": "Delete image", + "deleteImageConfirm": "Do you really want to delete this image?", + "parentFallback": "Parent", + "loadingMembers": "Loading members...", + "errorLoadingMembers": "Failed to load the member list.", + "scopeNotTraining": "No longer training", + "notInTrainingTooltip": "No participation for {weeks} training weeks", + "status": "Status", + "contact": "Contact", + "noPhoneShort": "No phone", + "noEmailShort": "No email", + "noAddressShort": "No address", + "clickTtSubmitted": "Click-TT submitted", + "markRegular": "Mark regular", + "markFormReceived": "Mark form verified", + "clickTtRequestShort": "Click-TT", + "clickTtRequestPendingShort": "Pending ...", + "memberDetails": "Member details", + "previewLastTraining": "Last training", + "previewNoLastTraining": "No participation yet", + "phoneListForSelection": "Phone list for selection", + "markFormsForSelection": "Verify forms for selection", + "markRegularForSelection": "Mark selection regular", + "phoneListSelectionFile": "phone-list-selection.pdf", + "batchFormsMarkedSuccess": "Marked {count} form(s) as verified.", + "batchFormsMarkedEmpty": "There are no unverified forms in the current selection.", + "batchMarkedRegularSuccess": "Marked {count} trial member(s) as regular.", + "batchMarkedRegularEmpty": "There are no trial members in the current selection.", + "batchPartialFailure": "{success} succeeded, {failed} failed.", + "sortBy": "Sort by", + "sortLastName": "Last name", + "sortFirstName": "First name", + "sortBirthday": "Birthday", + "sortAge": "Age", + "age": "Age", + "openTasks": "Open tasks", + "noOpenTasks": "No open tasks", + "taskVerifyForm": "Verify form", + "taskReviewTrialStatus": "Review trial status", + "taskCheckTrainingStatus": "Review training status", + "taskCheckClickTt": "Review Click-TT eligibility", + "taskActionVerify": "Verify", + "taskActionMarkRegular": "Mark regular", + "taskActionRequest": "Request", + "toggleSortDirection": "Toggle sort direction", + "sortLastTraining": "Last training", + "sortOpenTasks": "Open tasks", + "exportPreview": "Export preview", + "exportMembersSelected": "members currently selected", + "exportPhones": "Phone", + "exportReachableByPhone": "with phone number", + "exportEmails": "Email", + "exportReachableByEmail": "with email address", + "exportPreviewNames": "Preview", + "exportPreviewEmpty": "No members in the current selection", + "exportCsv": "Export CSV", + "exportCsvFile": "member-selection.csv", + "copyPhones": "Copy phones", + "copyEmails": "Copy emails", + "copyPhonesSuccess": "Phone list copied to clipboard.", + "copyPhonesEmpty": "There are no phone numbers in the current selection.", + "copyEmailsSuccess": "Email list copied to clipboard.", + "copyEmailsEmpty": "There are no email addresses in the current selection.", + "composeEmail": "Compose email", + "copyContactSummary": "Copy contact summary", + "copyContactSummarySuccess": "Contact summary copied to clipboard." } } diff --git a/frontend/src/i18n/locales/it.json b/frontend/src/i18n/locales/it.json index 0d62ac4c..f96b36e8 100644 --- a/frontend/src/i18n/locales/it.json +++ b/frontend/src/i18n/locales/it.json @@ -329,5 +329,98 @@ "stageFlowReadinessReady": "Transition is ready to start", "stageFlowQualifiedPreviewTitle": "Currently qualified", "stageFlowQualifiedPreviewEntry": "G{group} · Place {position} · {name}" + }, + "members": { + "subtitle": "Search, filter and edit members directly.", + "closeEditor": "Close editor", + "visibleMembers": "Visible members", + "search": "Search", + "searchPlaceholder": "Search by name, city, phone or email", + "memberScope": "Member scope", + "scopeAll": "All", + "scopeActive": "Active", + "scopeTest": "Trial", + "scopeNeedsForm": "Form unverified", + "scopeInactive": "Inactive", + "resultsVisible": "members visible", + "editHint": "Click a row to open the editor.", + "editorCreateHint": "Create a new member and capture contact details directly.", + "editorEditHint": "Edit the details for {name}.", + "transferSuccessTitle": "Transfer successful", + "transferErrorTitle": "Transfer error", + "clickTtRequestPending": "Click-TT request in progress", + "clickTtRequestAction": "Request click-TT eligibility", + "clickTtRequestTitle": "Start Click-TT request", + "clickTtRequestConfirm": "Start the automated Click-TT request for {name}?", + "clickTtRequestHint": "The request is processed automatically by the backend Click-TT workflow.", + "clickTtRequestSuccess": "Please sign in to click-tt and submit the request there.", + "clickTtRequestError": "The Click-TT request could not be submitted.", + "clickTtRequestFailedLog": "Click-TT request failed", + "deleteImageTitle": "Delete image", + "deleteImageConfirm": "Do you really want to delete this image?", + "parentFallback": "Parent", + "loadingMembers": "Loading members...", + "errorLoadingMembers": "Failed to load the member list.", + "scopeNotTraining": "No longer training", + "notInTrainingTooltip": "No participation for {weeks} training weeks", + "status": "Status", + "contact": "Contact", + "noPhoneShort": "No phone", + "noEmailShort": "No email", + "noAddressShort": "No address", + "clickTtSubmitted": "Click-TT submitted", + "markRegular": "Mark regular", + "markFormReceived": "Mark form verified", + "clickTtRequestShort": "Click-TT", + "clickTtRequestPendingShort": "Pending ...", + "memberDetails": "Member details", + "previewLastTraining": "Last training", + "previewNoLastTraining": "No participation yet", + "phoneListForSelection": "Phone list for selection", + "markFormsForSelection": "Verify forms for selection", + "markRegularForSelection": "Mark selection regular", + "phoneListSelectionFile": "phone-list-selection.pdf", + "batchFormsMarkedSuccess": "Marked {count} form(s) as verified.", + "batchFormsMarkedEmpty": "There are no unverified forms in the current selection.", + "batchMarkedRegularSuccess": "Marked {count} trial member(s) as regular.", + "batchMarkedRegularEmpty": "There are no trial members in the current selection.", + "batchPartialFailure": "{success} succeeded, {failed} failed.", + "sortBy": "Sort by", + "sortLastName": "Last name", + "sortFirstName": "First name", + "sortBirthday": "Birthday", + "sortAge": "Age", + "age": "Age", + "openTasks": "Open tasks", + "noOpenTasks": "No open tasks", + "taskVerifyForm": "Verify form", + "taskReviewTrialStatus": "Review trial status", + "taskCheckTrainingStatus": "Review training status", + "taskCheckClickTt": "Review Click-TT eligibility", + "taskActionVerify": "Verify", + "taskActionMarkRegular": "Mark regular", + "taskActionRequest": "Request", + "toggleSortDirection": "Toggle sort direction", + "sortLastTraining": "Last training", + "sortOpenTasks": "Open tasks", + "exportPreview": "Export preview", + "exportMembersSelected": "members currently selected", + "exportPhones": "Phone", + "exportReachableByPhone": "with phone number", + "exportEmails": "Email", + "exportReachableByEmail": "with email address", + "exportPreviewNames": "Preview", + "exportPreviewEmpty": "No members in the current selection", + "exportCsv": "Export CSV", + "exportCsvFile": "member-selection.csv", + "copyPhones": "Copy phones", + "copyEmails": "Copy emails", + "copyPhonesSuccess": "Phone list copied to clipboard.", + "copyPhonesEmpty": "There are no phone numbers in the current selection.", + "copyEmailsSuccess": "Email list copied to clipboard.", + "copyEmailsEmpty": "There are no email addresses in the current selection.", + "composeEmail": "Compose email", + "copyContactSummary": "Copy contact summary", + "copyContactSummarySuccess": "Contact summary copied to clipboard." } } diff --git a/frontend/src/i18n/locales/ja.json b/frontend/src/i18n/locales/ja.json index 6a1bb5dc..6d545456 100644 --- a/frontend/src/i18n/locales/ja.json +++ b/frontend/src/i18n/locales/ja.json @@ -329,5 +329,98 @@ "stageFlowReadinessReady": "Transition is ready to start", "stageFlowQualifiedPreviewTitle": "Currently qualified", "stageFlowQualifiedPreviewEntry": "G{group} · Place {position} · {name}" + }, + "members": { + "subtitle": "Search, filter and edit members directly.", + "closeEditor": "Close editor", + "visibleMembers": "Visible members", + "search": "Search", + "searchPlaceholder": "Search by name, city, phone or email", + "memberScope": "Member scope", + "scopeAll": "All", + "scopeActive": "Active", + "scopeTest": "Trial", + "scopeNeedsForm": "Form unverified", + "scopeInactive": "Inactive", + "resultsVisible": "members visible", + "editHint": "Click a row to open the editor.", + "editorCreateHint": "Create a new member and capture contact details directly.", + "editorEditHint": "Edit the details for {name}.", + "transferSuccessTitle": "Transfer successful", + "transferErrorTitle": "Transfer error", + "clickTtRequestPending": "Click-TT request in progress", + "clickTtRequestAction": "Request click-TT eligibility", + "clickTtRequestTitle": "Start Click-TT request", + "clickTtRequestConfirm": "Start the automated Click-TT request for {name}?", + "clickTtRequestHint": "The request is processed automatically by the backend Click-TT workflow.", + "clickTtRequestSuccess": "Please sign in to click-tt and submit the request there.", + "clickTtRequestError": "The Click-TT request could not be submitted.", + "clickTtRequestFailedLog": "Click-TT request failed", + "deleteImageTitle": "Delete image", + "deleteImageConfirm": "Do you really want to delete this image?", + "parentFallback": "Parent", + "loadingMembers": "Loading members...", + "errorLoadingMembers": "Failed to load the member list.", + "scopeNotTraining": "No longer training", + "notInTrainingTooltip": "No participation for {weeks} training weeks", + "status": "Status", + "contact": "Contact", + "noPhoneShort": "No phone", + "noEmailShort": "No email", + "noAddressShort": "No address", + "clickTtSubmitted": "Click-TT submitted", + "markRegular": "Mark regular", + "markFormReceived": "Mark form verified", + "clickTtRequestShort": "Click-TT", + "clickTtRequestPendingShort": "Pending ...", + "memberDetails": "Member details", + "previewLastTraining": "Last training", + "previewNoLastTraining": "No participation yet", + "phoneListForSelection": "Phone list for selection", + "markFormsForSelection": "Verify forms for selection", + "markRegularForSelection": "Mark selection regular", + "phoneListSelectionFile": "phone-list-selection.pdf", + "batchFormsMarkedSuccess": "Marked {count} form(s) as verified.", + "batchFormsMarkedEmpty": "There are no unverified forms in the current selection.", + "batchMarkedRegularSuccess": "Marked {count} trial member(s) as regular.", + "batchMarkedRegularEmpty": "There are no trial members in the current selection.", + "batchPartialFailure": "{success} succeeded, {failed} failed.", + "sortBy": "Sort by", + "sortLastName": "Last name", + "sortFirstName": "First name", + "sortBirthday": "Birthday", + "sortAge": "Age", + "age": "Age", + "openTasks": "Open tasks", + "noOpenTasks": "No open tasks", + "taskVerifyForm": "Verify form", + "taskReviewTrialStatus": "Review trial status", + "taskCheckTrainingStatus": "Review training status", + "taskCheckClickTt": "Review Click-TT eligibility", + "taskActionVerify": "Verify", + "taskActionMarkRegular": "Mark regular", + "taskActionRequest": "Request", + "toggleSortDirection": "Toggle sort direction", + "sortLastTraining": "Last training", + "sortOpenTasks": "Open tasks", + "exportPreview": "Export preview", + "exportMembersSelected": "members currently selected", + "exportPhones": "Phone", + "exportReachableByPhone": "with phone number", + "exportEmails": "Email", + "exportReachableByEmail": "with email address", + "exportPreviewNames": "Preview", + "exportPreviewEmpty": "No members in the current selection", + "exportCsv": "Export CSV", + "exportCsvFile": "member-selection.csv", + "copyPhones": "Copy phones", + "copyEmails": "Copy emails", + "copyPhonesSuccess": "Phone list copied to clipboard.", + "copyPhonesEmpty": "There are no phone numbers in the current selection.", + "copyEmailsSuccess": "Email list copied to clipboard.", + "copyEmailsEmpty": "There are no email addresses in the current selection.", + "composeEmail": "Compose email", + "copyContactSummary": "Copy contact summary", + "copyContactSummarySuccess": "Contact summary copied to clipboard." } } diff --git a/frontend/src/i18n/locales/pl.json b/frontend/src/i18n/locales/pl.json index 078a998f..a7011867 100644 --- a/frontend/src/i18n/locales/pl.json +++ b/frontend/src/i18n/locales/pl.json @@ -329,5 +329,98 @@ "stageFlowReadinessReady": "Transition is ready to start", "stageFlowQualifiedPreviewTitle": "Currently qualified", "stageFlowQualifiedPreviewEntry": "G{group} · Place {position} · {name}" + }, + "members": { + "subtitle": "Search, filter and edit members directly.", + "closeEditor": "Close editor", + "visibleMembers": "Visible members", + "search": "Search", + "searchPlaceholder": "Search by name, city, phone or email", + "memberScope": "Member scope", + "scopeAll": "All", + "scopeActive": "Active", + "scopeTest": "Trial", + "scopeNeedsForm": "Form unverified", + "scopeInactive": "Inactive", + "resultsVisible": "members visible", + "editHint": "Click a row to open the editor.", + "editorCreateHint": "Create a new member and capture contact details directly.", + "editorEditHint": "Edit the details for {name}.", + "transferSuccessTitle": "Transfer successful", + "transferErrorTitle": "Transfer error", + "clickTtRequestPending": "Click-TT request in progress", + "clickTtRequestAction": "Request click-TT eligibility", + "clickTtRequestTitle": "Start Click-TT request", + "clickTtRequestConfirm": "Start the automated Click-TT request for {name}?", + "clickTtRequestHint": "The request is processed automatically by the backend Click-TT workflow.", + "clickTtRequestSuccess": "Please sign in to click-tt and submit the request there.", + "clickTtRequestError": "The Click-TT request could not be submitted.", + "clickTtRequestFailedLog": "Click-TT request failed", + "deleteImageTitle": "Delete image", + "deleteImageConfirm": "Do you really want to delete this image?", + "parentFallback": "Parent", + "loadingMembers": "Loading members...", + "errorLoadingMembers": "Failed to load the member list.", + "scopeNotTraining": "No longer training", + "notInTrainingTooltip": "No participation for {weeks} training weeks", + "status": "Status", + "contact": "Contact", + "noPhoneShort": "No phone", + "noEmailShort": "No email", + "noAddressShort": "No address", + "clickTtSubmitted": "Click-TT submitted", + "markRegular": "Mark regular", + "markFormReceived": "Mark form verified", + "clickTtRequestShort": "Click-TT", + "clickTtRequestPendingShort": "Pending ...", + "memberDetails": "Member details", + "previewLastTraining": "Last training", + "previewNoLastTraining": "No participation yet", + "phoneListForSelection": "Phone list for selection", + "markFormsForSelection": "Verify forms for selection", + "markRegularForSelection": "Mark selection regular", + "phoneListSelectionFile": "phone-list-selection.pdf", + "batchFormsMarkedSuccess": "Marked {count} form(s) as verified.", + "batchFormsMarkedEmpty": "There are no unverified forms in the current selection.", + "batchMarkedRegularSuccess": "Marked {count} trial member(s) as regular.", + "batchMarkedRegularEmpty": "There are no trial members in the current selection.", + "batchPartialFailure": "{success} succeeded, {failed} failed.", + "sortBy": "Sort by", + "sortLastName": "Last name", + "sortFirstName": "First name", + "sortBirthday": "Birthday", + "sortAge": "Age", + "age": "Age", + "openTasks": "Open tasks", + "noOpenTasks": "No open tasks", + "taskVerifyForm": "Verify form", + "taskReviewTrialStatus": "Review trial status", + "taskCheckTrainingStatus": "Review training status", + "taskCheckClickTt": "Review Click-TT eligibility", + "taskActionVerify": "Verify", + "taskActionMarkRegular": "Mark regular", + "taskActionRequest": "Request", + "toggleSortDirection": "Toggle sort direction", + "sortLastTraining": "Last training", + "sortOpenTasks": "Open tasks", + "exportPreview": "Export preview", + "exportMembersSelected": "members currently selected", + "exportPhones": "Phone", + "exportReachableByPhone": "with phone number", + "exportEmails": "Email", + "exportReachableByEmail": "with email address", + "exportPreviewNames": "Preview", + "exportPreviewEmpty": "No members in the current selection", + "exportCsv": "Export CSV", + "exportCsvFile": "member-selection.csv", + "copyPhones": "Copy phones", + "copyEmails": "Copy emails", + "copyPhonesSuccess": "Phone list copied to clipboard.", + "copyPhonesEmpty": "There are no phone numbers in the current selection.", + "copyEmailsSuccess": "Email list copied to clipboard.", + "copyEmailsEmpty": "There are no email addresses in the current selection.", + "composeEmail": "Compose email", + "copyContactSummary": "Copy contact summary", + "copyContactSummarySuccess": "Contact summary copied to clipboard." } } diff --git a/frontend/src/i18n/locales/th.json b/frontend/src/i18n/locales/th.json index 1c377aad..ec2b23be 100644 --- a/frontend/src/i18n/locales/th.json +++ b/frontend/src/i18n/locales/th.json @@ -329,5 +329,98 @@ "stageFlowReadinessReady": "Transition is ready to start", "stageFlowQualifiedPreviewTitle": "Currently qualified", "stageFlowQualifiedPreviewEntry": "G{group} · Place {position} · {name}" + }, + "members": { + "subtitle": "Search, filter and edit members directly.", + "closeEditor": "Close editor", + "visibleMembers": "Visible members", + "search": "Search", + "searchPlaceholder": "Search by name, city, phone or email", + "memberScope": "Member scope", + "scopeAll": "All", + "scopeActive": "Active", + "scopeTest": "Trial", + "scopeNeedsForm": "Form unverified", + "scopeInactive": "Inactive", + "resultsVisible": "members visible", + "editHint": "Click a row to open the editor.", + "editorCreateHint": "Create a new member and capture contact details directly.", + "editorEditHint": "Edit the details for {name}.", + "transferSuccessTitle": "Transfer successful", + "transferErrorTitle": "Transfer error", + "clickTtRequestPending": "Click-TT request in progress", + "clickTtRequestAction": "Request click-TT eligibility", + "clickTtRequestTitle": "Start Click-TT request", + "clickTtRequestConfirm": "Start the automated Click-TT request for {name}?", + "clickTtRequestHint": "The request is processed automatically by the backend Click-TT workflow.", + "clickTtRequestSuccess": "Please sign in to click-tt and submit the request there.", + "clickTtRequestError": "The Click-TT request could not be submitted.", + "clickTtRequestFailedLog": "Click-TT request failed", + "deleteImageTitle": "Delete image", + "deleteImageConfirm": "Do you really want to delete this image?", + "parentFallback": "Parent", + "loadingMembers": "Loading members...", + "errorLoadingMembers": "Failed to load the member list.", + "scopeNotTraining": "No longer training", + "notInTrainingTooltip": "No participation for {weeks} training weeks", + "status": "Status", + "contact": "Contact", + "noPhoneShort": "No phone", + "noEmailShort": "No email", + "noAddressShort": "No address", + "clickTtSubmitted": "Click-TT submitted", + "markRegular": "Mark regular", + "markFormReceived": "Mark form verified", + "clickTtRequestShort": "Click-TT", + "clickTtRequestPendingShort": "Pending ...", + "memberDetails": "Member details", + "previewLastTraining": "Last training", + "previewNoLastTraining": "No participation yet", + "phoneListForSelection": "Phone list for selection", + "markFormsForSelection": "Verify forms for selection", + "markRegularForSelection": "Mark selection regular", + "phoneListSelectionFile": "phone-list-selection.pdf", + "batchFormsMarkedSuccess": "Marked {count} form(s) as verified.", + "batchFormsMarkedEmpty": "There are no unverified forms in the current selection.", + "batchMarkedRegularSuccess": "Marked {count} trial member(s) as regular.", + "batchMarkedRegularEmpty": "There are no trial members in the current selection.", + "batchPartialFailure": "{success} succeeded, {failed} failed.", + "sortBy": "Sort by", + "sortLastName": "Last name", + "sortFirstName": "First name", + "sortBirthday": "Birthday", + "sortAge": "Age", + "age": "Age", + "openTasks": "Open tasks", + "noOpenTasks": "No open tasks", + "taskVerifyForm": "Verify form", + "taskReviewTrialStatus": "Review trial status", + "taskCheckTrainingStatus": "Review training status", + "taskCheckClickTt": "Review Click-TT eligibility", + "taskActionVerify": "Verify", + "taskActionMarkRegular": "Mark regular", + "taskActionRequest": "Request", + "toggleSortDirection": "Toggle sort direction", + "sortLastTraining": "Last training", + "sortOpenTasks": "Open tasks", + "exportPreview": "Export preview", + "exportMembersSelected": "members currently selected", + "exportPhones": "Phone", + "exportReachableByPhone": "with phone number", + "exportEmails": "Email", + "exportReachableByEmail": "with email address", + "exportPreviewNames": "Preview", + "exportPreviewEmpty": "No members in the current selection", + "exportCsv": "Export CSV", + "exportCsvFile": "member-selection.csv", + "copyPhones": "Copy phones", + "copyEmails": "Copy emails", + "copyPhonesSuccess": "Phone list copied to clipboard.", + "copyPhonesEmpty": "There are no phone numbers in the current selection.", + "copyEmailsSuccess": "Email list copied to clipboard.", + "copyEmailsEmpty": "There are no email addresses in the current selection.", + "composeEmail": "Compose email", + "copyContactSummary": "Copy contact summary", + "copyContactSummarySuccess": "Contact summary copied to clipboard." } } diff --git a/frontend/src/i18n/locales/tl.json b/frontend/src/i18n/locales/tl.json index f1f0a083..e6bf5dc6 100644 --- a/frontend/src/i18n/locales/tl.json +++ b/frontend/src/i18n/locales/tl.json @@ -329,5 +329,98 @@ "stageFlowReadinessReady": "Transition is ready to start", "stageFlowQualifiedPreviewTitle": "Currently qualified", "stageFlowQualifiedPreviewEntry": "G{group} · Place {position} · {name}" + }, + "members": { + "subtitle": "Search, filter and edit members directly.", + "closeEditor": "Close editor", + "visibleMembers": "Visible members", + "search": "Search", + "searchPlaceholder": "Search by name, city, phone or email", + "memberScope": "Member scope", + "scopeAll": "All", + "scopeActive": "Active", + "scopeTest": "Trial", + "scopeNeedsForm": "Form unverified", + "scopeInactive": "Inactive", + "resultsVisible": "members visible", + "editHint": "Click a row to open the editor.", + "editorCreateHint": "Create a new member and capture contact details directly.", + "editorEditHint": "Edit the details for {name}.", + "transferSuccessTitle": "Transfer successful", + "transferErrorTitle": "Transfer error", + "clickTtRequestPending": "Click-TT request in progress", + "clickTtRequestAction": "Request click-TT eligibility", + "clickTtRequestTitle": "Start Click-TT request", + "clickTtRequestConfirm": "Start the automated Click-TT request for {name}?", + "clickTtRequestHint": "The request is processed automatically by the backend Click-TT workflow.", + "clickTtRequestSuccess": "Please sign in to click-tt and submit the request there.", + "clickTtRequestError": "The Click-TT request could not be submitted.", + "clickTtRequestFailedLog": "Click-TT request failed", + "deleteImageTitle": "Delete image", + "deleteImageConfirm": "Do you really want to delete this image?", + "parentFallback": "Parent", + "loadingMembers": "Loading members...", + "errorLoadingMembers": "Failed to load the member list.", + "scopeNotTraining": "No longer training", + "notInTrainingTooltip": "No participation for {weeks} training weeks", + "status": "Status", + "contact": "Contact", + "noPhoneShort": "No phone", + "noEmailShort": "No email", + "noAddressShort": "No address", + "clickTtSubmitted": "Click-TT submitted", + "markRegular": "Mark regular", + "markFormReceived": "Mark form verified", + "clickTtRequestShort": "Click-TT", + "clickTtRequestPendingShort": "Pending ...", + "memberDetails": "Member details", + "previewLastTraining": "Last training", + "previewNoLastTraining": "No participation yet", + "phoneListForSelection": "Phone list for selection", + "markFormsForSelection": "Verify forms for selection", + "markRegularForSelection": "Mark selection regular", + "phoneListSelectionFile": "phone-list-selection.pdf", + "batchFormsMarkedSuccess": "Marked {count} form(s) as verified.", + "batchFormsMarkedEmpty": "There are no unverified forms in the current selection.", + "batchMarkedRegularSuccess": "Marked {count} trial member(s) as regular.", + "batchMarkedRegularEmpty": "There are no trial members in the current selection.", + "batchPartialFailure": "{success} succeeded, {failed} failed.", + "sortBy": "Sort by", + "sortLastName": "Last name", + "sortFirstName": "First name", + "sortBirthday": "Birthday", + "sortAge": "Age", + "age": "Age", + "openTasks": "Open tasks", + "noOpenTasks": "No open tasks", + "taskVerifyForm": "Verify form", + "taskReviewTrialStatus": "Review trial status", + "taskCheckTrainingStatus": "Review training status", + "taskCheckClickTt": "Review Click-TT eligibility", + "taskActionVerify": "Verify", + "taskActionMarkRegular": "Mark regular", + "taskActionRequest": "Request", + "toggleSortDirection": "Toggle sort direction", + "sortLastTraining": "Last training", + "sortOpenTasks": "Open tasks", + "exportPreview": "Export preview", + "exportMembersSelected": "members currently selected", + "exportPhones": "Phone", + "exportReachableByPhone": "with phone number", + "exportEmails": "Email", + "exportReachableByEmail": "with email address", + "exportPreviewNames": "Preview", + "exportPreviewEmpty": "No members in the current selection", + "exportCsv": "Export CSV", + "exportCsvFile": "member-selection.csv", + "copyPhones": "Copy phones", + "copyEmails": "Copy emails", + "copyPhonesSuccess": "Phone list copied to clipboard.", + "copyPhonesEmpty": "There are no phone numbers in the current selection.", + "copyEmailsSuccess": "Email list copied to clipboard.", + "copyEmailsEmpty": "There are no email addresses in the current selection.", + "composeEmail": "Compose email", + "copyContactSummary": "Copy contact summary", + "copyContactSummarySuccess": "Contact summary copied to clipboard." } } diff --git a/frontend/src/i18n/locales/zh.json b/frontend/src/i18n/locales/zh.json index 1f23808d..5cabcd5a 100644 --- a/frontend/src/i18n/locales/zh.json +++ b/frontend/src/i18n/locales/zh.json @@ -329,5 +329,98 @@ "stageFlowReadinessReady": "Transition is ready to start", "stageFlowQualifiedPreviewTitle": "Currently qualified", "stageFlowQualifiedPreviewEntry": "G{group} · Place {position} · {name}" + }, + "members": { + "subtitle": "Search, filter and edit members directly.", + "closeEditor": "Close editor", + "visibleMembers": "Visible members", + "search": "Search", + "searchPlaceholder": "Search by name, city, phone or email", + "memberScope": "Member scope", + "scopeAll": "All", + "scopeActive": "Active", + "scopeTest": "Trial", + "scopeNeedsForm": "Form unverified", + "scopeInactive": "Inactive", + "resultsVisible": "members visible", + "editHint": "Click a row to open the editor.", + "editorCreateHint": "Create a new member and capture contact details directly.", + "editorEditHint": "Edit the details for {name}.", + "transferSuccessTitle": "Transfer successful", + "transferErrorTitle": "Transfer error", + "clickTtRequestPending": "Click-TT request in progress", + "clickTtRequestAction": "Request click-TT eligibility", + "clickTtRequestTitle": "Start Click-TT request", + "clickTtRequestConfirm": "Start the automated Click-TT request for {name}?", + "clickTtRequestHint": "The request is processed automatically by the backend Click-TT workflow.", + "clickTtRequestSuccess": "Please sign in to click-tt and submit the request there.", + "clickTtRequestError": "The Click-TT request could not be submitted.", + "clickTtRequestFailedLog": "Click-TT request failed", + "deleteImageTitle": "Delete image", + "deleteImageConfirm": "Do you really want to delete this image?", + "parentFallback": "Parent", + "loadingMembers": "Loading members...", + "errorLoadingMembers": "Failed to load the member list.", + "scopeNotTraining": "No longer training", + "notInTrainingTooltip": "No participation for {weeks} training weeks", + "status": "Status", + "contact": "Contact", + "noPhoneShort": "No phone", + "noEmailShort": "No email", + "noAddressShort": "No address", + "clickTtSubmitted": "Click-TT submitted", + "markRegular": "Mark regular", + "markFormReceived": "Mark form verified", + "clickTtRequestShort": "Click-TT", + "clickTtRequestPendingShort": "Pending ...", + "memberDetails": "Member details", + "previewLastTraining": "Last training", + "previewNoLastTraining": "No participation yet", + "phoneListForSelection": "Phone list for selection", + "markFormsForSelection": "Verify forms for selection", + "markRegularForSelection": "Mark selection regular", + "phoneListSelectionFile": "phone-list-selection.pdf", + "batchFormsMarkedSuccess": "Marked {count} form(s) as verified.", + "batchFormsMarkedEmpty": "There are no unverified forms in the current selection.", + "batchMarkedRegularSuccess": "Marked {count} trial member(s) as regular.", + "batchMarkedRegularEmpty": "There are no trial members in the current selection.", + "batchPartialFailure": "{success} succeeded, {failed} failed.", + "sortBy": "Sort by", + "sortLastName": "Last name", + "sortFirstName": "First name", + "sortBirthday": "Birthday", + "sortAge": "Age", + "age": "Age", + "openTasks": "Open tasks", + "noOpenTasks": "No open tasks", + "taskVerifyForm": "Verify form", + "taskReviewTrialStatus": "Review trial status", + "taskCheckTrainingStatus": "Review training status", + "taskCheckClickTt": "Review Click-TT eligibility", + "taskActionVerify": "Verify", + "taskActionMarkRegular": "Mark regular", + "taskActionRequest": "Request", + "toggleSortDirection": "Toggle sort direction", + "sortLastTraining": "Last training", + "sortOpenTasks": "Open tasks", + "exportPreview": "Export preview", + "exportMembersSelected": "members currently selected", + "exportPhones": "Phone", + "exportReachableByPhone": "with phone number", + "exportEmails": "Email", + "exportReachableByEmail": "with email address", + "exportPreviewNames": "Preview", + "exportPreviewEmpty": "No members in the current selection", + "exportCsv": "Export CSV", + "exportCsvFile": "member-selection.csv", + "copyPhones": "Copy phones", + "copyEmails": "Copy emails", + "copyPhonesSuccess": "Phone list copied to clipboard.", + "copyPhonesEmpty": "There are no phone numbers in the current selection.", + "copyEmailsSuccess": "Email list copied to clipboard.", + "copyEmailsEmpty": "There are no email addresses in the current selection.", + "composeEmail": "Compose email", + "copyContactSummary": "Copy contact summary", + "copyContactSummarySuccess": "Contact summary copied to clipboard." } } diff --git a/frontend/src/views/MembersView.vue b/frontend/src/views/MembersView.vue index fed27c2c..3721c5fd 100644 --- a/frontend/src/views/MembersView.vue +++ b/frontend/src/views/MembersView.vue @@ -1,46 +1,295 @@