update a lot

This commit is contained in:
2026-05-19 13:56:13 +04:00
parent 5863574a78
commit 99d28c2114
6 changed files with 64 additions and 35 deletions

View File

@@ -2,8 +2,6 @@
.gitignore .gitignore
node_modules node_modules
**/node_modules **/node_modules
frontend/dist
bin
backend/data backend/data
data data
*.db *.db

View File

@@ -1,26 +1,18 @@
# syntax=docker/dockerfile:1.7 # syntax=docker/dockerfile:1.7
FROM --platform=$BUILDPLATFORM node:20-alpine AS frontend-builder # FROM --platform=$BUILDPLATFORM golang:1.24 AS backend-builder
WORKDIR /app/frontend # WORKDIR /app/backend
COPY frontend/package.json frontend/pnpm-lock.yaml ./ # COPY backend/go.mod backend/go.sum ./
RUN corepack enable && pnpm install --frozen-lockfile # RUN go mod download
COPY frontend/ ./ # COPY backend/ ./
RUN pnpm build # ARG TARGETARCH
# RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH:-amd64} go build -trimpath -ldflags="-s -w" -o /out/shooting-event .
FROM --platform=$BUILDPLATFORM golang:1.24 AS backend-builder
WORKDIR /app/backend
COPY backend/go.mod backend/go.sum ./
RUN go mod download
COPY backend/ ./
COPY --from=frontend-builder /app/frontend/dist ./web
ARG TARGETARCH
RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH:-amd64} go build -trimpath -ldflags="-s -w" -o /out/shooting-event .
FROM --platform=$TARGETPLATFORM alpine:3.21 FROM --platform=$TARGETPLATFORM alpine:3.21
RUN addgroup -S app && adduser -S app -G app && apk add --no-cache ca-certificates RUN addgroup -S app && adduser -S app -G app && apk add --no-cache ca-certificates
WORKDIR /app WORKDIR /app
COPY --from=backend-builder /out/shooting-event /app/shooting-event COPY bin/shooting-event-amd64 /app/shooting-event
COPY --from=backend-builder /app/backend/web /app/web COPY frontend/dist /app/web
RUN mkdir -p /app/data && chown -R app:app /app RUN mkdir -p /app/data && chown -R app:app /app
USER app USER app
ENV PORT=8080 ENV PORT=8080

View File

@@ -36,6 +36,9 @@ build-backend:
mkdir -p bin mkdir -p bin
cd backend && $(GO) build -o ../bin/shooting-event . cd backend && $(GO) build -o ../bin/shooting-event .
build-backend-amd64:
mkdir -p bin
cd backend && GOARCH=amd64 GOOS=linux $(GO) build -o ../bin/shooting-event-amd64 .
build: build-frontend build: build-frontend
rm -rf backend/web rm -rf backend/web
mkdir -p backend/web mkdir -p backend/web

View File

