---
id: w5/m4/t003
title: Loading / error / empty states for the services list
worker: worker5
status: todo
estimate: 40m
depends_on: [w5/m4/t002]
---

## Objective

Give the wired services list the three non-happy-path states: loading (skeleton rows), query error (explicit error card), and zero services (empty state), matching the reference IA from t001.

## Context

- Home page: `src/routes/index.tsx` (now wired to live `services` from t002).
- shadcn primitives available under `src/common/components/ui/` (Skeleton, Card, etc.).
- All user-visible strings go through `useTranslations()` (`services.*` namespace) per `dashboard/CLAUDE.md`.

## Steps

1. Render skeleton rows while the `services` query is loading.
2. On error, render an explicit error card (message + retry affordance) instead of an empty table.
3. On an empty result, render a "no services yet" empty state.
4. Add the new strings to `src/features/services/locales/{en,zh}.ts` under the `services.*` namespace.

## Files

- `src/routes/index.tsx`
- `src/features/services/locales/{en,zh}.ts`

## Acceptance criteria

- [ ] Loading shows skeleton rows; error shows an error card; zero services shows an empty state.
- [ ] All new strings are namespaced `services.*` and localized in `en` + `zh`.

## Out of scope

- Lifecycle actions (t004).
