Commit Graph

17 Commits

Author SHA1 Message Date
BOHA
519edce373 fix: 2026-06-09 full-codebase audit hardening
Validation: shared NaN-guarded Zod coercion helpers in schemas/common.ts replace
the raw number|string transform idiom across every schema (the root-cause NaN bug
class); emailOrEmpty + lenient isoDateString/timeString.

Security: roles privilege-escalation closed; refresh-token family revocation on
reuse; TOTP uses config params; read endpoints permission-guarded; received-invoices
gross VAT on all paths; orders-pdf custom-items authz.

Concurrency: $queryRaw SELECT...FOR UPDATE locks in ascending-id order (warehouse
confirm/cancel, attendance lockUserRow); uniqueness checks moved into create
transactions (TOCTOU -> 409); deterministic id tiebreak on second-precision
timestamp ordering (plan resolveCell/resolveGrid, warehouse FIFO).

Frontend: Rules-of-Hooks fixed across ~14 pages + PlanCellModal; UTC-date persisted
fields; dashboard invalidation gaps; stale-closure confirm bugs.

Tooling/tests: ESLint flat config (react-hooks/rules-of-hooks = error) + Prettier;
tsconfig.test.json so tsc -b type-checks the tests; removed 3 dead deps; npm audit
fix (8 -> 3). Suite 195 -> 247 (happy-path auth, FIFO oldest-first, flakiness fixes),
isolated on app_test via .env.test with a hard-throw setup guard.

Gates: tsc 0 | build 0 | vitest 247/247 | eslint 0 errors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 06:45:26 +02:00
BOHA
8e7ab9158c fix(ui): readable status row tints — subtle washes, not solid .light fills
The per-status row backgrounds used MUI's solid `.light` palette shades
(error.light/success.light/warning.light). Those are LIGHT colors in both
schemes, so in dark mode the row's white text sat on a light fill and was
effectively invisible; in light mode they read as garish saturated blocks.

Replaced with low-alpha washes via the palette channel vars
(rgba(var(--mui-palette-X-mainChannel) / 0.12), 0.18 on hover), which keep
the row's normal theme text colour fully readable in BOTH schemes:

- Offers: completed = subtle green wash; invalidated = faded/muted
  (opacity + secondary text, the original "voided" look) instead of a
  solid red block; expired = subtle amber wash.
- DataTable rowDanger (kit-wide — Warehouse, WarehouseReports): subtle
  error wash for both the desktop row and the mobile card (card keeps its
  error.main border as the danger cue).
- Invoices overdue rows: subtle amber wash.
- Dashboard 2FA banner Card: subtle error wash (keeps the error.main
  border) so the banner copy stays readable in dark mode.

Verified live in Chrome on Offers (completed + invalidated, light + dark):
faint tint + normal readable text, channel switches per scheme. tsc -b
--noEmit, npm run build, vitest 152/152 all clean. (Left untouched: small
icon tiles / callout boxes that pair a .light bg with an explicit dark or
coloured text/glyph — those are readable in both schemes by construction.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 17:57:58 +02:00
BOHA
1e155f6ffb fix(ui): wrap action-button groups so they don't clip on mobile
Since kit buttons now keep their natural width (flexShrink:0 + nowrap), a row of them can't shrink — so button groups that were flexShrink:0 with no wrap got clipped on phones (the page has overflow-x:hidden). The draft-concept Alert actions (Offers + Invoices) and the shared PageHeader actions now use flexWrap:wrap and drop flexShrink:0, so the group conforms to the available width and its buttons wrap onto stacked lines. Verified at 430px: the Offers draft alert no longer overflows (buttons stack), page has no horizontal scroll.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 16:05:32 +02:00
BOHA
39fe84ce99 feat(mui): consistent staggered page entrance across all 43 route pages
Adopt the PageEnter wrapper as every page's outermost render element and remove the ad-hoc per-page entrance motion.div wrappers. Every page now enters the same way — all top-level sections rise+fade in, staggered — so nothing appears instantly and the motion is identical app-wide. Presentation-only: no data/logic/hooks/invalidate/permissions touched. Embedded sub-tabs (CompanySettings, ReceivedInvoices), Login (auth shell) and the dev UiKit are intentionally excluded. Gates: tsc -b --noEmit=0, build=0, vitest 152/152.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 10:13:06 +02:00
BOHA
5ca03bd662 feat(mui): migrate Invoices (Faktury — Vydané + Přijaté) onto MUI kit
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 01:09:43 +02:00
BOHA
0330453ad6 v1.6.8: remove offer exchange rate, add invoice item description, offer filters, table animations
- Remove exchange_rate and exchange_rate_date from quotations (schema, service, PDF, form)
- Add item_description field to invoice_items (schema, migration, service, form, PDF)
- Add offer status/customer/order filters with tab-based UI
- Clean up offer statuses to active/ordered/invalidated
- Allow invalidate action for non-ordered offers (not just expired)
- Add fade animations on offers and invoices table data changes

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 12:58:51 +02:00
BOHA
cd6d3daf43 v1.6.5: fix attendance unique constraint, schema sync, seed script
- Change attendance idx_attendance_user_date from unique to index (allow multiple shifts per day)
- Reset migrations to single baseline init migration
- Add seed script with admin user (admin/admin)
- Update CLAUDE.md with migration workflow documentation
- Various frontend fixes (queries, pages, hooks)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 16:21:34 +02:00
BOHA
ba95723b61 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>
2026-04-28 22:35:43 +02:00
BOHA
528e55991b security: fix all Critical and High findings from FLAWS_REPORT audit
- Auth: pessimistic locking on login tokens and refresh token rotation,
  backup code attempt counter, rate limiting verification
- Schema: unique constraints on business numbers, FK relations,
  unsigned/signed alignment, attendance duplicate prevention
- Invoices/PDFs: DOMPurify sanitization, bounded queries in stats
  and alerts, VAT rounding, Puppeteer error handling
- Orders/Offers: transactional parent+child creation, Zod NaN
  refinement, status enums, uniqueness checks
- Projects/Files: path traversal protection, streamed uploads,
  permission guards, query param validation
- Attendance/HR: duplicate checks, ownership validation, GPS
  restrictions, trip distance validation
- Frontend: modal lock reference counting, XSS escaping in print
  HTML, ref mutation fixes, accessibility attributes

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-24 00:58:35 +02:00
BOHA
e9f07a4a39 fix: invoice edit/list improvements
- Due date uses days selector in edit mode (same as create)
- Overdue invoices fully editable (same as issued)
- Overdue status reversed to issued when due date moved to future
- Invoice list: edit icon for issued/overdue, eye for paid
- Invoice list: PDF opens blob from NAS (removed lang modal)
- NAS cleanup: properly scans directories when cleaning old PDFs
- Fixed syntax error from leftover else block

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 20:01:43 +02:00
BOHA
8cdf057ab3 feat: CNB exchange rates, multi-currency KPI stats, invoice PDF VAT in CZK
- ČNB exchange rate service with date-specific rates and caching
- Invoice/received invoice stats convert foreign currencies to CZK
- Dashboard revenue converts all currencies to CZK
- Invoice PDF: VAT recap table always in CZK with CNB rate footer
- Inline styles replaced with utility classes (step 4 cleanup)
- Spinner animation exempt from prefers-reduced-motion

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:44:53 +01:00
BOHA
e0ea997c24 refactor: split admin.css monolith, standardize CSS architecture
- Split admin.css (3228 lines) into 12 focused files: variables, base,
  forms, buttons, layout, components, tables, skeleton, datepicker,
  filemanager, pagination, responsive
- Extracted shared styles from offers.css and dashboard.css into
  components.css and forms.css (offers-* → admin-* prefix)
- Standardized naming: dash-kpi-* → admin-kpi-*, session-* → dash-session-*,
  rich-editor → admin-rich-editor
- Deleted duplicate offers-tabs (using admin-tabs everywhere)
- Deduplicated DatePicker and FileManager CSS (~360 lines removed)
- Added 16 utility classes to base.css (font sizes, widths, gaps, margins)
- Deleted empty admin.css

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:00:45 +01:00
BOHA
6b31b2f74b feat: system settings, dynamic logos, template numbering, permission consolidation
- System settings page with tabs: Security, System, Firma
- Configurable attendance rules (break thresholds, rounding) from DB
- Configurable document numbering with template patterns ({YYYY}/{PREFIX}/{NNN})
- Dynamic logo upload (light/dark variants) served from DB instead of static files
- Email settings (SMTP from/name, alert/leave emails) configurable in UI
- Currency and VAT rate lists configurable, used across all modules
- Permissions simplified: offers.settings + settings.roles + settings.security → settings.manage
- Leaflet bundled locally, removed unpkg.com from CSP
- Silent catch blocks fixed with proper logging
- console.log replaced with app.log.info in server.ts
- Schema renamed: company-settings.schema → settings.schema
- App info section: version, Node.js, uptime, memory, DB status, NAS status

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 10:15:47 +01:00
BOHA
baceb88347 feat: NAS storage for invoices/offers, code cleanup, date/time fixes
- NAS storage for created invoices (PDF via puppeteer), received invoices,
  and offers with auto-save on create/edit
- Deterministic file paths derived from DB fields (no file_path column needed)
- Separate NAS mount points: NAS_FINANCIALS_PATH, NAS_OFFERS_PATH
- Invoice language field (cs/en) stored per invoice, replaces lang modal
- Invoices list filtered by month/year matching KPI card selection
- Centralized date helpers (src/utils/date.ts) replacing all .toISOString()
  calls that returned UTC instead of local time
- Attendance project switching uses exact time (not rounded)
- Comment cleanup: removed ~100 unnecessary/Czech comments
- Removed as-any casts in orders and attendance
- Prisma migrations: add invoice language, drop received_invoices BLOB columns

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 10:36:39 +01:00
BOHA
3c167cf5c4 style: run prettier on entire codebase 2026-03-24 19:59:14 +01:00
BOHA
635c6fd0ff fix: table sorting blocked by pointerEvents:none during loading
Root cause: useListData set loading=true on every refetch, and all 4
admin list pages (offers, orders, invoices, projects) applied
pointerEvents:'none' while loading — blocking all clicks including
sort column headers.

Fix: removed setLoading(true) from refetch (matching PHP behavior)
and removed pointerEvents from all list page cards. Opacity fade
kept as visual feedback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 10:57:17 +01:00
BOHA
4608494a3f initial commit
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 08:46:51 +01:00