Feat(cambi): supporto cambi multipli con UI migliorata
Consente di effettuare fino a 2 cambi simultanei per squadra con una nuova interfaccia utente più compatta e visuale. Gli input IN sono colorati di verde, gli OUT di rosso, e una freccia indica la direzione del cambio. La validazione permette cambi parziali (campi vuoti) ma richiede che ogni cambio inserito sia completo (sia IN che OUT) e che almeno un cambio sia presente per confermare
This commit is contained in:
@@ -75,29 +75,22 @@
|
|||||||
<w-button class="ma2" @click="selezionaTeamCambi('guest')">{{ sp.nomi.guest }}</w-button>
|
<w-button class="ma2" @click="selezionaTeamCambi('guest')">{{ sp.nomi.guest }}</w-button>
|
||||||
</w-flex>
|
</w-flex>
|
||||||
</w-dialog>
|
</w-dialog>
|
||||||
<w-dialog v-model="diaCambi.show" :width="520" @close="chiudiDialogCambi">
|
<w-dialog v-model="diaCambi.show" :width="360" @close="chiudiDialogCambi">
|
||||||
<div class="text-bold text-center mb2">CAMBI</div>
|
<div class="cambi-dialog">
|
||||||
<table class="cambi-table">
|
<div class="cambi-title">{{ sp.nomi[diaCambi.team] }}: CAMBIO</div>
|
||||||
<thead>
|
<div class="cambi-rows">
|
||||||
<tr>
|
<div class="cambi-row">
|
||||||
<th></th>
|
<w-input v-model="diaCambi[diaCambi.team].cambi[0].in" type="text" class="cambi-input cambi-in"></w-input>
|
||||||
<th>IN</th>
|
<span class="cambi-arrow">→</span>
|
||||||
<th>OUT</th>
|
<w-input v-model="diaCambi[diaCambi.team].cambi[0].out" type="text" class="cambi-input cambi-out"></w-input>
|
||||||
</tr>
|
</div>
|
||||||
</thead>
|
<div class="cambi-row">
|
||||||
<tbody>
|
<w-input v-model="diaCambi[diaCambi.team].cambi[1].in" type="text" class="cambi-input cambi-in"></w-input>
|
||||||
<tr v-if="diaCambi.team === 'home'">
|
<span class="cambi-arrow">→</span>
|
||||||
<td class="row-label">{{ sp.nomi.home }}</td>
|
<w-input v-model="diaCambi[diaCambi.team].cambi[1].out" type="text" class="cambi-input cambi-out"></w-input>
|
||||||
<td><w-input v-model="diaCambi.home.in" type="text" class="cambi-input"></w-input></td>
|
</div>
|
||||||
<td><w-input v-model="diaCambi.home.out" type="text" class="cambi-input"></w-input></td>
|
</div>
|
||||||
</tr>
|
</div>
|
||||||
<tr v-if="diaCambi.team === 'guest'">
|
|
||||||
<td class="row-label">{{ sp.nomi.guest }}</td>
|
|
||||||
<td><w-input v-model="diaCambi.guest.in" type="text" class="cambi-input"></w-input></td>
|
|
||||||
<td><w-input v-model="diaCambi.guest.out" type="text" class="cambi-input"></w-input></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<w-flex justify-end class="pa3">
|
<w-flex justify-end class="pa3">
|
||||||
<w-button bg-color="success" :disabled="!cambiConfermabili" @click="confermaCambi">
|
<w-button bg-color="success" :disabled="!cambiConfermabili" @click="confermaCambi">
|
||||||
CONFERMA
|
CONFERMA
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ export default {
|
|||||||
diaCambi: {
|
diaCambi: {
|
||||||
show: false,
|
show: false,
|
||||||
team: "home",
|
team: "home",
|
||||||
guest: { in: "", out: "" },
|
guest: { cambi: [{ in: "", out: "" }, { in: "", out: "" }] },
|
||||||
home: { in: "", out: "" },
|
home: { cambi: [{ in: "", out: "" }, { in: "", out: "" }] },
|
||||||
},
|
},
|
||||||
diaCambiTeam: {
|
diaCambiTeam: {
|
||||||
show: false,
|
show: false,
|
||||||
@@ -54,10 +54,25 @@ export default {
|
|||||||
},
|
},
|
||||||
cambiConfermabili() {
|
cambiConfermabili() {
|
||||||
const team = this.diaCambi.team;
|
const team = this.diaCambi.team;
|
||||||
const teamIn = (this.diaCambi[team].in || "").trim();
|
const cambi = this.diaCambi[team].cambi || [];
|
||||||
const teamOut = (this.diaCambi[team].out || "").trim();
|
let hasComplete = false;
|
||||||
|
let allValid = true;
|
||||||
|
|
||||||
return !!teamIn && !!teamOut;
|
cambi.forEach((cambio) => {
|
||||||
|
const teamIn = (cambio.in || "").trim();
|
||||||
|
const teamOut = (cambio.out || "").trim();
|
||||||
|
|
||||||
|
if (!teamIn && !teamOut) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!teamIn || !teamOut) {
|
||||||
|
allValid = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hasComplete = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return allValid && hasComplete;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -233,8 +248,10 @@ export default {
|
|||||||
resettaCambi(team) {
|
resettaCambi(team) {
|
||||||
const teams = team ? [team] : ["home", "guest"];
|
const teams = team ? [team] : ["home", "guest"];
|
||||||
teams.forEach((t) => {
|
teams.forEach((t) => {
|
||||||
this.diaCambi[t].in = "";
|
this.diaCambi[t].cambi.forEach((cambio) => {
|
||||||
this.diaCambi[t].out = "";
|
cambio.in = "";
|
||||||
|
cambio.out = "";
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
apriDialogCambi() {
|
apriDialogCambi() {
|
||||||
@@ -262,31 +279,38 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const team = this.diaCambi.team;
|
const team = this.diaCambi.team;
|
||||||
const cambio = {
|
const cambi = (this.diaCambi[team].cambi || [])
|
||||||
team,
|
.map((cambio) => ({
|
||||||
in: (this.diaCambi[team].in || "").trim(),
|
team,
|
||||||
out: (this.diaCambi[team].out || "").trim(),
|
in: (cambio.in || "").trim(),
|
||||||
};
|
out: (cambio.out || "").trim(),
|
||||||
|
}))
|
||||||
|
.filter((cambio) => cambio.in || cambio.out);
|
||||||
|
|
||||||
const form = this.sp.form[cambio.team].map((val) => String(val).trim());
|
const form = this.sp.form[team].map((val) => String(val).trim());
|
||||||
|
const formAggiornata = [...form];
|
||||||
|
|
||||||
if (form.includes(cambio.in)) {
|
for (const cambio of cambi) {
|
||||||
this.$waveui.notify(`Numero ${cambio.in} già presente in formazione ${cambio.team}`, "warning");
|
if (cambio.in === cambio.out) {
|
||||||
return;
|
this.$waveui.notify(`Numero IN e OUT uguali per ${cambio.team}`, "warning");
|
||||||
}
|
return;
|
||||||
if (!form.includes(cambio.out)) {
|
}
|
||||||
this.$waveui.notify(`Numero ${cambio.out} non presente in formazione ${cambio.team}`, "warning");
|
if (formAggiornata.includes(cambio.in)) {
|
||||||
return;
|
this.$waveui.notify(`Numero ${cambio.in} già presente in formazione ${cambio.team}`, "warning");
|
||||||
}
|
return;
|
||||||
if (cambio.in === cambio.out) {
|
}
|
||||||
this.$waveui.notify(`Numero IN e OUT uguali per ${cambio.team}`, "warning");
|
if (!formAggiornata.includes(cambio.out)) {
|
||||||
return;
|
this.$waveui.notify(`Numero ${cambio.out} non presente in formazione ${cambio.team}`, "warning");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const idx = formAggiornata.findIndex((val) => String(val).trim() === cambio.out);
|
||||||
|
if (idx !== -1) {
|
||||||
|
formAggiornata.splice(idx, 1, cambio.in);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const idx = this.sp.form[cambio.team].findIndex((val) => String(val).trim() === cambio.out);
|
this.sp.form[team] = formAggiornata;
|
||||||
if (idx !== -1) {
|
|
||||||
this.sp.form[cambio.team].splice(idx, 1, cambio.in);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.chiudiDialogCambi();
|
this.chiudiDialogCambi();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -191,27 +191,74 @@ button:focus-visible {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cambi-table {
|
.cambi-rows {
|
||||||
width: 100%;
|
display: flex;
|
||||||
border-collapse: collapse;
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 8px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cambi-table th,
|
.cambi-dialog {
|
||||||
.cambi-table td {
|
padding: 8px 6px 2px;
|
||||||
padding: 8px;
|
}
|
||||||
|
|
||||||
|
.cambi-title {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
padding-bottom: 6px;
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cambi-table th {
|
.cambi-row {
|
||||||
font-weight: bold;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cambi-table .row-label {
|
.cambi-arrow {
|
||||||
text-align: left;
|
font-weight: 700;
|
||||||
font-weight: bold;
|
font-size: 18px;
|
||||||
width: 90px;
|
line-height: 1;
|
||||||
|
padding: 6px 8px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cambi-input {
|
.cambi-input {
|
||||||
min-width: 110px;
|
min-width: 48px;
|
||||||
|
max-width: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cambi-input input,
|
||||||
|
.cambi-input .w-input__input,
|
||||||
|
.cambi-input .w-input__field {
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.35);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
color: #000;
|
||||||
|
text-align: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cambi-in input,
|
||||||
|
.cambi-in .w-input__input,
|
||||||
|
.cambi-in .w-input__field {
|
||||||
|
background: rgba(120, 200, 120, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cambi-out input,
|
||||||
|
.cambi-out .w-input__input,
|
||||||
|
.cambi-out .w-input__field {
|
||||||
|
background: rgba(200, 120, 120, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cambi-input input:focus,
|
||||||
|
.cambi-input .w-input__input:focus,
|
||||||
|
.cambi-input .w-input__field:focus {
|
||||||
|
border-color: rgba(255, 255, 255, 0.7);
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user