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:
28
.cursor/rules/api-errors-i18n.mdc
Normal file
28
.cursor/rules/api-errors-i18n.mdc
Normal 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.
|
||||
41
.cursor/rules/backend-nestjs.mdc
Normal file
41
.cursor/rules/backend-nestjs.mdc
Normal 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.
|
||||
29
.cursor/rules/dyolink-overview.mdc
Normal file
29
.cursor/rules/dyolink-overview.mdc
Normal 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`.
|
||||
47
.cursor/rules/frontend-components.mdc
Normal file
47
.cursor/rules/frontend-components.mdc
Normal 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.
|
||||
35
.cursor/rules/maintain-agent-docs.mdc
Normal file
35
.cursor/rules/maintain-agent-docs.mdc
Normal 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, 1–5 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.
|
||||
69
.cursor/skills/add-feature/SKILL.md
Normal file
69
.cursor/skills/add-feature/SKILL.md
Normal 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/` |
|
||||
40
.cursor/skills/api-errors/SKILL.md
Normal file
40
.cursor/skills/api-errors/SKILL.md
Normal 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`
|
||||
53
.cursor/skills/capture-convention/SKILL.md
Normal file
53
.cursor/skills/capture-convention/SKILL.md
Normal 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 3–7 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.
|
||||
39
.cursor/skills/frontend-structure/SKILL.md
Normal file
39
.cursor/skills/frontend-structure/SKILL.md
Normal 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)
|
||||
Reference in New Issue
Block a user