('asc');
+```
+
+**Key Functions:**
+
+- `fetchProducts()` - Retrieves all products with supplier details
+- `fetchSuppliers()` - Retrieves all suppliers
+- `handleSort(field)` - Toggles column sorting
+- Delete handler - Inline with confirmation
+
+**Sorting:**
+
+Click column headers to sort:
+- First click: ascending
+- Second click: descending
+- Visual indicator: `β` (asc), `β` (desc), `β` (unsorted)
+
+**Protection:**
+
+```typescript
+if (!isAdmin) {
+ return ;
+}
+```
+
+**Usage:**
+
+```typescript
+} />
+```
+
+**Table Columns:**
+- Name (sortable)
+- Supplier (sortable)
+- Price (sortable)
+- SKU (sortable)
+- Unit (sortable)
+- Discount (display only)
+- Description (truncated)
+- Actions (Edit/Delete buttons)
+
+**CRUD Operations:**
+
+**Create:**
+```typescript
+
+```
+
+**Update:**
+```typescript
+
+```
+
+**Delete:**
+```typescript
+
+```
+
+---
+
+## Component Best Practices
+
+### General Guidelines
+
+1. **Use TypeScript Interfaces**: Define props and state types explicitly
+2. **Theme Awareness**: Use `useTheme()` for consistent theming
+3. **Accessibility**: Include ARIA labels where appropriate
+4. **Responsive Design**: Use Tailwind's responsive classes
+5. **Error Handling**: Display user-friendly error messages
+6. **Loading States**: Show loading indicators during async operations
+
+### Example Component Template
+
+```typescript
+import { useTheme } from '../context/ThemeContext';
+
+interface MyComponentProps {
+ title: string;
+ onAction: () => void;
+}
+
+export default function MyComponent({ title, onAction }: MyComponentProps) {
+ const { darkMode } = useTheme();
+
+ return (
+
+
{title}
+
+
+ );
+}
+```
+
+### Common Patterns
+
+**Loading State:**
+```typescript
+if (isLoading) {
+ return (
+
+ );
+}
+```
+
+**Error State:**
+```typescript
+if (error) {
+ return (
+
+ Failed to load data. Please try again.
+
+ );
+}
+```
+
+**Empty State:**
+```typescript
+if (!data || data.length === 0) {
+ return (
+
+ );
+}
+```
+
+---
+
+## Adding New Components
+
+When creating a new component:
+
+1. **Create the file** in the appropriate directory:
+ - Layout components β `src/components/`
+ - Entity components β `src/components/entity/[entity-name]/`
+ - Admin components β `src/components/admin/`
+
+2. **Define TypeScript interfaces** for props and local types
+
+3. **Use hooks for state and context**:
+ ```typescript
+ const { darkMode } = useTheme();
+ const [localState, setLocalState] = useState(initialValue);
+ ```
+
+4. **Follow naming conventions**:
+ - Component file: `PascalCase.tsx`
+ - Variables/functions: `camelCase`
+ - Constants: `UPPER_SNAKE_CASE`
+
+5. **Include accessibility attributes**:
+ - `aria-label` for buttons/inputs without visible labels
+ - `role` for semantic regions
+ - Proper heading hierarchy
+
+6. **Add to routing** (if it's a page component):
+ ```typescript
+ } />
+ ```
+
+7. **Update documentation** - Add entry to this file!
diff --git a/docs/frontend/setup.md b/docs/frontend/setup.md
new file mode 100644
index 0000000..a928d30
--- /dev/null
+++ b/docs/frontend/setup.md
@@ -0,0 +1,493 @@
+# Setup and Development
+
+This guide covers everything you need to get the frontend application up and running.
+
+## Prerequisites
+
+### Required Software
+
+- **Node.js**: Version 18.x or higher
+ ```bash
+ node --version # Should be >= 18.0.0
+ ```
+- **npm**: Version 9.x or higher (comes with Node.js)
+ ```bash
+ npm --version
+ ```
+
+### Optional Tools
+
+- **Git**: For version control
+- **VS Code**: Recommended editor with these extensions:
+ - ESLint
+ - Prettier
+ - Tailwind CSS IntelliSense
+ - TypeScript Vue Plugin (Volar)
+
+## Installation
+
+### Clone the Repository
+
+```bash
+git clone https://github.com/webmaxru/copilot_agent_mode.git
+cd copilot_agent_mode
+```
+
+### Install Dependencies
+
+From the project root:
+
+```bash
+# Install all workspace dependencies (recommended)
+npm install
+
+# Or install only frontend dependencies
+cd frontend
+npm install
+```
+
+This installs:
+- React and React DOM
+- React Router
+- React Query
+- Axios
+- Tailwind CSS
+- Vite
+- TypeScript
+- ESLint
+- Testing libraries (Vitest, React Testing Library)
+
+## Environment Configuration
+
+### API URL Configuration
+
+The frontend automatically detects the API URL based on the environment:
+
+1. **Runtime Configuration** (Docker/Production):
+ - Set `window.RUNTIME_CONFIG.API_URL` in `public/runtime-config.js`
+
+2. **GitHub Codespaces**:
+ - Automatically detected and configured
+ - Maps to port 3000 on your codespace
+
+3. **Local Development**:
+ - Defaults to `http://localhost:3000`
+ - Matches protocol of frontend (http/https)
+
+### Custom API URL
+
+To override the API URL for local development:
+
+1. Create `public/runtime-config.js`:
+ ```javascript
+ window.RUNTIME_CONFIG = {
+ API_URL: 'http://your-custom-api:3000'
+ };
+ ```
+
+2. Include in `index.html`:
+ ```html
+
+ ```
+
+### Environment Variables
+
+Vite environment variables can be defined in `.env` files:
+
+```bash
+# .env.local (not committed to git)
+VITE_API_URL=http://localhost:3000
+```
+
+Access in code:
+```typescript
+const apiUrl = import.meta.env.VITE_API_URL;
+```
+
+## Development Server
+
+### Start the Development Server
+
+```bash
+cd frontend
+npm run dev
+```
+
+The server starts on `http://localhost:5137` by default.
+
+**Output:**
+```
+ VITE v6.2.0 ready in 234 ms
+
+ β Local: http://localhost:5137/
+ β Network: http://192.168.1.100:5137/
+ β press h + enter to show help
+```
+
+### Development Server Features
+
+- **Hot Module Replacement (HMR)**: Changes reflected instantly
+- **Fast Refresh**: Preserves component state during edits
+- **Source Maps**: Original TypeScript code in browser devtools
+- **Error Overlay**: Build errors displayed in browser
+
+### Running with Backend
+
+To run the full stack locally:
+
+```bash
+# Terminal 1: Start the API
+cd api
+npm run dev
+
+# Terminal 2: Start the frontend
+cd frontend
+npm run dev
+```
+
+Or use the convenience script from project root:
+
+```bash
+npm run dev # Starts both frontend and backend
+```
+
+## Build Process
+
+### Development Build
+
+For development with optimizations disabled:
+
+```bash
+npm run dev
+```
+
+### Production Build
+
+```bash
+npm run build
+```
+
+This process:
+1. **Type checks** with TypeScript compiler (`tsc -b`)
+2. **Bundles** code with Vite
+3. **Minifies** JavaScript and CSS
+4. **Optimizes** assets
+5. **Outputs** to `dist/` directory
+
+**Build Output:**
+```
+dist/
+βββ assets/
+β βββ index-[hash].js
+β βββ index-[hash].css
+β βββ [images]
+βββ index.html
+βββ vite.svg
+```
+
+### Preview Production Build
+
+Test the production build locally:
+
+```bash
+npm run preview
+```
+
+Serves the `dist/` folder on `http://localhost:4173`
+
+## Linting
+
+### Run ESLint
+
+```bash
+npm run lint
+```
+
+Checks TypeScript and TSX files for:
+- Code quality issues
+- TypeScript errors
+- React best practices
+- Accessibility issues
+
+### ESLint Configuration
+
+Located in `eslint.config.js`:
+- TypeScript ESLint rules
+- React Hooks rules
+- React Refresh rules
+
+### Auto-fix Issues
+
+```bash
+npm run lint -- --fix
+```
+
+## Code Formatting
+
+### Prettier (Recommended)
+
+While not included by default, Prettier is recommended:
+
+```bash
+# Install Prettier
+npm install -D prettier
+
+# Create .prettierrc
+echo '{ "semi": true, "singleQuote": true }' > .prettierrc
+
+# Format code
+npx prettier --write "src/**/*.{ts,tsx,css}"
+```
+
+## Testing
+
+### Test Configuration
+
+Testing setup uses:
+- **Vitest**: Fast unit test runner (Vite-native)
+- **React Testing Library**: Component testing utilities
+- **jsdom**: DOM implementation for Node.js
+- **@testing-library/jest-dom**: Additional matchers
+
+### Run Tests
+
+```bash
+# Run all tests
+npm run test
+
+# Run tests in watch mode
+npm run test:watch
+
+# Run tests with coverage
+npm run test:coverage
+```
+
+### Test File Location
+
+Place tests next to the components they test:
+
+```
+components/
+βββ ProductCard.tsx
+βββ ProductCard.test.tsx
+```
+
+Or in a `__tests__` directory:
+
+```
+components/
+βββ ProductCard.tsx
+βββ __tests__/
+ βββ ProductCard.test.tsx
+```
+
+### Example Test
+
+```typescript
+import { render, screen } from '@testing-library/react';
+import ProductCard from './ProductCard';
+
+test('renders product name', () => {
+ const product = { id: 1, name: 'Test Product', price: 10 };
+ render();
+ expect(screen.getByText('Test Product')).toBeInTheDocument();
+});
+```
+
+## Docker Development
+
+### Build Docker Image
+
+```bash
+cd frontend
+docker build -t octocat-frontend .
+```
+
+### Run in Container
+
+```bash
+docker run -p 5137:80 octocat-frontend
+```
+
+Access at `http://localhost:5137`
+
+### Docker Compose
+
+From project root:
+
+```bash
+docker-compose up
+```
+
+Starts both frontend and backend services.
+
+## IDE Setup
+
+### VS Code Configuration
+
+Recommended `.vscode/settings.json`:
+
+```json
+{
+ "editor.formatOnSave": true,
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": true
+ },
+ "typescript.tsdk": "node_modules/typescript/lib",
+ "tailwindCSS.experimental.classRegex": [
+ ["clsx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"]
+ ]
+}
+```
+
+### Recommended Extensions
+
+- **ESLint** (dbaeumer.vscode-eslint)
+- **Prettier** (esbenp.prettier-vscode)
+- **Tailwind CSS IntelliSense** (bradlc.vscode-tailwindcss)
+- **TypeScript Vue Plugin** (Vue.volar)
+- **Path Intellisense** (christian-kohler.path-intellisense)
+
+## Troubleshooting
+
+### Port Already in Use
+
+If port 5137 is in use:
+
+```bash
+# Change port in vite.config.ts
+server: {
+ port: 3001, // Use different port
+}
+```
+
+### API Connection Issues
+
+1. Verify backend is running on port 3000
+2. Check browser console for CORS errors
+3. Verify API URL in `src/api/config.ts`
+
+```typescript
+console.log('API Base URL:', API_BASE_URL);
+```
+
+### Module Not Found Errors
+
+Clear node_modules and reinstall:
+
+```bash
+rm -rf node_modules package-lock.json
+npm install
+```
+
+### TypeScript Errors
+
+Restart TypeScript server in VS Code:
+- Press `Cmd/Ctrl + Shift + P`
+- Type "TypeScript: Restart TS Server"
+- Press Enter
+
+### Vite Cache Issues
+
+Clear Vite cache:
+
+```bash
+rm -rf node_modules/.vite
+npm run dev
+```
+
+### Build Failures
+
+Check TypeScript errors:
+
+```bash
+npx tsc --noEmit
+```
+
+### Hot Reload Not Working
+
+1. Check file watchers limit (Linux):
+ ```bash
+ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
+ sudo sysctl -p
+ ```
+
+2. Ensure files are in `src/` directory
+3. Restart dev server
+
+## Development Workflow
+
+### Typical Development Flow
+
+1. **Start dev server**: `npm run dev`
+2. **Make changes**: Edit files in `src/`
+3. **View changes**: Browser updates automatically
+4. **Check console**: Look for errors/warnings
+5. **Run linter**: `npm run lint` before committing
+6. **Test changes**: `npm run test`
+7. **Commit code**: Git commit with meaningful message
+
+### Before Committing
+
+```bash
+# Run linter
+npm run lint
+
+# Fix auto-fixable issues
+npm run lint -- --fix
+
+# Run tests
+npm run test
+
+# Build to verify production works
+npm run build
+```
+
+### Branch Strategy
+
+- `main` - Production-ready code
+- `develop` - Integration branch
+- `feature/*` - New features
+- `fix/*` - Bug fixes
+
+## Performance Tips
+
+### Development Performance
+
+- Use Vite's fast HMR instead of full page reload
+- Keep dev tools open for better debugging
+- Use React DevTools for component inspection
+
+### Build Performance
+
+- Vite automatically code-splits routes
+- Images are optimized during build
+- CSS is minified and tree-shaken
+
+## Deployment
+
+See [deployment.md](../../deployment.md) for production deployment instructions.
+
+### Quick Deploy to Vercel
+
+```bash
+npm install -g vercel
+cd frontend
+vercel
+```
+
+### Quick Deploy to Netlify
+
+```bash
+npm install -g netlify-cli
+cd frontend
+netlify deploy --prod --dir=dist
+```
+
+## Next Steps
+
+- Review [Architecture](./architecture.md) to understand app structure
+- Check [Component Documentation](./components.md) for component details
+- Read [Styling Guidelines](./styling.md) for Tailwind conventions
+- Learn about [API Integration](./api-integration.md) patterns
diff --git a/docs/frontend/styling.md b/docs/frontend/styling.md
new file mode 100644
index 0000000..326166d
--- /dev/null
+++ b/docs/frontend/styling.md
@@ -0,0 +1,719 @@
+# Styling Guidelines
+
+This guide covers the styling conventions, Tailwind CSS usage, theme system, and responsive design approach in the OctoCAT Supply frontend.
+
+## Table of Contents
+
+- [Tailwind CSS Overview](#tailwind-css-overview)
+- [Theme System](#theme-system)
+- [Color Palette](#color-palette)
+- [Typography](#typography)
+- [Spacing and Layout](#spacing-and-layout)
+- [Responsive Design](#responsive-design)
+- [Component Styling Patterns](#component-styling-patterns)
+- [Transitions and Animations](#transitions-and-animations)
+- [Best Practices](#best-practices)
+
+---
+
+## Tailwind CSS Overview
+
+The application uses Tailwind CSS, a utility-first CSS framework. Styles are applied using utility classes directly in JSX/TSX.
+
+### Configuration
+
+**Location:** `tailwind.config.js`
+
+**Content Sources:**
+```javascript
+content: [
+ "./index.html",
+ "./src/**/*.{js,ts,jsx,tsx}",
+]
+```
+
+### Key Benefits
+
+- **No CSS file bloat** - Only used utilities are included in production
+- **Consistent design** - Predefined scale for spacing, colors, etc.
+- **Responsive by default** - Easy breakpoint-based styling
+- **Dark mode support** - Built-in with class strategy
+
+---
+
+## Theme System
+
+### Dark Mode Implementation
+
+The app uses Tailwind's class-based dark mode strategy:
+
+**Configuration:**
+```javascript
+// tailwind.config.js
+darkMode: 'class'
+```
+
+**How It Works:**
+
+1. ThemeContext manages `darkMode` state (boolean)
+2. Theme preference saved to `localStorage`
+3. `'dark'` or `'light'` class applied to `` element
+4. Components use conditional classes based on theme
+
+**Example:**
+
+```typescript
+const { darkMode } = useTheme();
+
+
+ Content
+
+```
+
+**Alternative Syntax:**
+
+Use Tailwind's `dark:` variant for inline conditional styling:
+
+```typescript
+
+ Content
+
+```
+
+### When to Use Each Approach
+
+**Conditional Classes** (Recommended for this project):
+```typescript
+className={darkMode ? 'bg-dark' : 'bg-white'}
+```
+- More explicit control
+- Easier to read complex conditions
+- Consistent with existing codebase
+
+**Dark Variant** (Alternative):
+```typescript
+className="bg-white dark:bg-dark"
+```
+- More concise
+- Leverages Tailwind's built-in dark mode
+- Good for simple color swaps
+
+---
+
+## Color Palette
+
+### Custom Colors
+
+**Location:** `tailwind.config.js` β `theme.extend.colors`
+
+```javascript
+colors: {
+ 'primary': '#76B852', // Green - Primary brand color
+ 'dark': '#0A0A0A', // Very dark gray - Dark mode background
+ 'light': '#F5F5F5', // Off-white - Light mode background/text
+ 'accent': '#8BC34A', // Light green - Accent/hover states
+ 'gray': { // Extended gray scale
+ 100: '#f5f5f5',
+ 200: '#e5e5e5',
+ 300: '#d4d4d4',
+ 400: '#a3a3a3',
+ 500: '#737373',
+ 600: '#525252',
+ 700: '#404040',
+ 800: '#262626',
+ 900: '#171717',
+ },
+}
+```
+
+### Color Usage Guidelines
+
+**Primary (`primary`):**
+- Buttons, CTAs
+- Links hover states
+- Brand elements
+- Active navigation items
+
+**Accent (`accent`):**
+- Hover states for primary buttons
+- Secondary CTAs
+- Highlights
+
+**Dark (`dark`):**
+- Dark mode backgrounds
+- Dark mode containers
+
+**Light (`light`):**
+- Dark mode text
+- Light mode backgrounds (as alternative to white)
+
+**Gray Scale:**
+- Borders: `gray-200` (light), `gray-700` (dark)
+- Text: `gray-600` to `gray-800` (light mode), `gray-300` to `gray-400` (dark mode)
+- Backgrounds: `gray-100` (light mode), `gray-800` (dark mode)
+
+### Color Accessibility
+
+- Ensure sufficient contrast ratios (WCAG AA: 4.5:1 for text)
+- Primary green on white: β
Passes
+- Light text on dark: β
Passes
+- Test combinations with tools like [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)
+
+---
+
+## Typography
+
+### Font Family
+
+Uses system font stack (default Tailwind):
+- San Francisco (macOS)
+- Segoe UI (Windows)
+- Roboto (Android)
+- Fallback to sans-serif
+
+### Font Sizes
+
+Use Tailwind's text size utilities:
+
+```typescript
+ {/* 30px */}
+ {/* 24px */}
+ {/* 20px */}
+
{/* 16px - default */}
+ {/* 14px */}
+ {/* 12px */}
+```
+
+### Font Weights
+
+```typescript
+ {/* 400 */}
+ {/* 500 */}
+ {/* 600 */}
+ {/* 700 */}
+```
+
+### Typography Patterns
+
+**Page Headings:**
+```typescript
+
+ Page Title
+
+```
+
+**Section Headings:**
+```typescript
+
+ Section Title
+
+```
+
+**Body Text:**
+```typescript
+
+ Body content goes here.
+
+```
+
+**Labels:**
+```typescript
+
+```
+
+---
+
+## Spacing and Layout
+
+### Spacing Scale
+
+Tailwind uses a consistent spacing scale (0.25rem = 4px increments):
+
+```typescript
+p-1 // padding: 0.25rem (4px)
+p-2 // padding: 0.5rem (8px)
+p-4 // padding: 1rem (16px)
+p-6 // padding: 1.5rem (24px)
+p-8 // padding: 2rem (32px)
+p-12 // padding: 3rem (48px)
+```
+
+### Common Layout Patterns
+
+**Page Container:**
+```typescript
+
+ {/* Content */}
+
+```
+
+**Card/Container:**
+```typescript
+
+ {/* Card content */}
+
+```
+
+**Full Height Page:**
+```typescript
+
+ {/* Account for fixed nav (pt-20) and footer */}
+
+```
+
+**Flex Container:**
+```typescript
+
+
Left content
+
Right content
+
+```
+
+**Grid Layout:**
+```typescript
+
+ {/* Grid items */}
+
+```
+
+---
+
+## Responsive Design
+
+### Breakpoints
+
+Tailwind default breakpoints used in this project:
+
+| Prefix | Min Width | Description |
+|--------|-----------|-------------|
+| `sm:` | 640px | Small devices (landscape phones) |
+| `md:` | 768px | Medium devices (tablets) |
+| `lg:` | 1024px | Large devices (laptops) |
+| `xl:` | 1280px | Extra large devices (desktops) |
+| `2xl:` | 1536px | 2X large devices (large desktops) |
+
+### Mobile-First Approach
+
+Base styles apply to mobile, then override for larger screens:
+
+```typescript
+
+ {/* 1 col on mobile, 2 on sm, 3 on md, 4 on lg+ */}
+
+```
+
+### Responsive Patterns
+
+**Show/Hide Elements:**
+```typescript
+
+ Desktop only
+
+
+
+ Mobile only
+
+```
+
+**Responsive Text Size:**
+```typescript
+
+ Responsive Heading
+
+```
+
+**Responsive Spacing:**
+```typescript
+
+ Content with responsive padding
+
+```
+
+**Responsive Flex Direction:**
+```typescript
+
+```
+
+### Product Grid Example
+
+```typescript
+
+ {products.map(product => (
+
+ ))}
+
+```
+
+Results in:
+- Mobile: 1 column
+- Small (β₯640px): 2 columns
+- Medium (β₯768px): 3 columns
+- Large (β₯1024px): 4 columns
+
+---
+
+## Component Styling Patterns
+
+### Button Styles
+
+**Primary Button:**
+```typescript
+
+```
+
+**Secondary Button:**
+```typescript
+
+```
+
+**Danger Button:**
+```typescript
+
+```
+
+**Disabled Button:**
+```typescript
+
+```
+
+### Input Styles
+
+**Text Input:**
+```typescript
+
+```
+
+**Textarea:**
+```typescript
+
+```
+
+**Select:**
+```typescript
+
+```
+
+### Card Styles
+
+**Basic Card:**
+```typescript
+
+
+ Card Title
+
+
+ Card content
+
+
+```
+
+**Hover Card:**
+```typescript
+
+ {/* Card content */}
+
+```
+
+### Modal Styles
+
+```typescript
+{/* Overlay */}
+
+ {/* Modal */}
+
+ {/* Modal content */}
+
+
+```
+
+### Table Styles
+
+```typescript
+
+
+
+ |
+ Column
+ |
+
+
+
+
+ |
+ Data
+ |
+
+
+
+```
+
+---
+
+## Transitions and Animations
+
+### Transition Duration
+
+Standard transition: **300ms**
+
+```typescript
+className="transition-colors duration-300"
+```
+
+### Common Transitions
+
+**Color Transitions:**
+```typescript
+className="transition-colors duration-300"
+```
+
+**All Properties:**
+```typescript
+className="transition-all duration-300"
+```
+
+**Transform + Shadow:**
+```typescript
+className="transform transition-all duration-300 hover:scale-105"
+```
+
+### Loading Spinner
+
+```typescript
+
+```
+
+### Hover Effects
+
+**Scale:**
+```typescript
+className="transform hover:scale-105 transition-transform duration-300"
+```
+
+**Glow:**
+```typescript
+className="hover:shadow-[0_0_25px_rgba(118,184,82,0.3)] transition-shadow duration-300"
+```
+
+**Color Change:**
+```typescript
+className="text-gray-700 hover:text-primary transition-colors duration-300"
+```
+
+---
+
+## Best Practices
+
+### 1. Consistency
+
+- Use the defined color palette consistently
+- Stick to standard spacing scale (4, 8, 12, 16, 24, 32, 48px)
+- Maintain consistent border radius (usually `rounded` or `rounded-lg`)
+- Use consistent shadow levels
+
+### 2. Theme Awareness
+
+Always make components theme-aware:
+
+```typescript
+const { darkMode } = useTheme();
+
+
+```
+
+### 3. Transitions
+
+Add smooth transitions for better UX:
+
+```typescript
+className="transition-colors duration-300"
+```
+
+### 4. Responsive Design
+
+Test at common breakpoints:
+- Mobile: 375px, 414px
+- Tablet: 768px, 1024px
+- Desktop: 1280px, 1920px
+
+### 5. Accessibility
+
+- Maintain color contrast ratios
+- Don't rely solely on color to convey information
+- Use semantic HTML with Tailwind classes
+- Test keyboard navigation
+
+### 6. Performance
+
+- Tailwind purges unused CSS in production
+- Avoid inline styles; use Tailwind utilities
+- Use `@apply` directive sparingly (prefer utilities in JSX)
+
+### 7. Avoid Magic Numbers
+
+Use Tailwind's scale, not arbitrary values:
+
+β Bad:
+```typescript
+className="p-[23px] text-[17px]"
+```
+
+β
Good:
+```typescript
+className="p-6 text-lg"
+```
+
+### 8. Group Related Classes
+
+Order classes logically:
+
+```typescript
+className="
+ flex items-center justify-between // Layout
+ px-4 py-2 mb-4 // Spacing
+ bg-primary text-white // Colors
+ rounded-lg shadow-md // Appearance
+ hover:bg-accent // Interactions
+ transition-colors duration-300 // Animations
+"
+```
+
+### 9. Component Class Reusability
+
+For frequently repeated class combinations, consider extracting:
+
+```typescript
+const cardClasses = `
+ ${darkMode ? 'bg-gray-800' : 'bg-white'}
+ rounded-lg shadow-lg p-6
+ transition-colors duration-300
+`;
+
+
+ {/* Content */}
+
+```
+
+### 10. Custom Tailwind Extensions
+
+Only add to `tailwind.config.js` when truly needed:
+- New colors that are project-wide
+- Custom spacing values (e.g., `width: 7/8` for specific layout needs)
+- Custom breakpoints (avoid; use defaults)
+
+---
+
+## Common Pitfalls
+
+### β Hardcoded Colors
+
+Don't use arbitrary color values:
+```typescript
+className="bg-[#76B852]" // Bad
+```
+
+Use named colors:
+```typescript
+className="bg-primary" // Good
+```
+
+### β Forgetting Dark Mode
+
+```typescript
+
// Missing dark mode
+```
+
+Always consider theme:
+```typescript
+
+```
+
+### β Inconsistent Spacing
+
+```typescript
+
// Inconsistent
+```
+
+Use standard scale:
+```typescript
+
// Consistent
+```
+
+### β Responsive Class Order
+
+```typescript
+className="lg:flex-row md:flex-col flex-col-reverse" // Wrong order
+```
+
+Correct order (mobile-first):
+```typescript
+className="flex-col-reverse md:flex-col lg:flex-row"
+```
+
+---
+
+## Resources
+
+- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
+- [Tailwind Color Palette](https://tailwindcss.com/docs/customizing-colors)
+- [Tailwind Play (Interactive)](https://play.tailwindcss.com/)
+- [Tailwind UI Components](https://tailwindui.com/)
+
+---
+
+## Quick Reference
+
+### Most Common Classes
+
+```typescript
+// Layout
+flex flex-col items-center justify-between
+grid grid-cols-4 gap-6
+
+// Spacing
+p-4 px-6 py-2 m-4 space-y-4
+
+// Typography
+text-xl font-bold text-gray-800 dark:text-light
+
+// Colors
+bg-primary text-white border-gray-300
+
+// Effects
+rounded-lg shadow-lg hover:shadow-xl
+transition-colors duration-300
+
+// Responsive
+hidden md:block
+grid-cols-1 md:grid-cols-2 lg:grid-cols-4
+```
diff --git a/docs/frontend/testing.md b/docs/frontend/testing.md
new file mode 100644
index 0000000..154b819
--- /dev/null
+++ b/docs/frontend/testing.md
@@ -0,0 +1,719 @@
+# Testing
+
+This guide covers the testing strategy, tools, and patterns for the OctoCAT Supply frontend application.
+
+## Table of Contents
+
+- [Testing Stack](#testing-stack)
+- [Test Structure](#test-structure)
+- [Running Tests](#running-tests)
+- [Unit Testing](#unit-testing)
+- [Component Testing](#component-testing)
+- [Integration Testing](#integration-testing)
+- [Testing Best Practices](#testing-best-practices)
+- [Common Testing Patterns](#common-testing-patterns)
+
+---
+
+## Testing Stack
+
+### Tools and Libraries
+
+The frontend uses the following testing tools:
+
+- **Vitest** - Fast unit test runner (Vite-native, Jest-compatible API)
+- **React Testing Library** - Component testing utilities
+- **jsdom** - DOM implementation for Node.js environment
+- **@testing-library/jest-dom** - Custom matchers for DOM assertions
+- **@testing-library/user-event** - User interaction simulation
+
+### Installation
+
+Already included in `package.json`:
+
+```json
+{
+ "devDependencies": {
+ "@testing-library/jest-dom": "^6.6.3",
+ "@testing-library/react": "^16.3.0",
+ "@testing-library/user-event": "^14.6.1",
+ "jsdom": "^26.0.0",
+ "vitest": "^3.1.1"
+ }
+}
+```
+
+### Configuration
+
+**Vitest Configuration:**
+
+Would typically be in `vite.config.ts` or `vitest.config.ts`:
+
+```typescript
+import { defineConfig } from 'vitest/config';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+ test: {
+ globals: true,
+ environment: 'jsdom',
+ setupFiles: './src/test/setup.ts',
+ },
+});
+```
+
+**Setup File (`src/test/setup.ts`):**
+
+```typescript
+import '@testing-library/jest-dom';
+```
+
+---
+
+## Test Structure
+
+### File Organization
+
+Place test files next to the components they test:
+
+```
+src/
+βββ components/
+β βββ ProductCard.tsx
+β βββ ProductCard.test.tsx
+βββ context/
+β βββ AuthContext.tsx
+β βββ AuthContext.test.tsx
+βββ utils/
+ βββ formatting.ts
+ βββ formatting.test.ts
+```
+
+**Alternative:** Use `__tests__` directory:
+
+```
+src/
+βββ components/
+β βββ ProductCard.tsx
+β βββ __tests__/
+β βββ ProductCard.test.tsx
+```
+
+### Test File Naming
+
+- `ComponentName.test.tsx` - Component tests
+- `ComponentName.spec.tsx` - Alternative (spec)
+- `utils.test.ts` - Utility function tests
+
+---
+
+## Running Tests
+
+### Commands
+
+```bash
+# Run all tests
+npm test
+
+# Run tests in watch mode (re-run on file changes)
+npm run test:watch
+
+# Run tests with coverage report
+npm run test:coverage
+
+# Run specific test file
+npm test -- ProductCard.test.tsx
+
+# Run tests matching pattern
+npm test -- --grep "ProductCard"
+```
+
+### Watch Mode
+
+In watch mode, Vitest provides an interactive menu:
+
+- Press `a` to run all tests
+- Press `f` to run only failed tests
+- Press `p` to filter by filename pattern
+- Press `t` to filter by test name pattern
+- Press `q` to quit
+
+---
+
+## Unit Testing
+
+### Testing Utility Functions
+
+**Example: Currency Formatting**
+
+```typescript
+// src/utils/formatting.ts
+export const formatCurrency = (amount: number): string => {
+ return `$${amount.toFixed(2)}`;
+};
+
+// src/utils/formatting.test.ts
+import { describe, it, expect } from 'vitest';
+import { formatCurrency } from './formatting';
+
+describe('formatCurrency', () => {
+ it('formats whole numbers correctly', () => {
+ expect(formatCurrency(10)).toBe('$10.00');
+ });
+
+ it('formats decimal numbers correctly', () => {
+ expect(formatCurrency(10.5)).toBe('$10.50');
+ });
+
+ it('rounds to two decimal places', () => {
+ expect(formatCurrency(10.999)).toBe('$11.00');
+ });
+
+ it('handles zero correctly', () => {
+ expect(formatCurrency(0)).toBe('$0.00');
+ });
+});
+```
+
+### Testing Context
+
+**Example: AuthContext**
+
+```typescript
+// src/context/AuthContext.test.tsx
+import { renderHook, act } from '@testing-library/react';
+import { AuthProvider, useAuth } from './AuthContext';
+import { describe, it, expect } from 'vitest';
+
+describe('AuthContext', () => {
+ it('initial state is logged out', () => {
+ const { result } = renderHook(() => useAuth(), {
+ wrapper: AuthProvider,
+ });
+
+ expect(result.current.isLoggedIn).toBe(false);
+ expect(result.current.isAdmin).toBe(false);
+ });
+
+ it('logs in user with github.com email as admin', async () => {
+ const { result } = renderHook(() => useAuth(), {
+ wrapper: AuthProvider,
+ });
+
+ await act(async () => {
+ await result.current.login('user@github.com', 'password');
+ });
+
+ expect(result.current.isLoggedIn).toBe(true);
+ expect(result.current.isAdmin).toBe(true);
+ });
+
+ it('logs in non-github user as regular user', async () => {
+ const { result } = renderHook(() => useAuth(), {
+ wrapper: AuthProvider,
+ });
+
+ await act(async () => {
+ await result.current.login('user@example.com', 'password');
+ });
+
+ expect(result.current.isLoggedIn).toBe(true);
+ expect(result.current.isAdmin).toBe(false);
+ });
+
+ it('logs out user', async () => {
+ const { result } = renderHook(() => useAuth(), {
+ wrapper: AuthProvider,
+ });
+
+ await act(async () => {
+ await result.current.login('user@github.com', 'password');
+ });
+
+ act(() => {
+ result.current.logout();
+ });
+
+ expect(result.current.isLoggedIn).toBe(false);
+ expect(result.current.isAdmin).toBe(false);
+ });
+});
+```
+
+---
+
+## Component Testing
+
+### Basic Component Test
+
+```typescript
+// src/components/Welcome.test.tsx
+import { render, screen } from '@testing-library/react';
+import { describe, it, expect } from 'vitest';
+import Welcome from './Welcome';
+
+describe('Welcome', () => {
+ it('renders welcome heading', () => {
+ render(
);
+ expect(screen.getByRole('heading', { name: /welcome/i })).toBeInTheDocument();
+ });
+
+ it('displays call-to-action button', () => {
+ render(
);
+ expect(screen.getByRole('button', { name: /get started/i })).toBeInTheDocument();
+ });
+});
+```
+
+### Testing with Context
+
+```typescript
+// src/components/Navigation.test.tsx
+import { render, screen } from '@testing-library/react';
+import { BrowserRouter } from 'react-router-dom';
+import { AuthProvider } from '../context/AuthContext';
+import { ThemeProvider } from '../context/ThemeContext';
+import Navigation from './Navigation';
+
+const renderWithProviders = (component: React.ReactElement) => {
+ return render(
+
+
+
+ {component}
+
+
+
+ );
+};
+
+describe('Navigation', () => {
+ it('renders logo and brand name', () => {
+ renderWithProviders(
);
+ expect(screen.getByAltText('Copilot icon')).toBeInTheDocument();
+ expect(screen.getByText('OctoCAT Supply')).toBeInTheDocument();
+ });
+
+ it('shows login button when not authenticated', () => {
+ renderWithProviders(
);
+ expect(screen.getByText(/login/i)).toBeInTheDocument();
+ });
+});
+```
+
+### Testing User Interactions
+
+```typescript
+// src/components/ProductCard.test.tsx
+import { render, screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import { describe, it, expect, vi } from 'vitest';
+import ProductCard from './ProductCard';
+
+describe('ProductCard', () => {
+ const mockProduct = {
+ productId: 1,
+ name: 'Test Product',
+ description: 'Test description',
+ price: 29.99,
+ imgName: 'test.png',
+ sku: 'TEST-001',
+ unit: 'unit',
+ supplierId: 1,
+ };
+
+ it('renders product information', () => {
+ render(
);
+
+ expect(screen.getByText('Test Product')).toBeInTheDocument();
+ expect(screen.getByText('Test description')).toBeInTheDocument();
+ expect(screen.getByText('$29.99')).toBeInTheDocument();
+ });
+
+ it('increments quantity when plus button clicked', async () => {
+ const user = userEvent.setup();
+ render(
);
+
+ const plusButton = screen.getByLabelText(`Increase quantity of ${mockProduct.name}`);
+ await user.click(plusButton);
+
+ expect(screen.getByLabelText(`Quantity of ${mockProduct.name}`)).toHaveTextContent('1');
+ });
+
+ it('decrements quantity when minus button clicked', async () => {
+ const user = userEvent.setup();
+ render(
);
+
+ // First increment to 1
+ const plusButton = screen.getByLabelText(`Increase quantity of ${mockProduct.name}`);
+ await user.click(plusButton);
+
+ // Then decrement
+ const minusButton = screen.getByLabelText(`Decrease quantity of ${mockProduct.name}`);
+ await user.click(minusButton);
+
+ expect(screen.getByLabelText(`Quantity of ${mockProduct.name}`)).toHaveTextContent('0');
+ });
+
+ it('calls onAddToCart when add to cart button clicked', async () => {
+ const user = userEvent.setup();
+ const onAddToCart = vi.fn();
+ render(
);
+
+ // Increment quantity
+ const plusButton = screen.getByLabelText(`Increase quantity of ${mockProduct.name}`);
+ await user.click(plusButton);
+
+ // Click add to cart
+ const addButton = screen.getByRole('button', { name: /add to cart/i });
+ await user.click(addButton);
+
+ expect(onAddToCart).toHaveBeenCalledWith(mockProduct.productId, 1);
+ });
+});
+```
+
+### Testing Forms
+
+```typescript
+// src/components/Login.test.tsx
+import { render, screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import { describe, it, expect, vi } from 'vitest';
+import Login from './Login';
+
+describe('Login', () => {
+ it('submits form with email and password', async () => {
+ const user = userEvent.setup();
+ const onLogin = vi.fn();
+ render(
);
+
+ // Fill in form
+ await user.type(screen.getByLabelText(/email/i), 'test@example.com');
+ await user.type(screen.getByLabelText(/password/i), 'password123');
+
+ // Submit
+ await user.click(screen.getByRole('button', { name: /login/i }));
+
+ expect(onLogin).toHaveBeenCalledWith('test@example.com', 'password123');
+ });
+
+ it('shows validation error for empty email', async () => {
+ const user = userEvent.setup();
+ render(
);
+
+ await user.click(screen.getByRole('button', { name: /login/i }));
+
+ expect(screen.getByText(/email is required/i)).toBeInTheDocument();
+ });
+});
+```
+
+---
+
+## Integration Testing
+
+### Testing with API Mocking
+
+```typescript
+// src/components/Products.test.tsx
+import { render, screen, waitFor } from '@testing-library/react';
+import { QueryClient, QueryClientProvider } from 'react-query';
+import { describe, it, expect, vi, beforeEach } from 'vitest';
+import axios from 'axios';
+import Products from './Products';
+
+// Mock axios
+vi.mock('axios');
+const mockedAxios = axios as jest.Mocked
;
+
+describe('Products', () => {
+ const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: { retry: false },
+ },
+ });
+
+ const wrapper = ({ children }: { children: React.ReactNode }) => (
+
+ {children}
+
+ );
+
+ beforeEach(() => {
+ queryClient.clear();
+ });
+
+ it('displays loading state initially', () => {
+ mockedAxios.get.mockImplementation(() => new Promise(() => {}));
+ render(, { wrapper });
+
+ expect(screen.getByRole('status')).toBeInTheDocument();
+ });
+
+ it('displays products after loading', async () => {
+ const mockProducts = [
+ { productId: 1, name: 'Product 1', price: 10.99 },
+ { productId: 2, name: 'Product 2', price: 20.99 },
+ ];
+
+ mockedAxios.get.mockResolvedValueOnce({ data: mockProducts });
+
+ render(, { wrapper });
+
+ await waitFor(() => {
+ expect(screen.getByText('Product 1')).toBeInTheDocument();
+ expect(screen.getByText('Product 2')).toBeInTheDocument();
+ });
+ });
+
+ it('displays error message on fetch failure', async () => {
+ mockedAxios.get.mockRejectedValueOnce(new Error('Network error'));
+
+ render(, { wrapper });
+
+ await waitFor(() => {
+ expect(screen.getByText(/failed to fetch products/i)).toBeInTheDocument();
+ });
+ });
+});
+```
+
+---
+
+## Testing Best Practices
+
+### 1. Test Behavior, Not Implementation
+
+β **Bad:**
+```typescript
+it('updates state when button clicked', () => {
+ // Testing internal state
+ expect(component.state.count).toBe(1);
+});
+```
+
+β
**Good:**
+```typescript
+it('displays incremented count when button clicked', () => {
+ // Testing visible output
+ expect(screen.getByText('Count: 1')).toBeInTheDocument();
+});
+```
+
+### 2. Use Accessible Queries
+
+Prefer queries in this order:
+1. `getByRole` - Most accessible
+2. `getByLabelText` - For form elements
+3. `getByPlaceholderText` - For inputs
+4. `getByText` - For content
+5. `getByTestId` - Last resort
+
+β **Avoid:**
+```typescript
+const button = container.querySelector('.submit-button');
+```
+
+β
**Prefer:**
+```typescript
+const button = screen.getByRole('button', { name: /submit/i });
+```
+
+### 3. Don't Test External Libraries
+
+Don't test that React Router or Axios workβthey're already tested.
+
+β **Bad:**
+```typescript
+it('React Router navigates correctly', () => {
+ // Testing React Router, not your code
+});
+```
+
+β
**Good:**
+```typescript
+it('redirects to login when not authenticated', () => {
+ // Testing your auth logic
+});
+```
+
+### 4. Keep Tests Independent
+
+Each test should be able to run in isolation.
+
+β
**Good:**
+```typescript
+describe('Counter', () => {
+ beforeEach(() => {
+ // Reset state before each test
+ });
+
+ it('test 1', () => { /* ... */ });
+ it('test 2', () => { /* ... */ });
+});
+```
+
+### 5. Mock External Dependencies
+
+Mock API calls, timers, and external services:
+
+```typescript
+vi.mock('axios');
+vi.mock('../api/config', () => ({
+ api: { baseURL: 'http://test.com', endpoints: {} },
+}));
+```
+
+### 6. Use Descriptive Test Names
+
+β
**Good:**
+```typescript
+it('displays error message when login fails', () => { });
+it('enables submit button when form is valid', () => { });
+```
+
+β **Bad:**
+```typescript
+it('works', () => { });
+it('test 1', () => { });
+```
+
+---
+
+## Common Testing Patterns
+
+### Testing Theme Context
+
+```typescript
+it('applies dark mode styles when dark mode enabled', () => {
+ const { rerender } = render(
+
+
+
+ );
+
+ // Component starts in light mode
+ expect(screen.getByTestId('container')).toHaveClass('bg-white');
+
+ // Enable dark mode
+ act(() => {
+ // trigger dark mode
+ });
+
+ expect(screen.getByTestId('container')).toHaveClass('bg-dark');
+});
+```
+
+### Testing Loading States
+
+```typescript
+it('shows loading spinner while fetching', () => {
+ mockedAxios.get.mockImplementation(() => new Promise(() => {})); // Never resolves
+
+ render();
+
+ expect(screen.getByRole('status')).toBeInTheDocument();
+ expect(screen.getByLabelText('loading')).toBeInTheDocument();
+});
+```
+
+### Testing Error States
+
+```typescript
+it('displays error message when API call fails', async () => {
+ mockedAxios.get.mockRejectedValueOnce(new Error('API Error'));
+
+ render();
+
+ await waitFor(() => {
+ expect(screen.getByText(/error/i)).toBeInTheDocument();
+ });
+});
+```
+
+### Testing Conditional Rendering
+
+```typescript
+it('shows admin menu only when user is admin', () => {
+ const { rerender } = render();
+
+ // Not logged in
+ expect(screen.queryByText('Admin Panel')).not.toBeInTheDocument();
+
+ // Log in as admin
+ rerender();
+ expect(screen.getByText('Admin Panel')).toBeInTheDocument();
+});
+```
+
+### Testing Async Operations
+
+```typescript
+it('updates product list after deletion', async () => {
+ const user = userEvent.setup();
+ mockedAxios.delete.mockResolvedValueOnce({});
+
+ render();
+
+ const deleteButton = screen.getByRole('button', { name: /delete/i });
+ await user.click(deleteButton);
+
+ await waitFor(() => {
+ expect(screen.queryByText('Product 1')).not.toBeInTheDocument();
+ });
+});
+```
+
+---
+
+## Coverage Goals
+
+### Target Coverage
+
+- **Statements:** > 80%
+- **Branches:** > 75%
+- **Functions:** > 80%
+- **Lines:** > 80%
+
+### Check Coverage
+
+```bash
+npm run test:coverage
+```
+
+Generates report in `coverage/` directory.
+
+### Focus Coverage On
+
+1. **Critical paths:** Authentication, data submission
+2. **Business logic:** Calculations, validations
+3. **Error handling:** Error states, edge cases
+
+### Don't Stress Coverage For
+
+- UI-only components without logic
+- Simple presentational components
+- Third-party library wrappers
+
+---
+
+## Resources
+
+- [Vitest Documentation](https://vitest.dev/)
+- [React Testing Library](https://testing-library.com/react)
+- [Testing Library Queries](https://testing-library.com/docs/queries/about)
+- [Common Mistakes](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library)
+
+---
+
+## Next Steps
+
+To implement testing in this project:
+
+1. Add test setup file: `src/test/setup.ts`
+2. Configure Vitest in `vite.config.ts`
+3. Write tests for critical components (AuthContext, Products, Navigation)
+4. Set up CI/CD to run tests on every PR
+5. Add coverage thresholds to fail build if coverage drops
diff --git a/frontend/README.md b/frontend/README.md
index 40ede56..230e4dd 100644
--- a/frontend/README.md
+++ b/frontend/README.md
@@ -1,54 +1,135 @@
-# React + TypeScript + Vite
-
-This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
-
-Currently, two official plugins are available:
-
-- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
-- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
-
-## Expanding the ESLint configuration
-
-If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
-
-```js
-export default tseslint.config({
- extends: [
- // Remove ...tseslint.configs.recommended and replace with this
- ...tseslint.configs.recommendedTypeChecked,
- // Alternatively, use this for stricter rules
- ...tseslint.configs.strictTypeChecked,
- // Optionally, add this for stylistic rules
- ...tseslint.configs.stylisticTypeChecked,
- ],
- languageOptions: {
- // other options...
- parserOptions: {
- project: ['./tsconfig.node.json', './tsconfig.app.json'],
- tsconfigRootDir: import.meta.dirname,
- },
- },
-})
+# OctoCAT Supply Chain Management - Frontend
+
+Modern React-based frontend for the OctoCAT Supply Chain Management System.
+
+## Overview
+
+A single-page application (SPA) built with React, TypeScript, Vite, and Tailwind CSS that provides an intuitive interface for managing supply chain operations including products, orders, suppliers, and more.
+
+## Key Features
+
+- π¨ **Dark/Light Theme** - User-switchable theme with localStorage persistence
+- π **Authentication** - Role-based access control (admin/regular users)
+- π± **Responsive Design** - Mobile-first approach with Tailwind CSS
+- β‘ **Fast Development** - Vite HMR for instant feedback
+- π― **Type-Safe** - Full TypeScript coverage
+- π **API Integration** - RESTful API communication with React Query
+- βΏ **Accessible** - ARIA labels and keyboard navigation support
+
+## Tech Stack
+
+- **React 18+** - UI library
+- **TypeScript** - Type-safe JavaScript
+- **Vite** - Build tool and dev server
+- **Tailwind CSS** - Utility-first CSS framework
+- **React Router v7** - Client-side routing
+- **React Query** - Server state management
+- **Axios** - HTTP client
+
+## Quick Start
+
+### Prerequisites
+
+- Node.js 18+ and npm 9+
+
+### Installation
+
+```bash
+# Install dependencies
+npm install
+
+# Start development server
+npm run dev
+
+# Access at http://localhost:5137
+```
+
+### Build for Production
+
+```bash
+npm run build
```
-You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
-
-```js
-// eslint.config.js
-import reactX from 'eslint-plugin-react-x'
-import reactDom from 'eslint-plugin-react-dom'
-
-export default tseslint.config({
- plugins: {
- // Add the react-x and react-dom plugins
- 'react-x': reactX,
- 'react-dom': reactDom,
- },
- rules: {
- // other rules...
- // Enable its recommended typescript rules
- ...reactX.configs['recommended-typescript'].rules,
- ...reactDom.configs.recommended.rules,
- },
-})
+### Linting
+
+```bash
+npm run lint
+```
+
+## Project Structure
+
+```
+src/
+βββ api/ # API configuration and endpoints
+βββ components/ # React components
+β βββ admin/ # Admin-specific components
+β βββ entity/ # Domain entity components
+β βββ ... # Layout and page components
+βββ context/ # React Context providers (Auth, Theme)
+βββ assets/ # Images and static assets
+βββ App.tsx # Root component with routing
+βββ main.tsx # Application entry point
```
+
+## Documentation
+
+Comprehensive documentation is available in the `docs/frontend/` directory:
+
+- **[Overview & Getting Started](../docs/frontend/README.md)** - Introduction and quick start
+- **[Architecture](../docs/frontend/architecture.md)** - Component structure, state management, routing patterns
+- **[Setup & Development](../docs/frontend/setup.md)** - Prerequisites, environment setup, development workflow
+- **[Component Documentation](../docs/frontend/components.md)** - Detailed component API and usage examples
+- **[Styling Guidelines](../docs/frontend/styling.md)** - Tailwind CSS conventions and theme system
+- **[API Integration](../docs/frontend/api-integration.md)** - API client, error handling, authentication
+- **[Testing](../docs/frontend/testing.md)** - Testing strategy, tools, and examples
+- **[Code Organization](../docs/frontend/code-organization.md)** - Folder structure and best practices
+
+## Available Routes
+
+- `/` - Welcome/landing page
+- `/about` - About page
+- `/products` - Product catalog
+- `/login` - User login
+- `/admin/products` - Admin product management (requires admin access)
+
+## Environment Configuration
+
+The application automatically detects the API URL:
+
+1. **Runtime Config** - `window.RUNTIME_CONFIG.API_URL` (Docker/production)
+2. **GitHub Codespaces** - Auto-detected and configured
+3. **Local Development** - Defaults to `http://localhost:3000`
+
+See [Setup Documentation](../docs/frontend/setup.md#environment-configuration) for details.
+
+## Development Scripts
+
+```bash
+npm run dev # Start dev server (http://localhost:5137)
+npm run build # Build for production
+npm run lint # Run ESLint
+npm run preview # Preview production build
+```
+
+## Contributing
+
+When adding new features:
+
+1. Follow [Code Organization](../docs/frontend/code-organization.md) patterns
+2. Adhere to [Styling Guidelines](../docs/frontend/styling.md)
+3. Add tests (see [Testing Guide](../docs/frontend/testing.md))
+4. Update relevant documentation
+
+## Architecture
+
+This frontend communicates with a REST API backend. See the [main architecture documentation](../docs/architecture.md) for system-wide design and [frontend architecture](../docs/frontend/architecture.md) for detailed frontend patterns.
+
+## Support
+
+- Check the [documentation](../docs/frontend/README.md)
+- Review [setup troubleshooting](../docs/frontend/setup.md#troubleshooting)
+- See component examples in the codebase
+
+## License
+
+Part of the OctoCAT Supply Chain Management System.
From fca577f3aa223f039174ee5612e2fe3a9e3369a0 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 19 Jan 2026 13:18:51 +0000
Subject: [PATCH 3/3] Address code review feedback - fix Vitest mocking, React
Query version notes, and error handling
Co-authored-by: webmaxru <1560278+webmaxru@users.noreply.github.com>
---
docs/frontend/api-integration.md | 16 +++++++++++++---
docs/frontend/components.md | 7 +++++++
docs/frontend/testing.md | 2 +-
3 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/docs/frontend/api-integration.md b/docs/frontend/api-integration.md
index 5c5de02..bdf6a03 100644
--- a/docs/frontend/api-integration.md
+++ b/docs/frontend/api-integration.md
@@ -193,6 +193,8 @@ React Query manages server state (fetching, caching, synchronization) with minim
npm install react-query
```
+**Current Version:** This project uses React Query v3. For newer projects, consider React Query v4+ (renamed to @tanstack/react-query) which uses object-based API syntax.
+
### Setup
**No setup required** - React Query is used directly in components without a provider in the current implementation.
@@ -205,6 +207,7 @@ import axios from 'axios';
import { api } from '../api/config';
function Products() {
+ // React Query v3 syntax (current)
const { data, isLoading, error } = useQuery('products', async () => {
const response = await axios.get(`${api.baseURL}${api.endpoints.products}`);
return response.data;
@@ -330,11 +333,18 @@ try {
} catch (error) {
if (axios.isAxiosError(error)) {
if (error.response?.status === 404) {
- alert('Product not found');
+ // Display user-friendly error in UI
+ setErrorMessage('Product not found');
} else if (error.response?.status === 500) {
- alert('Server error. Please try again later.');
+ // Display user-friendly error in UI
+ setErrorMessage('Server error. Please try again later.');
} else {
- alert('An error occurred');
+ // Display generic error in UI
+ setErrorMessage('An error occurred');
+ }
+ // Log error for debugging (in development only)
+ if (import.meta.env.DEV) {
+ console.error('API Error:', error);
}
}
}
diff --git a/docs/frontend/components.md b/docs/frontend/components.md
index 98b489a..3e7f4fb 100644
--- a/docs/frontend/components.md
+++ b/docs/frontend/components.md
@@ -311,7 +311,14 @@ const [showModal, setShowModal] = useState(false);
Uses React Query for data fetching:
```typescript
+// React Query v3 syntax (current version in this project)
const { data: products, isLoading, error } = useQuery('products', fetchProducts);
+
+// Note: For React Query v4+, use object syntax:
+// const { data, isLoading, error } = useQuery({
+// queryKey: ['products'],
+// queryFn: fetchProducts
+// });
```
**Key Functions:**
diff --git a/docs/frontend/testing.md b/docs/frontend/testing.md
index 154b819..0eb884b 100644
--- a/docs/frontend/testing.md
+++ b/docs/frontend/testing.md
@@ -426,7 +426,7 @@ import Products from './Products';
// Mock axios
vi.mock('axios');
-const mockedAxios = axios as jest.Mocked;
+const mockedAxios = vi.mocked(axios);
describe('Products', () => {
const queryClient = new QueryClient({