Implement gradient themes in CSS, enhance print functionality, and update card styles in templates. Add a PDF save button and improve layout for better accessibility and user experience.
This commit is contained in:
@@ -1,102 +1,169 @@
|
|||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
@plugin "daisyui";
|
@plugin "daisyui";
|
||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
--font-sans: "DM Sans", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
--font-sans: "DM Sans", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||||
}
|
}
|
||||||
|
|
||||||
@plugin "daisyui/theme" {
|
@plugin "daisyui/theme" {
|
||||||
name: "light";
|
name: "light";
|
||||||
default: true;
|
default: true;
|
||||||
prefersdark: false;
|
prefersdark: false;
|
||||||
color-scheme: "light";
|
color-scheme: "light";
|
||||||
--color-base-100: oklch(100% 0 0);
|
--color-base-100: oklch(100% 0.004 260);
|
||||||
--color-base-200: oklch(98% 0 0);
|
--color-base-200: oklch(98% 0.004 260);
|
||||||
--color-base-300: oklch(95% 0 0);
|
--color-base-300: oklch(95% 0.004 260);
|
||||||
--color-base-content: oklch(21% 0.006 285.885);
|
--color-base-content: oklch(22% 0.02 260);
|
||||||
--color-primary: #0A2896;
|
--color-primary: #0a2973;
|
||||||
--color-primary-content: oklch(93% 0.034 272.788);
|
--color-primary-content: #ffffff;
|
||||||
--color-secondary: #428BCA;
|
--color-secondary: #009fdf;
|
||||||
--color-secondary-content: oklch(100% 0 0);
|
--color-secondary-content: #ffffff;
|
||||||
--color-accent: #A492FF;
|
--color-accent: #009fdf;
|
||||||
--color-accent-content: oklch(21% 0.006 285.885);
|
--color-accent-content: #ffffff;
|
||||||
--color-neutral: #333333;
|
--color-neutral: #333333;
|
||||||
--color-neutral-content: oklch(92% 0.004 286.32);
|
--color-neutral-content: oklch(92% 0.004 286.32);
|
||||||
--color-info: oklch(74% 0.16 232.661);
|
--color-info: oklch(74% 0.16 232.661);
|
||||||
--color-info-content: oklch(29% 0.066 243.157);
|
--color-info-content: oklch(29% 0.066 243.157);
|
||||||
--color-success: oklch(76% 0.177 163.223);
|
--color-success: oklch(76% 0.177 163.223);
|
||||||
--color-success-content: oklch(37% 0.077 168.94);
|
--color-success-content: oklch(37% 0.077 168.94);
|
||||||
--color-warning: oklch(82% 0.189 84.429);
|
--color-warning: oklch(82% 0.189 84.429);
|
||||||
--color-warning-content: oklch(41% 0.112 45.904);
|
--color-warning-content: oklch(41% 0.112 45.904);
|
||||||
--color-error: oklch(71% 0.194 13.428);
|
--color-error: oklch(71% 0.194 13.428);
|
||||||
--color-error-content: oklch(27% 0.105 12.094);
|
--color-error-content: oklch(27% 0.105 12.094);
|
||||||
--radius-selector: 0.5rem;
|
--radius-selector: 0.5rem;
|
||||||
--radius-field: 0.25rem;
|
--radius-field: 0.25rem;
|
||||||
--radius-box: 0.5rem;
|
--radius-box: 0.5rem;
|
||||||
--size-selector: 0.25rem;
|
--size-selector: 0.25rem;
|
||||||
--size-field: 0.25rem;
|
--size-field: 0.25rem;
|
||||||
--border: 1px;
|
--border: 1px;
|
||||||
--depth: 1;
|
--depth: 1;
|
||||||
--noise: 0;
|
--noise: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@plugin "daisyui/theme" {
|
@plugin "daisyui/theme" {
|
||||||
name: "dark";
|
name: "dark";
|
||||||
default: false;
|
default: false;
|
||||||
prefersdark: true;
|
prefersdark: true;
|
||||||
color-scheme: "dark";
|
color-scheme: "dark";
|
||||||
--color-base-100: oklch(22% 0.014 260);
|
--color-base-100: oklch(22% 0.014 260);
|
||||||
--color-base-200: oklch(19% 0.012 260);
|
--color-base-200: oklch(19% 0.012 260);
|
||||||
--color-base-300: oklch(16% 0.01 260);
|
--color-base-300: oklch(16% 0.01 260);
|
||||||
--color-base-content: oklch(95% 0.01 260);
|
--color-base-content: oklch(96% 0.01 260);
|
||||||
--color-primary: oklch(58% 0.2 270);
|
--color-primary: #0a2973;
|
||||||
--color-primary-content: oklch(96% 0.02 272);
|
--color-primary-content: #ffffff;
|
||||||
--color-secondary: oklch(62% 0.15 250);
|
--color-secondary: #009fdf;
|
||||||
--color-secondary-content: oklch(96% 0.02 250);
|
--color-secondary-content: #ffffff;
|
||||||
--color-accent: oklch(72% 0.18 280);
|
--color-accent: #009fdf;
|
||||||
--color-accent-content: oklch(20% 0.02 280);
|
--color-accent-content: #ffffff;
|
||||||
--color-neutral: oklch(28% 0.02 260);
|
--color-neutral: oklch(28% 0.02 260);
|
||||||
--color-neutral-content: oklch(92% 0.004 286.32);
|
--color-neutral-content: oklch(92% 0.004 286.32);
|
||||||
--color-info: oklch(74% 0.16 232.661);
|
--color-info: oklch(74% 0.16 232.661);
|
||||||
--color-info-content: oklch(29% 0.066 243.157);
|
--color-info-content: oklch(29% 0.066 243.157);
|
||||||
--color-success: oklch(76% 0.177 163.223);
|
--color-success: oklch(76% 0.177 163.223);
|
||||||
--color-success-content: oklch(37% 0.077 168.94);
|
--color-success-content: oklch(37% 0.077 168.94);
|
||||||
--color-warning: oklch(82% 0.189 84.429);
|
--color-warning: oklch(82% 0.189 84.429);
|
||||||
--color-warning-content: oklch(41% 0.112 45.904);
|
--color-warning-content: oklch(41% 0.112 45.904);
|
||||||
--color-error: oklch(71% 0.194 13.428);
|
--color-error: oklch(71% 0.194 13.428);
|
||||||
--color-error-content: oklch(27% 0.105 12.094);
|
--color-error-content: oklch(27% 0.105 12.094);
|
||||||
--radius-selector: 0.5rem;
|
--radius-selector: 0.5rem;
|
||||||
--radius-field: 0.25rem;
|
--radius-field: 0.25rem;
|
||||||
--radius-box: 0.5rem;
|
--radius-box: 0.5rem;
|
||||||
--size-selector: 0.25rem;
|
--size-selector: 0.25rem;
|
||||||
--size-field: 0.25rem;
|
--size-field: 0.25rem;
|
||||||
--border: 1px;
|
--border: 1px;
|
||||||
--depth: 1;
|
--depth: 1;
|
||||||
--noise: 0;
|
--noise: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Main content area: distinct background so cards (base-100) stand out */
|
/* VTB gradient (both themes) */
|
||||||
[data-theme=light] main {
|
:root {
|
||||||
background-color: var(--color-base-200);
|
--gradient-vtb: linear-gradient(135deg, #0a2973 0%, #009fdf 100%);
|
||||||
}
|
}
|
||||||
[data-theme=dark] main {
|
|
||||||
background-color: var(--color-base-200);
|
/* Gradient top border for cards */
|
||||||
}
|
.border-t-gradient-vtb {
|
||||||
|
position: relative;
|
||||||
/* Accessibility: ensure focus ring is visible on key controls */
|
}
|
||||||
.btn:focus-visible,
|
.border-t-gradient-vtb::before {
|
||||||
.select:focus-within,
|
content: "";
|
||||||
label.swap:focus-within {
|
position: absolute;
|
||||||
outline: 2px solid var(--color-primary);
|
top: 0;
|
||||||
outline-offset: 2px;
|
left: 0;
|
||||||
}
|
right: 0;
|
||||||
|
height: 4px;
|
||||||
/* Light theme: slightly stronger card shadow for depth */
|
background: var(--gradient-vtb);
|
||||||
[data-theme=light] .card.shadow-sm {
|
border-radius: var(--radius-box) var(--radius-box) 0 0;
|
||||||
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.08), 0 1px 2px -1px rgb(0 0 0 / 0.06);
|
}
|
||||||
}
|
|
||||||
[data-theme=light] .card.shadow-sm:hover {
|
/* Gradient button (e.g. Load Analysis) */
|
||||||
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.08), 0 2px 4px -2px rgb(0 0 0 / 0.06);
|
.btn-gradient-vtb {
|
||||||
}
|
background: var(--gradient-vtb);
|
||||||
|
color: #ffffff;
|
||||||
@source "../../templates";
|
border: none;
|
||||||
|
}
|
||||||
|
.btn-gradient-vtb:hover {
|
||||||
|
opacity: 0.9;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main content area: distinct background so cards (base-100) stand out */
|
||||||
|
[data-theme=light] main {
|
||||||
|
background-color: var(--color-base-200);
|
||||||
|
}
|
||||||
|
[data-theme=dark] main {
|
||||||
|
background-color: var(--color-base-200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Accessibility: ensure focus ring is visible on key controls */
|
||||||
|
.btn:focus-visible,
|
||||||
|
.select:focus-within,
|
||||||
|
label.swap:focus-within:not(.theme-toggle) {
|
||||||
|
outline: 2px solid var(--color-primary);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light theme: slightly stronger card shadow for depth */
|
||||||
|
[data-theme=light] .card.shadow-sm {
|
||||||
|
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.08), 0 1px 2px -1px rgb(0 0 0 / 0.06);
|
||||||
|
}
|
||||||
|
[data-theme=light] .card.shadow-sm:hover {
|
||||||
|
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.08), 0 2px 4px -2px rgb(0 0 0 / 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
@source "../../templates";
|
||||||
|
|
||||||
|
/* --- Print (Save as PDF) --- */
|
||||||
|
@media print {
|
||||||
|
.no-print {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
.print-only {
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
/* Keep card backgrounds and colors when printing */
|
||||||
|
.card,
|
||||||
|
main,
|
||||||
|
.badge,
|
||||||
|
.progress {
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
}
|
||||||
|
/* Avoid breaking cards and sections across pages */
|
||||||
|
.card {
|
||||||
|
break-inside: avoid;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
section {
|
||||||
|
break-inside: avoid;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
/* Reduce top padding so content starts higher */
|
||||||
|
main {
|
||||||
|
padding-top: 0.5rem !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media screen {
|
||||||
|
.print-only {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,9 +21,15 @@
|
|||||||
<a class="btn btn-ghost text-xl" href="{% url 'index' %}">SWatcher</a>
|
<a class="btn btn-ghost text-xl" href="{% url 'index' %}">SWatcher</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="navbar-end">
|
<div class="navbar-end">
|
||||||
<div class="px-1 flex gap-3 pr-10">
|
<div class="px-1 flex items-center gap-3 pr-10">
|
||||||
|
<button type="button" class="btn btn-ghost btn-sm no-print" onclick="window.print()" title="Save as PDF" aria-label="Save as PDF">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
|
||||||
|
</svg>
|
||||||
|
Save as PDF
|
||||||
|
</button>
|
||||||
<span id="regionBadge" class="badge badge-primary badge-lg">{{ region.name }}</span>
|
<span id="regionBadge" class="badge badge-primary badge-lg">{{ region.name }}</span>
|
||||||
<label class="swap swap-rotate">
|
<label class="swap swap-rotate theme-toggle no-print">
|
||||||
<input type="checkbox" class="theme-controller" value="dark" />
|
<input type="checkbox" class="theme-controller" value="dark" />
|
||||||
<svg class="swap-off fill-current w-6 h-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
<svg class="swap-off fill-current w-6 h-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<path d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z"/>
|
<path d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z"/>
|
||||||
@@ -38,6 +44,7 @@
|
|||||||
|
|
||||||
<!-- Main Content -->
|
<!-- Main Content -->
|
||||||
<main class="container mx-auto px-4 py-8 min-h-screen">
|
<main class="container mx-auto px-4 py-8 min-h-screen">
|
||||||
|
<p class="print-only text-lg font-semibold mb-4">Dashboard report</p>
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -176,7 +176,7 @@
|
|||||||
<!-- DETAILED OVERVIEW -->
|
<!-- DETAILED OVERVIEW -->
|
||||||
<section class="grid grid-cols-1 lg:grid-cols-2 gap-4" aria-label="Resource allocation and flavors">
|
<section class="grid grid-cols-1 lg:grid-cols-2 gap-4" aria-label="Resource allocation and flavors">
|
||||||
<!-- Resource Allocation -->
|
<!-- Resource Allocation -->
|
||||||
<div class="card bg-base-100 shadow-sm border-t-2 border-primary" id="statsAllocationCard">
|
<div class="card bg-base-100 shadow-sm border-t-gradient-vtb" id="statsAllocationCard">
|
||||||
<div class="card-body p-5">
|
<div class="card-body p-5">
|
||||||
<h2 class="text-lg font-semibold mb-4 flex items-center gap-2">
|
<h2 class="text-lg font-semibold mb-4 flex items-center gap-2">
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
@@ -244,7 +244,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Flavor Distribution -->
|
<!-- Flavor Distribution -->
|
||||||
<div class="card bg-base-100 shadow-sm border-t-2 border-accent" id="statsFlavorsCard">
|
<div class="card bg-base-100 shadow-sm border-t-gradient-vtb" id="statsFlavorsCard">
|
||||||
<div class="card-body p-5">
|
<div class="card-body p-5">
|
||||||
<h2 class="text-lg font-semibold mb-4 flex items-center gap-2">
|
<h2 class="text-lg font-semibold mb-4 flex items-center gap-2">
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
@@ -319,11 +319,11 @@
|
|||||||
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-3 mb-4">
|
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-3 mb-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 class="text-lg font-semibold">Audit Analysis</h2>
|
<h2 class="text-lg font-semibold">Audit Analysis</h2>
|
||||||
<div class="text-sm text-base-content/60 mt-0.5">Select an audit to analyze resource distribution</div>
|
<div class="text-base text-base-content/60 mt-0.5">Select an audit to analyze resource distribution</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span class="text-xs text-base-content/60" id="auditsCount">{% if skeleton %}Loading…{% else %}{{ audits|length }} available{% endif %}</span>
|
<span class="text-xs text-base-content/60" id="auditsCount">{% if skeleton %}Loading…{% else %}{{ audits|length }} available{% endif %}</span>
|
||||||
<div class="dropdown dropdown-end">
|
<div class="dropdown dropdown-end no-print">
|
||||||
<label tabindex="0" class="btn btn-xs btn-ghost">
|
<label tabindex="0" class="btn btn-xs btn-ghost">
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||||
@@ -373,7 +373,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</select>
|
</select>
|
||||||
<button type="button" onclick="loadSelectedAudit()" class="btn btn-primary btn-sm gap-2">
|
<button type="button" onclick="loadSelectedAudit()" class="btn btn-primary btn-sm gap-2 no-print">
|
||||||
<svg class="w-4 h-4 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
<svg class="w-4 h-4 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6"/>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
Reference in New Issue
Block a user