Files
trumpsignal-frontend/store/dashboard.ts
T
k d50c05b120 fix: pre-launch UI hardening + KOL reduce-action type, proxy IP relay, settings redesign
Frontend half of the pre-launch audit campaign:

- types/index.ts + kol/KolPageClient.tsx: add missing 'reduce' KolAction
  (backend emits it; frontend lacked the type + color/label maps → undefined
  styling). Adds ACTION_COLOR/actionLabel/postActionLabel entries.
- proxy/[...path]/route.ts: relay real client IP (x-forwarded-for / x-real-ip)
  so the backend rate limiter buckets per-user instead of per-Next-server (BUG-02).
- Settings/BotConfigPanel redesign, paper-mode clarity, copy cleanup.
- Assorted page/display fixes, loading states, Pagination component.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 11:57:43 +08:00

51 lines
2.1 KiB
TypeScript

import { create } from 'zustand'
interface DashboardState {
selectedPostId: number | null
asset: 'BTC' | 'ETH'
timeframe: '5m' | '15m' | '1H' | '4H' | '1D' | '1W'
walletAddress: string | null
isSubscribed: boolean
botReadiness: 'unknown' | 'saved' | 'verified' | 'ready'
hlApiKeySet: boolean // true if user already has a key saved in backend
hlApiKeyMasked: string | null // e.g. "...a1b2c3" shown after successful save
// BUG-08 fix: backend now streams SOL/TRUMP/BNB/etc. — use an open Record
// so any asset tick can be stored, not just BTC/ETH.
livePrices: Record<string, number | null>
setSelectedPost: (id: number | null) => void
setAsset: (asset: 'BTC' | 'ETH') => void
setTimeframe: (tf: '5m' | '15m' | '1H' | '4H' | '1D' | '1W') => void
setWallet: (address: string | null) => void
setSubscribed: (subscribed: boolean) => void
setBotReadiness: (state: DashboardState['botReadiness']) => void
setHlApiKeySet: (set: boolean, masked?: string) => void
setLivePrice: (asset: string, price: number) => void
}
export const useDashboardStore = create<DashboardState>((set) => ({
selectedPostId: null,
asset: 'BTC',
timeframe: '4H',
walletAddress: null,
isSubscribed: false,
botReadiness: 'unknown',
hlApiKeySet: false,
hlApiKeyMasked: null,
livePrices: { BTC: null, ETH: null, SOL: null, TRUMP: null },
setSelectedPost: (id) => set({ selectedPostId: id }),
setAsset: (asset) => set({ asset }),
setTimeframe: (timeframe) => set({ timeframe }),
setWallet: (walletAddress) => set({ walletAddress }),
setSubscribed: (isSubscribed) => set({ isSubscribed }),
setBotReadiness: (botReadiness) => set({ botReadiness }),
setHlApiKeySet: (keySet, masked) =>
set((s) => ({
hlApiKeySet: keySet,
// Preserve existing mask when called without one (e.g. the /public poll
// only returns a boolean). Only explicitly clear when keySet=false.
hlApiKeyMasked: !keySet ? null : (masked !== undefined ? masked : s.hlApiKeyMasked),
})),
setLivePrice: (asset, price) =>
set((s) => ({ livePrices: { ...s.livePrices, [asset]: price } })),
}))