Files
Lucky_Wheel/apps/client/src/components/wheels/RusticWoodWheel.vue
T
s.esmaeili afde44ab8a fix(core): resolve local client url redirects and stabilize dev environment
- enforce localhost:5174 for wheel campaign client URL in local development
- lock vite dev server ports using strictPort on admin (5173) and client (5174)
- sanitize .env.example and remove hardcoded staging domain
- configure root dev orchestration and docker multi-stage build context
2026-09-13 02:02:46 +03:30

104 lines
4.1 KiB
Vue

<script setup lang="ts">
import { toFarsiDigits, WheelDesignProps } from '@lucky-wheel/shared-types';
import { useWheelFromProps } from '../../composables/useWheelBase';
const props = defineProps<WheelDesignProps>();
const emit = defineEmits<{ (e: 'spin-finished'): void }>();
const { wheelStyle, pointerStyle, getSlicePath, getTextRotation, pegs } = useWheelFromProps(
props,
() => emit('spin-finished'),
{ radius: 138, pegRadius: 143 },
);
const woodFallback = ['#8B5A2B', '#A0522D', '#6B4226', '#C4A484', '#8B5A2B', '#5D4037'];
</script>
<template>
<div class="relative w-full max-w-[340px] xs:max-w-[380px] sm:max-w-[420px] aspect-square mx-auto select-none">
<!-- Rustic wooden bezel -->
<div
class="absolute inset-0 rounded-full p-3 shadow-[0_12px_30px_rgba(60,30,10,0.55)]"
style="background: linear-gradient(145deg, #c9a36a 0%, #6b3f1e 40%, #3e2412 100%)"
>
<div
class="w-full h-full rounded-full border-[3px] border-[#c9a36a] relative overflow-hidden"
style="background: radial-gradient(circle at 40% 35%, #5c3a1e 0%, #2a160c 70%)"
>
<svg class="w-full h-full" :style="wheelStyle" viewBox="0 0 300 300">
<!-- Wood grain rings -->
<circle cx="150" cy="150" r="136" fill="none" stroke="#4a2c14" stroke-width="8" opacity="0.35" />
<circle cx="150" cy="150" r="120" fill="none" stroke="#7a4a22" stroke-width="2" opacity="0.25" />
<g v-for="(seg, idx) in segments" :key="seg.id">
<path
:d="getSlicePath(idx)"
:fill="seg.color || woodFallback[idx % woodFallback.length]"
stroke="#3e2723"
stroke-width="1.5"
/>
<g :transform="getTextRotation(idx)">
<text
x="150"
y="45"
text-anchor="middle"
fill="#fff8e7"
font-size="11"
font-weight="700"
class="wheel-slice-text font-sans"
>
{{ toFarsiDigits(seg.title) }}
</text>
<image v-if="seg.image" :href="seg.image" x="138" y="54" width="24" height="24" />
</g>
</g>
<!-- Metal bolts -->
<g v-for="(peg, pIdx) in pegs" :key="pIdx">
<circle :cx="peg.x" :cy="peg.y" r="4" fill="#2c1810" stroke="#8d6e63" stroke-width="0.8" />
<circle :cx="peg.x" :cy="peg.y" r="2.6" fill="url(#woodBolt)" />
<line
:x1="peg.x - 1.6"
:y1="peg.y"
:x2="peg.x + 1.6"
:y2="peg.y"
stroke="#5d4037"
stroke-width="0.7"
/>
</g>
<circle cx="150" cy="150" r="30" fill="url(#woodHub)" stroke="#d7ccc8" stroke-width="2" />
<circle cx="150" cy="150" r="18" fill="#3e2723" stroke="#a1887f" stroke-width="1.5" />
<text x="150" y="156" text-anchor="middle" font-size="14" fill="#efebe9">🪵</text>
<defs>
<radialGradient id="woodBolt" cx="35%" cy="30%" r="70%">
<stop offset="0%" stop-color="#efebe9" />
<stop offset="50%" stop-color="#9e9e9e" />
<stop offset="100%" stop-color="#424242" />
</radialGradient>
<radialGradient id="woodHub" cx="40%" cy="35%" r="65%">
<stop offset="0%" stop-color="#bcaaa4" />
<stop offset="100%" stop-color="#5d4037" />
</radialGradient>
</defs>
</svg>
</div>
</div>
<div class="absolute -top-3 left-1/2 -translate-x-1/2 z-20 pointer-events-none drop-shadow-lg">
<div :style="pointerStyle" class="w-9 h-[44px] origin-[50%_12px] will-change-transform">
<svg width="36" height="44" viewBox="0 0 36 44" fill="none">
<path
d="M18 44L5 14C3 9 7 3 12 3H24C29 3 33 9 31 14L18 44Z"
fill="#8d6e63"
stroke="#efebe9"
stroke-width="1.5"
/>
<circle cx="18" cy="12" r="4.5" fill="#5d4037" stroke="#d7ccc8" stroke-width="1.2" />
</svg>
</div>
</div>
</div>
</template>