Add Vocab Trainer feature with routing, database schema, and translations
- Introduced Vocab Trainer functionality, including new routes for managing languages and chapters. - Implemented database schema for vocab-related tables to ensure data integrity. - Updated navigation and UI components to include Vocab Trainer in the social network menu. - Added translations for Vocab Trainer in both German and English locales, enhancing user accessibility.
This commit is contained in:
93
frontend/src/views/social/VocabSubscribeView.vue
Normal file
93
frontend/src/views/social/VocabSubscribeView.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<h2>{{ $t('socialnetwork.vocab.subscribeTitle') }}</h2>
|
||||
|
||||
<div class="box">
|
||||
<p>{{ $t('socialnetwork.vocab.subscribeHint') }}</p>
|
||||
|
||||
<label class="label">
|
||||
{{ $t('socialnetwork.vocab.shareCode') }}
|
||||
<input v-model="shareCode" type="text" />
|
||||
</label>
|
||||
|
||||
<div class="actions">
|
||||
<button :disabled="saving || !canSave" @click="subscribe">
|
||||
{{ saving ? $t('socialnetwork.vocab.saving') : $t('socialnetwork.vocab.subscribe') }}
|
||||
</button>
|
||||
<button :disabled="saving" @click="back">{{ $t('general.back') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex';
|
||||
import apiClient from '@/utils/axios.js';
|
||||
|
||||
export default {
|
||||
name: 'VocabSubscribeView',
|
||||
data() {
|
||||
return {
|
||||
shareCode: '',
|
||||
saving: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
canSave() {
|
||||
return this.shareCode.trim().length >= 6;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['loadMenu']),
|
||||
back() {
|
||||
this.$router.push('/socialnetwork/vocab');
|
||||
},
|
||||
async subscribe() {
|
||||
this.saving = true;
|
||||
try {
|
||||
const res = await apiClient.post('/api/vocab/subscribe', { shareCode: this.shareCode });
|
||||
try { await this.loadMenu(); } catch (_) {}
|
||||
const langId = res.data?.languageId;
|
||||
this.$root.$refs.messageDialog?.open(
|
||||
this.$t('socialnetwork.vocab.subscribeSuccess'),
|
||||
this.$t('socialnetwork.vocab.subscribeTitle')
|
||||
);
|
||||
if (langId) {
|
||||
this.$router.push(`/socialnetwork/vocab/${langId}`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Subscribe failed:', e);
|
||||
this.$root.$refs.messageDialog?.open(
|
||||
this.$t('socialnetwork.vocab.subscribeError'),
|
||||
this.$t('error.title')
|
||||
);
|
||||
} finally {
|
||||
this.saving = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
// optional: ?code=... unterstützt
|
||||
const code = this.$route?.query?.code;
|
||||
if (typeof code === 'string' && code.trim()) {
|
||||
this.shareCode = code.trim();
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.box {
|
||||
background: #f6f6f6;
|
||||
padding: 12px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
.label {
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user