v1.5.6: boneyard-js skeleton migration, TanStack Query refactor, rate-limit config

- Replace hand-coded skeleton CSS/JSX with boneyard-js auto-generated bones
- Remove skeleton.css and @keyframes shimmer from base.css
- Add <Skeleton> wrappers with fixtures to all 25+ page components
- Generate 20 bone captures via boneyard CLI (CDP auth-gated capture)
- Refactor data fetching from useEffect+useState to TanStack Query
- Extract query hooks into src/admin/lib/queries/ and apiAdapter
- Add usePaginatedQuery hook replacing useApiCall/useListData
- Fix parseFloat || 0 anti-pattern in OfferDetail and OffersTemplates inputs
- Fix customer_id mandatory validation on offer creation
- Fix leave-requests comma-separated status filter (Prisma enum in: [])
- Add cross-entity cache invalidation for orders/offers/invoices/projects
- Make rate limits configurable via env vars (RATE_LIMIT_MAX, RATE_LIMIT_REFRESH, etc.)
- Add boneyard.config.json with routes and breakpoints

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
BOHA
2026-04-28 22:35:43 +02:00
parent 12289bdce3
commit ba95723b61
109 changed files with 26410 additions and 10159 deletions

View File

@@ -42,7 +42,7 @@ export default async function authRoutes(
{
config: {
rateLimit: {
max: 20,
max: config.rateLimit.login,
timeWindow: "1 minute",
},
},
@@ -95,7 +95,7 @@ export default async function authRoutes(
{
config: {
rateLimit: {
max: 5,
max: config.rateLimit.loginTotp,
timeWindow: "1 minute",
},
},
@@ -259,7 +259,7 @@ export default async function authRoutes(
{
config: {
rateLimit: {
max: 10,
max: config.rateLimit.refresh,
timeWindow: "1 minute",
},
},

View File

@@ -31,7 +31,10 @@ export default async function leaveRequestsRoutes(
const where: Record<string, unknown> = {};
if (!isAdmin || query.mine === "1") where.user_id = authData.userId;
else if (query.user_id) where.user_id = Number(query.user_id);
if (query.status) where.status = String(query.status);
if (query.status) {
const statuses = String(query.status).split(",");
where.status = statuses.length === 1 ? statuses[0] : { in: statuses };
}
const [requests, total] = await Promise.all([
prisma.leave_requests.findMany({

View File

@@ -248,7 +248,7 @@ export default async function totpRoutes(
{
config: {
rateLimit: {
max: 5,
max: config.rateLimit.loginTotp,
timeWindow: "1 minute",
},
},