+
{displayLabel}
-
{displayValueLabel} {value}
+
{displayValueLabel} {value}
);
}
@@ -256,19 +263,19 @@ const Dashboard = () => {
{revenueBySellerChartData.length ? (
-
- `${Number(value) / 1000}k`} />
+
+ `${Number(value) / 1000}k`} />
truncateLabel(String(value))}
/>
- } cursor={{ fill: '#222222' }} />
+ } cursor={{ fill: CHART_CURSOR_COLOR }} />
{revenueBySellerChartData.map((entry) => (
{
style={getBarGlowStyle(entry.fill)}
/>
))}
- formatCurrency(Number(value) || 0)} />
+ formatCurrency(Number(value) || 0)} />
|
@@ -297,19 +304,19 @@ const Dashboard = () => {
{ticketBySellerChartData.length ? (
-
- `${Number(value) / 1000}k`} />
+
+ `${Number(value) / 1000}k`} />
truncateLabel(String(value))}
/>
- } cursor={{ fill: '#222222' }} />
+ } cursor={{ fill: CHART_CURSOR_COLOR }} />
{ticketBySellerChartData.map((entry) => (
{
style={getBarGlowStyle(entry.fill)}
/>
))}
- formatCurrency(Number(value) || 0)} />
+ formatCurrency(Number(value) || 0)} />
|
@@ -372,13 +379,13 @@ const Dashboard = () => {
-
+
-
- } cursor={{ fill: '#222222' }} />
+
+ } cursor={{ fill: CHART_CURSOR_COLOR }} />
{ if(data?.payload?.id) navigate(`/products/${data.payload.id}`) }} style={{ cursor: 'pointer' }}>
{salesByProduct.map((entry) => (
| {
/>
))}
- } cursor={{ fill: '#222222' }} />
+ } cursor={{ fill: CHART_CURSOR_COLOR }} />
|
diff --git a/src/pages/ProductDetails.tsx b/src/pages/ProductDetails.tsx
index 1302cf4..e9d91a4 100644
--- a/src/pages/ProductDetails.tsx
+++ b/src/pages/ProductDetails.tsx
@@ -6,6 +6,11 @@ import DateRangePicker from '../components/DateRangePicker';
import type { DateRange, ProductDetailsAnalytics } from '../types';
import { fetchProductDetailsAnalytics } from '../dataService';
+const CHART_GRID_COLOR = 'var(--chart-grid)';
+const CHART_AXIS_COLOR = 'var(--chart-axis)';
+const CHART_CURSOR_COLOR = 'var(--chart-cursor)';
+const CHART_DETAIL_BAR_COLOR = 'var(--chart-detail-bar)';
+
type CustomTooltipProps = {
active?: boolean;
payload?: Array<{ value: number }>;
@@ -15,9 +20,12 @@ type CustomTooltipProps = {
const CustomTooltip = ({ active, payload, label }: CustomTooltipProps) => {
if (active && payload && payload.length) {
return (
-
-
{label}
-
Vendas: {payload[0].value}
+
+
{label}
+
Vendas: {payload[0].value}
);
}
@@ -135,17 +143,17 @@ const ProductDetails = () => {
-
+
-
- } cursor={{ fill: '#222222' }} />
-
+
+ } cursor={{ fill: CHART_CURSOR_COLOR }} />
+
diff --git a/src/pages/Rfm.tsx b/src/pages/Rfm.tsx
index 9854a71..86793bb 100644
--- a/src/pages/Rfm.tsx
+++ b/src/pages/Rfm.tsx
@@ -15,7 +15,9 @@ type SegmentStyle = {
text: string;
};
-const segmentStyles: Record
= {
+type ThemeMode = 'dark' | 'offwhite';
+
+const darkSegmentStyles: Record = {
champions: { accent: '#18D6B5', bg: 'rgba(24, 214, 181, 0.10)', border: 'rgba(24, 214, 181, 0.34)', text: '#18D6B5' },
potential_loyalists: { accent: '#A3E635', bg: 'rgba(163, 230, 53, 0.10)', border: 'rgba(163, 230, 53, 0.34)', text: '#A3E635' },
new_customers: { accent: '#25C2FF', bg: 'rgba(37, 194, 255, 0.10)', border: 'rgba(37, 194, 255, 0.34)', text: '#25C2FF' },
@@ -27,6 +29,18 @@ const segmentStyles: Record = {
lost: { accent: '#8c9298', bg: 'rgba(140, 146, 152, 0.08)', border: 'rgba(140, 146, 152, 0.24)', text: '#b3b7bb' }
};
+const offwhiteSegmentStyles: Record = {
+ champions: { accent: '#138B75', bg: 'rgba(19, 139, 117, 0.10)', border: 'rgba(19, 139, 117, 0.34)', text: '#138B75' },
+ potential_loyalists: { accent: '#5F8F12', bg: 'rgba(95, 143, 18, 0.11)', border: 'rgba(95, 143, 18, 0.34)', text: '#5F8F12' },
+ new_customers: { accent: '#0B7EA8', bg: 'rgba(11, 126, 168, 0.10)', border: 'rgba(11, 126, 168, 0.34)', text: '#0B7EA8' },
+ loyal_customers: { accent: '#356DCC', bg: 'rgba(53, 109, 204, 0.10)', border: 'rgba(53, 109, 204, 0.34)', text: '#356DCC' },
+ need_attention: { accent: '#A36C00', bg: 'rgba(163, 108, 0, 0.11)', border: 'rgba(163, 108, 0, 0.34)', text: '#A36C00' },
+ about_to_sleep: { accent: '#B75B12', bg: 'rgba(183, 91, 18, 0.11)', border: 'rgba(183, 91, 18, 0.34)', text: '#B75B12' },
+ at_risk: { accent: '#C73656', bg: 'rgba(199, 54, 86, 0.10)', border: 'rgba(199, 54, 86, 0.34)', text: '#C73656' },
+ hibernating: { accent: '#8C52D6', bg: 'rgba(140, 82, 214, 0.10)', border: 'rgba(140, 82, 214, 0.34)', text: '#8C52D6' },
+ lost: { accent: '#757C82', bg: 'rgba(117, 124, 130, 0.08)', border: 'rgba(117, 124, 130, 0.26)', text: '#757C82' }
+};
+
const rfmSegmentDefinitions: Array> = [
{ key: 'champions', label: 'Champions' },
{ key: 'potential_loyalists', label: 'Potenciais Leais' },
@@ -144,12 +158,14 @@ const ScoreBadge = ({ value }: { value: number }) => (
);
const Rfm = () => {
- const { dateRange, setDateRange, refreshInterval, setRefreshInterval } = useOutletContext<{
+ const { dateRange, setDateRange, refreshInterval, setRefreshInterval, themeMode } = useOutletContext<{
dateRange: DateRange;
setDateRange: (range: DateRange) => void;
refreshInterval: number;
setRefreshInterval: (interval: number) => void;
+ themeMode?: ThemeMode;
}>();
+ const segmentStyles = themeMode === 'offwhite' ? offwhiteSegmentStyles : darkSegmentStyles;
const initialCachedAnalytics = getCachedRfmAnalytics(dateRange);
const [analytics, setAnalytics] = useState(initialCachedAnalytics || null);