> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sagozen.digital/llms.txt
> Use this file to discover all available pages before exploring further.

# Code Standards & Best Practices

> TypeScript conventions, backend/frontend standards, testing, and code quality guidelines

# Code Standards & Best Practices

Standards and conventions for Pet Service Management System across backend (NestJS) and frontend (Next.js/React).

<Note>
  **TypeScript Strict Mode:** All files use strict mode with no implicit `any` types and null/undefined checking enforced.
</Note>

***

## TypeScript Conventions

### Naming Conventions

<Tabs>
  <Tab title="Files & Directories">
    * Use kebab-case for file names: `auth.guard.ts`, `booking.service.ts`
    * Feature directories in lowercase: `auth/`, `bookings/`, `services/`
    * Components in PascalCase: `DashboardHeader.tsx`, `LanguageSwitcher.tsx`
  </Tab>

  <Tab title="Types & Interfaces">
    * Use PascalCase: `User`, `Booking`, `Pet`, `CreateBookingDto`
    * Suffix DTOs with `Dto`: `CreateUserDto`, `UpdatePetDto`
    * Suffix types with `Type` if needed: `AuthTokenType`, `PetSpeciesType`
  </Tab>

  <Tab title="Variables & Constants">
    * Use camelCase for variables: `userId`, `isActive`, `totalAmount`
    * Use UPPER\_SNAKE\_CASE for constants: `MAX_RETRY_COUNT`, `API_TIMEOUT`
    * Use UPPER\_SNAKE\_CASE for enums: `BookingStatus`, `ServiceCategory`
  </Tab>

  <Tab title="Functions & Methods">
    * Use camelCase: `getUserById()`, `createBooking()`, `validateEmail()`
    * Use verb prefixes: `get`, `create`, `update`, `delete`, `fetch`, `process`
    * Async functions should be clear: `fetchUserFromDB()`, `submitBooking()`
  </Tab>
</Tabs>

### Type Annotations

<CodeGroup>
  ```typescript DO: Explicit Type Annotations theme={null}
  const userId: string = user.id;
  const booking: Booking = await bookingService.getById(id);
  function processBooking(id: string): Promise<Booking> { }
  ```

  ```typescript DON'T: Avoid Implicit Types theme={null}
  const userId = user.id; // OK if context is clear
  const data: any = response; // AVOID: use specific types
  ```
</CodeGroup>

### Comments & Documentation

```typescript theme={null}
/**
 * Retrieves a booking by ID with all related data
 * @param id - The booking identifier
 * @returns The booking or undefined if not found
 * @throws NotFoundException if booking doesn't exist
 */
async getBookingById(id: string): Promise<Booking> {
  // Fetch booking with relations
  return this.prisma.booking.findUnique({
    where: { id },
    include: {
      pets: true,
      services: true,
      assignedStaff: true,
    },
  });
}
```

### Common Type Patterns

<CodeGroup>
  ```typescript DTOs for API Endpoints theme={null}
  export class CreateBookingDto {
    customerId: string;
    petIds: string[];
    serviceIds: string[];
    startDate: Date;
    notes?: string;
  }
  ```

  ```typescript Response Types theme={null}
  export interface BookingResponse {
    id: string;
    status: BookingStatus;
    totalAmount: number;
    createdAt: Date;
  }
  ```

  ```typescript Database Model Types theme={null}
  import { Booking, User, Pet } from '@prisma/client';
  ```

  ```typescript Enum Types theme={null}
  export enum BookingStatus {
    PENDING = 'PENDING',
    CONFIRMED = 'CONFIRMED',
    IN_PROGRESS = 'IN_PROGRESS',
    COMPLETED = 'COMPLETED',
    CANCELLED = 'CANCELLED',
  }
  ```
</CodeGroup>

***

## Backend (NestJS) Standards

### Module Organization

