4.6 KiB
4.6 KiB
CLQMS Frontend - Code Style and Conventions
JavaScript/TypeScript
- Language: Plain JavaScript (no TypeScript)
- 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 5 Runes)
Component Structure
<script>
// 1. Imports first - group by: Svelte, $lib, external
import { onMount } from 'svelte';
import { goto } from '$app/navigation';
import { auth } from '$lib/stores/auth.js';
import { login } from '$lib/api/auth.js';
import { Icon } from 'lucide-svelte';
// 2. Props (Svelte 5 runes)
let { children, data } = $props();
// 3. State
let loading = $state(false);
let error = $state('');
// 4. Derived state (if needed)
let isValid = $derived(username.length > 0);
// 5. Effects
$effect(() => {
// side effects
});
// 6. Functions
function handleSubmit() {
// implementation
}
</script>
Naming Conventions
- Components: PascalCase (
LoginForm.svelte,DataTable.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,valuesets) - Event handlers: prefix with
handle(handleSubmit,handleClick)
Imports Order
- Svelte imports (
svelte,$app/*) - $lib aliases (
$lib/stores/*,$lib/api/*,$lib/components/*) - External libraries (
lucide-svelte) - Relative imports (minimize these, prefer
$lib)
API Client Pattern
Base Client (src/lib/api/client.js)
The base client handles JWT token management and 401 redirects automatically.
Feature-Specific API Modules
// src/lib/api/feature.js - Feature-specific endpoints
import { apiClient, get, post, put, patch, del } from '$lib/api/client.js';
export async function getItem(id) {
return get(`/api/items/${id}`);
}
export async function createItem(data) {
return post('/api/items', data);
}
Form Handling Pattern
let formData = { name: '', email: '' };
let errors = {};
let loading = false;
async function handleSubmit() {
loading = true;
errors = {};
try {
const result = await createItem(formData);
if (result.status === 'error') {
errors = result.errors || { general: result.message };
} else {
// Success - redirect or show message
}
} catch (err) {
errors = { general: err.message || 'An unexpected error occurred' };
}
loading = false;
}
Error Handling
- API errors are thrown with message
- Use try/catch blocks for async operations
- Store errors in state for display
- Toast notifications for user feedback
try {
const result = await api.login(username, password);
toast.success('Login successful');
} catch (err) {
error = err.message || 'An unexpected error occurred';
console.error('Login failed:', err);
toast.error('Login failed');
}
Styling with Tailwind & DaisyUI
- Use Tailwind utility classes
- DaisyUI components:
btn,card,alert,input,navbar,select - Color scheme:
primary(emerald),base-100,base-200 - Custom colors in
app.csswith@theme
Authentication Patterns
- Auth state in
$lib/stores/auth.js - Check auth in layout
onMountor+layout.server.js - Redirect to
/loginif unauthenticated - API client auto-redirects on 401
LocalStorage
- Only access in browser: check
browserfrom$app/environment - Use descriptive keys:
auth_token
Reusable Components
- DataTable.svelte: Sortable, paginated table with actions
- Modal.svelte: Reusable modal for confirmations and forms
- SelectDropdown.svelte: Dropdown populated from ValueSets or API data
- Sidebar.svelte: Navigation sidebar
- ToastContainer.svelte: Toast notifications
SvelteKit Patterns
- File-based routing with
+page.svelte,+layout.svelte - Route groups with
(app)for protected routes - Load data in
+page.jsor+page.server.jsif needed - Use
invalidateAll()after mutations to refresh data
Code Quality Notes
- No ESLint or Prettier configured yet
- No test framework configured yet (plan: Vitest for unit tests, Playwright for E2E)
- JSDoc comments are required for all exported functions
- Keep components focused and reusable
- Extract logic into utility functions when possible