diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 2a3ff8d..55bad5b 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,13 @@ Changelog ========= +1.0.6 (Unreleased) +------------------ +- Enh: Match card meta row split into date+time / stage / status; team badges enlarged with rectangular corners; probability tooltip scoped to text; "Show all tips" tied to actual tip existence. +- Enh: The "Show all tips" modal now shows each player's profile picture, matching the leaderboard and Top 10. +- Enh: URL-sourced team flag images keep their own aspect ratio and get a hairline frame drawn on the image, separating white-edged flags (Japan, England, France, …) from the card background. +- Enh: Team badges now prefer the bundled Twemoji flag over the data provider's logo (resolution order: flag → logo → initials), for consistent flags across browsers. + 1.0.5 (June 7, 2026) -------------------- - Fix: Top menu competition entries caused an `UnknownMethodException` on HumHub 1.19, where the deprecated `addItem()` method was removed — replaced with `addEntry()`. diff --git a/module.json b/module.json index 98962d7..aceaf30 100644 --- a/module.json +++ b/module.json @@ -10,7 +10,7 @@ "world cup", "leaderboard" ], - "version": "1.0.5", + "version": "1.0.6", "humhub": { "minVersion": "1.18" }, diff --git a/resources/css/kickoff.css b/resources/css/kickoff.css index d749e73..75fda81 100644 --- a/resources/css/kickoff.css +++ b/resources/css/kickoff.css @@ -150,9 +150,13 @@ } .kickoff-match-card.is-tipped { border-left: 3px solid #28a745; } .kickoff-match-card-meta { - display: flex; justify-content: space-between; + display: grid; grid-template-columns: 1fr auto 1fr; + align-items: baseline; font-size: 12px; margin-bottom: 8px; } +.kickoff-match-card-meta-time { text-align: left; color: #555; } +.kickoff-match-card-meta-stage { text-align: center; } +.kickoff-match-card-meta-status { text-align: right; } .kickoff-match-card-row { display: flex; align-items: center; gap: 12px; } @@ -177,6 +181,31 @@ width: 100%; height: 100%; object-fit: contain; background: #fff; } +.kickoff-team-badge--image, +.kickoff-team-badge--flag { + width: 36px; height: 36px; + border-radius: 3px; + overflow: visible; + background: transparent !important; + font-size: 28px; + line-height: 36px; + text-align: center; + margin-block: -4px; +} +/* URL-sourced flag images: shrink-wrap the img to the image's own ratio + (instead of letterboxing in the square badge) and draw a hairline frame on + top of it — no layout impact, barely visible on colourful flags, but + separates white-edged ones (Japan, England, France, …) from the card + background. An inset box-shadow won't paint over an 's content, so a + negative-offset outline is used; it follows the border-radius. */ +.kickoff-team-badge--image img { + width: auto; height: auto; + max-width: 100%; max-height: 100%; + background: transparent; + border-radius: 3px; + outline: 1px solid rgba(0, 0, 0, 0.12); + outline-offset: -1px; +} .kickoff-match-score { display: flex; align-items: center; gap: 4px; flex-shrink: 0; @@ -184,11 +213,14 @@ .kickoff-score-input { width: 50px !important; } .kickoff-match-card-probabilities { - margin-top: 4px; font-size: 11px; color: #6c757d; - text-align: center; letter-spacing: 0.02em; + margin-top: 4px; text-align: center; +} +.kickoff-probabilities-content { + font-size: 11px; color: #6c757d; + letter-spacing: 0.02em; cursor: help; } -.kickoff-match-card-probabilities span { display: inline-block; padding: 0 2px; } +.kickoff-probabilities-content span { display: inline-block; padding: 0 2px; } .kickoff-live-badge { color: #dc3545; font-weight: 700; letter-spacing: 0.04em; @@ -209,14 +241,20 @@ } .kickoff-match-card-large-score { margin: 4px 0 2px; - text-align: center; + /* 1fr auto 1fr keeps the separator dead-centre so the colon stays put even + when a score reaches two digits (the scores grow outward, not the colon + sideways). */ + display: grid; grid-template-columns: 1fr auto 1fr; + align-items: baseline; font-size: 2rem; font-weight: 700; color: #212529; line-height: 1.1; letter-spacing: 0.04em; } +.kickoff-match-card-large-score-home { text-align: right; } +.kickoff-match-card-large-score-away { text-align: left; } .kickoff-match-card-large-score-sep { color: #adb5bd; - margin: 0 4px; + margin: 0 16px; } .kickoff-match-card-footer { display: flex; align-items: center; gap: 8px; diff --git a/views/competition/_match_card.php b/views/competition/_match_card.php index 5306372..2b43593 100644 --- a/views/competition/_match_card.php +++ b/views/competition/_match_card.php @@ -7,6 +7,8 @@ /** @var Game $game */ /** @var \humhub\modules\kickoff\models\Tip|null $tip */ /** @var bool $editable */ +/** @var bool $canParticipate */ +/** @var bool $hasTips */ /** @var bool $showOtherTipsLink */ /** @var \humhub\modules\kickoff\models\Competition $competition */ @@ -35,6 +37,9 @@ $kickoffTime = $kickoffEpoch !== null ? Yii::$app->formatter->asTime($kickoffEpoch, 'short') : ''; +$kickoffDate = $kickoffEpoch !== null + ? Yii::$app->formatter->asDate($kickoffEpoch, 'short') + : ''; $relativeTime = $kickoffEpoch !== null ? Yii::$app->formatter->asRelativeTime($kickoffEpoch) : ''; @@ -57,27 +62,32 @@ ?>
- - + + + · + + - · + + + + + + + + getFormattedLiveMinute(); ?> + + · + + + + + + + + - - - - getFormattedLiveMinute(); ?> - - · - - - - - - - - -
@@ -110,24 +120,26 @@ class="form-control form-control-sm text-center kickoff-score-input"
- + : - +
-
- % - 0): ?> +
+ + % + 0): ?> + · + % + · - % - - · - % + % +
venue); $hasFooterActions = !empty($showOtherTipsLink); ?> @@ -135,29 +147,25 @@ class="form-control form-control-sm text-center kickoff-score-input"
diff --git a/views/competition/_match_tips.php b/views/competition/_match_tips.php index 2a2360d..6b15608 100644 --- a/views/competition/_match_tips.php +++ b/views/competition/_match_tips.php @@ -2,6 +2,7 @@ use humhub\modules\kickoff\models\Game; use humhub\modules\kickoff\services\KickoffTime; +use humhub\modules\user\widgets\Image as UserImage; use yii\helpers\Html; use yii\helpers\Url; @@ -57,6 +58,7 @@ + @@ -67,6 +69,11 @@ $user = $tip->user; ?> +
+ + $user, 'width' => 34]) ?> + + displayName) : '' . Yii::t('KickoffModule.base', '(deleted user)') . '' ?> home_score ?>:away_score ?> diff --git a/views/competition/_team_badge.php b/views/competition/_team_badge.php index 467a38e..d9e6b48 100644 --- a/views/competition/_team_badge.php +++ b/views/competition/_team_badge.php @@ -9,7 +9,7 @@ $logo = $team && $team->logo_url !== null && $team->logo_url !== '' ? $team->logo_url : null; $flagUrl = null; -if (!$logo && $team) { +if ($team) { // The codepoint sequence doubles as the Twemoji filename: regional // indicator pairs for countries, tag sequences for England/Scotland/Wales. $codepoints = \humhub\modules\kickoff\services\TeamNameLocalizer::flagCodepoints($team->country_code); @@ -44,18 +44,20 @@ $color = $team ? $palette[$team->id % count($palette)] : '#9ca3af'; ?> - - - - <?= Html::encode($name) ?> - - + <?= Html::encode($name) ?> + + + <?= Html::encode($name) ?> + diff --git a/views/competition/view.php b/views/competition/view.php index 2bd637e..0461f48 100644 --- a/views/competition/view.php +++ b/views/competition/view.php @@ -40,6 +40,15 @@ } } +// Games that have at least one tip from any player (one query for the whole matchday). +$gamesWithTips = []; +if ($matchdayGames !== []) { + $gameIds = array_map(fn(Game $g) => $g->id, $matchdayGames); + $gamesWithTips = array_flip( + Tip::find()->select('game_id')->where(['game_id' => $gameIds])->distinct()->column() + ); +} + $this->registerAssetBundle(\humhub\modules\kickoff\assets\Assets::class); $autosaveMessages = [ @@ -430,6 +439,8 @@ class="form-control" 'game' => $g, 'tip' => $tipsByGame[$g->id] ?? null, 'editable' => $canParticipate && !$g->isKickoffPassed(), + 'canParticipate' => $canParticipate, + 'hasTips' => isset($gamesWithTips[$g->id]), 'showOtherTipsLink' => $competition->tipsVisibleForGame($g), 'competition' => $competition, ]) ?>