Skip to content
This repository has been archived by the owner on Sep 27, 2024. It is now read-only.

fix(recommendations): prepping recommendations to fire impression events for analytics #58

Merged
merged 2 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions components/recommendation/RecommendationArticle.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<script setup lang="ts">
import type { Recommendation } from '../composables/recommendations'

const {
item,
} = defineProps<{
item: Recommendation
}>()

const target = ref<HTMLDivElement>()
const { isActive } = useIntersectionObserver(target, checkIntersection, { threshold: 0.5 })

function checkIntersection([{ isIntersecting }]: [{ isIntersecting: boolean }]): void {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line hurts to dissect at first but got better afterwards 😃

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like it, too. I could probably add some line breaks to make it a little easier to grok.

if (isIntersecting && isActive.value) {
// fire analytics event here: item.id || item.title || item.url
isActive.value = false
}
}

// Shorten a string to less than maxLen characters without truncating words.
function shorten(str: string, maxLen: number): string {
if (str.length <= maxLen)
return str
return `${str.slice(0, str.lastIndexOf(' ', maxLen))}...`
}

const clipboard = useClipboard()
async function copyLink(url: string, event: Event): void {
event.preventDefault()
if (url)
await clipboard.copy(url)
}
</script>

<template>
<NuxtLink ref="target" :to="item.url" target="_blank" external p-y-16px p-x-8px flex border="b base">
<div class="content" w-full pr>
<h4 text-sm text-secondary>
{{ item.publisher }}
</h4>
<h3 text-lg line-height-tight font-500 m-y-4px>
{{ shorten(item.title, 100) }}
</h3>
<p>
{{ shorten(item.excerpt, 140) }}
</p>
</div>
<div class="media" relative overflow-hidden max-w-120px min-w-120px>
<img :src="item.image.sizes?.[0]?.url" rounded-lg overflow-hidden w-full ha>
<div m-y-4px flex flex-justify-end>
<button p-12px text-xl @click="copyLink(item.url, $event)">
<div i-ri:share-line />
</button>
</div>
</div>
</NuxtLink>
</template>

<style scoped>
a:hover h3 {
text-decoration: underline;
}
</style>
52 changes: 1 addition & 51 deletions components/timeline/TimelineDiscover.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,63 +6,13 @@ const { locale: lang } = useI18n()
const locale = getLanguageForRecs(lang.value)

const recommendations: Recommendation[] = await $fetch(`/api/${publicServer.value}/recommendations?locale=${locale}`)

// Shorten a string to less than maxLen characters without truncating words.
function shorten(str: string, maxLen: number): string {
if (str.length <= maxLen)
return str
return `${str.slice(0, str.lastIndexOf(' ', maxLen))}...`
}

const clipboard = useClipboard()
async function copyLink(url, event) {
event.preventDefault()
if (url)
await clipboard.copy(url)
}
</script>

<template>
<h1 text-2xl p-2>
Today’s Top Picks
</h1>
<main>
<template v-for="item in recommendations" :key="item.tileId">
<NuxtLink
:to="item.url"
target="_blank"
external
p-y-16px
p-x-8px
flex
border="b base"
>
<div class="content" w-full pr>
<h4 text-sm text-secondary>
{{ item.publisher }}
</h4>
<h3 text-lg line-height-tight font-500 m-y-4px>
{{ shorten(item.title, 100) }}
</h3>
<p>
{{ shorten(item.excerpt, 140) }}
</p>
</div>
<div class="media" relative overflow-hidden max-w-120px min-w-120px>
<img :src="item.image.sizes?.[0]?.url" rounded-lg overflow-hidden w-full ha>
<div m-y-4px flex flex-justify-end>
<button p-12px text-xl @click="copyLink(item.url, $event)">
<div i-ri:share-line />
</button>
</div>
</div>
</NuxtLink>
</template>
<RecommendationArticle v-for="item in recommendations" :key="item.id" :item="item" />

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the key changing from item.tileId intentional?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup! This matches up with the new API.

It should have been done before, but since we weren't using this value for anything it was missed.

</main>
</template>

<style scoped>
a:hover h3 {
text-decoration: underline;
}
</style>
Loading