I added scroll tracking functionality so that the user can click Accept only after scrolling to the end of the dialog window. But after the code review I was told that I need to use an existing directive from Vuetify. After 3 hrs of searching I end up with nothing.
How i did it:
<template>
<UIDialog
:value="isVisible"
:loading="loading"
scrollable
:persistent="!isAccepted"
max-width="800px"
actions-sticky-bottom
>
<template #content>
<div v-html="licenseText" v-scroll="handleScroll"/>
<div
ref="scrollEndRef"
class="scroll-end-marker"
/>
</template>
<template #actions>
<UICheckbox
v-if="!isAccepted"
v-model="acceptIsChecked"
:disabled="loading || !isScrolledToBottom"
:label="$t('legal.i_accept')"
/>
<UISpacer />
<UIButton
v-if="isAccepted"
:text="$t('general.close')"
color="primary"
:disabled="loading"
@click="close"
/>
<UIButton
v-else
:text="$t('general.continue')"
color="primary"
:disabled="loading || !acceptIsChecked"
@click="accept"
/>
</template>
</UIDialog>
</template>
<script lang="ts">
import {
computed,
defineComponent, nextTick, onUnmounted,
ref,
watch,
} from 'vue';
import { useSettingStore } from '@/stores/setting';
import api from '@/services/data';
import UIButton from '@/components/UI/UIButton/UIButton.vue';
import UICheckbox from '@/components/UI/UIForm/UICheckbox.vue';
import UIDialog from '@/components/UI/UIDialog/UIDialog.vue';
import UISpacer from '@/components/UI/UILayout/UISpacer.vue';
export default defineComponent({
components: {
UISpacer,
UIDialog,
UICheckbox,
UIButton,
},
setup() {
const settingStore = useSettingStore();
const loading = ref(false);
const acceptIsChecked = ref(false);
const licenseText = ref<string|null>(null);
const isAccepted = computed(() => settingStore.eulaIsAccepted);
const isVisible = computed(() => settingStore.eulaAcceptDialogIsVisible);
const accept = async () => {
const date = new Date();
const isoDateTime = JSON.stringify(date.toISOString());
loading.value = true;
try {
await api.eula.setAcceptanceDate(isoDateTime);
settingStore.setEulaAcceptanceValue(acceptIsChecked.value);
settingStore.setEulaAcceptDialogVisibility(!acceptIsChecked.value);
} catch {} finally {
loading.value = false;
}
};
const close = () => {
if (!isVisible.value) {
return;
}
settingStore.setEulaAcceptDialogVisibility(false);
};
const loadLicenseText = async () => {
try {
loading.value = true;
const response = await api.eula.getLicenseText();
licenseText.value = response.data;
} catch {} finally {
loading.value = false;
}
};
const isScrolledToBottom = ref<boolean>(false);
const scrollEndRef = ref(null);
let observer: IntersectionObserver|null = null;
const handleIntersection = (entries: IntersectionObserverEntry[]) => {
entries.forEach((entry) => {
isScrolledToBottom.value = entry.isIntersecting;
});
};
loadLicenseText();
watch(() => isVisible.value, (value) => {
if (value && !licenseText.value) {
loadLicenseText();
}
}, { immediate: true });
watch(() => isVisible.value, (value) => {
if (value) {
nextTick().then(() => {
if (scrollEndRef.value) {
observer = new IntersectionObserver(handleIntersection, { threshold: 1.0 });
observer.observe(scrollEndRef.value);
}
});
}
});
onUnmounted(() => {
if (observer && scrollEndRef.value) {
observer.unobserve(scrollEndRef.value);
}
});
return {
loading,
acceptIsChecked,
isAccepted,
isVisible,
licenseText,
accept,
close,
isScrolledToBottom,
onUnmounted,
handleIntersection,
scrollEndRef,
};
},
});
</script>
So yeah, I need to replace my functionality with Vuetify directive
New contributor
FxReinhard is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.