Nav: a small "Grand livre" / "Dashboard" switcher, top-right on both
pages, with the current page highlighted. Needed hook_theme() to
declare current_route as an accepted variable for both theme hooks --
same class of bug as the earlier can_view_history fix: an undeclared
variable passed via the render array is silently dropped rather than
reaching Twig.
Dashboard: replaced the old "solde par compte / par client" tables
(computed client-side from a full unwindowed JSON:API fetch of every
node -- the same performance problem the /lignes sliding window was
built to avoid, just not yet felt at 1500+ lines) with a single
aggregate endpoint (DashboardStatsController, plain SQL GROUP BY) and
five chart panels: CA par année, solde par compte (diverging,
red/green), solde par compte trend (small multiples per compte),
répartition par type, top clients par CA. No charting library --
small dependency-free div/CSS bar charts (HBarChart/ColumnChart/
MiniTrend components in dashboard.js), consistent with this project
vendoring its own JS.
Two data-correctness fixes along the way: (1) the historical stray
mistyped dates (0213-06-15, 2015-08-29 -- preserved as-is per this
module's policy) needed excluding from per-year buckets without
excluding their money from all-time totals, so the filtering happens
per-output-field in PHP rather than as a blanket SQL date range. (2)
PHP silently casts numeric-looking array keys ("2021") to actual
integers, so array_keys() on a year-keyed map produces a mix of ints
and strings -- json_encode emits the int ones as bare JSON numbers in
a list (unlike object keys, which JSON always stringifies), which
broke the frontend's annees[i].slice(2) trend-card labels. Fixed with
an explicit array_map('strval', ...).
Verified: bar widths/colors match the underlying data exactly (e.g.
EXT.'s red bar is proportionally sized against Maud's green one per
their actual solde ratio), all 8 trend cards render correct year
labels, and both nav links correctly highlight on their own page.
121 lines
4.0 KiB
CSS
121 lines
4.0 KiB
CSS
/* Core Navigation's top bar (`.top-bar`) only shows itself when its
|
|
tools/context/actions regions are non-empty -- but with no blocks placed
|
|
there, the regions still contain whitespace text nodes from the Twig
|
|
loop scaffolding, which defeats the `:not(:empty)` check. Result: an
|
|
empty top bar renders anyway, with the page content pushed down to make
|
|
room for it. We only use the Gin sidebar (the left icon rail), so force
|
|
the phantom bar off and collapse the space it would otherwise reserve. */
|
|
.top-bar {
|
|
display: none !important;
|
|
}
|
|
|
|
.top-bar ~ .dialog-off-canvas-main-canvas {
|
|
margin-block-start: 0 !important;
|
|
}
|
|
|
|
/* Grand livre / Dashboard switcher, top-right of both pages. Only present
|
|
on those two custom routes, but attached here (already loaded on every
|
|
page for the phantom-top-bar fix above) rather than duplicated between
|
|
home.css and dashboard.css -- and defined with its own explicit colors
|
|
rather than relying on either page's #figli-*-app-scoped custom
|
|
properties, since this <nav> sits outside both of those elements. */
|
|
.figli-page-nav {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 0.4rem;
|
|
padding: 0.5rem 0.25rem 0;
|
|
}
|
|
.figli-page-nav a {
|
|
padding: 0.3rem 0.8rem;
|
|
border-radius: 6px;
|
|
font-size: 0.82rem;
|
|
font-weight: 600;
|
|
text-decoration: none;
|
|
color: #6b7280;
|
|
border: 1px solid transparent;
|
|
}
|
|
.figli-page-nav a:hover {
|
|
border-color: #dcdee2;
|
|
}
|
|
.figli-page-nav a.is-active {
|
|
background: #eef1f6;
|
|
color: #1a1a1a;
|
|
}
|
|
html.gin--dark-mode .figli-page-nav a {
|
|
color: #a1a5ab;
|
|
}
|
|
html.gin--dark-mode .figli-page-nav a:hover {
|
|
border-color: #3d3e42;
|
|
}
|
|
html.gin--dark-mode .figli-page-nav a.is-active {
|
|
background: #2c2d30;
|
|
color: #e8e9ea;
|
|
}
|
|
|
|
/* Drupal status messages: fixed top-right, out of document flow, so they
|
|
never shift the page layout the way the default in-flow placement does
|
|
-- and shrunk to a fraction of Gin's default size, which is sized for a
|
|
single full-width flash banner on an admin form, not a toast for
|
|
frequent background feedback here. Targets both the real region
|
|
([data-drupal-messages], present once a message is queued on a normal
|
|
page load) and the JS-only fallback container
|
|
([data-drupal-messages-fallback], used when Drupal.Message.add() -- our
|
|
own MessageCommand-driven AJAX messages included -- has no region to
|
|
attach to). Auto-dismiss timing for non-error messages is handled in
|
|
admin-chrome.js. */
|
|
[data-drupal-messages],
|
|
[data-drupal-messages-fallback] {
|
|
position: fixed !important;
|
|
top: 0.75rem;
|
|
right: 0.75rem;
|
|
left: auto !important;
|
|
width: auto;
|
|
max-width: 22rem;
|
|
z-index: 1000;
|
|
}
|
|
[data-drupal-messages] .messages-list__wrapper,
|
|
[data-drupal-messages] .messages__wrapper,
|
|
[data-drupal-messages-fallback] .messages-list__wrapper,
|
|
[data-drupal-messages-fallback] .messages__wrapper {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.4rem;
|
|
}
|
|
[data-drupal-messages] .messages,
|
|
[data-drupal-messages-fallback] .messages {
|
|
padding: 0.5rem 0.6rem;
|
|
font-size: 0.78rem;
|
|
line-height: 1.3;
|
|
border-radius: 6px;
|
|
}
|
|
[data-drupal-messages] .messages__header,
|
|
[data-drupal-messages-fallback] .messages__header {
|
|
margin-block-end: 0.15rem;
|
|
margin-inline-end: 1.1em;
|
|
}
|
|
[data-drupal-messages] .messages__header::before,
|
|
[data-drupal-messages-fallback] .messages__header::before {
|
|
width: 1rem !important;
|
|
height: 1rem !important;
|
|
}
|
|
[data-drupal-messages] .messages__title,
|
|
[data-drupal-messages-fallback] .messages__title {
|
|
font-size: 0.78rem;
|
|
}
|
|
[data-drupal-messages] .messages__title,
|
|
[data-drupal-messages] .messages__content,
|
|
[data-drupal-messages-fallback] .messages__title,
|
|
[data-drupal-messages-fallback] .messages__content {
|
|
margin-inline-start: 1.4rem;
|
|
}
|
|
[data-drupal-messages] .button--dismiss,
|
|
[data-drupal-messages-fallback] .button--dismiss {
|
|
height: 20px !important;
|
|
width: 20px !important;
|
|
margin: 0.3rem !important;
|
|
}
|
|
[data-drupal-messages] .button--dismiss .icon-close,
|
|
[data-drupal-messages-fallback] .button--dismiss .icon-close {
|
|
mask-size: 11px 11px !important;
|
|
}
|