# 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)