# CA Grow Ops Manager — Frontend
**Version**: 0.1.0
**Stack**: TypeScript, React, Vite/Next.js, Radix UI/shadcn
---
## Overview
The frontend is a **mobile-first, accessible** web application optimized for low-friction daily use in cultivation facilities. It provides intuitive interfaces for tasks, batches, labor tracking, compliance, and team communication.
---
## Tech Stack
- **Language**: TypeScript 5.x
- **Framework**: React 18.x
- **Build Tool**: Vite or Next.js (to be decided during implementation)
- **Component Library**: Radix UI or shadcn-style accessible primitives
- **Styling**: Tailwind CSS or modern CSS-in-JS
- **State Management**: React Context + hooks (Zustand or Redux Toolkit for complex state)
- **Routing**: React Router (Vite) or Next.js App Router
- **Forms**: React Hook Form + Zod validation
- **API Client**: Axios or Fetch with TypeScript types
- **Testing**: Vitest + React Testing Library
---
## Project Structure
### Vite Option
```
frontend/
├── src/
│ ├── app/ # App shell
│ │ ├── App.tsx
│ │ ├── Router.tsx
│ │ └── Layout.tsx
│ ├── pages/ # Page components
│ │ ├── Dashboard.tsx
│ │ ├── Tasks/
│ │ │ ├── TasksPage.tsx
│ │ │ ├── TaskDetail.tsx
│ │ │ └── TodayView.tsx
│ │ ├── Batches/
│ │ ├── Labor/
│ │ ├── Compliance/
│ │ └── Settings/
│ ├── components/ # Reusable components
│ │ ├── ui/ # Base UI components (buttons, inputs, etc.)
│ │ ├── tasks/ # Task-specific components
│ │ ├── batches/
│ │ └── shared/ # Shared components (nav, header, etc.)
│ ├── hooks/ # Custom React hooks
│ │ ├── useAuth.ts
│ │ ├── useTasks.ts
│ │ └── useApi.ts
│ ├── lib/ # Utilities and helpers
│ │ ├── api.ts # API client
│ │ ├── auth.ts # Auth helpers
│ │ └── utils.ts
│ ├── types/ # TypeScript types
│ │ ├── api.ts
│ │ └── models.ts
│ ├── styles/ # Global styles
│ │ ├── index.css
│ │ └── tailwind.css
│ └── main.tsx # Entry point
├── public/ # Static assets
├── .env.example
├── package.json
├── tsconfig.json
├── vite.config.ts
└── README.md
```
### Next.js Option
```
frontend/
├── app/ # Next.js App Router
│ ├── layout.tsx
│ ├── page.tsx # Dashboard
│ ├── tasks/
│ │ ├── page.tsx
│ │ └── [id]/page.tsx
│ ├── batches/
│ ├── labor/
│ └── api/ # API routes (if needed)
├── components/ # Same as Vite
├── hooks/
├── lib/
├── types/
├── styles/
└── public/
```
---
## Design System
### Component Library (Radix UI / shadcn)
Use accessible primitives for:
- **Buttons**: Primary, secondary, destructive
- **Inputs**: Text, number, date, select
- **Dialogs**: Modals, drawers, alerts
- **Dropdowns**: Menus, selects, comboboxes
- **Tabs**: Navigation, content switching
- **Cards**: Content containers
- **Badges**: Status indicators
### Styling (Tailwind CSS)
```css
/* Design tokens */
:root {
--color-primary: #10b981; /* Green for cultivation */
--color-secondary: #3b82f6; /* Blue for actions */
--color-danger: #ef4444; /* Red for alerts */
--color-warning: #f59e0b; /* Orange for warnings */
--color-success: #10b981; /* Green for success */
--spacing-xs: 0.25rem;
--spacing-sm: 0.5rem;
--spacing-md: 1rem;
--spacing-lg: 1.5rem;
--spacing-xl: 2rem;
--font-sans: 'Inter', system-ui, sans-serif;
--font-mono: 'Fira Code', monospace;
}
```
### Mobile-First Design
- **Big Tap Targets**: Minimum 44×44px for all interactive elements
- **Dark Mode**: Default dark theme with light mode option
- **Responsive Breakpoints**:
- Mobile: < 640px
- Tablet: 640px - 1024px
- Desktop: > 1024px
---
## Key Features
### 1. Today View (Mobile-Optimized)
```tsx
// TodayView.tsx
export const TodayView = () => {
const { tasks, loading } = useTasks({ dueToday: true });
return (
Today's Tasks
{tasks.map(task => (
))}
);
};
```
### 2. Timeclock Widget
```tsx
// TimeclockWidget.tsx
export const TimeclockWidget = () => {
const { currentShift, clockIn, clockOut } = useTimeclock();
return (
{currentShift ? (
Clocked in: {formatTime(currentShift.clockIn)}
) : (
)}
);
};
```
### 3. Batch Timeline
```tsx
// BatchTimeline.tsx
export const BatchTimeline = ({ batchId }: { batchId: string }) => {
const { events } = useBatchTimeline(batchId);
return (
{events.map(event => (
))}
);
};
```
---
## API Integration
### API Client
```typescript
// lib/api.ts
import axios from 'axios';
const api = axios.create({
baseURL: import.meta.env.VITE_API_URL,
headers: {
'Content-Type': 'application/json',
},
});
// Add auth token to requests
api.interceptors.request.use(config => {
const token = localStorage.getItem('accessToken');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// Handle token refresh
api.interceptors.response.use(
response => response,
async error => {
if (error.response?.status === 401) {
// Attempt token refresh
const refreshToken = localStorage.getItem('refreshToken');
if (refreshToken) {
const { data } = await axios.post('/api/auth/refresh', { refreshToken });
localStorage.setItem('accessToken', data.accessToken);
error.config.headers.Authorization = `Bearer ${data.accessToken}`;
return axios(error.config);
}
}
return Promise.reject(error);
}
);
export default api;
```
### Custom Hooks
```typescript
// hooks/useTasks.ts
export const useTasks = (filters?: TaskFilters) => {
const [tasks, setTasks] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchTasks = async () => {
const { data } = await api.get('/api/tasks', { params: filters });
setTasks(data.data);
setLoading(false);
};
fetchTasks();
}, [filters]);
return { tasks, loading };
};
```
---
## Authentication
### Auth Context
```typescript
// hooks/useAuth.ts
const AuthContext = createContext(null);
export const AuthProvider = ({ children }: { children: ReactNode }) => {
const [user, setUser] = useState(null);
const login = async (email: string, password: string) => {
const { data } = await api.post('/api/auth/login', { email, password });
localStorage.setItem('accessToken', data.accessToken);
localStorage.setItem('refreshToken', data.refreshToken);
setUser(data.user);
};
const logout = () => {
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
setUser(null);
};
return (
{children}
);
};
export const useAuth = () => {
const context = useContext(AuthContext);
if (!context) throw new Error('useAuth must be used within AuthProvider');
return context;
};
```
---
## Testing
### Component Tests (Vitest + React Testing Library)
```typescript
// TaskCard.test.tsx
import { render, screen } from '@testing-library/react';
import { TaskCard } from './TaskCard';
describe('TaskCard', () => {
it('renders task name', () => {
const task = { id: '1', name: 'Water plants', status: 'PENDING' };
render();
expect(screen.getByText('Water plants')).toBeInTheDocument();
});
});
```
---
## Environment Variables
```bash
# API
VITE_API_URL=http://localhost:3000/api
# Auth
VITE_AUTH_ENABLED=true
# Features
VITE_METRC_ENABLED=false
```
---
## Development Workflow
### Setup
```bash
# Install dependencies
npm install
# Set up environment variables
cp .env.example .env
# Start dev server
npm run dev
```
### Scripts
```json
{
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"test": "vitest",
"test:ui": "vitest --ui",
"lint": "eslint src --ext .ts,.tsx",
"format": "prettier --write src"
}
}
```
---
## Accessibility
- **WCAG 2.1 AA Compliance**: All components meet accessibility standards
- **Keyboard Navigation**: All interactive elements keyboard-accessible
- **Screen Reader Support**: Proper ARIA labels and roles
- **Focus Management**: Clear focus indicators and logical tab order
- **Color Contrast**: Minimum 4.5:1 contrast ratio for text
---
## Mobile & PWA
### Progressive Web App (Stretch Goal)
```typescript
// vite.config.ts
import { VitePWA } from 'vite-plugin-pwa';
export default defineConfig({
plugins: [
VitePWA({
registerType: 'autoUpdate',
manifest: {
name: 'CA Grow Ops Manager',
short_name: 'Grow Ops',
theme_color: '#10b981',
icons: [
{ src: '/icon-192.png', sizes: '192x192', type: 'image/png' },
{ src: '/icon-512.png', sizes: '512x512', type: 'image/png' },
],
},
}),
],
});
```
---
## Next Steps
1. **Choose Build Tool**: Decide between Vite and Next.js
2. **Set Up Project**: Initialize React project with TypeScript
3. **Configure Tailwind**: Set up Tailwind CSS and design tokens
4. **Build Design System**: Implement base UI components
5. **Implement Pages**: Build page components per spec
6. **Write Tests**: Component and integration tests
7. **Deploy**: Set up CI/CD and deploy to staging
---
## Resources
- [React Documentation](https://react.dev)
- [Vite Documentation](https://vitejs.dev)
- [Next.js Documentation](https://nextjs.org/docs)
- [Radix UI Documentation](https://www.radix-ui.com)
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
- [React Testing Library](https://testing-library.com/react)