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') {
return (
<input

View File

@@ -5,14 +5,14 @@ export const TABLES = {
endpoint: '/words',
statusField: 'status',
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' },
editableFields: {
titel_de: { type: 'text' },
titel_en: { type: 'text' },
titel_sv: { type: 'text' },
status: { type: 'select', options: ['published', 'blocked', 'draft', 'requested', 'translated'] },
difficulty_level:{ type: 'number', min: 1, max: 10 },
status: { type: 'select', options: ['requested', 'translated', 'generated', 'published', 'blocked'] },
difficulty_level:{ type: 'number', min: 1, max: 50 },
},
fetchRelated: [
{
@@ -29,21 +29,22 @@ export const TABLES = {
key: 'categories',
label: 'Kategorien',
endpoint: id => `/words/${id}/categories`,
display: c => c.name_de || c.id,
display: c => c.titel_de || c.id,
targetTable: 'categories',
linkEndpoint: (id, targetId) => `/words/${id}/categories/${targetId}`,
searchEndpoint: '/categories',
searchLabel: c => c.name_de || c.id,
searchLabel: c => c.titel_de || c.id,
},
],
},
pictures: {
label: 'Bilder',
icon: '🖼️',
endpoint: '/pictures',
statusField: 'status',
primaryLabel: 'design',
columns: ['design', 'status', 'picture_link', 'blurhash', 'created_at'],
columns: ['design', 'status', 'objects_created', 'picture_link', 'blurhash', 'generation_prompt', 'created_at'],
linkedFields: {},
heroPanel: {
imageField: 'picture_link',
@@ -52,9 +53,12 @@ export const TABLES = {
},
editableFields: {
design: { type: 'text' },
status: { type: 'select', options: ['published', 'blocked', 'uploaded', 'requested', 'generated'] },
status: { type: 'select', options: ['uploaded', 'published', 'blocked'] },
picture_link: { type: 'text' },
blurhash: { type: 'text' },
generation_prompt:{ type: 'textarea' },
blocked_reason: { type: 'select', options: ['regenerate', 'not_to_use'] },
objects_created: { type: 'boolean' },
},
fetchRelated: [
{
@@ -69,17 +73,19 @@ export const TABLES = {
},
],
},
objects: {
label: 'Objekte',
icon: '📦',
endpoint: '/objects',
statusField: 'status',
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' },
editableFields: {
notes: { type: 'textarea' },
status: { type: 'select', options: ['published', 'blocked', 'draft'] },
blocked_topic:{ type: 'text' },
status: { type: 'select', options: ['draft', 'published', 'blocked'] },
},
fetchRelated: [
{
@@ -104,69 +110,166 @@ export const TABLES = {
},
],
},
pairs: {
label: 'Pairs',
icon: '🔗',
endpoint: '/pairs',
statusField: 'status',
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: {
question_id: 'questions',
positive_statement_id: 'statements',
negative_statement_id: 'statements',
},
editableFields: {
answer_type: { type: 'select', options: ['word', 'sentence'] },
difficulty_level:{ type: 'number', min: 1, max: 10 },
status: { type: 'select', options: ['published', 'blocked', 'draft'] },
answer_type: { type: 'select', options: ['yes_no', 'text', 'question', 'word'] },
difficulty_level: { type: 'number', min: 1, max: 50 },
blocked_topic: { type: 'text' },
status: { type: 'select', options: ['draft', 'published', 'blocked'] },
},
fetchRelated: [],
},
questions: {
label: 'Fragen',
icon: '❓',
endpoint: '/questions',
statusField: 'status',
primaryLabel: 'sentence_de',
columns: ['sentence_de', 'sentence_en', 'status', 'created_at'],
columns: ['sentence_de', 'sentence_en', 'sentence_sv', 'status', 'blocked_topic', 'created_at'],
linkedFields: {},
editableFields: {
sentence_de: { 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: [],
},
statements: {
label: 'Statements',
icon: '💬',
endpoint: '/statements',
statusField: 'status',
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: {},
editableFields: {
positive_sentence_de: { type: 'textarea' },
negative_sentence_de: { type: 'textarea' },
positive_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: [],
},
categories: {
label: 'Kategorien',
icon: '🏷️',
endpoint: '/categories',
statusField: null,
primaryLabel: 'name_de',
columns: ['name_de', 'name_en', 'name_sv', 'created_at'],
statusField: 'status',
primaryLabel: 'titel_de',
columns: ['titel_de', 'titel_en', 'titel_sv', 'status', 'difficulty_level', 'created_at'],
linkedFields: {},
editableFields: {
name_de: { type: 'text' },
name_en: { type: 'text' },
name_sv: { type: 'text' },
titel_de: { type: 'text' },
titel_en: { 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: [],
},