mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 09:33:46 +00:00
fix: replace hardcoded green with theme-aware accent color
Normal traffic zone now uses configurable accent palette instead of hardcoded success/green. Added useTrafficZone hook that resolves mainHex dynamically from theme colors. Replaced emerald/teal classes with success palette in SuccessNotificationModal. Fixed hardcoded green hex values in Subscription and SubscriptionPurchase pages.
This commit is contained in:
@@ -159,13 +159,13 @@ export default function SuccessNotificationModal() {
|
|||||||
let title = data.title;
|
let title = data.title;
|
||||||
const message = data.message;
|
const message = data.message;
|
||||||
let icon = <CheckCircleIcon />;
|
let icon = <CheckCircleIcon />;
|
||||||
let gradientClass = 'from-success-500 to-emerald-600';
|
let gradientClass = 'from-success-500 to-success-600';
|
||||||
|
|
||||||
if (!title) {
|
if (!title) {
|
||||||
if (isBalanceTopup) {
|
if (isBalanceTopup) {
|
||||||
title = t('successNotification.balanceTopup.title', 'Balance topped up!');
|
title = t('successNotification.balanceTopup.title', 'Balance topped up!');
|
||||||
icon = <WalletIcon />;
|
icon = <WalletIcon />;
|
||||||
gradientClass = 'from-success-500 to-emerald-600';
|
gradientClass = 'from-success-500 to-success-600';
|
||||||
} else if (data.type === 'subscription_activated') {
|
} else if (data.type === 'subscription_activated') {
|
||||||
title = t('successNotification.subscriptionActivated.title', 'Subscription activated!');
|
title = t('successNotification.subscriptionActivated.title', 'Subscription activated!');
|
||||||
icon = <RocketIcon />;
|
icon = <RocketIcon />;
|
||||||
@@ -185,7 +185,7 @@ export default function SuccessNotificationModal() {
|
|||||||
} else if (data.type === 'traffic_purchased') {
|
} else if (data.type === 'traffic_purchased') {
|
||||||
title = t('successNotification.trafficPurchased.title', 'Traffic added!');
|
title = t('successNotification.trafficPurchased.title', 'Traffic added!');
|
||||||
icon = <TrafficIcon />;
|
icon = <TrafficIcon />;
|
||||||
gradientClass = 'from-emerald-500 to-teal-600';
|
gradientClass = 'from-success-500 to-success-600';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,7 +273,7 @@ export default function SuccessNotificationModal() {
|
|||||||
<span className="text-dark-400">
|
<span className="text-dark-400">
|
||||||
{t('successNotification.trafficAdded', 'Traffic added')}
|
{t('successNotification.trafficAdded', 'Traffic added')}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-lg font-bold text-emerald-400">+{data.trafficGbAdded} GB</span>
|
<span className="text-lg font-bold text-success-400">+{data.trafficGbAdded} GB</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -329,7 +329,7 @@ export default function SuccessNotificationModal() {
|
|||||||
{isBalanceTopup && (
|
{isBalanceTopup && (
|
||||||
<button
|
<button
|
||||||
onClick={handleGoToBalance}
|
onClick={handleGoToBalance}
|
||||||
className="flex w-full items-center justify-center gap-2 rounded-xl bg-gradient-to-r from-success-500 to-emerald-600 py-3.5 font-bold text-white shadow-lg shadow-success-500/25 transition-all hover:from-success-400 hover:to-emerald-500 active:from-success-600 active:to-emerald-700"
|
className="flex w-full items-center justify-center gap-2 rounded-xl bg-gradient-to-r from-success-500 to-success-600 py-3.5 font-bold text-white shadow-lg shadow-success-500/25 transition-all hover:from-success-400 hover:to-success-500 active:from-success-600 active:to-success-700"
|
||||||
>
|
>
|
||||||
<WalletIcon />
|
<WalletIcon />
|
||||||
<span>{t('successNotification.goToBalance', 'Go to Balance')}</span>
|
<span>{t('successNotification.goToBalance', 'Go to Balance')}</span>
|
||||||
@@ -349,7 +349,7 @@ export default function SuccessNotificationModal() {
|
|||||||
{isTrafficPurchased && (
|
{isTrafficPurchased && (
|
||||||
<button
|
<button
|
||||||
onClick={handleGoToSubscription}
|
onClick={handleGoToSubscription}
|
||||||
className="flex w-full items-center justify-center gap-2 rounded-xl bg-gradient-to-r from-emerald-500 to-teal-600 py-3.5 font-bold text-white shadow-lg shadow-emerald-500/25 transition-all hover:from-emerald-400 hover:to-teal-500 active:from-emerald-600 active:to-teal-700"
|
className="flex w-full items-center justify-center gap-2 rounded-xl bg-gradient-to-r from-success-500 to-success-600 py-3.5 font-bold text-white shadow-lg shadow-success-500/25 transition-all hover:from-success-400 hover:to-success-500 active:from-success-600 active:to-success-700"
|
||||||
>
|
>
|
||||||
<TrafficIcon />
|
<TrafficIcon />
|
||||||
<span>{t('successNotification.goToSubscription', 'Go to Subscription')}</span>
|
<span>{t('successNotification.goToSubscription', 'Go to Subscription')}</span>
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { useMemo } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import type { Subscription } from '../../types';
|
import type { Subscription } from '../../types';
|
||||||
import { useCurrency } from '../../hooks/useCurrency';
|
import { useCurrency } from '../../hooks/useCurrency';
|
||||||
import { useTheme } from '../../hooks/useTheme';
|
import { useTheme } from '../../hooks/useTheme';
|
||||||
import { getTrafficZone } from '../../utils/trafficZone';
|
import { useTrafficZone } from '../../hooks/useTrafficZone';
|
||||||
import { getGlassColors } from '../../utils/glassTheme';
|
import { getGlassColors } from '../../utils/glassTheme';
|
||||||
|
|
||||||
interface StatsGridProps {
|
interface StatsGridProps {
|
||||||
@@ -46,10 +45,7 @@ export default function StatsGrid({
|
|||||||
const { isDark } = useTheme();
|
const { isDark } = useTheme();
|
||||||
const g = getGlassColors(isDark);
|
const g = getGlassColors(isDark);
|
||||||
|
|
||||||
const zone = useMemo(
|
const zone = useTrafficZone(subscription?.traffic_used_percent ?? 0);
|
||||||
() => getTrafficZone(subscription?.traffic_used_percent ?? 0),
|
|
||||||
[subscription?.traffic_used_percent],
|
|
||||||
);
|
|
||||||
|
|
||||||
const cards = [
|
const cards = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { useMemo } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useNavigate } from 'react-router';
|
import { useNavigate } from 'react-router';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
@@ -7,7 +6,7 @@ import TrafficProgressBar from './TrafficProgressBar';
|
|||||||
import Sparkline from './Sparkline';
|
import Sparkline from './Sparkline';
|
||||||
import { useAnimatedNumber } from '../../hooks/useAnimatedNumber';
|
import { useAnimatedNumber } from '../../hooks/useAnimatedNumber';
|
||||||
import { useTheme } from '../../hooks/useTheme';
|
import { useTheme } from '../../hooks/useTheme';
|
||||||
import { getTrafficZone } from '../../utils/trafficZone';
|
import { useTrafficZone } from '../../hooks/useTrafficZone';
|
||||||
import { formatTraffic } from '../../utils/formatTraffic';
|
import { formatTraffic } from '../../utils/formatTraffic';
|
||||||
import { getGlassColors } from '../../utils/glassTheme';
|
import { getGlassColors } from '../../utils/glassTheme';
|
||||||
import { HoverBorderGradient } from '../ui/hover-border-gradient';
|
import { HoverBorderGradient } from '../ui/hover-border-gradient';
|
||||||
@@ -57,7 +56,7 @@ export default function SubscriptionCardActive({
|
|||||||
const usedPercent = trafficData?.traffic_used_percent ?? subscription.traffic_used_percent;
|
const usedPercent = trafficData?.traffic_used_percent ?? subscription.traffic_used_percent;
|
||||||
const usedGb = trafficData?.traffic_used_gb ?? subscription.traffic_used_gb;
|
const usedGb = trafficData?.traffic_used_gb ?? subscription.traffic_used_gb;
|
||||||
const isUnlimited = trafficData?.is_unlimited ?? subscription.traffic_limit_gb === 0;
|
const isUnlimited = trafficData?.is_unlimited ?? subscription.traffic_limit_gb === 0;
|
||||||
const zone = useMemo(() => getTrafficZone(usedPercent), [usedPercent]);
|
const zone = useTrafficZone(usedPercent);
|
||||||
const animatedPercent = useAnimatedNumber(usedPercent);
|
const animatedPercent = useAnimatedNumber(usedPercent);
|
||||||
|
|
||||||
const formattedDate = new Date(subscription.end_date).toLocaleDateString();
|
const formattedDate = new Date(subscription.end_date).toLocaleDateString();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { getTrafficZone } from '../../utils/trafficZone';
|
import { useTrafficZone } from '../../hooks/useTrafficZone';
|
||||||
import { formatTraffic } from '../../utils/formatTraffic';
|
import { formatTraffic } from '../../utils/formatTraffic';
|
||||||
import { useTheme } from '../../hooks/useTheme';
|
import { useTheme } from '../../hooks/useTheme';
|
||||||
import { getGlassColors } from '../../utils/glassTheme';
|
import { getGlassColors } from '../../utils/glassTheme';
|
||||||
@@ -25,17 +25,20 @@ export default function TrafficProgressBar({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { isDark } = useTheme();
|
const { isDark } = useTheme();
|
||||||
const g = getGlassColors(isDark);
|
const g = getGlassColors(isDark);
|
||||||
const zone = useMemo(() => getTrafficZone(percent), [percent]);
|
const zone = useTrafficZone(percent);
|
||||||
|
// Gradient always starts from the accent color (normal zone)
|
||||||
|
const startHex = zone.colors.accent || '#3b82f6';
|
||||||
const clampedPercent = Math.min(percent, 100);
|
const clampedPercent = Math.min(percent, 100);
|
||||||
const barHeight = compact ? 8 : 14;
|
const barHeight = compact ? 8 : 14;
|
||||||
|
|
||||||
// Multi-segment gradient matching prototype
|
// Multi-segment gradient matching prototype
|
||||||
const fillGradient = useMemo(() => {
|
const fillGradient = useMemo(() => {
|
||||||
if (percent < 50) return `linear-gradient(90deg, #00C987, ${zone.mainHex})`;
|
if (percent < 50) return `linear-gradient(90deg, ${startHex}, ${zone.mainHex})`;
|
||||||
if (percent < 75) return `linear-gradient(90deg, #00C987, #FFB800, ${zone.mainHex})`;
|
if (percent < 75) return `linear-gradient(90deg, ${startHex}, #FFB800, ${zone.mainHex})`;
|
||||||
if (percent < 90) return `linear-gradient(90deg, #00C987, #FFB800, #FF6B35, ${zone.mainHex})`;
|
if (percent < 90)
|
||||||
return 'linear-gradient(90deg, #00C987, #FFB800, #FF6B35, #FF3B5C)';
|
return `linear-gradient(90deg, ${startHex}, #FFB800, #FF6B35, ${zone.mainHex})`;
|
||||||
}, [percent, zone.mainHex]);
|
return `linear-gradient(90deg, ${startHex}, #FFB800, #FF6B35, #FF3B5C)`;
|
||||||
|
}, [percent, zone.mainHex, startHex]);
|
||||||
|
|
||||||
if (isUnlimited) {
|
if (isUnlimited) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
27
src/hooks/useTrafficZone.ts
Normal file
27
src/hooks/useTrafficZone.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
import { getTrafficZone, TrafficColorKey } from '../utils/trafficZone';
|
||||||
|
import { useThemeColors } from './useThemeColors';
|
||||||
|
import type { ThemeColors } from '../types/theme';
|
||||||
|
|
||||||
|
const FALLBACKS: Record<TrafficColorKey, string> = {
|
||||||
|
accent: '#3b82f6',
|
||||||
|
warning: '#FFB800',
|
||||||
|
error: '#FF3B5C',
|
||||||
|
};
|
||||||
|
|
||||||
|
const COLOR_MAP: Record<TrafficColorKey, keyof ThemeColors> = {
|
||||||
|
accent: 'accent',
|
||||||
|
warning: 'warning',
|
||||||
|
error: 'error',
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useTrafficZone(percent: number) {
|
||||||
|
const { colors } = useThemeColors();
|
||||||
|
const zone = useMemo(() => getTrafficZone(percent), [percent]);
|
||||||
|
const mainHex = useMemo(() => {
|
||||||
|
const key = zone.colorKey;
|
||||||
|
return colors[COLOR_MAP[key]] || FALLBACKS[key];
|
||||||
|
}, [zone.colorKey, colors]);
|
||||||
|
|
||||||
|
return { ...zone, mainHex, colors };
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import { useNavigate } from 'react-router';
|
|||||||
import { subscriptionApi } from '../api/subscription';
|
import { subscriptionApi } from '../api/subscription';
|
||||||
import TrafficProgressBar from '../components/dashboard/TrafficProgressBar';
|
import TrafficProgressBar from '../components/dashboard/TrafficProgressBar';
|
||||||
import { HoverBorderGradient } from '../components/ui/hover-border-gradient';
|
import { HoverBorderGradient } from '../components/ui/hover-border-gradient';
|
||||||
import { getTrafficZone } from '../utils/trafficZone';
|
import { useTrafficZone } from '../hooks/useTrafficZone';
|
||||||
import { formatTraffic } from '../utils/formatTraffic';
|
import { formatTraffic } from '../utils/formatTraffic';
|
||||||
import { getGlassColors } from '../utils/glassTheme';
|
import { getGlassColors } from '../utils/glassTheme';
|
||||||
import { useTheme } from '../hooks/useTheme';
|
import { useTheme } from '../hooks/useTheme';
|
||||||
@@ -203,6 +203,10 @@ export default function Subscription() {
|
|||||||
// Extract subscription from response (null if no subscription)
|
// Extract subscription from response (null if no subscription)
|
||||||
const subscription = subscriptionResponse?.subscription ?? null;
|
const subscription = subscriptionResponse?.subscription ?? null;
|
||||||
|
|
||||||
|
// Traffic zone (theme-aware) — called unconditionally at top level
|
||||||
|
const usedPercent = trafficData?.traffic_used_percent ?? subscription?.traffic_used_percent ?? 0;
|
||||||
|
const zone = useTrafficZone(usedPercent);
|
||||||
|
|
||||||
// Purchase options (needed for balance_kopeks in device/traffic/server management)
|
// Purchase options (needed for balance_kopeks in device/traffic/server management)
|
||||||
const { data: purchaseOptions } = useQuery({
|
const { data: purchaseOptions } = useQuery({
|
||||||
queryKey: ['purchase-options'],
|
queryKey: ['purchase-options'],
|
||||||
@@ -432,12 +436,9 @@ export default function Subscription() {
|
|||||||
{/* Current Subscription */}
|
{/* Current Subscription */}
|
||||||
{subscription ? (
|
{subscription ? (
|
||||||
(() => {
|
(() => {
|
||||||
const usedPercent =
|
|
||||||
trafficData?.traffic_used_percent ?? subscription.traffic_used_percent;
|
|
||||||
const usedGb = trafficData?.traffic_used_gb ?? subscription.traffic_used_gb;
|
const usedGb = trafficData?.traffic_used_gb ?? subscription.traffic_used_gb;
|
||||||
const isUnlimited =
|
const isUnlimited =
|
||||||
(trafficData?.is_unlimited ?? false) || subscription.traffic_limit_gb === 0;
|
(trafficData?.is_unlimited ?? false) || subscription.traffic_limit_gb === 0;
|
||||||
const zone = getTrafficZone(usedPercent);
|
|
||||||
const connectedDevices = devicesData?.total ?? 0;
|
const connectedDevices = devicesData?.total ?? 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -1089,7 +1090,8 @@ export default function Subscription() {
|
|||||||
className="absolute inset-0 rounded-full transition-[width] duration-500"
|
className="absolute inset-0 rounded-full transition-[width] duration-500"
|
||||||
style={{
|
style={{
|
||||||
width: `${progress}%`,
|
width: `${progress}%`,
|
||||||
background: 'linear-gradient(90deg, #00E5A0, #00C987)',
|
background:
|
||||||
|
'linear-gradient(90deg, rgb(var(--color-accent-500)), rgb(var(--color-accent-400)))',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -1244,14 +1246,14 @@ export default function Subscription() {
|
|||||||
{/* Discount badge */}
|
{/* Discount badge */}
|
||||||
{devicePriceData.discount_percent && devicePriceData.discount_percent > 0 && (
|
{devicePriceData.discount_percent && devicePriceData.discount_percent > 0 && (
|
||||||
<div className="mb-2">
|
<div className="mb-2">
|
||||||
<span className="inline-block rounded-full bg-green-500/20 px-2.5 py-0.5 text-sm font-medium text-green-400">
|
<span className="inline-block rounded-full bg-success-500/20 px-2.5 py-0.5 text-sm font-medium text-success-400">
|
||||||
-{devicePriceData.discount_percent}%
|
-{devicePriceData.discount_percent}%
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{/* Total price - show as free if 100% discount or 0 */}
|
{/* Total price - show as free if 100% discount or 0 */}
|
||||||
{devicePriceData.total_price_kopeks === 0 ? (
|
{devicePriceData.total_price_kopeks === 0 ? (
|
||||||
<div className="text-2xl font-bold text-green-400">
|
<div className="text-2xl font-bold text-success-400">
|
||||||
{t('subscription.switchTariff.free')}
|
{t('subscription.switchTariff.free')}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -1570,7 +1572,7 @@ export default function Subscription() {
|
|||||||
{/* Discount badge */}
|
{/* Discount badge */}
|
||||||
{pkg.discount_percent && pkg.discount_percent > 0 && (
|
{pkg.discount_percent && pkg.discount_percent > 0 && (
|
||||||
<div className="mb-1">
|
<div className="mb-1">
|
||||||
<span className="inline-block rounded-full bg-green-500/20 px-2 py-0.5 text-xs font-medium text-green-400">
|
<span className="inline-block rounded-full bg-success-500/20 px-2 py-0.5 text-xs font-medium text-success-400">
|
||||||
-{pkg.discount_percent}%
|
-{pkg.discount_percent}%
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -1971,7 +1973,10 @@ export default function Subscription() {
|
|||||||
<div className="flex items-center justify-center py-8">
|
<div className="flex items-center justify-center py-8">
|
||||||
<div
|
<div
|
||||||
className="h-8 w-8 animate-spin rounded-full border-2 border-t-transparent"
|
className="h-8 w-8 animate-spin rounded-full border-2 border-t-transparent"
|
||||||
style={{ borderColor: '#00E5A0', borderTopColor: 'transparent' }}
|
style={{
|
||||||
|
borderColor: 'rgb(var(--color-accent-500))',
|
||||||
|
borderTopColor: 'transparent',
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : devicesData && devicesData.devices.length > 0 ? (
|
) : devicesData && devicesData.devices.length > 0 ? (
|
||||||
|
|||||||
@@ -577,7 +577,7 @@ export default function SubscriptionPurchase() {
|
|||||||
{t('subscription.switchTariff.upgradeCost')}
|
{t('subscription.switchTariff.upgradeCost')}
|
||||||
</span>
|
</span>
|
||||||
{switchPreview.discount_percent && switchPreview.discount_percent > 0 && (
|
{switchPreview.discount_percent && switchPreview.discount_percent > 0 && (
|
||||||
<span className="ml-2 inline-block rounded-full bg-green-500/20 px-2 py-0.5 text-xs font-medium text-green-400">
|
<span className="ml-2 inline-block rounded-full bg-success-500/20 px-2 py-0.5 text-xs font-medium text-success-400">
|
||||||
-{switchPreview.discount_percent}%
|
-{switchPreview.discount_percent}%
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
@@ -592,7 +592,7 @@ export default function SubscriptionPurchase() {
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<span
|
<span
|
||||||
className={`text-lg font-bold ${switchPreview.upgrade_cost_kopeks === 0 ? 'text-green-400' : 'text-accent-400'}`}
|
className={`text-lg font-bold ${switchPreview.upgrade_cost_kopeks === 0 ? 'text-success-400' : 'text-accent-400'}`}
|
||||||
>
|
>
|
||||||
{switchPreview.upgrade_cost_kopeks > 0
|
{switchPreview.upgrade_cost_kopeks > 0
|
||||||
? switchPreview.upgrade_cost_label
|
? switchPreview.upgrade_cost_label
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
export type TrafficZone = 'normal' | 'warning' | 'danger' | 'critical';
|
export type TrafficZone = 'normal' | 'warning' | 'danger' | 'critical';
|
||||||
|
|
||||||
|
export type TrafficColorKey = 'accent' | 'warning' | 'error';
|
||||||
|
|
||||||
interface TrafficZoneResult {
|
interface TrafficZoneResult {
|
||||||
zone: TrafficZone;
|
zone: TrafficZone;
|
||||||
textClass: string;
|
textClass: string;
|
||||||
@@ -8,19 +10,19 @@ interface TrafficZoneResult {
|
|||||||
labelKey: string;
|
labelKey: string;
|
||||||
gradientFrom: string;
|
gradientFrom: string;
|
||||||
gradientTo: string;
|
gradientTo: string;
|
||||||
/** Hex color for inline styles */
|
/** Key into ThemeColors for resolving mainHex at runtime */
|
||||||
mainHex: string;
|
colorKey: TrafficColorKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ZONES: Record<TrafficZone, Omit<TrafficZoneResult, 'zone'>> = {
|
const ZONES: Record<TrafficZone, Omit<TrafficZoneResult, 'zone'>> = {
|
||||||
normal: {
|
normal: {
|
||||||
textClass: 'text-success-400',
|
textClass: 'text-accent-400',
|
||||||
dotClass: 'bg-success-400',
|
dotClass: 'bg-accent-400',
|
||||||
glowColor: 'rgba(var(--color-success-500), 0.5)',
|
glowColor: 'rgba(var(--color-accent-500), 0.5)',
|
||||||
labelKey: 'dashboard.zone.normal',
|
labelKey: 'dashboard.zone.normal',
|
||||||
gradientFrom: 'rgb(var(--color-success-500))',
|
gradientFrom: 'rgb(var(--color-accent-500))',
|
||||||
gradientTo: 'rgb(var(--color-success-400))',
|
gradientTo: 'rgb(var(--color-accent-400))',
|
||||||
mainHex: '#00E5A0',
|
colorKey: 'accent',
|
||||||
},
|
},
|
||||||
warning: {
|
warning: {
|
||||||
textClass: 'text-warning-400',
|
textClass: 'text-warning-400',
|
||||||
@@ -29,7 +31,7 @@ const ZONES: Record<TrafficZone, Omit<TrafficZoneResult, 'zone'>> = {
|
|||||||
labelKey: 'dashboard.zone.warning',
|
labelKey: 'dashboard.zone.warning',
|
||||||
gradientFrom: 'rgb(var(--color-warning-500))',
|
gradientFrom: 'rgb(var(--color-warning-500))',
|
||||||
gradientTo: 'rgb(var(--color-warning-400))',
|
gradientTo: 'rgb(var(--color-warning-400))',
|
||||||
mainHex: '#FFB800',
|
colorKey: 'warning',
|
||||||
},
|
},
|
||||||
danger: {
|
danger: {
|
||||||
textClass: 'text-warning-300',
|
textClass: 'text-warning-300',
|
||||||
@@ -38,7 +40,7 @@ const ZONES: Record<TrafficZone, Omit<TrafficZoneResult, 'zone'>> = {
|
|||||||
labelKey: 'dashboard.zone.danger',
|
labelKey: 'dashboard.zone.danger',
|
||||||
gradientFrom: 'rgb(var(--color-warning-600))',
|
gradientFrom: 'rgb(var(--color-warning-600))',
|
||||||
gradientTo: 'rgb(var(--color-warning-400))',
|
gradientTo: 'rgb(var(--color-warning-400))',
|
||||||
mainHex: '#FF6B35',
|
colorKey: 'warning',
|
||||||
},
|
},
|
||||||
critical: {
|
critical: {
|
||||||
textClass: 'text-error-400',
|
textClass: 'text-error-400',
|
||||||
@@ -47,7 +49,7 @@ const ZONES: Record<TrafficZone, Omit<TrafficZoneResult, 'zone'>> = {
|
|||||||
labelKey: 'dashboard.zone.critical',
|
labelKey: 'dashboard.zone.critical',
|
||||||
gradientFrom: 'rgb(var(--color-error-500))',
|
gradientFrom: 'rgb(var(--color-error-500))',
|
||||||
gradientTo: 'rgb(var(--color-error-400))',
|
gradientTo: 'rgb(var(--color-error-400))',
|
||||||
mainHex: '#FF3B5C',
|
colorKey: 'error',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user