feat: dashboard overhaul, chargeability reports, dispo import enhancements, UI polish
Dashboard: expanded chargeability widget, resource/project table widgets with sorting and filters, stat cards with formatMoney integration. Chargeability: new report client with filtering, chargeability-bookings use case, updated dashboard overview logic. Dispo import: TBD project handling, parse-dispo-matrix improvements, stage-dispo-projects resource value scores, new tests. Estimates: CommercialTermsEditor component, commercial-terms engine module, expanded estimate schemas and types. UI: AppShell navigation updates, timeline filter/toolbar enhancements, role management improvements, signin page redesign, Tailwind/globals polish, SystemSettings SMTP section, anonymization support. Tests: new router tests (anonymization, chargeability, effort-rule, entitlement, estimate, experience-multiplier, notification, resource, staffing, vacation). Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -5,15 +5,25 @@ import type { WidgetProps } from "~/components/dashboard/widget-registry.js";
|
||||
import { formatMoney } from "~/lib/format.js";
|
||||
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
|
||||
|
||||
function StatCard({ label, value, sub, info }: { label: string; value: string | number; sub?: string; info?: React.ReactNode }) {
|
||||
function StatCard({
|
||||
label,
|
||||
value,
|
||||
sub,
|
||||
info,
|
||||
}: {
|
||||
label: string;
|
||||
value: string | number;
|
||||
sub?: string;
|
||||
info?: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-xs font-medium text-gray-500 flex items-center">
|
||||
<div className="rounded-2xl border border-gray-200 bg-white/80 p-4 shadow-sm dark:border-gray-700 dark:bg-gray-900/70">
|
||||
<span className="flex items-center text-xs font-semibold uppercase tracking-[0.18em] text-gray-500">
|
||||
{label}
|
||||
{info && <InfoTooltip content={info} />}
|
||||
</span>
|
||||
<span className="text-2xl font-bold text-gray-900">{value}</span>
|
||||
{sub && <span className="text-xs text-gray-400">{sub}</span>}
|
||||
<span className="mt-2 text-2xl font-semibold text-gray-900 dark:text-gray-50">{value}</span>
|
||||
{sub && <span className="mt-1 text-xs text-gray-500 dark:text-gray-400">{sub}</span>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -29,7 +39,10 @@ export function StatCardsWidget(_props: Partial<WidgetProps> = {}) {
|
||||
return (
|
||||
<div className="grid grid-cols-2 gap-3 h-full animate-pulse">
|
||||
{[...Array(4)].map((_, i) => (
|
||||
<div key={i} className="rounded-xl bg-gray-100 dark:bg-gray-800 p-4 flex flex-col gap-2">
|
||||
<div
|
||||
key={i}
|
||||
className="rounded-2xl border border-gray-200 bg-gray-100 p-4 dark:border-gray-700 dark:bg-gray-800"
|
||||
>
|
||||
<div className="h-3 w-20 bg-gray-200 dark:bg-gray-700 rounded" />
|
||||
<div className="h-7 w-16 bg-gray-300 dark:bg-gray-600 rounded" />
|
||||
<div className="h-2 w-24 bg-gray-200 dark:bg-gray-700 rounded" />
|
||||
|
||||
Reference in New Issue
Block a user