448 lines
13 KiB
Vue
448 lines
13 KiB
Vue
<template>
|
|
<div class="no-login-view">
|
|
<div class="beta-banner" role="status" aria-live="polite">
|
|
<strong>{{ $t('home.betaNoticeLabel') }}</strong> {{ $t('home.betaNoticeText') }}
|
|
</div>
|
|
<div class="home-structure">
|
|
<div class="mascot">
|
|
<Character3D gender="male" />
|
|
</div>
|
|
<div class="actions">
|
|
<section class="actions-panel actions-panel--story surface-card">
|
|
<div class="panel-intro">
|
|
<span class="panel-kicker">Dein Einstieg</span>
|
|
<h2>{{ $t('home.nologin.welcome') }}</h2>
|
|
<p>{{ $t('home.nologin.description') }}</p>
|
|
</div>
|
|
|
|
<div class="story-highlight">
|
|
<p>
|
|
YourPart verbindet Community, Echtzeit-Chat, Foren, Bildergalerie und das Aufbauspiel
|
|
<em>Falukant</em> in einer Plattform. Der Fokus liegt auf Austausch, spielerischer Tiefe und
|
|
einer wachsenden Produktwelt.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="story-block">
|
|
<h3>{{ $t('home.nologin.expected.title') }}</h3>
|
|
<ul class="feature-list">
|
|
<li v-html="$t('home.nologin.expected.items.chat')"></li>
|
|
<li v-html="$t('home.nologin.expected.items.social')"></li>
|
|
<li v-html="$t('home.nologin.expected.items.forum')"></li>
|
|
<li v-html="$t('home.nologin.expected.items.falukant')"></li>
|
|
<li v-html="$t('home.nologin.expected.items.minigames')"></li>
|
|
<li v-html="$t('home.nologin.expected.items.multilingual')"></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="story-columns">
|
|
<article>
|
|
<h3>{{ $t('home.nologin.falukantShort.title') }}</h3>
|
|
<p>{{ $t('home.nologin.falukantShort.text') }}</p>
|
|
</article>
|
|
<article>
|
|
<h3>{{ $t('home.nologin.privacyBeta.title') }}</h3>
|
|
<p>{{ $t('home.nologin.privacyBeta.text') }}</p>
|
|
</article>
|
|
</div>
|
|
|
|
<div class="story-cta">
|
|
<h3>{{ $t('home.nologin.getStarted.title') }}</h3>
|
|
<p>{{ $t('home.nologin.getStarted.text', { register: $t('home.nologin.login.register') }) }}</p>
|
|
</div>
|
|
</section>
|
|
<section class="actions-panel actions-panel--access surface-card">
|
|
<div class="login-panel">
|
|
<span class="panel-kicker">Direkt starten</span>
|
|
<h2>{{ $t('home.nologin.login.submit') }}</h2>
|
|
<p class="login-panel__hint">Mit bestehendem Konto direkt einloggen oder alternativ ohne Konto den Random-Chat testen.</p>
|
|
<div class="quick-access-actions">
|
|
<button type="button" class="primary-action" @click="doLogin">{{ $t('home.nologin.login.submit') }}</button>
|
|
<button type="button" class="secondary-action" @click="openRegisterDialog">{{ $t('home.nologin.login.register') }}</button>
|
|
</div>
|
|
<div class="login-fields">
|
|
<input ref="usernameInput" v-model="username" size="20" type="text" :placeholder="$t('home.nologin.login.name')"
|
|
:title="$t('home.nologin.login.namedescription')" @keydown.enter="focusPassword">
|
|
<input v-model="password" size="20" type="password"
|
|
:placeholder="$t('home.nologin.login.password')"
|
|
:title="$t('home.nologin.login.passworddescription')" @keydown.enter="doLogin"
|
|
ref="passwordInput">
|
|
</div>
|
|
<div class="stay-logged-in-row">
|
|
<label class="stay-logged-in-label">
|
|
<input class="stay-logged-in-checkbox" type="checkbox">
|
|
<span>{{ $t('home.nologin.login.stayLoggedIn') }}</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="access-split">
|
|
<article class="access-card">
|
|
<h3>{{ $t('home.nologin.randomchat') }}</h3>
|
|
<p>Ohne lange Vorbereitung direkt in spontane Begegnungen und offene Gespraeche starten.</p>
|
|
<button type="button" class="secondary-action" @click="openRandomChat">{{ $t('home.nologin.startrandomchat') }}</button>
|
|
</article>
|
|
<article class="access-card">
|
|
<h3>Konto und Zugang</h3>
|
|
<p>Neu hier oder Passwort vergessen? Von hier aus gelangst du direkt in Registrierung und Wiederherstellung.</p>
|
|
<div class="access-links">
|
|
<span @click="openPasswordResetDialog" class="link">{{
|
|
$t('home.nologin.login.lostpassword') }}</span>
|
|
<span @click="openRegisterDialog" class="link">{{ $t('home.nologin.login.register') }}</span>
|
|
</div>
|
|
</article>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
<div class="mascot">
|
|
<Character3D gender="female" />
|
|
</div>
|
|
<RandomChatDialog ref="randomChatDialog" />
|
|
<RegisterDialog ref="registerDialog" />
|
|
<PasswordResetDialog ref="passwordResetDialog" />
|
|
</div>
|
|
|
|
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import RandomChatDialog from '@/dialogues/chat/RandomChatDialog.vue';
|
|
import RegisterDialog from '@/dialogues/auth/RegisterDialog.vue';
|
|
import PasswordResetDialog from '@/dialogues/auth/PasswordResetDialog.vue';
|
|
import Character3D from '@/components/Character3D.vue';
|
|
import apiClient from '@/utils/axios.js';
|
|
import { mapActions } from 'vuex';
|
|
|
|
export default {
|
|
name: 'HomeNoLoginView',
|
|
data() {
|
|
return {
|
|
username: '',
|
|
password: '',
|
|
};
|
|
},
|
|
components: {
|
|
RandomChatDialog,
|
|
RegisterDialog,
|
|
PasswordResetDialog,
|
|
Character3D,
|
|
},
|
|
methods: {
|
|
...mapActions(['login']),
|
|
openRandomChat() {
|
|
const dlg = this.$refs.randomChatDialog;
|
|
if (dlg && typeof dlg.open === 'function') dlg.open();
|
|
},
|
|
openRegisterDialog() {
|
|
const dlg = this.$refs.registerDialog;
|
|
if (dlg && typeof dlg.open === 'function') dlg.open();
|
|
},
|
|
openPasswordResetDialog() {
|
|
const dlg = this.$refs.passwordResetDialog;
|
|
if (dlg && typeof dlg.open === 'function') dlg.open();
|
|
},
|
|
focusPassword() {
|
|
this.$refs.passwordInput.focus();
|
|
},
|
|
async doLogin() {
|
|
try {
|
|
const response = await apiClient.post('/api/auth/login', { username: this.username, password: this.password });
|
|
this.login(response.data);
|
|
} catch (error) {
|
|
const errorKey = error?.response?.data?.error || 'network';
|
|
this.$root.$refs.errorDialog.open(`tr:error.${errorKey}`);
|
|
}
|
|
}
|
|
},
|
|
mounted() {
|
|
this.$nextTick(() => {
|
|
this.$refs.usernameInput?.focus?.();
|
|
});
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.beta-banner {
|
|
width: min(100%, var(--content-max-width));
|
|
background: linear-gradient(180deg, #fff2cf 0%, #fde7b2 100%);
|
|
border: 1px solid rgba(201, 130, 31, 0.24);
|
|
color: #8a5a12;
|
|
padding: 10px 14px;
|
|
margin: 0 0 14px 0;
|
|
text-align: center;
|
|
border-radius: var(--radius-lg);
|
|
box-shadow: var(--shadow-soft);
|
|
}
|
|
|
|
.home-structure {
|
|
display: flex;
|
|
align-items: stretch;
|
|
justify-content: center;
|
|
gap: 1.4rem;
|
|
width: 100%;
|
|
height: 100%;
|
|
flex: 1;
|
|
min-height: 0;
|
|
}
|
|
|
|
.home-structure>div {
|
|
text-align: center;
|
|
display: flex;
|
|
min-height: 0;
|
|
}
|
|
|
|
.mascot {
|
|
flex: 0 0 clamp(180px, 22%, 280px);
|
|
justify-content: center;
|
|
align-items: stretch;
|
|
background: linear-gradient(180deg, #fff5e8 0%, #fce7ca 100%);
|
|
border: 1px solid rgba(248, 162, 43, 0.16);
|
|
border-radius: var(--radius-lg);
|
|
box-shadow: 0 10px 24px rgba(93, 64, 55, 0.08);
|
|
overflow: hidden;
|
|
align-self: center;
|
|
height: clamp(320px, 68vh, 560px);
|
|
min-height: 320px;
|
|
max-height: 560px;
|
|
}
|
|
|
|
.actions {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 1rem;
|
|
flex: 1 1 auto;
|
|
min-height: 0;
|
|
}
|
|
|
|
.actions-panel {
|
|
flex: 1;
|
|
min-height: 0;
|
|
background:
|
|
linear-gradient(180deg, rgba(255, 251, 246, 0.96) 0%, rgba(248, 240, 231, 0.96) 100%);
|
|
color: #5D4037;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: auto;
|
|
padding: 1.2rem 1.25rem;
|
|
text-align: left;
|
|
}
|
|
|
|
.actions-panel h2,
|
|
.actions-panel h3 {
|
|
width: 100%;
|
|
}
|
|
|
|
.panel-kicker {
|
|
display: inline-block;
|
|
margin-bottom: 0.7rem;
|
|
padding: 0.3rem 0.65rem;
|
|
border-radius: 999px;
|
|
background: rgba(248, 162, 43, 0.12);
|
|
color: #8a5411;
|
|
font-size: 0.74rem;
|
|
font-weight: 700;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.panel-intro,
|
|
.story-highlight,
|
|
.story-block,
|
|
.story-columns,
|
|
.story-cta,
|
|
.login-panel,
|
|
.access-split {
|
|
width: 100%;
|
|
}
|
|
|
|
.story-highlight {
|
|
padding: 1rem 1.1rem;
|
|
margin: 0.8rem 0 1rem;
|
|
border-radius: var(--radius-lg);
|
|
background: rgba(248, 162, 43, 0.08);
|
|
border: 1px solid rgba(248, 162, 43, 0.12);
|
|
}
|
|
|
|
.story-block {
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.feature-list {
|
|
padding-left: 1.1rem;
|
|
}
|
|
|
|
.feature-list li + li {
|
|
margin-top: 0.55rem;
|
|
}
|
|
|
|
.story-columns {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
gap: 0.9rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.story-columns article,
|
|
.story-cta,
|
|
.access-card {
|
|
padding: 1rem 1.05rem;
|
|
border-radius: var(--radius-lg);
|
|
background: rgba(255, 255, 255, 0.68);
|
|
border: 1px solid var(--color-border);
|
|
}
|
|
|
|
.login-panel {
|
|
padding: 1rem 1.05rem;
|
|
border-radius: var(--radius-lg);
|
|
background: rgba(255, 255, 255, 0.7);
|
|
border: 1px solid var(--color-border);
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.login-panel__hint {
|
|
margin: 0 0 0.9rem;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
.quick-access-actions {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 0.75rem;
|
|
margin-bottom: 0.9rem;
|
|
}
|
|
|
|
.login-fields {
|
|
display: grid;
|
|
gap: 0.8rem;
|
|
}
|
|
|
|
.primary-action,
|
|
.secondary-action {
|
|
align-self: flex-start;
|
|
}
|
|
|
|
.access-split {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
gap: 0.9rem;
|
|
}
|
|
|
|
.access-card p {
|
|
margin-bottom: 0.9rem;
|
|
}
|
|
|
|
.access-links {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 0.9rem;
|
|
}
|
|
|
|
.stay-logged-in-row {
|
|
width: 100%;
|
|
display: flex;
|
|
justify-content: flex-start;
|
|
margin-top: 0.35rem;
|
|
}
|
|
|
|
.stay-logged-in-label {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.55rem;
|
|
cursor: pointer;
|
|
font-size: 0.95rem;
|
|
}
|
|
|
|
.stay-logged-in-checkbox {
|
|
width: 16px;
|
|
min-width: 16px;
|
|
height: 16px;
|
|
min-height: 16px;
|
|
margin: 0;
|
|
padding: 0;
|
|
flex: 0 0 16px;
|
|
accent-color: var(--color-primary-orange);
|
|
box-shadow: none;
|
|
}
|
|
|
|
.seo-content {
|
|
max-width: 1000px;
|
|
margin: 24px auto 0 auto;
|
|
padding: 0 16px 40px 16px;
|
|
color: #5D4037;
|
|
background-color: #FFF4F0;
|
|
border: 1px solid rgba(0, 0, 0, 0.06);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.seo-content h1 {
|
|
font-size: 28px;
|
|
margin: 0 0 8px 0;
|
|
}
|
|
|
|
.seo-content h2 {
|
|
font-size: 20px;
|
|
margin: 18px 0 6px 0;
|
|
color: #444;
|
|
}
|
|
|
|
.seo-content p {
|
|
line-height: 1.6;
|
|
margin: 0 0 8px 0;
|
|
}
|
|
|
|
.seo-content ul {
|
|
margin: 0 0 8px 20px;
|
|
}
|
|
|
|
/* Scrollbarer Bereich für "Was dich erwartet" */
|
|
.seo-content .expected {
|
|
max-height: 200px;
|
|
overflow: auto;
|
|
padding-right: 8px;
|
|
background-color: #fdf1db;
|
|
border: 1px solid rgba(0, 0, 0, 0.05);
|
|
border-radius: 4px;
|
|
margin: 12px 0;
|
|
}
|
|
|
|
.no-login-view {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: flex-start;
|
|
width: 100%;
|
|
height: 100%;
|
|
min-height: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
@media (max-width: 960px) {
|
|
.home-structure {
|
|
flex-direction: column;
|
|
gap: 1rem;
|
|
overflow: auto;
|
|
}
|
|
|
|
.mascot {
|
|
min-height: 260px;
|
|
height: 260px;
|
|
flex: 0 0 260px;
|
|
}
|
|
|
|
.actions {
|
|
min-height: auto;
|
|
}
|
|
|
|
.actions-panel {
|
|
min-height: 260px;
|
|
}
|
|
|
|
.story-columns,
|
|
.access-split {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
</style>
|