From 3bbfb8740f1ed02a9f4a2234aee3c4f5f9330f12 Mon Sep 17 00:00:00 2001
From: Lang <7system7@gmail.com>
Date: Tue, 21 Apr 2026 11:30:07 +0200
Subject: [PATCH] chg: dev: massive refactor on front-end for unification and
readiness #8
---
assets/css/homepage/_animations.scss | 9 +
assets/css/homepage/_auth-bar.scss | 9 +
assets/css/homepage/_auth.scss | 9 +
assets/css/homepage/_battle-dialog.scss | 200 ++++++++++++++++++
assets/css/homepage/_content.scss | 9 +
assets/css/homepage/_cta.scss | 9 +
assets/css/homepage/_features.scss | 9 +
assets/css/homepage/_footer.scss | 9 +
assets/css/homepage/_header.scss | 9 +
assets/css/homepage/_hero-compact.scss | 9 +
assets/css/homepage/_hero.scss | 9 +
assets/css/homepage/_reset.scss | 9 +
assets/css/homepage/_responsive.scss | 9 +
assets/css/homepage/_tech.scss | 9 +
assets/css/mineseeker/_back-button.scss | 9 +
assets/css/mineseeker/_base.scss | 9 +
assets/css/mineseeker/_bomb.scss | 9 +
assets/css/mineseeker/_grid.scss | 9 +
assets/css/mineseeker/_mine-counter.scss | 9 +
assets/css/mineseeker/_overlay.scss | 9 +
assets/css/mineseeker/_responsive.scss | 9 +
assets/css/mineseeker/_timer.scss | 9 +
assets/css/mineseeker/_users.scss | 9 +
assets/css/mineseeker/_waiting-dialog.scss | 9 +
assets/css/passkey.scss | 9 +
assets/css/style.homepage.scss | 10 +
assets/css/style.layout.scss | 2 +-
assets/css/style.mineseeker.scss | 2 +-
assets/css/style.scss | 9 +
assets/js/components/AvatarUpload.jsx | 63 +++---
assets/js/components/BattleDialog.jsx | 115 +++++-----
assets/js/components/ContactForm.jsx | 6 +
assets/js/components/PasskeyLogin.jsx | 10 +-
assets/js/components/PasskeyManager.jsx | 34 ++-
assets/js/components/ProfileCharts.jsx | 27 +++
assets/js/components/battle-dialog/Avatar.jsx | 110 +++-------
.../components/battle-dialog/BonusPoints.jsx | 151 ++++++-------
.../js/components/battle-dialog/StatRow.jsx | 47 ++--
assets/js/components/index.js | 18 ++
assets/js/contact.jsx | 3 +-
assets/js/mine-seeker/MineSeeker.jsx | 7 +
assets/js/mine-seeker/components/BonusBox.jsx | 8 +
.../components/BonusStatsDialog.jsx | 102 ++++-----
.../mine-seeker/components/CaptchaOverlay.jsx | 11 +-
.../components/ChallengeCountdown.jsx | 7 +
.../js/mine-seeker/components/GameBoard.jsx | 8 +
.../js/mine-seeker/components/GameTimer.jsx | 91 +++-----
.../components/OnlinePlayersDialog.jsx | 66 +++---
.../components/WaitingOverlayContent.jsx | 8 +
.../components/grid/GridControl.jsx | 14 +-
.../mine-seeker/components/grid/GridField.jsx | 14 ++
assets/js/mine-seeker/components/index.js | 4 +
.../components/profile/PlayerColumn.jsx | 52 +++++
.../mine-seeker/components/timer/Avatar.jsx | 28 +++
.../js/mine-seeker/components/user/User.jsx | 13 ++
.../components/user/UserControl.jsx | 5 +
.../mine-seeker/hooks/useGameDataProvider.js | 18 ++
.../hooks/useServerCommunication.jsx | 3 +-
assets/js/mine-seeker/hooks/useStepTimer.jsx | 7 -
assets/js/passkey.jsx | 3 +-
assets/js/profile.jsx | 38 ++--
assets/js/utils/format.js | 44 ++++
vite.config.js | 2 +
63 files changed, 1096 insertions(+), 480 deletions(-)
create mode 100644 assets/css/homepage/_battle-dialog.scss
create mode 100644 assets/js/components/index.js
create mode 100644 assets/js/mine-seeker/components/profile/PlayerColumn.jsx
create mode 100644 assets/js/mine-seeker/components/timer/Avatar.jsx
create mode 100644 assets/js/utils/format.js
diff --git a/assets/css/homepage/_animations.scss b/assets/css/homepage/_animations.scss
index 7f42902..195bcbe 100644
--- a/assets/css/homepage/_animations.scss
+++ b/assets/css/homepage/_animations.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
@keyframes appear {
from { opacity: 0; transform: scale(0.94); }
to { opacity: 1; transform: scale(1); }
diff --git a/assets/css/homepage/_auth-bar.scss b/assets/css/homepage/_auth-bar.scss
index 1217c93..50b4da3 100644
--- a/assets/css/homepage/_auth-bar.scss
+++ b/assets/css/homepage/_auth-bar.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
#hero-auth {
padding: 20px;
diff --git a/assets/css/homepage/_auth.scss b/assets/css/homepage/_auth.scss
index 4e3f90a..a895dd9 100644
--- a/assets/css/homepage/_auth.scss
+++ b/assets/css/homepage/_auth.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
.auth-page {
display: flex;
flex-direction: column;
diff --git a/assets/css/homepage/_battle-dialog.scss b/assets/css/homepage/_battle-dialog.scss
new file mode 100644
index 0000000..929c66f
--- /dev/null
+++ b/assets/css/homepage/_battle-dialog.scss
@@ -0,0 +1,200 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+// ── Avatar ───────────────────────────────────────────────────────────────────
+
+.bd-avatar-wrap {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 10px;
+ position: relative;
+}
+
+.bd-avatar-ring-wrap {
+ position: relative;
+}
+
+.bd-avatar-ring {
+ width: 72px;
+ height: 72px;
+ border-radius: 50%;
+ background: var(--bd-avatar-gradient);
+ border: 2px solid var(--bd-avatar-border);
+ box-shadow: var(--bd-avatar-glow);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font: 800 24px 'Rajdhani', sans-serif;
+ color: var(--bd-avatar-color);
+ letter-spacing: 2px;
+ overflow: hidden;
+}
+
+.bd-avatar-img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.bd-avatar-bonus {
+ position: absolute;
+ bottom: -6px;
+ right: -6px;
+ background: #ffd700;
+ border-radius: 50%;
+ width: 28px;
+ height: 28px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 0 12px rgba(255, 215, 0, 0.6), 0 0 0 2px rgba(7, 9, 13, 1);
+ border: 2px solid rgba(0, 0, 0, 0.5);
+ z-index: 10;
+
+ i {
+ color: #000;
+ font-size: 14px;
+ }
+}
+
+.bd-avatar-name {
+ font: 700 15px 'Rajdhani', sans-serif;
+ color: var(--bd-avatar-color);
+ letter-spacing: 1px;
+ max-width: 120px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ text-align: center;
+}
+
+.bd-avatar-side {
+ font: 600 10px 'Rajdhani', sans-serif;
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ color: rgba(255, 255, 255, 0.3);
+}
+
+// ── StatRow ──────────────────────────────────────────────────────────────────
+
+.bd-stat-row {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 9px 0;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
+
+ &__icon {
+ width: 16px;
+ color: rgba(149, 207, 245, 0.4);
+ font-size: 13px;
+ }
+
+ &__label {
+ font: 500 13px 'Rajdhani', sans-serif;
+ color: rgba(255, 255, 255, 0.45);
+ flex: 1;
+ letter-spacing: 0.5px;
+ }
+
+ &__value {
+ font: 700 13px 'Rajdhani', sans-serif;
+ color: var(--bd-stat-value-color, rgba(255, 255, 255, 0.75));
+ letter-spacing: 0.5px;
+ }
+}
+
+// ── BonusPoints ──────────────────────────────────────────────────────────────
+
+.bd-bonus {
+ padding: 16px 20px 0;
+ border-top: 1px solid rgba(255, 255, 255, 0.08);
+ margin: 16px 0;
+
+ &__grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 16px;
+ }
+
+ &__column {
+ padding: 16px;
+ border-radius: 6px;
+
+ &--red {
+ border: 1px solid rgba(173, 10, 5, 0.2);
+ background: rgba(173, 10, 5, 0.05);
+ }
+
+ &--blue {
+ border: 1px solid rgba(149, 207, 245, 0.2);
+ background: rgba(149, 207, 245, 0.05);
+ }
+ }
+
+ &__heading {
+ font: 700 12px 'Rajdhani', sans-serif;
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ color: #ffd700;
+ display: block;
+ margin-bottom: 12px;
+
+ i {
+ margin-right: 8px;
+ }
+ }
+
+ &__rows {
+ display: flex;
+ flex-direction: column;
+ }
+}
+
+// ── BattleDialog header actions & bonus score row ────────────────────────────
+
+.bd-header-actions {
+ display: flex;
+ gap: 8px;
+}
+
+.bd-bonus-score {
+ margin-bottom: 8px;
+
+ &__red {
+ font: 700 13px 'Rajdhani', sans-serif;
+ color: #f67d52;
+ display: flex;
+ align-items: center;
+ gap: 4px;
+
+ i {
+ font-size: 11px;
+ }
+ }
+
+ &__blue {
+ font: 700 13px 'Rajdhani', sans-serif;
+ color: #95cff5;
+ display: flex;
+ align-items: center;
+ gap: 4px;
+
+ i {
+ font-size: 11px;
+ }
+ }
+}
+
+.bd-result-badge {
+ background: var(--bd-result-bg);
+ border: 1px solid var(--bd-result-border);
+ color: var(--bd-result-color);
+}
diff --git a/assets/css/homepage/_content.scss b/assets/css/homepage/_content.scss
index d5b82d6..d01ebfe 100644
--- a/assets/css/homepage/_content.scss
+++ b/assets/css/homepage/_content.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
main div.txt {
color: rgba(255, 255, 255, 0.85);
max-width: 900px;
diff --git a/assets/css/homepage/_cta.scss b/assets/css/homepage/_cta.scss
index f2d0d77..3736da7 100644
--- a/assets/css/homepage/_cta.scss
+++ b/assets/css/homepage/_cta.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
.hero-cta {
position: relative;
display: inline-block;
diff --git a/assets/css/homepage/_features.scss b/assets/css/homepage/_features.scss
index d74278f..1bb9c85 100644
--- a/assets/css/homepage/_features.scss
+++ b/assets/css/homepage/_features.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
.feature-block {
width: 100%;
padding: 80px 40px;
diff --git a/assets/css/homepage/_footer.scss b/assets/css/homepage/_footer.scss
index 5f23bc1..a414d16 100644
--- a/assets/css/homepage/_footer.scss
+++ b/assets/css/homepage/_footer.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
footer {
background: #040608;
border-top: 1px solid rgba(35, 111, 135, 0.12);
diff --git a/assets/css/homepage/_header.scss b/assets/css/homepage/_header.scss
index a4226bd..d91cfe5 100644
--- a/assets/css/homepage/_header.scss
+++ b/assets/css/homepage/_header.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
header {
position: relative;
width: 100%;
diff --git a/assets/css/homepage/_hero-compact.scss b/assets/css/homepage/_hero-compact.scss
index ea71fd7..b08ff55 100644
--- a/assets/css/homepage/_hero-compact.scss
+++ b/assets/css/homepage/_hero-compact.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
.hero--compact {
min-height: unset;
padding: 36px 60px 48px;
diff --git a/assets/css/homepage/_hero.scss b/assets/css/homepage/_hero.scss
index 942e6b8..29ea81e 100644
--- a/assets/css/homepage/_hero.scss
+++ b/assets/css/homepage/_hero.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
.hero {
position: relative;
z-index: 2;
diff --git a/assets/css/homepage/_reset.scss b/assets/css/homepage/_reset.scss
index 9c43d4e..72cce14 100644
--- a/assets/css/homepage/_reset.scss
+++ b/assets/css/homepage/_reset.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
* {
outline: none;
padding: 0;
diff --git a/assets/css/homepage/_responsive.scss b/assets/css/homepage/_responsive.scss
index d32b5a7..4fe5ddf 100644
--- a/assets/css/homepage/_responsive.scss
+++ b/assets/css/homepage/_responsive.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
@media screen and (max-width: 900px) {
.hero h1 {
font-size: 44px;
diff --git a/assets/css/homepage/_tech.scss b/assets/css/homepage/_tech.scss
index fdd23ed..cf99d2a 100644
--- a/assets/css/homepage/_tech.scss
+++ b/assets/css/homepage/_tech.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
main {
background: #07090d;
}
diff --git a/assets/css/mineseeker/_back-button.scss b/assets/css/mineseeker/_back-button.scss
index 6a213c2..2981122 100644
--- a/assets/css/mineseeker/_back-button.scss
+++ b/assets/css/mineseeker/_back-button.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
.back-from-game {
display: inline-block;
position: fixed;
diff --git a/assets/css/mineseeker/_base.scss b/assets/css/mineseeker/_base.scss
index d8a12ad..40c8a30 100644
--- a/assets/css/mineseeker/_base.scss
+++ b/assets/css/mineseeker/_base.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
html {
height: 100%;
padding: 0;
diff --git a/assets/css/mineseeker/_bomb.scss b/assets/css/mineseeker/_bomb.scss
index 86c0329..04906af 100644
--- a/assets/css/mineseeker/_bomb.scss
+++ b/assets/css/mineseeker/_bomb.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
#mine-wrapper .game-wrapper .users .user-container .user-control {
background: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.5) 0%, rgba(125, 185, 232, 0) 100%);
background: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.5) 0%, rgba(125, 185, 232, 0) 100%);
diff --git a/assets/css/mineseeker/_grid.scss b/assets/css/mineseeker/_grid.scss
index 07bb4a3..5da85cf 100644
--- a/assets/css/mineseeker/_grid.scss
+++ b/assets/css/mineseeker/_grid.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
#mine-wrapper .grid {
display: flex;
flex-direction: row;
diff --git a/assets/css/mineseeker/_mine-counter.scss b/assets/css/mineseeker/_mine-counter.scss
index d0368cf..fa387e9 100644
--- a/assets/css/mineseeker/_mine-counter.scss
+++ b/assets/css/mineseeker/_mine-counter.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
#mine-wrapper .game-wrapper .users .active-mines-container {
background: -moz-radial-gradient(center, ellipse cover, rgba(255, 252, 252, 1) 0%, rgba(255, 252, 252, 0.99) 1%, rgba(106, 106, 106, 0.39) 61%, rgba(106, 106, 106, 0) 100%);
background: -webkit-radial-gradient(center, ellipse cover, rgba(255, 252, 252, 1) 0%, rgba(255, 252, 252, 0.99) 1%, rgba(106, 106, 106, 0.39) 61%, rgba(106, 106, 106, 0) 100%);
diff --git a/assets/css/mineseeker/_overlay.scss b/assets/css/mineseeker/_overlay.scss
index a6dfa9a..bd6b435 100644
--- a/assets/css/mineseeker/_overlay.scss
+++ b/assets/css/mineseeker/_overlay.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
#mine-wrapper .game-wrapper .game-overlay {
background: rgba(255, 255, 255, 0.2);
display: flex;
diff --git a/assets/css/mineseeker/_responsive.scss b/assets/css/mineseeker/_responsive.scss
index 17b72a5..55b5d48 100644
--- a/assets/css/mineseeker/_responsive.scss
+++ b/assets/css/mineseeker/_responsive.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
@media screen and (max-width: 900px) {
#mine-wrapper .game-wrapper .users {
visibility: hidden;
diff --git a/assets/css/mineseeker/_timer.scss b/assets/css/mineseeker/_timer.scss
index 9fac241..e68ab8a 100644
--- a/assets/css/mineseeker/_timer.scss
+++ b/assets/css/mineseeker/_timer.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
#mine-wrapper .game-timer-container {
display: flex;
gap: 12px;
diff --git a/assets/css/mineseeker/_users.scss b/assets/css/mineseeker/_users.scss
index 98db70a..e1cb153 100644
--- a/assets/css/mineseeker/_users.scss
+++ b/assets/css/mineseeker/_users.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
#mine-wrapper .game-wrapper .users {
width: 180px;
padding: 0 10px 0 0;
diff --git a/assets/css/mineseeker/_waiting-dialog.scss b/assets/css/mineseeker/_waiting-dialog.scss
index 3f6d868..a0c6b3a 100644
--- a/assets/css/mineseeker/_waiting-dialog.scss
+++ b/assets/css/mineseeker/_waiting-dialog.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
.opd-paper {
background: #07090d !important;
background-image: linear-gradient(rgba(35, 111, 135, 0.08) 1px, transparent 1px),
diff --git a/assets/css/passkey.scss b/assets/css/passkey.scss
index ea29656..610e6aa 100644
--- a/assets/css/passkey.scss
+++ b/assets/css/passkey.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
@use "sass:color";
.twofa-status {
diff --git a/assets/css/style.homepage.scss b/assets/css/style.homepage.scss
index b607650..400d10c 100644
--- a/assets/css/style.homepage.scss
+++ b/assets/css/style.homepage.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2019 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
@use 'homepage/reset';
@use 'homepage/animations';
@use 'homepage/header';
@@ -12,4 +21,5 @@
@use 'homepage/tech';
@use 'homepage/footer';
@use 'homepage/profile';
+@use 'homepage/battle-dialog';
@use 'homepage/responsive';
diff --git a/assets/css/style.layout.scss b/assets/css/style.layout.scss
index e038be3..cc6980f 100644
--- a/assets/css/style.layout.scss
+++ b/assets/css/style.layout.scss
@@ -1,7 +1,7 @@
/*!*
* This file is part of the SplendidBear Websites' projects.
*
- * Copyright (c) 2026 @ www.splendidbear.org
+ * Copyright (c) 2019 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
diff --git a/assets/css/style.mineseeker.scss b/assets/css/style.mineseeker.scss
index 34d835b..8b38048 100644
--- a/assets/css/style.mineseeker.scss
+++ b/assets/css/style.mineseeker.scss
@@ -1,7 +1,7 @@
/*!*
* This file is part of the SplendidBear Websites' projects.
*
- * Copyright (c) 2026 @ www.splendidbear.org
+ * Copyright (c) 2019 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
diff --git a/assets/css/style.scss b/assets/css/style.scss
index 9542f17..b0ed6e7 100644
--- a/assets/css/style.scss
+++ b/assets/css/style.scss
@@ -1,3 +1,12 @@
+/*!*
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2019 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
.mine-beta {
position: fixed;
top: 0;
diff --git a/assets/js/components/AvatarUpload.jsx b/assets/js/components/AvatarUpload.jsx
index bcec227..ce1fa8a 100644
--- a/assets/js/components/AvatarUpload.jsx
+++ b/assets/js/components/AvatarUpload.jsx
@@ -1,36 +1,32 @@
-import React, { useRef, useState } from 'react';
+/**
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
-export default function AvatarUpload({ uploadUrl, initialThumbUrl, initials }) {
- const [thumbUrl, setThumbUrl] = useState(initialThumbUrl || null);
- const [loading, setLoading] = useState(false);
- const [error, setError] = useState(null);
+import React, { useMemo, useRef } from 'react';
+import { string } from 'prop-types';
+import { useProfileDataProvider } from '@mine-hooks/useGameDataProvider';
+
+export const AvatarUpload = ({ uploadUrl, initialThumbUrl, initials }) => {
const inputRef = useRef(null);
+ const [thumbUrl, setThumbUrl] = React.useState(initialThumbUrl || null);
+ const { uploadAvatarMutation: { isPending, error, mutate } } = useProfileDataProvider();
- function handleClick() {
- inputRef.current?.click();
- }
-
- function handleChange(e) {
+ const handleChange = e => {
const file = e.target.files?.[0];
if (!file) return;
- const fd = new FormData();
- fd.append('avatar', file);
-
- setLoading(true);
- setError(null);
-
- fetch(uploadUrl, { method: 'POST', body: fd })
- .then(r => r.json())
- .then(data => {
- if (data.error) {
- setError(data.error);
- return;
- }
+ mutate({ uploadUrl, file }, {
+ onSuccess: data => {
setThumbUrl(data.thumbUrl);
const navImg = document.querySelector('.hero-auth-avatar:not(.hero-auth-avatar--initials)');
const navInitials = document.querySelector('.hero-auth-avatar.hero-auth-avatar--initials');
+
if (navImg) {
navImg.src = data.thumbUrl;
} else if (navInitials) {
@@ -40,16 +36,17 @@ export default function AvatarUpload({ uploadUrl, initialThumbUrl, initials }) {
img.className = 'hero-auth-avatar';
navInitials.replaceWith(img);
}
- })
- .catch(() => setError('Upload failed. Please try again.'))
- .finally(() => setLoading(false));
- }
+ },
+ });
+ };
+
+ const errorMessage = useMemo(() => error?.message ?? null, [error]);
return (
inputRef.current?.click()}
>
{thumbUrl
?

@@ -65,7 +62,13 @@ export default function AvatarUpload({ uploadUrl, initialThumbUrl, initials }) {
style={{ display: 'none' }}
onChange={handleChange}
/>
- {error &&
{error}
}
+ {errorMessage &&
{errorMessage}
}
);
}
+
+AvatarUpload.propTypes = {
+ uploadUrl: string.isRequired,
+ initialThumbUrl: string,
+ initials: string.isRequired,
+};
diff --git a/assets/js/components/BattleDialog.jsx b/assets/js/components/BattleDialog.jsx
index f14ee7f..3785839 100644
--- a/assets/js/components/BattleDialog.jsx
+++ b/assets/js/components/BattleDialog.jsx
@@ -1,34 +1,21 @@
+/**
+ * This file is part of the SplendidBear Websites' projects.
+ *
+ * Copyright (c) 2026 @ www.splendidbear.org
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
import React, { useEffect, useState } from 'react';
+import { array } from 'prop-types';
+import { formatDuration } from '@global-utils/format';
import Dialog from '@mui/material/Dialog';
-import { createTheme, ThemeProvider } from '@mui/material/styles';
-import Avatar from './battle-dialog/Avatar';
-import StatRow from './battle-dialog/StatRow';
-import BonusPoints from './battle-dialog/BonusPoints';
+import { createTheme, styled, ThemeProvider } from '@mui/material/styles';
+import { Avatar, BonusPoints, StatRow } from '@global-components';
const darkTheme = createTheme({ palette: { mode: 'dark' } });
-const DIALOG_SX = {
- '& .MuiDialog-paper': {
- background: '#07090d',
- backgroundImage: `
- linear-gradient(rgba(35, 111, 135, 0.08) 1px, transparent 1px),
- linear-gradient(90deg, rgba(35, 111, 135, 0.08) 1px, transparent 1px)
- `,
- backgroundSize: '46px 46px',
- border: '1px solid rgba(35, 111, 135, 0.4)',
- borderRadius: '12px',
- boxShadow: '0 0 80px rgba(35, 111, 135, 0.15), 0 32px 80px rgba(0,0,0,0.9)',
- width: '580px',
- maxWidth: '94vw',
- overflow: 'hidden',
- color: '#fff',
- },
- '& .MuiBackdrop-root': {
- background: 'rgba(2, 4, 8, 0.88)',
- backdropFilter: 'blur(4px)',
- },
-};
-
const RESULT_META = {
win: {
label: 'Victory',
@@ -53,7 +40,7 @@ const RESULT_META = {
},
};
-export default function BattleDialog({ games }) {
+export const BattleDialog = ({ games }) => {
const [open, setOpen] = useState(false);
const [game, setGame] = useState(null);
const [copied, setCopied] = useState(false);
@@ -73,7 +60,7 @@ export default function BattleDialog({ games }) {
}, [games]);
if (!game) {
- return ;
+ return ;
}
const meta = RESULT_META[game.result] ?? RESULT_META.draw;
@@ -86,18 +73,6 @@ export default function BattleDialog({ games }) {
const canContinue = !resign && 26 > maxPoints;
const playUrl = `${window.location.origin}/play/${game.uuid}`;
- const formatDuration = (from, to) => {
- if (!from || !to) return null;
- const diffMs = new Date(to.replace(' ', 'T')) - new Date(from.replace(' ', 'T'));
- if (isNaN(diffMs) || 0 >= diffMs) return null;
- const totalSec = Math.floor(diffMs / 1000);
- const h = Math.floor(totalSec / 3600);
- const m = Math.floor((totalSec % 3600) / 60);
- const s = totalSec % 60;
- if (0 < h) return `${h}h ${m}m ${s}s`;
- if (0 < m) return `${m}m ${s}s`;
- return `${s}s`;
- };
const duration = formatDuration(game.created, game.date);
const pointDiff = Math.abs((game.redPoints ?? 0) - (game.bluePoints ?? 0));
const winnerColor = (game.redPoints ?? 0) > (game.bluePoints ?? 0) ? '#f67d52'
@@ -113,7 +88,7 @@ export default function BattleDialog({ games }) {
return (
-