Files
yourpart3/frontend/src/views/social/VocabSubscribeView.vue
Torsten Schulz (local) 83597d9e02 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.
2025-12-30 18:34:32 +01:00

94 lines
2.2 KiB
Vue

<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>