diff --git a/pages/index.vue b/pages/index.vue index 0bda6c61..733482aa 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -6,241 +6,344 @@ const { t, locale } = useI18n(); useSeoMeta({ title: t("page.home.meta.title") }); -const words = [t("page.home.words.music"), t("page.home.words.videos"), t("page.home.words.streams"), t("page.home.words.media")]; +const words = [ + t("page.home.words.music"), + t("page.home.words.videos"), + t("page.home.words.streams"), + t("page.home.words.media"), +]; const currentWord = ref(words[0]); let currentWordIndex = 0; let wordInterval: number; -onMounted(() => { - wordInterval = window.setInterval(() => { - currentWordIndex = (currentWordIndex + 1) % words.length; - currentWord.value = words[currentWordIndex]; - }, 2000); -}); +const scrollerMouseDown = ref(false); +const scroller = ref(null); +const scrollerItems = ref(null); +onMounted(async () => { + wordInterval = window.setInterval(() => { + currentWordIndex = (currentWordIndex + 1) % words.length; + currentWord.value = words[currentWordIndex]; + }, 2000); -onUnmounted(() => { - clearInterval(wordInterval); -}); + + // Draggable User Cards + let startX: number; + let scrollLeft: number; + + const handleMouseDown = (e: MouseEvent) => { + scrollerMouseDown.value = true; + startX = e.pageX - (scrollerItems.value?.offsetLeft || 0); + scrollLeft = scrollerItems.value?.scrollLeft ?? 0; + }; + + const handleMouseUp = () => { + scrollerMouseDown.value = false; + }; + + const handleMouseMove = (e: MouseEvent) => { + if (!scrollerMouseDown.value) return; + const x = e.pageX - (scrollerItems.value?.offsetLeft || 0); + const walk = x - startX; + + //ensure we loop the cards + //TODO: loop by shifting elements from back to front + if (scrollerItems.value) { + scrollerItems.value.scrollLeft = scrollLeft - walk; + const scrollWidth = scrollerItems.value.scrollWidth / 2; + if (scrollerItems.value.scrollLeft >= scrollWidth) { + scrollerItems.value.scrollLeft -= scrollWidth; + } else if (scrollerItems.value.scrollLeft <= 0) { + scrollerItems.value.scrollLeft += scrollWidth; + } + } + }; -const scroller = ref(); + if (scroller.value && scrollerItems.value) { + scroller.value.addEventListener("pointerdown", handleMouseDown); + window.addEventListener("pointerup", handleMouseUp); + scroller.value.addEventListener("pointermove", handleMouseMove); + } + + onUnmounted(() => { + if (scroller.value && scrollerItems.value) { + scroller.value.removeEventListener("pointerdown", handleMouseDown); + window.removeEventListener("pointerup", handleMouseUp); + scroller.value.removeEventListener("pointermove", handleMouseMove); + } + clearInterval(wordInterval); + }); +}); const { data: staffData } = await useFetch("/api/getStaffData"); const features = ref([ - { - icon: "fas fa-lock", - title: t("page.home.sections.feature.feature1.title"), - description: t("page.home.sections.feature.feature1.description"), - }, - { - icon: "fas fa-users", - title: t("page.home.sections.feature.feature2.title"), - description: t("page.home.sections.feature.feature2.description"), - }, - { - icon: "fas fa-cogs", - title: t("page.home.sections.feature.feature3.title"), - description: t("page.home.sections.feature.feature3.description"), - }, - { - icon: "fas fa-check-circle", - title: t("page.home.sections.feature.feature4.title"), - description: t("page.home.sections.feature.feature4.description"), - }, - { - icon: "fas fa-handshake", - title: t("page.home.sections.feature.feature5.title"), - description: t("page.home.sections.feature.feature5.description"), - }, - { - icon: "fas fa-lightbulb", - title: t("page.home.sections.feature.feature6.title"), - description: t("page.home.sections.feature.feature6.description"), - }, + { + icon: "fas fa-lock", + title: t("page.home.sections.feature.feature1.title"), + description: t("page.home.sections.feature.feature1.description"), + }, + { + icon: "fas fa-users", + title: t("page.home.sections.feature.feature2.title"), + description: t("page.home.sections.feature.feature2.description"), + }, + { + icon: "fas fa-cogs", + title: t("page.home.sections.feature.feature3.title"), + description: t("page.home.sections.feature.feature3.description"), + }, + { + icon: "fas fa-check-circle", + title: t("page.home.sections.feature.feature4.title"), + description: t("page.home.sections.feature.feature4.description"), + }, + { + icon: "fas fa-handshake", + title: t("page.home.sections.feature.feature5.title"), + description: t("page.home.sections.feature.feature5.description"), + }, + { + icon: "fas fa-lightbulb", + title: t("page.home.sections.feature.feature6.title"), + description: t("page.home.sections.feature.feature6.description"), + }, ]); const steps = ref([ - { - icon: "download", - title: t("page.home.sections.howItWorks.step1.title"), - description: t("page.home.sections.howItWorks.step1.description"), - }, - { - icon: "sign-in-alt", - title: t("page.home.sections.howItWorks.step2.title"), - description: t("page.home.sections.howItWorks.step2.description"), - - }, - { - icon: "plus", - title: t("page.home.sections.howItWorks.step3.title"), - description: t("page.home.sections.howItWorks.step3.description"), - }, - { - icon: "smile", - title: t("page.home.sections.howItWorks.step4.title"), - description: t("page.home.sections.howItWorks.step4.description"), - }, + { + icon: "download", + title: t("page.home.sections.howItWorks.step1.title"), + description: t("page.home.sections.howItWorks.step1.description"), + }, + { + icon: "sign-in-alt", + title: t("page.home.sections.howItWorks.step2.title"), + description: t("page.home.sections.howItWorks.step2.description"), + }, + { + icon: "plus", + title: t("page.home.sections.howItWorks.step3.title"), + description: t("page.home.sections.howItWorks.step3.description"), + }, + { + icon: "smile", + title: t("page.home.sections.howItWorks.step4.title"), + description: t("page.home.sections.howItWorks.step4.description"), + }, ]); const { data } = await useAsyncGql("getIndexData"); -const computedUsage = computed(() => Intl.NumberFormat(locale.value).format(data.value?.usage?.count ?? 0)); +const computedUsage = computed(() => + Intl.NumberFormat(locale.value).format(data.value?.usage?.count ?? 0), +); const localePath = useLocalePath();