store raffles, wheel of fortune
This commit is contained in:
parent
1645b3be50
commit
fd3ac2c9fc
5 changed files with 127 additions and 5 deletions
|
@ -3,12 +3,12 @@
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@apply min-h-screen bg-slate-900 text-slate-100 leading-relaxed;
|
@apply min-h-screen m-0 p-0 bg-slate-900 text-slate-100 leading-relaxed;
|
||||||
transition: color 0.3s, background-color 0.2s;
|
transition: color 0.3s, background-color 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
@apply flex justify-around items-center w-screen min-h-screen m-0 p-4;
|
@apply flex justify-around items-center w-screen min-h-screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
button, input {
|
button, input {
|
||||||
|
|
|
@ -11,6 +11,7 @@ export default function useRaffle() {
|
||||||
const raffleStore = useStorage<Raffle[]>('', EMPTY_STORE)
|
const raffleStore = useStorage<Raffle[]>('', EMPTY_STORE)
|
||||||
|
|
||||||
const newRaffle = ref<Raffle>({
|
const newRaffle = ref<Raffle>({
|
||||||
|
id: genId(),
|
||||||
title: '',
|
title: '',
|
||||||
date: new Date().toLocaleDateString('de'),
|
date: new Date().toLocaleDateString('de'),
|
||||||
participants: [],
|
participants: [],
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useHead } from '@vueuse/head'
|
import { useHead } from '@vueuse/head'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
import useRaffle from '../composables/useRaffle'
|
import useRaffle from '../composables/useRaffle'
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
|
@ -19,13 +20,27 @@ const showNewRaffleForm = $ref(false)
|
||||||
|
|
||||||
function startRaffle() {
|
function startRaffle() {
|
||||||
if (!readyToRaffle) return
|
if (!readyToRaffle) return
|
||||||
//
|
|
||||||
|
raffleStore.value.push(newRaffle.value)
|
||||||
|
const router = useRouter()
|
||||||
|
router.push(`/raffle/${newRaffle.value.id}`)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<header>
|
<header>
|
||||||
<h1 class="text-4xl">Raffle Me That!</h1>
|
<h1 class="text-4xl">Raffle Me That!</h1>
|
||||||
|
|
||||||
|
<div class="mt-8" v-if="raffleStore.length">
|
||||||
|
<strong>Select Existing:</strong>
|
||||||
|
<ul>
|
||||||
|
<li v-for="raffle in raffleStore">
|
||||||
|
<router-link :to="`/raffle/${raffle.id}`">
|
||||||
|
{{ raffle.title }}
|
||||||
|
</router-link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
|
|
|
@ -1,6 +1,111 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { onMounted } from 'vue'
|
||||||
import { useHead } from '@vueuse/head'
|
import { useHead } from '@vueuse/head'
|
||||||
useHead({
|
import { useStorage } from '@vueuse/core'
|
||||||
title: 'Lets go!',
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const raffleId = route.params.id as string
|
||||||
|
|
||||||
|
const raffleStore = useStorage<Raffle[]>('', [])
|
||||||
|
const raffle = raffleStore.value.find(r => r.id === raffleId)
|
||||||
|
|
||||||
|
const participants = $computed(() => {
|
||||||
|
return raffle ? raffle.participants : []
|
||||||
|
})
|
||||||
|
|
||||||
|
const amount = $computed(() => participants.length)
|
||||||
|
let aligned = $ref(false) // used for animation
|
||||||
|
|
||||||
|
function degrees(index: number) {
|
||||||
|
if (!aligned) return 0
|
||||||
|
return (360 / amount) * index
|
||||||
|
}
|
||||||
|
|
||||||
|
useHead({ title: raffle ? raffle.title : 'Lets Go' })
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
aligned = true
|
||||||
|
}, 100)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="relative w-screen h-screen overflow-hidden flex justify-end items-center">
|
||||||
|
<ol class="absolute top-0 -left-1/2 w-screen h-screen transition-transform duration-500 ease-in" :class="aligned ? 'aligned' : 'shifted'">
|
||||||
|
<li v-for="(participant, i) in participants"
|
||||||
|
class="slice"
|
||||||
|
:style="`
|
||||||
|
transform: rotate(${degrees(i)}deg);
|
||||||
|
`"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
{{ participant }}bcdef ghijklmn
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<div class="absolute top-1/2 left-1/2 w-32 h-32 -ml-16 -mt-16 rounded-full bg-black"></div>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.shifted {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
.aligned {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
.slice {
|
||||||
|
--w: 50vw;
|
||||||
|
--h: calc(6.283185307179586 * var(--w) / v-bind(amount));
|
||||||
|
position: absolute;
|
||||||
|
width: var(--w);
|
||||||
|
height: var(--h);
|
||||||
|
left: 50%;
|
||||||
|
top: 28%;
|
||||||
|
padding: 0;
|
||||||
|
text-align: right;
|
||||||
|
transform-origin: left center;
|
||||||
|
transition: transform 1s ease-out .4s;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
.slice:nth-child(even) {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
.slice::before, .slice::after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-style: solid;
|
||||||
|
}
|
||||||
|
.slice::before {
|
||||||
|
margin-bottom: -1px;
|
||||||
|
border-width: 0 0 calc(var(--h) / 2) calc(var(--w) * .97);
|
||||||
|
border-color: transparent transparent #0074D9 transparent;
|
||||||
|
}
|
||||||
|
.slice:nth-child(even)::before {
|
||||||
|
border-color: transparent transparent #2ECC40 transparent;
|
||||||
|
}
|
||||||
|
.slice::after {
|
||||||
|
border-width: 0 calc(var(--w) * .97) calc(var(--h) / 2) 0;
|
||||||
|
border-color: transparent #0074D9 transparent transparent;
|
||||||
|
}
|
||||||
|
.slice:nth-child(even)::after {
|
||||||
|
border-color: transparent #2ECC40 transparent transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slice > div {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
width: 85%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
1
src/types.d.ts
vendored
1
src/types.d.ts
vendored
|
@ -1,5 +1,6 @@
|
||||||
declare global {
|
declare global {
|
||||||
type Raffle = {
|
type Raffle = {
|
||||||
|
id: string
|
||||||
title: string
|
title: string
|
||||||
date: string
|
date: string
|
||||||
participants: string[]
|
participants: string[]
|
||||||
|
|
Loading…
Add table
Reference in a new issue