improvement: some files replaced, lots of them i shall say. AGENT.MD file created. some rules and skills added for cursor agent.

This commit is contained in:
2026-07-12 21:08:29 +03:30
parent 1cdf853d32
commit 0d3fb0a51d
86 changed files with 4758 additions and 4260 deletions

View File

@@ -0,0 +1,28 @@
---
description: Error codes backend ↔ frontend and i18n message keys
globs: backend/src/common/errors/**,frontend/src/components/shared/formatApiError.ts,frontend/messages/**
alwaysApply: false
---
# API errors & translations
## Adding a new error
1. Add code to `backend/src/common/errors/error-codes.ts`
2. Throw via `AppException` (or validation DTO with that code)
3. Add matching key under `errors` in **all three** message files:
- `frontend/messages/en.json`
- `frontend/messages/fa.json`
- `frontend/messages/nl.json`
4. Frontend catch: `getUserFacingError(err, tErrors, t('fallbackKey'))`
## Validation field errors
Backend returns `{ success: false, error: { code, details: [{ field, code }] } }`.
Frontend maps `details[].code` through the `errors` namespace.
## Do not
- Show raw `error.message` or stack traces to users.
- Add English-only strings inline in components.

View File

@@ -0,0 +1,41 @@
---
description: Backend NestJS modules, Prisma, permissions, guards
globs: backend/src/**
alwaysApply: false
---
# Backend conventions
## Module layout
`backend/src/modules/{feature}/` → `{feature}.module.ts`, `.controller.ts`, `.service.ts`, `dto/`.
Register new modules in `app.module.ts`.
## Errors
Use coded errors — not raw user-facing strings:
```typescript
throw new AppException(ErrorCode.PERMISSION_DENIED, HttpStatus.FORBIDDEN);
```
- Codes: `backend/src/common/errors/error-codes.ts`
- DTO validation: `{ message: ErrorCode.VALIDATION_* }` on class-validator decorators
- Global filter: `HttpExceptionFilter` in `main.ts`
## Permissions
- Check access with `hasEffectivePermission(membership, 'TAB_*')` from `common/membership-permissions.ts`.
- Clinic-only routes: `ClinicOrgGuard`. Lab-only: `LabOrgGuard`.
- Feature-specific checks belong in the **service**, not only the controller.
## Prisma
- Schema: `backend/prisma/schema.prisma`
- Always add a migration for schema changes (`npm run prisma:migrate` in backend).
- Seed permissions stay in sync with `ALL_TAB_PERMISSIONS` in `common/permissions.ts`.
## API responses
Prefer `{ success: true, data: ... }` shape consistent with existing modules.

View File

@@ -0,0 +1,29 @@
---
description: Dyolink project context — stack, org types, git safety, verification
alwaysApply: true
---
# Dyolink overview
Monorepo: `backend/` (NestJS + Prisma), `frontend/` (Next.js + next-intl), `infrastructure/` (Docker).
## Domain
- **CLINIC** orgs: patients, appointments, treatment, staff.
- **LAB** orgs: cases, tasks, lab workflows.
- Tab access: `TAB_*_READ` / `TAB_*_EDIT` in `backend/src/common/permissions.ts`. EDIT implies READ.
## Agent behavior
- Read `AGENTS.md` and file-scoped rules before large changes.
- **Never commit or push** unless the user explicitly asks.
- Prefer minimal diffs; reuse existing components and API patterns.
- After cross-cutting changes: `backend` → `npm run build`; `frontend` → `npx tsc --noEmit`.
## i18n
All user-visible strings: `frontend/messages/en.json`, `fa.json`, `nl.json` — add keys to **all three**.
## Treatment / appointment colors
Treatment-type colors and labels: `components/shared/treatmentTypeDisplay.ts` + `catalog-type-colors.ts`. UI badges: `components/ui/treatment/TreatmentTypeBadge.tsx`.

View File

@@ -0,0 +1,47 @@
---
description: Frontend folder structure — ui vs non-ui, thin pages, feature layout
globs: frontend/src/**
alwaysApply: false
---
# Frontend component structure
## Rules
| Kind | Location |
|------|----------|
| Cross-feature UI | `components/ui/shared/` |
| Feature UI | `components/ui/{feature}/` |
| Cross-feature non-UI | `components/shared/` |
| Feature non-UI | `components/{feature}/` |
| Route logic | `components/ui/{feature}/{Feature}Page.tsx` |
| App routes | `app/**/page.tsx` — **thin wrapper only** |
## Thin page pattern
```tsx
'use client';
import { PatientsPage } from '@/components/ui/patient/PatientsPage';
export default function Page() {
return <PatientsPage />;
}
```
Reference: `app/.../treatment/page.tsx` + `components/ui/treatment/TreatmentWorkspace.tsx`.
## Do not
- Put React components (`.tsx` with JSX) in `components/` outside `ui/`.
- Put pure helpers (`.ts`, no JSX) inside `components/ui/`.
- Put business logic, API calls, or large forms directly in `app/**/page.tsx`.
## API & errors
- API clients: `lib/api/`.
- Catch blocks: `getUserFacingError(err, tErrors, fallback)` from `components/shared/formatApiError.ts`.
## When adding UI
1. Check `components/ui/shared/` for an existing primitive.
2. Check the feature's `ui/{feature}/` folder for an existing pattern.
3. Add i18n keys to en, fa, and nl.

View File

@@ -0,0 +1,35 @@
---
description: When and how to update AGENTS.md, rules, and skills after new conventions
alwaysApply: true
---
# Maintaining agent docs
Rules and skills **load automatically** but **do not self-update**. Update them when the user establishes a durable convention.
## Update when the user says (or clearly means)
- "Remember this" / "Save as convention" / "Add to project rules"
- "Document this for future agents"
- "We always do X in this project" (and it is not already in rules/skills)
## Where to put new knowledge
| Kind of knowledge | Update |
|-------------------|--------|
| Always true, 15 bullets | `.cursor/rules/*.mdc` (pick existing file or create new, <50 lines) |
| Multi-step workflow | `.cursor/skills/{name}/SKILL.md` |
| Project map / onboarding | `AGENTS.md` (index only — link to rules/skills) |
## Do not auto-update when
- One-off task instructions ("fix this bug today")
- Experimental code not yet agreed as standard
- User did not ask to persist the pattern
## After updating
- Keep rules concise; split if a file grows past ~50 lines.
- Tell the user which file(s) changed in one sentence.
Use skill `.cursor/skills/capture-convention/` for the full workflow.

View File

@@ -0,0 +1,69 @@
---
name: dyolink-add-feature
description: Adds a new Dyolink feature end-to-end (permission, backend module, frontend tab, i18n). Use when the user asks for a new tab, module, screen, or CRUD feature in Dyolink.
---
# Add a Dyolink feature
Follow this checklist. Adapt steps if the feature is read-only or org-type-specific.
## Checklist
```
- [ ] 1. Permissions & org type
- [ ] 2. Backend module
- [ ] 3. Frontend UI + thin page
- [ ] 4. i18n (en, fa, nl)
- [ ] 5. Verify build / tsc
```
## 1. Permissions & org type
- Add `TAB_{FEATURE}_READ` and `TAB_{FEATURE}_EDIT` to:
- `backend/src/common/permissions.ts` (`ALL_TAB_PERMISSIONS`, `EDIT_TO_READ`)
- `backend/prisma/seed.ts` (owner defaults per org type)
- `backend/src/modules/auth/auth.service.ts` if listed there
- Frontend: `components/staff/staff-permission-form.ts`, `components/shared/permissions.ts` route prefix if needed.
- Sidebar: `components/ui/shared/Sidebar.tsx` with `orgTypes` filter.
## 2. Backend module
```
backend/src/modules/{feature}/
{feature}.module.ts
{feature}.controller.ts
{feature}.service.ts
dto/
```
- Apply guards (`JwtAuthGuard`, org-type guard as needed).
- Service-level permission checks with `hasEffectivePermission`.
- DTOs use `ErrorCode` validation messages.
- Register in `app.module.ts`.
## 3. Frontend
- API client: `frontend/src/lib/api/{feature}.ts`
- Types: `frontend/src/types/{feature}.ts`
- UI: `frontend/src/components/ui/{feature}/`
- Non-UI helpers: `frontend/src/components/{feature}/`
- Page: thin `app/[locale]/(dashboard)/{feature}/page.tsx``{Feature}Page.tsx`
## 4. i18n
Add keys to `en.json`, `fa.json`, `nl.json` under a feature namespace (e.g. `"patients": { ... }`).
## 5. Verify
```bash
cd backend && npm run build
cd frontend && npx tsc --noEmit
```
## Reference implementations
| Pattern | Look at |
|---------|---------|
| Thin page + workspace | `treatment/page.tsx`, `TreatmentWorkspace.tsx` |
| CRUD + permissions | `modules/patients/` |
| Lab feature | `modules/cases/`, `ui/lab/` |

View File

@@ -0,0 +1,40 @@
---
name: dyolink-api-errors
description: Adds or migrates Dyolink API error codes with frontend translations. Use when adding backend validation errors, permission errors, or migrating catch blocks to getUserFacingError.
---
# Dyolink API errors
## Backend
1. Add to `ErrorCode` in `backend/src/common/errors/error-codes.ts`.
2. Throw with `AppException`:
```typescript
throw new AppException(ErrorCode.MY_CODE, HttpStatus.BAD_REQUEST, [
{ field: 'email', code: ErrorCode.VALIDATION_EMAIL_INVALID },
]);
```
3. DTOs: `@IsEmail({}, { message: ErrorCode.VALIDATION_EMAIL_INVALID })`
## Frontend
1. Add key under `"errors"` in `en.json`, `fa.json`, `nl.json` (key = error code string).
2. In components:
```typescript
const tErrors = useTranslations('errors');
// ...
catch (err: unknown) {
toast.showError(getUserFacingError(err, tErrors, t('fallbackKey')));
}
```
3. Do not use `err.message` or `(err as Error).message` for user display.
## Axios shape
Parsed in `lib/api/client` — expects `{ success: false, error: { code, details? } }`.
See rule: `.cursor/rules/api-errors-i18n.mdc`

View File

@@ -0,0 +1,53 @@
---
name: dyolink-capture-convention
description: Saves a new Dyolink project convention into AGENTS.md, .cursor/rules, or .cursor/skills. Use when the user says remember this, save as convention, add to project rules, document for future agents, or asks to update agent docs after a task.
---
# Capture convention
Persist a **durable** project pattern so the next agent chat knows it without re-explaining.
## Trigger phrases
- "Remember this"
- "Save as convention" / "Add to project rules"
- "Document this for future agents"
- "Update the cursor rules/skills"
## Workflow
1. **Confirm it is durable** — not a one-off fix. If unclear, ask: "Should every future agent follow this?"
2. **Choose target:**
- Short rule (always or file-scoped) → `.cursor/rules/{topic}.mdc`
- Step-by-step process → `.cursor/skills/{name}/SKILL.md` (new folder if needed)
- High-level pointer only → one line in `AGENTS.md` linking to the rule/skill
3. **Write concisely** — bullets, one example, under 50 lines per rule file.
4. **Avoid duplication** — merge into an existing rule if the topic fits.
5. **Commit with the feature** — remind user these files belong in git with the code change.
## Rule file template
```markdown
---
description: One-line summary
globs: frontend/src/** # omit if alwaysApply: true
alwaysApply: false
---
# Title
- Bullet convention
- ✅ Do / ❌ Don't example
```
## What not to capture
- Temporary deadlines or "for v1 only" unless labeled as such
- Secrets, env values, credentials
- Entire chat transcripts — distill to 37 bullets
## Example
User: "Remember: all lab task status badges use labTaskStatusDisplay helpers."
Action: Add bullet to `frontend-components.mdc` or `backend-nestjs.mdc` (whichever fits), not a new 200-line doc.

View File

@@ -0,0 +1,39 @@
---
name: dyolink-frontend-structure
description: Audits or refactors Dyolink frontend folder layout (components vs components/ui, thin pages). Use when moving components, fixing structure violations, or when the user mentions folder rules, page.tsx bloat, or component organization.
---
# Frontend structure audit
## Target layout
```
components/ui/shared/ → reusable UI (Button, Dialog, …)
components/ui/{feature}/ → feature UI + {Feature}Page.tsx
components/shared/ → cross-feature non-UI
components/{feature}/ → feature non-UI (helpers, config)
app/**/page.tsx → thin wrapper importing ui/{feature} page component
```
## Audit steps
1. List files in `components/` **outside** `ui/` — any `.tsx` with JSX → move to `components/ui/{feature}/`.
2. List files in `components/ui/` — any pure `.ts` helper → move to `components/{feature}/` or `components/shared/`.
3. List `app/**/page.tsx` — if > ~30 lines of logic/state, extract to `components/ui/{feature}/{Feature}Page.tsx`.
4. Update all `@/components/...` imports.
5. Run `npx tsc --noEmit` in `frontend/`.
## Common mistakes
| Wrong | Right |
|-------|-------|
| `components/today/TodayDashboard.tsx` | `components/ui/today/TodayDashboard.tsx` |
| `components/ui/treatment/treatmentTypeDisplay.ts` | `components/shared/treatmentTypeDisplay.ts` |
| Logic in `app/.../staff/page.tsx` | `components/ui/staff/StaffPage.tsx` |
## Non-UI that stays outside ui/
- `components/today/widget-registry.ts`, `chart-theme.ts` (config)
- `components/staff/workingHours.ts`
- `components/appointments/appointmentTime.ts`
- `components/i18n/LocaleSync.tsx` (null-render side effect for layout)