Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 43 additions & 43 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
name: Deploy to EC2
on:
push:
branches:
- main # Triggers deployment when pushing to main branch
workflow_dispatch: # Allows manual deployment from GitHub Actions tab
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Configure SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.EC2_SSH_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ec2-3-139-205-219.us-east-2.compute.amazonaws.com >> ~/.ssh/known_hosts
- name: Deploy to EC2
run: |
ssh -o StrictHostKeyChecking=no ubuntu@ec2-3-139-205-219.us-east-2.compute.amazonaws.com << 'EOF'
# Navigate to project directory
cd /home/ubuntu/Plated
# Run deployment script (it handles git pull, dependencies, and restart)
echo "🚀 Starting deployment process..."
bash deploy.sh
echo "✅ Deployment completed successfully!"
EOF
- name: Deployment Status
if: success()
run: echo "🎉 Deployment to EC2 completed successfully!"
- name: Deployment Failed
if: failure()
run: echo "❌ Deployment failed. Please check the logs above."
name: Deploy to EC2

on:
push:
branches:
- main # Triggers deployment when pushing to main branch
workflow_dispatch: # Allows manual deployment from GitHub Actions tab

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Configure SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.EC2_SSH_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ec2-3-139-205-219.us-east-2.compute.amazonaws.com >> ~/.ssh/known_hosts

- name: Deploy to EC2
run: |
ssh -o StrictHostKeyChecking=no ubuntu@ec2-3-139-205-219.us-east-2.compute.amazonaws.com << 'EOF'
# Navigate to project directory
cd /home/ubuntu/Plated

# Run deployment script (it handles git pull, dependencies, and restart)
echo "🚀 Starting deployment process..."
bash deploy.sh

echo "✅ Deployment completed successfully!"
EOF

- name: Deployment Status
if: success()
run: echo "🎉 Deployment to EC2 completed successfully!"

