unwind/unwind-ui/src/components/MovieList.vue

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

139 lines
3 KiB
Vue
Raw Normal View History

2021-07-25 19:01:25 +02:00
<template>
<table class="table is-fullwidth is-striped">
<thead>
<tr>
<th>title</th>
<th>year</th>
<th>type</th>
<th>rating</th>
<th>runtime</th>
</tr>
</thead>
<tbody>
2021-08-05 17:50:44 +02:00
<tr v-for="item in items" :key="item.id" :data-unwind-id="item.id">
2021-07-25 19:01:25 +02:00
<td v-if="item.original_title">
<a :href="`https://www.imdb.com/title/${item.imdb_id}/`">
<span>{{ item.original_title }}</span>
</a>
<span v-if="item.title != item.original_title"> ({{ item.title }})</span>
</td>
<td v-else>
<a :href="`https://www.imdb.com/title/${item.imdb_id}/`">
<span>{{ item.title }}</span>
</a>
</td>
<td>
<span class="year">{{ item.release_year }}</span>
</td>
<td>
<span class="mediatype">{{ item.media_type }}</span>
</td>
<td>
2021-08-04 17:30:17 +02:00
<span
class="score imdb-score tag is-large"
:title="`IMDb rating (1-10) / ${item.imdb_votes} votes`"
>{{ imdb_rating(item.imdb_score) }}</span
>
<span
class="score tag is-info is-large"
:title="`User rating (1-10) / ${
item.user_scores.length
} votes / σ = ${imdb_stdev(item.user_scores)}`"
>{{ avg_imdb_rating(item.user_scores) }}</span
>
2021-07-25 19:01:25 +02:00
</td>
<td>
<span>{{ duration(item.runtime) }}</span>
</td>
</tr>
</tbody>
</table>
<div ref="sentinel"></div>
</template>
<script lang="ts">
import { defineComponent } from "vue"
2021-08-04 01:04:13 +02:00
import { mean, pstdev } from "../utils.ts"
function avg_imdb_rating(scores) {
return imdb_rating(scores.length === 0 ? null : mean(scores))
}
function imdb_stdev(scores) {
return pstdev(scores.map(imdb_rating_from_score))
}
function imdb_rating_from_score(score) {
2021-08-04 17:10:44 +02:00
return Math.round((score * 9) / 10 + 10) / 10
2021-08-04 01:04:13 +02:00
}
2021-07-25 19:01:25 +02:00
function imdb_rating(score) {
if (score == null) {
return "-"
}
2021-08-04 17:10:44 +02:00
const deci = 10 * imdb_rating_from_score(score)
2021-07-25 19:01:25 +02:00
return `${(deci / 10) | 0}.${deci % 10}`
}
function duration(minutes_total) {
if (minutes_total == null) {
return "-"
}
const m = minutes_total % 60
const h = (minutes_total / 60) | 0
return `${h} h ${m} m`
}
export default defineComponent({
props: {
items: {
type: Array,
required: true,
},
},
emits: ["reach-bottom"],
mounted() {
const options = {
rootMargin: "500px",
}
const observer = new IntersectionObserver(([e]) => {
if (!e.isIntersecting) {
return
}
this.$emit("reach-bottom")
}, options)
observer.observe(this.$refs.sentinel)
},
methods: {
2021-08-04 01:04:13 +02:00
avg_imdb_rating,
2021-07-25 19:01:25 +02:00
imdb_rating,
2021-08-04 01:04:13 +02:00
imdb_stdev,
2021-07-25 19:01:25 +02:00
duration,
},
})
</script>
<style scoped>
.year {
color: grey;
}
.mediatype {
color: grey;
}
.score {
width: 2em;
height: 2em;
}
.score + .score {
margin-left: 1em;
}
.imdb-score {
background-color: rgb(245, 197, 24);
}
.user-score {
}
</style>