lukcy-draw/CLAUDE.md
2025-12-12 09:15:19 +07:00

4.7 KiB

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

# 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