Skip to content

Commit

Permalink
Merge branch 'feature/knockout-bracket'
Browse files Browse the repository at this point in the history
  • Loading branch information
phrasmotica committed Apr 27, 2024
2 parents cc3adfa + 48c1f41 commit 8c7a158
Show file tree
Hide file tree
Showing 14 changed files with 482 additions and 40 deletions.
57 changes: 57 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"test": "vitest"
},
"dependencies": {
"@panzoom/panzoom": "^4.5.1",
"@vueuse/core": "^10.8.0",
"date-fns": "^3.3.1",
"html2canvas": "^1.4.1",
Expand All @@ -23,6 +24,7 @@
"primevue": "^3.51.0",
"uuid": "^9.0.1",
"vue": "^3.4.15",
"vue-dragscroll": "^4.0.5",
"vue-i18n": "^9.9.1",
"vue-router": "^4.2.5",
"vuedraggable": "^4.1.0"
Expand Down
133 changes: 133 additions & 0 deletions src/components/modals/BracketModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<script setup lang="ts">
import Panzoom, { type PanzoomObject } from '@panzoom/panzoom'
import { ref, watch } from "vue"
import { useI18n } from "vue-i18n"
import KnockoutBracket from "../play/KnockoutBracket.vue"
import { useZoomLevel } from "@/composables/useZoomLevel"
const { t } = useI18n()
const visible = defineModel<boolean>("visible", {
default: false,
})
const {
currentLevel,
currentPercentage,
minZoom,
maxZoom,
isMinZoom,
isMaxZoom,
zoomIn,
zoomOut,
resetZoom,
// BUG: zoom levels less than 1 do not play nicely, due to the
// contain: 'outside' option on line 52. Try to find a workaround...
} = useZoomLevel([1, 1.25, 1.5, 1.75, 2], 1)
watch(currentLevel, () => {
panzoom.value?.zoom(currentLevel.value, {
animate: true,
})
})
const panzoom = ref<PanzoomObject>()
const show = () => {
fixButtonsWidth()
createPanzoom()
}
const fixButtonsWidth = () => {
// ensures the zoom buttons are in the actual centre of the modal header
const zoomButtons = document.getElementById('zoomButtons')
if (!zoomButtons) {
return
}
const modalButtons = <HTMLElement>document.getElementsByClassName('p-dialog-header-icons')[0]
const newMargin = modalButtons?.offsetWidth || 0
zoomButtons.style.marginLeft = `${newMargin}px`
}
const createPanzoom = () => {
const orgChartTable = document
.getElementById('bracketDiv')
?.getElementsByTagName("table")[0]
if (!orgChartTable) {
return
}
// matches empty org chart line cell at the bottom of the bracket
orgChartTable.style.paddingTop = "20px"
panzoom.value = Panzoom(orgChartTable, {
minScale: minZoom.value,
maxScale: maxZoom.value,
contain: 'outside',
cursor: 'grab',
})
}
</script>

<template>
<Dialog
modal
maximizable
class="bracket-modal"
v-model:visible="visible"
:header="t('bracket.knockoutBracket')"
@show="show">
<template #header>
<div
id="zoomButtons"
class="flex justify-content-center flex-grow-1 gap-2">
<Button
class="w-5rem"
icon="pi pi-search-minus"
:disabled="isMinZoom"
@click="() => zoomOut()" />

<Button
class="w-5rem text-xl p-0"
:label="currentPercentage + '%'"
severity="secondary"
@click="() => resetZoom()" />

<Button
class="w-5rem"
icon="pi pi-search-plus"
:disabled="isMaxZoom"
@click="() => zoomIn()" />
</div>
</template>

<div id="bracketDiv">
<KnockoutBracket />
</div>
</Dialog>
</template>

<style>
.bracket-modal {
max-width: 90vw;
}
.bracket-modal.p-dialog-maximized {
max-width: 100vw;
}
.grab {
cursor: grab!important;
}
/* BUG: this is not applying when we put the mouse down on the panzoom child */
.grabbing {
cursor: grabbing!important;
}
</style>
38 changes: 23 additions & 15 deletions src/components/play/FixtureCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const props = defineProps<{
fixture: Fixture
highlightedFixtureId: string
showComment: boolean
vertical?: boolean
static?: boolean
}>()
const emit = defineEmits<{
Expand Down Expand Up @@ -82,21 +84,27 @@ const fixtureCardClass = (fixture: Fixture) => [
</div>

<div class="grid m-0 py-1">
<ScoreCard
:fixture="fixture"
:scoreIndex="0"
position="left"
:highlightedFixtureId="props.highlightedFixtureId"
@showModal="emit('showModal')"
@highlight="emit('highlight')" />

<ScoreCard
:fixture="fixture"
:scoreIndex="1"
position="right"
:highlightedFixtureId="props.highlightedFixtureId"
@showModal="emit('showModal')"
@highlight="emit('highlight')" />
<div class="col-6 p-0" :class="props.vertical && 'col-12'">
<ScoreCard
:static="props.static"
:fixture="fixture"
:scoreIndex="0"
position="left"
:highlightedFixtureId="props.highlightedFixtureId"
@showModal="emit('showModal')"
@highlight="emit('highlight')" />
</div>

<div class="col-6 p-0" :class="props.vertical && 'col-12 mt-2'">
<ScoreCard
:static="props.static"
:fixture="fixture"
:scoreIndex="1"
:position="props.vertical ? 'left' : 'right'"
:highlightedFixtureId="props.highlightedFixtureId"
@showModal="emit('showModal')"
@highlight="emit('highlight')" />
</div>
</div>

<div v-if="props.showComment && fixture.comment">
Expand Down
33 changes: 33 additions & 0 deletions src/components/play/KnockoutBracket.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<script setup lang="ts">
import FixtureCard from "./FixtureCard.vue"
import { useFlyer } from "@/composables/useFlyer"
import { useKnockout } from "@/composables/useKnockout"
import { useFlyerStore } from "@/stores/flyer"
const flyerStore = useFlyerStore()
const {
currentPhase,
} = useFlyer(flyerStore.flyer)
const {
bracketData,
} = useKnockout(currentPhase.value)
</script>

<template>
<OrganizationChart :value="bracketData">
<template #default="{ node }">
<div style="width: 12vw;">
<FixtureCard
vertical
static
:fixture="node.data"
highlightedFixtureId=""
:showComment="false" />
</div>
</template>
</OrganizationChart>
</template>
Loading

0 comments on commit 8c7a158

Please sign in to comment.