c91e292066
Design system (Layout2): - Solid token-driven theme (no animated grid); single-source tokens for bg, cards (bg/border/radius), popups, fonts (Inter), and full semantic + data-viz color palette. Swept ~168 hardcoded colors to tokens. Dashboard: - Reflow: To Do + Calendar row (fixed right rail) over Activity / In-Progress / Team Performance; CSS height-match (To Do = Calendar); responsive stacking. - 'Tasks Not Started' -> 'To Do' card with R#/Assigned columns; compact money fmt. Tasks page: - Combined tabs into Tasks + Completed with a Status column. - Column-header sort + filter (Status, R#/new-vs-revision, Project, Task Type, Company) via portaled, scrollable FilterDropdown; removed toolbar filters and the projects side panel; headers stay visible when empty; renamed to 'Tasks'. Perf: - FK/filter index migration; removed redundant client/external scope waterfall (rely on RLS); parallel follow-up queries. Mobile: - Responsive grids; mobile topbar = hamburger only, blends with bg, proper offset. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
25 lines
903 B
JavaScript
25 lines
903 B
JavaScript
import { useRef, useCallback } from 'react';
|
|
|
|
// Guards async handlers against double-fire (e.g. a rapid double-click that triggers
|
|
// both onClick callbacks before React re-renders the now-disabled button). Disabled
|
|
// buttons alone don't prevent this because the disable only takes effect after a render.
|
|
//
|
|
// Usage:
|
|
// const guard = useActionLock();
|
|
// const handleSubmit = guard('submit', async () => { ... });
|
|
//
|
|
// Each `key` locks independently, so unrelated buttons don't block each other. While a
|
|
// run is in-flight the same key is a no-op until it settles (resolve or throw).
|
|
export function useActionLock() {
|
|
const locks = useRef(new Set());
|
|
return useCallback((key, fn) => async (...args) => {
|
|
if (locks.current.has(key)) return undefined;
|
|
locks.current.add(key);
|
|
try {
|
|
return await fn(...args);
|
|
} finally {
|
|
locks.current.delete(key);
|
|
}
|
|
}, []);
|
|
}
|