Files
Vulture/VApp/src/components/CardButtonScore.vue
2026-02-01 13:53:36 +01:00

166 lines
5.1 KiB
Vue

<template>
<v-card tile outlined :class="{ 'card--reduced': isCardReduced }">
<v-card-title class="card__title primary" @click="toggleCardSize">
<v-icon left class="white--text pr-5 pl-2" size="40">mdi-calculator-variant</v-icon>
Gestion des scores
</v-card-title>
<v-container class="text-center pt-8">
<!-- Team Lines -->
<v-row v-for="(team, color) in scores" :key="color" align="center" justify="center" class="mb-2">
<!-- Icon/Label -->
<v-col cols="2" class="d-flex justify-center">
<v-icon :color="getTeamColor(color)" size="40">mdi-circle</v-icon>
</v-col>
<!-- Total Score Input -->
<v-col cols="5">
<v-text-field
v-model.number="team.Total"
label="Total"
type="number"
variant="outlined"
density="compact"
hide-details
prepend-inner-icon="mdi-minus"
append-inner-icon="mdi-plus"
:color="getTeamColor(color)"
:base-color="getTeamColor(color)"
@click:prepend-inner="changeScore(color, 'Total', -1)"
@click:append-inner="changeScore(color, 'Total', 1)"
@update:model-value="updateScore(color)"
class="centered-input"
readonly
></v-text-field>
</v-col>
<!-- Round Score Input -->
<v-col cols="5">
<v-text-field
v-model.number="team.Round"
label="Manche"
type="number"
variant="outlined"
density="compact"
hide-details
prepend-inner-icon="mdi-minus"
append-inner-icon="mdi-plus"
:color="getTeamColor(color)"
:base-color="getTeamColor(color)"
@click:prepend-inner="changeScore(color, 'Round', -1)"
@click:append-inner="changeScore(color, 'Round', 1)"
@update:model-value="updateScore(color)"
class="centered-input"
readonly
></v-text-field>
</v-col>
</v-row>
</v-container>
</v-card>
</template>
<script setup>
import { ref, reactive, onMounted, onUnmounted } from 'vue';
import mqtt from 'mqtt';
import config from '@/config.js'; // Ensure correct path
const isCardReduced = ref(false);
const scores = reactive({
Red: { Total: 0, Round: 0 },
Blue: { Total: 0, Round: 0 },
Yellow: { Total: 0, Round: 0 },
Green: { Total: 0, Round: 0 },
});
// const client = mqtt.connect(config.mqttBrokerUrl);
let client = null;
onMounted(() => {
client = mqtt.connect(config.mqttBrokerUrl);
client.on('connect', () => {
console.log('CardButtonScore: Connected to MQTT broker at', config.mqttBrokerUrl);
client.subscribe('game/score');
});
client.on('error', (err) => {
console.error('CardButtonScore: MQTT Error:', err);
});
client.on('message', (topic, message) => {
if (topic === 'game/score') {
try {
const data = JSON.parse(message.toString());
console.log('CardButtonScore: Received score update:', data);
if (data && data.TEAM) {
Object.keys(scores).forEach(color => {
if (data.TEAM[color]) {
scores[color].Total = data.TEAM[color].TotalScore;
scores[color].Round = data.TEAM[color].RoundScore;
}
});
}
} catch (e) {
console.error("Error parsing score update:", e);
}
}
});
});
onUnmounted(() => {
if (client) {
client.end();
}
});
function toggleCardSize() {
isCardReduced.value = !isCardReduced.value;
}
function getTeamColor(color) {
if (color === 'Yellow') return '#D4D100'; // Custom yellow
if (color === 'Red') return '#d42828';
if (color === 'Blue') return '#2867d4';
if (color === 'Green') return '#28d42e';
return color.toLowerCase();
}
function changeScore(teamColor, field, delta) {
scores[teamColor][field] += delta;
updateScore(teamColor);
}
function updateScore(teamColor) {
const payload = {
[teamColor]: {
Total: scores[teamColor].Total,
Round: scores[teamColor].Round
}
};
console.log('CardButtonScore: Publishing update:', payload);
client.publish('game/score/update', JSON.stringify(payload));
}
</script>
<style>
.card--reduced {
height: 56px;
width: 60%; /* Adjusted width for layout */
overflow: hidden;
transition: height 0.3s ease-in-out;
}
.centered-input input {
text-align: center;
}
.centered-input .v-field__label {
text-align: center;
}
/* Remove number spin buttons */
.centered-input input[type=number]::-webkit-inner-spin-button,
.centered-input input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
</style>