- name: Deployment Failed
if: failure()
run: echo "❌ Deployment failed. Please check the logs above."

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
80 changes: 40 additions & 40 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
{
"sqltools.connections": [
{
"ssh": "Disabled",
"previewLimit": 50,
"server": "localhost",
"port": 5432,
"driver": "PostgreSQL",
"name": "Lab1DB",
"database": "CS4350_Lab1",
"username": "postgres"
},
{
"ssh": "Disabled",
"previewLimit": 50,
"server": "localhost",
"port": 5432,
"driver": "PostgreSQL",
"name": "CS4350_Lab2",
"database": "cs4350_lab2",
"username": "postgres"
},
{
"pgOptions": {
"ssl": {
"rejectUnauthorized": false,
"requestCert": false
}
},
"ssh": "Disabled",
"previewLimit": 50,
"server": "aws-1-us-east-2.pooler.supabase.com",
"port": 5432,
"askForPassword": true,
"driver": "PostgreSQL",
"name": "SupabaseDB Cooking App",
"database": "postgres",
"username": "postgres.gevrbjruaiffugjrctme"
}
]
{
"sqltools.connections": [
{
"ssh": "Disabled",
"previewLimit": 50,
"server": "localhost",
"port": 5432,
"driver": "PostgreSQL",
"name": "Lab1DB",
"database": "CS4350_Lab1",
"username": "postgres"
},
{
"ssh": "Disabled",
"previewLimit": 50,
"server": "localhost",
"port": 5432,
"driver": "PostgreSQL",
"name": "CS4350_Lab2",
"database": "cs4350_lab2",
"username": "postgres"
},
{
"pgOptions": {
"ssl": {
"rejectUnauthorized": false,
"requestCert": false
}
},
"ssh": "Disabled",
"previewLimit": 50,
"server": "aws-1-us-east-2.pooler.supabase.com",
"port": 5432,
"askForPassword": true,
"driver": "PostgreSQL",
"name": "SupabaseDB Cooking App",
"database": "postgres",
"username": "postgres.gevrbjruaiffugjrctme"
}
]
}
170 changes: 170 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,173 @@ The project deploys to a DigitalOcean Droplet with GitHub Actions (`.github/work
3. **Implement optimistic updates** in store actions
4. **Use store** in components via `const { action } = useStore()`

## Gamification Architecture

**IMPORTANT:** Plated's gamification system is a core selling point. It uses a multi-layered reward system to drive engagement.

### Overview

The gamification system includes:
1. **Recipe Completion (Cooked-It Chain)** - Social proof of who cooked each recipe
2. **Daily Chaos Ingredient** - Daily featured ingredient with bonus multipliers
3. **Skill Tracks** - Progressive achievement collections
4. **Coins & XP** - Dual currency system with levels
5. **Badges & Streaks** - Achievement system
6. **Branding Images** - Custom cat-themed reward visuals

### Database Tables

**New Gamification Tables** (see `docs/database/gamification_enhancement_migration.sql`):
- `recipe_completion` - Tracks when users cook recipes
- `coin_transaction` - Audit log for all coin movements
- `daily_ingredient` - Daily featured ingredient with multiplier
- `recipe_ingredient_tag` - Maps recipes to ingredients
- `skill_track` - Track definitions (e.g., "Microwave Master")
- `skill_track_recipe` - Many-to-many: tracks ↔ recipes
- `skill_track_progress` - User progress through tracks

**Existing Tables:**
- `user_gamification` - User stats (XP, level, coins, streak, freeze_tokens)
- `badges` - Available badges
- `user_badges` - Earned badges
- `challenges` - Challenge definitions
- `user_challenges` - Challenge progress

### Backend Routes

**Location:** `backend/routes/gamification_routes.py`

**Key Endpoints:**
- `POST /api/gamification/recipes/<id>/complete` - Complete a recipe
- Awards base coins (10) + XP (15)
- Checks for Daily Chaos bonus (multiplies rewards)
- Awards creator bonus (5 coins)
- Updates skill track progress
- Awards track completion bonus (50 coins) when threshold reached
- `GET /api/gamification/recipes/<id>/completions` - Get Cooked-It Chain
- `GET /api/gamification/daily-ingredient` - Get today's chaos ingredient
- `GET /api/gamification/skill-tracks?user_id=X` - Get all tracks with progress

### Frontend Components

**Store:** `frontend/Plated/src/stores/gamificationStore.ts`
- Manages: `dailyIngredient`, `skillTracks`, `completionsByRecipe`
- Actions: `completeRecipe()`, `fetchDailyIngredient()`, `fetchSkillTracks()`

**Components:**
1. **RecipeActions** (`components/gamification/RecipeActions.tsx`)
- "I cooked this!" button
- Chaos Ingredient banner (when recipe uses today's ingredient)
- Cooked-It Chain (avatar list of users who completed recipe)
- Reward toast notification

2. **SkillTracksPage** (`pages/SkillTracksPage.tsx`)
- Grid of skill track cards
- Progress bars and completion status
- Rewards info section

3. **RewardNotification** (`components/gamification/RewardNotification.tsx`)
- Branded notification system using cat images
- Types: `recipe_complete`, `level_up`, `challenge_complete`, etc.
- Images: `/assets/gamification/*.jpg`

### Branding Assets

**Location:** `frontend/Plated/public/assets/gamification/`

**Available Images:**
- `CatTimer.jpg` - Timer/cooking in progress
- `ChallengeCompleted.jpg` - Success state
- `ChallengeFailed.jpg` - Failure state
- `CookingWithCat.jpg` - Cooking activity
- `Eating.jpg` - Eating/completion
- `HappyCooking.jpg` - General cooking happiness
- `LevelUp.jpg` - Level up celebration

**Usage Pattern:**
```tsx
import { RewardNotification } from './components/gamification/RewardNotification';

<RewardNotification
type="recipe_complete"
title="Recipe Completed!"
message="You earned rewards!"
rewards={{ coins: 20, xp: 30 }}
/>
```

### Reward Flow

**When user completes a recipe:**
1. Backend checks if already completed (idempotent)
2. Creates `recipe_completion` record
3. Checks Daily Chaos Ingredient:
- If recipe uses today's ingredient → multiply rewards by `multiplier`
4. Awards coins via `coin_transaction` (audit log)
5. Updates `user_gamification.coins` balance
6. Awards XP and checks for level up
7. Awards creator bonus (5 coins to recipe creator)
8. Updates skill track progress:
- Increments `completed_recipes` count
- If threshold reached (5 recipes) → marks track complete + 50 coin bonus
9. Returns reward summary to frontend

### Testing

**Seed Script:** `backend/seed_gamification_data.py`
```bash
cd backend
python seed_gamification_data.py
```

Creates:
- 5 skill tracks (Microwave Master, $5 Dinners, etc.)
- 14 days of daily ingredients
- Recipe ingredient tags (auto-extracted from recipe data)

**Manual Testing:**
1. Upload SQL migration to Supabase SQL Editor
2. Run seed script
3. Open `/tracks` page to view skill tracks
4. Complete recipes to test reward flow
5. Check Daily Chaos banner on recipe pages

### Integration Points

**To add RecipeActions to a recipe page:**
```tsx
import { RecipeActions } from '../components/gamification/RecipeActions';

<RecipeActions
recipeId={recipe.id}
ingredients={recipe.ingredients}
userId={currentUser.id}
/>
```

**To show notifications:**
```tsx
import { useRewardNotifications } from '../components/gamification/RewardNotification';

const { notifications, showNotification } = useRewardNotifications();

// Show notification
showNotification({
type: 'level_up',
title: 'Level Up!',
message: 'You reached level 5!',
rewards: { level: 5 }
});
```

### Configuration Constants

**Track Completion Threshold:** 5 recipes (in `gamification_routes.py:476`)
**Base Recipe Reward:** 10 coins, 15 XP
**Creator Bonus:** 5 coins
**Track Completion Bonus:** 50 coins
**Default Chaos Multiplier:** 2.0x

## Common Gotchas

1. **Two databases:** Don't use SQLAlchemy for posts/comments/etc. Use Supabase client.
Expand All @@ -475,6 +642,9 @@ The project deploys to a DigitalOcean Droplet with GitHub Actions (`.github/work
9. **Production URLs:** NEVER hardcode `localhost` or port numbers in fetch/axios calls. Always use `API_BASE_URL` from `utils/api.ts` or the axios instance.
10. **Production builds:** Run `npm run build` and serve from `dist/`, NEVER run `npm run dev` in production.
11. **Error boundaries:** No error boundary exists in App.tsx - unhandled errors cause white screens.
12. **Gamification user_id:** Backend endpoints use `user_id` query param for testing. In production, extract from JWT token.
13. **Image paths:** Gamification images must be in `public/assets/gamification/` to be served correctly.
14. **DO NOT MODIFY:** `.gitattributes` enforces line endings - never change this file.

## Documentation

Expand Down
Loading