Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions frontend/src/app/app-routing.constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ export const DASHBOARD_USER_DATASET_CREATE = `${DASHBOARD_USER_DATASET}/create`;
export const DASHBOARD_USER_COMPUTING_UNIT = `${DASHBOARD_USER}/compute`;
export const DASHBOARD_USER_QUOTA = `${DASHBOARD_USER}/quota`;
export const DASHBOARD_USER_DISCUSSION = `${DASHBOARD_USER}/discussion`;
export const DASHBOARD_USER_BET_PILOT = `${DASHBOARD_USER}/bet-pilot`;
export const DASHBOARD_USER_BET_PILOT_TODAY = `${DASHBOARD_USER_BET_PILOT}/today`;
export const DASHBOARD_USER_BET_PILOT_SCOUTING = `${DASHBOARD_USER_BET_PILOT}/scouting`;
export const DASHBOARD_USER_BET_PILOT_HEALTH = `${DASHBOARD_USER_BET_PILOT}/health`;
export const DASHBOARD_USER_BET_PILOT_BANKROLL = `${DASHBOARD_USER_BET_PILOT}/bankroll`;
export const DASHBOARD_USER_BET_PILOT_CALIBRATION = `${DASHBOARD_USER_BET_PILOT}/calibration`;
export const DASHBOARD_USER_BET_PILOT_GLOSSARY = `${DASHBOARD_USER_BET_PILOT}/glossary`;
export const DASHBOARD_USER_BET_PILOT_LINES_INPUT = `${DASHBOARD_USER_BET_PILOT}/lines-input`;

export const DASHBOARD_ADMIN = `${DASHBOARD}/admin`;
export const DASHBOARD_ADMIN_USER = `${DASHBOARD_ADMIN}/user`;
Expand Down
22 changes: 22 additions & 0 deletions frontend/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ import { DASHBOARD_ABOUT, DASHBOARD_USER_WORKFLOW } from "./app-routing.constant
import { HubSearchResultComponent } from "./hub/component/hub-search-result/hub-search-result.component";
import { AdminSettingsComponent } from "./dashboard/component/admin/settings/admin-settings.component";
import { GuiConfigService } from "./common/service/gui-config.service";
import { BetPilotComponent } from "./dashboard/component/user/bet-pilot/bet-pilot.component";
import { BpTodayComponent } from "./dashboard/component/user/bet-pilot/screens/bp-today.component";
import { BpScoutingComponent } from "./dashboard/component/user/bet-pilot/screens/bp-scouting.component";
import { BpHealthComponent } from "./dashboard/component/user/bet-pilot/screens/bp-health.component";
import { BpBankrollComponent } from "./dashboard/component/user/bet-pilot/screens/bp-bankroll.component";
import { BpCalibrationComponent } from "./dashboard/component/user/bet-pilot/screens/bp-calibration.component";
import { BpGlossaryComponent } from "./dashboard/component/user/bet-pilot/screens/bp-glossary.component";
import { BpLinesInputComponent } from "./dashboard/component/user/bet-pilot/screens/bp-lines-input.component";

