127 lines
4.7 KiB
Markdown
127 lines
4.7 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
This is a React-based lucky draw application (Year End Party draw system) built with Vite, featuring an animated slot machine interface for random number selection with persistent state management.
|
|
|
|
## Development Commands
|
|
|
|
```bash
|
|
# Install dependencies
|
|
npm install
|
|
|
|
# Start development server (with HMR)
|
|
npm run dev
|
|
|
|
# Build for production
|
|
npm run build
|
|
|
|
# Preview production build
|
|
npm run preview
|
|
|
|
# Lint code
|
|
npm run lint
|
|
```
|
|
|
|
## Tech Stack
|
|
|
|
- **Frontend Framework**: React 19.2.0 with JSX
|
|
- **Build Tool**: Vite 7.2.4
|
|
- **Styling**: Tailwind CSS 3.4.17 with custom configuration
|
|
- **Animation**: Framer Motion 12.23.26 (for slot machine animations)
|
|
- **Icons**: Lucide React 0.559.0
|
|
- **Linting**: ESLint 9.39.1 with flat config
|
|
|
|
## Architecture
|
|
|
|
### State Management Pattern
|
|
|
|
The app uses a custom hook pattern for state management (`useLuckyDraw` hook) that encapsulates all draw logic and persists state to localStorage. Key features:
|
|
|
|
- **Persistent State**: All draw state (pool, history, maxNumber) is automatically saved to localStorage
|
|
- **State Shape**: `{ maxNumber, remainingNumbers, drawHistory }`
|
|
- **Pool Management**: Numbers are removed from pool when drawn, preventing duplicates
|
|
- **History Tracking**: All drawn numbers are stored in reverse chronological order
|
|
|
|
### Component Structure
|
|
|
|
```
|
|
App.jsx (Main container)
|
|
├── SlotMachine.jsx (Animated 3-digit display)
|
|
│ └── Uses framer-motion with 3 independent reel controls
|
|
│ └── Staggered animation (3s, 3.5s, 4s) for luxury effect
|
|
└── HistoryPanel.jsx (Sidebar with history + controls)
|
|
└── Shows draw history, max number control, reset button
|
|
```
|
|
|
|
### Animation System (SlotMachine)
|
|
|
|
The slot machine uses a sophisticated animation approach:
|
|
|
|
- **3 Independent Reels**: Each digit has its own animation control
|
|
- **Duplicate Strips**: Each reel contains 6 sets of 0-9 (NUM_DUPLICATES=5 + final set)
|
|
- **Staggered Timing**: Reels stop at different times (delay: 0s, 0.5s, 1.0s) for dramatic effect
|
|
- **Target Calculation**: `targetY = -((NUM_DUPLICATES * 10) + digit) * SLOT_HEIGHT`
|
|
- **Animation Callback**: `onAnimationComplete` fires when all reels finish, triggering history update
|
|
|
|
### Custom Hook: useLuckyDraw
|
|
|
|
Located in `src/hooks/useLuckyDraw.js`, this hook manages:
|
|
|
|
- **Draw Logic**: Random selection from remaining pool
|
|
- **Pool Management**: Automatic pool updates and persistence
|
|
- **Animation State**: `isSpinning` flag prevents concurrent draws
|
|
- **Two-Phase Draw**: `drawNumber()` initiates, `completeDraw(winner)` finalizes after animation
|
|
|
|
### Styling Approach
|
|
|
|
- **Background**: Full-screen image (`/asset/img/background.jpg`) with overlay gradients
|
|
- **Glass Morphism**: History panel uses `backdrop-blur-xl` and `bg-white/20`
|
|
- **Custom Colors**: Tailwind extended with `sky-light`, `sky-dark`, `gold`
|
|
- **Responsive**: Main slot machine centered, history panel shows only on `xl:` breakpoint
|
|
|
|
## Important Implementation Details
|
|
|
|
### Draw Flow Sequence
|
|
|
|
1. User clicks "DRAW" button (disabled if `isSpinning` or `pool.length === 0`)
|
|
2. `drawNumber()` → Selects random number, removes from pool, sets `currentWinner`, sets `isSpinning=true`
|
|
3. `SlotMachine` detects winner change → Triggers 3-reel animation (3-4 second duration)
|
|
4. Animation completes → Calls `handleAnimationComplete()`
|
|
5. `completeDraw(currentWinner)` → Adds to history, sets `isSpinning=false`
|
|
|
|
### Max Number Changes
|
|
|
|
Changing max number triggers a confirmation dialog and full reset:
|
|
- Clears pool and regenerates with new max
|
|
- Clears history
|
|
- User must confirm to prevent accidental data loss
|
|
|
|
### Legacy Code
|
|
|
|
The `legacy/` directory contains an older vanilla JS implementation that is not part of the current app. It can be ignored for development purposes but is preserved for reference.
|
|
|
|
## File Locations
|
|
|
|
- **Config**: `src/config.json` (currently stores default maxNumber, though runtime state overrides this)
|
|
- **Background Image**: Expected at `public/asset/img/background.jpg`
|
|
- **Main Entry**: `src/main.jsx` → renders `App.jsx`
|
|
- **Styles**: `src/index.css` (imports Tailwind)
|
|
|
|
## ESLint Configuration
|
|
|
|
Uses flat config format (`eslint.config.js`) with:
|
|
- React Hooks plugin (enforces rules of hooks)
|
|
- React Refresh plugin (for HMR)
|
|
- Custom rule: Allows unused variables starting with uppercase (e.g., component imports)
|
|
|
|
## Notes for Development
|
|
|
|
- The app is NOT a git repository (no version control initialized)
|
|
- No TypeScript - uses plain JSX
|
|
- LocalStorage key: `'luckyDrawState'`
|
|
- Slot machine dimensions: Each reel is 320px (w-80 h-80), digit height is also 320px
|
|
- History panel is hidden on screens smaller than `xl` breakpoint
|