Update dependencies, containerize, add build workflow
All checks were successful
Build / build (push) Successful in 1m14s
All checks were successful
Build / build (push) Successful in 1m14s
This commit is contained in:
parent
ae1c71f4c5
commit
88f0632194
38 changed files with 1139 additions and 829 deletions
72
frontend/screens/DirectorScreen.vue
Normal file
72
frontend/screens/DirectorScreen.vue
Normal file
|
@ -0,0 +1,72 @@
|
|||
<template>
|
||||
<div class="flex gap-6 p-4">
|
||||
<section class="w-80">
|
||||
<div class="font-bold text-2xl pb-2">Raum</div>
|
||||
<div class="flex flex-col overflow-y-auto bg-dark-900 bg-opacity-50 h-80vh">
|
||||
<template
|
||||
v-for="(room, index) in script.roomsById.values()"
|
||||
:key="room.id"
|
||||
>
|
||||
<div v-if="index !== 0" class="w-full h-1px bg-dark-300"/>
|
||||
<div class="flex-shrink-0 bg-dark-600 flex items-center">
|
||||
<div class="px-3 py-2 flex-grow">
|
||||
{{ room.label }}
|
||||
</div>
|
||||
<button v-if="game.currentRoomId === room.id" disabled class="bg-green-900 h-full px-3 text-sm cursor-not-allowed">
|
||||
Aktiv
|
||||
</button>
|
||||
<button v-else class="bg-dark-300 h-full px-3 text-sm" @click="game.switchRoom(room.id)">
|
||||
Aktivieren
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</section>
|
||||
<section class="flex-grow">
|
||||
<div class="font-bold text-2xl pb-2">Versteckte Objekte</div>
|
||||
<div class="grid gap-3 grid-cols-2 flex-grow auto-rows-min p-4 pt-0 relative">
|
||||
<button
|
||||
v-for="object in game.allObjectsById.values().filter(o => !game.visibleObjectIds.has(o.id))"
|
||||
:key="object.id"
|
||||
class="flex flex-col items-center gap-2 bg-dark-600 rounded-lg p-3"
|
||||
@click="game.setObjectVisibility(object.id, true)"
|
||||
>
|
||||
<ObjectPicture :object-id="object.id"/>
|
||||
<span class="text-sm text-gray-200 text-center">
|
||||
{{ object.label }}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
<section class="w-80">
|
||||
<div class="font-bold text-2xl pb-2">Interaktionen</div>
|
||||
<transition name="fade" mode="out-in">
|
||||
<div v-if="game.sortedInteractionQueue.length === 0" class="text-xl text-gray-200">
|
||||
Keine Interaktionen vorhanden.
|
||||
</div>
|
||||
<transition-group v-else tag="div" name="list" class="flex flex-col gap-4 relative h-80vh">
|
||||
<InteractionQueueItemCard
|
||||
v-for="(item, index) in game.sortedInteractionQueue"
|
||||
:key="item.id"
|
||||
:style="{ zIndex: 1000 - index }"
|
||||
:item="item"
|
||||
mode="director"
|
||||
/>
|
||||
</transition-group>
|
||||
</transition>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style module lang="scss">
|
||||
|
||||
</style>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { script } from "../../shared/script"
|
||||
import { useGame } from "../game"
|
||||
import ObjectPicture from "../components/ObjectPicture.vue"
|
||||
import InteractionQueueItemCard from "../components/InteractionQueueItemCard.vue"
|
||||
|
||||
const game = useGame()
|
||||
</script>
|
115
frontend/screens/InteractionsScreen.vue
Normal file
115
frontend/screens/InteractionsScreen.vue
Normal file
|
@ -0,0 +1,115 @@
|
|||
<template>
|
||||
<div class="h-full flex flex-col relative">
|
||||
<div class="flex-shrink-0 flex order-1">
|
||||
<ObjectCardDropZone
|
||||
label="Benutzen"
|
||||
class="bg-green-800"
|
||||
:has-floating="useFloatingObjectIds.size > 0"
|
||||
@object-change="(v, i) => createSetInclusionSetter(useFloatingObjectIds)(v, i)"
|
||||
@object-drop="onObjectUseDrop"
|
||||
/>
|
||||
<ObjectCardDropZone
|
||||
label="Kombinieren"
|
||||
class="bg-blue-900"
|
||||
:has-floating="combineFloatingObjectIds.size > 0"
|
||||
@object-change="(v, i) => createSetInclusionSetter(combineFloatingObjectIds)(v, i)"
|
||||
@object-drop="onObjectInteractionDrop"
|
||||
/>
|
||||
</div>
|
||||
<transition-group tag="div" name="list" class="grid gap-3 grid-cols-2 flex-grow auto-rows-min p-4 pt-0 relative">
|
||||
<ObjectCard
|
||||
v-for="object in game.visibleObjectsById.values()"
|
||||
:key="object.id"
|
||||
:object="object"
|
||||
:is-over-dropzone="allFloatingObjectIds.has(object.id)"
|
||||
:marked-for="getMarkedFor(object.id)"
|
||||
@drag-start="onObjectDragStart"
|
||||
@drag-end="onObjectDragEnd"
|
||||
/>
|
||||
</transition-group>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style module lang="scss">
|
||||
|
||||
</style>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ObjectCard from "../components/ObjectCard.vue"
|
||||
import { useGame } from "../game"
|
||||
import { computed, reactive, ref } from "vue"
|
||||
import { useScrollLock } from "@vueuse/core"
|
||||
import ObjectCardDropZone from "../components/ObjectCardDropZone.vue"
|
||||
|
||||
const game = useGame()
|
||||
|
||||
const dragCounter = ref(0)
|
||||
|
||||
const useFloatingObjectIds = reactive(new Set())
|
||||
const combineFloatingObjectIds = reactive(new Set())
|
||||
const allFloatingObjectIds = computed(() => new Set([...useFloatingObjectIds, ...combineFloatingObjectIds]))
|
||||
|
||||
const firstCombinationObjectId = ref<null | string>(null)
|
||||
|
||||
function createSetInclusionSetter<T>(set: Set<T>) {
|
||||
return (value: T, isIncluded: boolean) => {
|
||||
if (isIncluded) set.add(value)
|
||||
else set.delete(value)
|
||||
}
|
||||
}
|
||||
|
||||
function getMarkedFor(objectId: string) {
|
||||
if (firstCombinationObjectId.value !== null) {
|
||||
if (firstCombinationObjectId.value === objectId) return "combine-first"
|
||||
} else if (game.currentInteraction !== null) {
|
||||
switch (game.currentInteraction.type) {
|
||||
case "use":
|
||||
if (game.currentInteraction.objectId === objectId) return "use"
|
||||
break
|
||||
|
||||
case "combine":
|
||||
if (game.currentInteraction.objectIds.has(objectId)) return "combine"
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function onObjectDragStart() {
|
||||
dragCounter.value++
|
||||
}
|
||||
|
||||
function onObjectDragEnd() {
|
||||
dragCounter.value--
|
||||
if (dragCounter.value <= 0) {
|
||||
// lock scrolling?
|
||||
}
|
||||
}
|
||||
|
||||
function onObjectUseDrop(objectId: string) {
|
||||
game.voteForInteraction({
|
||||
type: "use",
|
||||
objectId
|
||||
})
|
||||
}
|
||||
|
||||
function onObjectInteractionDrop(objectId: string) {
|
||||
if (firstCombinationObjectId.value === null) {
|
||||
game.revokeCurrentInteractionVote()
|
||||
firstCombinationObjectId.value = objectId
|
||||
} else {
|
||||
if (firstCombinationObjectId.value === objectId) {
|
||||
firstCombinationObjectId.value = null
|
||||
return
|
||||
}
|
||||
|
||||
game.voteForInteraction({
|
||||
type: "combine",
|
||||
objectIds: new Set([firstCombinationObjectId.value, objectId])
|
||||
})
|
||||
|
||||
firstCombinationObjectId.value = null
|
||||
}
|
||||
}
|
||||
</script>
|
40
frontend/screens/QueueScreen.vue
Normal file
40
frontend/screens/QueueScreen.vue
Normal file
|
@ -0,0 +1,40 @@
|
|||
<template>
|
||||
<div class="h-full p-4 pt-0">
|
||||
<transition name="fade" mode="out-in">
|
||||
<div v-if="game.sortedInteractionQueue.length === 0" class="h-full flex flex-col justify-center items-center gap-4 p-6">
|
||||
<div class="text-xl text-center text-gray-200">
|
||||
Noch keine Interaktionen zum Abstimmen vorhanden.
|
||||
</div>
|
||||
<button class="flex items-center gap-2 px-4 py-2 rounded-lg bg-green-800 text-lg" @click="emit('switch-screen', 'interactions')">
|
||||
<ArrowRightIcon/>
|
||||
<span class="relative top-1px">Interagieren</span>
|
||||
</button>
|
||||
</div>
|
||||
<transition-group v-else tag="div" name="list" class="flex flex-col gap-4 relative">
|
||||
<InteractionQueueItemCard
|
||||
v-for="(item, index) in game.sortedInteractionQueue"
|
||||
:key="item.id"
|
||||
:style="{ zIndex: 1000 - index }"
|
||||
:item="item"
|
||||
mode="audience"
|
||||
/>
|
||||
</transition-group>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
|
||||
<script setup lang="ts">
|
||||
import InteractionQueueItemCard from "../components/InteractionQueueItemCard.vue"
|
||||
import { useGame } from "../game"
|
||||
import ArrowRightIcon from "virtual:icons/ph/arrow-right"
|
||||
|
||||
const emit = defineEmits<{
|
||||
"switch-screen": [string]
|
||||
}>()
|
||||
|
||||
const game = useGame()
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue