update ui update and fix layout issue

This commit is contained in:
2026-08-06 13:21:10 +05:30
parent 92322bff16
commit e5f8144fb3
251 changed files with 9041 additions and 2119 deletions

120
ARCHITECTURE.md Normal file
View File

@@ -0,0 +1,120 @@
# Architecture
How this codebase is organised, and the rules that keep it that way. Read this
before adding a feature; it should take about five minutes.
## The layers
Data flows in one direction, and each layer is allowed to know only the one
below it:
```
component / page renders state, owns no rules
features/<f>/hooks binds a service or repository to React
features/<f>/services domain rules: validation, interpretation, defaults
features/<f>/repositories TRANSPORT ONLY — the single place that knows a URL
app/api/<f>/route.ts HTTP boundary: authorises, parses, responds
features/<f>/mock/*.mock fixtures, server-side only
```
**Connecting a real backend touches the repository layer and nothing else.**
Point `NEXT_PUBLIC_API_BASE` at a host, or rewrite the four lines in a
repository, and every component above it is untouched. That is the property the
whole structure exists to protect, so:
- **Never** `import` from a `mock/` module in a component, hook or page. Server
Components read through a `*ServerRepository`; clients go over HTTP.
- **Never** call `fetch` in a component. `shared/services/httpClient` is the
only module that does.
- A repository never interprets a response, and a service never builds a URL.
## Where things live
```
src/
app/ routing only — thin files, no logic
(public)/login unauthenticated routes → PublicLayout → GuestGuard
(workspace)/… authenticated routes → ProtectedLayout → AuthGuard
api/ route handlers
proxy.ts the server-side auth gate (Next 16 renamed middleware → proxy)
features/<feature>/
components/ UI for this feature only
hooks/ data access + view state
services/ domain rules, framework-free, unit-testable
repositories/ URLs and verbs
types/ the wire contract for this feature
mock/ fixtures (server-side)
utils/ · config/ · guards/ · providers/ as needed
shared/
components/ brand · charts · patterns · primitives · scope · data · motion
hooks/ useResource · useScope · useBreakpoint · usePersistentFlag
layouts/ ProtectedLayout · PublicLayout · workspace shell
providers/ app-wide state (workspace scope)
services/ httpClient (transport) · apiRoute (handler helpers)
types/ the response envelope
mock/ seeded RNG shared by every fixture
theme/ design tokens; edit loyalyTheme.ts, run `npm run theme:build`
```
A feature owns everything about itself. If two features need the same thing, it
moves to `shared/` — it does not get imported across features, with one
deliberate exception: `features/dashboard/types` holds the analytics primitives
(`TimePoint`, `ActivityEvent`) that LYTs and Stores genuinely share, because
duplicating them would let two modules disagree about the same wire shape.
## Authentication
Three independent gates, in order of authority:
1. **`src/proxy.ts`** — runs before any protected route renders. No valid
session cookie, no page. API paths get a 401 JSON; pages get a redirect to
`/login?next=…`. This is the one that matters.
2. **`requireApiSession()`** — every data route handler calls it. Next's own
docs warn that proxy coverage can be silently lost by a matcher change or a
route move, so the check is repeated where the data is.
3. **`AuthGuard` / `GuestGuard`** — client-side. Covers what the server never
sees: a session expiring in an open tab, a logout in another tab, a
client-side navigation. **Not a security boundary.**
The session is a signed httpOnly cookie (`features/auth/services/sessionToken`),
so the browser cannot read or forge it. `SessionProvider` holds only what to
draw, never what to permit — it asks `GET /api/auth/session` and believes the
answer.
Swapping the mock for a real identity provider means changing
`verifyCredentials` in `features/auth/mock/users.mock.ts` and the three URLs in
`authRepository`. Nothing else, including the login form, is aware.
## Conventions
- **No `any`.** The codebase has zero, and `tsc --noEmit` is expected to pass
before every commit.
- **Components stay under ~300 lines.** When one grows past that, the split is
usually behaviour-into-a-hook, not markup-into-more-markup.
- **Names say what the thing is**: `DashboardKpiCard`, `StaffAttendanceTable`.
Never `Card.tsx`, `utils.ts`, `NewFile.tsx`.
- **Styling comes from the design system**, in this order: component props →
token-backed Tailwind utilities → a theme override in `loyalyTheme.ts`. There
are no per-feature CSS files; see the note below.
### On CSS
The brief that produced this refactor asked for per-feature stylesheets
(`dashboard/styles/kpi.css`, and so on) so that changing one module cannot
affect another. That isolation is already total here, by construction rather
than by convention: styling lives in component props and utility classes scoped
to the element they are written on, so there is no selector in the codebase
that *can* reach another feature. Adding stylesheets would introduce global
selectors — the one mechanism that can leak — and they would have to fight
StyleX's `@layer astryx-base` for the cascade. Shared visual decisions belong in
`theme/loyalyTheme.ts`, which is the single place a change is meant to be
system-wide.
If a future component genuinely needs CSS that props and utilities cannot
express, `astryx swizzle <Component>` ejects the source for that one component
rather than opening a stylesheet the whole app can be edited through.