feat: card for team
This commit is contained in:
parent
d749dea6f4
commit
9018ecef12
@ -6,6 +6,9 @@ import lombok.AllArgsConstructor;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import org.hibernate.annotations.CreationTimestamp;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@ -27,6 +30,12 @@ public class CardModel {
|
|||||||
Long competition;
|
Long competition;
|
||||||
|
|
||||||
CardType type;
|
CardType type;
|
||||||
|
String reason;
|
||||||
|
@CreationTimestamp
|
||||||
|
Date date;
|
||||||
|
|
||||||
|
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||||
|
boolean teamCard = false;
|
||||||
|
|
||||||
public enum CardType {
|
public enum CardType {
|
||||||
BLUE,
|
BLUE,
|
||||||
|
|||||||
@ -0,0 +1,38 @@
|
|||||||
|
package fr.titionfire.ffsaf.data.model;
|
||||||
|
|
||||||
|
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.hibernate.annotations.CreationTimestamp;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@RegisterForReflection
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "card_team")
|
||||||
|
public class ClubCardModel {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
Long id;
|
||||||
|
|
||||||
|
Long competition;
|
||||||
|
String teamUuid;
|
||||||
|
String teamName;
|
||||||
|
|
||||||
|
CardModel.CardType type;
|
||||||
|
String reason;
|
||||||
|
@CreationTimestamp
|
||||||
|
Date date;
|
||||||
|
|
||||||
|
List<Long> cardIds;
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package fr.titionfire.ffsaf.data.repository;
|
||||||
|
|
||||||
|
import fr.titionfire.ffsaf.data.model.ClubCardModel;
|
||||||
|
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class ClubCardRepository implements PanacheRepositoryBase<ClubCardModel, Long> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,11 +1,13 @@
|
|||||||
package fr.titionfire.ffsaf.domain.service;
|
package fr.titionfire.ffsaf.domain.service;
|
||||||
|
|
||||||
import fr.titionfire.ffsaf.data.model.CardModel;
|
import fr.titionfire.ffsaf.data.model.CardModel;
|
||||||
|
import fr.titionfire.ffsaf.data.model.ClubCardModel;
|
||||||
|
import fr.titionfire.ffsaf.data.model.CompetitionModel;
|
||||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||||
import fr.titionfire.ffsaf.data.repository.CardRepository;
|
import fr.titionfire.ffsaf.data.repository.*;
|
||||||
import fr.titionfire.ffsaf.domain.entity.MatchEntity;
|
|
||||||
import fr.titionfire.ffsaf.rest.exception.DBadRequestException;
|
import fr.titionfire.ffsaf.rest.exception.DBadRequestException;
|
||||||
import fr.titionfire.ffsaf.ws.recv.RCard;
|
import fr.titionfire.ffsaf.ws.recv.RCard;
|
||||||
|
import io.quarkus.hibernate.reactive.panache.Panache;
|
||||||
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
||||||
import io.quarkus.panache.common.Sort;
|
import io.quarkus.panache.common.Sort;
|
||||||
import io.smallrye.mutiny.Uni;
|
import io.smallrye.mutiny.Uni;
|
||||||
@ -13,9 +15,9 @@ import jakarta.enterprise.context.ApplicationScoped;
|
|||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@WithSession
|
@WithSession
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
@ -23,6 +25,18 @@ public class CardService {
|
|||||||
@Inject
|
@Inject
|
||||||
CardRepository cardRepository;
|
CardRepository cardRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ClubCardRepository clubCardRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
RegisterRepository registerRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
CompetitionGuestRepository competitionGuestRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
MatchRepository matchRepository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
TradService trad;
|
TradService trad;
|
||||||
|
|
||||||
@ -45,15 +59,6 @@ public class CardService {
|
|||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<Long> extractCombIds(MatchEntity match) {
|
|
||||||
List<Long> ids = new ArrayList<>();
|
|
||||||
if (match.getC1() != null)
|
|
||||||
ids.add(match.getC1().getId());
|
|
||||||
if (match.getC2() != null)
|
|
||||||
ids.add(match.getC2().getId());
|
|
||||||
return ids;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Uni<List<CardModel>> getForMatch(MatchModel match) {
|
public Uni<List<CardModel>> getForMatch(MatchModel match) {
|
||||||
return cardRepository.list(
|
return cardRepository.list(
|
||||||
"competition = ?1 AND (type IN ?2 OR (type = CardType.BLUE AND category = ?4)) AND comb IN ?3",
|
"competition = ?1 AND (type IN ?2 OR (type = CardType.BLUE AND category = ?4)) AND comb IN ?3",
|
||||||
@ -88,4 +93,102 @@ public class CardService {
|
|||||||
return Uni.createFrom().failure(new DBadRequestException(trad.t("card.cannot.be.added")));
|
return Uni.createFrom().failure(new DBadRequestException(trad.t("card.cannot.be.added")));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Uni<List<CardModel>> addTeamCard(CompetitionModel competition, String teamUuid, String teamName,
|
||||||
|
CardModel.CardType type, String reason) {
|
||||||
|
return clubCardRepository.find("competition = ?1 AND (teamUuid = ?2 OR teamName = ?3)",
|
||||||
|
Sort.descending("type"), competition.getId(), teamUuid, teamName)
|
||||||
|
.firstResult()
|
||||||
|
.map(card_ -> {
|
||||||
|
if (type == CardModel.CardType.BLACK) {
|
||||||
|
return card_ != null && card_.getType() == CardModel.CardType.RED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return card_ == null || card_.getType().ordinal() < type.ordinal();
|
||||||
|
})
|
||||||
|
.chain(b -> {
|
||||||
|
if (!b)
|
||||||
|
return Uni.createFrom().failure(new DBadRequestException(trad.t("card.cannot.be.added")));
|
||||||
|
|
||||||
|
if (teamUuid != null) {
|
||||||
|
return registerRepository.list("competition = ?1 AND club.clubId = ?2", competition, teamUuid)
|
||||||
|
.map(l -> l.stream().map(r -> r.getMembre().getId()).toList());
|
||||||
|
} else {
|
||||||
|
return competitionGuestRepository.list("competition = ?1 AND club = ?2", competition,
|
||||||
|
teamName)
|
||||||
|
.map(l -> l.stream().map(r -> r.getId() * -1).toList());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.chain(combIds -> cardRepository.list("competition = ?1 AND comb IN ?2", competition.getId(), combIds)
|
||||||
|
.map(cards -> {
|
||||||
|
List<CardModel> newCards = new ArrayList<>();
|
||||||
|
for (Long id : combIds) {
|
||||||
|
Optional<CardModel> optional = cards.stream()
|
||||||
|
.filter(c -> id.equals(c.getComb()) && c.getType() == type).findAny();
|
||||||
|
|
||||||
|
CardModel model = new CardModel();
|
||||||
|
model.setCompetition(competition.getId());
|
||||||
|
model.setComb(id);
|
||||||
|
model.setTeamCard(true);
|
||||||
|
|
||||||
|
if (optional.isEmpty()) {
|
||||||
|
model.setType(type);
|
||||||
|
} else {
|
||||||
|
model.setType(
|
||||||
|
CardModel.CardType.values()[Math.min(optional.get().getType().ordinal() + 1,
|
||||||
|
CardModel.CardType.BLACK.ordinal())]);
|
||||||
|
}
|
||||||
|
newCards.add(model);
|
||||||
|
}
|
||||||
|
return newCards;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.call(newCards -> Panache.withTransaction(() -> cardRepository.persist(newCards)))
|
||||||
|
.call(newCards -> {
|
||||||
|
ClubCardModel model = new ClubCardModel();
|
||||||
|
model.setCompetition(competition.getId());
|
||||||
|
model.setTeamUuid(teamUuid);
|
||||||
|
model.setTeamName(teamName);
|
||||||
|
model.setType(type);
|
||||||
|
model.setReason(reason);
|
||||||
|
model.setCardIds(newCards.stream().map(CardModel::getId).toList());
|
||||||
|
|
||||||
|
return Panache.withTransaction(() -> clubCardRepository.persist(model));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uni<List<CardModel>> recvReturnState(CompetitionModel competition, RCard.SendTeamCardReturnState state) {
|
||||||
|
return clubCardRepository.find("competition = ?1 AND (teamUuid = ?2 OR teamName = ?3) AND type = ?4",
|
||||||
|
competition.getId(), state.teamUuid(), state.teamName(), state.type())
|
||||||
|
.firstResult()
|
||||||
|
.chain(o -> cardRepository.list("id IN ?1", o.getCardIds()))
|
||||||
|
.call(cards -> matchRepository.list("category.compet = ?1 AND category.id IN ?2", competition,
|
||||||
|
state.selectedCategory())
|
||||||
|
.invoke(matches -> {
|
||||||
|
for (CardModel card : cards) {
|
||||||
|
for (MatchModel m : matches.stream()
|
||||||
|
.filter(m -> extractCombIds(m).contains(card.getComb())).toList()) {
|
||||||
|
|
||||||
|
if (state.state() == 1) {
|
||||||
|
card.setCategory(m.getCategory().getId());
|
||||||
|
} else if (state.state() == 2) {
|
||||||
|
card.setCategory(m.getCategory().getId());
|
||||||
|
if (Objects.equals(m.getId(), state.selectedMatch()))
|
||||||
|
card.setMatch(m.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.chain(() -> Panache.withTransaction(() -> cardRepository.persist(cards))));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uni<List<Long>> rmTeamCard(CompetitionModel competition, String teamUuid, String teamName,
|
||||||
|
CardModel.CardType type) {
|
||||||
|
return clubCardRepository.find("competition = ?1 AND (teamUuid = ?2 OR teamName = ?3) AND type = ?4",
|
||||||
|
competition.getId(), teamUuid, teamName, type)
|
||||||
|
.firstResult()
|
||||||
|
.chain(card -> Uni.createFrom().item(card.getCardIds())
|
||||||
|
.call(() -> Panache.withTransaction(() -> cardRepository.delete("id IN ?1", card.getCardIds())))
|
||||||
|
.call(() -> Panache.withTransaction(() -> clubCardRepository.delete(card))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,8 +3,8 @@ package fr.titionfire.ffsaf.ws.recv;
|
|||||||
import fr.titionfire.ffsaf.data.model.CardModel;
|
import fr.titionfire.ffsaf.data.model.CardModel;
|
||||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||||
import fr.titionfire.ffsaf.data.repository.CardRepository;
|
import fr.titionfire.ffsaf.data.repository.CardRepository;
|
||||||
import fr.titionfire.ffsaf.data.repository.CombRepository;
|
import fr.titionfire.ffsaf.data.repository.ClubCardRepository;
|
||||||
import fr.titionfire.ffsaf.data.repository.CompetitionGuestRepository;
|
import fr.titionfire.ffsaf.data.repository.CompetitionRepository;
|
||||||
import fr.titionfire.ffsaf.data.repository.MatchRepository;
|
import fr.titionfire.ffsaf.data.repository.MatchRepository;
|
||||||
import fr.titionfire.ffsaf.domain.service.CardService;
|
import fr.titionfire.ffsaf.domain.service.CardService;
|
||||||
import fr.titionfire.ffsaf.domain.service.TradService;
|
import fr.titionfire.ffsaf.domain.service.TradService;
|
||||||
@ -21,6 +21,7 @@ import io.smallrye.mutiny.unchecked.Unchecked;
|
|||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@WithSession
|
@WithSession
|
||||||
@ -31,6 +32,9 @@ public class RCard {
|
|||||||
@Inject
|
@Inject
|
||||||
MatchRepository matchRepository;
|
MatchRepository matchRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ClubCardRepository clubCardRepository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
CardRepository cardRepository;
|
CardRepository cardRepository;
|
||||||
|
|
||||||
@ -38,10 +42,7 @@ public class RCard {
|
|||||||
CardService cardService;
|
CardService cardService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
CombRepository combRepository;
|
CompetitionRepository competitionRepository;
|
||||||
|
|
||||||
@Inject
|
|
||||||
CompetitionGuestRepository competitionGuestRepository;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
TradService trad;
|
TradService trad;
|
||||||
@ -63,6 +64,16 @@ public class RCard {
|
|||||||
return getById(matchId, connection).chain(matchModel -> cardService.getForMatch(matchModel));
|
return getById(matchId, connection).chain(matchModel -> cardService.getForMatch(matchModel));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WSReceiver(code = "getAllForTeamNoDetail", permission = PermLevel.VIEW)
|
||||||
|
public Uni<List<SendTeamCards>> getAllForTeamNoDetail(WebSocketConnection connection, Object o) {
|
||||||
|
return competitionRepository.find("uuid", connection.pathParam("uuid")).firstResult()
|
||||||
|
.chain(c -> clubCardRepository.list("competition = ?1", c.getId()))
|
||||||
|
.map(cards -> cards.stream()
|
||||||
|
.map(card -> new SendTeamCards(card.getTeamUuid(), card.getTeamName(), List.of(),
|
||||||
|
card.getType(), card.getReason(), card.getDate()))
|
||||||
|
.toList());
|
||||||
|
}
|
||||||
|
|
||||||
@WSReceiver(code = "sendCardAdd", permission = PermLevel.TABLE)
|
@WSReceiver(code = "sendCardAdd", permission = PermLevel.TABLE)
|
||||||
public Uni<Void> sendCardAdd(WebSocketConnection connection, SendCardAdd card) {
|
public Uni<Void> sendCardAdd(WebSocketConnection connection, SendCardAdd card) {
|
||||||
return getById(card.matchId(), connection)
|
return getById(card.matchId(), connection)
|
||||||
@ -74,11 +85,12 @@ public class RCard {
|
|||||||
model.setCategory(matchModel.getCategory().getId());
|
model.setCategory(matchModel.getCategory().getId());
|
||||||
model.setCompetition(matchModel.getCategory().getCompet().getId());
|
model.setCompetition(matchModel.getCategory().getCompet().getId());
|
||||||
model.setType(card.type());
|
model.setType(card.type());
|
||||||
|
model.setReason(card.reason());
|
||||||
|
|
||||||
return Panache.withTransaction(() -> cardRepository.persist(model));
|
return Panache.withTransaction(() -> cardRepository.persist(model));
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.invoke(cardModel -> SSCard.sendCard(connection, cardModel))
|
.invoke(cardModel -> SSCard.sendCards(connection, List.of(cardModel)))
|
||||||
.replaceWithVoid();
|
.replaceWithVoid();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,14 +103,55 @@ public class RCard {
|
|||||||
.invoke(Unchecked.consumer(o -> {
|
.invoke(Unchecked.consumer(o -> {
|
||||||
if (o == null)
|
if (o == null)
|
||||||
throw new DNotFoundException(trad.t("carton.non.trouver"));
|
throw new DNotFoundException(trad.t("carton.non.trouver"));
|
||||||
SSCard.sendRmCard(connection, o.getId());
|
SSCard.sendRmCards(connection, List.of(o.getId()));
|
||||||
}))
|
}))
|
||||||
.chain(cardModel -> Panache.withTransaction(() -> cardRepository.delete(cardModel)))
|
.chain(cardModel -> Panache.withTransaction(() -> cardRepository.delete(cardModel)))
|
||||||
)
|
)
|
||||||
.replaceWithVoid();
|
.replaceWithVoid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WSReceiver(code = "applyTeamCards", permission = PermLevel.TABLE)
|
||||||
|
public Uni<Void> applyTeamCards(WebSocketConnection connection, SendTeamCards teamCards) {
|
||||||
|
return competitionRepository.find("uuid", connection.pathParam("uuid")).firstResult()
|
||||||
|
.chain(c -> cardService.addTeamCard(c, teamCards.teamUuid(), teamCards.teamName(), teamCards.type,
|
||||||
|
teamCards.reason()))
|
||||||
|
.invoke(cards -> SSCard.sendTeamCard(connection,
|
||||||
|
new SendTeamCards(teamCards.teamUuid(), teamCards.teamName(), cards, teamCards.type(),
|
||||||
|
teamCards.reason(), new Date())))
|
||||||
|
.replaceWithVoid();
|
||||||
|
}
|
||||||
|
|
||||||
|
@WSReceiver(code = "sendTeamCardReturnState", permission = PermLevel.TABLE)
|
||||||
|
public Uni<Void> sendTeamCardReturnState(WebSocketConnection connection, SendTeamCardReturnState state) {
|
||||||
|
if (state.state <= 0 || state.state > 2)
|
||||||
|
return Uni.createFrom().voidItem();
|
||||||
|
|
||||||
|
return competitionRepository.find("uuid", connection.pathParam("uuid")).firstResult()
|
||||||
|
.chain(c -> cardService.recvReturnState(c, state))
|
||||||
|
.invoke(cards -> SSCard.sendCards(connection, cards))
|
||||||
|
.replaceWithVoid();
|
||||||
|
}
|
||||||
|
|
||||||
|
@WSReceiver(code = "removeTeamCards", permission = PermLevel.TABLE)
|
||||||
|
public Uni<Void> removeTeamCards(WebSocketConnection connection, SendTeamCards teamCards) {
|
||||||
|
return competitionRepository.find("uuid", connection.pathParam("uuid")).firstResult()
|
||||||
|
.chain(c -> cardService.rmTeamCard(c, teamCards.teamUuid(), teamCards.teamName(), teamCards.type))
|
||||||
|
.invoke(cards -> SSCard.sendRmCards(connection, cards))
|
||||||
|
.invoke(__ -> SSCard.rmTeamCard(connection, teamCards))
|
||||||
|
.replaceWithVoid();
|
||||||
|
}
|
||||||
|
|
||||||
@RegisterForReflection
|
@RegisterForReflection
|
||||||
public record SendCardAdd(long matchId, long combId, CardModel.CardType type) {
|
public record SendCardAdd(long matchId, long combId, CardModel.CardType type, String reason) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@RegisterForReflection
|
||||||
|
public record SendTeamCards(String teamUuid, String teamName, List<CardModel> cards, CardModel.CardType type,
|
||||||
|
String reason, Date date) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@RegisterForReflection
|
||||||
|
public record SendTeamCardReturnState(String teamUuid, String teamName, CardModel.CardType type,
|
||||||
|
int state, Long selectedCategory, Long selectedMatch) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -117,6 +117,20 @@ public class RState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Long> getAllCategories(String uuid) {
|
||||||
|
return tableStates.values().stream()
|
||||||
|
.filter(s -> s.getCompetitionUuid()
|
||||||
|
.equals(uuid) && s.getSelectedCategory() != null && s.getSelectedCategory() != -1)
|
||||||
|
.map(TableState::getSelectedCategory).distinct().toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getAllMatchActive(String uuid) {
|
||||||
|
return tableStates.values().stream()
|
||||||
|
.filter(s -> s.getCompetitionUuid()
|
||||||
|
.equals(uuid) && s.getState() == MatchState.IN_PROGRESS && s.getSelectedMatch() != null && s.getSelectedMatch() != -1)
|
||||||
|
.map(TableState::getSelectedMatch).distinct().toList();
|
||||||
|
}
|
||||||
|
|
||||||
@RegisterForReflection
|
@RegisterForReflection
|
||||||
public record ChronoState(long time, long startTime, long configTime, long configPause, int state) {
|
public record ChronoState(long time, long startTime, long configTime, long configPause, int state) {
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
|
|||||||
@ -2,15 +2,26 @@ package fr.titionfire.ffsaf.ws.send;
|
|||||||
|
|
||||||
import fr.titionfire.ffsaf.data.model.CardModel;
|
import fr.titionfire.ffsaf.data.model.CardModel;
|
||||||
import fr.titionfire.ffsaf.ws.CompetitionWS;
|
import fr.titionfire.ffsaf.ws.CompetitionWS;
|
||||||
|
import fr.titionfire.ffsaf.ws.recv.RCard;
|
||||||
import io.quarkus.websockets.next.WebSocketConnection;
|
import io.quarkus.websockets.next.WebSocketConnection;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class SSCard {
|
public class SSCard {
|
||||||
|
|
||||||
public static void sendCard(WebSocketConnection connection, CardModel cardModel) {
|
public static void sendCards(WebSocketConnection connection, List<CardModel> cardModel) {
|
||||||
CompetitionWS.sendNotifyToOtherEditor(connection, "sendCard", cardModel);
|
CompetitionWS.sendNotifyToOtherEditor(connection, "sendCards", cardModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sendRmCard(WebSocketConnection connection, Long id) {
|
public static void sendRmCards(WebSocketConnection connection, List<Long> ids) {
|
||||||
CompetitionWS.sendNotifyToOtherEditor(connection, "rmCard", id);
|
CompetitionWS.sendNotifyToOtherEditor(connection, "rmCards", ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendTeamCard(WebSocketConnection connection, RCard.SendTeamCards teamCards) {
|
||||||
|
CompetitionWS.sendNotifyToOtherEditor(connection, "sendTeamCard", teamCards);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void rmTeamCard(WebSocketConnection connection, RCard.SendTeamCards teamCards) {
|
||||||
|
CompetitionWS.sendNotifyToOtherEditor(connection, "rmTeamCard", teamCards);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,10 +16,13 @@
|
|||||||
"blue": "Blue",
|
"blue": "Blue",
|
||||||
"cardAdded": "Card added",
|
"cardAdded": "Card added",
|
||||||
"cardRemoved": "Card removed",
|
"cardRemoved": "Card removed",
|
||||||
|
"carton": "Card",
|
||||||
|
"cartonDéquipe": "Team's card",
|
||||||
"cartonJaune": "Yellow card",
|
"cartonJaune": "Yellow card",
|
||||||
"cartonNoir": "Black card",
|
"cartonNoir": "Black card",
|
||||||
"cartonRouge": "Red card",
|
"cartonRouge": "Red card",
|
||||||
"catégorie": "Category",
|
"catégorie": "Category",
|
||||||
|
"ceCartonEstIssuDunCartonDéquipe": "This card comes from a team card, do you really want to delete it?",
|
||||||
"chrono.+/-...S": "+/- ... s",
|
"chrono.+/-...S": "+/- ... s",
|
||||||
"chrono.+10S": "+10 s",
|
"chrono.+10S": "+10 s",
|
||||||
"chrono.+1S": "+1 s",
|
"chrono.+1S": "+1 s",
|
||||||
@ -48,9 +51,12 @@
|
|||||||
"confirm3.title": "Change category type",
|
"confirm3.title": "Change category type",
|
||||||
"confirm4.msg": "Do you really want to delete the category {{name}}. This will delete all associated matches!",
|
"confirm4.msg": "Do you really want to delete the category {{name}}. This will delete all associated matches!",
|
||||||
"confirm4.title": "Delete category",
|
"confirm4.title": "Delete category",
|
||||||
|
"confirmer": "Confirm",
|
||||||
"conserverUniquementLesMatchsTerminés": "Keep only finished matches",
|
"conserverUniquementLesMatchsTerminés": "Keep only finished matches",
|
||||||
"contre": "vs",
|
"contre": "vs",
|
||||||
|
"couleur": "Color",
|
||||||
"créerLesMatchs": "Create matches",
|
"créerLesMatchs": "Create matches",
|
||||||
|
"date": "Date",
|
||||||
"demi-finalesEtFinales": "Semi-finals and finals",
|
"demi-finalesEtFinales": "Semi-finals and finals",
|
||||||
"duréePause": "Pause duration",
|
"duréePause": "Pause duration",
|
||||||
"duréeRound": "Round duration",
|
"duréeRound": "Round duration",
|
||||||
@ -72,7 +78,9 @@
|
|||||||
"genre.f": "F",
|
"genre.f": "F",
|
||||||
"genre.h": "M",
|
"genre.h": "M",
|
||||||
"genre.na": "NA",
|
"genre.na": "NA",
|
||||||
|
"individuelle": "Individual",
|
||||||
"inscrit": "Registered",
|
"inscrit": "Registered",
|
||||||
|
"listeDesCartons": "List of cards",
|
||||||
"manche": "Round",
|
"manche": "Round",
|
||||||
"matchPourLesPerdantsDuTournoi": "Match for tournament losers:",
|
"matchPourLesPerdantsDuTournoi": "Match for tournament losers:",
|
||||||
"matches": "Matches",
|
"matches": "Matches",
|
||||||
@ -117,6 +125,9 @@
|
|||||||
"team": "Team",
|
"team": "Team",
|
||||||
"terminé": "Finished",
|
"terminé": "Finished",
|
||||||
"texteCopiéDansLePresse": "Text copied to clipboard! Paste it into an HTML tag on your WordPress.",
|
"texteCopiéDansLePresse": "Text copied to clipboard! Paste it into an HTML tag on your WordPress.",
|
||||||
|
"toast.card.team.error": "Error while editing team card",
|
||||||
|
"toast.card.team.pending": "Editing team card...",
|
||||||
|
"toast.card.team.success": "Team card edited!",
|
||||||
"toast.createCategory.error": "Error while creating the category",
|
"toast.createCategory.error": "Error while creating the category",
|
||||||
"toast.createCategory.pending": "Creating category...",
|
"toast.createCategory.pending": "Creating category...",
|
||||||
"toast.createCategory.success": "Category created!",
|
"toast.createCategory.success": "Category created!",
|
||||||
|
|||||||
@ -16,10 +16,13 @@
|
|||||||
"blue": "Blue",
|
"blue": "Blue",
|
||||||
"cardAdded": "Carton ajouté",
|
"cardAdded": "Carton ajouté",
|
||||||
"cardRemoved": "Carton retiré",
|
"cardRemoved": "Carton retiré",
|
||||||
|
"carton": "Carton",
|
||||||
|
"cartonDéquipe": "Carton d'équipe",
|
||||||
"cartonJaune": "Carton jaune",
|
"cartonJaune": "Carton jaune",
|
||||||
"cartonNoir": "Carton noir",
|
"cartonNoir": "Carton noir",
|
||||||
"cartonRouge": "Carton rouge",
|
"cartonRouge": "Carton rouge",
|
||||||
"catégorie": "Catégorie",
|
"catégorie": "Catégorie",
|
||||||
|
"ceCartonEstIssuDunCartonDéquipe": "Ce carton est issu d'un carton d'équipe, voulez-vous vraiment le supprimer ?",
|
||||||
"chrono.+/-...S": "+/- ... s",
|
"chrono.+/-...S": "+/- ... s",
|
||||||
"chrono.+10S": "+10 s",
|
"chrono.+10S": "+10 s",
|
||||||
"chrono.+1S": "+1 s",
|
"chrono.+1S": "+1 s",
|
||||||
@ -48,9 +51,12 @@
|
|||||||
"confirm3.title": "Changement de type de catégorie",
|
"confirm3.title": "Changement de type de catégorie",
|
||||||
"confirm4.msg": "Voulez-vous vraiment supprimer la catégorie {{name}}. Cela va supprimer tous les matchs associés !",
|
"confirm4.msg": "Voulez-vous vraiment supprimer la catégorie {{name}}. Cela va supprimer tous les matchs associés !",
|
||||||
"confirm4.title": "Suppression de la catégorie",
|
"confirm4.title": "Suppression de la catégorie",
|
||||||
|
"confirmer": "Confirmer",
|
||||||
"conserverUniquementLesMatchsTerminés": "Conserver uniquement les matchs terminés",
|
"conserverUniquementLesMatchsTerminés": "Conserver uniquement les matchs terminés",
|
||||||
"contre": "contre",
|
"contre": "contre",
|
||||||
|
"couleur": "Couleur",
|
||||||
"créerLesMatchs": "Créer les matchs",
|
"créerLesMatchs": "Créer les matchs",
|
||||||
|
"date": "Date",
|
||||||
"demi-finalesEtFinales": "Demi-finales et finales",
|
"demi-finalesEtFinales": "Demi-finales et finales",
|
||||||
"duréePause": "Durée pause",
|
"duréePause": "Durée pause",
|
||||||
"duréeRound": "Durée round",
|
"duréeRound": "Durée round",
|
||||||
@ -72,7 +78,9 @@
|
|||||||
"genre.f": "F",
|
"genre.f": "F",
|
||||||
"genre.h": "H",
|
"genre.h": "H",
|
||||||
"genre.na": "NA",
|
"genre.na": "NA",
|
||||||
|
"individuelle": "Individuelle",
|
||||||
"inscrit": "Inscrit",
|
"inscrit": "Inscrit",
|
||||||
|
"listeDesCartons": "Liste des cartons",
|
||||||
"manche": "Manche",
|
"manche": "Manche",
|
||||||
"matchPourLesPerdantsDuTournoi": "Match pour les perdants du tournoi:",
|
"matchPourLesPerdantsDuTournoi": "Match pour les perdants du tournoi:",
|
||||||
"matches": "Matches",
|
"matches": "Matches",
|
||||||
@ -117,6 +125,9 @@
|
|||||||
"team": "Équipe",
|
"team": "Équipe",
|
||||||
"terminé": "Terminé",
|
"terminé": "Terminé",
|
||||||
"texteCopiéDansLePresse": "Texte copié dans le presse-papier ! Collez-le dans une balise HTML sur votre WordPress.",
|
"texteCopiéDansLePresse": "Texte copié dans le presse-papier ! Collez-le dans une balise HTML sur votre WordPress.",
|
||||||
|
"toast.card.team.error": "Erreur lors de la modification du carton d'équipe",
|
||||||
|
"toast.card.team.pending": "Modification du carton d'équipe...",
|
||||||
|
"toast.card.team.success": "Carton d'équipe modifié !",
|
||||||
"toast.createCategory.error": "Erreur lors de la création de la catégorie",
|
"toast.createCategory.error": "Erreur lors de la création de la catégorie",
|
||||||
"toast.createCategory.pending": "Création de la catégorie...",
|
"toast.createCategory.pending": "Création de la catégorie...",
|
||||||
"toast.createCategory.success": "Catégorie créée !",
|
"toast.createCategory.success": "Catégorie créée !",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import {createContext, useContext, useEffect, useReducer} from "react";
|
import {createContext, useContext, useEffect, useReducer} from "react";
|
||||||
import {useWS} from "./useWS.jsx";
|
import {useWS} from "./useWS.jsx";
|
||||||
|
|
||||||
const CardContext = createContext({});
|
const CardContext = createContext({comb: {}, team: []});
|
||||||
const CardDispatchContext = createContext(() => {
|
const CardDispatchContext = createContext(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -29,34 +29,49 @@ export function compareCardOrder(a, b) {
|
|||||||
function reducer(state, action) {
|
function reducer(state, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'SET_CARD':
|
case 'SET_CARD':
|
||||||
if (state[action.payload.id] === undefined || !compareCards(action.payload, state[action.payload.id])) {
|
if (state.comb[action.payload.id] === undefined || !compareCards(action.payload, state.comb[action.payload.id])) {
|
||||||
return {
|
return {
|
||||||
...state,
|
comb: {
|
||||||
[action.payload.id]: action.payload
|
...state.comb,
|
||||||
|
[action.payload.id]: action.payload
|
||||||
|
},
|
||||||
|
team: state.team
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return state
|
return state
|
||||||
case 'SET_ALL':
|
case 'SET_ALL':
|
||||||
if (action.payload.some(e => state[e.id] === undefined || !compareCards(e, state[e.id]))) {
|
if (action.payload.some(e => state.comb[e.id] === undefined || !compareCards(e, state.comb[e.id]))) {
|
||||||
const newCombs = {};
|
const newCombs = {};
|
||||||
for (const o of action.payload) {
|
for (const o of action.payload) {
|
||||||
newCombs[o.id] = o;
|
newCombs[o.id] = o;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
comb: {
|
||||||
...newCombs
|
...state.comb,
|
||||||
|
...newCombs
|
||||||
|
},
|
||||||
|
team: state.team
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return state
|
return state
|
||||||
case 'REMOVE_CARD':
|
case 'REMOVE_CARDS':
|
||||||
console.log("Removing card", action.payload, state[action.payload]);
|
const newState = {...state}
|
||||||
if (state[action.payload] !== undefined) {
|
for (const id of action.payload)
|
||||||
const newState = {...state}
|
delete newState.comb[id]
|
||||||
delete newState[action.payload]
|
return newState
|
||||||
return newState
|
case 'SET_TEAM_CARD':
|
||||||
|
return {
|
||||||
|
comb: state.comb,
|
||||||
|
team: [...state.team.filter(e => e.teamName !== action.payload.teamName || e.teamUuid !== action.payload.teamUuid || e.type !== action.payload.type),
|
||||||
|
action.payload]
|
||||||
}
|
}
|
||||||
return state
|
case 'REMOVE_TEAM_CARD':
|
||||||
|
return {
|
||||||
|
comb: state.comb,
|
||||||
|
team: [...state.team.filter(e => e.teamName !== action.payload.teamName || e.teamUuid !== action.payload.teamUuid || e.type !== action.payload.type)]
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
@ -66,18 +81,35 @@ function WSListener({dispatch}) {
|
|||||||
const {dispatch: dispatchWS} = useWS()
|
const {dispatch: dispatchWS} = useWS()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const sendCard = ({data}) => {
|
const sendCards = ({data}) => {
|
||||||
dispatch({type: 'SET_CARD', payload: data});
|
dispatch({type: 'SET_ALL', payload: data});
|
||||||
}
|
}
|
||||||
const rmCard = ({data}) => {
|
const rmCards = ({data}) => {
|
||||||
dispatch({type: 'REMOVE_CARD', payload: data});
|
dispatch({type: 'REMOVE_CARDS', payload: data});
|
||||||
|
}
|
||||||
|
const sendTeamCard = ({data}) => {
|
||||||
|
dispatch({type: 'SET_ALL', payload: data.cards});
|
||||||
|
dispatch({
|
||||||
|
type: 'SET_TEAM_CARD',
|
||||||
|
payload: {teamName: data.teamName, teamUuid: data.teamUuid, type: data.type, reason: data.reason, date: data.date}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const rmTeamCard = ({data}) => {
|
||||||
|
dispatch({
|
||||||
|
type: 'REMOVE_TEAM_CARD',
|
||||||
|
payload: {teamName: data.teamName, teamUuid: data.teamUuid, type: data.type, reason: data.reason, date: data.date}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatchWS({type: 'addListener', payload: {callback: sendCard, code: 'sendCard'}})
|
dispatchWS({type: 'addListener', payload: {callback: sendCards, code: 'sendCards'}})
|
||||||
dispatchWS({type: 'addListener', payload: {callback: rmCard, code: 'rmCard'}})
|
dispatchWS({type: 'addListener', payload: {callback: rmCards, code: 'rmCards'}})
|
||||||
|
dispatchWS({type: 'addListener', payload: {callback: sendTeamCard, code: 'sendTeamCard'}})
|
||||||
|
dispatchWS({type: 'addListener', payload: {callback: rmTeamCard, code: 'rmTeamCard'}})
|
||||||
return () => {
|
return () => {
|
||||||
dispatchWS({type: 'removeListener', payload: sendCard})
|
dispatchWS({type: 'removeListener', payload: sendCards})
|
||||||
dispatchWS({type: 'removeListener', payload: rmCard})
|
dispatchWS({type: 'removeListener', payload: rmCards})
|
||||||
|
dispatchWS({type: 'removeListener', payload: sendTeamCard})
|
||||||
|
dispatchWS({type: 'removeListener', payload: rmTeamCard})
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -85,7 +117,7 @@ function WSListener({dispatch}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function CardsProvider({children}) {
|
export function CardsProvider({children}) {
|
||||||
const [cards, dispatch] = useReducer(reducer, {})
|
const [cards, dispatch] = useReducer(reducer, {comb: {}, team: []})
|
||||||
|
|
||||||
return <CardContext.Provider value={cards}>
|
return <CardContext.Provider value={cards}>
|
||||||
<CardDispatchContext.Provider value={dispatch}>
|
<CardDispatchContext.Provider value={dispatch}>
|
||||||
@ -98,9 +130,9 @@ export function CardsProvider({children}) {
|
|||||||
export function useCards() {
|
export function useCards() {
|
||||||
const cards = useContext(CardContext);
|
const cards = useContext(CardContext);
|
||||||
return {
|
return {
|
||||||
cards,
|
cards_t: cards.team,
|
||||||
cards_v: Object.values(cards),
|
cards_v: Object.values(cards.comb),
|
||||||
...useCardsStatic(Object.values(cards))
|
...useCardsStatic(Object.values(cards.comb))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -29,7 +29,7 @@ function reducer(state, action) {
|
|||||||
//console.debug("Updating comb", comb);
|
//console.debug("Updating comb", comb);
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
[comb.id]: comb
|
[comb.id]: {...state[comb.id], ...comb}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return state
|
return state
|
||||||
@ -49,7 +49,10 @@ function reducer(state, action) {
|
|||||||
if (combs.some(e => state[e.id] === undefined || !compareCombs(e, state[e.id]))) {
|
if (combs.some(e => state[e.id] === undefined || !compareCombs(e, state[e.id]))) {
|
||||||
const newCombs = {};
|
const newCombs = {};
|
||||||
for (const o of combs) {
|
for (const o of combs) {
|
||||||
newCombs[o.id] = o;
|
newCombs[o.id] = {
|
||||||
|
...state[o.id],
|
||||||
|
...o
|
||||||
|
};
|
||||||
}
|
}
|
||||||
//console.debug("Updating combs", newCombs);
|
//console.debug("Updating combs", newCombs);
|
||||||
|
|
||||||
|
|||||||
@ -88,7 +88,7 @@ export function CompetitionRegisterAdmin({source}) {
|
|||||||
<div className="col-lg-9">
|
<div className="col-lg-9">
|
||||||
{data ? <div className="">
|
{data ? <div className="">
|
||||||
<MakeCentralPanel
|
<MakeCentralPanel
|
||||||
data={state.filter(s => (clubFilter.length === 0 || s.data.club.name === clubFilter)
|
data={state.filter(s => (clubFilter.length === 0 || s.data.club?.name === clubFilter)
|
||||||
&& (catAgeFilter.length === 0 || s.data.categorie === catAgeFilter)
|
&& (catAgeFilter.length === 0 || s.data.categorie === catAgeFilter)
|
||||||
&& (catFilter === -1 || s.data.categoriesInscrites.includes(catFilter))
|
&& (catFilter === -1 || s.data.categoriesInscrites.includes(catFilter))
|
||||||
&& (!filterNotWeight || (data3?.requiredWeight.includes(s.data.categorie) && (
|
&& (!filterNotWeight || (data3?.requiredWeight.includes(s.data.categorie) && (
|
||||||
|
|||||||
@ -11,12 +11,14 @@ import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
|||||||
import {SimpleIconsOBS} from "../../../assets/SimpleIconsOBS.ts";
|
import {SimpleIconsOBS} from "../../../assets/SimpleIconsOBS.ts";
|
||||||
import JSZip from "jszip";
|
import JSZip from "jszip";
|
||||||
import {detectOptimalBackground} from "../../../components/SmartLogoBackground.jsx";
|
import {detectOptimalBackground} from "../../../components/SmartLogoBackground.jsx";
|
||||||
import {faGlobe, faTableCellsLarge} from "@fortawesome/free-solid-svg-icons";
|
import {faFile, faGlobe, faTableCellsLarge, faTrash} from "@fortawesome/free-solid-svg-icons";
|
||||||
import {Trans, useTranslation} from "react-i18next";
|
import {Trans, useTranslation} from "react-i18next";
|
||||||
import i18n from "i18next";
|
import i18n from "i18next";
|
||||||
import {getToastMessage} from "../../../utils/Tools.js";
|
import {getToastMessage} from "../../../utils/Tools.js";
|
||||||
import {copyStyles} from "../../../utils/copyStyles.js";
|
import {copyStyles} from "../../../utils/copyStyles.js";
|
||||||
import {StateWindow} from "./StateWindow.jsx";
|
import {StateWindow} from "./StateWindow.jsx";
|
||||||
|
import {CombName, useCombs} from "../../../hooks/useComb.jsx";
|
||||||
|
import {hasEffectCard, useCards, useCardsDispatch} from "../../../hooks/useCard.jsx";
|
||||||
|
|
||||||
const vite_url = import.meta.env.VITE_URL;
|
const vite_url = import.meta.env.VITE_URL;
|
||||||
|
|
||||||
@ -169,6 +171,7 @@ function Menu({menuActions, compUuid}) {
|
|||||||
const e = document.getElementById("actionMenu")
|
const e = document.getElementById("actionMenu")
|
||||||
const longPress = useRef({time: null, timer: null, button: null});
|
const longPress = useRef({time: null, timer: null, button: null});
|
||||||
const obsModal = useRef(null);
|
const obsModal = useRef(null);
|
||||||
|
const teamCardModal = useRef(null);
|
||||||
const {t} = useTranslation("cm");
|
const {t} = useTranslation("cm");
|
||||||
|
|
||||||
const [showStateWin, setShowStateWin] = useState(false)
|
const [showStateWin, setShowStateWin] = useState(false)
|
||||||
@ -235,6 +238,8 @@ function Menu({menuActions, compUuid}) {
|
|||||||
if (button === "obs") {
|
if (button === "obs") {
|
||||||
downloadResourcesAsZip(menuActions.current.resourceList || [])
|
downloadResourcesAsZip(menuActions.current.resourceList || [])
|
||||||
.then(__ => console.log("Ressources téléchargées"));
|
.then(__ => console.log("Ressources téléchargées"));
|
||||||
|
} else if (button === "cards") {
|
||||||
|
teamCardModal.current.click();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -274,8 +279,14 @@ function Menu({menuActions, compUuid}) {
|
|||||||
{createPortal(
|
{createPortal(
|
||||||
<>
|
<>
|
||||||
<div className="vr" style={{margin: "0 0.5em", height: "100%"}}></div>
|
<div className="vr" style={{margin: "0 0.5em", height: "100%"}}></div>
|
||||||
|
<FontAwesomeIcon icon={faFile} size="xl"
|
||||||
|
style={{color: "#6c757d", cursor: "pointer"}}
|
||||||
|
onMouseDown={() => longPressDown("cards")}
|
||||||
|
onMouseUp={() => longPressUp("cards")}
|
||||||
|
data-bs-toggle="tooltip2" data-bs-placement="top"
|
||||||
|
data-bs-title={t("carton")}/>
|
||||||
<FontAwesomeIcon icon={SimpleIconsOBS} size="xl"
|
<FontAwesomeIcon icon={SimpleIconsOBS} size="xl"
|
||||||
style={{color: "#6c757d", cursor: "pointer", marginRight: "0.25em"}}
|
style={{color: "#6c757d", cursor: "pointer"}}
|
||||||
onMouseDown={() => longPressDown("obs")}
|
onMouseDown={() => longPressDown("obs")}
|
||||||
onMouseUp={() => longPressUp("obs")}
|
onMouseUp={() => longPressUp("obs")}
|
||||||
data-bs-toggle="tooltip2" data-bs-placement="top"
|
data-bs-toggle="tooltip2" data-bs-placement="top"
|
||||||
@ -347,10 +358,147 @@ function Menu({menuActions, compUuid}) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<button ref={teamCardModal} type="button" className="btn btn-link" data-bs-toggle="modal" data-bs-target="#TeamCardModal"
|
||||||
|
style={{display: 'none'}}>
|
||||||
|
Launch OBS Modal
|
||||||
|
</button>
|
||||||
|
<div className="modal modal-xl fade" id="TeamCardModal" tabIndex="-1" aria-labelledby="TeamCardModalLabel" aria-hidden="true">
|
||||||
|
<div className="modal-dialog">
|
||||||
|
<div className="modal-content">
|
||||||
|
<TeamCardModal/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
function CategoryHeader({cat, setCatId}) {
|
function TeamCardModal() {
|
||||||
|
const [club, setClub] = useState("")
|
||||||
|
|
||||||
|
const {t} = useTranslation("cm");
|
||||||
|
const {combs} = useCombs()
|
||||||
|
const {sendRequest} = useWS()
|
||||||
|
const {cards_t, cards_v} = useCards()
|
||||||
|
const cardDispatch = useCardsDispatch();
|
||||||
|
const {data} = useRequestWS("getAllForTeamNoDetail", {}, null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!data)
|
||||||
|
return;
|
||||||
|
for (const card of data) {
|
||||||
|
cardDispatch({type: 'SET_TEAM_CARD', payload: card});
|
||||||
|
}
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
let clubList = [];
|
||||||
|
if (combs != null) {
|
||||||
|
clubList = Object.values(combs).map(d => d.club_str).filter((v, i, a) => v !== "" && v !== undefined && a.indexOf(v) === i);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAdd = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
toast.promise(sendRequest("applyTeamCards", {
|
||||||
|
teamUuid: Object.values(combs).find(d => d.club_str === club)?.club_uuid,
|
||||||
|
teamName: club,
|
||||||
|
type: "YELLOW"
|
||||||
|
}),
|
||||||
|
getToastMessage("toast.card.team", "cm"))
|
||||||
|
.then(() => {
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const GetCard = ({type}) => {
|
||||||
|
if (!type)
|
||||||
|
return <></>
|
||||||
|
let bg = "";
|
||||||
|
switch (type) {
|
||||||
|
case "YELLOW":
|
||||||
|
bg = " bg-warning";
|
||||||
|
break;
|
||||||
|
case "RED":
|
||||||
|
bg = " bg-danger";
|
||||||
|
break;
|
||||||
|
case "BLACK":
|
||||||
|
bg = " bg-dark text-white";
|
||||||
|
break;
|
||||||
|
case "BLUE":
|
||||||
|
bg = " bg-primary text-white";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return <span className={"badge border border-light p-2" + bg}><span className="visually-hidden">card</span></span>
|
||||||
|
}
|
||||||
|
|
||||||
|
let cards = [...cards_t, ...cards_v].sort((a, b) => new Date(b.date) - new Date(a.date))
|
||||||
|
return <>
|
||||||
|
<div className="modal-header">
|
||||||
|
<h5 className="modal-title">{t('carton')}</h5>
|
||||||
|
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<h5>{t('cartonDéquipe')}</h5>
|
||||||
|
<div className="input-group mb-3">
|
||||||
|
<label htmlFor="inputGroupSelect09" className="input-group-text">{t('club')}</label>
|
||||||
|
<select id="inputGroupSelect09" className="form-select" value={club} onChange={(e) => setClub(e.target.value)}>
|
||||||
|
{clubList.sort((a, b) => a.localeCompare(b)).map((club, index) => (
|
||||||
|
<option key={index} value={club}>{club}</option>))}
|
||||||
|
</select>
|
||||||
|
<button className="btn btn-outline-primary" type="button" onClick={handleAdd}>{t("ajouter")}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h5>{t('listeDesCartons')}</h5>
|
||||||
|
<table className="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">{t('date')}</th>
|
||||||
|
<th scope="col">{t('type')}</th>
|
||||||
|
<th scope="col">{t('couleur')}</th>
|
||||||
|
<th scope="col">{t('nom')}</th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{cards.map((card, index) => <tr key={index}>
|
||||||
|
<td scope="row">{new Date(card.date).toLocaleString()}</td>
|
||||||
|
{card.teamName ? <>
|
||||||
|
<td>{t('team')}</td>
|
||||||
|
<td><GetCard type={card.type}/></td>
|
||||||
|
<td>{card.teamName}</td>
|
||||||
|
</> : <>
|
||||||
|
<td>{card.teamCard ? "|-> " + t('team'): t('individuelle')} </td>
|
||||||
|
<td><GetCard type={card.type}/></td>
|
||||||
|
<td><CombName combId={card.comb}/></td>
|
||||||
|
</>}
|
||||||
|
|
||||||
|
<td style={{textAlign: "center", cursor: "pointer", color: "#ff1313"}} onClick={_ => {
|
||||||
|
if (confirm("Êtes-vous sûr de vouloir supprimer ce carton ?")) {
|
||||||
|
if (card.teamName) {
|
||||||
|
toast.promise(sendRequest("removeTeamCards", {
|
||||||
|
teamUuid: card.teamUuid, teamName: card.teamName, type: card.type
|
||||||
|
}),
|
||||||
|
getToastMessage("toast.card.team", "cm"))
|
||||||
|
.then(() => {
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
sendRequest('sendCardRm', {matchId: card.match, combId: card.comb, type: card.type})
|
||||||
|
.then(() => toast.success(t('cardRemoved')))
|
||||||
|
.catch(err => toast.error(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}><FontAwesomeIcon icon={faTrash}/></td>
|
||||||
|
</tr>)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div className="modal-footer">
|
||||||
|
<button type="button" className="btn btn-secondary" data-bs-dismiss="modal">{t('fermer')}</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
function CategoryHeader({
|
||||||
|
cat, setCatId
|
||||||
|
}) {
|
||||||
const setLoading = useLoadingSwitcher()
|
const setLoading = useLoadingSwitcher()
|
||||||
const bthRef = useRef();
|
const bthRef = useRef();
|
||||||
const confirmRef = useRef();
|
const confirmRef = useRef();
|
||||||
@ -428,7 +576,7 @@ function CategoryHeader({cat, setCatId}) {
|
|||||||
<button className="btn btn-primary float-end" onClick={() => {
|
<button className="btn btn-primary float-end" onClick={() => {
|
||||||
setModal(cat);
|
setModal(cat);
|
||||||
bthRef.current.click();
|
bthRef.current.click();
|
||||||
}} disabled={cat === null}>Modifier
|
}} disabled={cat === null}>{t('modifier')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -197,7 +197,7 @@ function MatchList({matches, cat, menuActions}) {
|
|||||||
const liceName = (cat.liceName || "N/A").split(";");
|
const liceName = (cat.liceName || "N/A").split(";");
|
||||||
const marches2 = matches.filter(m => m.categorie_ord !== -42)
|
const marches2 = matches.filter(m => m.categorie_ord !== -42)
|
||||||
.sort((a, b) => a.categorie_ord - b.categorie_ord)
|
.sort((a, b) => a.categorie_ord - b.categorie_ord)
|
||||||
.map(m => ({...m, ...win_end(m, cards_v), end: m.end}))
|
.map(m => ({...m, ...win_end(m, cards_v)}))
|
||||||
const firstIndex = marches2.findLastIndex(m => m.poule === '-') + 1;
|
const firstIndex = marches2.findLastIndex(m => m.poule === '-') + 1;
|
||||||
|
|
||||||
const isActiveMatch = (index) => {
|
const isActiveMatch = (index) => {
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import React, {useEffect, useRef, useState} from "react";
|
import React, {useEffect, useRef, useState} from "react";
|
||||||
import {useRequestWS, useWS} from "../../../hooks/useWS.jsx";
|
import {useRequestWS, useWS} from "../../../hooks/useWS.jsx";
|
||||||
import {useCombs, useCombsDispatch} from "../../../hooks/useComb.jsx";
|
import {CombName, useCombs, useCombsDispatch} from "../../../hooks/useComb.jsx";
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||||
import {createPortal} from "react-dom";
|
import {createPortal} from "react-dom";
|
||||||
import {copyStyles} from "../../../utils/copyStyles.js";
|
import {copyStyles} from "../../../utils/copyStyles.js";
|
||||||
import {PubAffProvider, usePubAffDispatch, usePubAffState} from "../../../hooks/useExternalWindow.jsx";
|
import {PubAffProvider, usePubAffDispatch, usePubAffState} from "../../../hooks/useExternalWindow.jsx";
|
||||||
import {faArrowRightArrowLeft, faDisplay} from "@fortawesome/free-solid-svg-icons";
|
import {faArrowRightArrowLeft, faDisplay, faFile, faTrash} from "@fortawesome/free-solid-svg-icons";
|
||||||
import {PubAffWindow} from "./PubAffWindow.jsx";
|
import {PubAffWindow} from "./PubAffWindow.jsx";
|
||||||
import {SimpleIconsScore} from "../../../assets/SimpleIconsScore.ts";
|
import {SimpleIconsScore} from "../../../assets/SimpleIconsScore.ts";
|
||||||
import {ChronoPanel} from "./CMTChronoPanel.jsx";
|
import {ChronoPanel} from "./CMTChronoPanel.jsx";
|
||||||
@ -13,8 +13,10 @@ import {CategorieSelect} from "./CMTMatchPanel.jsx";
|
|||||||
import {PointPanel} from "./CMTPoint.jsx";
|
import {PointPanel} from "./CMTPoint.jsx";
|
||||||
import {importOBSConfiguration, OBSProvider, useOBS} from "../../../hooks/useOBS.jsx";
|
import {importOBSConfiguration, OBSProvider, useOBS} from "../../../hooks/useOBS.jsx";
|
||||||
import {SimpleIconsOBS} from "../../../assets/SimpleIconsOBS.ts";
|
import {SimpleIconsOBS} from "../../../assets/SimpleIconsOBS.ts";
|
||||||
import {toast} from "react-toastify";
|
import {Flip, toast} from "react-toastify";
|
||||||
import {useTranslation} from "react-i18next";
|
import {useTranslation} from "react-i18next";
|
||||||
|
import {useCards, useCardsDispatch} from "../../../hooks/useCard.jsx";
|
||||||
|
import {getToastMessage} from "../../../utils/Tools.js";
|
||||||
|
|
||||||
export function CMTable() {
|
export function CMTable() {
|
||||||
const combDispatch = useCombsDispatch()
|
const combDispatch = useCombsDispatch()
|
||||||
@ -78,6 +80,7 @@ function Menu({menuActions}) {
|
|||||||
const {connected, connect, disconnect} = useOBS();
|
const {connected, connect, disconnect} = useOBS();
|
||||||
const longPress = useRef({time: null, timer: null, button: null});
|
const longPress = useRef({time: null, timer: null, button: null});
|
||||||
const obsModal = useRef(null);
|
const obsModal = useRef(null);
|
||||||
|
const teamCardModal = useRef(null);
|
||||||
const {t} = useTranslation("cm");
|
const {t} = useTranslation("cm");
|
||||||
|
|
||||||
const externalWindow = useRef(null)
|
const externalWindow = useRef(null)
|
||||||
@ -194,6 +197,9 @@ function Menu({menuActions}) {
|
|||||||
<div className="vr" style={{margin: "0 0.5em", height: "100%"}}></div>
|
<div className="vr" style={{margin: "0 0.5em", height: "100%"}}></div>
|
||||||
<span onClick={() => obsModal.current.click()} style={{cursor: "pointer"}}>Zone {zone}</span>
|
<span onClick={() => obsModal.current.click()} style={{cursor: "pointer"}}>Zone {zone}</span>
|
||||||
<div className="vr" style={{margin: "0 0.5em", height: "100%"}}></div>
|
<div className="vr" style={{margin: "0 0.5em", height: "100%"}}></div>
|
||||||
|
<FontAwesomeIcon icon={faFile} size="xl" style={{color: "#6c757d", cursor: "pointer", marginRight: "0.25em"}}
|
||||||
|
onClick={() => teamCardModal.current.click()} data-bs-toggle="tooltip2" data-bs-placement="top"
|
||||||
|
data-bs-title={t('cartonDéquipe')}/>
|
||||||
<FontAwesomeIcon icon={faArrowRightArrowLeft} size="xl" style={{color: "#6c757d", cursor: "pointer", marginRight: "0.25em"}}
|
<FontAwesomeIcon icon={faArrowRightArrowLeft} size="xl" style={{color: "#6c757d", cursor: "pointer", marginRight: "0.25em"}}
|
||||||
onClick={handleSwitchScore} data-bs-toggle="tooltip2" data-bs-placement="top"
|
onClick={handleSwitchScore} data-bs-toggle="tooltip2" data-bs-placement="top"
|
||||||
data-bs-title={t('ttm.table.inverserLaPosition')}/>
|
data-bs-title={t('ttm.table.inverserLaPosition')}/>
|
||||||
@ -241,10 +247,67 @@ function Menu({menuActions}) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<button ref={teamCardModal} type="button" className="btn btn-link" data-bs-toggle="modal" data-bs-target="#TeamCardModal"
|
||||||
|
style={{display: 'none'}}>
|
||||||
|
Launch OBS Modal
|
||||||
|
</button>s
|
||||||
|
<div className="modal fade" id="TeamCardModal" tabIndex="-1" aria-labelledby="TeamCardModalLabel" aria-hidden="true">
|
||||||
|
<div className="modal-dialog">
|
||||||
|
<div className="modal-content">
|
||||||
|
<TeamCardModal/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<SendLiceName name={zone}/>
|
<SendLiceName name={zone}/>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function TeamCardModal() {
|
||||||
|
const [club, setClub] = useState("")
|
||||||
|
|
||||||
|
const {t} = useTranslation("cm");
|
||||||
|
const {combs} = useCombs()
|
||||||
|
const {sendRequest} = useWS()
|
||||||
|
|
||||||
|
let clubList = [];
|
||||||
|
if (combs != null) {
|
||||||
|
clubList = Object.values(combs).map(d => d.club_str).filter((v, i, a) => v !== "" && v !== undefined && a.indexOf(v) === i);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAdd = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
toast.promise(sendRequest("applyTeamCards", {
|
||||||
|
teamUuid: Object.values(combs).find(d => d.club_str === club)?.club_uuid,
|
||||||
|
teamName: club,
|
||||||
|
type: "YELLOW"
|
||||||
|
}),
|
||||||
|
getToastMessage("toast.card.team", "cm"))
|
||||||
|
.then(() => {
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<div className="modal-header">
|
||||||
|
<h5 className="modal-title">{t('cartonDéquipe')}</h5>
|
||||||
|
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="input-group mb-3">
|
||||||
|
<label htmlFor="inputGroupSelect09" className="input-group-text">{t('club')}</label>
|
||||||
|
<select id="inputGroupSelect09" className="form-select" value={club} onChange={(e) => setClub(e.target.value)}>
|
||||||
|
{clubList.sort((a, b) => a.localeCompare(b)).map((club, index) => (
|
||||||
|
<option key={index} value={club}>{club}</option>))}
|
||||||
|
</select>
|
||||||
|
<button className="btn btn-outline-primary" type="button" onClick={handleAdd}>{t("ajouter")}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="modal-footer">
|
||||||
|
<button type="button" className="btn btn-secondary" data-bs-dismiss="modal">{t('fermer')}</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
function SendLiceName({name}) {
|
function SendLiceName({name}) {
|
||||||
const {sendNotify, setState} = useWS();
|
const {sendNotify, setState} = useWS();
|
||||||
|
|
||||||
@ -258,15 +321,94 @@ function SendLiceName({name}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function SendCatId({catId}) {
|
function SendCatId({catId}) {
|
||||||
|
const notifState = useRef(undefined);
|
||||||
const {sendNotify, setState, dispatch, tableState} = useWS();
|
const {sendNotify, setState, dispatch, tableState} = useWS();
|
||||||
|
const {t} = useTranslation("cm");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const welcomeInfo = () => {
|
const welcomeInfo = () => {
|
||||||
sendNotify("sendState", tableState.current)
|
sendNotify("sendState", tableState.current)
|
||||||
}
|
}
|
||||||
|
const sendTeamCards = ({data}) => {
|
||||||
|
function content({closeToast, data}) {
|
||||||
|
const sendState = (s) => {
|
||||||
|
sendNotify("sendTeamCardReturnState", {
|
||||||
|
state: s,
|
||||||
|
teamUuid: data.teamUuid,
|
||||||
|
teamName: data.teamName,
|
||||||
|
type: data.type,
|
||||||
|
selectedCategory: tableState.current.selectedCategory,
|
||||||
|
selectedMatch: tableState.current.selectedMatch
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex items-center w-full">
|
||||||
|
<span>{`Un carton jaune d'équipe a été émis à l'encontre du club ${data.teamName}. Dans votre zone de combat :`}</span><br/>
|
||||||
|
<div className="form-check">
|
||||||
|
<input className="form-check-input" type="radio" name="radioState" id="radioState1"
|
||||||
|
onChange={e => e.target.checked ? notifState.current = 0 : null}/>
|
||||||
|
<label className="form-check-label" htmlFor="radioState1">
|
||||||
|
Rien n'est en cours
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="form-check">
|
||||||
|
<input className="form-check-input" type="radio" name="radioState" id="radioState2"
|
||||||
|
onChange={e => e.target.checked ? notifState.current = 1 : null}/>
|
||||||
|
<label className="form-check-label" htmlFor="radioState2">
|
||||||
|
La categorie est en cours
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="form-check">
|
||||||
|
<input className="form-check-input" type="radio" name="radioState" id="radioState3"
|
||||||
|
onChange={e => e.target.checked ? notifState.current = 2 : null}/>
|
||||||
|
<label className="form-check-label" htmlFor="radioState3">
|
||||||
|
Le match est en cours
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<button className="btn btn-sm btn-outline-primary ml-2" onClick={() => {
|
||||||
|
if (notifState.current === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sendState(notifState.current)
|
||||||
|
closeToast(true);
|
||||||
|
}}>
|
||||||
|
{t('confirmer')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
toast.warn(content, {
|
||||||
|
position: "top-center",
|
||||||
|
autoClose: false,
|
||||||
|
closeButton: false,
|
||||||
|
hideProgressBar: false,
|
||||||
|
closeOnClick: false,
|
||||||
|
pauseOnHover: true,
|
||||||
|
draggable: false,
|
||||||
|
progress: undefined,
|
||||||
|
theme: "colored",
|
||||||
|
transition: Flip,
|
||||||
|
data: {
|
||||||
|
teamUuid: data.teamUuid,
|
||||||
|
teamName: data.teamName,
|
||||||
|
type: data.type,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
welcomeInfo();
|
welcomeInfo();
|
||||||
|
|
||||||
dispatch({type: 'addListener', payload: {callback: welcomeInfo, code: 'welcomeInfo'}})
|
dispatch({type: 'addListener', payload: {callback: welcomeInfo, code: 'welcomeInfo'}})
|
||||||
return () => dispatch({type: 'removeListener', payload: welcomeInfo});
|
dispatch({type: 'addListener', payload: {callback: sendTeamCards, code: 'sendTeamCards'}})
|
||||||
|
return () => {
|
||||||
|
dispatch({type: 'removeListener', payload: welcomeInfo});
|
||||||
|
dispatch({type: 'removeListener', payload: sendTeamCards});
|
||||||
|
|
||||||
|
setState({selectedCategory: -1});
|
||||||
|
sendNotify("sendSelectCategory", -1);
|
||||||
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -694,6 +694,7 @@ function MatchList({matches, cat, groups, reducer}) {
|
|||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@ -267,7 +267,27 @@ function CardPanel({matchId, match, vEnd, admin}) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCardRm = (combId, type) => {
|
const confirmRm = (combId, type) => {
|
||||||
|
function content({closeToast}) {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center w-full">
|
||||||
|
<span>{t('ceCartonEstIssuDunCartonDéquipe')}</span>{' '}
|
||||||
|
<button
|
||||||
|
className="btn btn-sm btn-warning ml-2"
|
||||||
|
onClick={() => {
|
||||||
|
closeToast(true);
|
||||||
|
handleCardRm_(combId, type)
|
||||||
|
}}>
|
||||||
|
{t('confirmer')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
toast.warn(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCardRm_ = (combId, type) => {
|
||||||
setLoading(1)
|
setLoading(1)
|
||||||
sendRequest('sendCardRm', {matchId, combId, type})
|
sendRequest('sendCardRm', {matchId, combId, type})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@ -282,6 +302,15 @@ function CardPanel({matchId, match, vEnd, admin}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const cards = getCardInMatch(match)
|
const cards = getCardInMatch(match)
|
||||||
|
|
||||||
|
const handleCardRm = (combId, type) => {
|
||||||
|
if (cards.find(c => c.comb === combId && c.type === type)?.teamCard) {
|
||||||
|
confirmRm(combId, type)
|
||||||
|
} else {
|
||||||
|
handleCardRm_(combId, type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const MakeList = ({comb}) => {
|
const MakeList = ({comb}) => {
|
||||||
const card = getHeightCardForCombInMatch(comb, match);
|
const card = getHeightCardForCombInMatch(comb, match);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user