```
src/bookings/
├── dto/
│   ├── create-booking.dto.ts
│   ├── update-booking.dto.ts
│   └── booking-filters.dto.ts
├── bookings.controller.spec.ts
├── bookings.controller.ts
├── bookings.module.ts
├── bookings.service.spec.ts
└── bookings.service.ts
```

### Controllers

```typescript theme={null}
import { Controller, Get, Post, Body, Param, UseGuards } from '@nestjs/common';
import { AuthGuard } from '../auth/guards/auth.guard';
import { BookingsService } from './bookings.service';
import { CreateBookingDto } from './dto/create-booking.dto';

@Controller('bookings')
@UseGuards(AuthGuard) // Protect entire controller
export class BookingsController {
  constructor(private readonly bookingsService: BookingsService) {}

  @Get()
  async getBookings() {
    return this.bookingsService.findAll();
  }

  @Get(':id')
  async getBookingById(@Param('id') id: string) {
    return this.bookingsService.findById(id);
  }

  @Post()
  async createBooking(@Body() createDto: CreateBookingDto) {
    return this.bookingsService.create(createDto);
  }
}
```

**Controller Patterns:**

* One controller per module
* Use decorators: @Controller, @Get, @Post, @Put, @Delete, @Patch
* Parameters: @Param, @Body, @Query
* Guards for authentication/authorization
* Error handling with appropriate HTTP status codes

### Services

```typescript theme={null}
import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { CreateBookingDto } from './dto/create-booking.dto';
import { Booking } from '@prisma/client';

@Injectable()
export class BookingsService {
  constructor(private readonly prisma: PrismaService) {}

  async findAll(): Promise<Booking[]> {
    return this.prisma.booking.findMany({
      include: {
        pets: true,
        services: true,
        assignedStaff: true,
      },
    });
  }

  async findById(id: string): Promise<Booking> {
    const booking = await this.prisma.booking.findUnique({
      where: { id },
      include: {
        pets: true,
        services: true,
      },
    });
    if (!booking) {
      throw new NotFoundException(`Booking ${id} not found`);
    }
    return booking;
  }

  async create(createDto: CreateBookingDto): Promise<Booking> {
    // Validation
    if (createDto.petIds.length === 0) {
      throw new BadRequestException('At least one pet is required');
    }

    // Business logic
    return this.prisma.booking.create({
      data: {
        customerId: createDto.customerId,
        startDate: createDto.startDate,
        status: 'PENDING',
        pets: {
          connect: createDto.petIds.map(id => ({ id })),
        },
        services: {
          connect: createDto.serviceIds.map(id => ({ id })),
        },
      },
      include: {
        pets: true,
        services: true,
      },
    });
  }
}
```

**Service Patterns:**

* Inject PrismaService for database access
* One responsibility per method
* Throw appropriate exceptions
* Return typed responses
* Use async/await
* Include relations in queries
* Add business logic validation

### Error Handling

```typescript theme={null}
import {
  BadRequestException,
  NotFoundException,
  UnauthorizedException,
  ConflictException,
} from '@nestjs/common';

// Use appropriate exceptions
if (!booking) {
  throw new NotFoundException('Booking not found');
}

if (booking.status === 'COMPLETED') {
  throw new BadRequestException('Cannot update completed booking');
}

if (!hasPermission(user, 'UPDATE_BOOKING')) {
  throw new UnauthorizedException('Permission denied');
}

if (emailExists) {
  throw new ConflictException('Email already registered');
}
```

***

## Frontend (React/Next.js) Standards

### Component Structure

```typescript theme={null}
// components/DashboardHeader.tsx
import React, { FC, ReactNode } from 'react';

interface DashboardHeaderProps {
  title: string;
  subtitle?: string;
  actions?: ReactNode;
}

/**
 * Dashboard header component with title and optional actions
 */
export const DashboardHeader: FC<DashboardHeaderProps> = ({
  title,
  subtitle,
  actions,
}) => {
  return (
    <div className="flex justify-between items-center p-6 bg-white border-b">
      <div>
        <h1 className="text-2xl font-bold">{title}</h1>
        {subtitle && <p className="text-gray-600">{subtitle}</p>}
      </div>
      {actions && <div>{actions}</div>}
    </div>
  );
};

DashboardHeader.displayName = 'DashboardHeader';
```

