Compare commits
No commits in common. "56c4b143d084998c372d22192bc66713e3dd9284" and "09a51edd5f48f63db4fdf29821190cc60ce9bb60" have entirely different histories.
56c4b143d0
...
09a51edd5f
@ -17,7 +17,7 @@ public class CombEntity {
|
|||||||
private String lname;
|
private String lname;
|
||||||
private String fname;
|
private String fname;
|
||||||
Categorie categorie;
|
Categorie categorie;
|
||||||
String club_uuid;
|
Long club;
|
||||||
String club_str;
|
String club_str;
|
||||||
Genre genre;
|
Genre genre;
|
||||||
String country;
|
String country;
|
||||||
@ -29,7 +29,7 @@ public class CombEntity {
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new CombEntity(model.getId(), model.getLname(), model.getFname(), model.getCategorie(),
|
return new CombEntity(model.getId(), model.getLname(), model.getFname(), model.getCategorie(),
|
||||||
model.getClub() == null ? null : model.getClub().getClubId(),
|
model.getClub() == null ? null : model.getClub().getId(),
|
||||||
model.getClub() == null ? "Sans club" : model.getClub().getName(), model.getGenre(), model.getCountry(),
|
model.getClub() == null ? "Sans club" : model.getClub().getName(), model.getGenre(), model.getCountry(),
|
||||||
0, null);
|
0, null);
|
||||||
}
|
}
|
||||||
@ -49,7 +49,7 @@ public class CombEntity {
|
|||||||
MembreModel model = registerModel.getMembre();
|
MembreModel model = registerModel.getMembre();
|
||||||
|
|
||||||
return new CombEntity(model.getId(), model.getLname(), model.getFname(), registerModel.getCategorie(),
|
return new CombEntity(model.getId(), model.getLname(), model.getFname(), registerModel.getCategorie(),
|
||||||
registerModel.getClub2() == null ? null : registerModel.getClub2().getClubId(),
|
registerModel.getClub2() == null ? null : registerModel.getClub2().getId(),
|
||||||
registerModel.getClub2() == null ? "Sans club" : registerModel.getClub2().getName(), model.getGenre(),
|
registerModel.getClub2() == null ? "Sans club" : registerModel.getClub2().getName(), model.getGenre(),
|
||||||
model.getCountry(), registerModel.getOverCategory(), registerModel.getWeight());
|
model.getCountry(), registerModel.getOverCategory(), registerModel.getWeight());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -186,6 +186,6 @@ public class AffiliationRequestEndpoints {
|
|||||||
public Uni<Response> getStatus(
|
public Uni<Response> getStatus(
|
||||||
@Parameter(description = "L'identifiant de la demande d'affiliation") @PathParam("id") long id) throws URISyntaxException {
|
@Parameter(description = "L'identifiant de la demande d'affiliation") @PathParam("id") long id) throws URISyntaxException {
|
||||||
return Utils.getMediaFile(id, media, "aff_request/status", "affiliation_request_" + id,
|
return Utils.getMediaFile(id, media, "aff_request/status", "affiliation_request_" + id,
|
||||||
Uni.createFrom().nullItem(), false);
|
Uni.createFrom().nullItem());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -335,7 +335,7 @@ public class ClubEndpoints {
|
|||||||
@Parameter(description = "Identifiant long (clubId) de club") @PathParam("clubId") String clubId) {
|
@Parameter(description = "Identifiant long (clubId) de club") @PathParam("clubId") String clubId) {
|
||||||
return clubService.getByClubId(clubId).chain(Unchecked.function(clubModel -> {
|
return clubService.getByClubId(clubId).chain(Unchecked.function(clubModel -> {
|
||||||
try {
|
try {
|
||||||
return Utils.getMediaFileNoDefault((clubModel != null) ? clubModel.getId() : -1, media, "ppClub",
|
return Utils.getMediaFile((clubModel != null) ? clubModel.getId() : -1, media, "ppClub",
|
||||||
Uni.createFrom().nullItem());
|
Uni.createFrom().nullItem());
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
throw new InternalError();
|
throw new InternalError();
|
||||||
@ -358,7 +358,7 @@ public class ClubEndpoints {
|
|||||||
return clubService.getById(id).onItem().invoke(checkPerm).chain(Unchecked.function(clubModel -> {
|
return clubService.getById(id).onItem().invoke(checkPerm).chain(Unchecked.function(clubModel -> {
|
||||||
try {
|
try {
|
||||||
return Utils.getMediaFile(clubModel.getId(), media, "clubStatus",
|
return Utils.getMediaFile(clubModel.getId(), media, "clubStatus",
|
||||||
"statue-" + clubModel.getName(), Uni.createFrom().nullItem(), false);
|
"statue-" + clubModel.getName(), Uni.createFrom().nullItem());
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
throw new InternalError();
|
throw new InternalError();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -150,16 +150,11 @@ public class Utils {
|
|||||||
|
|
||||||
public static Uni<Response> getMediaFile(long id, String media, String dirname,
|
public static Uni<Response> getMediaFile(long id, String media, String dirname,
|
||||||
Uni<?> uniBase) throws URISyntaxException {
|
Uni<?> uniBase) throws URISyntaxException {
|
||||||
return getMediaFile(id, media, dirname, null, uniBase, true);
|
return getMediaFile(id, media, dirname, null, uniBase);
|
||||||
}
|
|
||||||
|
|
||||||
public static Uni<Response> getMediaFileNoDefault(long id, String media, String dirname,
|
|
||||||
Uni<?> uniBase) throws URISyntaxException {
|
|
||||||
return getMediaFile(id, media, dirname, null, uniBase, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Uni<Response> getMediaFile(long id, String media, String dirname, String out_filename,
|
public static Uni<Response> getMediaFile(long id, String media, String dirname, String out_filename,
|
||||||
Uni<?> uniBase, boolean default_) throws URISyntaxException {
|
Uni<?> uniBase) throws URISyntaxException {
|
||||||
Future<Pair<File, byte[]>> future = CompletableFuture.supplyAsync(() -> {
|
Future<Pair<File, byte[]>> future = CompletableFuture.supplyAsync(() -> {
|
||||||
FilenameFilter filter = (directory, filename) -> filename.startsWith(id + ".");
|
FilenameFilter filter = (directory, filename) -> filename.startsWith(id + ".");
|
||||||
File[] files = new File(media, dirname).listFiles(filter);
|
File[] files = new File(media, dirname).listFiles(filter);
|
||||||
@ -187,7 +182,6 @@ public class Utils {
|
|||||||
return uniBase.chain(__ -> Uni.createFrom().future(future)
|
return uniBase.chain(__ -> Uni.createFrom().future(future)
|
||||||
.chain(filePair -> {
|
.chain(filePair -> {
|
||||||
if (filePair == null) {
|
if (filePair == null) {
|
||||||
if (default_) {
|
|
||||||
return Uni.createFrom().future(future2).map(data -> {
|
return Uni.createFrom().future(future2).map(data -> {
|
||||||
if (data == null)
|
if (data == null)
|
||||||
return Response.noContent().build();
|
return Response.noContent().build();
|
||||||
@ -201,11 +195,6 @@ public class Utils {
|
|||||||
"inline; " + ((out_filename == null) ? "" : "filename=\"" + out_filename + "\""));
|
"inline; " + ((out_filename == null) ? "" : "filename=\"" + out_filename + "\""));
|
||||||
return resp.build();
|
return resp.build();
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
Response.ResponseBuilder resp = Response.status(404);
|
|
||||||
resp.header(HttpHeaders.CACHE_CONTROL, "max-age=600");
|
|
||||||
return Uni.createFrom().item(resp.build());
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return Uni.createFrom().item(() -> {
|
return Uni.createFrom().item(() -> {
|
||||||
String mimeType = URLConnection.guessContentTypeFromName(filePair.getKey().getName());
|
String mimeType = URLConnection.guessContentTypeFromName(filePair.getKey().getName());
|
||||||
|
|||||||
@ -22,7 +22,7 @@ public class RRegister {
|
|||||||
@Inject
|
@Inject
|
||||||
CompetitionRepository competitionRepository;
|
CompetitionRepository competitionRepository;
|
||||||
|
|
||||||
@WSReceiver(code = "getRegister", permission = PermLevel.TABLE)
|
@WSReceiver(code = "getRegister", permission = PermLevel.ADMIN)
|
||||||
public Uni<List<CombEntity>> getRegister(WebSocketConnection connection, Object o) {
|
public Uni<List<CombEntity>> getRegister(WebSocketConnection connection, Object o) {
|
||||||
return competitionRepository.find("uuid", connection.pathParam("uuid")).firstResult()
|
return competitionRepository.find("uuid", connection.pathParam("uuid")).firstResult()
|
||||||
.call(cm -> Mutiny.fetch(cm.getInsc()))
|
.call(cm -> Mutiny.fetch(cm.getInsc()))
|
||||||
|
|||||||
@ -40,7 +40,7 @@ public class SRegister {
|
|||||||
public Uni<Void> send(String uuid, String code, Object data) {
|
public Uni<Void> send(String uuid, String code, Object data) {
|
||||||
List<Uni<Void>> queue = connections.findByEndpointId(CompetitionWS.class.getCanonicalName()).stream()
|
List<Uni<Void>> queue = connections.findByEndpointId(CompetitionWS.class.getCanonicalName()).stream()
|
||||||
.filter(c -> c.pathParam("uuid").equals(uuid) && PermLevel.valueOf(
|
.filter(c -> c.pathParam("uuid").equals(uuid) && PermLevel.valueOf(
|
||||||
c.userData().get(UserData.TypedKey.forString("prem"))).ordinal() >= PermLevel.TABLE.ordinal())
|
c.userData().get(UserData.TypedKey.forString("prem"))).ordinal() >= PermLevel.ADMIN.ordinal())
|
||||||
.map(c -> c.sendText(
|
.map(c -> c.sendText(
|
||||||
new MessageOut(UUID.randomUUID(), code, MessageType.NOTIFY, data)))
|
new MessageOut(UUID.randomUUID(), code, MessageType.NOTIFY, data)))
|
||||||
.toList();
|
.toList();
|
||||||
|
|||||||
@ -1,26 +0,0 @@
|
|||||||
import {
|
|
||||||
IconDefinition,
|
|
||||||
IconName,
|
|
||||||
IconPrefix
|
|
||||||
} from "@fortawesome/fontawesome-svg-core";
|
|
||||||
|
|
||||||
export const SimpleIconsScore: IconDefinition = {
|
|
||||||
icon: [
|
|
||||||
// SVG viewbox width (in pixels)
|
|
||||||
122.88,
|
|
||||||
|
|
||||||
// SVG viewbox height (in pixels)
|
|
||||||
100.08,
|
|
||||||
|
|
||||||
// Aliases (not needed)
|
|
||||||
[],
|
|
||||||
|
|
||||||
// Unicode as hex value (not needed)
|
|
||||||
"",
|
|
||||||
|
|
||||||
// SVG path data
|
|
||||||
"M5.49,0h55.95h55.95c1.51,0,2.89,0.62,3.88,1.61c0.99,0.99,1.61,2.37,1.61,3.88v75.79c0,1.51-0.62,2.89-1.61,3.88 c-0.99,0.99-2.37,1.61-3.88,1.61h-25v12.15c0,0.64-0.52,1.16-1.16,1.16H31.66c-0.65,0-1.17-0.53-1.17-1.17V86.77h-25 c-1.51,0-2.89-0.62-3.88-1.61C0.62,84.17,0,82.8,0,81.28V5.49C0,3.98,0.62,2.6,1.61,1.61C2.6,0.62,3.98,0,5.49,0L5.49,0z M45.45,37.11v13.88c0,3.16-0.18,5.45-0.52,6.89c-0.34,1.45-1.05,2.79-2.13,4.05c-1.08,1.25-2.38,2.15-3.9,2.69 c-1.52,0.55-3.22,0.82-5.11,0.82c-2.48,0-4.54-0.29-6.19-0.86c-1.64-0.58-2.95-1.47-3.93-2.68c-0.97-1.22-1.67-2.5-2.08-3.84 c-0.41-1.35-0.61-3.49-0.61-6.42V37.11c0-3.83,0.33-6.69,0.99-8.59c0.66-1.9,1.97-3.43,3.93-4.58c1.96-1.15,4.33-1.72,7.12-1.72 c2.28,0,4.32,0.39,6.12,1.19c1.8,0.8,3.14,1.77,4.03,2.92c0.89,1.15,1.5,2.44,1.82,3.88C45.29,31.66,45.45,33.95,45.45,37.11 L45.45,37.11z M35.08,33.63c0-2.21-0.11-3.59-0.32-4.15c-0.21-0.55-0.71-0.83-1.51-0.83c-0.77,0-1.28,0.3-1.53,0.89 c-0.25,0.59-0.38,1.96-0.38,4.1v20.29c0,2.41,0.11,3.87,0.35,4.36c0.23,0.5,0.73,0.75,1.51,0.75c0.77,0,1.27-0.29,1.52-0.88 c0.24-0.58,0.36-1.89,0.36-3.92V33.63L35.08,33.63z M98.87,23.01v41.64H88.49V42.3c0-3.23-0.07-5.18-0.23-5.83 c-0.15-0.65-0.58-1.15-1.27-1.48c-0.69-0.33-2.24-0.5-4.63-0.5h-1.03v-4.83c5.02-1.07,8.83-3.29,11.42-6.64H98.87L98.87,23.01z M64.96,7.05v72.68h50.87V7.05H64.96L64.96,7.05z M57.92,79.73V7.05H7.05v72.68H57.92L57.92,79.73z"
|
|
||||||
],
|
|
||||||
iconName: "simple-icons-score" as IconName,
|
|
||||||
prefix: "simple-icons" as IconPrefix
|
|
||||||
};
|
|
||||||
@ -1,118 +0,0 @@
|
|||||||
import {useEffect, useRef, useState, memo} from 'react';
|
|
||||||
|
|
||||||
const cache = {};
|
|
||||||
|
|
||||||
export function SmartLogoBackground({
|
|
||||||
src,
|
|
||||||
darkBackground = '#333333',
|
|
||||||
lightBackground = '#f0f0f0',
|
|
||||||
defaultBackground = 'transparent',
|
|
||||||
tolerance = 55,
|
|
||||||
minPixels = 10, // Seuil minimal de pixels détectés pour appliquer un fond
|
|
||||||
alt = 'Logo',
|
|
||||||
style = {},
|
|
||||||
imgClassName = '',
|
|
||||||
}) {
|
|
||||||
const canvasRef = useRef(null);
|
|
||||||
const [background, setBackground] = useState(defaultBackground);
|
|
||||||
const [load, setLoad] = useState(false)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (cache[src]) {
|
|
||||||
setBackground(cache[src]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!load)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const canvas = canvasRef.current;
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
const img = new Image();
|
|
||||||
|
|
||||||
img.crossOrigin = 'Anonymous';
|
|
||||||
img.src = src;
|
|
||||||
|
|
||||||
// Prevent error logging
|
|
||||||
img.onerror = function () {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
img.onload = () => {
|
|
||||||
canvas.width = img.width;
|
|
||||||
canvas.height = img.height;
|
|
||||||
ctx.drawImage(img, 0, 0);
|
|
||||||
|
|
||||||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
||||||
const pixels = imageData.data;
|
|
||||||
let lightBorderCount = 0;
|
|
||||||
let darkBorderCount = 0;
|
|
||||||
|
|
||||||
const isTransparent = (i) => pixels[i + 3] === 0;
|
|
||||||
const isLightColor = (i) => {
|
|
||||||
const r = pixels[i];
|
|
||||||
const g = pixels[i + 1];
|
|
||||||
const b = pixels[i + 2];
|
|
||||||
const a = pixels[i + 3];
|
|
||||||
return r > 255 - tolerance && g > 255 - tolerance && b > 255 - tolerance && a > 128;
|
|
||||||
};
|
|
||||||
const isDarkColor = (i) => {
|
|
||||||
const r = pixels[i];
|
|
||||||
const g = pixels[i + 1];
|
|
||||||
const b = pixels[i + 2];
|
|
||||||
const a = pixels[i + 3];
|
|
||||||
return r < tolerance && g < tolerance && b < tolerance && a > 128;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parcourir une ligne/colonne sur 3
|
|
||||||
for (let y = 0; y < canvas.height; y += Math.max(canvas.height / 500, 1)) {
|
|
||||||
for (let x = 0; x < canvas.width; x += Math.max(canvas.width / 500, 1)) {
|
|
||||||
const i = Math.round(y * canvas.width + x) * 4;
|
|
||||||
if (isTransparent(i)) {
|
|
||||||
const neighbors = [
|
|
||||||
i - 4, // Haut
|
|
||||||
i + 4, // Bas
|
|
||||||
i - 4 * canvas.width, // Gauche
|
|
||||||
i + 4 * canvas.width, // Droite
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const neighbor of neighbors) {
|
|
||||||
if (neighbor >= 0 && neighbor < pixels.length) {
|
|
||||||
if (isLightColor(neighbor)) lightBorderCount++;
|
|
||||||
if (isDarkColor(neighbor)) darkBorderCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (lightBorderCount >= 25 || darkBorderCount >= 25)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lightBorderCount > darkBorderCount && lightBorderCount >= minPixels) {
|
|
||||||
cache[src] = darkBackground;
|
|
||||||
setBackground(darkBackground)
|
|
||||||
} else if (darkBorderCount > lightBorderCount && darkBorderCount >= minPixels) {
|
|
||||||
cache[src] = lightBackground;
|
|
||||||
setBackground(lightBackground)
|
|
||||||
} else {
|
|
||||||
cache[src] = defaultBackground;
|
|
||||||
setBackground(defaultBackground)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [src, darkBackground, lightBackground, defaultBackground, tolerance, minPixels, load]);
|
|
||||||
|
|
||||||
return <>
|
|
||||||
<img className={imgClassName} src={src} alt={alt} style={{...style, filter: `drop-shadow(0 0 1rem ${background})`}}
|
|
||||||
onError={e => {
|
|
||||||
e.target.style.opacity = "0"
|
|
||||||
}}
|
|
||||||
onLoad={e => {
|
|
||||||
e.target.style.opacity = "1"
|
|
||||||
setLoad(true)
|
|
||||||
}}/>
|
|
||||||
<canvas ref={canvasRef} style={{display: 'none'}}/>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SmartLogoBackgroundMemo = memo(SmartLogoBackground);
|
|
||||||
@ -1,5 +1,4 @@
|
|||||||
import {createContext, useContext, useEffect, useReducer} from "react";
|
import {createContext, useContext, useReducer} from "react";
|
||||||
import {useWS} from "./useWS.jsx";
|
|
||||||
|
|
||||||
const CombsContext = createContext({});
|
const CombsContext = createContext({});
|
||||||
const CombsDispatchContext = createContext(() => {
|
const CombsDispatchContext = createContext(() => {
|
||||||
@ -17,18 +16,11 @@ function compareCombs(a, b) {
|
|||||||
function reducer(state, action) {
|
function reducer(state, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'SET_COMB':
|
case 'SET_COMB':
|
||||||
const comb = (action.payload.source === "register") ? action.payload.data : ({
|
if (state[action.payload.id] === undefined || !compareCombs(state[action.payload.id], action.payload)) {
|
||||||
id: action.payload.data.id,
|
console.debug("Updating comb", action.payload);
|
||||||
fname: action.payload.data.fname,
|
|
||||||
lname: action.payload.data.lname,
|
|
||||||
genre: action.payload.data.genre,
|
|
||||||
country: action.payload.data.country,
|
|
||||||
})
|
|
||||||
if (state[comb.id] === undefined || !compareCombs(comb, state[comb.id])) {
|
|
||||||
console.debug("Updating comb", comb);
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
[comb.id]: comb
|
[action.payload.id]: action.payload.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return state
|
return state
|
||||||
@ -66,30 +58,12 @@ function reducer(state, action) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function WSListener({dispatch}) {
|
|
||||||
const {dispatch: dispatchWS} = useWS()
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const sendRegister = ({data}) => {
|
|
||||||
dispatch({type: 'SET_ALL', payload: {source: "register", data: data}});
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatchWS({type: 'addListener', payload: {callback: sendRegister, code: 'sendRegister'}})
|
|
||||||
return () => {
|
|
||||||
dispatchWS({type: 'removeListener', payload: {callback: sendRegister, code: 'sendRegister'}})
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return <></>
|
|
||||||
}
|
|
||||||
|
|
||||||
export function CombsProvider({children}) {
|
export function CombsProvider({children}) {
|
||||||
const [combs, dispatch] = useReducer(reducer, {})
|
const [combs, dispatch] = useReducer(reducer, {})
|
||||||
|
|
||||||
return <CombsContext.Provider value={combs}>
|
return <CombsContext.Provider value={combs}>
|
||||||
<CombsDispatchContext.Provider value={dispatch}>
|
<CombsDispatchContext.Provider value={dispatch}>
|
||||||
{children}
|
{children}
|
||||||
<WSListener dispatch={dispatch}/>
|
|
||||||
</CombsDispatchContext.Provider>
|
</CombsDispatchContext.Provider>
|
||||||
</CombsContext.Provider>
|
</CombsContext.Provider>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import {createContext, useContext, useReducer} from "react";
|
import {createContext, useContext, useReducer} from "react";
|
||||||
|
|
||||||
const PubAffContext = createContext({next: [], c1: undefined, c2: undefined, showScore: true});
|
const PubAffContext = createContext({next: [], c1: undefined, c2: undefined});
|
||||||
const PubAffDispatchContext = createContext(() => {
|
const PubAffDispatchContext = createContext(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,6 @@ import {ContactEditor} from "../../../components/Club/ContactEditor.jsx";
|
|||||||
import {HoraireEditor} from "../../../components/Club/HoraireEditor.jsx";
|
import {HoraireEditor} from "../../../components/Club/HoraireEditor.jsx";
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||||
import {faFilePdf} from "@fortawesome/free-solid-svg-icons";
|
import {faFilePdf} from "@fortawesome/free-solid-svg-icons";
|
||||||
import {SmartLogoBackground} from "../../../components/SmartLogoBackground.jsx";
|
|
||||||
|
|
||||||
const vite_url = import.meta.env.VITE_URL;
|
const vite_url = import.meta.env.VITE_URL;
|
||||||
|
|
||||||
@ -110,10 +109,10 @@ function InformationForm({data}) {
|
|||||||
<TextField name="name" text="Nom" value={data.name}/>
|
<TextField name="name" text="Nom" value={data.name}/>
|
||||||
<CountryList name="country" text="Pays" value={data.country}/>
|
<CountryList name="country" text="Pays" value={data.country}/>
|
||||||
|
|
||||||
<SmartLogoBackground
|
<img
|
||||||
src={`${vite_url}/api/club/${data.clubId}/logo`}
|
src={`${vite_url}/api/club/${data.clubId}/logo`}
|
||||||
alt="avatar"
|
alt="avatar"
|
||||||
imgClassName="img-fluid" style={{object_fit: 'contain', maxHeight: '15em'}}/>
|
className="img-fluid" style={{object_fit: 'contain', maxHeight: '15em'}}/>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<div className="input-group">
|
<div className="input-group">
|
||||||
<label className="input-group-text" htmlFor="logo">Blason</label>
|
<label className="input-group-text" htmlFor="logo">Blason</label>
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import {ContactEditor} from "../../../components/Club/ContactEditor.jsx";
|
|||||||
import {HoraireEditor} from "../../../components/Club/HoraireEditor.jsx";
|
import {HoraireEditor} from "../../../components/Club/HoraireEditor.jsx";
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||||
import {faFilePdf} from "@fortawesome/free-solid-svg-icons";
|
import {faFilePdf} from "@fortawesome/free-solid-svg-icons";
|
||||||
import {SmartLogoBackground} from "../../../components/SmartLogoBackground.jsx";
|
|
||||||
|
|
||||||
const vite_url = import.meta.env.VITE_URL;
|
const vite_url = import.meta.env.VITE_URL;
|
||||||
|
|
||||||
@ -81,10 +80,10 @@ function InformationForm({data}) {
|
|||||||
|
|
||||||
<div className="row mb-3">
|
<div className="row mb-3">
|
||||||
<div className="col-md-6">
|
<div className="col-md-6">
|
||||||
<SmartLogoBackground
|
<img
|
||||||
src={`${vite_url}/api/club/${data.clubId}/logo`}
|
src={`${vite_url}/api/club/${data.clubId}/logo`}
|
||||||
alt="avatar"
|
alt="avatar"
|
||||||
ingClassName="img-fluid" style={{object_fit: 'contain', maxHeight: '15em'}}/>
|
className="img-fluid" style={{object_fit: 'contain', maxHeight: '15em'}}/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-6">
|
<div className="col-md-6">
|
||||||
<a href={`${vite_url}/api/club/${data.id}/status`} target='_blank'>
|
<a href={`${vite_url}/api/club/${data.id}/status`} target='_blank'>
|
||||||
|
|||||||
@ -11,10 +11,9 @@ import {scorePrint, win} from "../../../utils/Tools.js";
|
|||||||
import {toast} from "react-toastify";
|
import {toast} from "react-toastify";
|
||||||
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} from "../../../hooks/useExternalWindow.jsx";
|
import {PubAffProvider, usePubAffDispatch, usePubAffState} from "../../../hooks/useExternalWindow.jsx";
|
||||||
import {faDisplay} from "@fortawesome/free-solid-svg-icons";
|
import {faDisplay} from "@fortawesome/free-solid-svg-icons";
|
||||||
import {PubAffWindow} from "./PubAffWindow.jsx";
|
import {PubAffWindow} from "./PubAffWindow.jsx";
|
||||||
import {SimpleIconsScore} from "../../../assets/SimpleIconsScore.ts";
|
|
||||||
|
|
||||||
function CupImg() {
|
function CupImg() {
|
||||||
return <img decoding="async" loading="lazy" width={"16"} height={"16"} className="wp-image-1635"
|
return <img decoding="async" loading="lazy" width={"16"} height={"16"} className="wp-image-1635"
|
||||||
@ -23,15 +22,8 @@ function CupImg() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function CMTable() {
|
export function CMTable() {
|
||||||
const combDispatch = useCombsDispatch()
|
|
||||||
const [catId, setCatId] = useState(-1);
|
const [catId, setCatId] = useState(-1);
|
||||||
const {data} = useRequestWS("getRegister", null)
|
const menuAction = useRef({});
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (data === null)
|
|
||||||
return;
|
|
||||||
combDispatch({type: 'SET_ALL', payload: {source: "register", data: data}});
|
|
||||||
}, [data]);
|
|
||||||
|
|
||||||
return <PubAffProvider>
|
return <PubAffProvider>
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
@ -48,7 +40,7 @@ export function CMTable() {
|
|||||||
<div className="card">
|
<div className="card">
|
||||||
<div className="card-header">Matches</div>
|
<div className="card-header">Matches</div>
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<CategorieSelect catId={catId} setCatId={setCatId}/>
|
<CategorieSelect catId={catId} setCatId={setCatId} menuAction={menuAction}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{backgroundColor: "#c70000"}}>
|
<div style={{backgroundColor: "#c70000"}}>
|
||||||
@ -56,18 +48,16 @@ export function CMTable() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Menu/>
|
<Menu menuAction={menuAction}/>
|
||||||
</div>
|
</div>
|
||||||
</PubAffProvider>
|
</PubAffProvider>
|
||||||
}
|
}
|
||||||
|
|
||||||
const windowName = "FFSAFScorePublicWindow";
|
const windowName = "FFSAFScorePublicWindow";
|
||||||
|
|
||||||
function Menu() {
|
function Menu({menuAction}) {
|
||||||
const e = document.getElementById("actionMenu")
|
const e = document.getElementById("actionMenu")
|
||||||
const publicAffDispatch = usePubAffDispatch()
|
|
||||||
const [showPubAff, setShowPubAff] = useState(false)
|
const [showPubAff, setShowPubAff] = useState(false)
|
||||||
const [showScore, setShowScore] = useState(true)
|
|
||||||
|
|
||||||
const externalWindow = useRef(null)
|
const externalWindow = useRef(null)
|
||||||
const containerEl = useRef(document.createElement("div"))
|
const containerEl = useRef(document.createElement("div"))
|
||||||
@ -103,28 +93,20 @@ function Menu() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleScore = __ => {
|
|
||||||
setShowScore(!showScore);
|
|
||||||
publicAffDispatch({type: 'SET_DATA', payload: {showScore: !showScore}});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!e)
|
if (!e)
|
||||||
return <></>;
|
return <></>;
|
||||||
return <>
|
return <>
|
||||||
{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={faDisplay} size="xl"
|
<FontAwesomeIcon icon={faDisplay} size="xl" style={{color: showPubAff ? "#00c700" : "#6c757d", cursor: "pointer"}}
|
||||||
style={{color: showPubAff ? "#00c700" : "#6c757d", cursor: "pointer", marginRight: "0.25em"}}
|
|
||||||
onClick={handlePubAff}/>
|
onClick={handlePubAff}/>
|
||||||
<FontAwesomeIcon icon={SimpleIconsScore} size="xl" style={{color: showScore ? "#00c700" : "#6c757d", cursor: "pointer"}}
|
|
||||||
onClick={handleScore}/>
|
|
||||||
</>, document.getElementById("actionMenu"))}
|
</>, document.getElementById("actionMenu"))}
|
||||||
{externalWindow.current && createPortal(<PubAffWindow document={externalWindow.current.document}/>, containerEl.current)}
|
{externalWindow.current && createPortal(<PubAffWindow document={externalWindow.current.document}/>, containerEl.current)}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
function CategorieSelect({catId, setCatId}) {
|
function CategorieSelect({catId, setCatId, menuAction}) {
|
||||||
const setLoading = useLoadingSwitcher()
|
const setLoading = useLoadingSwitcher()
|
||||||
const {data: cats, setData: setCats} = useRequestWS('getAllCategory', {}, setLoading);
|
const {data: cats, setData: setCats} = useRequestWS('getAllCategory', {}, setLoading);
|
||||||
const {dispatch} = useWS();
|
const {dispatch} = useWS();
|
||||||
@ -148,11 +130,11 @@ function CategorieSelect({catId, setCatId}) {
|
|||||||
<option key={c.id} value={c.id}>{c.name}</option>))}
|
<option key={c.id} value={c.id}>{c.name}</option>))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
{catId !== -1 && <MatchPanel catId={catId} cat={cat}/>}
|
{catId !== -1 && <MatchPanel catId={catId} cat={cat} menuAction={menuAction}/>}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
function MatchPanel({catId, cat}) {
|
function MatchPanel({catId, cat, menuAction}) {
|
||||||
const setLoading = useLoadingSwitcher()
|
const setLoading = useLoadingSwitcher()
|
||||||
const {sendRequest, dispatch} = useWS();
|
const {sendRequest, dispatch} = useWS();
|
||||||
const [trees, setTrees] = useState([]);
|
const [trees, setTrees] = useState([]);
|
||||||
@ -224,10 +206,10 @@ function MatchPanel({catId, cat}) {
|
|||||||
}
|
}
|
||||||
}, [catId]);
|
}, [catId]);
|
||||||
|
|
||||||
return <ListMatch cat={cat} matches={matches} trees={trees}/>
|
return <ListMatch cat={cat} matches={matches} trees={trees} menuAction={menuAction}/>
|
||||||
}
|
}
|
||||||
|
|
||||||
function ListMatch({cat, matches, trees}) {
|
function ListMatch({cat, matches, trees, menuAction}) {
|
||||||
const [type, setType] = useState(1);
|
const [type, setType] = useState(1);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -264,7 +246,6 @@ function ListMatch({cat, matches, trees}) {
|
|||||||
|
|
||||||
function MatchList({matches, cat}) {
|
function MatchList({matches, cat}) {
|
||||||
const [activeMatch, setActiveMatch] = useState(null)
|
const [activeMatch, setActiveMatch] = useState(null)
|
||||||
const [lice, setLice] = useState(localStorage.getItem("cm_lice") || "A")
|
|
||||||
const publicAffDispatch = usePubAffDispatch();
|
const publicAffDispatch = usePubAffDispatch();
|
||||||
|
|
||||||
const liceName = (cat.liceName || "N/A").split(";");
|
const liceName = (cat.liceName || "N/A").split(";");
|
||||||
@ -279,7 +260,7 @@ function MatchList({matches, cat}) {
|
|||||||
} else {
|
} else {
|
||||||
publicAffDispatch({
|
publicAffDispatch({
|
||||||
type: 'SET_DATA',
|
type: 'SET_DATA',
|
||||||
payload: {c1: match.c1, c2: match.c2, next: marches2.filter(m => !m.end && m.poule === lice && m.id !== activeMatch).map(m => ({c1: m.c1, c2: m.c2}))}
|
payload: {c1: match.c1, c2: match.c2, next: marches2.filter(m => !m.end && m.id !== activeMatch).map(m => ({c1: m.c1, c2: m.c2}))}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [match]);
|
}, [match]);
|
||||||
@ -288,36 +269,17 @@ function MatchList({matches, cat}) {
|
|||||||
// setActiveMatch(null);
|
// setActiveMatch(null);
|
||||||
//}, [cat])
|
//}, [cat])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (match && match.poule !== lice)
|
|
||||||
setActiveMatch(marches2.find(m => !m.end && m.poule === lice)?.id)
|
|
||||||
}, [lice]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (marches2.length === 0)
|
if (marches2.length === 0)
|
||||||
return;
|
return;
|
||||||
if (marches2.some(m => m.id === activeMatch))
|
if (marches2.some(m => m.id === activeMatch))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
setActiveMatch(marches2.find(m => !m.end && m.poule === lice)?.id);
|
setActiveMatch(marches2.find(m => !m.end)?.id);
|
||||||
}, [matches])
|
}, [matches])
|
||||||
|
|
||||||
const firstIndex = marches2.findLastIndex(m => m.poule === '-') + 1;
|
const firstIndex = marches2.findLastIndex(m => m.poule === '-') + 1;
|
||||||
return <>
|
return <>
|
||||||
{liceName.length > 1 &&
|
|
||||||
<div className="input-group" style={{maxWidth: "10em", marginTop: "0.5em"}}>
|
|
||||||
<label className="input-group-text" htmlFor="selectLice">Lice</label>
|
|
||||||
<select className="form-select" id="selectLice" value={lice} onChange={e => {
|
|
||||||
setLice(e.target.value);
|
|
||||||
localStorage.setItem("cm_lice", e.target.value);
|
|
||||||
}}>
|
|
||||||
{liceName.map((l, index) => (
|
|
||||||
<option key={index} value={l}>{l}</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div className="table-responsive-xxl">
|
<div className="table-responsive-xxl">
|
||||||
<table className="table table-striped table-hover">
|
<table className="table table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
@ -333,7 +295,7 @@ function MatchList({matches, cat}) {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody className="table-group-divider">
|
<tbody className="table-group-divider">
|
||||||
{marches2.map((m, index) => (
|
{marches2.map((m, index) => (
|
||||||
<tr key={m.id} className={m.id === activeMatch ? "table-info" : (m.poule === lice ? "" : "table-warning")} onClick={() => setActiveMatch(m.id)}>
|
<tr key={m.id} className={m.id === activeMatch ? "table-info" : ""} onClick={() => setActiveMatch(m.id)}>
|
||||||
<td style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}}>
|
<td style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}}>
|
||||||
{liceName[(index - firstIndex) % liceName.length]}</td>
|
{liceName[(index - firstIndex) % liceName.length]}</td>
|
||||||
<td style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}}>{m.poule}</td>
|
<td style={{textAlign: "center", paddingLeft: "0.2em", paddingRight: "0.2em"}}>{m.poule}</td>
|
||||||
|
|||||||
@ -1,9 +1,5 @@
|
|||||||
import {useCombs} from "../../../hooks/useComb.jsx";
|
import {useCombs} from "../../../hooks/useComb.jsx";
|
||||||
import {usePubAffState} from "../../../hooks/useExternalWindow.jsx";
|
import {usePubAffState} from "../../../hooks/useExternalWindow.jsx";
|
||||||
import {SmartLogoBackgroundMemo} from "../../../components/SmartLogoBackground.jsx";
|
|
||||||
import {useMemo} from 'react';
|
|
||||||
|
|
||||||
const vite_url = import.meta.env.VITE_URL;
|
|
||||||
|
|
||||||
const noMP = {margin: 0, padding: 0};
|
const noMP = {margin: 0, padding: 0};
|
||||||
const redBackground = "radial-gradient(circle, #C80000FF 0%, #000000FF 100%)"
|
const redBackground = "radial-gradient(circle, #C80000FF 0%, #000000FF 100%)"
|
||||||
@ -18,7 +14,7 @@ export function PubAffWindow({document}) {
|
|||||||
document.title = "A React portal window"
|
document.title = "A React portal window"
|
||||||
document.body.className = "bg-dark text-white overflow-hidden";
|
document.body.className = "bg-dark text-white overflow-hidden";
|
||||||
|
|
||||||
const showScore = state.showScore ?? true;
|
const showScore = false;
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<div className="row text-center"
|
<div className="row text-center"
|
||||||
@ -77,6 +73,8 @@ function MatchDisplay({state}) {
|
|||||||
const {getComb} = useCombs();
|
const {getComb} = useCombs();
|
||||||
const combs = state?.next?.slice(1, 6) || [];
|
const combs = state?.next?.slice(1, 6) || [];
|
||||||
|
|
||||||
|
console.log("Rendering MatchDisplay for", combs);
|
||||||
|
|
||||||
return <div className="col-12 position-relative" style={{height: `calc(${combHeight} * 2)`}}>
|
return <div className="col-12 position-relative" style={{height: `calc(${combHeight} * 2)`}}>
|
||||||
<div className="position-absolute bottom-0 start-0" style={{height: "100%", background: redBackground, width: "50vw"}}/>
|
<div className="position-absolute bottom-0 start-0" style={{height: "100%", background: redBackground, width: "50vw"}}/>
|
||||||
<div className="position-absolute bottom-0 start-50" style={{height: "100%", background: blueBackground, width: "50vw"}}/>
|
<div className="position-absolute bottom-0 start-50" style={{height: "100%", background: blueBackground, width: "50vw"}}/>
|
||||||
@ -101,8 +99,7 @@ function MatchDisplay({state}) {
|
|||||||
<div className="col" style={{fontSize: `3vh`}}>
|
<div className="col" style={{fontSize: `3vh`}}>
|
||||||
{c2.fname} {c2.lname}
|
{c2.fname} {c2.lname}
|
||||||
</div>
|
</div>
|
||||||
{index !== combs.length - 1 &&
|
{index !== combs.length - 1 && <div className="w-75" style={{...noMP, height: "0.2vh", margin: "0 12.5vw", backgroundColor: "#646464AA"}}/>}
|
||||||
<div className="w-75" style={{...noMP, height: "0.2vh", margin: "0 12.5vw", backgroundColor: "#646464AA"}}/>}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
})}
|
})}
|
||||||
@ -110,18 +107,11 @@ function MatchDisplay({state}) {
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
const logoStyle = {width: "6vw", height: "min(11vh, 6vw)", objectFit: "contain", margin: "0 .5vw"};
|
|
||||||
|
|
||||||
function CombDisplay({combId, background, children}) {
|
function CombDisplay({combId, background, children}) {
|
||||||
const {getComb} = useCombs();
|
const {getComb} = useCombs();
|
||||||
const comb = getComb(combId, "");
|
const comb = getComb(combId, "");
|
||||||
|
|
||||||
const logoAlt = useMemo(() => {
|
//console.log("Rendering CombDisplay for", combId, comb);
|
||||||
return comb?.club_str
|
|
||||||
}, [comb]);
|
|
||||||
const logoSrc = useMemo(() => {
|
|
||||||
return `${vite_url}/api/club/${comb?.club_uuid}/logo`
|
|
||||||
}, [comb]);
|
|
||||||
|
|
||||||
return <div className="col position-relative"
|
return <div className="col position-relative"
|
||||||
style={{
|
style={{
|
||||||
@ -133,8 +123,8 @@ function CombDisplay({combId, background, children}) {
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
}}>
|
}}>
|
||||||
{comb !== "" && <>
|
{comb !== "" && <>
|
||||||
<SmartLogoBackgroundMemo src={logoSrc} alt={logoAlt} style={logoStyle}/>
|
<img src={`/flags/svg/ad.svg`} alt={"fr"} style={{width: "6vw", height: "min(9vh, 6vw)", objectFit: "contain", margin: "0 .5vw"}}/>
|
||||||
<div style={{fontSize: "min(3.5vw, 6.5vh)"}}>{comb.fname} {comb.lname}</div>
|
<div style={{fontSize: "min(3.5vw, 10vh)"}}>{comb.fname} {comb.lname}</div>
|
||||||
<img src={`/flags/svg/${comb.country.toLowerCase()}.svg`} alt={comb.country}
|
<img src={`/flags/svg/${comb.country.toLowerCase()}.svg`} alt={comb.country}
|
||||||
style={{width: "4vw", height: "8vh", objectFit: "contain", margin: "0 1.25vw"}}/>
|
style={{width: "4vw", height: "8vh", objectFit: "contain", margin: "0 1.25vw"}}/>
|
||||||
</>}
|
</>}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user