feat: complete tables config — all tables, all fields, boolean type

- Add missing tables: languages, users, blocklist, user-names, users-public
- Fix categories field names (name_de → titel_de/en/sv)
- Add missing fields: objects_created, sentence_sv, answer, negative_statement_id, etc.
- Fix pairs answer_type options (yes_no/text/question/word)
- Add boolean field type support in RecordModal

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 18:19:58 +02:00
parent 8242dab18c
commit 29786c531b
2 changed files with 147 additions and 30 deletions

View File

@@ -80,6 +80,20 @@ function EditableField({ fieldKey, value, fieldDef, onChange }) {
); );
} }
if (type === 'boolean') {
return (
<select
value={value === true ? 'true' : value === false ? 'false' : ''}
onChange={e => onChange(e.target.value === 'true' ? true : e.target.value === 'false' ? false : null)}
className="w-full border border-slate-300 rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-400 bg-white"
>
<option value=""> wählen </option>
<option value="true">true</option>
<option value="false">false</option>
</select>
);
}
if (type === 'number') { if (type === 'number') {
return ( return (
<input <input

View File

@@ -5,14 +5,14 @@ export const TABLES = {
endpoint: '/words', endpoint: '/words',
statusField: 'status', statusField: 'status',
primaryLabel: 'titel_de', primaryLabel: 'titel_de',
columns: ['titel_de', 'titel_en', 'status', 'difficulty_level', 'created_at'], columns: ['titel_de', 'titel_en', 'titel_sv', 'status', 'difficulty_level', 'created_at'],
linkedFields: { picture_ids: 'pictures', category_ids: 'categories' }, linkedFields: { picture_ids: 'pictures', category_ids: 'categories' },
editableFields: { editableFields: {
titel_de: { type: 'text' }, titel_de: { type: 'text' },
titel_en: { type: 'text' }, titel_en: { type: 'text' },
titel_sv: { type: 'text' }, titel_sv: { type: 'text' },
status: { type: 'select', options: ['published', 'blocked', 'draft', 'requested', 'translated'] }, status: { type: 'select', options: ['requested', 'translated', 'generated', 'published', 'blocked'] },
difficulty_level:{ type: 'number', min: 1, max: 10 }, difficulty_level:{ type: 'number', min: 1, max: 50 },
}, },
fetchRelated: [ fetchRelated: [
{ {
@@ -29,21 +29,22 @@ export const TABLES = {
key: 'categories', key: 'categories',
label: 'Kategorien', label: 'Kategorien',
endpoint: id => `/words/${id}/categories`, endpoint: id => `/words/${id}/categories`,
display: c => c.name_de || c.id, display: c => c.titel_de || c.id,
targetTable: 'categories', targetTable: 'categories',
linkEndpoint: (id, targetId) => `/words/${id}/categories/${targetId}`, linkEndpoint: (id, targetId) => `/words/${id}/categories/${targetId}`,
searchEndpoint: '/categories', searchEndpoint: '/categories',
searchLabel: c => c.name_de || c.id, searchLabel: c => c.titel_de || c.id,
}, },
], ],
}, },
pictures: { pictures: {
label: 'Bilder', label: 'Bilder',
icon: '🖼️', icon: '🖼️',
endpoint: '/pictures', endpoint: '/pictures',
statusField: 'status', statusField: 'status',
primaryLabel: 'design', primaryLabel: 'design',
columns: ['design', 'status', 'picture_link', 'blurhash', 'created_at'], columns: ['design', 'status', 'objects_created', 'picture_link', 'blurhash', 'generation_prompt', 'created_at'],
linkedFields: {}, linkedFields: {},
heroPanel: { heroPanel: {
imageField: 'picture_link', imageField: 'picture_link',
@@ -52,9 +53,12 @@ export const TABLES = {
}, },
editableFields: { editableFields: {
design: { type: 'text' }, design: { type: 'text' },
status: { type: 'select', options: ['published', 'blocked', 'uploaded', 'requested', 'generated'] }, status: { type: 'select', options: ['uploaded', 'published', 'blocked'] },
picture_link: { type: 'text' }, picture_link: { type: 'text' },
blurhash: { type: 'text' }, blurhash: { type: 'text' },
generation_prompt:{ type: 'textarea' },
blocked_reason: { type: 'select', options: ['regenerate', 'not_to_use'] },
objects_created: { type: 'boolean' },
}, },
fetchRelated: [ fetchRelated: [
{ {
@@ -69,17 +73,19 @@ export const TABLES = {
}, },
], ],
}, },
objects: { objects: {
label: 'Objekte', label: 'Objekte',
icon: '📦', icon: '📦',
endpoint: '/objects', endpoint: '/objects',
statusField: 'status', statusField: 'status',
primaryLabel: 'notes', primaryLabel: 'notes',
columns: ['id', 'status', 'notes', 'created_at'], columns: ['id', 'status', 'notes', 'blocked_topic', 'created_at'],
linkedFields: { word_ids: 'words', picture_ids: 'pictures', pair_ids: 'pairs' }, linkedFields: { word_ids: 'words', picture_ids: 'pictures', pair_ids: 'pairs' },
editableFields: { editableFields: {
notes: { type: 'textarea' }, notes: { type: 'textarea' },
status: { type: 'select', options: ['published', 'blocked', 'draft'] }, blocked_topic:{ type: 'text' },
status: { type: 'select', options: ['draft', 'published', 'blocked'] },
}, },
fetchRelated: [ fetchRelated: [
{ {
@@ -104,69 +110,166 @@ export const TABLES = {
}, },
], ],
}, },
pairs: { pairs: {
label: 'Pairs', label: 'Pairs',
icon: '🔗', icon: '🔗',
endpoint: '/pairs', endpoint: '/pairs',
statusField: 'status', statusField: 'status',
primaryLabel: 'id', primaryLabel: 'id',
columns: ['id', 'answer_type', 'difficulty_level', 'status', 'question_id', 'positive_statement_id', 'created_at'], columns: ['id', 'answer_type', 'difficulty_level', 'status', 'question_id', 'positive_statement_id', 'negative_statement_id', 'created_at'],
linkedFields: { linkedFields: {
question_id: 'questions', question_id: 'questions',
positive_statement_id: 'statements', positive_statement_id: 'statements',
negative_statement_id: 'statements', negative_statement_id: 'statements',
}, },
editableFields: { editableFields: {
answer_type: { type: 'select', options: ['word', 'sentence'] }, answer_type: { type: 'select', options: ['yes_no', 'text', 'question', 'word'] },
difficulty_level:{ type: 'number', min: 1, max: 10 }, difficulty_level: { type: 'number', min: 1, max: 50 },
status: { type: 'select', options: ['published', 'blocked', 'draft'] }, blocked_topic: { type: 'text' },
status: { type: 'select', options: ['draft', 'published', 'blocked'] },
}, },
fetchRelated: [], fetchRelated: [],
}, },
questions: { questions: {
label: 'Fragen', label: 'Fragen',
icon: '❓', icon: '❓',
endpoint: '/questions', endpoint: '/questions',
statusField: 'status', statusField: 'status',
primaryLabel: 'sentence_de', primaryLabel: 'sentence_de',
columns: ['sentence_de', 'sentence_en', 'status', 'created_at'], columns: ['sentence_de', 'sentence_en', 'sentence_sv', 'status', 'blocked_topic', 'created_at'],
linkedFields: {}, linkedFields: {},
editableFields: { editableFields: {
sentence_de: { type: 'textarea' }, sentence_de: { type: 'textarea' },
sentence_en: { type: 'textarea' }, sentence_en: { type: 'textarea' },
status: { type: 'select', options: ['published', 'blocked', 'draft'] }, sentence_sv: { type: 'textarea' },
blocked_topic:{ type: 'text' },
status: { type: 'select', options: ['draft', 'published', 'blocked'] },
}, },
fetchRelated: [], fetchRelated: [],
}, },
statements: { statements: {
label: 'Statements', label: 'Statements',
icon: '💬', icon: '💬',
endpoint: '/statements', endpoint: '/statements',
statusField: 'status', statusField: 'status',
primaryLabel: 'positive_sentence_de', primaryLabel: 'positive_sentence_de',
columns: ['positive_sentence_de', 'negative_sentence_de', 'status', 'created_at'], columns: ['positive_sentence_de', 'negative_sentence_de', 'answer', 'status', 'created_at'],
linkedFields: {}, linkedFields: {},
editableFields: { editableFields: {
positive_sentence_de: { type: 'textarea' }, positive_sentence_de: { type: 'textarea' },
negative_sentence_de: { type: 'textarea' }, negative_sentence_de: { type: 'textarea' },
positive_sentence_en: { type: 'textarea' }, positive_sentence_en: { type: 'textarea' },
negative_sentence_en: { type: 'textarea' }, negative_sentence_en: { type: 'textarea' },
status: { type: 'select', options: ['published', 'blocked', 'draft'] }, positive_sentence_sv: { type: 'textarea' },
negative_sentence_sv: { type: 'textarea' },
answer: { type: 'boolean' },
blocked_topic: { type: 'text' },
status: { type: 'select', options: ['draft', 'published', 'blocked'] },
}, },
fetchRelated: [], fetchRelated: [],
}, },
categories: { categories: {
label: 'Kategorien', label: 'Kategorien',
icon: '🏷️', icon: '🏷️',
endpoint: '/categories', endpoint: '/categories',
statusField: null, statusField: 'status',
primaryLabel: 'name_de', primaryLabel: 'titel_de',
columns: ['name_de', 'name_en', 'name_sv', 'created_at'], columns: ['titel_de', 'titel_en', 'titel_sv', 'status', 'difficulty_level', 'created_at'],
linkedFields: {}, linkedFields: {},
editableFields: { editableFields: {
name_de: { type: 'text' }, titel_de: { type: 'text' },
name_en: { type: 'text' }, titel_en: { type: 'text' },
name_sv: { type: 'text' }, titel_sv: { type: 'text' },
status: { type: 'select', options: ['requested', 'published', 'blocked'] },
difficulty_level:{ type: 'number', min: 1, max: 50 },
},
fetchRelated: [],
},
languages: {
label: 'Sprachen',
icon: '🌐',
endpoint: '/languages',
statusField: 'status',
primaryLabel: 'titel_en',
columns: ['titel_en', 'titel_de', 'titel_sv', 'short_en', 'status', 'created_at'],
linkedFields: {},
editableFields: {
titel_en: { type: 'text' },
titel_de: { type: 'text' },
titel_sv: { type: 'text' },
short_en: { type: 'text' },
status: { type: 'select', options: ['draft', 'published', 'blocked'] },
},
fetchRelated: [],
},
users: {
label: 'Users',
icon: '👤',
endpoint: '/users',
statusField: null,
primaryLabel: 'email',
columns: ['email', 'role', 'is_active', 'created_at'],
linkedFields: {},
editableFields: {
role: { type: 'select', options: ['end-user', 'admin'] },
is_active: { type: 'boolean' },
},
fetchRelated: [],
},
blocklist: {
label: 'Blocklist',
icon: '🚫',
endpoint: '/blocklist',
statusField: null,
primaryLabel: 'email',
columns: ['email', 'username', 'phone', 'ip', 'is_blocked', 'blocked_at', 'created_at'],
linkedFields: {},
editableFields: {
email: { type: 'text' },
username: { type: 'text' },
phone: { type: 'text' },
ip: { type: 'text' },
is_blocked: { type: 'boolean' },
},
fetchRelated: [],
},
'user-names': {
label: 'Usernames',
icon: '🪪',
endpoint: '/user-names',
statusField: null,
primaryLabel: 'username',
columns: ['username', 'username_lowercase', 'created_at'],
linkedFields: {},
editableFields: {
username: { type: 'text' },
},
fetchRelated: [],
},
'users-public': {
label: 'Users Public',
icon: '🧑‍🤝‍🧑',
endpoint: '/users-public',
statusField: null,
primaryLabel: 'id',
columns: ['id', 'username_id', 'language_native_id', 'language_target_id', 'created_at'],
linkedFields: {
username_id: 'user-names',
language_native_id: 'languages',
language_target_id: 'languages',
},
editableFields: {
language_native_id: { type: 'text' },
language_target_id: { type: 'text' },
}, },
fetchRelated: [], fetchRelated: [],
}, },