Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f4112fd
docs: add comprehensive contributing guidelines
FabienPineau Feb 19, 2026
360d248
Merge pull request #1 from FabienPineau/docs/setup-contributing-guide
FabienPineau Feb 19, 2026
2df8000
feat(ai): integrate Claude Code and MOAI SDK
FabienPineau Feb 19, 2026
c299be8
fix(router): import BrowserRouter from react-router-dom
FabienPineau Feb 19, 2026
da42fa2
chore: migrate to pnpm and update project configuration
FabienPineau Feb 19, 2026
ccbf698
Merge pull request #2 from FabienPineau/feat/setup-claude-moai-sdk
FabienPineau Feb 19, 2026
9e37b34
Merge pull request #3 from FabienPineau/fix/router-import-source
FabienPineau Feb 19, 2026
d46bfa1
Merge pull request #4 from FabienPineau/chore/migrate-to-pnpm-and-upd…
FabienPineau Feb 19, 2026
083689b
feat(ui): migrate Bootstrap 5 → TailwindCSS v4 + shadcn/ui (SPEC-UI-0…
FabienPineau Mar 1, 2026
21c58aa
chore(devops): setup Prettier, Husky, lint-staged, EditorConfig (SPEC…
FabienPineau Mar 1, 2026
d7f9d48
fix(checkout): use optional chaining for undefined address fields in …
FabienPineau Mar 1, 2026
0e64f1e
fix(toolbar): handle null value from Base UI Select onValueChange (#10)
FabienPineau Mar 1, 2026
b6379d7
feat(static): add 404 NotFoundPage with catch-all route (#11)
FabienPineau Mar 4, 2026
4d59124
feat(auth): add auth pages and remove change-password route (#12)
FabienPineau Mar 5, 2026
557da64
refactor(forms): global TanStack Form v1 + Zod migration (SPEC-REFACT…
FabienPineau Mar 9, 2026
aeebaff
fix(ui): add nativeButton={false} to Button components rendered as Li…
FabienPineau Mar 9, 2026
9217a8f
fix(routing): register ChangePasswordPage route at /account/change-pa…
FabienPineau Mar 10, 2026
503cf06
feat(forms): form validation UX enhancement (SPEC-UPDATE-001) (#16)
FabienPineau Mar 11, 2026
d9ac2a1
feat(test): add unit and E2E test infrastructure (SPEC-TEST-001)
FabienPineau Apr 6, 2026
e8e5883
feat(devops): Docker & HTTPS local development infrastructure (SPEC-D…
FabienPineau Apr 6, 2026
4079b92
docs: update README, CHANGELOG and CONTRIBUTING for SPEC-TEST-001 and…
FabienPineau Apr 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
node_modules
dist
.git
.gitignore
*.log
playwright-report
test-results
coverage
e2e/.auth
.moai
.claude
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VITE_REACT_APP_API_URL=http://localhost
VITE_REACT_APP_API_URL=https://localhost
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# URL of your Sylius API (no trailing slash)
# Dev: https://localhost
# Prod: https://api.myshop.com
VITE_REACT_APP_API_URL=https://localhost
17 changes: 17 additions & 0 deletions .env.test.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Test environment variables
# Copy this file to .env.test.local and fill in the values
# Used by: make docker-test-e2e (passed via --env-file .env.test.local)

# Base URL for Playwright E2E tests
# Local dev server (pnpm dev): https://localhost:5173
# Docker E2E (set automatically): https://app:4174
PLAYWRIGHT_BASE_URL=http://localhost:5173

# Test user credentials for E2E authentication
PLAYWRIGHT_TEST_EMAIL=test@example.com
PLAYWRIGHT_TEST_PASSWORD=your-test-password

# Sylius API base URL
# Local (pointing to your Sylius instance): https://localhost
# Docker E2E: overridden automatically by compose.test.yml to https://api-proxy
VITE_REACT_APP_API_URL=https://localhost
71 changes: 71 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Tests

on:
push:
branches: [main, dev, feat/**]
pull_request:
branches: [main, dev]

jobs:
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: pnpm/action-setup@v4
with:
version: 10

- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Run unit tests
run: pnpm test:unit --run

e2e-tests:
name: E2E Tests
needs: unit-tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: pnpm/action-setup@v4
with:
version: 10

- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Install Playwright browsers
run: pnpm exec playwright install --with-deps chromium

- name: Build app
run: pnpm build

- name: Run E2E tests
run: pnpm test:e2e
env:
PLAYWRIGHT_BASE_URL: ${{ env.PLAYWRIGHT_BASE_URL || 'http://localhost:5173' }}
PLAYWRIGHT_TEST_EMAIL: ${{ secrets.PLAYWRIGHT_TEST_EMAIL }}
PLAYWRIGHT_TEST_PASSWORD: ${{ secrets.PLAYWRIGHT_TEST_PASSWORD }}
VITE_REACT_APP_API_URL: ${{ secrets.VITE_REACT_APP_API_URL }}
CI: true

- name: Upload Playwright report
if: failure()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: playwright-report/
retention-days: 7
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pnpm-debug.log*
lerna-debug.log*

node_modules
.pnpm-store
dist
dist-ssr
*.local
Expand All @@ -22,3 +23,15 @@ dist-ssr
*.njsproj
*.sln
*.sw?

# AI directories and files
.claude
.moai

# Test artifacts
playwright-report/
test-results/
.auth/

# Local TLS certificates (generated by mkcert, machine-specific)
docker/app/certs/*.pem
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pnpm lint-staged
24 changes: 24 additions & 0 deletions .mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"$schema": "https://raw.githubusercontent.com/anthropics/claude-code/main/.mcp.schema.json",
"mcpServers": {
"context7": {
"$comment": "Up-to-date documentation and code examples via Context7",
"command": "/bin/bash",
"args": ["-l", "-c", "exec npx -y @upstash/context7-mcp@latest"]
},
"sequential-thinking": {
"$comment": "Step-by-step reasoning for complex problems",
"command": "/bin/bash",
"args": ["-l", "-c", "exec npx -y @modelcontextprotocol/server-sequential-thinking"]
},
"shadcn": {
"command": "npx",
"args": ["shadcn@latest", "mcp"]
}
},
"staggeredStartup": {
"enabled": true,
"delayMs": 500,
"connectionTimeout": 15000
}
}
6 changes: 6 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
dist/
node_modules/
pnpm-lock.yaml
*.generated.*
schema/
public/
8 changes: 8 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"semi": true,
"singleQuote": false,
"trailingComma": "es5",
"printWidth": 100,
"tabWidth": 2,
"plugins": ["prettier-plugin-tailwindcss"]
}
129 changes: 129 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- Vitest v4 unit test suite — 48 tests across schemas, utilities, and UI components (SPEC-TEST-001)
- `src/schemas/__tests__/` — auth, account, review schema validation (28 tests)
- `src/lib/__tests__/` — `formError`, `applyServerErrors`, `clearServerErrors` utilities (6 tests)
- `src/components/ui/__tests__/` — `FieldError`, `PasswordStrength` components (14 tests)
- Playwright v1.58 E2E test suite with Page Object Model pattern (SPEC-TEST-001)
- Auth flows: login, register, logout
- Form validation: inline errors, onBlur/onSubmit behaviour
- Account pages: profile update, change password
- Auth fixture with JWT seed via Sylius API (`e2e/fixtures/auth.ts`)
- Docker multi-stage test infrastructure (`docker/Dockerfile.test`) with isolated stages per concern (SPEC-TEST-001)
- `docker/compose.test.yml` — fully self-contained test environment (unit-tests, app-serve, e2e-tests services)
- `docker/compose.yml` — React dev container with hot-reload (node:22-alpine)
- `docker/Dockerfile` — multi-stage app image (dev, builder, production)
- `Makefile` — unified command interface for development, Docker, and all test scenarios
- GitHub Actions CI workflow (`.github/workflows/test.yml`) — unit job (blocking) then E2E job on `main`, `dev`, and `feat/**` branches
- `FieldError` component (`src/components/ui/field-error.tsx`) — accessible inline field error with `id`, `aria-live` (SPEC-UPDATE-001)
- `applyServerErrors` utility — maps Sylius API error payloads to TanStack Form server errors (SPEC-UPDATE-001)
- `clearServerErrors` utility — clears `onServer` errors before re-submission to unblock `canSubmit` (SPEC-UPDATE-001)
- `onBlur` validators on all form fields using the same Zod schemas as `onSubmit` (SPEC-UPDATE-001)
- `aria-describedby` linking all inputs to their `FieldError` component (SPEC-UPDATE-001)

### Changed

- All form fields updated with `aria-invalid` driven by TanStack Form field state (SPEC-UPDATE-001)
- `submitForm()` utility extended to call `clearServerErrors` before submission (SPEC-UPDATE-001)

## [0.4.0] - 2026-03-09

### Added

- `@tanstack/react-form` v1.28.4 and `zod` v3.25.76 as production dependencies (SPEC-REFACTOR-001)
- `src/schemas/` directory with centralized Zod schemas: `auth.ts`, `address.ts`, `account.ts`, `review.ts`, `index.ts`
- `formError()` utility in `src/lib/utils.ts` — safely extracts error message from TanStack Form v1 error values (handles both Zod `ZodIssue` objects and plain strings)
- `noValidate` attribute on all form elements — disables browser-native HTML5 validation in favour of TanStack Form inline errors
- `aria-invalid` attribute on all validated inputs and `SelectTrigger` components across 10 form pages (accessibility improvement)
- Form-level pre-fill timing guard (`canInitialize`) on `AddressPage` — waits for async customer/order data before populating form fields

### Changed

- All 10 form pages migrated from raw `useState` to TanStack Form `useForm` + `form.Field` render-prop pattern (SPEC-REFACTOR-001)
- Auth pages: `LoginPage`, `RegisterPage`, `ForgotPasswordPage`, `ResetPasswordPage`
- Account pages: `ProfilePage`, `ChangePasswordPage`, `AddAddressPage`, `EditAddressPage`
- Checkout: `AddressPage`
- Product: `AddReviewPage`
- `AddressForm` refactored to receive TanStack Form field API via render-prop — parent `useForm` instance now controls validation and submission for account address pages
- `AddressPage` nested address fields (`billingAddress.*`, `shippingAddress.*`) validated via form-level `validators.onSubmit` using `addressSchema.safeParse()` with `{ fields: {} }` error map format
- `RegisterPage` password strength indicator and show/hide toggles preserved; strength score computed via `useMemo` from `useStore`-subscribed password value
- Zod schemas replace all hand-written `if` checks, `validateAddress()` function, and `Record<string, string>` form data objects; TypeScript types derived via `z.infer<>` enforce type safety between form values and API payloads

### Removed

- `validateAddress()` ad-hoc validation function (replaced by `addressSchema`)
- All `useState`-based manual field tracking and error state across migrated pages
- `@tanstack/zod-form-adapter` runtime dependency (TanStack Form v1 uses native StandardSchema — adapter installed but not used)

## [0.3.0] - 2026-03-01

### Added

- Prettier v3 with `prettier-plugin-tailwindcss` for automatic Tailwind class sorting
- Husky v9 pre-commit git hook running lint-staged automatically
- lint-staged: runs `eslint --fix` + `prettier --write` on staged `.ts/.tsx` files
- `.editorconfig` for consistent editor settings (UTF-8, LF, 2-space indent)
- `pnpm format` script for manual full-codebase formatting

### Changed

- ESLint config updated: added `eslint-config-prettier` (disables formatting rules conflicting with Prettier)
- ESLint config: `react-refresh/only-export-components` disabled for `src/components/ui/` and `src/context/` (legitimate multi-export pattern)
- `react-hooks/exhaustive-deps` warnings fixed in `ProductList.tsx` and `ProductPage.tsx` by moving fetch functions inside `useEffect`/`useCallback`
- Entire codebase reformatted with Prettier baseline (formatting-only, no logic changes)

## [0.2.0] - 2026-03-01

### Added

- TailwindCSS v4 via `@tailwindcss/vite` Vite plugin
- shadcn/ui component library with Base UI (`base-vega` style)
- New UI components: `Button`, `Input`, `Textarea`, `Select`, `Table`, `Badge`, `Alert`, `Checkbox`, `Accordion`, `Breadcrumb`, `Card`, `Sheet`, `NavigationMenu`, `DropdownMenu`, `Separator`, `Label`, `Sonner` toasts
- `@base-ui/react` as the primitives layer (replaces Radix UI)
- Mobile navigation via shadcn/ui `Sheet` component (React-controlled, replaces Bootstrap offcanvas)
- Desktop navigation via shadcn/ui `NavigationMenu` with hover dropdowns
- Flash messages replaced by Sonner toast notifications
- `input-group`, `navigation-menu`, `separator`, `textarea` shadcn/ui components added
- `@theme` block with brand color token `--color-primary: #22B99A` and Bootstrap-compatible `--breakpoint-lg: 992px`
- `.link-reset` utility class ported to Tailwind `@layer components`
- Proper TypeScript types for cart/order product rows (removes all `any` types)
- pnpm as the package manager

### Changed

- All UI styling migrated from Bootstrap 5 to TailwindCSS v4
- All native HTML elements (`<input>`, `<button>`, `<select>`, `<table>`, `<textarea>`, `<input type="checkbox">`) replaced with shadcn/ui components
- Navbar fully migrated to shadcn/ui Sheet (mobile) + NavigationMenu (desktop)
- Bootstrap grid classes replaced with Tailwind equivalents
- ESLint configuration updated to flat config (`eslint.config.js`) with TypeScript and React plugins
- `schema/` directory excluded from ESLint to avoid linting auto-generated files
- `catch (err: any)` patterns replaced with `catch (err: unknown)` for type safety

### Removed

- Bootstrap 5 package and all Bootstrap CSS/JS imports
- `@types/bootstrap` package
- `sass` package and all SCSS files (`main.scss`)
- `@radix-ui/react-*` packages (replaced by `@base-ui/react`)
- `FlashMessages.tsx` component (replaced by Sonner)
- All `data-bs-*` HTML attributes
- All Bootstrap class names (`btn-*`, `col-*`, `form-control`, `d-flex`, etc.)

## [0.1.0] - 2025-01-01

### Added

- Initial headless Sylius frontend implementation
- Product listing, product detail, cart, checkout, and account pages
- TanStack Query for data fetching
- React Router for client-side navigation
- TypeScript support
Loading