Initial commit
This commit is contained in:
207
pages/settings/_index.vue
Normal file
207
pages/settings/_index.vue
Normal file
@@ -0,0 +1,207 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-lg-9 col-md-11 col-sm-12 col-xl-8">
|
||||
<!-- Header Section -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h1 class="h3 fw-bold text-center pt-3">
|
||||
{{ t('Account') }}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Account Details -->
|
||||
<div class="border-bottom row mx-0 pt-4">
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-start">
|
||||
{{ t('First Name') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-end text-muted">
|
||||
{{ user.first_name }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-bottom row mx-0 pt-4">
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-start">
|
||||
{{ t('Last Name') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-end text-muted">
|
||||
{{ user.last_name }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-bottom row mx-0 pt-4">
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-start">
|
||||
{{ t('Language') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-end text-muted">
|
||||
{{ user.language == 'de' ? 'German' : 'English' }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-bottom row mx-0 pt-4">
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-start">
|
||||
{{ t('Email') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-end text-muted">
|
||||
{{ user.email }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-bottom row mx-0 pt-4">
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-start">
|
||||
{{ t('Password') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-end text-muted">•••••••••</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Conditional Manager Details -->
|
||||
<div v-if="user.inviter" class="border-bottom row mx-0 pt-4">
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-start">
|
||||
{{ t('Manager Name') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-end text-muted">
|
||||
{{ user.inviter.first_name ?? '' }} {{ user.inviter.last_name ?? '' }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="user.inviter" class="border-bottom row mx-0 pt-4">
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-start">
|
||||
{{ t('Manager Email') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-end text-muted">
|
||||
{{ user.inviter.email ?? '' }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="user.inviter" class="row pt-4">
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-start">
|
||||
{{ t('Current Package') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-end text-muted">
|
||||
{{ showManagerPlan() }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Logout Button -->
|
||||
<div class="account-buttons d-flex justify-content-center pt-5">
|
||||
<nuxt-link
|
||||
:to="localePath('/settings/editaccount')"
|
||||
class="btn btn-primary-custom text-decoration-none"
|
||||
>
|
||||
{{ t('Edit_') }}
|
||||
</nuxt-link>
|
||||
<button class="btn fw-bold btn-outline-dark" @click="logoutNow">
|
||||
{{ t("Log Out") }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Subscription Call-to-Action -->
|
||||
<div class="row pt-5 pb-4 px-2 mx-0">
|
||||
<div
|
||||
class="col-12 rounded text-center py-3 py-md-5"
|
||||
style="background-image: linear-gradient(40.53deg, #E9A446 6.68%, #E9C046 100%)"
|
||||
>
|
||||
<h4 class="text-center text-white">
|
||||
{{ t("Get another free 30 days") }}
|
||||
</h4>
|
||||
<h5 class="text-center px-2 px-md-5 text-white pt-2">
|
||||
{{ t("You can still use Mindboost for 30 days for free. Subscribe to increase your productivity with Mindboost afterwards.") }}
|
||||
</h5>
|
||||
<NuxtLink
|
||||
disabled
|
||||
type="button"
|
||||
class="btn px-4 py-2 mt-2 mt-md-3 fs-5"
|
||||
style="background-color: white; gap: 10px;"
|
||||
>
|
||||
{{ t("Subscribe") }}
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
|
||||
// Composition API setup
|
||||
const { t } = useI18n()
|
||||
const localePath = useLocalePath()
|
||||
const userStore = useUserStore()
|
||||
const router = useRouter()
|
||||
|
||||
// Computed property for user state
|
||||
const user = computed(() => userStore.user)
|
||||
|
||||
// Logout method
|
||||
const logoutNow = async () => {
|
||||
await userStore.logout()
|
||||
try {
|
||||
await $axios.post('/api/logout')
|
||||
} catch (error) {
|
||||
// Handle the error if needed
|
||||
}
|
||||
router.push(localePath('/auth/login'))
|
||||
}
|
||||
|
||||
function showManagerPlan () {
|
||||
if (user.value.inviter.current_subscription_plan === 1) {
|
||||
return 'Basic'
|
||||
} else if (user.value.inviter.current_subscription_plan === 2) {
|
||||
return 'Team'
|
||||
} else if (user.value.inviter.current_subscription_plan === 3) {
|
||||
return 'Enterprise'
|
||||
}
|
||||
|
||||
// this.$toast.success(`Manager already has the ${managerPlan} plan`) // Fixed typo
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.account-buttons {
|
||||
gap: 1.5em;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 576px) {
|
||||
.account-buttons {
|
||||
flex-direction: column;
|
||||
gap: 0.75em;
|
||||
}
|
||||
}
|
||||
</style>
|
60
pages/settings/about.vue
Normal file
60
pages/settings/about.vue
Normal file
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-lg-9 col-md-11 col-sm-12 col-xl-8">
|
||||
<h1 class="h3 fw-bold text-center py-3">
|
||||
{{ t('About Mindboost') }}
|
||||
</h1>
|
||||
<div class="row pt-4">
|
||||
<div class="col-12">
|
||||
<h2 class="h6 fw-bold">
|
||||
{{ t('WHAT IS MINDBOOST?') }}
|
||||
</h2>
|
||||
<p class="text-muted ">
|
||||
{{ t('Mindboost creates soundscapes for your headphones that help you focus up to 35% better. Mindboost combines voice masking, binaural beats and alpha waves.') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-12 pt-3">
|
||||
<h2 class="h6 fw-bold">
|
||||
{{ t('HOW DOES MINDBOOST WORK?') }}
|
||||
</h2>
|
||||
<p class="text-muted ">
|
||||
{{ t('Our algorithm measures the acoustics of your cell phone or other device in the room in real time and generates a soundscape that optimally blocks out disruptive background noise such as colleagues on the phone.') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-12 pt-3">
|
||||
<h2 class="h6 fw-bold">
|
||||
{{ t('WHY DOES MINDBOOST WORK?') }}
|
||||
</h2>
|
||||
<p class="text-muted ">
|
||||
{{ t('All soundscapes in Mindboost have been tested and optimized in listening tests in cooperation with the Fraunhofer IBP. So you can be sure that Mindboost supports you optimally with your concentration.') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-12 pt-3">
|
||||
<h2 class="h6 fw-bold">
|
||||
{{ t('WHO WE ARE?') }}
|
||||
</h2>
|
||||
<p class="text-muted ">
|
||||
{{ t('We are a small team of audio developers. Inspiried by the power of sound, well known from music, we cannot stop exploring the digital audio world. We are happy that we can be part of a community that uses audio next to practical services mainly to generate fun.') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'SettingPage',
|
||||
setup () {
|
||||
const { t } = useI18n()
|
||||
const localePath = useLocalePath()
|
||||
return { t, localePath }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
271
pages/settings/account.vue
Normal file
271
pages/settings/account.vue
Normal file
@@ -0,0 +1,271 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-lg-9 col-md-11 col-sm-12 col-xl-8">
|
||||
<!-- Header Section -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h1 class="h3 fw-bold text-center pt-3">
|
||||
{{ t('Account') }}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Account Details -->
|
||||
<div class="border-bottom row flex-column flex-sm-row mx-0 pt-4">
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-start">
|
||||
{{ t('First Name') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-sm-end text-muted">
|
||||
{{ user.first_name }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-bottom row flex-column flex-sm-row mx-0 pt-4">
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-start">
|
||||
{{ t('Last Name') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-sm-end text-muted">
|
||||
{{ user.surname }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-bottom row flex-column flex-sm-row mx-0 pt-4">
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-start">
|
||||
{{ t('Language') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-sm-end text-muted">
|
||||
{{ user.language == 'de' ? 'German' : 'English' }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-bottom row flex-column flex-sm-row mx-0 pt-4">
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-start">
|
||||
{{ t('Email') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-sm-end text-muted">
|
||||
{{ user.email }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-bottom row flex-column flex-sm-row mx-0 pt-4">
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-start">
|
||||
{{ t('Password') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-sm-end text-muted">•••••••••</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Conditional Manager Details -->
|
||||
<div v-if="user.inviter" class="border-bottom row flex-column flex-sm-row mx-0 pt-4">
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-start">
|
||||
{{ t('Manager Name') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-sm-end text-muted">
|
||||
{{ user.inviter.first_name ?? '' }} {{ user.inviter.surname ?? '' }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="user.inviter" class="border-bottom row flex-column flex-sm-row mx-0 pt-4">
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-start">
|
||||
{{ t('Manager Email') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-sm-end text-muted">
|
||||
{{ user.inviter.email ?? '' }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="user.inviter" class="row flex-column flex-sm-row pt-4">
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-start">
|
||||
{{ t('Current Package') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<p class="fw-bold text-sm-end text-muted">
|
||||
{{ showManagerPlan() }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Logout Button -->
|
||||
<div class="account-buttons d-flex justify-content-center pt-5">
|
||||
<nuxt-link
|
||||
:to="localePath('/settings/editaccount')"
|
||||
class="btn btn-primary-custom text-decoration-none"
|
||||
>
|
||||
{{ t('Edit_') }}
|
||||
</nuxt-link>
|
||||
<button class="btn fw-bold btn-outline-dark" @click="logoutNow">
|
||||
{{ t("Log Out") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button type="button" class="btn btn-link position-absolute bottom-0 start-50 translate-middle-x mb-3" @click="showModal = true">
|
||||
{{ t("Delete Account") }}
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="modal fade"
|
||||
tabindex="-1"
|
||||
:class="{ show: showModal }"
|
||||
:style="showModal ? 'display: block;' : 'display: none;'"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
@click.self="closeModal"
|
||||
>
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">{{ t("Delete Account") }}</h5>
|
||||
<button type="button" class="btn-close" @click="closeModal" />
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>{{ t('Delete Account Text') }}</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-dark-custom" @click="closeModal">{{ t('Cancel') }}</button>
|
||||
<button class="btn btn-primary-custom" @click="deleteAccount">{{ t('Delete Account') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hintergrund-Overlay -->
|
||||
<div v-if="showModal" class="modal-backdrop fade show" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
import { mapActions, mapState } from 'pinia'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
|
||||
export default {
|
||||
name: 'Account',
|
||||
setup () {
|
||||
const { t } = useI18n()
|
||||
const localePath = useLocalePath()
|
||||
const userStore = useUserStore()
|
||||
const user = useUserStore().user
|
||||
const router = useRouter()
|
||||
|
||||
return { t, localePath, router, user, userStore }
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showModal: false,
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async logoutNow () {
|
||||
await this.userStore.logout()
|
||||
try {
|
||||
await this.$axios.post('/api/logout')
|
||||
} catch (error) {
|
||||
// Handle the error if needed
|
||||
}
|
||||
this.$router.push(this.localePath('/auth/login'))
|
||||
},
|
||||
closeModal () {
|
||||
this.showModal = false
|
||||
},
|
||||
async deleteAccount () {
|
||||
this.loading = true
|
||||
try {
|
||||
await this.$axios.post('/api/account/delete')
|
||||
await this.userStore.logout()
|
||||
this.$router.push(this.localePath('/auth/login'))
|
||||
this.$toast.success('Account gelöscht. Du wurdest ausgeloggt.')
|
||||
} catch (error) {
|
||||
this.$toast.error('Fehler beim Löschen: ' + (error.response?.data?.message || 'Unbekannter Fehler'))
|
||||
} finally {
|
||||
this.loading = false
|
||||
this.closeModal()
|
||||
}
|
||||
},
|
||||
showManagerPlan () {
|
||||
if (user.value.inviter.current_subscription_plan === 1) {
|
||||
return 'Basic'
|
||||
} else if (user.value.inviter.current_subscription_plan === 2) {
|
||||
return 'Team'
|
||||
} else if (user.value.inviter.current_subscription_plan === 3) {
|
||||
return 'Enterprise'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.btn-primary-custom {
|
||||
background-color: #e9c046;
|
||||
border-color: #e9c046;
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.btn-primary-custom:hover, .btn-primary-custom:focus{
|
||||
background-color: transparent;
|
||||
border-color: #e9c046;
|
||||
color: #e9c046;
|
||||
}
|
||||
|
||||
.account-buttons {
|
||||
gap: 1.5em;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 576px) {
|
||||
.account-buttons {
|
||||
flex-direction: column;
|
||||
gap: 0.75em;
|
||||
}
|
||||
}
|
||||
|
||||
.modal {
|
||||
z-index: 1050;
|
||||
}
|
||||
.modal-backdrop {
|
||||
z-index: 1040;
|
||||
}
|
||||
.btn-link {
|
||||
color: black;
|
||||
transition: 250ms ease-in-out;
|
||||
|
||||
&:hover, &:focus {
|
||||
color: #e9c046;
|
||||
}
|
||||
}
|
||||
</style>
|
66
pages/settings/dataprotection.vue
Normal file
66
pages/settings/dataprotection.vue
Normal file
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-lg-9 col-md-11 col-sm-12 col-xl-8">
|
||||
<h1 class="h3 fw-bold py-3">Datenschutz­erklärung</h1>
|
||||
<div class="row pt-4">
|
||||
<div class="col-12">
|
||||
<h2 class="h4">1. Datenschutz auf einen Blick</h2>
|
||||
<h3 class="h5">Allgemeine Hinweise</h3> <p>Die folgenden Hinweise geben einen einfachen Überblick darüber, was mit Ihren personenbezogenen Daten passiert, wenn Sie diese Website besuchen. Personenbezogene Daten sind alle Daten, mit denen Sie persönlich identifiziert werden können. Ausführliche Informationen zum Thema Datenschutz entnehmen Sie unserer unter diesem Text aufgeführten Datenschutzerklärung.</p>
|
||||
<h3 class="h5">Datenerfassung auf dieser Website</h3>
|
||||
<h4 class="h6">Wer ist verantwortlich für die Datenerfassung auf dieser Website?</h4> <p>Die Datenverarbeitung auf dieser Website erfolgt durch den Websitebetreiber. Dessen Kontaktdaten können Sie dem Abschnitt „Hinweis zur Verantwortlichen Stelle“ in dieser Datenschutzerklärung entnehmen.</p> <h4 class="h6">Wie erfassen wir Ihre Daten?</h4> <p>Ihre Daten werden zum einen dadurch erhoben, dass Sie uns diese mitteilen. Hierbei kann es sich z. B. um Daten handeln, die Sie in ein Kontaktformular eingeben.</p> <p>Andere Daten werden automatisch oder nach Ihrer Einwilligung beim Besuch der Website durch unsere IT-Systeme erfasst. Das sind vor allem technische Daten (z. B. Internetbrowser, Betriebssystem oder Uhrzeit des Seitenaufrufs). Die Erfassung dieser Daten erfolgt automatisch, sobald Sie diese Website betreten.</p> <h4 class="h6">Wofür nutzen wir Ihre Daten?</h4> <p>Ein Teil der Daten wird erhoben, um eine fehlerfreie Bereitstellung der Website zu gewährleisten. Andere Daten können zur Analyse Ihres Nutzerverhaltens verwendet werden.</p> <h4 class="h6">Welche Rechte haben Sie bezüglich Ihrer Daten?</h4> <p>Sie haben jederzeit das Recht, unentgeltlich Auskunft über Herkunft, Empfänger und Zweck Ihrer gespeicherten personenbezogenen Daten zu erhalten. Sie haben außerdem ein Recht, die Berichtigung oder Löschung dieser Daten zu verlangen. Wenn Sie eine Einwilligung zur Datenverarbeitung erteilt haben, können Sie diese Einwilligung jederzeit für die Zukunft widerrufen. Außerdem haben Sie das Recht, unter bestimmten Umständen die Einschränkung der Verarbeitung Ihrer personenbezogenen Daten zu verlangen. Des Weiteren steht Ihnen ein Beschwerderecht bei der zuständigen Aufsichtsbehörde zu.</p> <p>Hierzu sowie zu weiteren Fragen zum Thema Datenschutz können Sie sich jederzeit an uns wenden.</p>
|
||||
<h2 class="h4">2. Hosting</h2>
|
||||
<p>Wir hosten die Inhalte unserer Website bei folgendem Anbieter:</p>
|
||||
<h3 class="h5">Strato</h3> <p>Anbieter ist die Strato AG, Otto-Ostrowski-Straße 7, 10249 Berlin (nachfolgend „Strato“). Wenn Sie unsere Website besuchen, erfasst Strato verschiedene Logfiles inklusive Ihrer IP-Adressen.</p> <p>Weitere Informationen entnehmen Sie der Datenschutzerklärung von Strato: <a href="https://www.strato.de/datenschutz/" target="_blank" rel="noopener noreferrer">https://www.strato.de/datenschutz/</a>.</p> <p>Die Verwendung von Strato erfolgt auf Grundlage von Art. 6 Abs. 1 lit. f DSGVO. Wir haben ein berechtigtes Interesse an einer möglichst zuverlässigen Darstellung unserer Website. Sofern eine entsprechende Einwilligung abgefragt wurde, erfolgt die Verarbeitung ausschließlich auf Grundlage von Art. 6 Abs. 1 lit. a DSGVO und § 25 Abs. 1 TTDSG, soweit die Einwilligung die Speicherung von Cookies oder den Zugriff auf Informationen im Endgerät des Nutzers (z. B. Device-Fingerprinting) im Sinne des TTDSG umfasst. Die Einwilligung ist jederzeit widerrufbar.</p>
|
||||
|
||||
<h4 class="h6">Auftragsverarbeitung</h4> <p>Wir haben einen Vertrag über Auftragsverarbeitung (AVV) zur Nutzung des oben genannten Dienstes geschlossen. Hierbei handelt es sich um einen datenschutzrechtlich vorgeschriebenen Vertrag, der gewährleistet, dass dieser die personenbezogenen Daten unserer Websitebesucher nur nach unseren Weisungen und unter Einhaltung der DSGVO verarbeitet.</p>
|
||||
<h2 class="h4">3. Allgemeine Hinweise und Pflicht­informationen</h2>
|
||||
<h3 class="h5">Datenschutz</h3> <p>Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend den gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung.</p> <p>Wenn Sie diese Website benutzen, werden verschiedene personenbezogene Daten erhoben. Personenbezogene Daten sind Daten, mit denen Sie persönlich identifiziert werden können. Die vorliegende Datenschutzerklärung erläutert, welche Daten wir erheben und wofür wir sie nutzen. Sie erläutert auch, wie und zu welchem Zweck das geschieht.</p> <p>Wir weisen darauf hin, dass die Datenübertragung im Internet (z. B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich.</p>
|
||||
<h3 class="h5">Hinweis zur verantwortlichen Stelle</h3> <p>Die verantwortliche Stelle für die Datenverarbeitung auf dieser Website ist:</p> <p>
|
||||
Robert-Carl Rapp<br>
|
||||
Sindlingerstr. 23,<br>
|
||||
71083 Herrenberg
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Telefon: (+49) 15784037946<br>
|
||||
E-Mail: kontakt@mindboost.team
|
||||
</p>
|
||||
<p>Verantwortliche Stelle ist die natürliche oder juristische Person, die allein oder gemeinsam mit anderen über die Zwecke und Mittel der Verarbeitung von personenbezogenen Daten (z. B. Namen, E-Mail-Adressen o. Ä.) entscheidet.</p>
|
||||
|
||||
<h3 class="h5">Speicherdauer</h3> <p>Soweit innerhalb dieser Datenschutzerklärung keine speziellere Speicherdauer genannt wurde, verbleiben Ihre personenbezogenen Daten bei uns, bis der Zweck für die Datenverarbeitung entfällt. Wenn Sie ein berechtigtes Löschersuchen geltend machen oder eine Einwilligung zur Datenverarbeitung widerrufen, werden Ihre Daten gelöscht, sofern wir keine anderen rechtlich zulässigen Gründe für die Speicherung Ihrer personenbezogenen Daten haben (z. B. steuer- oder handelsrechtliche Aufbewahrungsfristen); im letztgenannten Fall erfolgt die Löschung nach Fortfall dieser Gründe.</p>
|
||||
<h3 class="h5">Allgemeine Hinweise zu den Rechtsgrundlagen der Datenverarbeitung auf dieser Website</h3> <p>Sofern Sie in die Datenverarbeitung eingewilligt haben, verarbeiten wir Ihre personenbezogenen Daten auf Grundlage von Art. 6 Abs. 1 lit. a DSGVO bzw. Art. 9 Abs. 2 lit. a DSGVO, sofern besondere Datenkategorien nach Art. 9 Abs. 1 DSGVO verarbeitet werden. Im Falle einer ausdrücklichen Einwilligung in die Übertragung personenbezogener Daten in Drittstaaten erfolgt die Datenverarbeitung außerdem auf Grundlage von Art. 49 Abs. 1 lit. a DSGVO. Sofern Sie in die Speicherung von Cookies oder in den Zugriff auf Informationen in Ihr Endgerät (z. B. via Device-Fingerprinting) eingewilligt haben, erfolgt die Datenverarbeitung zusätzlich auf Grundlage von § 25 Abs. 1 TTDSG. Die Einwilligung ist jederzeit widerrufbar. Sind Ihre Daten zur Vertragserfüllung oder zur Durchführung vorvertraglicher Maßnahmen erforderlich, verarbeiten wir Ihre Daten auf Grundlage des Art. 6 Abs. 1 lit. b DSGVO. Des Weiteren verarbeiten wir Ihre Daten, sofern diese zur Erfüllung einer rechtlichen Verpflichtung erforderlich sind auf Grundlage von Art. 6 Abs. 1 lit. c DSGVO. Die Datenverarbeitung kann ferner auf Grundlage unseres berechtigten Interesses nach Art. 6 Abs. 1 lit. f DSGVO erfolgen. Über die jeweils im Einzelfall einschlägigen Rechtsgrundlagen wird in den folgenden Absätzen dieser Datenschutzerklärung informiert.</p>
|
||||
<h3 class="h5">Empfänger von personenbezogenen Daten</h3> <p>Im Rahmen unserer Geschäftstätigkeit arbeiten wir mit verschiedenen externen Stellen zusammen. Dabei ist teilweise auch eine Übermittlung von personenbezogenen Daten an diese externen Stellen erforderlich. Wir geben personenbezogene Daten nur dann an externe Stellen weiter, wenn dies im Rahmen einer Vertragserfüllung erforderlich ist, wenn wir gesetzlich hierzu verpflichtet sind (z. B. Weitergabe von Daten an Steuerbehörden), wenn wir ein berechtigtes Interesse nach Art. 6 Abs. 1 lit. f DSGVO an der Weitergabe haben oder wenn eine sonstige Rechtsgrundlage die Datenweitergabe erlaubt. Beim Einsatz von Auftragsverarbeitern geben wir personenbezogene Daten unserer Kunden nur auf Grundlage eines gültigen Vertrags über Auftragsverarbeitung weiter. Im Falle einer gemeinsamen Verarbeitung wird ein Vertrag über gemeinsame Verarbeitung geschlossen.</p>
|
||||
<h3 class="h5">Widerruf Ihrer Einwilligung zur Datenverarbeitung</h3> <p>Viele Datenverarbeitungsvorgänge sind nur mit Ihrer ausdrücklichen Einwilligung möglich. Sie können eine bereits erteilte Einwilligung jederzeit widerrufen. Die Rechtmäßigkeit der bis zum Widerruf erfolgten Datenverarbeitung bleibt vom Widerruf unberührt.</p>
|
||||
<h3 class="h5">Widerspruchsrecht gegen die Datenerhebung in besonderen Fällen sowie gegen Direktwerbung (Art. 21 DSGVO)</h3> <p>WENN DIE DATENVERARBEITUNG AUF GRUNDLAGE VON ART. 6 ABS. 1 LIT. E ODER F DSGVO ERFOLGT, HABEN SIE JEDERZEIT DAS RECHT, AUS GRÜNDEN, DIE SICH AUS IHRER BESONDEREN SITUATION ERGEBEN, GEGEN DIE VERARBEITUNG IHRER PERSONENBEZOGENEN DATEN WIDERSPRUCH EINZULEGEN; DIES GILT AUCH FÜR EIN AUF DIESE BESTIMMUNGEN GESTÜTZTES PROFILING. DIE JEWEILIGE RECHTSGRUNDLAGE, AUF DENEN EINE VERARBEITUNG BERUHT, ENTNEHMEN SIE DIESER DATENSCHUTZERKLÄRUNG. WENN SIE WIDERSPRUCH EINLEGEN, WERDEN WIR IHRE BETROFFENEN PERSONENBEZOGENEN DATEN NICHT MEHR VERARBEITEN, ES SEI DENN, WIR KÖNNEN ZWINGENDE SCHUTZWÜRDIGE GRÜNDE FÜR DIE VERARBEITUNG NACHWEISEN, DIE IHRE INTERESSEN, RECHTE UND FREIHEITEN ÜBERWIEGEN ODER DIE VERARBEITUNG DIENT DER GELTENDMACHUNG, AUSÜBUNG ODER VERTEIDIGUNG VON RECHTSANSPRÜCHEN (WIDERSPRUCH NACH ART. 21 ABS. 1 DSGVO).</p> <p>WERDEN IHRE PERSONENBEZOGENEN DATEN VERARBEITET, UM DIREKTWERBUNG ZU BETREIBEN, SO HABEN SIE DAS RECHT, JEDERZEIT WIDERSPRUCH GEGEN DIE VERARBEITUNG SIE BETREFFENDER PERSONENBEZOGENER DATEN ZUM ZWECKE DERARTIGER WERBUNG EINZULEGEN; DIES GILT AUCH FÜR DAS PROFILING, SOWEIT ES MIT SOLCHER DIREKTWERBUNG IN VERBINDUNG STEHT. WENN SIE WIDERSPRECHEN, WERDEN IHRE PERSONENBEZOGENEN DATEN ANSCHLIESSEND NICHT MEHR ZUM ZWECKE DER DIREKTWERBUNG VERWENDET (WIDERSPRUCH NACH ART. 21 ABS. 2 DSGVO).</p>
|
||||
<h3 class="h5">Beschwerde­recht bei der zuständigen Aufsichts­behörde</h3> <p>Im Falle von Verstößen gegen die DSGVO steht den Betroffenen ein Beschwerderecht bei einer Aufsichtsbehörde, insbesondere in dem Mitgliedstaat ihres gewöhnlichen Aufenthalts, ihres Arbeitsplatzes oder des Orts des mutmaßlichen Verstoßes zu. Das Beschwerderecht besteht unbeschadet anderweitiger verwaltungsrechtlicher oder gerichtlicher Rechtsbehelfe.</p>
|
||||
<h3 class="h5">Recht auf Daten­übertrag­barkeit</h3> <p>Sie haben das Recht, Daten, die wir auf Grundlage Ihrer Einwilligung oder in Erfüllung eines Vertrags automatisiert verarbeiten, an sich oder an einen Dritten in einem gängigen, maschinenlesbaren Format aushändigen zu lassen. Sofern Sie die direkte Übertragung der Daten an einen anderen Verantwortlichen verlangen, erfolgt dies nur, soweit es technisch machbar ist.</p>
|
||||
<h3 class="h5">Auskunft, Berichtigung und Löschung</h3> <p>Sie haben im Rahmen der geltenden gesetzlichen Bestimmungen jederzeit das Recht auf unentgeltliche Auskunft über Ihre gespeicherten personenbezogenen Daten, deren Herkunft und Empfänger und den Zweck der Datenverarbeitung und ggf. ein Recht auf Berichtigung oder Löschung dieser Daten. Hierzu sowie zu weiteren Fragen zum Thema personenbezogene Daten können Sie sich jederzeit an uns wenden.</p>
|
||||
<h3 class="h5">Recht auf Einschränkung der Verarbeitung</h3> <p>Sie haben das Recht, die Einschränkung der Verarbeitung Ihrer personenbezogenen Daten zu verlangen. Hierzu können Sie sich jederzeit an uns wenden. Das Recht auf Einschränkung der Verarbeitung besteht in folgenden Fällen:</p> <ul> <li>Wenn Sie die Richtigkeit Ihrer bei uns gespeicherten personenbezogenen Daten bestreiten, benötigen wir in der Regel Zeit, um dies zu überprüfen. Für die Dauer der Prüfung haben Sie das Recht, die Einschränkung der Verarbeitung Ihrer personenbezogenen Daten zu verlangen.</li> <li>Wenn die Verarbeitung Ihrer personenbezogenen Daten unrechtmäßig geschah/geschieht, können Sie statt der Löschung die Einschränkung der Datenverarbeitung verlangen.</li> <li>Wenn wir Ihre personenbezogenen Daten nicht mehr benötigen, Sie sie jedoch zur Ausübung, Verteidigung oder Geltendmachung von Rechtsansprüchen benötigen, haben Sie das Recht, statt der Löschung die Einschränkung der Verarbeitung Ihrer personenbezogenen Daten zu verlangen.</li> <li>Wenn Sie einen Widerspruch nach Art. 21 Abs. 1 DSGVO eingelegt haben, muss eine Abwägung zwischen Ihren und unseren Interessen vorgenommen werden. Solange noch nicht feststeht, wessen Interessen überwiegen, haben Sie das Recht, die Einschränkung der Verarbeitung Ihrer personenbezogenen Daten zu verlangen.</li> </ul> <p>Wenn Sie die Verarbeitung Ihrer personenbezogenen Daten eingeschränkt haben, dürfen diese Daten – von ihrer Speicherung abgesehen – nur mit Ihrer Einwilligung oder zur Geltendmachung, Ausübung oder Verteidigung von Rechtsansprüchen oder zum Schutz der Rechte einer anderen natürlichen oder juristischen Person oder aus Gründen eines wichtigen öffentlichen Interesses der Europäischen Union oder eines Mitgliedstaats verarbeitet werden.</p>
|
||||
<h3 class="h5">SSL- bzw. TLS-Verschlüsselung</h3> <p>Diese Seite nutzt aus Sicherheitsgründen und zum Schutz der Übertragung vertraulicher Inhalte, wie zum Beispiel Bestellungen oder Anfragen, die Sie an uns als Seitenbetreiber senden, eine SSL- bzw. TLS-Verschlüsselung. Eine verschlüsselte Verbindung erkennen Sie daran, dass die Adresszeile des Browsers von „http://“ auf „https://“ wechselt und an dem Schloss-Symbol in Ihrer Browserzeile.</p> <p>Wenn die SSL- bzw. TLS-Verschlüsselung aktiviert ist, können die Daten, die Sie an uns übermitteln, nicht von Dritten mitgelesen werden.</p>
|
||||
<h3 class="h5">Widerspruch gegen Werbe-E-Mails</h3> <p>Der Nutzung von im Rahmen der Impressumspflicht veröffentlichten Kontaktdaten zur Übersendung von nicht ausdrücklich angeforderter Werbung und Informationsmaterialien wird hiermit widersprochen. Die Betreiber der Seiten behalten sich ausdrücklich rechtliche Schritte im Falle der unverlangten Zusendung von Werbeinformationen, etwa durch Spam-E-Mails, vor.</p>
|
||||
<h2>4. Datenerfassung auf dieser Website</h2>
|
||||
<h3 class="h5">Kontaktformular</h3> <p>Wenn Sie uns per Kontaktformular Anfragen zukommen lassen, werden Ihre Angaben aus dem Anfrageformular inklusive der von Ihnen dort angegebenen Kontaktdaten zwecks Bearbeitung der Anfrage und für den Fall von Anschlussfragen bei uns gespeichert. Diese Daten geben wir nicht ohne Ihre Einwilligung weiter.</p> <p>Die Verarbeitung dieser Daten erfolgt auf Grundlage von Art. 6 Abs. 1 lit. b DSGVO, sofern Ihre Anfrage mit der Erfüllung eines Vertrags zusammenhängt oder zur Durchführung vorvertraglicher Maßnahmen erforderlich ist. In allen übrigen Fällen beruht die Verarbeitung auf unserem berechtigten Interesse an der effektiven Bearbeitung der an uns gerichteten Anfragen (Art. 6 Abs. 1 lit. f DSGVO) oder auf Ihrer Einwilligung (Art. 6 Abs. 1 lit. a DSGVO) sofern diese abgefragt wurde; die Einwilligung ist jederzeit widerrufbar.</p> <p>Die von Ihnen im Kontaktformular eingegebenen Daten verbleiben bei uns, bis Sie uns zur Löschung auffordern, Ihre Einwilligung zur Speicherung widerrufen oder der Zweck für die Datenspeicherung entfällt (z. B. nach abgeschlossener Bearbeitung Ihrer Anfrage). Zwingende gesetzliche Bestimmungen – insbesondere Aufbewahrungsfristen – bleiben unberührt.</p>
|
||||
<h3 class="h5">Anfrage per E-Mail, Telefon oder Telefax</h3> <p>Wenn Sie uns per E-Mail, Telefon oder Telefax kontaktieren, wird Ihre Anfrage inklusive aller daraus hervorgehenden personenbezogenen Daten (Name, Anfrage) zum Zwecke der Bearbeitung Ihres Anliegens bei uns gespeichert und verarbeitet. Diese Daten geben wir nicht ohne Ihre Einwilligung weiter.</p> <p>Die Verarbeitung dieser Daten erfolgt auf Grundlage von Art. 6 Abs. 1 lit. b DSGVO, sofern Ihre Anfrage mit der Erfüllung eines Vertrags zusammenhängt oder zur Durchführung vorvertraglicher Maßnahmen erforderlich ist. In allen übrigen Fällen beruht die Verarbeitung auf unserem berechtigten Interesse an der effektiven Bearbeitung der an uns gerichteten Anfragen (Art. 6 Abs. 1 lit. f DSGVO) oder auf Ihrer Einwilligung (Art. 6 Abs. 1 lit. a DSGVO) sofern diese abgefragt wurde; die Einwilligung ist jederzeit widerrufbar.</p> <p>Die von Ihnen an uns per Kontaktanfragen übersandten Daten verbleiben bei uns, bis Sie uns zur Löschung auffordern, Ihre Einwilligung zur Speicherung widerrufen oder der Zweck für die Datenspeicherung entfällt (z. B. nach abgeschlossener Bearbeitung Ihres Anliegens). Zwingende gesetzliche Bestimmungen – insbesondere gesetzliche Aufbewahrungsfristen – bleiben unberührt.</p>
|
||||
<h2>5. Newsletter</h2>
|
||||
<h3 class="h5">Newsletter­daten</h3> <p>Wenn Sie den auf der Website angebotenen Newsletter beziehen möchten, benötigen wir von Ihnen eine E-Mail-Adresse sowie Informationen, welche uns die Überprüfung gestatten, dass Sie der Inhaber der angegebenen E-Mail-Adresse sind und mit dem Empfang des Newsletters einverstanden sind. Weitere Daten werden nicht bzw. nur auf freiwilliger Basis erhoben. Diese Daten verwenden wir ausschließlich für den Versand der angeforderten Informationen und geben diese nicht an Dritte weiter.</p> <p>Die Verarbeitung der in das Newsletteranmeldeformular eingegebenen Daten erfolgt ausschließlich auf Grundlage Ihrer Einwilligung (Art. 6 Abs. 1 lit. a DSGVO). Die erteilte Einwilligung zur Speicherung der Daten, der E-Mail-Adresse sowie deren Nutzung zum Versand des Newsletters können Sie jederzeit widerrufen, etwa über den „Austragen“-Link im Newsletter. Die Rechtmäßigkeit der bereits erfolgten Datenverarbeitungsvorgänge bleibt vom Widerruf unberührt.</p> <p>Die von Ihnen zum Zwecke des Newsletter-Bezugs bei uns hinterlegten Daten werden von uns bis zu Ihrer Austragung aus dem Newsletter bei uns bzw. dem Newsletterdiensteanbieter gespeichert und nach der Abbestellung des Newsletters oder nach Zweckfortfall aus der Newsletterverteilerliste gelöscht. Wir behalten uns vor, E-Mail-Adressen aus unserem Newsletterverteiler nach eigenem Ermessen im Rahmen unseres berechtigten Interesses nach Art. 6 Abs. 1 lit. f DSGVO zu löschen oder zu sperren.</p> <p>Daten, die zu anderen Zwecken bei uns gespeichert wurden, bleiben hiervon unberührt.</p> <p>Nach Ihrer Austragung aus der Newsletterverteilerliste wird Ihre E-Mail-Adresse bei uns bzw. dem Newsletterdiensteanbieter ggf. in einer Blacklist gespeichert, sofern dies zur Verhinderung künftiger Mailings erforderlich ist. Die Daten aus der Blacklist werden nur für diesen Zweck verwendet und nicht mit anderen Daten zusammengeführt. Dies dient sowohl Ihrem Interesse als auch unserem Interesse an der Einhaltung der gesetzlichen Vorgaben beim Versand von Newslettern (berechtigtes Interesse im Sinne des Art. 6 Abs. 1 lit. f DSGVO). Die Speicherung in der Blacklist ist zeitlich nicht befristet. <strong>Sie können der Speicherung widersprechen, sofern Ihre Interessen unser berechtigtes Interesse überwiegen.</strong></p>
|
||||
<h2>6. Plugins und Tools</h2>
|
||||
<h3 class="h5">Google Fonts (lokales Hosting)</h3> <p>Diese Seite nutzt zur einheitlichen Darstellung von Schriftarten so genannte Google Fonts, die von Google bereitgestellt werden. Die Google Fonts sind lokal installiert. Eine Verbindung zu Servern von Google findet dabei nicht statt.</p> <p>Weitere Informationen zu Google Fonts finden Sie unter <a href="https://developers.google.com/fonts/faq" target="_blank" rel="noopener noreferrer">https://developers.google.com/fonts/faq</a> und in der Datenschutzerklärung von Google: <a href="https://policies.google.com/privacy?hl=de" target="_blank" rel="noopener noreferrer">https://policies.google.com/privacy?hl=de</a>.</p>
|
||||
<h3 class="h5">Font Awesome (lokales Hosting)</h3> <p>Diese Seite nutzt zur einheitlichen Darstellung von Schriftarten Font Awesome. Font Awesome ist lokal installiert. Eine Verbindung zu Servern von Fonticons, Inc. findet dabei nicht statt.</p> <p>Weitere Informationen zu Font Awesome finden Sie in der Datenschutzerklärung für Font Awesome unter: <a href="https://fontawesome.com/privacy" target="_blank" rel="noopener noreferrer">https://fontawesome.com/privacy</a>.</p>
|
||||
<p>Quelle: <a href="https://www.e-recht24.de">https://www.e-recht24.de</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
setup () {
|
||||
const { t } = useI18n()
|
||||
const localePath = useLocalePath()
|
||||
return { t, localePath }
|
||||
}
|
||||
}
|
||||
</script>
|
310
pages/settings/donation.vue
Normal file
310
pages/settings/donation.vue
Normal file
@@ -0,0 +1,310 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-lg-9 col-md-11 col-sm-12 col-xl-8">
|
||||
<h1 class="h3 fw-bold text-center pt-3">
|
||||
{{ t("Donation") }}
|
||||
</h1>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<p class="fw-light text-center py-3">
|
||||
{{ t("DonationHeading") }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-column flex-md-row gap-3">
|
||||
<div class="col-12 py-1 flex-auto">
|
||||
<div class="card" :class="{'active-sub':oneMonth,'sub-card':!oneMonth}" @click="oneMonth=true;twoMonth=false;threeMonth=false">
|
||||
<div class="card-body py-4">
|
||||
<h2 class="text-center fw-bolder">
|
||||
€3.00
|
||||
</h2>
|
||||
<p class="text-center">
|
||||
{{ t("SmallAmount") }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 py-1 flex-auto">
|
||||
<div class="card" :class="{'active-sub':twoMonth,'sub-card':!twoMonth}" @click="twoMonth=true;oneMonth=false;threeMonth=false">
|
||||
<div class="card-body py-4">
|
||||
<h2 class="text-center fw-bolder">
|
||||
€10.00
|
||||
</h2>
|
||||
<p class=" text-center">
|
||||
{{ t("MediumAmount") }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 py-1 flex-auto">
|
||||
<div class="card" :class="{'active-sub':threeMonth,'sub-card':!threeMonth}" @click="threeMonth=true;twoMonth=false;oneMonth=false">
|
||||
<div class="card-body py-4">
|
||||
<h2 class="text-center fw-bolder">
|
||||
€15.00
|
||||
</h2>
|
||||
<p class=" text-center">
|
||||
{{ t("BigAmount") }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row pt-5">
|
||||
<div class="col-12 px-md-5 px-0">
|
||||
<p class="text-center text-muted">
|
||||
{{ t("EndStatement") }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-12 text-end" />
|
||||
</div>
|
||||
<div class="row pt-5 justify-content-center ">
|
||||
<div class="col-12 col-md-6 col-lg-6 text-center">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<p class="fw-medium text-center"><strong>{{ t("bankaccount") }}:</strong><br></p>
|
||||
<p class="fw-light text-center">
|
||||
{{ t("Name") }}: Robert Rapp<br>
|
||||
</p>
|
||||
<p class="fw-light text-center">
|
||||
IBAN: DE42 1001 1001 2629 4590 53
|
||||
<span class="tooltip-container">
|
||||
<i class="fas fa-copy ml-2 cursor-pointer" title="In die Zwischenablage kopieren" @click="copyIBANToClipboard('DE42 1001 1001 2629 4590 53')" />
|
||||
<span class="tooltiptext" :class="{ 'show': showTooltip }">Kopiert!</span>
|
||||
</span>
|
||||
</p>
|
||||
<p class="fw-light text-center">
|
||||
BIC: NTSBDEB1XXX
|
||||
</p>
|
||||
<p class="fw-light text-center">
|
||||
{{ userVerwendungszweck }}
|
||||
<span class="tooltip-container">
|
||||
<i class="fas fa-copy ml-2 cursor-pointer" title="In die Zwischenablage kopieren" @click="copyToClipboard(userVerwendungszweck)" />
|
||||
<span class="tooltiptext" :class="{ 'show': showTooltip1 }">Kopiert!</span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <StripeElements-->
|
||||
<!-- v-if="stripeLoaded"-->
|
||||
<!-- v-slot="{ elements, instance }" ref="elms"-->
|
||||
<!-- :stripe-key="stripeKey"-->
|
||||
<!-- :instance-options="instanceOptions"-->
|
||||
<!-- :elements-options="elementsOptions"-->
|
||||
<!-- >-->
|
||||
<!-- <StripeElement-->
|
||||
<!-- ref="card"-->
|
||||
<!-- :elements="elements"-->
|
||||
<!-- :options="cardOptions"-->
|
||||
<!-- />-->
|
||||
<!-- </StripeElements>-->
|
||||
<!-- <button type="button" class="btn text-white fs-5 col-12 fw-bold py-2" @click="pay" style="background-color: #e9c046">Pay</button>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { mapActions, mapStores } from 'pinia'
|
||||
import { useUserStore } from '~/stores/user'
|
||||
export default {
|
||||
setup () {
|
||||
const { t } = useI18n()
|
||||
const localePath = useLocalePath()
|
||||
const userVerwendungszweck = ref(useUserStore().user.email)
|
||||
const usermail = useUserStore().user.email
|
||||
|
||||
return { t, localePath, userVerwendungszweck, usermail }
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
oneMonth: false,
|
||||
twoMonth: false,
|
||||
threeMonth: false,
|
||||
loading: false,
|
||||
cancel_loading: false,
|
||||
showTooltip: false,
|
||||
showTooltip1: false,
|
||||
subscription: '',
|
||||
form: {
|
||||
type: 'one'
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// ...mapState(useUserStore, ['user']),
|
||||
...mapStores(useUserStore)
|
||||
},
|
||||
mounted () {
|
||||
this.fetchSubscription()
|
||||
},
|
||||
|
||||
methods: {
|
||||
...mapActions(useUserStore, ['updateUser', 'logout']),
|
||||
copyToClipboard (text) {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
this.showTooltip1 = true
|
||||
setTimeout(() => {
|
||||
this.showTooltip1 = false
|
||||
}, 2000) // Tooltip verschwindet nach 2 Sekunden
|
||||
}).catch((err) => {
|
||||
useNuxtApp().$logger.error('Fehler beim Kopieren: ', err)
|
||||
})
|
||||
},
|
||||
copyIBANToClipboard (text) {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
this.showTooltip = true
|
||||
setTimeout(() => {
|
||||
this.showTooltip = false
|
||||
}, 2000) // Tooltip verschwindet nach 2 Sekunden
|
||||
}).catch((err) => {
|
||||
useNuxtApp().$logger.error('Fehler beim Kopieren: ', err)
|
||||
})
|
||||
},
|
||||
updateUserNow () {
|
||||
this.$axios.post('/api/auth/me').then(({ data }) => {
|
||||
this.updateUser(data.user)
|
||||
}).catch(() => {
|
||||
this.logout()
|
||||
this.$router.push(this.localePath('/auth/login'))
|
||||
})
|
||||
},
|
||||
paypal () {
|
||||
window.open('https://www.paypal.com/pools/c/93YzF9GqEP', '_blank')
|
||||
},
|
||||
fetchSubscription () {
|
||||
this.$axios.post('/api/fetch-subscription').then(({ data }) => {
|
||||
this.subscription = data.name
|
||||
if (data.name === 'monthly') {
|
||||
this.oneMonth = true
|
||||
this.twoMonth = false
|
||||
this.threeMonth = false
|
||||
}
|
||||
if (data.name === 'sixmonth') {
|
||||
this.oneMonth = false
|
||||
this.twoMonth = true
|
||||
this.threeMonth = false
|
||||
}
|
||||
if (data.name === 'yearly') {
|
||||
this.oneMonth = false
|
||||
this.twoMonth = false
|
||||
this.threeMonth = true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// export default {
|
||||
// name: 'CardOnly',
|
||||
// data() {
|
||||
// return {
|
||||
// stripeKey: 'pk_test_0S0H9CTYtkhPlArgg4KkPFcZ',
|
||||
// instanceOptions: {},
|
||||
// elementsOptions: {},
|
||||
// cardOptions: {},
|
||||
// stripeLoaded: false,
|
||||
// card: null,
|
||||
// elms: null,
|
||||
// oneMonth:false,
|
||||
// twoMonth:false,
|
||||
// threeMonth:false,
|
||||
// };
|
||||
// },
|
||||
// components: {
|
||||
// StripeElements,
|
||||
// StripeElement,
|
||||
// },
|
||||
// beforeMount() {
|
||||
// const stripePromise = loadStripe(this.stripeKey);
|
||||
// stripePromise.then(() => {
|
||||
// this.stripeLoaded = true;
|
||||
// });
|
||||
// },
|
||||
// methods: {
|
||||
// pay() {
|
||||
// const cardElement = this.$refs.card.stripeElement;
|
||||
//
|
||||
// this.$refs.elms.instance
|
||||
// .createPaymentMethod({ type: 'card', card: cardElement })
|
||||
// .then((result) => {
|
||||
// // useNuxtApp().$logger.log(result);
|
||||
// // useNuxtApp().$logger.log(result.paymentMethod);
|
||||
// this.$axios.post('/api/subscribe', result).then((response) => {
|
||||
// // useNuxtApp().$logger.log(response.data);
|
||||
// });
|
||||
// });
|
||||
// },
|
||||
// },
|
||||
// computed: {
|
||||
//
|
||||
// },
|
||||
// created() {
|
||||
//
|
||||
// },
|
||||
// };
|
||||
</script>
|
||||
<style>
|
||||
.flex-auto {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
.active-sub{
|
||||
background: #E9C046;
|
||||
box-shadow: 0px 0px 16px 1px rgba(108, 97, 97, 0.05);
|
||||
border-radius: 12px;
|
||||
color:white;
|
||||
background-color:#E9C046 !important;
|
||||
}
|
||||
.sub-card{
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0px 0px 16px 1px rgba(108, 97, 97, 0.05);
|
||||
border-radius: 12px;
|
||||
color:black;
|
||||
height: 100%;
|
||||
transition: 250ms ease-in-out;
|
||||
}
|
||||
.sub-card:hover, .sub-card:focus{
|
||||
background: #E9C046;
|
||||
box-shadow: 0px 0px 16px 1px rgba(108, 97, 97, 0.05);
|
||||
border-radius: 12px;
|
||||
color:white;
|
||||
border-color: #E9C046;
|
||||
background-color:#E9C046 !important;
|
||||
}
|
||||
.tooltip-container {
|
||||
margin-left: 10px;
|
||||
font-size: smaller;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tooltiptext {
|
||||
visibility: hidden;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
font-size: 14px;
|
||||
width: auto;
|
||||
background-color: #e9c046;
|
||||
color: #000000;
|
||||
text-align: center;
|
||||
border-radius: 6px;
|
||||
padding: 5px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 125%;
|
||||
left: 20%;
|
||||
margin-left: -30px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.tooltiptext.show {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
632
pages/settings/donation_paddle.vue
Normal file
632
pages/settings/donation_paddle.vue
Normal file
@@ -0,0 +1,632 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-sm-9">
|
||||
<h2 class="fw-bold text-center me-5 pt-5">
|
||||
<span class="float-start" style="cursor: pointer" @click="$router.go(-1)"><i
|
||||
class="fa-solid fa-arrow-left-long"
|
||||
/></span> {{ t("Donation") }}
|
||||
</h2>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h4 class="fw-light text-center pt-3">
|
||||
{{ t("DonationHeading") }}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<section class="pricing py-5">
|
||||
<div class="row">
|
||||
<!-- Basic Tier -->
|
||||
<div class="col-md-4">
|
||||
<div id="basic-plan" class="card mb-5 mb-lg-0" data-plan="starter">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-muted text-uppercase text-center">
|
||||
Basic
|
||||
</h5>
|
||||
<h6 class="card-price text-center">
|
||||
<span class="price" data-price-type="starter">8.00</span><span class="period">/month</span>
|
||||
</h6>
|
||||
<div v-if="currentSubscription() == 1" class="d-flex justify-content-center my-2">
|
||||
<span class="badge bg-warning">Active</span>
|
||||
</div>
|
||||
<hr>
|
||||
<ul class="fa-ul">
|
||||
<li><span class="fa-li"><i class="fas fa-check" /></span>Good for students, employees</li>
|
||||
<li><span class="fa-li"><i class="fas fa-check" /></span>Full access to app</li>
|
||||
<li><span class="fa-li"><i class="fas fa-check" /></span>3 Professional soundscapes</li>
|
||||
<li><span class="fa-li"><i class="fas fa-check" /></span>mindboost@technology</li>
|
||||
<li><span class="fa-li"><i class="fas fa-check" /></span>30 Days Trial</li>
|
||||
<li>
|
||||
<div class="pricing-toggle my-2 d-flex align-items-center">
|
||||
<div class="me-3">
|
||||
<input
|
||||
id="starter-month"
|
||||
type="radio"
|
||||
class="me-1"
|
||||
name="cycle-starter"
|
||||
value="month"
|
||||
:checked="currentSubscription() === 1 && dataStore.user.montly === '1' || currentSubscription() !== 1"
|
||||
>
|
||||
<label for="starter-month" class="form-check-label">Monthly</label>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
id="starter-year"
|
||||
type="radio"
|
||||
class="me-1"
|
||||
name="cycle-starter"
|
||||
:checked="currentSubscription() == 1 && dataStore.user.yearly === '1'"
|
||||
value="year"
|
||||
>
|
||||
<label for="starter-year" class="form-check-label">Yearly <sup>save 20%</sup></label>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="d-grid">
|
||||
<span v-if="isInvited">
|
||||
<div class="row">
|
||||
<button class="btn btn-warning text-uppercase buy-now" @click="showManagerPlan()">Buy
|
||||
Now</button>
|
||||
</div>
|
||||
</span>
|
||||
<span v-else>
|
||||
<div class="row">
|
||||
<button
|
||||
class="btn btn-warning text-uppercase buy-now"
|
||||
:disabled="currentSubscription() === 1"
|
||||
>Active</button>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Team Tier -->
|
||||
<div class="col-md-4">
|
||||
<div id="team-plan" class="card mb-5 mb-lg-0" data-plan="pro">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-muted text-uppercase text-center">
|
||||
Team
|
||||
</h5>
|
||||
<h6 class="card-price text-center">
|
||||
<span class="price" data-price-type="pro">5</span><span class="period">/month</span>
|
||||
</h6>
|
||||
<div v-if="currentSubscription() == 2" class="d-flex justify-content-center my-2">
|
||||
<span class="badge bg-warning">Active</span>
|
||||
</div>
|
||||
<hr>
|
||||
<ul class="fa-ul">
|
||||
<li>
|
||||
<span class="fa-li"><i class="fas fa-check" /></span>Good for colleagues, groups, teams,
|
||||
departments
|
||||
</li>
|
||||
<li><span class="fa-li"><i class="fas fa-check" /></span>Full access to app</li>
|
||||
<li><span class="fa-li"><i class="fas fa-check" /></span>3 Professional soundscapes</li>
|
||||
<li><span class="fa-li"><i class="fas fa-check" /></span>mindboost@technology</li>
|
||||
<li><span class="fa-li"><i class="fas fa-plus" /></span>Individual User Management</li>
|
||||
<li><span class="fa-li"><i class="fas fa-plus" /></span>Flexible Trial Version</li>
|
||||
<li><span class="fa-li"><i class="fas fa-plus" /></span>Coherent invoicing</li>
|
||||
<li><span class="fa-li"><i class="fas fa-plus" /></span> + Basic Per User</li>
|
||||
<li><span class="fa-li"><i class="fas fa-plus" /></span>30 Days Trial</li>
|
||||
<li>
|
||||
<div class="pricing-toggle my-2 d-flex align-items-center">
|
||||
<div class="me-3">
|
||||
<input
|
||||
id="pro-month"
|
||||
type="radio"
|
||||
class="me-1"
|
||||
name="cycle-pro"
|
||||
value="month"
|
||||
:checked="currentSubscription() === 2 && dataStore.user.montly === '1' || currentSubscription() !== 2"
|
||||
>
|
||||
<label for="pro-month" class="form-check-label">Monthly</label>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
id="pro-year"
|
||||
type="radio"
|
||||
class="me-1"
|
||||
name="cycle-pro"
|
||||
:checked="currentSubscription() === 2 && dataStore.user.yearly === '1'"
|
||||
value="year"
|
||||
>
|
||||
<label for="pro-year" class="form-check-label">Yearly <sup>save 20%</sup></label>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="d-grid">
|
||||
<span v-if="isInvited">
|
||||
<div class="row">
|
||||
<button class="btn btn-warning text-uppercase team-plan" @click="showManagerPlan()">Buy
|
||||
Now</button>
|
||||
</div>
|
||||
</span>
|
||||
<span v-else>
|
||||
<div class="row">
|
||||
<button
|
||||
class="btn btn-warning text-uppercase team-plan"
|
||||
:disabled="currentSubscription() === 2"
|
||||
>Active</button>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Enterprise Tier -->
|
||||
<div class="col-md-4">
|
||||
<div id="enterprise-plan" class="card" data-plan="enterprise">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-muted text-uppercase text-center">
|
||||
Enterprise
|
||||
</h5>
|
||||
<h6 class="card-price text-center">
|
||||
<span>Depends</span>
|
||||
</h6>
|
||||
<div v-if="currentSubscription() == 3" class="d-flex justify-content-center my-2">
|
||||
<span class="badge bg-warning">Active</span>
|
||||
</div>
|
||||
<hr>
|
||||
<ul class="fa-ul">
|
||||
<li><span class="fa-li"><i class="fas fa-check" /></span>Good For Enterprise > 200</li>
|
||||
<li><span class="fa-li"><i class="fas fa-check" /></span>Full access to app</li>
|
||||
<li><span class="fa-li"><i class="fas fa-check" /></span>3 Professional soundscapes</li>
|
||||
<li><span class="fa-li"><i class="fas fa-check" /></span>mindboost@technology</li>
|
||||
<li><span class="fa-li"><i class="fas fa-check" /></span>Individual User Management</li>
|
||||
<li><span class="fa-li"><i class="fas fa-check" /></span>Flexible Trial Version</li>
|
||||
<li><span class="fa-li"><i class="fas fa-check" /></span>Coherent invoicing</li>
|
||||
<li><span class="fa-li"><i class="fas fa-plus" /></span>Dedicated Partnership</li>
|
||||
<li><span class="fa-li"><i class="fas fa-plus" /></span>In-person Onboarding</li>
|
||||
<li><span class="fa-li"><i class="fas fa-plus" /></span>Individual Pricing</li>
|
||||
<li><span class="fa-li"><i class="fas fa-plus" /></span>30 Days Trial</li>
|
||||
<li>
|
||||
<div class="pricing-toggle my-2 d-flex align-items-center">
|
||||
<div class="me-3">
|
||||
<input
|
||||
id="enterprise-month"
|
||||
type="radio"
|
||||
class="me-1"
|
||||
name="cycle-enterprise"
|
||||
value="month"
|
||||
checked
|
||||
>
|
||||
<label for="enterprise-month" class="form-check-label">Monthly</label>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
id="enterprise-year"
|
||||
type="radio"
|
||||
class="me-1"
|
||||
name="cycle-enterprise"
|
||||
value="year"
|
||||
>
|
||||
<label for="enterprise-year" class="form-check-label">Yearly <sup>save 20%</sup></label>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="d-grid">
|
||||
<span v-if="isInvited">
|
||||
<div class="row">
|
||||
<button type="button" class="btn btn-warning text-uppercase" @click="showManagerPlan()">
|
||||
contact us
|
||||
</button>
|
||||
</div>
|
||||
</span>
|
||||
<span v-else>
|
||||
<div class="row">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-warning text-uppercase"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#exampleModal"
|
||||
>
|
||||
contact us
|
||||
</button>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<!-- Modal for enterprise contact us form -->
|
||||
<div
|
||||
id="exampleModal"
|
||||
class="modal fade"
|
||||
tabindex="-1"
|
||||
aria-labelledby="exampleModalLabel"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 id="exampleModalLabel" class="modal-title fs-5">
|
||||
Contact Us
|
||||
</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" />
|
||||
</div>
|
||||
<form @submit.prevent="submitForm">
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Name</label>
|
||||
<input
|
||||
id="name"
|
||||
v-model="contact_form.name"
|
||||
type="text"
|
||||
class="form-control"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="companyName" class="form-label">Company Name</label>
|
||||
<input
|
||||
id="companyName"
|
||||
v-model="contact_form.company_name"
|
||||
type="text"
|
||||
class="form-control"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="message" class="form-label">Message</label>
|
||||
<textarea id="message" v-model="contact_form.message" class="form-control" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-warning text-uppercase">
|
||||
Send Message
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapActions, mapStores } from 'pinia'
|
||||
import { useUserStore } from '~/stores/user'
|
||||
// entery point
|
||||
export default {
|
||||
components: { },
|
||||
setup () {
|
||||
const { t } = useI18n()
|
||||
const localePath = useLocalePath()
|
||||
const dataStore = useUserStore() // Initialize store in setup()
|
||||
|
||||
return {
|
||||
t,
|
||||
localePath,
|
||||
dataStore
|
||||
}
|
||||
},
|
||||
// dara store
|
||||
data () {
|
||||
return {
|
||||
oneMonth: false,
|
||||
twoMonth: false,
|
||||
threeMonth: false,
|
||||
loading: false,
|
||||
cancel_loading: false,
|
||||
subscription: '',
|
||||
form: {
|
||||
type: 'one'
|
||||
},
|
||||
contact_form: {
|
||||
name: '',
|
||||
company_name: '',
|
||||
email: 'dowhf@access.bro', // Removed direct reference to userStore
|
||||
message: ''
|
||||
},
|
||||
isInvited: 0,
|
||||
isManagerPlan: 0
|
||||
}
|
||||
},
|
||||
// computed
|
||||
computed: {
|
||||
...mapStores(useUserStore)
|
||||
},
|
||||
// mounted
|
||||
mounted () {
|
||||
const urlBackend = useRuntimeConfig().public.BACKEND_URL || 'https://b.mindboost.team'
|
||||
this.fetchSubscription()
|
||||
this.GetManagerDetails()
|
||||
|
||||
if (window.Paddle) {
|
||||
// Initialize Paddle
|
||||
Paddle.Environment.set('sandbox')
|
||||
Paddle.Initialize({
|
||||
token: 'test_27bb608597d1a4d75fe1bce2be7',
|
||||
eventCallback: async function (data) {
|
||||
if (data.name === 'checkout.completed') {
|
||||
// useNuxtApp().$logger.log(data)
|
||||
try {
|
||||
const response = await axios.post(urlBackend + '/api/paddle-webhook', data)
|
||||
// useNuxtApp().$logger.log('this is subscription data data', response)
|
||||
// Access the Pinia store and update the user data
|
||||
const userStore = useUserStore()
|
||||
userStore.updateUser(response.data.user)
|
||||
} catch (error) {
|
||||
// useNuxtApp().$logger.log(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
// Product definitions for each plan
|
||||
const products = {
|
||||
starter: {
|
||||
productId: 'pro_01j508hk3rp5f5g68n7tqv1thd',
|
||||
monthPriceId: 'pri_01j508ssstj4n6xra9j8ymr3d1',
|
||||
yearPriceId: 'pri_01j508x0rwntqs581rj3xfx49n'
|
||||
},
|
||||
pro: {
|
||||
productId: 'pro_01j5090jy3jkf4w9vr0j279fm5',
|
||||
monthPriceId: 'pri_01j50947nd6t9ztgsrq5h6fsmx',
|
||||
yearPriceId: 'pri_01j5097bzyp9zrevw0nsagb477'
|
||||
},
|
||||
enterprise: {
|
||||
productId: 'pro_01j509nre47wbdtmqmd6x098s5',
|
||||
monthPriceId: 'pri_01j509qknvfx3hv0459kpkvvar',
|
||||
yearPriceId: 'pri_01j509ryg22rzs0ahwrb2vwzhq'
|
||||
}
|
||||
}
|
||||
|
||||
// Functions to handle pricing updates
|
||||
const updateBasicPlan = () => {
|
||||
const plan = 'starter'
|
||||
const cycle = document.querySelector('input[name="cycle-starter"]:checked').value
|
||||
const priceId = cycle === 'month' ? products[plan].monthPriceId : products[plan].yearPriceId
|
||||
Paddle.PricePreview({ items: [{ quantity: 1, priceId }] })
|
||||
.then((result) => {
|
||||
document.querySelector('#basic-plan .price').textContent = result.data.details.lineItems[0].formattedTotals.subtotal
|
||||
document.querySelector('#basic-plan .period').textContent = cycle === 'month' ? '/month' : '/year'
|
||||
})
|
||||
}
|
||||
|
||||
// Update the basic plan pricing on page load
|
||||
const updateTeamPlan = () => {
|
||||
const plan = 'pro'
|
||||
const cycle = document.querySelector('input[name="cycle-pro"]:checked').value
|
||||
const priceId = cycle === 'month' ? products[plan].monthPriceId : products[plan].yearPriceId
|
||||
Paddle.PricePreview({ items: [{ quantity: 5, priceId }] })
|
||||
.then((result) => {
|
||||
document.querySelector('#team-plan .price').textContent = result.data.details.lineItems[0].formattedTotals.subtotal
|
||||
document.querySelector('#team-plan .period').textContent = cycle === 'month' ? '/month' : '/year'
|
||||
})
|
||||
}
|
||||
|
||||
// Update the enterprise plan pricing on page load
|
||||
const updateEnterprisePlan = () => {
|
||||
const plan = 'enterprise'
|
||||
const cycle = document.querySelector('input[name="cycle-enterprise"]:checked').value
|
||||
const priceId = cycle === 'month' ? products[plan].monthPriceId : products[plan].yearPriceId
|
||||
Paddle.PricePreview({ items: [{ quantity: 1, priceId }] })
|
||||
.then((result) => {
|
||||
document.querySelector('#enterprise-plan .price').textContent = result.data.details.lineItems[0].formattedTotals.subtotal
|
||||
document.querySelector('#enterprise-plan .period').textContent = cycle === 'month' ? '/month' : '/year'
|
||||
})
|
||||
}
|
||||
|
||||
// Event handlers for plan and cycle changes
|
||||
const handlePlanChange = (event) => {
|
||||
const plan = event.target.closest('.card').getAttribute('data-plan')
|
||||
if (plan === 'starter') {
|
||||
updateBasicPlan()
|
||||
} else if (plan === 'pro') {
|
||||
updateTeamPlan()
|
||||
} else if (plan === 'enterprise') {
|
||||
updateEnterprisePlan()
|
||||
}
|
||||
}
|
||||
|
||||
// Set event listeners for plan and cycle changes
|
||||
document.querySelectorAll('input[name^="cycle-"]').forEach((input) => {
|
||||
input.addEventListener('change', handlePlanChange)
|
||||
})
|
||||
|
||||
// Event handlers for buy now buttons
|
||||
document.querySelectorAll('.buy-now').forEach((button) => {
|
||||
button.addEventListener('click', () => {
|
||||
const plan = button.closest('.card').getAttribute('data-plan')
|
||||
const cycle = document.querySelector(`input[name="cycle-${plan}"]:checked`).value
|
||||
const priceId = cycle === 'month' ? products[plan].monthPriceId : products[plan].yearPriceId
|
||||
Paddle.Checkout.open({
|
||||
items: [{ priceId, quantity: 1 }],
|
||||
customer: {
|
||||
email: this.dataStore.user.email,
|
||||
address: { countryCode: 'PK', postalCode: '59351' }
|
||||
},
|
||||
source: window.location.href
|
||||
})
|
||||
})
|
||||
})
|
||||
// Event handlers for team-plan class
|
||||
document.querySelectorAll('.team-plan').forEach((button) => {
|
||||
button.addEventListener('click', () => {
|
||||
const plan = button.closest('.card').getAttribute('data-plan')
|
||||
const cycle = document.querySelector(`input[name="cycle-${plan}"]:checked`).value
|
||||
const priceId = cycle === 'month' ? products[plan].monthPriceId : products[plan].yearPriceId
|
||||
Paddle.Checkout.open({
|
||||
items: [{ priceId, quantity: 5 }],
|
||||
customer: {
|
||||
email: this.dataStore.user.email,
|
||||
address: { countryCode: 'PK', postalCode: '59351' }
|
||||
},
|
||||
source: window.location.href
|
||||
})
|
||||
})
|
||||
})
|
||||
// Initialize prices
|
||||
updateBasicPlan()
|
||||
updateTeamPlan()
|
||||
updateEnterprisePlan()
|
||||
}
|
||||
},
|
||||
// ======================= methods =======================
|
||||
methods: {
|
||||
// check user plan
|
||||
isDisabled () {
|
||||
const dataStore = useUserStore()
|
||||
const userasdf = dataStore
|
||||
// useNuxtApp().$logger.log('store', user); // Debugging
|
||||
return !(userasdf.user.team_subscription_plan === '1' ||
|
||||
userasdf.user.enterprise_subscription_plan === '1') &&
|
||||
(userasdf.user.basic_subscription_plan !== '0')
|
||||
},
|
||||
// get user current plan
|
||||
currentSubscription () {
|
||||
const dataStore = useUserStore()
|
||||
const userasdf = dataStore
|
||||
return (userasdf.user.current_subscription_plan)
|
||||
},
|
||||
/**
|
||||
* showManagerPlan in toster form
|
||||
*/
|
||||
showManagerPlan () {
|
||||
let managerPlan = '' // Changed from const to let
|
||||
if (this.isManagerPlan === 1) {
|
||||
managerPlan = 'Basic'
|
||||
} else if (this.isManagerPlan === 2) {
|
||||
managerPlan = 'Team'
|
||||
} else if (this.isManagerPlan === 3) {
|
||||
managerPlan = 'Enterprise'
|
||||
}
|
||||
|
||||
this.$toast.success(`Manager already has the ${managerPlan} plan`) // Fixed typo
|
||||
},
|
||||
/**
|
||||
* Submits the contact form to the server
|
||||
*/
|
||||
async submitForm () {
|
||||
try {
|
||||
await axios.post(urlBackend + '/api/enterprise-plan-contact', this.contact_form)
|
||||
// useNuxtApp().$logger.log('Success:', response.data)
|
||||
Swal.fire({
|
||||
title: 'Good job!',
|
||||
text: 'Message sent successfully! Support team will contact you soon.',
|
||||
icon: 'success'
|
||||
})
|
||||
} catch (error) {
|
||||
// useNuxtApp().$logger.error('Error:', error.response);
|
||||
this.$toast.error('Oops, something went wrong!')
|
||||
}
|
||||
},
|
||||
...mapActions(useUserStore, ['updateUser', 'logout']),
|
||||
updateUserNow () {
|
||||
this.$axios.post('/api/auth/me').then(({ data }) => {
|
||||
this.updateUser(data.user)
|
||||
}).catch(() => {
|
||||
this.logout()
|
||||
this.$router.push(this.localePath('/auth/login'))
|
||||
})
|
||||
},
|
||||
paypal () {
|
||||
window.open('https://www.paypal.com/pools/c/93YzF9GqEP', '_blank')
|
||||
},
|
||||
fetchSubscription () {
|
||||
this.$axios.post('/api/fetch-subscription').then(({ data }) => {
|
||||
this.subscription = data.name
|
||||
this.oneMonth = data.name === 'monthly'
|
||||
this.twoMonth = data.name === 'sixmonth'
|
||||
this.threeMonth = data.name === 'yearly'
|
||||
})
|
||||
},
|
||||
async GetManagerDetails () {
|
||||
const userStore = useUserStore()
|
||||
if (userStore.user.inviter_id) {
|
||||
const response = await axios.post(urlBackend + '/api/fetch-manger-detail', { manager_id: userStore.user.inviter_id })
|
||||
// useNuxtApp().$logger.log('manager_id', response.data.data)
|
||||
this.isInvited = 1
|
||||
// useNuxtApp().$logger.log('response.data.data.inviter_id', response.data.data.inviter_id)
|
||||
this.isManagerPlan = response.data.data.current_subscription_plan
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.active-sub {
|
||||
background: #E9C046;
|
||||
box-shadow: 0px 0px 16px 1px rgba(108, 97, 97, 0.05);
|
||||
border-radius: 12px;
|
||||
color: white;
|
||||
background-color: #E9C046 !important;
|
||||
}
|
||||
|
||||
.sub-card {
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0px 0px 16px 1px rgba(108, 97, 97, 0.05);
|
||||
border-radius: 12px;
|
||||
color: black;
|
||||
}
|
||||
|
||||
/* style for plan cards */
|
||||
.pricing .card {
|
||||
border: none;
|
||||
border-radius: 1rem;
|
||||
transition: all 0.2s;
|
||||
box-shadow: 0 0.5rem 1rem 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.pricing hr {
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
|
||||
.pricing .card-title {
|
||||
margin: 0.5rem 0;
|
||||
font-size: 0.9rem;
|
||||
letter-spacing: .1rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.pricing .card-price {
|
||||
font-size: 3rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pricing .card-price .period {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.pricing ul li {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.pricing .text-muted {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.pricing .btn {
|
||||
font-size: 80%;
|
||||
border-radius: 5rem;
|
||||
letter-spacing: .1rem;
|
||||
font-weight: bold;
|
||||
padding: 1rem;
|
||||
opacity: 0.7;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
/* Hover Effects on Card */
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.pricing .card:hover {
|
||||
margin-top: -.25rem;
|
||||
margin-bottom: .25rem;
|
||||
box-shadow: 0 0.5rem 1rem 0 rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.pricing .card:hover .btn {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
175
pages/settings/editaccount.vue
Normal file
175
pages/settings/editaccount.vue
Normal file
@@ -0,0 +1,175 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-lg-9 col-md-11 col-sm-12 col-xl-8">
|
||||
<h1 class="h3 fw-bold text-center py-3">
|
||||
<span class="float-start" style="cursor: pointer" @click="$router.go(-1)"><i class="fa-solid fa-arrow-left-long" /></span>
|
||||
{{ t("Edit Account") }}
|
||||
</h1>
|
||||
<div class="row pt-4">
|
||||
<div class="col-12">
|
||||
<form @submit.prevent="validateAndSave">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<label for="firstname" class="text-muted ">{{ t("First Name") }} </label>
|
||||
<input id="firstname" v-model="form.first_name" type="text" class="form-control" :placeholder="t('First Name')">
|
||||
<div v-if="errors.first_name" class="invalid-feedback d-block">
|
||||
{{ errors.first_name[0] }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row pt-3">
|
||||
<div class="col-12">
|
||||
<label for="surname" class="text-muted ">{{ t("Surname") }} </label>
|
||||
<input id="surname" v-model="form.surname" type="text" class="form-control" :placeholder="t('Surname')">
|
||||
<div v-if="errors.surname" class="invalid-feedback d-block">
|
||||
{{ errors.surname[0] }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row pt-3">
|
||||
<div class="col-12">
|
||||
<label for="email" class="text-muted ">{{ t("Email") }} </label>
|
||||
<input id="email" v-model="form.email" type="email" class="form-control" :placeholder="t('Email')">
|
||||
<div v-if="errors.email" class="invalid-feedback d-block">
|
||||
{{ errors.email[0] }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row pt-3">
|
||||
<div class="col-12 col-sm-6">
|
||||
<label for="password" class="text-muted ">{{ t("Password") }} </label>
|
||||
<input id="password" v-model="form.password" type="password" class="form-control" placeholder="***">
|
||||
<div v-if="errors.password" class="invalid-feedback d-block">
|
||||
{{ errors.password[0] }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<label for="confirm-password" class="text-muted ">{{ t("Confirm Password") }} </label>
|
||||
<input id="confirm-password" v-model="form.confirm_password" type="password" class="form-control" placeholder="***">
|
||||
<div v-if="errors.confirm_password" class="invalid-feedback d-block">
|
||||
{{ errors.confirm_password[0] }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row pt-3">
|
||||
<div class="col-12">
|
||||
<label for="language" class="text-muted ">{{ t("Language") }} </label>
|
||||
<select id="language" v-model="form.language" class="form-select" @change="changeLanguage">
|
||||
<option value="en">
|
||||
English
|
||||
</option>
|
||||
<option value="de">
|
||||
German
|
||||
</option>
|
||||
</select>
|
||||
<div v-if="errors.language" class="invalid-feedback d-block">
|
||||
{{ errors.language[0] }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row pt-5 g-2">
|
||||
<button type="submit" class="btn btn-primary-custom mx-auto col-4" style="background-color: #e9c046">
|
||||
{{ t("Save Changes") }} <div v-if="loading" class="spinner-border spinner-border-sm" role="status">
|
||||
<span class="sr-only">{{ t("Loading...") }} </span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapActions } from 'pinia'
|
||||
// import Index from '~/pages/index.vue'
|
||||
import { useUserStore } from '~/stores/user'
|
||||
export default {
|
||||
name: 'EditAccount',
|
||||
components: {
|
||||
// Index
|
||||
},
|
||||
|
||||
setup () {
|
||||
const { t } = useI18n()
|
||||
const localePath = useLocalePath()
|
||||
const switchLocalePath = useSwitchLocalePath()
|
||||
const changeLanguage = (locale) => {
|
||||
// useNuxtApp().$logger.log('switch', locale)
|
||||
useRouter().push(switchLocalePath(locale))
|
||||
|
||||
// i18n.global.locale.value=
|
||||
}
|
||||
return { t, localePath, changeLanguage }
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
form: {
|
||||
first_name: '',
|
||||
surname: '',
|
||||
email: 'email',
|
||||
password: '',
|
||||
confirm_password: '',
|
||||
language: 'de'
|
||||
},
|
||||
errors: []
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(useUserStore, ['user'])
|
||||
},
|
||||
mounted () {
|
||||
this.form.first_name = this.user.first_name
|
||||
this.form.email = this.user.email
|
||||
this.form.surname = this.user.surname
|
||||
this.form.language = this.user.language
|
||||
},
|
||||
methods: {
|
||||
|
||||
...mapActions(useUserStore, ['updateUser']),
|
||||
|
||||
validateAndSave () {
|
||||
this.errors = []
|
||||
|
||||
// Wenn Passwort leer ist, lassen wir die Prüfung zu – Änderung des Passworts ist optional
|
||||
if (this.form.password !== '') {
|
||||
if (this.form.password !== this.form.confirm_password) {
|
||||
this.errors.confirm_password = ['Passwörter stimmen nicht überein.']
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.saveUser()
|
||||
},
|
||||
saveUser () {
|
||||
this.loading = true
|
||||
|
||||
const payload = { ...this.form }
|
||||
if (!payload.password) { delete payload.password }
|
||||
if (!payload.confirm_password) { delete payload.confirm_password }
|
||||
|
||||
this.$axios.post('/api/account/update', payload).then(({ data }) => {
|
||||
this.changeLanguage(this.form.language)
|
||||
this.loading = false
|
||||
if (data.success) {
|
||||
this.$toast.success(data.message)
|
||||
this.updateUser(data.user)
|
||||
this.$router.push(this.localePath('/settings/account'))
|
||||
}
|
||||
}).catch((error) => {
|
||||
this.loading = false
|
||||
this.$toast.error('Something wrong while saving...')
|
||||
if (error.response.status === 422) {
|
||||
this.errors = error.response.data.errors
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
238
pages/settings/faq.vue
Normal file
238
pages/settings/faq.vue
Normal file
@@ -0,0 +1,238 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row justify-content-center m-0 p-0">
|
||||
<div class="col-12 col-lg-9 col-md-11 col-sm-12 col-xl-8">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="me-4">
|
||||
<h1 class="h3 fw-bold text-center py-3">
|
||||
{{ t("FAQ") }}
|
||||
</h1>
|
||||
</div>
|
||||
<div id="accordionExample" class="accordion">
|
||||
<div class="accordion-item">
|
||||
<h2 id="headingOne" class="accordion-header">
|
||||
<button
|
||||
class="accordion-button fw-semibold"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#collapseOne"
|
||||
aria-expanded="true"
|
||||
aria-controls="collapseOne"
|
||||
>
|
||||
{{ t("question1") }}
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseOne" class="accordion-collapse collapse show" aria-labelledby="headingOne" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body">
|
||||
<p>
|
||||
{{ t("answer_part_1") }}
|
||||
<br>{{ t("answer_part_2") }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<h2 id="headingTwo" class="accordion-header">
|
||||
<button
|
||||
class="accordion-button fw-semibold collapsed"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#collapseTwo"
|
||||
aria-expanded="false"
|
||||
aria-controls="collapseTwo"
|
||||
>
|
||||
{{ t("question_2") }}
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseTwo" class="accordion-collapse collapse" aria-labelledby="headingTwo" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body">
|
||||
{{ t("answer_2") }} 01
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<h2 id="headingThree" class="accordion-header">
|
||||
<button
|
||||
class="accordion-button fw-semibold collapsed"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#collapseThree"
|
||||
aria-expanded="false"
|
||||
aria-controls="collapseThree"
|
||||
>
|
||||
{{ t("question_3") }}
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseThree" class="accordion-collapse collapse" aria-labelledby="headingThree" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body">
|
||||
{{ t("answer_3") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<h2 id="headingFour" class="accordion-header">
|
||||
<button
|
||||
class="accordion-button fw-semibold collapsed"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#collapseFour"
|
||||
aria-expanded="false"
|
||||
aria-controls="collapseThree"
|
||||
>
|
||||
{{ t("question_4") }}
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseFour" class="accordion-collapse collapse" aria-labelledby="headingThree" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body">
|
||||
{{ t("answer_4") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<h2 id="headingFive" class="accordion-header">
|
||||
<button
|
||||
class="accordion-button fw-semibold collapsed"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#collapseFive"
|
||||
aria-expanded="false"
|
||||
aria-controls="collapseThree"
|
||||
>
|
||||
{{ t("question_5") }}
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseFive" class="accordion-collapse collapse" aria-labelledby="headingThree" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body">
|
||||
{{ t("answer_5") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 id="headingsix" class="accordion-header">
|
||||
<button
|
||||
class="accordion-button fw-semibold collapsed"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#collapsesix"
|
||||
aria-expanded="false"
|
||||
aria-controls="collapseThree"
|
||||
>
|
||||
{{ t("question_6") }}
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapsesix" class="accordion-collapse collapse" aria-labelledby="headingThree" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body">
|
||||
{{ t("answer_6") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<h2 id="headingsaven" class="accordion-header">
|
||||
<button
|
||||
class="accordion-button fw-semibold collapsed"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#collapseseven"
|
||||
aria-expanded="false"
|
||||
aria-controls="collapseThree"
|
||||
>
|
||||
{{ t("question_7") }}
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseseven" class="accordion-collapse collapse" aria-labelledby="headingThree" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body">
|
||||
{{ t("answer_7") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<h2 id="headingeight" class="accordion-header">
|
||||
<button
|
||||
class="accordion-button fw-semibold collapsed"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#collapseeight"
|
||||
aria-expanded="false"
|
||||
aria-controls="collapseThree"
|
||||
>
|
||||
{{ t("question_8") }}
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseeight" class="accordion-collapse collapse" aria-labelledby="headingThree" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body">
|
||||
<ol class="px-0 mx-0">
|
||||
<li>{{ t("answer_8_1") }}</li>
|
||||
<li>{{ t("answer_8_2") }}</li>
|
||||
<li>{{ t("answer_8_3") }}</li>
|
||||
<li>{{ t("answer_8_4") }}</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<h2 id="headingnine" class="accordion-header">
|
||||
<button
|
||||
class="accordion-button fw-semibold collapsed"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#collapsenine"
|
||||
aria-expanded="false"
|
||||
aria-controls="collapseThree"
|
||||
>
|
||||
{{ t("question_9") }}
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapsenine" class="accordion-collapse collapse" aria-labelledby="headingThree" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body">
|
||||
{{ t("answer_9") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Subscription',
|
||||
setup () {
|
||||
const { t } = useI18n()
|
||||
const localePath = useLocalePath()
|
||||
return { t, localePath }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.accordion-item {
|
||||
border: none;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
.accordion-button {
|
||||
background-color: rgb(244, 245, 247) !important;
|
||||
}
|
||||
.accordion-button:focus {
|
||||
z-index: 3;
|
||||
border:none;
|
||||
outline: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
.accordion-button:not(.open) {
|
||||
color: black;
|
||||
box-shadow: none;
|
||||
background-color: rgb(244, 245, 247) !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
.accordion-collapse {
|
||||
background-color: rgb(244, 245, 247);
|
||||
}
|
||||
.accordion-button:not(.open):hover, .accordion-button:not(.open):focus {
|
||||
background-color: rgb(226, 229, 234) !important;
|
||||
}
|
||||
</style>
|
51
pages/settings/imprint.vue
Normal file
51
pages/settings/imprint.vue
Normal file
@@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-lg-9 col-md-11 col-sm-12 col-xl-8">
|
||||
<h1 class="h3 fw-bold py-3">Impressum</h1>
|
||||
<div class="row pt-4">
|
||||
<div class="col-12">
|
||||
<h2 class="h4 mt-4">Angaben gemäß § 5 TMG</h2>
|
||||
<p>
|
||||
Robert-Carl Rapp<br>
|
||||
Sindlingerstr. 23<br>
|
||||
71083 Herrenberg
|
||||
</p>
|
||||
|
||||
<h2 class="h4 mt-4">Postadresse</h2>
|
||||
<p>
|
||||
Sindlingerstr. 23</br>
|
||||
71083 Herrenberg
|
||||
</p>
|
||||
|
||||
<h2 class="h4 mt-4">Kontakt</h2>
|
||||
<p>
|
||||
Telefon: +(49)15784037946<br>
|
||||
E-Mail: kontakt@mindboost.team
|
||||
</p>
|
||||
|
||||
<p>Quelle: <a href="https://www.e-recht24.de/impressum-generator.html">Generated by eRecht24</a></p>
|
||||
|
||||
<h2 class="h4 mt-4">Bildnachweise</h2>
|
||||
<a href="https://de.vecteezy.com/kostenlos-videos/wei%C3%9F">Weiß Stockvideos von Vecteezy</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'SettingPage',
|
||||
setup () {
|
||||
const { t } = useI18n()
|
||||
const localePath = useLocalePath()
|
||||
return { t, localePath }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
88
pages/settings/soundscap1.vue
Normal file
88
pages/settings/soundscap1.vue
Normal file
File diff suppressed because one or more lines are too long
480
pages/settings/soundscape.vue
Normal file
480
pages/settings/soundscape.vue
Normal file
File diff suppressed because one or more lines are too long
54
pages/settings/termsandcondition.vue
Normal file
54
pages/settings/termsandcondition.vue
Normal file
@@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-lg-9 col-md-11 col-sm-12 col-xl-8">
|
||||
<h1 class="h3 fw-bold py-3">Nutzungsbedingungen der App von Mindboost</h1>
|
||||
<div class="row pt-4">
|
||||
<div class="col-12">
|
||||
<h2 class="h4">1. Geltungsbereich</h2>
|
||||
<p>Diese Nutzungsbedingungen gelten für alle Dienste und Inhalte, die durch die App von Mindboost bereitgestellt werden. Mit der Registrierung bei oder der Nutzung unserer Dienste erklären Sie sich mit diesen Bedingungen einverstanden.</p>
|
||||
|
||||
<h2 class="h4">2. Nutzung von Audiodateien</h2>
|
||||
<p>Die in dieser App verfügbaren Audiodateien dürfen ausschließlich auf der Webseite von Mindboost genutzt werden. Jede Verwendung dieser Audiodateien außerhalb dieser Domain ist strengstens untersagt.</p>
|
||||
|
||||
<h2 class="h4">3. Nutzung des Algorithmus</h2>
|
||||
<p>Der in dieser App enthaltene Algorithmus darf nur von Nutzern mit einer aktiven und gültigen Lizenz verwendet werden. Die Lizenz muss während der gesamten Nutzungsdauer des Algorithmus gültig sein. Eine Nutzung ohne gültige Lizenz verstößt gegen unsere Nutzungsbedingungen.</p>
|
||||
|
||||
<h2 class="h4">4. Trial-Version</h2>
|
||||
<p>Jede natürliche oder juristische Person darf die Trial-Version dieser App nur einmal nutzen. Eine erneute Nutzung der Trial-Version ohne vorherige Absprache mit uns ist nicht erlaubt.</p>
|
||||
|
||||
<h2 class="h4">5. Account-Registrierung und Verantwortlichkeit</h2>
|
||||
<p>Die Nutzer sind verantwortlich für das sichere Aufbewahren ihrer Passwörter und für alle Aktivitäten, die unter ihrem Account stattfinden. Jeder Verdacht auf unbefugte Nutzung des Accounts sollte unverzüglich an unseren Kundenservice gemeldet werden.</p>
|
||||
|
||||
<h2 class="h4">6. Zahlungsbedingungen</h2>
|
||||
<p>Für bestimmte Teile unserer Dienste kann eine Gebühr anfallen. Alle Gebühren sind klar angegeben und sind zum Zeitpunkt der Fälligkeit zahlbar. Zahlungsverzögerungen können zur Deaktivierung des Zugangs führen.</p>
|
||||
|
||||
<h2 class="h4">7. Datenschutz</h2>
|
||||
<p>Ihre persönlichen Daten werden gemäß unserer Datenschutzrichtlinie behandelt, die Sie auf unserer Webseite einsehen können. Mit der Nutzung unserer Dienste stimmen Sie der Verarbeitung Ihrer Daten zu.</p>
|
||||
|
||||
<h2 class="h4">8. Änderungen der Dienste</h2>
|
||||
<p>Wir behalten uns das Recht vor, jederzeit Änderungen an unseren Diensten vorzunehmen oder Dienste einzustellen. Wir werden uns bemühen, die Nutzer rechtzeitig über solche Änderungen zu informieren.</p>
|
||||
|
||||
<h2 class="h4">9. Kündigung</h2>
|
||||
<p>Die Nutzer können ihr Abonnement jederzeit kündigen. Mindboost behält sich das Recht vor, den Service eines Nutzers zu kündigen oder zu suspendieren, wenn dieser gegen die Nutzungsbedingungen verstößt.</p>
|
||||
|
||||
<h2 class="h4">10. Haftungsbeschränkung</h2>
|
||||
<p>Mindboost haftet nicht für indirekte, zufällige, spezielle oder folgeschädigte Schäden, die aus der Nutzung oder Unfähigkeit zur Nutzung der Dienste entstehen.</p>
|
||||
|
||||
<h2 class="h4">11. Geltendes Recht und Gerichtsstand</h2>
|
||||
<p>Diese Nutzungsbedingungen unterliegen dem Recht des Landes, in dem Mindboost seinen Sitz hat, und alle Streitigkeiten werden ausschließlich vor den dortigen Gerichten verhandelt. </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
setup () {
|
||||
const { t } = useI18n()
|
||||
const localePath = useLocalePath()
|
||||
return { t, localePath }
|
||||
}
|
||||
}
|
||||
</script>
|
298
pages/settings/timersettings.vue
Normal file
298
pages/settings/timersettings.vue
Normal file
@@ -0,0 +1,298 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-lg-9 col-md-11 col-sm-12 col-xl-8">
|
||||
<h1 class="h3 fw-bold text-center py-3">
|
||||
Timer Settings
|
||||
</h1>
|
||||
<div class="timer__settings">
|
||||
<!-- Timer Settings -->
|
||||
<v-list class="px-2 px-md-16">
|
||||
<!-- Work Time -->
|
||||
<div class="slider">
|
||||
<input
|
||||
id="gain-control"
|
||||
v-model="timer().settings.timer.work"
|
||||
type="range"
|
||||
min="5"
|
||||
max="60"
|
||||
step="5"
|
||||
data-toggle="tooltip"
|
||||
data-placement="top"
|
||||
:title="tooltipTitle"
|
||||
@wheel.prevent="changeVolumeOnWheel"
|
||||
>
|
||||
<span
|
||||
class="slider-progress-bar"
|
||||
:style="{ width: `${volume * 100}%` }"
|
||||
/>
|
||||
</div>
|
||||
<!-- <v-list-item title="Work Sessions">
|
||||
<v-slider
|
||||
v-model="settings.timer.work"
|
||||
min="5"
|
||||
max="60"
|
||||
step="5"
|
||||
show-ticks
|
||||
thumb-label
|
||||
:color="timer().getCurrentColor"
|
||||
class="w-100"
|
||||
:ticks="sliderTicks.workTimer"
|
||||
:rules="rules.workRules"
|
||||
>
|
||||
<template #append>
|
||||
<v-text-field
|
||||
v-model="settings.timer.work"
|
||||
hide-details
|
||||
single-line
|
||||
density="compact"
|
||||
type="number"
|
||||
style="width: 70px"
|
||||
min="5"
|
||||
max="60"
|
||||
/>
|
||||
</template>
|
||||
</v-slider> -->
|
||||
<!-- </v-list-item> -->
|
||||
<!-- Breaks Sessions -->
|
||||
<v-list-item
|
||||
v-for="value, i in ['short-break', 'long-break']"
|
||||
:key="i"
|
||||
:title="timer().settings.timer[value].text"
|
||||
>
|
||||
<v-slider
|
||||
v-model="settings.timer[value]"
|
||||
min="0"
|
||||
max="60"
|
||||
step="5"
|
||||
show-ticks
|
||||
thumb-label
|
||||
:color="timer().getCurrentColor"
|
||||
class="w-100"
|
||||
:ticks="sliderTicks.breakTimers"
|
||||
:rules="rules.breakRules"
|
||||
>
|
||||
<template #append>
|
||||
<v-text-field
|
||||
v-model="settings.timer[value]"
|
||||
hide-details
|
||||
single-line
|
||||
density="compact"
|
||||
type="number"
|
||||
style="width: 70px"
|
||||
min="0"
|
||||
max="60"
|
||||
/>
|
||||
</template>
|
||||
</v-slider>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item
|
||||
title="Max Sessions"
|
||||
subtitle="The number of work sessions before a long break"
|
||||
>
|
||||
<v-slider
|
||||
v-model="settings.maxSessions"
|
||||
min="1"
|
||||
max="10"
|
||||
step="1"
|
||||
show-ticks
|
||||
thumb-label
|
||||
:color="timer().getCurrentColor"
|
||||
class="w-100"
|
||||
:ticks="sliderTicks.maxSessions"
|
||||
:rules="rules.maxSessionsRules"
|
||||
>
|
||||
<template #append>
|
||||
<v-text-field
|
||||
v-model="settings.maxSessions"
|
||||
hide-details
|
||||
single-line
|
||||
density="compact"
|
||||
type="number"
|
||||
style="width: 70px"
|
||||
min="1"
|
||||
max="10"
|
||||
/>
|
||||
</template>
|
||||
</v-slider>
|
||||
</v-list-item>
|
||||
<v-list-item>
|
||||
<v-checkbox
|
||||
v-model="timer().settings.autoStart"
|
||||
:color="timer().getCurrentColor"
|
||||
label="Auto Start Sessions"
|
||||
true-icon="mdi-timer-play-outline"
|
||||
false-icon="mdi-timer-play-outline"
|
||||
/>
|
||||
</v-list-item>
|
||||
|
||||
<v-divider />
|
||||
|
||||
<!-- General Settings -->
|
||||
<v-list-subheader>General Settings</v-list-subheader>
|
||||
<v-list-item>
|
||||
<v-checkbox
|
||||
v-model="settings.notificationsEnabled"
|
||||
:color="timer().getCurrentColor"
|
||||
label="Notifications"
|
||||
true-icon="mdi-bell"
|
||||
false-icon="mdi-bell-off"
|
||||
/>
|
||||
</v-list-item>
|
||||
<v-list-item>
|
||||
<v-checkbox
|
||||
v-model="timer().playSessionEndSound"
|
||||
:color="timer().getCurrentColor"
|
||||
label="Sounds"
|
||||
true-icon="mdi-volume-high"
|
||||
false-icon="mdi-volume-off"
|
||||
/>
|
||||
</v-list-item>
|
||||
<!-- <v-list-item>
|
||||
<v-checkbox
|
||||
v-model="app().showThemeToggle"
|
||||
:color="timer().getCurrentColor"
|
||||
label="Show Theme Toggle"
|
||||
true-icon="mdi-theme-light-dark"
|
||||
false-icon="mdi-theme-light-dark"
|
||||
/>
|
||||
</v-list-item> -->
|
||||
</v-list>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { useTimerStore as timer } from '~~/stores/timer'
|
||||
|
||||
export default {
|
||||
name: 'TimerSettings',
|
||||
setup () {
|
||||
const { t } = useI18n()
|
||||
const localePath = useLocalePath()
|
||||
|
||||
const sliderTicks = reactive({
|
||||
workTimer: {
|
||||
5: '5',
|
||||
60: '60'
|
||||
},
|
||||
breakTimers: {
|
||||
0: '0',
|
||||
60: '60'
|
||||
},
|
||||
maxSessions: {
|
||||
1: '1',
|
||||
10: '10'
|
||||
}
|
||||
})
|
||||
// only the settings that need validation
|
||||
const settings = reactive({
|
||||
timer: {
|
||||
work: 25,
|
||||
'short-break': 5,
|
||||
'long-break': 15
|
||||
},
|
||||
maxSessions: 4,
|
||||
notificationsEnabled: false
|
||||
})
|
||||
const state = reactive({
|
||||
dialog: false,
|
||||
snackbar: false
|
||||
})
|
||||
|
||||
// rules for validating inputs
|
||||
const rules = reactive({
|
||||
workRules: [
|
||||
(value) => {
|
||||
if (value >= 5 && value <= 60) { return true }
|
||||
|
||||
if (value <= 0) { return "Are you kidding me? if you don't wanna work then just go find something better to do than playing with my settings." }
|
||||
if (value < 5) { return 'Do you want to work for less than 5 mins?! You can do better.' }
|
||||
return "Don't be so hard on yourself, work for an hour or less before taking a break."
|
||||
}
|
||||
],
|
||||
breakRules: [
|
||||
(value) => {
|
||||
if (value >= 0 && value <= 60) { return true }
|
||||
|
||||
if (value < 0) { return 'How tf would you take a negative break time you moron?' }
|
||||
return "That's too much time for a break, stop wasting your time."
|
||||
}
|
||||
],
|
||||
maxSessionsRules: [
|
||||
(value) => {
|
||||
if (value >= 1) { return true }
|
||||
|
||||
return "Max sessions can't be less than one!"
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// save settings to localstorage
|
||||
const saveSettings = () => {
|
||||
saveNotification()
|
||||
|
||||
// validate user inputs before saving
|
||||
if (rules.workRules[0](settings.timer.work) === true) {
|
||||
timer().settings.timer.work.time = settings.timer.work
|
||||
}
|
||||
if (rules.breakRules[0](settings.timer['short-break']) === true) {
|
||||
timer().settings.timer['short-break'].time = settings.timer['short-break']
|
||||
}
|
||||
if (rules.breakRules[0](settings.timer['long-break']) === true) {
|
||||
timer().settings.timer['long-break'].time = settings.timer['long-break']
|
||||
}
|
||||
if (rules.maxSessionsRules[0](settings.maxSessions) === true) {
|
||||
timer().settings.maxSessions = settings.maxSessions
|
||||
}
|
||||
|
||||
storeSettings()
|
||||
|
||||
state.dialog = false
|
||||
state.snackbar = true
|
||||
}
|
||||
return { t, localePath }
|
||||
}
|
||||
}
|
||||
|
||||
// watch(
|
||||
// () => state.dialog,
|
||||
// (dialog) => {
|
||||
// if (!dialog) { // if dialog is closed
|
||||
// saveSettings()
|
||||
// } else {
|
||||
// // retrieve settings from state when dialog is opened
|
||||
// // settings.notificationsEnabled = timer().showNotification
|
||||
// settings.maxSessions = timer().settings.maxSessions
|
||||
// for (const session of Object.keys(settings.timer)) {
|
||||
// settings.timer[session] = timer().settings.timer[session].time
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// )
|
||||
|
||||
// get notification permission from the browser
|
||||
// const saveNotification = () => {
|
||||
// const { isSupported, show } = useWebNotification({
|
||||
// title: 'Notifications enabled.'
|
||||
// })
|
||||
// if (isSupported.value) {
|
||||
// if (!timer().showNotification && settings.notificationsEnabled) { show() }
|
||||
// } else {
|
||||
// useNuxtApp().$logger.error('Your browser does not support notifications.')
|
||||
// }
|
||||
// timer().showNotification = settings.notificationsEnabled
|
||||
// }
|
||||
|
||||
</script>
|
||||
<style>
|
||||
.dialog-bottom-transition-enter-active,
|
||||
.dialog-bottom-transition-leave-active {
|
||||
transition: transform .1s ease-in-out;
|
||||
}
|
||||
.v-footer {
|
||||
row-gap: 0.4rem;
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user