### Page Components

```typescript theme={null}
// app/[locale]/dashboard/booking/page.tsx
import { ReactNode } from 'react';
import { useTranslations } from 'next-intl';
import { DashboardHeader } from '@/components/DashboardHeader';

interface BookingPageProps {
  params: Promise<{
    locale: string;
  }>;
}

export const metadata = {
  title: 'Bookings Management',
};

export default async function BookingPage({ params }: BookingPageProps) {
  const { locale } = await params;
  const t = useTranslations('dashboard.booking');

  return (
    <div>
      <DashboardHeader
        title={t('title')}
        subtitle={t('subtitle')}
      />
      {/* Content */}
    </div>
  );
}
```

### API Clients

```typescript theme={null}
// lib/api/bookings.ts
import { API_URL } from '@/lib/config';
import { Booking, CreateBookingDto } from '@/types/booking';

const BASE_URL = `${API_URL}/bookings`;

export async function getBookings(): Promise<Booking[]> {
  const response = await fetch(BASE_URL, {
    headers: {
      'Authorization': `Bearer ${getToken()}`,
    },
  });

  if (!response.ok) {
    throw new Error(`Failed to fetch bookings: ${response.statusText}`);
  }

  return response.json();
}

export async function getBookingById(id: string): Promise<Booking> {
  const response = await fetch(`${BASE_URL}/${id}`, {
    headers: {
      'Authorization': `Bearer ${getToken()}`,
    },
  });

  if (!response.ok) {
    throw new Error('Booking not found');
  }

  return response.json();
}

export async function createBooking(data: CreateBookingDto): Promise<Booking> {
  const response = await fetch(BASE_URL, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${getToken()}`,
    },
    body: JSON.stringify(data),
  },);

  if (!response.ok) {
    throw new Error('Failed to create booking');
  }

  return response.json();
}
```

***

## Styling Guidelines

### Design System Overview

**Framework:** Tailwind CSS 4 with custom design tokens

### Color Palette

<CodeGroup>
  ```typescript Brand Colors (Coral Red) theme={null}
  '#FF6B6B'  // Primary brand color - buttons, links, accents
  '#FF5A5A'  // Hover state
  '#E24D4D'  // Active/pressed state
  ```

  ```typescript Background theme={null}
  '#FFFFFF'  // Primary background (white)
  '#FFFBF5'  // Secondary background (cream/off-white)
  '#FFE5E5'  // Tertiary background (light pink)
  '#FFF5F5'  // Notification/alert background
  ```

  ```typescript Border & Dividers theme={null}
  '#EADFD6'  // Primary border color (light beige)
  ```

  ```typescript Text Colors theme={null}
  '#1F2937'  // Primary text (dark gray)
  '#475569'  // Secondary text (slate)
  '#6B7280'  // Tertiary text (lighter gray)
  ```
</CodeGroup>

### Component Patterns

<Tabs>
  <Tab title="Buttons">
    ```typescript theme={null}
    // Primary button
    className="bg-[#FF6B6B] text-white px-4 md:px-6 py-2 rounded-md
               hover:bg-[#FF5A5A] active:bg-[#E24D4D] transition-colors"

    // Secondary button
    className="border border-[#EADFD6] text-[#475569] px-4 md:px-6 py-2 rounded-md
               hover:bg-[#FFFBF5] active:bg-[#FFE5E5] transition-colors"
    ```
  </Tab>

  <Tab title="Cards">
    ```typescript theme={null}
    // Default card
    className="bg-white p-4 md:p-6 rounded-lg border border-[#EADFD6]
               shadow-sm hover:shadow-lg transition-shadow"

    // Highlighted card
    className="bg-white p-4 rounded-lg border-l-4 border-[#FF6B6B]
               bg-[#FFF5F5] shadow-md"
    ```
  </Tab>

  <Tab title="Inputs">
    ```typescript theme={null}
    className="w-full px-4 py-2 border border-[#EADFD6] rounded-md
               focus:border-[#FF6B6B] focus:outline-none focus:ring-2
               focus:ring-[#FF6B6B] focus:ring-opacity-20"
    ```
  </Tab>

  <Tab title="Header/Navigation">
    ```typescript theme={null}
    className="bg-white border-b border-[#EADFD6] sticky top-0 z-50 shadow-sm"
    ```
  </Tab>
</Tabs>

***

## Git & Version Control

### Commit Conventions

**Format:** `<type>: <subject>`

**Types:**

* `feat:` New feature
* `fix:` Bug fix
* `refactor:` Code refactoring
* `style:` Formatting changes
* `test:` Testing additions
* `docs:` Documentation updates
* `chore:` Build or dependency updates
* `perf:` Performance improvements

**Examples:**

```
feat: Add booking status update endpoint
fix: Resolve duplicate booking creation issue
refactor: Extract booking validation logic into separate module
docs: Update README with setup instructions
test: Add unit tests for BookingService
chore: Upgrade NestJS to v11.0.1
```

### Branch Naming

**Format:** `<type>/<short-description>`

**Examples:**

```
feat/booking-status-workflow
fix/duplicate-pet-creation
refactor/auth-guards
docs/api-documentation
```

***

## Testing Standards

### Unit Tests

**Coverage Target:** 80% minimum

```typescript theme={null}
describe('BookingsService', () => {
  describe('create', () => {
    it('should create a booking with valid data', async () => {
      // Arrange
      const createDto: CreateBookingDto = { /* ... */ };

      // Act
      const result = await service.create(createDto);

      // Assert
      expect(result).toBeDefined();
      expect(result.id).toBeDefined();
      expect(result.status).toBe('PENDING');
    });

    it('should throw error if no pets provided', async () => {
      // Arrange
      const createDto = { ...validDto, petIds: [] };

      // Act & Assert
      await expect(service.create(createDto)).rejects.toThrow(
        BadRequestException
      );
    });
  });
});
```

***

## Performance Standards

### Backend

* API response time: \< 300ms (p95)
* Database queries with proper indexing
* Implement pagination for list endpoints
* Use select to avoid unnecessary fields
* Connection pooling configured

### Frontend

* Lazy load components and routes
* Image optimization with Next.js Image component
* CSS-in-JS: Minimal runtime overhead
* Code splitting by route
* Minimize bundle size

***

## Security Standards

### Backend

* HTTPS/TLS enforced in production
* CORS configured for specific origins
* Rate limiting on auth endpoints
* SQL injection prevention via ORM
* Password hashing with bcrypt
* Secure session management

### Frontend

* CSP headers
* XSS prevention through React escaping
* CSRF tokens for state-changing operations
* No sensitive data in localStorage
* Secure cookie attributes (HttpOnly, Secure)

***

## Accessibility Standards

### WCAG 2.1 AA Compliance

* Semantic HTML elements
* ARIA labels for interactive components
* Color contrast ratios 4.5:1 minimum
* Keyboard navigation support
* Form labels and error messages
* Screen reader compatibility

***

<CardGroup cols={2}>
  <Card title="Design Guidelines" icon="palette" href="/design-guidelines">
    View design system
  </Card>

  <Card title="Codebase Summary" icon="folder" href="/codebase-summary">
    Explore project structure
  </Card>

  <Card title="Testing Guide" icon="vial" href="/installation#testing">
    Learn about testing
  </Card>

  <Card title="Back to Home" icon="home" href="/">
    Return to homepage
  </Card>
</CardGroup>
