From 0f8ec8362bccb547a6956c47bbc56ebe03e16297 Mon Sep 17 00:00:00 2001 From: mahdahar <89adham@gmail.com> Date: Tue, 10 Feb 2026 06:43:07 +0700 Subject: [PATCH] feat: Add AGENTS.md and update login with Lucide icons, add API proxy config --- AGENTS.md | 168 ++++++++++++++++++++++++++++++++++ docs/templates/dashboard.html | 11 +++ package.json | 3 + pnpm-lock.yaml | 13 +++ src/lib/api/auth.js | 4 +- src/lib/api/client.js | 2 +- src/routes/login/+page.svelte | 17 ++-- vite.config.js | 10 +- 8 files changed, 218 insertions(+), 10 deletions(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..2a196c8 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,168 @@ +# AGENTS.md - Coding Guidelines for CLQMS Frontend + +## Project Overview + +SvelteKit frontend for Clinical Laboratory Quality Management System (CLQMS). Uses Svelte 5 runes, TailwindCSS 4, DaisyUI, and Lucide icons. + +## Build Commands + +```bash +# Development server +npm run dev + +# Production build +npm run build + +# Preview production build +npm run preview + +# Sync SvelteKit (runs automatically on install) +npm run prepare +``` + +## Testing + +**No test framework configured yet.** When adding tests: +- Use Vitest for unit tests (recommended with SvelteKit) +- Use Playwright for E2E tests +- Run single test: `vitest run src/path/to/test.js` +- Run tests in watch mode: `vitest` + +## Code Style Guidelines + +### JavaScript/TypeScript + +- **ES Modules**: Always use `import`/`export` (type: "module" in package.json) +- **Semicolons**: Use semicolons consistently +- **Quotes**: Use single quotes for strings +- **Indentation**: 2 spaces +- **Trailing commas**: Use in multi-line objects/arrays +- **JSDoc**: Document all exported functions with JSDoc comments + +### Svelte Components + +```svelte + +``` + +### Naming Conventions + +- **Components**: PascalCase (`LoginForm.svelte`) +- **Files/Routes**: lowercase with hyphens (`+page.svelte`, `user-profile/`) +- **Variables**: camelCase (`isLoading`, `userName`) +- **Constants**: UPPER_SNAKE_CASE (`API_URL`, `STORAGE_KEY`) +- **Stores**: camelCase, descriptive (`auth`, `userStore`) +- **Event handlers**: prefix with `handle` (`handleSubmit`, `handleClick`) + +### Imports Order + +1. Svelte imports (`svelte`, `$app/*`) +2. $lib aliases (`$lib/stores/*`, `$lib/api/*`, `$lib/components/*`) +3. External libraries (`lucide-svelte`) +4. Relative imports (minimize these, prefer `$lib`) + +### Project Structure + +``` +src/ + lib/ + api/ # API client and endpoints + stores/ # Svelte stores + components/ # Reusable components + assets/ # Static assets + routes/ # SvelteKit routes + (app)/ # Route groups + login/ + dashboard/ +``` + +### API Client Patterns + +```javascript +// src/lib/api/client.js - Base client handles auth +import { apiClient, get, post, put, del } from '$lib/api/client.js'; + +// src/lib/api/feature.js - Feature-specific endpoints +export async function getItem(id) { + return get(`/api/items/${id}`); +} + +export async function createItem(data) { + return post('/api/items', data); +} +``` + +### Error Handling + +```javascript +// API errors are thrown with message +try { + const result = await api.login(username, password); +} catch (err) { + error = err.message || 'An unexpected error occurred'; + console.error('Login failed:', err); +} +``` + +### Styling with Tailwind & DaisyUI + +- Use Tailwind utility classes +- DaisyUI components: `btn`, `card`, `alert`, `input`, `navbar` +- Color scheme: `primary` (emerald), `base-100`, `base-200` +- Custom colors in `app.css` with `@theme` + +### Authentication Patterns + +- Auth state in `$lib/stores/auth.js` +- Check auth in layout `onMount` +- Redirect to `/login` if unauthenticated +- API client auto-redirects on 401 + +### Environment Variables + +```javascript +const API_URL = import.meta.env.VITE_API_URL || ''; +``` + +### LocalStorage + +- Only access in browser: check `browser` from `$app/environment` +- Use descriptive keys: `clqms_username`, `clqms_remember` + +## Proxy Configuration + +API requests to `/api` are proxied to `http://localhost:8000` in dev. + +## Important Notes + +- No ESLint or Prettier configured yet - add if needed +- No test framework configured yet +- Uses Svelte 5 runes: `$props`, `$state`, `$derived`, `$effect` +- SvelteKit file-based routing with `+page.svelte`, `+layout.svelte` diff --git a/docs/templates/dashboard.html b/docs/templates/dashboard.html index 132a1f4..56b036e 100644 --- a/docs/templates/dashboard.html +++ b/docs/templates/dashboard.html @@ -291,6 +291,17 @@ + + + diff --git a/package.json b/package.json index 7ab6dca..ead458e 100644 --- a/package.json +++ b/package.json @@ -20,5 +20,8 @@ "svelte": "^5.49.2", "tailwindcss": "^4.1.18", "vite": "^7.3.1" + }, + "dependencies": { + "lucide-svelte": "^0.563.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e59e234..20b28ae 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,6 +7,10 @@ settings: importers: .: + dependencies: + lucide-svelte: + specifier: ^0.563.0 + version: 0.563.0(svelte@5.50.0) devDependencies: '@sveltejs/adapter-auto': specifier: ^7.0.0 @@ -682,6 +686,11 @@ packages: locate-character@3.0.0: resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + lucide-svelte@0.563.0: + resolution: {integrity: sha512-pjZKw7TpQcamfQrx7YdbOHgmrcNeKiGGMD0tKZQaVktwSsbqw28CsKc2Q97ttwjytiCWkJyOa8ij2Q+Og0nPfQ==} + peerDependencies: + svelte: ^3 || ^4 || ^5.0.0-next.42 + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -1261,6 +1270,10 @@ snapshots: locate-character@3.0.0: {} + lucide-svelte@0.563.0(svelte@5.50.0): + dependencies: + svelte: 5.50.0 + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 diff --git a/src/lib/api/auth.js b/src/lib/api/auth.js index 8d34fb0..ec375ae 100644 --- a/src/lib/api/auth.js +++ b/src/lib/api/auth.js @@ -10,8 +10,8 @@ import { post } from './client.js'; * @param {string} password * @returns {Promise<{token: string, user: Object}>} */ -export async function login(email, password) { - return post('/api/auth/login', { email, password }); +export async function login(username, password) { + return post('/api/auth/login', { username, password }); } /** diff --git a/src/lib/api/client.js b/src/lib/api/client.js index bbf362e..30ec22b 100644 --- a/src/lib/api/client.js +++ b/src/lib/api/client.js @@ -1,7 +1,7 @@ import { goto } from '$app/navigation'; import { auth } from '$lib/stores/auth.js'; -const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000'; +const API_URL = import.meta.env.VITE_API_URL || ''; /** * Base API client with JWT handling diff --git a/src/routes/login/+page.svelte b/src/routes/login/+page.svelte index feaa7cc..d1c80f1 100644 --- a/src/routes/login/+page.svelte +++ b/src/routes/login/+page.svelte @@ -3,6 +3,7 @@ import { auth } from '$lib/stores/auth.js'; import { login } from '$lib/api/auth.js'; import { onMount } from 'svelte'; + import { User, Lock, Eye, EyeOff, LogIn } from 'lucide-svelte'; let username = ''; let password = ''; @@ -40,7 +41,7 @@ usernameError = 'Username must be at least 3 characters'; isValid = false; } - + /* if (!password) { passwordError = 'Password is required'; isValid = false; @@ -48,7 +49,7 @@ passwordError = 'Password must be at least 6 characters'; isValid = false; } - + */ return isValid; } @@ -106,7 +107,7 @@