Spaces:
Sleeping
Sleeping
| import { currencyDecimals } from '../../utils/formatters' | |
| import { SYMBOLS, SPLIT_COLORS } from './BudgetPanel.constants' | |
| export function widgetTheme(dark: boolean) { | |
| if (dark) return { | |
| bg: 'linear-gradient(180deg, #17171d 0%, #0d0d12 100%)', | |
| border: 'rgba(255,255,255,0.07)', | |
| text: '#ffffff', | |
| sub: 'rgba(255,255,255,0.6)', | |
| faint: 'rgba(255,255,255,0.4)', | |
| track: 'rgba(255,255,255,0.04)', | |
| divider: 'rgba(255,255,255,0.07)', | |
| iconBg: 'rgba(255,255,255,0.08)', | |
| iconBorder: 'rgba(255,255,255,0.12)', | |
| iconColor: 'rgba(255,255,255,0.9)', | |
| centerBg: '#17171d', | |
| flowBg: 'rgba(255,255,255,0.05)', | |
| flowBorder: 'rgba(255,255,255,0.07)', | |
| flowHoverBg: 'rgba(255,255,255,0.08)', | |
| flowHoverBorder: 'rgba(255,255,255,0.12)', | |
| rowHover: 'rgba(255,255,255,0.03)', | |
| shadow: '0 20px 50px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.04)', | |
| donutShadow: 'drop-shadow(0 0 20px rgba(0,0,0,0.3))', | |
| } | |
| return { | |
| bg: 'linear-gradient(180deg, #ffffff 0%, #f9fafb 100%)', | |
| border: 'rgba(15,23,42,0.08)', | |
| text: '#111827', | |
| sub: 'rgba(17,24,39,0.6)', | |
| faint: 'rgba(17,24,39,0.4)', | |
| track: 'rgba(15,23,42,0.05)', | |
| divider: 'rgba(15,23,42,0.08)', | |
| iconBg: 'rgba(15,23,42,0.05)', | |
| iconBorder: 'rgba(15,23,42,0.1)', | |
| iconColor: 'rgba(17,24,39,0.75)', | |
| centerBg: '#ffffff', | |
| flowBg: 'rgba(15,23,42,0.03)', | |
| flowBorder: 'rgba(15,23,42,0.08)', | |
| flowHoverBg: 'rgba(15,23,42,0.06)', | |
| flowHoverBorder: 'rgba(15,23,42,0.14)', | |
| rowHover: 'rgba(15,23,42,0.04)', | |
| shadow: '0 12px 32px rgba(15,23,42,0.08), 0 2px 6px rgba(0,0,0,0.04)', | |
| donutShadow: 'drop-shadow(0 4px 18px rgba(15,23,42,0.12))', | |
| } | |
| } | |
| export function hexLighten(hex: string, amount: number): string { | |
| const m = hex.replace('#', '').match(/.{2}/g) | |
| if (!m || m.length !== 3) return hex | |
| const mix = (c: number) => Math.min(255, Math.round(c + (255 - c) * amount)) | |
| const [r, g, b] = m.map(x => parseInt(x, 16)) | |
| return `#${[mix(r), mix(g), mix(b)].map(v => v.toString(16).padStart(2, '0')).join('')}` | |
| } | |
| export const fmtNum = (v: number | null | undefined, locale: string, cur: string) => { | |
| if (v == null || isNaN(v)) return '-' | |
| const d = currencyDecimals(cur) | |
| return Number(v).toLocaleString(locale, { minimumFractionDigits: d, maximumFractionDigits: d }) + ' ' + (SYMBOLS[cur] || cur) | |
| } | |
| type NumOrNull = number | null | undefined | |
| export const calcPP = (p: NumOrNull, n: NumOrNull) => (n! > 0 ? (p as number) / (n as number) : null) | |
| export const calcPD = (p: NumOrNull, d: NumOrNull) => (d! > 0 ? (p as number) / (d as number) : null) | |
| export const calcPPD = (p: NumOrNull, n: NumOrNull, d: NumOrNull) => (n! > 0 && d! > 0 ? (p as number) / ((n as number) * (d as number)) : null) | |
| export function splitColorFor(userId: number, order: number) { | |
| return SPLIT_COLORS[order % SPLIT_COLORS.length] | |
| } | |
| export function colorForUserId(userId: number) { | |
| return SPLIT_COLORS[((userId | 0) - 1 + SPLIT_COLORS.length * 1000) % SPLIT_COLORS.length] | |
| } | |