Spaces:
Paused
Paused
| # Job Apply AI - React Frontend | |
| A modern, SaaS-like React frontend for the Job Application AI Agent with beautiful animations, dark theme, and professional UI. | |
| ## π Features | |
| - **Modern React 18** with TypeScript | |
| - **State Management** with Zustand for efficient state handling | |
| - **Tailwind CSS** with custom emerald/black SaaS theme | |
| - **Framer Motion** animations for smooth interactions | |
| - **Component Library** with reusable, animated components | |
| - **Responsive Design** that works on all devices | |
| - **REST API Integration** with the Python backend | |
| - **Dark Mode** with professional styling | |
| ## π οΈ Tech Stack | |
| - **React 18** - UI framework | |
| - **TypeScript** - Type safety | |
| - **Vite** - Build tool and dev server | |
| - **Tailwind CSS** - Utility-first CSS framework | |
| - **Framer Motion** - Animation library | |
| - **Zustand** - State management | |
| - **Axios** - HTTP client | |
| - **Lucide React** - Icon library | |
| ## π¦ Installation | |
| ### Prerequisites | |
| - Node.js 18+ and npm/yarn | |
| - Python backend running on port 5050 | |
| ### Setup | |
| 1. **Install Dependencies** | |
| ```bash | |
| cd frontend | |
| npm install | |
| ``` | |
| 2. **Configure Environment** | |
| ```bash | |
| # Copy environment template | |
| cp .env.example .env | |
| # Edit .env if needed | |
| # VITE_API_URL=http://localhost:5050 | |
| ``` | |
| 3. **Start Development Server** | |
| ```bash | |
| npm run dev | |
| ``` | |
| The app will be available at `http://localhost:3000` | |
| ## ποΈ Project Structure | |
| ``` | |
| frontend/ | |
| βββ src/ | |
| β βββ components/ | |
| β β βββ common/ # Reusable UI components | |
| β β β βββ Button.tsx | |
| β β β βββ Card.tsx | |
| β β β βββ Input.tsx | |
| β β β βββ Modal.tsx | |
| β β β βββ ... | |
| β β βββ pages/ # Full page components | |
| β β β βββ HomePage.tsx | |
| β β β βββ WorkflowPage.tsx | |
| β β β βββ JobListPage.tsx | |
| β β β βββ SettingsModal.tsx | |
| β β βββ sections/ # Reusable page sections | |
| β β βββ Header.tsx | |
| β β βββ Footer.tsx | |
| β β βββ CVUpload.tsx | |
| β β βββ JobSearch.tsx | |
| β βββ store/ # Zustand state management | |
| β β βββ appStore.ts | |
| β βββ types/ # TypeScript type definitions | |
| β β βββ index.ts | |
| β βββ utils/ # Utility functions | |
| β β βββ api.ts | |
| β β βββ helpers.ts | |
| β βββ styles/ # Global styles | |
| β β βββ globals.css | |
| β βββ App.tsx # Root component | |
| β βββ main.tsx # Entry point | |
| βββ public/ # Static assets | |
| βββ index.html # HTML template | |
| βββ package.json | |
| βββ tailwind.config.js # Tailwind CSS config | |
| βββ tsconfig.json | |
| βββ vite.config.ts # Vite config | |
| ``` | |
| ## π¨ Styling & Theming | |
| The project uses Tailwind CSS with a custom color scheme: | |
| ### Colors | |
| - **Background**: `#0A0E27` (black) | |
| - **Primary**: `#22c55e` (emerald-500) | |
| - **Secondary**: Slate gray colors | |
| - **Accents**: Emerald shades for highlights | |
| ### Key Tailwind Config Features | |
| - Custom gradient backgrounds | |
| - Glow effects with custom shadows | |
| - Animation utilities | |
| - Responsive breakpoints | |
| ### Using Layout Classes | |
| ```tsx | |
| // Dark SaaS background | |
| <div className="bg-gradient-saas"> | |
| // Primary button with glow | |
| <Button className="shadow-glow">Generate CVs</Button> | |
| // Card with optional glow and inner glow | |
| <Card glow innerGlow>Content</Card> | |
| // Emerald gradient text | |
| <h1 className="bg-gradient-emerald bg-clip-text text-transparent"> | |
| Title | |
| </h1> | |
| ``` | |
| ## π§© Components | |
| ### Common Components | |
| All components are in `src/components/common/`: | |
| #### Button | |
| ```tsx | |
| <Button | |
| variant="primary" // primary, secondary, outline, ghost, danger | |
| size="lg" // sm, md, lg | |
| loading={false} | |
| icon={<Icon />} | |
| fullWidth | |
| > | |
| Click Me | |
| </Button> | |
| ``` | |
| #### Card | |
| ```tsx | |
| <Card hover glow innerGlow> | |
| Content with animations | |
| </Card> | |
| ``` | |
| #### Input | |
| ```tsx | |
| <Input | |
| label="Your Name" | |
| placeholder="Enter name" | |
| error={errors.name} | |
| icon={<Icon />} | |
| helperText="Optional" | |
| /> | |
| ``` | |
| #### Badge | |
| ```tsx | |
| <Badge variant="primary" size="md" icon={<Icon />}> | |
| Label | |
| </Badge> | |
| ``` | |
| #### Modal | |
| ```tsx | |
| <Modal isOpen={isOpen} onClose={handleClose} title="Dialog"> | |
| Content | |
| </Modal> | |
| ``` | |
| #### Toast Notification | |
| ```tsx | |
| <Toast | |
| type="success" // success, error, warning, info | |
| message="Success!" | |
| title="Great" | |
| onClose={() => {}} | |
| autoClose={true} | |
| /> | |
| ``` | |
| ## π State Management with Zustand | |
| The app uses Zustand for state management. Store is located in `src/store/appStore.ts`: | |
| ```tsx | |
| import { useJobStore } from '@/store/appStore'; | |
| function MyComponent() { | |
| const { jobs, setJobs, cvTemplate, setCVTemplate } = useJobStore(); | |
| // State is automatically persisted to localStorage | |
| // Update state by calling setter functions | |
| } | |
| ``` | |
| ### Available State | |
| - `jobs` - Array of found jobs | |
| - `cvTemplate` - Uploaded CV template | |
| - `tailoringMode` - 'local' or 'api' | |
| - `isSearching`, `isGenerating` - Loading states | |
| - `selectedJobIds` - Jobs selected for batch generation | |
| - `batchProgress` - Progress of batch operation | |
| - `notification` - Toast notification data | |
| ## π API Integration | |
| The frontend communicates with the backend via REST API endpoints in `src/utils/api.ts`: | |
| ```tsx | |
| import { jobsAPI } from '@/utils/api'; | |
| // Search jobs | |
| const result = await jobsAPI.searchJobs({ | |
| keyword: 'React Developer', | |
| location: 'San Francisco', | |
| maxJobs: 10 | |
| }); | |
| // Upload CV | |
| await jobsAPI.uploadCV(file); | |
| // Generate CV | |
| await jobsAPI.generateCV(jobId); | |
| // Batch generate | |
| await jobsAPI.generateAllCVs(jobIds); | |
| // Download file | |
| const blob = await jobsAPI.downloadFile(filename); | |
| ``` | |
| ## π¬ Animations with Framer Motion | |
| All components use Framer Motion for smooth animations: | |
| ```tsx | |
| import { motion } from 'framer-motion'; | |
| <motion.div | |
| initial={{ opacity: 0, y: 20 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| exit={{ opacity: 0, y: -20 }} | |
| whileHover={{ scale: 1.05 }} | |
| whileTap={{ scale: 0.95 }} | |
| > | |
| Animated content | |
| </motion.div> | |
| ``` | |
| ## π§ Development | |
| ### Commands | |
| ```bash | |
| # Start dev server | |
| npm run dev | |
| # Build for production | |
| npm run build | |
| # Preview production build | |
| npm run preview | |
| # Type check | |
| npm run type-check | |
| # Lint code | |
| npm run lint | |
| ``` | |
| ### File Paths | |
| Components use path aliases for clean imports: | |
| ```tsx | |
| // Instead of: | |
| import Button from '../../../components/common/Button'; | |
| // Use: | |
| import { Button } from '@/components/common'; | |
| import type { Job } from '@/types'; | |
| ``` | |
| Available aliases: | |
| - `@/components/*` - Components | |
| - `@/store/*` - State management | |
| - `@/types/*` - Type definitions | |
| - `@/utils/*` - Utilities | |
| - `@/hooks/*` - Custom hooks | |
| ## π Build & Deployment | |
| ### Production Build | |
| ```bash | |
| npm run build | |
| ``` | |
| This generates a production-optimized build in `dist/` folder that gets served by the Flask backend. | |
| ### Integration with Flask | |
| The Vite config is set up to build directly into the Flask static folder: | |
| ``` | |
| frontend/dist/ β job_apply_ai/ui/static/dist/ | |
| ``` | |
| The Flask app serves these files at `/static/dist/` or `/app/` routes. | |
| ## π± Responsive Design | |
| The app is fully responsive with Tailwind breakpoints: | |
| ```tsx | |
| <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4"> | |
| // 1 column on mobile, 2 on tablet, 4 on desktop | |
| </div> | |
| ``` | |
| ## βΏ Accessibility | |
| - Semantic HTML | |
| - ARIA labels where needed | |
| - Keyboard navigation support | |
| - Focus states for all interactive elements | |
| - Color contrast compliance | |
| ## π Troubleshooting | |
| ### Dev server not connecting to backend | |
| - Ensure Flask is running on port 5050 | |
| - Check `VITE_API_URL` in `.env` | |
| - Clear browser cache | |
| ### Tailwind styles not applying | |
| - Restart dev server | |
| - Verify file paths in `tailwind.config.js` include all source files | |
| ### Type errors | |
| - Run `npm run type-check` | |
| - Ensure `tsconfig.json` paths are correct | |
| ## π License | |
| MIT | |
| ## π€ Contributing | |
| Contributions welcome! Please follow the existing code style and component patterns. | |