---
description: Service layer architecture, API patterns, and data management with TanStack Query
globs: ["src/lib/**/*.ts", "src/services/**/*.ts", "src/hooks/use*.ts"]
alwaysApply: false
---

# Service Layer & Data Management Rules

## Service Layer Organization

### File Structure
```
src/lib/
├── utils.ts          # General utilities (keep cn function)
├── types.ts          # Shared TypeScript interfaces
├── constants.ts      # App-wide constants
├── validations/      # Zod schemas
│   ├── user.ts
│   ├── product.ts
│   └── common.ts
└── services/         # API service layer
    ├── api.ts        # Base API client
    ├── userService.ts
    └── productService.ts
```

### Service Layer Pattern
```tsx
// services/userService.ts
export const userService = {
  async getAll(): Promise<User[]> {
    const response = await fetch('/api/users')
    if (!response.ok) throw new Error('Failed to fetch users')
    return response.json()
  },
  
  async getById(id: string): Promise<User> {
    const response = await fetch(`/api/users/${id}`)
    if (!response.ok) throw new Error('Failed to fetch user')
    return response.json()
  },
  
  async create(data: CreateUserData): Promise<User> {
    const response = await fetch('/api/users', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data)
    })
    if (!response.ok) throw new Error('Failed to create user')
    return response.json()
  },
  
  async update(id: string, data: Partial<User>): Promise<User> {
    const response = await fetch(`/api/users/${id}`, {
      method: 'PATCH',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data)
    })
    if (!response.ok) throw new Error('Failed to update user')
    return response.json()
  }
}
```

### Shared Types (lib/types.ts)
```tsx
export interface User {
  id: string
  email: string
  name: string
  avatar?: string
  role: UserRole
  createdAt: string
  updatedAt: string
}

export interface ApiResponse<T> {
  data: T
  message: string
  success: boolean
  meta?: {
    total: number
    page: number
    limit: number
  }
}

export type UserRole = 'admin' | 'user' | 'guest'
export type Theme = 'light' | 'dark' | 'system'
export type LoadingState = 'idle' | 'loading' | 'success' | 'error'
```

### Constants (lib/constants.ts)
```tsx
export const API_ENDPOINTS = {
  USERS: '/api/users',
  PRODUCTS: '/api/products',
  AUTH: '/api/auth',
} as const

export const QUERY_KEYS = {
  USERS: 'users',
  PRODUCTS: 'products',
  USER_PROFILE: 'user-profile',
} as const

export const ROUTES = {
  HOME: '/',
  DASHBOARD: '/dashboard',
  USERS: '/users',
  PROFILE: '/profile',
} as const
```

### Validation Schemas
```tsx
// lib/validations/common.ts
export const emailSchema = z.string().email('Invalid email address')
export const phoneSchema = z.string().regex(/^\+?[\d\s-()]+$/, 'Invalid phone number')

// lib/validations/user.ts
export const userSchema = z.object({
  name: z.string().min(2, 'Name must be at least 2 characters'),
  email: emailSchema,
  phone: phoneSchema.optional(),
  role: z.enum(['admin', 'user', 'guest'])
})

export const createUserSchema = userSchema.omit({ role: true })
export const updateUserSchema = userSchema.partial()

export type UserFormData = z.infer<typeof userSchema>
export type CreateUserData = z.infer<typeof createUserSchema>
export type UpdateUserData = z.infer<typeof updateUserSchema>
```

## TanStack Query Integration

### Query Hooks Pattern
```tsx
// hooks/useUsers.ts
export const useUsers = (params?: UserQueryParams) => {
  return useQuery({
    queryKey: [QUERY_KEYS.USERS, params],
    queryFn: () => userService.getAll(params),
    staleTime: 5 * 60 * 1000, // 5 minutes
  })
}

export const useUser = (id: string) => {
  return useQuery({
    queryKey: [QUERY_KEYS.USERS, id],
    queryFn: () => userService.getById(id),
    enabled: !!id,
  })
}
```

### Mutation Hooks Pattern
```tsx
// hooks/useUserMutations.ts
export const useCreateUser = () => {
  const queryClient = useQueryClient()
  
  return useMutation({
    mutationFn: userService.create,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.USERS] })
      toast.success('User created successfully')
    },
    onError: (error) => {
      toast.error(error.message)
    }
  })
}
```

## NEVER in Components
- Direct API calls (`fetch`, `axios` inline)
- Business logic mixed with UI
- Hardcoded API URLs
- Duplicate validation schemas

## ALWAYS Use
- Service layer for all API calls
- Shared types for consistent interfaces
- Custom hooks for data fetching
- Centralized constants for URLs and keys