const rootRedirectGuard: CanActivateFn = () => {
const config = inject(GuiConfigService);
Expand Down Expand Up @@ -143,6 +151,20 @@ routes.push({
path: "discussion",
component: FlarumComponent,
},
{
path: "bet-pilot",
component: BetPilotComponent,
children: [
{ path: "", redirectTo: "today", pathMatch: "full" },
{ path: "today", component: BpTodayComponent },
{ path: "scouting", component: BpScoutingComponent },
{ path: "health", component: BpHealthComponent },
{ path: "bankroll", component: BpBankrollComponent },
{ path: "calibration", component: BpCalibrationComponent },
{ path: "glossary", component: BpGlossaryComponent },
{ path: "lines-input", component: BpLinesInputComponent },
],
},
],
},
{
Expand Down
18 changes: 18 additions & 0 deletions frontend/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ import { UserWorkflowComponent } from "./dashboard/component/user/user-workflow/
import { ShareAccessComponent } from "./dashboard/component/user/share-access/share-access.component";
import { WorkflowExecutionHistoryComponent } from "./dashboard/component/user/user-workflow/ngbd-modal-workflow-executions/workflow-execution-history.component";
import { UserQuotaComponent } from "./dashboard/component/user/user-quota/user-quota.component";
import { BetPilotComponent } from "./dashboard/component/user/bet-pilot/bet-pilot.component";
import { BpTodayComponent } from "./dashboard/component/user/bet-pilot/screens/bp-today.component";
import { BpScoutingComponent } from "./dashboard/component/user/bet-pilot/screens/bp-scouting.component";
import { BpHealthComponent } from "./dashboard/component/user/bet-pilot/screens/bp-health.component";
import { BpBankrollComponent } from "./dashboard/component/user/bet-pilot/screens/bp-bankroll.component";
import { BpCalibrationComponent } from "./dashboard/component/user/bet-pilot/screens/bp-calibration.component";
import { BpGlossaryComponent } from "./dashboard/component/user/bet-pilot/screens/bp-glossary.component";
import { BpWfPreviewComponent } from "./dashboard/component/user/bet-pilot/screens/bp-wf-preview.component";
import { BpLinesInputComponent } from "./dashboard/component/user/bet-pilot/screens/bp-lines-input.component";
import { UserIconComponent } from "./dashboard/component/user/user-icon/user-icon.component";
import { UserAvatarComponent } from "./dashboard/component/user/user-avatar/user-avatar.component";
import { CodeEditorComponent } from "./workspace/component/code-editor-dialog/code-editor.component";
Expand Down Expand Up @@ -286,6 +295,15 @@ registerLocaleData(en);
LocalLoginComponent,
UserWorkflowComponent,
UserQuotaComponent,
BetPilotComponent,
BpTodayComponent,
BpScoutingComponent,
BpHealthComponent,
BpBankrollComponent,
BpCalibrationComponent,
BpGlossaryComponent,
BpWfPreviewComponent,
BpLinesInputComponent,
RowModalComponent,
OperatorLabelComponent,
MiniMapComponent,
Expand Down
28 changes: 28 additions & 0 deletions frontend/src/app/dashboard/component/dashboard.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,27 @@
</ul>
</li>

<li
*ngIf="isLogin"
nz-submenu
nzTitle="Apps"
nzIcon="appstore">
<ul>
<li
nz-menu-item
nz-tooltip="Valorant prop-bet picker (stand-in data)"
nzMatchRouter="true"
nzTooltipPlacement="right"
[routerLink]="DASHBOARD_USER_BET_PILOT">
<span
nz-icon
nzType="rocket"></span>
<span>Bet Pilot</span>
<span class="app-version-pill">{{ BET_PILOT_VERSION }}</span>
</li>
</ul>
</li>

<li
*ngIf="sidebarTabs.about_enabled"
nz-menu-item
Expand All @@ -210,6 +231,13 @@
[hidden]="!displayNavbar"
id="nav">
<texera-search-bar></texera-search-bar>
<button
class="app-theme-toggle"
(click)="toggleAppTheme()"
[title]="appTheme === 'dark' ? 'Switch to light theme' : 'Switch to dark theme'"
aria-label="Toggle theme">
{{ appTheme === "dark" ? "☀" : "☾" }}
</button>
<ng-container *ngIf="isLogin">
<texera-user-icon></texera-user-icon>
</ng-container>
Expand Down
42 changes: 42 additions & 0 deletions frontend/src/app/dashboard/component/dashboard.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,45 @@ nz-content {
max-height: 100%;
overflow: hidden;
}

.app-version-pill {
margin-left: auto;
padding: 1px 7px;
font-size: 10px;
font-weight: 600;
letter-spacing: 0.04em;
background: rgba(255, 70, 85, 0.12);
color: #ff4655;
border: 1px solid rgba(255, 70, 85, 0.45);
border-radius: 999px;
line-height: 1.5;
}

.app-theme-toggle {
background: transparent;
border: 1px solid rgba(0, 0, 0, 0.12);
color: inherit;
width: 34px;
height: 34px;
border-radius: 8px;
cursor: pointer;
font-size: 15px;
display: inline-grid;
place-items: center;
margin: 0 8px;
transition:
background-color 0.15s ease,
border-color 0.15s ease,
color 0.15s ease;
&:hover {
background: rgba(0, 0, 0, 0.04);
border-color: rgba(0, 0, 0, 0.22);
}
}
html[data-app-theme="dark"] .app-theme-toggle {
border-color: rgba(255, 255, 255, 0.12);
&:hover {
background: rgba(255, 255, 255, 0.04);
border-color: rgba(255, 255, 255, 0.22);
}
}
30 changes: 30 additions & 0 deletions frontend/src/app/dashboard/component/dashboard.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
DASHBOARD_USER_PROJECT,
DASHBOARD_USER_QUOTA,
DASHBOARD_USER_WORKFLOW,
DASHBOARD_USER_BET_PILOT,
} from "../../app-routing.constant";
import { Version } from "../../../environments/version";
import { SidebarTabs } from "../../common/type/gui-config";
Expand Down Expand Up @@ -115,6 +116,32 @@ export class DashboardComponent implements OnInit {
protected readonly DASHBOARD_ADMIN_GMAIL = DASHBOARD_ADMIN_GMAIL;
protected readonly DASHBOARD_ADMIN_EXECUTION = DASHBOARD_ADMIN_EXECUTION;
protected readonly DASHBOARD_ADMIN_SETTINGS = DASHBOARD_ADMIN_SETTINGS;
protected readonly DASHBOARD_USER_BET_PILOT = DASHBOARD_USER_BET_PILOT;
protected readonly BET_PILOT_VERSION = "v0.1.0";

// Global theme — applies across all of Texera and Bet Pilot.
appTheme: "dark" | "light" = "dark";

toggleAppTheme(): void {
this.applyAppTheme(this.appTheme === "dark" ? "light" : "dark");
}

private applyAppTheme(t: "dark" | "light"): void {
this.appTheme = t;
document.documentElement.setAttribute("data-bp-theme", t);
document.documentElement.setAttribute("data-app-theme", t);
try {
globalThis.localStorage?.setItem("betpilot-theme", t);
} catch {}
}

private readAppTheme(): "dark" | "light" {
try {
return (globalThis.localStorage?.getItem("betpilot-theme") as "dark" | "light" | null) || "dark";
} catch {
return "dark";
}
}

constructor(
private userService: UserService,
Expand All @@ -130,6 +157,9 @@ export class DashboardComponent implements OnInit {
ngOnInit(): void {
this.isCollapsed = false;

// Restore saved theme on app boot.
this.applyAppTheme(this.readAppTheme());

this.router.events.pipe(untilDestroyed(this)).subscribe(() => {
this.checkRoute();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->

<div class="bp-shell">
<aside class="bp-sidebar">
<div class="bp-sidebar-header">
<span class="brand">
<span class="dot"></span>
<span class="wordmark">Bet Pilot</span>
<span class="badge-version">v0.1.0</span>
</span>
</div>

<nav>
<div class="nav-section">
<div class="nav-section-title">Live</div>
<a
class="nav-item"
routerLinkActive="active"
[routerLink]="LINK_TODAY">
<span>Today's bets</span>
<span></span>
<span class="nav-icon">●</span>
</a>
<a
class="nav-item"
routerLinkActive="active"
[routerLink]="LINK_LINES_INPUT">
<span>Lines input</span>
<span></span>
<span class="nav-icon">↥</span>
</a>
<a
class="nav-item"
routerLinkActive="active"
[routerLink]="LINK_HEALTH">
<span>Model health</span>
<span class="nav-sub">amber</span>
<span class="nav-icon">◆</span>
</a>
</div>

<div class="nav-section">
<div class="nav-section-title">Reports</div>
<a
class="nav-item"
routerLinkActive="active"
[routerLink]="LINK_SCOUTING">
<span>Scouting report</span>
<span></span>
<span class="nav-icon">▣</span>
</a>
</div>

<div class="nav-section">
<div class="nav-section-title">Performance</div>
<a
class="nav-item"
routerLinkActive="active"
[routerLink]="LINK_BANKROLL">
<span>Bankroll</span>
<span class="nav-sub">$574</span>
<span class="nav-icon">$</span>
</a>
<a
class="nav-item"
routerLinkActive="active"
[routerLink]="LINK_CALIBRATION">
<span>Calibration log</span>
<span></span>
<span class="nav-icon">◯</span>
</a>
</div>
</nav>

<div class="bp-sidebar-bottom">
<a
class="nav-item"
routerLinkActive="active"
[routerLink]="LINK_GLOSSARY">
<span>Glossary</span>
<span></span>
<span class="nav-icon">?</span>
</a>
</div>
</aside>

<main class="bp-main">
<router-outlet></router-outlet>
</main>
</div>
Loading