polish: fix page title, multi-select styling, chart colors
All checks were successful
Deploy HiHala Dashboard / deploy (push) Successful in 6s

- Page title: "HiHala Data - Museums" -> "HiHala Data"
- Meta description: updated to "Event analytics"
- Multi-select dropdown: fix inherited uppercase, wider to fit labels
- Multi-select arrow: smooth CSS rotation instead of swapping characters
- Chart colors: 10-color palette for events/channels (was 3)
- Remove unused ArcElement (Doughnut) from Chart.js registration (-5KB)
- District chart uses dynamic palette instead of hardcoded 2 colors

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
fahed
2026-03-31 15:16:20 +03:00
parent 9332cae350
commit 3912b3dd41
5 changed files with 41 additions and 16 deletions

View File

@@ -5,11 +5,11 @@
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#f8fafc" /> <meta name="theme-color" content="#f8fafc" />
<meta name="description" content="HiHala Data Dashboard — Museum analytics, visitor tracking, and revenue insights" /> <meta name="description" content="HiHala Data Dashboard — Event analytics, visitor tracking, and revenue insights" />
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600&family=IBM+Plex+Sans+Arabic:wght@400;500;600;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600&family=IBM+Plex+Sans+Arabic:wght@400;500;600;700&display=swap" rel="stylesheet">
<title>HiHala Data Museums</title> <title>HiHala Data</title>
</head> </head>
<body> <body>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>

View File

@@ -796,16 +796,22 @@ table tbody tr:hover {
} }
.multi-select-arrow { .multi-select-arrow {
font-size: 0.65rem; font-size: 0.6rem;
opacity: 0.5; opacity: 0.4;
margin-inline-start: 8px; margin-inline-start: 8px;
transition: transform 150ms ease;
}
.multi-select-trigger[aria-expanded="true"] .multi-select-arrow {
transform: rotate(180deg);
} }
.multi-select-dropdown { .multi-select-dropdown {
position: absolute; position: absolute;
top: calc(100% + 4px); top: calc(100% + 4px);
left: 0; left: 0;
right: 0; min-width: 100%;
width: max-content;
background: var(--surface); background: var(--surface);
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: 8px; border-radius: 8px;
@@ -816,6 +822,12 @@ table tbody tr:hover {
padding: 4px; padding: 4px;
} }
.multi-select-dropdown,
.multi-select-dropdown * {
text-transform: none;
letter-spacing: normal;
}
.multi-select-option { .multi-select-option {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -825,8 +837,6 @@ table tbody tr:hover {
cursor: pointer; cursor: pointer;
font-size: 0.875rem; font-size: 0.875rem;
color: var(--text-primary); color: var(--text-primary);
text-transform: none;
letter-spacing: normal;
font-weight: normal; font-weight: normal;
} }

View File

@@ -3,7 +3,7 @@ import { useSearchParams } from 'react-router-dom';
import { Line, Bar } from 'react-chartjs-2'; import { Line, Bar } from 'react-chartjs-2';
import { Carousel, EmptyState, FilterControls, MultiSelect, StatCard } from './shared'; import { Carousel, EmptyState, FilterControls, MultiSelect, StatCard } from './shared';
import { ExportableChart } from './ChartExport'; import { ExportableChart } from './ChartExport';
import { chartColors, createBaseOptions } from '../config/chartConfig'; import { chartColors, chartPalette, createBaseOptions } from '../config/chartConfig';
import { useLanguage } from '../contexts/LanguageContext'; import { useLanguage } from '../contexts/LanguageContext';
import { import {
filterData, filterData,
@@ -206,15 +206,16 @@ function Dashboard({ data, showDataLabels, setShowDataLabels, includeVAT, setInc
labels: museums, labels: museums,
datasets: [{ datasets: [{
data: museums.map(m => grouped[m].visitors), data: museums.map(m => grouped[m].visitors),
backgroundColor: [chartColors.primary + 'cc', chartColors.secondary + 'cc', chartColors.tertiary + 'cc'], backgroundColor: museums.map((_, i) => chartPalette[i % chartPalette.length] + 'cc'),
borderWidth: 0 borderWidth: 0,
borderRadius: 4
}] }]
}, },
revenue: { revenue: {
labels: museums, labels: museums,
datasets: [{ datasets: [{
data: museums.map(m => grouped[m].revenue), data: museums.map(m => grouped[m].revenue),
backgroundColor: [chartColors.primary + 'cc', chartColors.secondary + 'cc', chartColors.tertiary + 'cc'], backgroundColor: museums.map((_, i) => chartPalette[i % chartPalette.length] + 'cc'),
borderRadius: 4 borderRadius: 4
}] }]
} }
@@ -229,7 +230,7 @@ function Dashboard({ data, showDataLabels, setShowDataLabels, includeVAT, setInc
labels: channels, labels: channels,
datasets: [{ datasets: [{
data: channels.map(d => grouped[d].revenue), data: channels.map(d => grouped[d].revenue),
backgroundColor: [chartColors.secondary + 'cc', chartColors.tertiary + 'cc'], backgroundColor: channels.map((_, i) => chartPalette[i % chartPalette.length] + 'cc'),
borderRadius: 4 borderRadius: 4
}] }]
}; };
@@ -243,7 +244,7 @@ function Dashboard({ data, showDataLabels, setShowDataLabels, includeVAT, setInc
labels: districtNames, labels: districtNames,
datasets: [{ datasets: [{
data: districtNames.map(d => grouped[d].revenue), data: districtNames.map(d => grouped[d].revenue),
backgroundColor: [chartColors.primary + 'cc', chartColors.secondary + 'cc', chartColors.tertiary + 'cc', chartColors.muted + 'cc'], backgroundColor: districtNames.map((_, i) => chartPalette[i % chartPalette.length] + 'cc'),
borderRadius: 4 borderRadius: 4
}] }]
}; };

View File

@@ -50,7 +50,7 @@ function MultiSelect({ options, selected, onChange, allLabel, placeholder }: Mul
aria-expanded={open} aria-expanded={open}
> >
<span className="multi-select-text">{displayText}</span> <span className="multi-select-text">{displayText}</span>
<span className="multi-select-arrow">{open ? '▲' : '▼'}</span> <span className="multi-select-arrow"></span>
</button> </button>
{open && ( {open && (

View File

@@ -5,7 +5,7 @@ import {
PointElement, PointElement,
LineElement, LineElement,
BarElement, BarElement,
ArcElement,
Title, Title,
Tooltip, Tooltip,
Legend, Legend,
@@ -20,7 +20,7 @@ ChartJS.register(
PointElement, PointElement,
LineElement, LineElement,
BarElement, BarElement,
ArcElement,
Title, Title,
Tooltip, Tooltip,
Legend, Legend,
@@ -38,6 +38,20 @@ export const chartColors = {
grid: '#f1f5f9' grid: '#f1f5f9'
}; };
// Extended palette for charts with many categories (events, channels)
export const chartPalette = [
'#2563eb', // blue
'#7c3aed', // purple
'#0891b2', // cyan
'#059669', // emerald
'#d97706', // amber
'#e11d48', // rose
'#4f46e5', // indigo
'#0d9488', // teal
'#c026d3', // fuchsia
'#ea580c', // orange
];
export const createDataLabelConfig = (showDataLabels: boolean): any => ({ export const createDataLabelConfig = (showDataLabels: boolean): any => ({
display: showDataLabels, display: showDataLabels,
color: '#1e293b', color: '#1e293b',