# JAM Members Club — Deployment Guide (cPanel / Shared Hosting)

## Prerequisites

- cPanel hosting with PHP 8.2+
- MySQL database
- SSH access (recommended) or File Manager
- A domain or subdomain pointed to the hosting

---

## Step 1 — Upload Files

**Option A (SSH + Git):**
```bash
ssh user@yourhost.com
cd public_html          # or your chosen directory
git clone <repo-url> .
```

**Option B (File Manager / FTP):**
1. Zip the project locally (exclude `node_modules/` and `.git/`)
2. Upload the zip via File Manager → Extract into your desired directory

> **Important:** The Laravel `public/` folder should map to your web root.  
> For cPanel the cleanest approach is to deploy the project one level above `public_html` and symlink:
> ```
> /home/username/jam_loyalty/        ← Laravel root (all files here)
> /home/username/public_html/        ← points to /home/username/jam_loyalty/public
> ```
> Or copy the contents of `public/` into `public_html/` and update `public/index.php` paths accordingly.

---

## Step 2 — Configure `.env`

Copy the example file and fill in your values:
```bash
cp .env.example .env
```

Key values to set:
```dotenv
APP_NAME="JAM Members Club"
APP_ENV=production
APP_KEY=                        # generated in Step 3
APP_DEBUG=false
APP_URL=https://yourdomain.com.au

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=your_cpanel_db_name
DB_USERNAME=your_cpanel_db_user
DB_PASSWORD=your_db_password

MAIL_MAILER=smtp
MAIL_HOST=mail.yourdomain.com.au
MAIL_PORT=465
MAIL_USERNAME=noreply@yourdomain.com.au
MAIL_PASSWORD=your_mail_password
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS=noreply@yourdomain.com.au
MAIL_FROM_NAME="JAM Members Club"

QUEUE_CONNECTION=database
SESSION_DRIVER=file
CACHE_STORE=file
```

---

## Step 3 — Install Dependencies & Bootstrap

Run these via SSH:
```bash
cd /home/username/jam_loyalty

# Install PHP dependencies (production — no dev tools)
composer install --no-dev --optimize-autoloader

# Generate app key
php artisan key:generate

# Run database migrations
php artisan migrate --force

# Seed initial data (tiers, settings, super admin)
php artisan db:seed --force

# Link storage for profile image uploads
php artisan storage:link

# Cache config/routes for performance
php artisan config:cache
php artisan route:cache
php artisan view:cache

# Create the queue jobs table
php artisan queue:table
php artisan migrate --force
```

---

## Step 4 — Build Frontend Assets

Build assets **locally** (shared hosting usually can't run Node):
```bash
# On your local machine in the project root:
npm install
npm run build
```

Then upload the generated `public/build/` folder to your hosting `public/build/`.

---

## Step 5 — File Permissions

```bash
chmod -R 755 /home/username/jam_loyalty
chmod -R 775 /home/username/jam_loyalty/storage
chmod -R 775 /home/username/jam_loyalty/bootstrap/cache
```

---

## Step 6 — Set Up Cron Jobs in cPanel

Go to **cPanel → Cron Jobs** and add the following entries.

> Replace `/home/username/jam_loyalty` with your actual path.  
> Run `which php` via SSH to confirm the PHP binary path — common values:
> - Hostinger: `/usr/local/bin/php`
> - cPanel standard: `/usr/bin/php`

### 6a. Laravel Scheduler (runs every minute — required for all scheduled tasks)
```
* * * * * /usr/local/bin/php /home/username/jam_loyalty/artisan schedule:run >> /dev/null 2>&1
```

### 6b. Queue Worker (processes email notifications)
```
* * * * * /usr/local/bin/php /home/username/jam_loyalty/artisan queue:work --stop-when-empty >> /dev/null 2>&1
```

> `--stop-when-empty` is safe for shared hosting — it processes jobs then exits, avoiding long-running process limits.

The Laravel Scheduler handles the rest automatically:
- **Daily at 1am** — Tier assessment (`tiers:assess`)
- **Daily at 2am** — Points expiry (`loyalty:expire-points`)
- **Daily at 9am** — Expiry reminder emails (`loyalty:send-expiry-reminders`)

---

## Step 7 — Create Super Admin

```bash
php artisan tinker
```
```php
\App\Models\Admin::create([
    'name'     => 'Your Name',
    'email'    => 'admin@jamcorner.com.au',
    'password' => bcrypt('YourSecurePassword123!'),
    'role'     => 'super_admin',
    'status'   => 'active',
]);
```

---

## Step 8 — Verify Deployment

| Check | URL |
|-------|-----|
| Member login | `https://yourdomain.com.au/login` |
| Admin login  | `https://yourdomain.com.au/admin/login` |
| Admin panel  | `https://yourdomain.com.au/admin/dashboard` |

---

## Tier Assessment — Manual Options

You can also trigger assessment manually via SSH:

```bash
# All changes require admin approval (recommended default)
php artisan tiers:assess

# Auto-apply upgrades, flag downgrades for review
php artisan tiers:assess --auto-approve=true --auto-downgrade=false

# Fully automated (use with caution)
php artisan tiers:assess --auto-approve=true --auto-downgrade=true
```

---

## Troubleshooting

| Issue | Fix |
|-------|-----|
| 500 error after deploy | Check `storage/logs/laravel.log`; usually a missing `.env` key or wrong DB credentials |
| Emails not sending | Verify MAIL_* settings; test with `php artisan tinker` → `Mail::raw('test', fn($m) => $m->to('you@email.com'))` |
| Profile images not showing | Run `php artisan storage:link` |
| Queue jobs not processing | Add the queue:work cron (Step 6b); check `jobs` table isn't empty |
| Vite assets 404 | Upload `public/build/` from a local `npm run build` |
| Class not found | Run `composer dump-autoload` |
