diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index d8f2634..b719e56 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -23,7 +23,7 @@ jobs: container: # Use Playwright image for faster Storybook test execution # https://playwright.dev/docs/docker#pull-the-image - image: mcr.microsoft.com/playwright:v1.57.0-noble + image: mcr.microsoft.com/playwright:v1.58.2-noble steps: - name: Checkout code diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..0ffe6ef --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,46 @@ +# Contributing to Cookie Voting + +Thank you for your interest in contributing to Cookie Voting! We welcome contributions from everyone. + +## Getting Started + +1. **Fork** the repository on GitHub. +2. **Clone** your fork locally: + ```bash + git clone https://github.com/YOUR_USERNAME/CookieVoting.git + cd CookieVoting + ``` +3. **Install dependencies**: + ```bash + npm install + cd functions && npm install && cd .. + ``` +4. **Set up environment**: + Copy `.env.example` to `.env` and fill in your Firebase credentials. + ```bash + cp .env.example .env + ``` + +## Development Workflow + +- **Start Development Server**: `npm run dev` (starts Vite on port 5173) +- **Run Tests**: `npm test` (runs Vitest unit tests) +- **Run Storybook**: `npm run storybook` (starts Storybook on port 6006) +- **Run End-to-End Tests**: `npm run test:e2e` (runs Playwright tests) + +## Pull Requests + +1. Create a new branch for your feature or fix: `git checkout -b feature/my-new-feature` +2. Make your changes. +3. Run verification script to ensure no regressions: `npm run verify` +4. Commit your changes using conventional commits (e.g., `feat: add new voting category`). +5. Push your branch and open a Pull Request. + +## Documentation + +For more detailed information, please refer to: + +- [Testing Guide](./docs/TESTING_GUIDE.md) +- [Storybook Setup](./docs/STORYBOOK_SETUP.md) +- [Architecture](./docs/ARCHITECTURE.md) +- [Emulator Setup](./docs/EMULATOR_SETUP.md) diff --git a/README.md b/README.md index c601dff..5f62681 100644 --- a/README.md +++ b/README.md @@ -4,61 +4,37 @@ [🚀 Launch App](https://cookie-voting.web.app/) • [📖 Documentation](#documentation) • [🐞 Report Bug](https://github.com/TytaniumDev/CookieVoting/issues) -Cookie Voting is a full-stack application designed to facilitate cookie competition events. Event administrators can upload images of cookies, and the system automatically detects individual cookies using Google Cloud Vision API. Voters can then vote on their favorite cookies in different categories, and results are tallied and displayed in real-time. +Cookie Voting is a full-stack application for managing and voting on cookie competitions. Powered by AI detection, Firebase, and React.
-- **AI-Powered Cookie Detection**: Automatically detects cookies in images using Google Cloud Vision API -- **Interactive Voting System**: Users can vote on cookies across multiple categories -- **Real-time Results**: View voting results and statistics as votes are cast -- **Admin Dashboard**: Create and manage voting events, upload images, and tag cookies -- **Responsive Design**: Works seamlessly on desktop and mobile devices -- **Component Documentation**: Comprehensive Storybook documentation for all UI components -> A modern web application for managing and voting on cookie competitions. Powered by AI cookie detection, Firebase, and React. - - - +Cookie Voting Dashboard ## 🚀 Quick Start ### Prerequisites -- Node.js 20+ and npm -- Firebase CLI (for deployment) -- Google Cloud Vision API enabled (for cookie detection) -- **Node.js 20+** -- **Firebase CLI** +- **Node.js 20+** +- **Firebase CLI** ### Installation -**Option 1: Fast Track (Mac/Linux)** ```bash +# 1. Setup Environment ./scripts/setup.sh -``` - -**Option 2: Manual Setup** -```bash -# Install dependencies -npm install && cd functions && npm install && cd .. -# Setup Environment -cp .env.example .env -# (Update .env with your Firebase credentials) -``` - -### Run -```bash +# 2. Run Local Development Server npm run dev ``` ## ✨ Key Features -- 🤖 **AI-Powered Detection**: Automatically detects individual cookies in tray images using Google Gemini AI. -- 🗳️ **Interactive Voting**: Real-time voting system with multiple categories. -- 📊 **Live Results**: Instant tallying and leaderboard updates. -- 🛡️ **Admin Dashboard**: Comprehensive tools for event management and image tagging. -- 📱 **Responsive Design**: Seamless experience across desktop and mobile. +- 🤖 **AI-Powered Detection**: Automatically detects individual cookies in tray images using Google Cloud Vision API. +- 🗳️ **Interactive Voting**: Real-time voting system with multiple categories. +- 📊 **Live Results**: Instant tallying and leaderboard updates. +- 🛡️ **Admin Dashboard**: Comprehensive tools for event management and image tagging. +- 📱 **Responsive Design**: Seamless experience across desktop and mobile. @@ -66,36 +42,24 @@ npm run dev Detailed documentation is available for developers and contributors: -- **[Product Requirements (PRD)](./docs/PRD.md)**: Feature specs and user stories. -- **[Architecture & Tech Stack](#tech-stack)**: Overview of the system. -- **[Gemini AI Setup](./docs/GEMINI_SETUP.md)**: Configuring the vision API. -- **[Emulator Setup](./docs/EMULATOR_SETUP.md)**: Running Firebase locally. -- **[Testing Guide](./docs/TESTING_GUIDE.md)**: Strategy for Unit, E2E, and Visual tests. -- **[Storybook Library](https://tytaniumdev.github.io/CookieVoting/)**: Component documentation. -- **[Deployment](./.github/DEPLOYMENT_SETUP.md)**: CI/CD configuration. - -- **[Storybook Component Library](https://tytaniumdev.github.io/CookieVoting/)** - Browse and interact with all UI components -- [Product Requirements Document (PRD)](./docs/PRD.md) - Source of truth for functionality -- [GEMINI_SCRIPT_SETUP.md](./docs/GEMINI_SCRIPT_SETUP.md) - Setup guide for experimental Gemini AI cookie detection script -- [EMULATOR_SETUP.md](./docs/EMULATOR_SETUP.md) - Local Firebase emulator setup -- [STORYBOOK_SETUP.md](./docs/STORYBOOK_SETUP.md) - Storybook development guide -- [.github/DEPLOYMENT_SETUP.md](./.github/DEPLOYMENT_SETUP.md) - Deployment configuration - +- **[Product Requirements (PRD)](./docs/PRD.md)**: Feature specs and user stories. +- **[Gemini AI Setup](./docs/GEMINI_SCRIPT_SETUP.md)**: Configuring the experimental vision script. +- **[Emulator Setup](./docs/EMULATOR_SETUP.md)**: Running Firebase locally. +- **[Testing Guide](./docs/TESTING_GUIDE.md)**: Strategy for Unit, E2E, and Visual tests. +- **[Storybook Library](https://tytaniumdev.github.io/CookieVoting/)**: Component documentation. +- **[Deployment](./.github/DEPLOYMENT_SETUP.md)**: CI/CD configuration. ## 🛠️ Tech Stack -- **Frontend**: React 19, TypeScript, Vite, TailwindCSS -- **Backend**: Firebase (Auth, Firestore, Storage, Functions) -- **AI Detection**: Google Cloud Vision API -- **UI Components**: Custom components with Storybook documentation -- **Testing**: Vitest, Playwright, Storybook -- **AI**: Google Gemini API -- **Testing**: Vitest, Playwright -- **CI/CD**: GitHub Actions +- **Frontend**: React 19, TypeScript, Vite, TailwindCSS +- **Backend**: Firebase (Auth, Firestore, Storage, Functions) +- **AI Detection**: Google Cloud Vision API & Google Gemini (Experimental) +- **Testing**: Vitest, Playwright, Storybook +- **CI/CD**: GitHub Actions ## 🤝 Contributing -Contributions are welcome! Please check out the [Issues](https://github.com/TytaniumDev/CookieVoting/issues) to get started. +We welcome contributions! Please see our [Contributing Guide](./CONTRIBUTING.md) to get started. ## 📄 License diff --git a/package-lock.json b/package-lock.json index 0c7d330..5cae152 100644 --- a/package-lock.json +++ b/package-lock.json @@ -71,7 +71,7 @@ "firebase-tools": "^15.1.0", "globals": "^16.5.0", "jsdom": "^27.3.0", - "playwright": "^1.57.0", + "playwright": "^1.58.2", "postcss": "^8.5.6", "prettier": "^3.7.4", "storybook": "^10.1.10", @@ -3879,6 +3879,53 @@ "node": ">=18" } }, + "node_modules/@playwright/test/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/@playwright/test/node_modules/playwright": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz", + "integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.57.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/@playwright/test/node_modules/playwright-core": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz", + "integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@pnpm/config.env-replace": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", @@ -16238,13 +16285,13 @@ } }, "node_modules/playwright": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz", - "integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz", + "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.57.0" + "playwright-core": "1.58.2" }, "bin": { "playwright": "cli.js" @@ -16257,9 +16304,9 @@ } }, "node_modules/playwright-core": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz", - "integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz", + "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 5f9a583..e3acb32 100644 --- a/package.json +++ b/package.json @@ -117,7 +117,7 @@ "firebase-tools": "^15.1.0", "globals": "^16.5.0", "jsdom": "^27.3.0", - "playwright": "^1.57.0", + "playwright": "^1.58.2", "postcss": "^8.5.6", "prettier": "^3.7.4", "storybook": "^10.1.10", diff --git a/public/hero.png b/public/hero.png new file mode 100644 index 0000000..d6f8dc5 Binary files /dev/null and b/public/hero.png differ diff --git a/scripts/generate-hero.js b/scripts/generate-hero.js new file mode 100644 index 0000000..9451426 --- /dev/null +++ b/scripts/generate-hero.js @@ -0,0 +1,31 @@ +import { chromium } from 'playwright'; + +async function generateHero() { + console.log('Launching browser...'); + const browser = await chromium.launch(); + const context = await browser.newContext({ + viewport: { width: 1280, height: 720 }, + deviceScaleFactor: 2, // High DPI for better quality + }); + const page = await context.newPage(); + + const url = 'http://localhost:5173'; + console.log(`Navigating to ${url}...`); + try { + await page.goto(url, { waitUntil: 'networkidle' }); + + // Maybe wait a bit more for animations + await page.waitForTimeout(2000); + + console.log('Taking screenshot...'); + await page.screenshot({ path: 'public/hero.png' }); + console.log('Hero image saved to public/hero.png'); + } catch (error) { + console.error('Failed to generate hero image:', error); + process.exit(1); + } finally { + await browser.close(); + } +} + +generateHero();