@@ -132,9 +132,13 @@
<tr <tr
v-for="row in pagedPreliminaryRows" v-for="row in pagedPreliminaryRows"
:key="'live-pre-overall-' + row.playerId" :key="'live-pre-overall-' + row.playerId"
:class="{ 'qualified-row': isFinalist(row.playerId) }"
> >
<td class="mono rank">{{ row.rank }}</td> <td class="mono rank">
<div class="live-rank-cell">
<span>{{ row.rank }}</span>
<span v-if="prelimOverallHintLabel(row)" class="live-rank-hint">{{ prelimOverallHintLabel(row) }}</span>
</div>
</td>
<td> <td>
<div class="competitor-cell compact"> <div class="competitor-cell compact">
<img :src="playerImage(row)" :alt="row.nameAr" class="competitor-image" /> <img :src="playerImage(row)" :alt="row.nameAr" class="competitor-image" />
@@ -270,7 +274,12 @@
</thead> </thead>
<tbody> <tbody>
<tr v-for="row in pagedFinalOverallRows" :key="'live-final-overall-' + row.playerId"> <tr v-for="row in pagedFinalOverallRows" :key="'live-final-overall-' + row.playerId">
<td class="mono rank">{{ row.rank }}</td> <td class="mono rank">
<div class="live-rank-cell">
<span>{{ row.rank }}</span>
<span v-if="finalOverallHintLabel(row)" class="live-rank-hint">{{ finalOverallHintLabel(row) }}</span>
</div>
</td>
<td> <td>
<div class="competitor-cell compact"> <div class="competitor-cell compact">
<img :src="playerImage(row)" :alt="row.nameAr" class="competitor-image" /> <img :src="playerImage(row)" :alt="row.nameAr" class="competitor-image" />
@@ -387,6 +396,8 @@ const props = defineProps({
}) })
const finalistIds = computed(() => new Set((props.finalists || []).map((row) => row.playerId))) const finalistIds = computed(() => new Set((props.finalists || []).map((row) => row.playerId)))
const prelimTieIds = computed(() => new Set((props.prelimTieRows || []).map((row) => row.playerId)))
const finalTieIds = computed(() => new Set((props.finalTieRows || []).map((row) => row.playerId)))
const activeView = computed(() => props.liveSettings.activeView || 'group_live') const activeView = computed(() => props.liveSettings.activeView || 'group_live')
const listPageIndex = ref(0) const listPageIndex = ref(0)
const tieGroupIndex = ref(0) const tieGroupIndex = ref(0)
@@ -488,6 +499,25 @@ function isFinalist(playerId) {
return finalistIds.value.has(playerId) return finalistIds.value.has(playerId)
} }
function isPrelimTiePlayer(playerId) {
return prelimTieIds.value.has(playerId)
}
function isFinalTiePlayer(playerId) {
return finalTieIds.value.has(playerId)
}
function prelimOverallHintLabel(row) {
if (isPrelimTiePlayer(row.playerId)) return props.t('labels.tieBreak')
if (isFinalist(row.playerId)) return props.t('labels.finalist')
return ''
}
function finalOverallHintLabel(row) {
if (isFinalTiePlayer(row.playerId)) return props.t('labels.tieBreak')
return ''
}
watch( watch(
() => () =>
`${activeView.value}|${rotationIntervalSec.value}|${rotationPlayerCount.value}|${props.prelimTieRows.length}|${props.preliminaryRows.length}|${props.finalOverallRows.length}|${props.finalTieRows.length}`, `${activeView.value}|${rotationIntervalSec.value}|${rotationPlayerCount.value}|${props.prelimTieRows.length}|${props.preliminaryRows.length}|${props.finalOverallRows.length}|${props.finalTieRows.length}`,

View File

@@ -24,6 +24,7 @@ export const I18N = {
allPlayers: 'جميع اللاعبين', allPlayers: 'جميع اللاعبين',
top12: 'أفضل 12 متأهل', top12: 'أفضل 12 متأهل',
finalist: 'متأهل', finalist: 'متأهل',
tieBreak: 'كسر تعادل',
notFinalist: 'غير متأهل', notFinalist: 'غير متأهل',
noPlayers: 'لا يوجد لاعبين بعد', noPlayers: 'لا يوجد لاعبين بعد',
noFinalists: 'لا يوجد متأهلون بعد', noFinalists: 'لا يوجد متأهلون بعد',
@@ -224,6 +225,7 @@ export const I18N = {
allPlayers: 'All players', allPlayers: 'All players',
top12: 'Top 12 finalists', top12: 'Top 12 finalists',
finalist: 'Finalist', finalist: 'Finalist',
tieBreak: 'Tie-break',
notFinalist: 'Not finalist', notFinalist: 'Not finalist',
noPlayers: 'No players yet', noPlayers: 'No players yet',
noFinalists: 'No finalists yet', noFinalists: 'No finalists yet',

View File

@@ -1514,6 +1514,7 @@ select.name-input {
.live-footer-slot { .live-footer-slot {
display: flex; display: flex;
align-items: center; align-items: center;
min-height: 56px;
} }
.live-footer-slot.left { .live-footer-slot.left {
@@ -1529,18 +1530,13 @@ select.name-input {
} }
.live-footer-logo { .live-footer-logo {
max-width: min(35vw, 200px);
padding: 8px 6px; padding: 8px 6px;
width: auto; width: auto;
height: auto; height: 60px;
object-fit: contain; object-fit: contain;
filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.28)); filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.28));
} }
.live-footer-slot.right .live-footer-logo {
max-width: min(45vw, 280px);
}
.live-tie-grid { .live-tie-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
@@ -1897,8 +1893,20 @@ select.name-input {
background: #0d1931; background: #0d1931;
} }
.live-screen-card .qualified-row { .live-rank-cell {
background: rgba(0, 140, 168, 0.16); display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
}
.live-rank-hint {
color: rgba(255, 255, 255, 0.74);
font-size: 11px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
white-space: nowrap;
} }
.live-podium { .live-podium {
@@ -2901,11 +2909,7 @@ select.name-input {
} }
.live-footer-logo { .live-footer-logo {
max-height: 36px; max-width: min(34vw, 150px);
}
.live-footer-slot.right .live-footer-logo {
max-width: min(40vw, 150px);
} }
.live-tie-grid { .live-tie-grid {