update
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
<script setup>
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { posterUrl } from '../images'
|
||||
import { abonnieren } from '../live'
|
||||
|
||||
const emit = defineEmits(['open'])
|
||||
defineProps({ host: Boolean })
|
||||
const emit = defineEmits(['open', 'reset'])
|
||||
|
||||
const items = ref([])
|
||||
const mine = ref(null)
|
||||
@@ -26,16 +28,14 @@ const FARBEN = [
|
||||
]
|
||||
|
||||
// Ohne Server-Ziehung sähe jede Seite ein anderes Ergebnis
|
||||
let quelle = null
|
||||
let abbestellen = null
|
||||
|
||||
function verbinden() {
|
||||
quelle = new EventSource('/api/events')
|
||||
quelle.onmessage = (ereignis) => {
|
||||
const nachricht = JSON.parse(ereignis.data)
|
||||
abbestellen = abonnieren((nachricht) => {
|
||||
if (nachricht.type === 'suggestions') laden_()
|
||||
else if (nachricht.type === 'spin') abspielen(nachricht.data)
|
||||
}
|
||||
// Der Browser verbindet nach einem Abbruch von selbst neu
|
||||
else if (nachricht.type === 'reset') zurueckgesetzt()
|
||||
})
|
||||
}
|
||||
|
||||
function abspielen(ergebnis, uebersprungen = 0) {
|
||||
@@ -101,7 +101,7 @@ onMounted(async () => {
|
||||
verbinden()
|
||||
})
|
||||
|
||||
onUnmounted(() => quelle?.close())
|
||||
onUnmounted(() => abbestellen?.())
|
||||
|
||||
defineExpose({ neu: laden_ })
|
||||
|
||||
@@ -165,6 +165,25 @@ async function drehen() {
|
||||
}
|
||||
}
|
||||
|
||||
function zurueckgesetzt() {
|
||||
// Ohne Dauer 0 würde das Rad die Strecke zurück sichtbar abfahren
|
||||
dauer.value = 0
|
||||
winkel.value = 0
|
||||
gewinner.value = null
|
||||
dreht.value = false
|
||||
emit('reset')
|
||||
laden_()
|
||||
}
|
||||
|
||||
async function zuruecksetzen() {
|
||||
// Der Server meldet den Reset an alle zurück, auch an uns
|
||||
try {
|
||||
await fetch('/api/suggestions/alle', { method: 'DELETE' })
|
||||
} catch {
|
||||
fehler.value = 'Zurücksetzen hat nicht geklappt.'
|
||||
}
|
||||
}
|
||||
|
||||
async function oeffnen(item) {
|
||||
const resp = await fetch(`/api/search/${item.movie_id}`)
|
||||
if (resp.ok) emit('open', await resp.json())
|
||||
@@ -174,64 +193,70 @@ async function oeffnen(item) {
|
||||
<template>
|
||||
<div class="wheel-tab">
|
||||
<div class="buehne">
|
||||
<p v-if="laden" class="note">Lade Vorschläge…</p>
|
||||
<p v-else-if="fehler" class="note error">{{ fehler }}</p>
|
||||
<p v-else-if="!items.length" class="note">
|
||||
Noch keine Vorschläge. Öffne einen Film und klicke auf „Vorschlagen“.
|
||||
</p>
|
||||
<p v-if="fehler" class="note error">{{ fehler }}</p>
|
||||
|
||||
<template v-else>
|
||||
<div class="rad-halter">
|
||||
<div class="zeiger"></div>
|
||||
<svg
|
||||
class="rad"
|
||||
:class="{ dreht }"
|
||||
:viewBox="`0 0 ${GROESSE} ${GROESSE}`"
|
||||
:style="{
|
||||
transform: `rotate(${winkel}deg)`,
|
||||
transitionDuration: `${dauer}s`,
|
||||
}"
|
||||
>
|
||||
<g v-for="(seg, i) in segmente" :key="seg.item.id">
|
||||
<path :d="seg.pfad" :fill="seg.farbe" stroke="#0a0a0c" stroke-width="2" />
|
||||
<text
|
||||
v-if="seg.breit"
|
||||
:transform="`rotate(${seg.textDreh} ${MITTE} ${MITTE})`"
|
||||
:x="seg.gespiegelt ? MITTE - 40 : MITTE + 40"
|
||||
:y="MITTE + 4"
|
||||
:text-anchor="seg.gespiegelt ? 'end' : 'start'"
|
||||
class="beschriftung"
|
||||
>
|
||||
{{ seg.kurz }}
|
||||
</text>
|
||||
</g>
|
||||
<circle :cx="MITTE" :cy="MITTE" r="26" fill="#0a0a0c" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="rad-halter">
|
||||
<div class="zeiger"></div>
|
||||
<svg
|
||||
class="rad"
|
||||
:class="{ dreht }"
|
||||
:viewBox="`0 0 ${GROESSE} ${GROESSE}`"
|
||||
:style="{
|
||||
transform: `rotate(${winkel}deg)`,
|
||||
transitionDuration: `${dauer}s`,
|
||||
}"
|
||||
>
|
||||
<circle :cx="MITTE" :cy="MITTE" :r="RADIUS" fill="var(--bg-soft)" />
|
||||
<g v-for="(seg, i) in segmente" :key="seg.item.id">
|
||||
<path :d="seg.pfad" :fill="seg.farbe" stroke="#0a0a0c" stroke-width="2" />
|
||||
<text
|
||||
v-if="seg.breit"
|
||||
:transform="`rotate(${seg.textDreh} ${MITTE} ${MITTE})`"
|
||||
:x="seg.gespiegelt ? MITTE - 40 : MITTE + 40"
|
||||
:y="MITTE + 4"
|
||||
:text-anchor="seg.gespiegelt ? 'end' : 'start'"
|
||||
class="beschriftung"
|
||||
>
|
||||
{{ seg.kurz }}
|
||||
</text>
|
||||
</g>
|
||||
<circle :cx="MITTE" :cy="MITTE" r="26" fill="#0a0a0c" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<button class="dreh" type="button" :disabled="dreht" @click="drehen">
|
||||
<div v-if="host" class="knoepfe">
|
||||
<button class="dreh" type="button" :disabled="dreht || !items.length" @click="drehen">
|
||||
{{ dreht ? 'dreht…' : 'Drehen' }}
|
||||
</button>
|
||||
<button
|
||||
class="reset"
|
||||
type="button"
|
||||
:disabled="dreht || !items.length"
|
||||
@click="zuruecksetzen"
|
||||
>
|
||||
Zurücksetzen
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="gewinner" class="gewinner" @click="oeffnen(gewinner)">
|
||||
<img
|
||||
v-if="posterUrl(gewinner.poster_path, 'w154')"
|
||||
:src="posterUrl(gewinner.poster_path, 'w154')"
|
||||
:alt="gewinner.title"
|
||||
/>
|
||||
<div>
|
||||
<p class="label">Der Film des Abends</p>
|
||||
<h2>{{ gewinner.title }}</h2>
|
||||
<p class="jahr">
|
||||
{{ gewinner.year }}<span v-if="gewinner.name"> · von {{ gewinner.name }}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div v-if="gewinner" class="gewinner" @click="oeffnen(gewinner)">
|
||||
<img
|
||||
v-if="posterUrl(gewinner.poster_path, 'w154')"
|
||||
:src="posterUrl(gewinner.poster_path, 'w154')"
|
||||
:alt="gewinner.title"
|
||||
/>
|
||||
<div>
|
||||
<p class="label">Der Film des Abends</p>
|
||||
<h2>{{ gewinner.title }}</h2>
|
||||
<p class="jahr">
|
||||
{{ gewinner.year }}<span v-if="gewinner.name"> · von {{ gewinner.name }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<aside v-if="items.length" class="liste">
|
||||
<aside class="liste">
|
||||
<h3>Vorschläge <span class="anzahl">{{ items.length }}</span></h3>
|
||||
<p v-if="!items.length && !laden" class="leer">Noch nichts vorgeschlagen.</p>
|
||||
<ul>
|
||||
<li v-for="(item, i) in items" :key="item.id">
|
||||
<button
|
||||
@@ -300,6 +325,35 @@ async function oeffnen(item) {
|
||||
border-left: 11px solid transparent;
|
||||
}
|
||||
|
||||
.knoepfe {
|
||||
display: flex;
|
||||
gap: 0.7rem;
|
||||
}
|
||||
|
||||
.reset {
|
||||
padding: 0.7rem 1.4rem;
|
||||
color: var(--muted);
|
||||
font-size: 0.95rem;
|
||||
background: var(--bg-soft);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.reset:hover:not(:disabled) {
|
||||
color: var(--text);
|
||||
border-color: var(--muted);
|
||||
}
|
||||
|
||||
.reset:disabled {
|
||||
opacity: 0.4;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.leer {
|
||||
color: var(--muted);
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.dreh {
|
||||
padding: 0.7rem 2.2rem;
|
||||
color: #fff;
|
||||
|
||||
Reference in New Issue
Block a user