lukcy-draw/CLAUDE.md

127 lines
4.7 KiB
Markdown
Raw Normal View History

2025-12-12 02:15:19 +00:00
# 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