174 lines
4.4 KiB
Vue
174 lines
4.4 KiB
Vue
<template>
|
|
<div class="vocab-new-language-view">
|
|
<section class="vocab-new-language-hero surface-card">
|
|
<span class="vocab-new-language-hero__eyebrow">Vokabeltrainer</span>
|
|
<h2>{{ $t('socialnetwork.vocab.newLanguageTitle') }}</h2>
|
|
<p>Neue Sprache anlegen, Freigabecode erzeugen und direkt in die Bearbeitung wechseln.</p>
|
|
</section>
|
|
|
|
<section class="box surface-card">
|
|
<label class="label form-field">
|
|
<span>{{ $t('socialnetwork.vocab.languageName') }}</span>
|
|
<input v-model="name" type="text" :class="{ 'field-error': nameTouched && !canSave }" />
|
|
<span class="form-hint">Ein kurzer, klarer Sprachname reicht für den Start.</span>
|
|
<span v-if="nameTouched && !canSave" class="form-error">Der Name sollte mindestens 2 Zeichen haben.</span>
|
|
</label>
|
|
|
|
<div class="actions form-actions-row">
|
|
<button :disabled="saving || !canSave" @click="create">
|
|
{{ saving ? $t('socialnetwork.vocab.saving') : $t('socialnetwork.vocab.create') }}
|
|
</button>
|
|
<button :disabled="saving" @click="cancel" class="button-secondary">{{ $t('Cancel') }}</button>
|
|
</div>
|
|
|
|
<div v-if="created" class="created">
|
|
<div><strong>{{ $t('socialnetwork.vocab.created') }}</strong></div>
|
|
<div>
|
|
{{ $t('socialnetwork.vocab.shareCode') }}:
|
|
<code>{{ created.shareCode }}</code>
|
|
</div>
|
|
<div class="hint">{{ $t('socialnetwork.vocab.shareHint') }}</div>
|
|
<button @click="openLanguage(created.id)">{{ $t('socialnetwork.vocab.openLanguage') }}</button>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapActions } from 'vuex';
|
|
import apiClient from '@/utils/axios.js';
|
|
import { showApiError, showSuccess } from '@/utils/feedback.js';
|
|
|
|
export default {
|
|
name: 'VocabNewLanguageView',
|
|
data() {
|
|
return {
|
|
name: '',
|
|
nameTouched: false,
|
|
saving: false,
|
|
created: null,
|
|
};
|
|
},
|
|
computed: {
|
|
canSave() {
|
|
return this.name.trim().length >= 2;
|
|
},
|
|
},
|
|
methods: {
|
|
...mapActions(['loadMenu']),
|
|
cancel() {
|
|
this.$router.push('/socialnetwork/vocab');
|
|
},
|
|
openLanguage(id) {
|
|
this.$router.push(`/socialnetwork/vocab/${id}`);
|
|
},
|
|
async create() {
|
|
this.nameTouched = true;
|
|
if (!this.canSave) {
|
|
return;
|
|
}
|
|
this.saving = true;
|
|
try {
|
|
const res = await apiClient.post('/api/vocab/languages', { name: this.name });
|
|
this.created = res.data;
|
|
// Menü sofort lokal aktualisieren (zusätzlich zum serverseitigen reloadmenu event)
|
|
try { await this.loadMenu(); } catch (_) {}
|
|
showSuccess(this, this.$t('socialnetwork.vocab.createdMessage'), this.$t('socialnetwork.vocab.createdTitle'));
|
|
} catch (e) {
|
|
console.error('Create vocab language failed:', e);
|
|
showApiError(this, e, this.$t('socialnetwork.vocab.createError'));
|
|
} finally {
|
|
this.saving = false;
|
|
}
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.vocab-new-language-view {
|
|
display: grid;
|
|
gap: 18px;
|
|
max-width: 760px;
|
|
}
|
|
|
|
.vocab-new-language-hero,
|
|
.box {
|
|
background: linear-gradient(180deg, rgba(255, 252, 247, 0.97), rgba(250, 244, 235, 0.95));
|
|
border: 1px solid var(--color-border);
|
|
border-radius: var(--radius-lg);
|
|
box-shadow: var(--shadow-soft);
|
|
}
|
|
|
|
.vocab-new-language-hero,
|
|
.box {
|
|
padding: 22px 24px;
|
|
}
|
|
|
|
.vocab-new-language-hero__eyebrow {
|
|
display: inline-flex;
|
|
margin-bottom: 8px;
|
|
padding: 4px 10px;
|
|
border-radius: var(--radius-pill);
|
|
background: var(--color-secondary-soft);
|
|
color: var(--color-text-secondary);
|
|
font-size: 0.78rem;
|
|
font-weight: 700;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.vocab-new-language-hero p {
|
|
margin: 0;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
.label {
|
|
display: grid;
|
|
gap: 8px;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.label span {
|
|
font-weight: 600;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
.actions {
|
|
display: flex;
|
|
gap: 8px;
|
|
flex-wrap: wrap;
|
|
}
|
|
.created {
|
|
display: grid;
|
|
gap: 8px;
|
|
margin-top: 18px;
|
|
padding: 18px;
|
|
background: rgba(255, 255, 255, 0.68);
|
|
border: 1px solid var(--color-border);
|
|
border-radius: var(--radius-md);
|
|
}
|
|
.hint {
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
code {
|
|
padding: 2px 8px;
|
|
border-radius: 999px;
|
|
background: var(--color-primary-soft);
|
|
color: var(--color-text-primary);
|
|
}
|
|
|
|
@media (max-width: 760px) {
|
|
.vocab-new-language-hero,
|
|
.box {
|
|
padding: 18px;
|
|
}
|
|
|
|
.actions button,
|
|
.created button {
|
|
width: 100%;
|
|
}
|
|
}
|
|
</style>
|