modif
This commit is contained in:
parent
791cbe79d6
commit
cf2274d49c
8 changed files with 834 additions and 536 deletions
|
|
@ -1,560 +1,568 @@
|
||||||
.match-card {
|
.match-card {
|
||||||
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
||||||
border: 2px solid #daa520;
|
border: 2px solid #daa520;
|
||||||
border-radius: 16px;
|
padding: 24px;
|
||||||
padding: 24px;
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4),
|
||||||
box-shadow:
|
inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||||
0 8px 32px rgba(0, 0, 0, 0.4),
|
position: relative;
|
||||||
inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
overflow: hidden;
|
||||||
position: relative;
|
transition: all 0.3s ease;
|
||||||
overflow: hidden;
|
height: 80vh;
|
||||||
transition: all 0.3s ease;
|
width: 100%;
|
||||||
height: 80vh;
|
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.match-card::before {
|
.match-card::before {
|
||||||
content: '';
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
height: 2px;
|
height: 2px;
|
||||||
background: linear-gradient(90deg, #daa520, #ffd700, #daa520);
|
background: linear-gradient(90deg, #daa520, #ffd700, #daa520);
|
||||||
background-size: 200% 100%;
|
background-size: 200% 100%;
|
||||||
animation: gradientShift 15s ease infinite;
|
animation: gradientShift 15s ease infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes gradientShift {
|
@keyframes gradientShift {
|
||||||
0% {
|
0% {
|
||||||
background-position: 0% 50%;
|
background-position: 0% 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
50% {
|
||||||
background-position: 100% 50%;
|
background-position: 100% 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
background-position: 0% 50%;
|
background-position: 0% 50%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.match-card:hover {
|
.match-card {
|
||||||
transform: translateY(-4px);
|
transform: translateY(-4px);
|
||||||
box-shadow:
|
box-shadow: 0 12px 48px rgba(218, 165, 32, 0.2), 0 8px 32px rgba(0, 0, 0, 0.4);
|
||||||
0 12px 48px rgba(218, 165, 32, 0.2),
|
|
||||||
0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.match-background {
|
.match-background {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.background-image {
|
.background-image {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
filter: grayscale(30%) brightness(0.4) contrast(1.2);
|
filter: grayscale(30%) brightness(0.4) contrast(1.2);
|
||||||
transition: all 0.5s ease;
|
transition: all 0.5s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.match-card:hover .background-image {
|
.match-card:hover .background-image {
|
||||||
filter: grayscale(10%) brightness(0.3) contrast(1.4);
|
filter: grayscale(10%) brightness(0.3) contrast(1.4);
|
||||||
transform: scale(1.05);
|
transform: scale(1.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-overlay {
|
.image-overlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background:
|
background: linear-gradient(
|
||||||
linear-gradient(135deg,
|
135deg,
|
||||||
rgba(26, 26, 46, 0.85) 0%,
|
rgba(26, 26, 46, 0.85) 0%,
|
||||||
rgba(0, 0, 0, 0.7) 50%,
|
rgba(0, 0, 0, 0.7) 50%,
|
||||||
rgba(22, 33, 62, 0.85) 100%
|
rgba(22, 33, 62, 0.85) 100%
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Header */
|
/* Header */
|
||||||
.match-header {
|
.match-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.match-weapon {
|
.match-weapon {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
color: #daa520;
|
color: #daa520;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.weapon-type {
|
.weapon-type {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Status */
|
/* Status */
|
||||||
.match-status {
|
.match-status {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.5px;
|
letter-spacing: 0.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-live {
|
.status-warning {
|
||||||
background: rgba(34, 197, 94, 0.2);
|
background: rgba(34, 197, 94, 0.2);
|
||||||
color: #22c55e;
|
color: #22c55e;
|
||||||
border: 1px solid #22c55e;
|
border: 1px solid #22c55e;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-finished {
|
.status-success {
|
||||||
background: rgba(239, 68, 68, 0.2);
|
background: rgba(239, 68, 68, 0.2);
|
||||||
color: #ef4444;
|
color: #ef4444;
|
||||||
border: 1px solid #ef4444;
|
border: 1px solid #ef4444;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-upcoming {
|
.status-secondary {
|
||||||
background: rgba(59, 130, 246, 0.2);
|
background: rgba(59, 130, 246, 0.2);
|
||||||
color: #3b82f6;
|
color: #3b82f6;
|
||||||
border: 1px solid #3b82f6;
|
border: 1px solid #3b82f6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-dot {
|
.status-dot {
|
||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: currentColor;
|
background: currentColor;
|
||||||
animation: pulse 2s infinite;
|
animation: pulse 2s infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
0%, 100% { opacity: 1; }
|
0%,
|
||||||
50% { opacity: 0.5; }
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Versus Section */
|
/* Versus Section */
|
||||||
.match-versus {
|
.match-versus {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin: 24px 0;
|
margin: 24px 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fencer {
|
.fencer {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fencer-name {
|
.fencer-name {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
color: #daa520;
|
color: #daa520;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fencer-club {
|
.fencer-club {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #9ca3af;
|
color: #9ca3af;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.score {
|
.score {
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
color: white;
|
color: white;
|
||||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
|
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.vs-divider {
|
.vs-divider {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
margin: 0 20px;
|
margin: 0 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vs-text {
|
.vs-text {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #6b7280;
|
color: #6b7280;
|
||||||
letter-spacing: 2px;
|
letter-spacing: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.crossed-swords {
|
.crossed-swords {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Details */
|
/* Details */
|
||||||
.match-details {
|
.match-details {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-item {
|
.detail-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-item .icon {
|
.detail-item .icon {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-item .label {
|
.detail-item .label {
|
||||||
color: #9ca3af;
|
color: #9ca3af;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
min-width: 60px;
|
min-width: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-item .value {
|
.detail-item .value {
|
||||||
color: white;
|
color: white;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Responsive */
|
/* Responsive */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.match-card {
|
.match-card {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.match-versus {
|
.match-versus {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vs-divider {
|
.vs-divider {
|
||||||
transform: rotate(90deg);
|
transform: rotate(90deg);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fencer {
|
.fencer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.combat-arena {
|
.combat-arena {
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
background:
|
background: linear-gradient(
|
||||||
linear-gradient(135deg,
|
135deg,
|
||||||
rgba(220, 38, 38, 0.1) 0%,
|
rgba(220, 38, 38, 0.1) 0%,
|
||||||
rgba(0, 0, 0, 0.8) 50%,
|
rgba(0, 0, 0, 0.8) 50%,
|
||||||
rgba(255, 215, 0, 0.1) 100%
|
rgba(255, 215, 0, 0.1) 100%
|
||||||
);
|
);
|
||||||
border: 2px solid;
|
border: 2px solid;
|
||||||
border-image: linear-gradient(45deg, #dc2626, #ffd700, #dc2626) 1;
|
border-image: linear-gradient(45deg, #dc2626, #ffd700, #dc2626) 1;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.combat-arena::before {
|
.combat-arena::before {
|
||||||
content: '';
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -50%;
|
top: -50%;
|
||||||
left: -50%;
|
left: -50%;
|
||||||
width: 200%;
|
width: 200%;
|
||||||
height: 200%;
|
height: 200%;
|
||||||
background:
|
background: repeating-conic-gradient(
|
||||||
repeating-conic-gradient(
|
from 0deg at 50% 50%,
|
||||||
from 0deg at 50% 50%,
|
transparent 0deg 2deg,
|
||||||
transparent 0deg 2deg,
|
rgba(220, 38, 38, 0.05) 2deg 4deg
|
||||||
rgba(220, 38, 38, 0.05) 2deg 4deg
|
);
|
||||||
);
|
animation: rotate 20s linear infinite;
|
||||||
animation: rotate 20s linear infinite;
|
pointer-events: none;
|
||||||
pointer-events: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes rotate {
|
@keyframes rotate {
|
||||||
0% { transform: rotate(0deg); }
|
0% {
|
||||||
100% { transform: rotate(360deg); }
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Header Arena */
|
/* Header Arena */
|
||||||
.arena-header {
|
.arena-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.arena-title {
|
.arena-title {
|
||||||
font-family: 'Orbitron', monospace;
|
font-family: "Orbitron", monospace;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
color: #ffd700;
|
color: #ffd700;
|
||||||
letter-spacing: 3px;
|
letter-spacing: 3px;
|
||||||
text-shadow:
|
text-shadow: 0 0 10px #ffd700, 0 0 20px #ffd700, 0 0 30px #ffd700;
|
||||||
0 0 10px #ffd700,
|
animation: titleGlow 2s ease-in-out infinite alternate;
|
||||||
0 0 20px #ffd700,
|
|
||||||
0 0 30px #ffd700;
|
|
||||||
animation: titleGlow 2s ease-in-out infinite alternate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes titleGlow {
|
@keyframes titleGlow {
|
||||||
from { text-shadow: 0 0 10px #ffd700, 0 0 20px #ffd700, 0 0 30px #ffd700; }
|
from {
|
||||||
to { text-shadow: 0 0 20px #ffd700, 0 0 30px #ffd700, 0 0 40px #ffd700; }
|
text-shadow: 0 0 10px #ffd700, 0 0 20px #ffd700, 0 0 30px #ffd700;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
text-shadow: 0 0 20px #ffd700, 0 0 30px #ffd700, 0 0 40px #ffd700;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.arena-pulse {
|
.arena-pulse {
|
||||||
width: 10px;
|
width: 10px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
background: #dc2626;
|
background: #dc2626;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
position: relative;
|
position: relative;
|
||||||
animation: pulse-danger 1s infinite;
|
animation: pulse-danger 1s infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.arena-pulse::before {
|
.arena-pulse::before {
|
||||||
content: '';
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -5px;
|
top: -5px;
|
||||||
left: -5px;
|
left: -5px;
|
||||||
right: -5px;
|
right: -5px;
|
||||||
bottom: -5px;
|
bottom: -5px;
|
||||||
background: #dc2626;
|
background: #dc2626;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
animation: pulse-ring 1s infinite;
|
animation: pulse-ring 1s infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse-danger {
|
@keyframes pulse-danger {
|
||||||
0%, 100% { transform: scale(1); }
|
0%,
|
||||||
50% { transform: scale(1.2); }
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse-ring {
|
@keyframes pulse-ring {
|
||||||
0% { transform: scale(0.8); opacity: 0.8; }
|
0% {
|
||||||
100% { transform: scale(2); opacity: 0; }
|
transform: scale(0.8);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(2);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Combat Grid */
|
/* Combat Grid */
|
||||||
.combat-grid {
|
.combat-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.combat-stat {
|
.combat-stat {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
background:
|
background: linear-gradient(
|
||||||
linear-gradient(90deg,
|
90deg,
|
||||||
rgba(0, 0, 0, 0.8) 0%,
|
rgba(0, 0, 0, 0.8) 0%,
|
||||||
rgba(26, 26, 46, 0.9) 50%,
|
rgba(26, 26, 46, 0.9) 50%,
|
||||||
rgba(0, 0, 0, 0.8) 100%
|
rgba(0, 0, 0, 0.8) 100%
|
||||||
);
|
);
|
||||||
border: 1px solid rgba(255, 215, 0, 0.3);
|
border: 1px solid rgba(255, 215, 0, 0.3);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
position: relative;
|
position: relative;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.combat-stat:hover {
|
.combat-stat:hover {
|
||||||
transform: translateX(8px);
|
transform: translateX(8px);
|
||||||
border-color: #ffd700;
|
border-color: #ffd700;
|
||||||
box-shadow:
|
box-shadow: 0 4px 20px rgba(255, 215, 0, 0.3),
|
||||||
0 4px 20px rgba(255, 215, 0, 0.3),
|
inset 0 1px 0 rgba(255, 215, 0, 0.1);
|
||||||
inset 0 1px 0 rgba(255, 215, 0, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Icons animés */
|
/* Icons animés */
|
||||||
.stat-icon {
|
.stat-icon {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 48px;
|
width: 48px;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.location-radar {
|
.location-radar {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
border: 2px solid #10b981;
|
border: 2px solid #10b981;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border-top-color: transparent;
|
border-top-color: transparent;
|
||||||
animation: radar-spin 2s linear infinite;
|
animation: radar-spin 2s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.referee-badge {
|
.referee-badge {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 35px;
|
width: 35px;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
background: linear-gradient(45deg, #ffd700, #ffed4a);
|
background: linear-gradient(45deg, #ffd700, #ffed4a);
|
||||||
clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
|
clip-path: polygon(
|
||||||
animation: badge-pulse 3s ease-in-out infinite;
|
50% 0%,
|
||||||
|
61% 35%,
|
||||||
|
98% 35%,
|
||||||
|
68% 57%,
|
||||||
|
79% 91%,
|
||||||
|
50% 70%,
|
||||||
|
21% 91%,
|
||||||
|
32% 57%,
|
||||||
|
2% 35%,
|
||||||
|
39% 35%
|
||||||
|
);
|
||||||
|
animation: badge-pulse 3s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.time-ring {
|
.time-ring {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 36px;
|
width: 36px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
border: 3px solid #dc2626;
|
border: 3px solid #dc2626;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border-left-color: transparent;
|
border-left-color: transparent;
|
||||||
animation: time-tick 1s linear infinite;
|
animation: time-tick 1s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes radar-spin {
|
@keyframes radar-spin {
|
||||||
0% { transform: rotate(0deg); }
|
0% {
|
||||||
100% { transform: rotate(360deg); }
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes badge-pulse {
|
@keyframes badge-pulse {
|
||||||
0%, 100% { transform: scale(1) rotate(0deg); }
|
0%,
|
||||||
50% { transform: scale(1.1) rotate(5deg); }
|
100% {
|
||||||
|
transform: scale(1) rotate(0deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1.1) rotate(5deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes time-tick {
|
@keyframes time-tick {
|
||||||
0% { transform: rotate(0deg); }
|
0% {
|
||||||
100% { transform: rotate(360deg); }
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Content */
|
/* Content */
|
||||||
.stat-content {
|
.stat-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 2px;
|
gap: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-label {
|
.stat-label {
|
||||||
font-family: 'Orbitron', monospace;
|
font-family: "Orbitron", monospace;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #6b7280;
|
color: #6b7280;
|
||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-value {
|
.stat-value {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-sub {
|
.stat-sub {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
color: #9ca3af;
|
color: #9ca3af;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Glows spécifiques */
|
/* Glows spécifiques */
|
||||||
.venue .stat-value { color: #10b981; }
|
.venue .stat-value {
|
||||||
.referee .stat-value { color: #ffd700; }
|
color: #10b981;
|
||||||
.timing .stat-value { color: #dc2626; }
|
}
|
||||||
|
.referee .stat-value {
|
||||||
|
color: #ffd700;
|
||||||
|
}
|
||||||
|
.timing .stat-value {
|
||||||
|
color: #dc2626;
|
||||||
|
}
|
||||||
|
|
||||||
.stat-glow {
|
.stat-glow {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 0.3s ease;
|
transition: opacity 0.3s ease;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.combat-stat:hover .stat-glow {
|
.combat-stat:hover .stat-glow {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.venue-glow { box-shadow: inset 0 0 20px rgba(16, 185, 129, 0.2); }
|
.venue-glow {
|
||||||
.referee-glow { box-shadow: inset 0 0 20px rgba(255, 215, 0, 0.2); }
|
box-shadow: inset 0 0 20px rgba(16, 185, 129, 0.2);
|
||||||
.timing-glow { box-shadow: inset 0 0 20px rgba(220, 38, 38, 0.2); }
|
|
||||||
|
|
||||||
/* Footer Arena */
|
|
||||||
.arena-footer {
|
|
||||||
margin-top: 20px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
}
|
||||||
|
.referee-glow {
|
||||||
.danger-tape {
|
box-shadow: inset 0 0 20px rgba(255, 215, 0, 0.2);
|
||||||
flex: 1;
|
|
||||||
height: 4px;
|
|
||||||
background:
|
|
||||||
repeating-linear-gradient(
|
|
||||||
45deg,
|
|
||||||
#ffd700 0px,
|
|
||||||
#ffd700 10px,
|
|
||||||
#dc2626 10px,
|
|
||||||
#dc2626 20px
|
|
||||||
);
|
|
||||||
animation: tape-move 2s linear infinite;
|
|
||||||
}
|
}
|
||||||
|
.timing-glow {
|
||||||
@keyframes tape-move {
|
box-shadow: inset 0 0 20px rgba(220, 38, 38, 0.2);
|
||||||
0% { background-position: 0px 0px; }
|
|
||||||
100% { background-position: 28px 0px; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.warning-text {
|
|
||||||
font-family: 'Orbitron', monospace;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: #ffd700;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
animation: warning-blink 1.5s ease-in-out infinite alternate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes warning-blink {
|
|
||||||
0% { opacity: 1; }
|
|
||||||
100% { opacity: 0.6; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Responsive */
|
/* Responsive */
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.combat-grid {
|
.combat-grid {
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
.combat-stat {
|
|
||||||
flex-direction: column;
|
|
||||||
text-align: center;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.combat-stat:hover {
|
|
||||||
transform: translateY(-4px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
.combat-stat {
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.combat-stat:hover {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,91 +1,114 @@
|
||||||
<div class="match-card">
|
<div class="match-card" *ngIf="latestMatch">
|
||||||
<div class="match-background">
|
<div class="match-background">
|
||||||
<img src="./assets/duel.webp" alt="Escrime" class="background-image">
|
<img src="./assets/duel.webp" alt="Escrime" class="background-image" />
|
||||||
<div class="image-overlay"></div>
|
<div class="image-overlay"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="match-header">
|
||||||
|
<div class="match-weapon">
|
||||||
|
<i class="sword-icon">⚔️</i>
|
||||||
|
<span class="weapon-type">{{ latestMatch.weapon }}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="match-status"
|
||||||
|
[ngClass]="'status-' + getMatchStateColor(latestMatch.state)"
|
||||||
|
>
|
||||||
|
<span class="status-dot"></span>
|
||||||
|
{{ getMatchStateLabel(latestMatch.state) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="match-versus">
|
||||||
|
<div class="fencer fencer-left">
|
||||||
|
<div class="fencer-name">
|
||||||
|
{{ player1?.name }} {{ player1?.firstName }}
|
||||||
|
</div>
|
||||||
|
<div class="fencer-club">{{ player1?.club }}</div>
|
||||||
|
<div class="score">{{ latestMatch.score1 }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="match-header">
|
<div class="vs-divider">
|
||||||
<div class="match-weapon">
|
<span class="vs-text">VS</span>
|
||||||
<i class="sword-icon">⚔️</i>
|
<div class="crossed-swords">⚔️</div>
|
||||||
<span class="weapon-type">Épée</span>
|
|
||||||
</div>
|
|
||||||
<div class="match-status status-live">
|
|
||||||
<span class="status-dot"></span>
|
|
||||||
En cours
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="match-versus">
|
<div class="fencer fencer-right">
|
||||||
<div class="fencer fencer-left">
|
<div class="fencer-name">
|
||||||
<div class="fencer-name">Martin DUBOIS</div>
|
{{ player2?.name }} {{ player2?.firstName }}
|
||||||
<div class="fencer-club">CE Paris</div>
|
</div>
|
||||||
<div class="score">12</div>
|
<div class="fencer-club">{{ player2?.club }}</div>
|
||||||
</div>
|
<div class="score">{{ latestMatch.score2 }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="vs-divider">
|
<div class="combat-arena">
|
||||||
<span class="vs-text">VS</span>
|
<div class="arena-header">
|
||||||
<div class="crossed-swords">⚔️</div>
|
<span class="arena-title">ARENA COMBAT</span>
|
||||||
</div>
|
<div class="arena-pulse"></div>
|
||||||
|
|
||||||
<div class="fencer fencer-right">
|
|
||||||
<div class="fencer-name">Sophie BERNARD</div>
|
|
||||||
<div class="fencer-club">Escrime Lyon</div>
|
|
||||||
<div class="score">8</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="combat-arena">
|
<div class="combat-grid">
|
||||||
<div class="arena-header">
|
<div class="combat-stat venue">
|
||||||
<span class="arena-title">ARENA COMBAT</span>
|
<div class="stat-icon">
|
||||||
<div class="arena-pulse"></div>
|
<div class="location-radar"></div>
|
||||||
|
<span>🏛️</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="stat-content">
|
||||||
<div class="combat-grid">
|
<span class="stat-label">BATTLEFIELD</span>
|
||||||
<div class="combat-stat venue">
|
<span class="stat-value">{{ latestMatch.city }}</span>
|
||||||
<div class="stat-icon">
|
<span class="stat-sub">{{ latestMatch.country }}</span>
|
||||||
<div class="location-radar"></div>
|
|
||||||
<span>🏛️</span>
|
|
||||||
</div>
|
|
||||||
<div class="stat-content">
|
|
||||||
<span class="stat-label">BATTLEFIELD</span>
|
|
||||||
<span class="stat-value">Gymnase Jean Moulin</span>
|
|
||||||
<span class="stat-sub">PARIS • ZONE A</span>
|
|
||||||
</div>
|
|
||||||
<div class="stat-glow venue-glow"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="combat-stat referee">
|
|
||||||
<div class="stat-icon">
|
|
||||||
<div class="referee-badge"></div>
|
|
||||||
<span>⚖️</span>
|
|
||||||
</div>
|
|
||||||
<div class="stat-content">
|
|
||||||
<span class="stat-label">COMBAT JUDGE</span>
|
|
||||||
<span class="stat-value">Pierre MARTIN</span>
|
|
||||||
<span class="stat-sub">OFFICIAL REFEREE</span>
|
|
||||||
</div>
|
|
||||||
<div class="stat-glow referee-glow"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="combat-stat timing">
|
|
||||||
<div class="stat-icon">
|
|
||||||
<div class="time-ring"></div>
|
|
||||||
<span>⚡</span>
|
|
||||||
</div>
|
|
||||||
<div class="stat-content">
|
|
||||||
<span class="stat-label">COMBAT START</span>
|
|
||||||
<span class="stat-value">14:30</span>
|
|
||||||
<span class="stat-sub">LIVE BATTLE</span>
|
|
||||||
</div>
|
|
||||||
<div class="stat-glow timing-glow"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="stat-glow venue-glow"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="arena-footer">
|
<div class="combat-stat referee">
|
||||||
<div class="danger-tape"></div>
|
<div class="stat-icon">
|
||||||
<span class="warning-text">⚠️ COMBAT ZONE ACTIVE ⚠️</span>
|
<div class="referee-badge"></div>
|
||||||
|
<span>⚖️</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="stat-content">
|
||||||
|
<span class="stat-label">COMBAT JUDGE</span>
|
||||||
|
<span class="stat-value"
|
||||||
|
>{{ referee?.name }} {{ referee?.firstName }}</span
|
||||||
|
>
|
||||||
|
<span class="stat-sub">OFFICIAL REFEREE</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat-glow referee-glow"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="combat-stat timing"
|
||||||
|
*ngIf="latestMatch?.state === MatchState.NOT_STARTED"
|
||||||
|
>
|
||||||
|
<div class="stat-icon">
|
||||||
|
<div class="time-ring"></div>
|
||||||
|
<span>⚡</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat-content">
|
||||||
|
<span class="stat-label">COMBAT START</span>
|
||||||
|
<span class="stat-value">{{ getTimeUntilMatch() }}</span>
|
||||||
|
<span class="stat-sub">LIVE BATTLE</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat-glow timing-glow"></div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="combat-stat funfact"
|
||||||
|
*ngIf="latestMatch?.state !== MatchState.NOT_STARTED"
|
||||||
|
>
|
||||||
|
<div class="stat-icon">
|
||||||
|
<span>🎯</span>
|
||||||
|
</div>
|
||||||
|
<div class="stat-content">
|
||||||
|
<span class="stat-label">FUN FACT</span>
|
||||||
|
<span class="stat-value">
|
||||||
|
Saviez-vous que l'escrime est l'un des sports les plus anciens aux
|
||||||
|
Jeux Olympiques ?
|
||||||
|
</span>
|
||||||
|
<span class="stat-sub">Inspiration et tradition au rendez-vous</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<app-sponsort></app-sponsort>
|
<app-sponsort></app-sponsort>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,159 @@
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
import { MatchesService } from '@services/matches/matches.service';
|
||||||
|
import { Matches, MatchState } from '@interfaces/matches';
|
||||||
|
|
||||||
|
import { PlayerService } from '@services/player/player.service';
|
||||||
|
import { Player } from '@interfaces/player';
|
||||||
|
|
||||||
|
import { RefereeService } from '@services/referee/referee.service';
|
||||||
|
import { Referee, RefereeLevel } from '@interfaces/referee';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-home',
|
selector: 'app-home',
|
||||||
standalone: false,
|
standalone: false,
|
||||||
templateUrl: './home.component.html',
|
templateUrl: './home.component.html',
|
||||||
styleUrl: './home.component.css',
|
styleUrl: './home.component.css',
|
||||||
})
|
})
|
||||||
export class HomeComponent {}
|
export class HomeComponent {
|
||||||
|
latestMatch?: Matches;
|
||||||
|
player1?: Player;
|
||||||
|
player2?: Player;
|
||||||
|
referee?: Referee;
|
||||||
|
MatchState = MatchState;
|
||||||
|
intervalId?: any;
|
||||||
|
timeUntilMatch: string | null = null;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private matchesService: MatchesService,
|
||||||
|
private playerService: PlayerService,
|
||||||
|
private refereeService: RefereeService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.getLatestMatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (this.intervalId) {
|
||||||
|
clearInterval(this.intervalId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getLatestMatch(): void {
|
||||||
|
this.matchesService.getMatches().subscribe((matches) => {
|
||||||
|
if (matches.length > 0) {
|
||||||
|
this.latestMatch = matches[matches.length - 1];
|
||||||
|
console.log(
|
||||||
|
'[HomeComponent] 🏁 Dernier match ajouté :',
|
||||||
|
this.latestMatch
|
||||||
|
);
|
||||||
|
|
||||||
|
// Récupération des données liées
|
||||||
|
this.loadRelatedEntities(this.latestMatch);
|
||||||
|
|
||||||
|
if (this.latestMatch.state === MatchState.NOT_STARTED) {
|
||||||
|
this.updateTimeUntilMatch(); // initial
|
||||||
|
this.intervalId = setInterval(() => {
|
||||||
|
this.updateTimeUntilMatch();
|
||||||
|
}, 60000); // chaque minute
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn('[HomeComponent] Aucun match disponible');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateTimeUntilMatch(): void {
|
||||||
|
if (!this.latestMatch) return;
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
const matchDate = new Date(this.latestMatch.date);
|
||||||
|
const diffMs = matchDate.getTime() - now.getTime();
|
||||||
|
|
||||||
|
if (diffMs <= 0) {
|
||||||
|
this.timeUntilMatch = null;
|
||||||
|
clearInterval(this.intervalId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalMinutes = Math.floor(diffMs / (1000 * 60));
|
||||||
|
const days = Math.floor(totalMinutes / (60 * 24));
|
||||||
|
const hours = Math.floor((totalMinutes % (60 * 24)) / 60);
|
||||||
|
const minutes = totalMinutes % 60;
|
||||||
|
|
||||||
|
let result = '';
|
||||||
|
if (days > 0) result += `${days}j `;
|
||||||
|
if (hours > 0 || days > 0) result += `${hours}h `;
|
||||||
|
result += `${minutes}min`;
|
||||||
|
|
||||||
|
this.timeUntilMatch = result.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
private loadRelatedEntities(match: Matches): void {
|
||||||
|
this.playerService.getPlayerById(match.player1ID).subscribe((p1) => {
|
||||||
|
this.player1 = p1!;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.playerService.getPlayerById(match.player2ID).subscribe((p2) => {
|
||||||
|
this.player2 = p2!;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.refereeService.getRefereeById(match.refereeID).subscribe((ref) => {
|
||||||
|
this.referee = ref!;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getMatchStateLabel(state: MatchState): string {
|
||||||
|
switch (state) {
|
||||||
|
case MatchState.NOT_STARTED:
|
||||||
|
return 'À venir';
|
||||||
|
case MatchState.ONGOING:
|
||||||
|
return 'En cours';
|
||||||
|
case MatchState.OVER:
|
||||||
|
return 'Terminé';
|
||||||
|
default:
|
||||||
|
return 'Inconnu';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getMatchStateColor(state: MatchState): string {
|
||||||
|
switch (state) {
|
||||||
|
case MatchState.NOT_STARTED:
|
||||||
|
return 'secondary';
|
||||||
|
case MatchState.ONGOING:
|
||||||
|
return 'warning';
|
||||||
|
case MatchState.OVER:
|
||||||
|
return 'success';
|
||||||
|
default:
|
||||||
|
return 'light';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getTimeUntilMatch(): string | null {
|
||||||
|
if (
|
||||||
|
!this.latestMatch ||
|
||||||
|
this.latestMatch.state !== MatchState.NOT_STARTED
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
const matchDate = new Date(this.latestMatch.date);
|
||||||
|
const diffMs = matchDate.getTime() - now.getTime();
|
||||||
|
|
||||||
|
if (diffMs <= 0) return null;
|
||||||
|
|
||||||
|
const totalMinutes = Math.floor(diffMs / (1000 * 60));
|
||||||
|
const days = Math.floor(totalMinutes / (60 * 24));
|
||||||
|
const hours = Math.floor((totalMinutes % (60 * 24)) / 60);
|
||||||
|
const minutes = totalMinutes % 60;
|
||||||
|
|
||||||
|
let result = '';
|
||||||
|
if (days > 0) result += `${days}j `;
|
||||||
|
if (hours > 0 || days > 0) result += `${hours}h `;
|
||||||
|
result += `${minutes}min`;
|
||||||
|
|
||||||
|
return result.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
form fieldset {
|
||||||
|
background-color: #f8f9fa; /* gris clair */
|
||||||
|
}
|
||||||
|
|
||||||
|
form legend {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
form label {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
form button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.6rem;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
@ -1,102 +1,171 @@
|
||||||
<h2>Ajouter un match</h2>
|
<h2 class="mb-4">Ajouter un match</h2>
|
||||||
|
|
||||||
<form (ngSubmit)="onSubmit()">
|
<form (ngSubmit)="onSubmit()" class="needs-validation" novalidate>
|
||||||
<fieldset>
|
<fieldset class="border p-3 mb-4 rounded">
|
||||||
<legend>Joueur 1</legend>
|
<legend class="w-auto px-2">Joueur 1</legend>
|
||||||
<label>Prénom :</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
[(ngModel)]="formData.player1FirstName"
|
|
||||||
name="player1FirstName"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
|
|
||||||
<label>Nom :</label>
|
<div class="mb-3">
|
||||||
<input
|
<label class="form-label">Prénom :</label>
|
||||||
type="text"
|
<input
|
||||||
[(ngModel)]="formData.player1Name"
|
type="text"
|
||||||
name="player1Name"
|
class="form-control"
|
||||||
required
|
[(ngModel)]="formData.player1FirstName"
|
||||||
/>
|
name="player1FirstName"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Club :</label>
|
<div class="mb-3">
|
||||||
<input
|
<label class="form-label">Nom :</label>
|
||||||
type="text"
|
<input
|
||||||
[(ngModel)]="formData.player1Club"
|
type="text"
|
||||||
name="player1Club"
|
class="form-control"
|
||||||
required
|
[(ngModel)]="formData.player1Name"
|
||||||
/>
|
name="player1Name"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Club :</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
[(ngModel)]="formData.player1Club"
|
||||||
|
name="player1Club"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset class="border p-3 mb-4 rounded">
|
||||||
<legend>Joueur 2</legend>
|
<legend class="w-auto px-2">Joueur 2</legend>
|
||||||
<label>Prénom :</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
[(ngModel)]="formData.player2FirstName"
|
|
||||||
name="player2FirstName"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
|
|
||||||
<label>Nom :</label>
|
<div class="mb-3">
|
||||||
<input
|
<label class="form-label">Prénom :</label>
|
||||||
type="text"
|
<input
|
||||||
[(ngModel)]="formData.player2Name"
|
type="text"
|
||||||
name="player2Name"
|
class="form-control"
|
||||||
required
|
[(ngModel)]="formData.player2FirstName"
|
||||||
/>
|
name="player2FirstName"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Club :</label>
|
<div class="mb-3">
|
||||||
<input
|
<label class="form-label">Nom :</label>
|
||||||
type="text"
|
<input
|
||||||
[(ngModel)]="formData.player2Club"
|
type="text"
|
||||||
name="player2Club"
|
class="form-control"
|
||||||
required
|
[(ngModel)]="formData.player2Name"
|
||||||
/>
|
name="player2Name"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Club :</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
[(ngModel)]="formData.player2Club"
|
||||||
|
name="player2Club"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset class="border p-3 mb-4 rounded">
|
||||||
<legend>Arbitre</legend>
|
<legend class="w-auto px-2">Arbitre</legend>
|
||||||
<label>Prénom :</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
[(ngModel)]="formData.refereeFirstName"
|
|
||||||
name="refereeFirstName"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
|
|
||||||
<label>Nom :</label>
|
<div class="mb-3">
|
||||||
<input
|
<label class="form-label">Prénom :</label>
|
||||||
type="text"
|
<input
|
||||||
[(ngModel)]="formData.refereeName"
|
type="text"
|
||||||
name="refereeName"
|
class="form-control"
|
||||||
required
|
[(ngModel)]="formData.refereeFirstName"
|
||||||
/>
|
name="refereeFirstName"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Niveau :</label>
|
<div class="mb-3">
|
||||||
<select [(ngModel)]="formData.refereelevel" name="refereelevel" required>
|
<label class="form-label">Nom :</label>
|
||||||
<option [value]="0">Départemental</option>
|
<input
|
||||||
<option [value]="1">Régional</option>
|
type="text"
|
||||||
<option [value]="2">National</option>
|
class="form-control"
|
||||||
<option [value]="3">International</option>
|
[(ngModel)]="formData.refereeName"
|
||||||
</select>
|
name="refereeName"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Niveau :</label>
|
||||||
|
<select
|
||||||
|
class="form-select"
|
||||||
|
[(ngModel)]="formData.refereelevel"
|
||||||
|
name="refereelevel"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<option [value]="0">Départemental</option>
|
||||||
|
<option [value]="1">Régional</option>
|
||||||
|
<option [value]="2">National</option>
|
||||||
|
<option [value]="3">International</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset class="border p-3 mb-4 rounded">
|
||||||
<legend>Match</legend>
|
<legend class="w-auto px-2">Match</legend>
|
||||||
<label>Ville :</label>
|
|
||||||
<input type="text" [(ngModel)]="formData.city" name="city" required />
|
|
||||||
|
|
||||||
<label>Pays :</label>
|
<div class="mb-3">
|
||||||
<input type="text" [(ngModel)]="formData.country" name="country" required />
|
<label class="form-label">Ville :</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
[(ngModel)]="formData.city"
|
||||||
|
name="city"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Arme :</label>
|
<div class="mb-3">
|
||||||
<select [(ngModel)]="formData.weapon" name="weapon" required>
|
<label class="form-label">Pays :</label>
|
||||||
<option value="Épée">Épée</option>
|
<input
|
||||||
<option value="Sabre">Sabre</option>
|
type="text"
|
||||||
<option value="Fleuret">Fleuret</option>
|
class="form-control"
|
||||||
</select>
|
[(ngModel)]="formData.country"
|
||||||
|
name="country"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Arme :</label>
|
||||||
|
<select
|
||||||
|
class="form-select"
|
||||||
|
[(ngModel)]="formData.weapon"
|
||||||
|
name="weapon"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<option value="Épée">Épée</option>
|
||||||
|
<option value="Sabre">Sabre</option>
|
||||||
|
<option value="Fleuret">Fleuret</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Date :</label>
|
||||||
|
<input
|
||||||
|
type="datetime-local"
|
||||||
|
class="form-control"
|
||||||
|
[(ngModel)]="formData.date"
|
||||||
|
name="date"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<button type="submit">Créer le match</button>
|
<button type="submit" class="btn btn-primary">Créer le match</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ export class MatchesAddComponent {
|
||||||
city: '',
|
city: '',
|
||||||
country: '',
|
country: '',
|
||||||
weapon: '',
|
weapon: '',
|
||||||
|
date: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|
@ -82,7 +83,7 @@ export class MatchesAddComponent {
|
||||||
country: this.formData.country,
|
country: this.formData.country,
|
||||||
city: this.formData.city,
|
city: this.formData.city,
|
||||||
weapon: this.formData.weapon,
|
weapon: this.formData.weapon,
|
||||||
date: new Date(),
|
date: new Date(this.formData.date),
|
||||||
state: MatchState.NOT_STARTED,
|
state: MatchState.NOT_STARTED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ import { Player } from '@interfaces/player';
|
||||||
import { RefereeService } from '@services/referee/referee.service';
|
import { RefereeService } from '@services/referee/referee.service';
|
||||||
import { Referee, RefereeLevel } from '@interfaces/referee';
|
import { Referee, RefereeLevel } from '@interfaces/referee';
|
||||||
|
|
||||||
|
import { getMatchStateLabel, getMatchStateColor } from '@utils/getState';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-matches-id',
|
selector: 'app-matches-id',
|
||||||
standalone: false,
|
standalone: false,
|
||||||
|
|
|
||||||
27
FencerJudgeFront/src/app/utils/getState.ts
Normal file
27
FencerJudgeFront/src/app/utils/getState.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { MatchState } from '@interfaces/matches';
|
||||||
|
|
||||||
|
export function getMatchStateLabel(state: MatchState): string {
|
||||||
|
switch (state) {
|
||||||
|
case MatchState.NOT_STARTED:
|
||||||
|
return 'À venir';
|
||||||
|
case MatchState.ONGOING:
|
||||||
|
return 'En cours';
|
||||||
|
case MatchState.OVER:
|
||||||
|
return 'Terminé';
|
||||||
|
default:
|
||||||
|
return 'Inconnu';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMatchStateColor(state: MatchState): string {
|
||||||
|
switch (state) {
|
||||||
|
case MatchState.NOT_STARTED:
|
||||||
|
return 'secondary';
|
||||||
|
case MatchState.ONGOING:
|
||||||
|
return 'warning';
|
||||||
|
case MatchState.OVER:
|
||||||
|
return 'success';
|
||||||
|
default:
|
||||||
|
return 'light';
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue