Chamilo is a learning management system focused on ease of use and accessibility
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
chamilo-lms/assets/vue/views/user/PersonalData.vue

257 lines
7.9 KiB

<template>
<div class="flex flex-col gap-4">
<BaseCard plain class="bg-white">
<template #header>
<div class="px-4 py-2 -mb-2 bg-gray-15">
<h2 class="text-h5">{{ t('Personal Data: Introduction') }}</h2>
</div>
</template>
<hr class="-mt-2 mb-4 -mx-4">
<div>
{{ t('We respect your personal data! This page...') }}
</div>
</BaseCard>
<BaseCard plain class="bg-white">
<template #header>
<div class="px-4 py-2 -mb-2 bg-gray-15">
<h2 class="text-h5">{{ t('Personal data we keep about you') }}</h2>
</div>
</template>
<hr class="-mt-2 mb-4 -mx-4">
<div>
<div v-for="(categoryData, categoryName) in personalData.data" :key="categoryName">
<button @click="toggleCategory(categoryName)" class="text-left w-full">
<span class="underline">{{ categoryName }}</span>
</button>
<ul v-if="expandedCategories.includes(categoryName)">
<li v-for="(dataSet, dataSetIndex) in categoryData" :key="`dataset-${dataSetIndex}`">
<div v-for="(value, key) in dataSet" :key="`item-${dataSetIndex}-${key}`">
<span><strong>{{ key }}:</strong> {{ value }}</span>
</div>
</li>
</ul>
</div>
</div>
</BaseCard>
<BaseCard plain class="bg-white">
<template #header>
<div class="px-4 py-2 -mb-2 bg-gray-15">
<h2 class="text-h5">{{ t('Terms and Conditions') }}</h2>
</div>
</template>
<hr class="-mt-2 mb-4 -mx-4">
<div>
<a href="#" @click="openTermsDialog">{{ t('Read the Terms and Conditions') }}</a>
</div>
</BaseCard>
<BaseCard plain class="bg-white">
<template #header>
<div class="px-4 py-2 -mb-2 bg-gray-15">
<h2 class="text-h5">{{ t('Permissions you gave us') }}</h2>
</div>
</template>
<hr class="-mt-2 mb-4 -mx-4">
<div>
<div v-if="legalStatus.isAccepted">
<p>{{ t('Legal agreement accepted') }}
<BaseIcon
icon="check"
size="small"
class="text-green-500"
/>
</p>
<p>{{ t('Date') }}: {{ legalStatus.acceptDate }}</p>
<div v-if="termsAndConditions">
<div class="p-4">
<p class="text-sm text-gray-600">
{{ t('Why you want to delete your Legal Agreement') }}
</p>
</div>
<form class="flex flex-col gap-2 mt-6">
<BaseTextArea
v-model="deleteTermExplanation"
:label="t('Please tell us why you want to withdraw the rights you previously gave us, to let us make it in the smoothest way possible')"
required
/>
<LayoutFormButtons>
<BaseButton
:label="t('Delete legal agreement')"
type="danger"
icon="delete"
@click="submitDeleteTerm"
/>
</LayoutFormButtons>
</form>
<form @submit.prevent="submitDeleteAccount" class="flex flex-col gap-2 mt-6">
<BaseTextArea
v-model="deleteAccountExplanation"
:label="t('Explain in this box why you want your account deleted')"
required
/>
<LayoutFormButtons>
<BaseButton
:label="t('Delete Account')"
type="danger"
icon="delete"
@click="submitDeleteAccount"
/>
</LayoutFormButtons>
</form>
</div>
</div>
<div v-else>
<p>{{ legalStatus.message }}</p>
</div>
</div>
</BaseCard>
</div>
<BaseDialog
v-if="termsAndConditions.length > 0"
v-model:is-visible="termsAndConditionsDialogVisible"
:style="{ width: '28rem' }"
:title="t('Read the Terms and Conditions')"
>
<template v-for="(term, index) in termsAndConditions" :key="`term-${index}`">
<h3>{{ term.title }}</h3>
<div v-html="term.content"></div>
<p>{{ term.date_text }}</p>
</template>
</BaseDialog>
</template>
<script setup>
import axios from 'axios';
import { onMounted, reactive, ref, computed } from "vue"
import { useI18n } from 'vue-i18n';
import BaseCard from "../../components/basecomponents/BaseCard.vue"
import { useStore } from "vuex"
import BaseDialog from "../../components/basecomponents/BaseDialog.vue"
import BaseIcon from "../../components/basecomponents/BaseIcon.vue"
import BaseTextArea from "../../components/basecomponents/BaseTextArea.vue"
import LayoutFormButtons from "../../components/layout/LayoutFormButtons.vue"
import BaseButton from "../../components/basecomponents/BaseButton.vue"
import { useNotification } from "../../composables/notification"
const { t } = useI18n()
const store = useStore()
const { showSuccessNotification, showErrorNotification } = useNotification()
const user = computed(() => store.getters["security/getUser"])
const personalData = reactive({
data: {},
})
const termsAndConditions = ref({
content: [],
date_text: '',
})
const legalStatus = reactive({
isAccepted: false,
acceptDate: null,
message: ''
})
const termsAndConditionsDialogVisible = ref(false)
const expandedCategories = ref([])
const deleteTermExplanation = ref('')
const deleteAccountExplanation = ref('')
const openTermsDialog = () => {
termsAndConditionsDialogVisible.value = true
}
const submitPrivacyRequest = async (requestType) => {
const explanation = requestType === 'delete_account' ? deleteAccountExplanation.value : deleteTermExplanation.value
if (explanation.trim() === '') {
showErrorNotification('Explanation is required')
return
}
try {
const response = await axios.post('/social-network/handle-privacy-request', {
explanation,
userId: user.value["@id"].split('/').pop(),
requestType
})
if (response.data.success) {
showSuccessNotification(response.data.message)
} else {
showErrorNotification(response.data.message)
}
} catch (error) {
showErrorNotification('Error submitting privacy request:', error)
}
}
const submitDeleteTerm = () => submitPrivacyRequest('delete_legal')
const submitDeleteAccount = () => submitPrivacyRequest('delete_account')
function toggleCategory(categoryName) {
const index = expandedCategories.value.indexOf(categoryName)
if (index === -1) {
expandedCategories.value.push(categoryName)
} else {
expandedCategories.value.splice(index, 1)
}
}
async function fetchPersonalData() {
if (!user.value) {
console.error("User ID is not available.")
return
}
try {
const userId = user.value["@id"].split('/').pop()
const response = await axios.get(`/social-network/personal-data/${userId}`)
personalData.data = response.data.personalData
} catch (error) {
console.error('Error fetching personal data:', error)
}
}
async function fetchTermsAndConditions() {
if (!user.value) {
console.error("User ID is not available.")
return
}
try {
const userId = user.value["@id"].split('/').pop()
const response = await axios.get(`/social-network/terms-and-conditions/${userId}`)
termsAndConditions.value = response.data.terms
} catch (error) {
console.error('Error fetching terms and conditions:', error)
}
}
async function fetchLegalStatus() {
if (!user.value) {
console.error("User ID is not available.")
return
}
try {
const userId = user.value["@id"].split('/').pop()
const response = await axios.get(`/social-network/legal-status/${userId}`)
Object.assign(legalStatus, response.data)
} catch (error) {
console.error('Error fetching legal status:', error)
}
}
onMounted(async () => {
await fetchPersonalData()
await fetchTermsAndConditions()
await fetchLegalStatus()
})
</script>