# Bongo Asset Package - Claude Code Guide

## Overview

This is a Laravel-based frontend asset package that provides compiled JavaScript, CSS, and Vue.js components for the admin section of all Bongo applications. It centralizes frontend assets for 30+ Bongo packages.

**Package**: `bongo/asset`
**Namespace**: `Bongo\Asset`
**Type**: Pure asset package (no routes, controllers, or models)

## Quick Links

- **Architecture**: See [ARCHITECTURE.md](ARCHITECTURE.md) for detailed diagrams and component patterns
- **Cursor Rules**: See [.cursorrules](.cursorrules) for development guidelines
- **Copilot Guide**: See [.github/copilot-instructions.md](.github/copilot-instructions.md) for code templates

## Commands

### Build Commands (npm)

From `src/` directory:

```bash
# Development build
npm run dev

# Watch mode
npm run watch

# Watch with polling (Docker/VMs)
npm run watch-poll

# Hot module replacement
npm run hot

# Production build
npm run production
```

**Note**: All commands use `NODE_OPTIONS=--openssl-legacy-provider` for legacy OpenSSL compatibility.

### Testing Commands (Composer)

From package root:

```bash
# Run tests
vendor/bin/phpunit

# Code style check
vendor/bin/pint --test

# Code style fix
vendor/bin/pint

# Static analysis
vendor/bin/phpstan analyse
```

### Laravel Commands

In consuming Laravel application:

```bash
# Publish compiled assets to public directory
php artisan vendor:publish --tag=bongo:assets

# Force republish (overwrites existing)
php artisan vendor:publish --tag=bongo:assets --force
```

## Technology Stack

| Technology | Version | Purpose |
|------------|---------|---------|
| PHP | >=8.2 | Service provider |
| Laravel | 10+ | Framework integration |
| Laravel Mix | 5.x | Build tool (webpack wrapper) |
| Vue | 2.5.17 | Component framework |
| TailwindCSS | 1.4.6 | Utility-first CSS |
| Redactor | - | WYSIWYG editor |
| Axios | 0.19 | HTTP client |
| jQuery | 3.2 | DOM manipulation |
| Moment.js | 2.26.0 | Date formatting |
| SweetAlert2 | 11.7.1 | Alert dialogs |
| vuedraggable | 2.23.2 | Drag and drop |

## Architecture Quick Reference

### Package Structure

```
src/
├── AssetServiceProvider.php          # Publishes compiled assets
├── package.json                      # npm dependencies
├── webpack.mix.js                    # Build config
├── tailwind.config.js                # Tailwind theme
├── public/                           # Compiled (git-ignored)
│   ├── css/backend.css
│   ├── js/backend.js
│   └── images/
└── resources/                        # Source files
    ├── js/
    │   ├── backend.js                # Vue app entry
    │   ├── layout/                   # 5 layout components
    │   ├── components/               # 50+ feature components
    │   └── vendor/                   # Redactor & handlers
    ├── sass/
    │   ├── backend.scss              # Sass entry
    │   ├── components/               # Custom styles
    │   ├── pages/                    # Page styles
    │   └── vendor/                   # Third-party overrides
    └── images/                       # Source images
```

### Vue Application Bootstrap

1. Load global dependencies (jQuery, lodash, moment, axios, swal)
2. Configure axios (CSRF & API tokens)
3. Load Redactor WYSIWYG
4. Create global event bus (`window.EventBus`)
5. Register global filters (date, currency, truncate, etc.)
6. Register global directives (v-uppercase, v-numeric, etc.)
7. Register global components (50+ components)
8. Create Vue instance mounted to `#app`

### Service Provider

```php
namespace Bongo\Asset;

use Illuminate\Support\ServiceProvider;

class AssetServiceProvider extends ServiceProvider
{
    public function boot()
    {
        // Publishes src/public/ to public_path()
        $this->publishes([__DIR__.'/public/' => public_path()], 'bongo:assets');
    }
}
```

**Note**: Unlike other Bongo packages, this does NOT extend `AbstractServiceProvider`.

## Key Files Reference

| File | Purpose | Key Contents |
|------|---------|--------------|
| `src/AssetServiceProvider.php` | Laravel integration | Asset publishing |
| `src/resources/js/backend.js` | Vue app entry | Global config, components |
| `src/resources/sass/backend.scss` | Sass entry | TailwindCSS imports |
| `src/webpack.mix.js` | Build config | Entry points, code splitting |
| `src/tailwind.config.js` | Tailwind theme | Custom colors, utilities |
| `src/package.json` | npm config | Dependencies, scripts |
| `tests/TestCase.php` | Test base | Orchestra Testbench setup |

## Global Components

### Layout Components

```vue
<v-container>
    <v-header>
        <v-header-menu></v-header-menu>
    </v-header>
    <v-sidebar></v-sidebar>
    <v-main>
        <!-- Page content -->
    </v-main>
</v-container>
```

### UI Components

| Component | Usage |
|-----------|-------|
| `<v-alert>` | Alert messages |
| `<v-button>` | Buttons |
| `<v-card>` | Card containers |
| `<v-combobox>` | Multi-select dropdown |
| `<v-colorpicker>` | Color picker |
| `<v-datepicker>` | Date picker |
| `<v-error>` | Validation errors |
| `<v-label>` | Form labels |
| `<dropdown>` | Generic dropdown |
| `<tabs>` + `<tab>` | Tab system |

### Feature Components (Builders)

| Component | Purpose |
|-----------|---------|
| `<data-table>` | Data table with filtering/pagination |
| `<form-builder>` | Drag-and-drop form builder |
| `<menu-builder>` | Hierarchical menu editor |
| `<gallery-builder>` | Gallery management |
| `<image-manager>` | Image upload/management |
| `<document-manager>` | Document management |
| `<estimate-plan-builder>` | Plan item builder |

### Editor Components

| Component | Purpose |
|-----------|---------|
| `<editor>` | WYSIWYG editor |
| `<css-editor>` | CSS code editor |
| `<js-editor>` | JavaScript code editor |
| `<schema-editor>` | JSON schema editor |
| `<file-uploader>` | File upload |
| `<preview>` | Content preview |

## Global Filters

Use in templates with pipe syntax: `{{ value | filterName }}`

| Filter | Input | Output | Example |
|--------|-------|--------|---------|
| `date` | Date string | Formatted date | `"2026-01-19" \| date` → "Jan 19th 2026" |
| `percent` | Decimal | Percentage | `0.15 \| percent` → "15%" |
| `currency` | Number | Currency | `1234.56 \| currency` → "1,234.56" |
| `truncate` | String, length, suffix | Truncated | `text \| truncate(50, '...')` |
| `uppercase` | String | UPPERCASE | `"hello" \| uppercase` → "HELLO" |
| `lowercase` | String | lowercase | `"HELLO" \| lowercase` → "hello" |
| `ucwords` | String | Title Case | `"hello world" \| ucwords` → "Hello World" |
| `plaintext` | String | Clean text | `"hello-world" \| plaintext` → "hello world" |

## Global Directives

Use as attributes on input elements: `<input v-directiveName>`

| Directive | Purpose | Allows |
|-----------|---------|--------|
| `v-uppercase` | Force uppercase | ABCD... |
| `v-alpha` | Letters only | a-z, A-Z |
| `v-numeric` | Numbers/decimals | 0-9, . |
| `v-alphanumeric` | Letters, numbers, symbols | a-z, 0-9, !, *, % |
| `v-currency` | Currency format | 0-9, , . |
| `v-date` | Auto-format date | MM/DD/YYYY |
| `v-maxnumber="100"` | Limit numeric value | Max: 100 |
| `v-maxchars="50"` | Limit character count | Max: 50 chars |

## Builder Component Pattern

All builder components follow this structure:

### Component Files
```
Builder/
├── Builder.vue         # Parent container (state management)
├── BuilderForm.vue     # Form component (create/edit)
└── BuilderItem.vue     # Item display (view/actions)
```

### Event Flow

```
BuilderForm → EventBus.$emit('newItem')      → Builder.newItem()
BuilderForm → EventBus.$emit('saveItem')     → Builder.saveItem()
BuilderItem → EventBus.$emit('editItem')     → Builder.editItem()
BuilderItem → EventBus.$emit('deleteItem')   → Builder.deleteItem()
```

### Component States

| State | Description | Display |
|-------|-------------|---------|
| `loading` | Fetching data | Spinner + "Loading..." |
| `has-items` | Items loaded | Draggable list |
| `no-items` | No items | "No items found" |
| `no-results` | Search/filter no match | "No results" + reset button |

## TailwindCSS Custom Theme

### Custom Colors

```javascript
// Brand color (green-yellow)
bg-primary-500        // #BED62F
text-primary-700      // Darker shade

// Greys
bg-light-500          // #EEEEEE (very light)
text-medium-500       // #888888 (medium)
text-dark-500         // #222222 (very dark)
bg-dark-alpha         // rgba(0, 0, 0, 0.8)
```

### Custom Utilities

```css
min-h-0, min-h-1/4, min-h-1/2, min-h-3/4, min-h-full
```

### Font

```css
font-sans  /* Inter var */
```

## Code Style

### JavaScript/Vue
- Strict mode enabled
- ES6+ syntax (let/const, arrow functions, template literals)
- camelCase for variables/methods
- PascalCase for component names
- Event names: camelCase or kebab-case

### PHP
- PSR-12 compliant (Laravel Pint)
- Type hints for parameters and return types
- Namespace: `Bongo\Asset`

### CSS/Sass
- TailwindCSS utilities first
- Custom CSS only when necessary
- Mobile-first responsive design
- BEM naming not used (Tailwind preferred)

## Common Patterns

### Loading Data from API

```javascript
mounted() {
    this.fetchItems();
},
methods: {
    fetchItems() {
        this.state = 'loading';
        axios.get(this.endpoint)
            .then(response => {
                this.items = response.data.data;
                this.state = this.items.length ? 'has-items' : 'no-items';
            })
            .catch(error => {
                this.state = 'error';
            });
    }
}
```

### Saving Data to API

```javascript
saveItem(item) {
    const method = this.mode === 'create' ? 'post' : 'put';
    const url = this.mode === 'create'
        ? this.endpoint
        : `${this.endpoint}/${item.id}`;

    axios[method](url, item)
        .then(() => {
            swal.fire('Success', 'Saved!', 'success');
            this.fetchItems();
        })
        .catch(() => {
            swal.fire('Error', 'Failed to save', 'error');
        });
}
```

### Event Bus Communication

```javascript
// Emit
EventBus.$emit('eventName', data);

// Listen
mounted() {
    EventBus.$on('eventName', this.handleEvent);
},
beforeDestroy() {
    EventBus.$off('eventName', this.handleEvent);
}
```

### Drag and Drop Reordering

```vue
<draggable :list="items" @update="updateSortOrder">
    <transition-group name="list" tag="div">
        <item v-for="item in items" :key="item.id"></item>
    </transition-group>
</draggable>
```

```javascript
updateSortOrder() {
    const ids = this.items.map(item => item.id);
    axios.post(`${this.endpoint}/reorder`, { ids });
}
```

## Development Workflow

### Making Changes

1. **Edit source files** in `src/resources/js/` or `src/resources/sass/`
2. **Watch for changes**: `npm run watch`
3. **Test in browser**: Changes rebuild automatically
4. **Production build**: `npm run production` when done
5. **Commit changes**: Git commit in this package
6. **Republish**: `php artisan vendor:publish --tag=bongo:assets --force` in consuming app

### Adding New Component

1. **Create component file**: `src/resources/js/components/YourComponent.vue`
2. **Register in backend.js**: `Vue.component('your-component', require('./components/YourComponent').default)`
3. **Rebuild**: `npm run dev`
4. **Use in templates**: `<your-component></your-component>`

### Adding New Filter/Directive

1. **Edit backend.js**: Add filter/directive registration
2. **Rebuild**: `npm run dev`
3. **Use in templates**: `{{ value | yourFilter }}` or `<input v-yourDirective>`

### Updating Tailwind Theme

1. **Edit tailwind.config.js**: Add colors, utilities, etc.
2. **Rebuild**: `npm run dev`
3. **Use in templates**: `class="your-color-500"`

## Testing

### PHP Tests

Currently minimal (only TestCase.php) as this is primarily a frontend package.

```bash
vendor/bin/phpunit
```

### Code Quality

```bash
# Check code style
vendor/bin/pint --test

# Fix code style
vendor/bin/pint

# Static analysis
vendor/bin/phpstan analyse
```

### JavaScript/Vue

No formal testing setup. Consider adding:
- ESLint with Vue plugin
- Jest for component testing
- Prettier for formatting

## Browser Compatibility

- Modern browsers with ES6+ support (via Babel)
- VTooltip disabled on mobile (viewport ≤ 768px)
- Legacy OpenSSL provider required for build (Node/webpack)

## Package Integration

### In Laravel Application

**1. Require package**:
```bash
composer require bongo/asset
```

**2. Publish assets**:
```bash
php artisan vendor:publish --tag=bongo:assets
```

**3. Include in Blade template**:
```blade
<!DOCTYPE html>
<html>
<head>
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <meta name="api-token" content="{{ auth()->user()?->api_token }}">
    <link rel="stylesheet" href="{{ asset('css/backend.css') }}">
</head>
<body>
    <div id="app">
        <v-container>
            <!-- Your components here -->
        </v-container>
    </div>
    <script src="{{ asset('js/backend.js') }}"></script>
</body>
</html>
```

**Meta tags required**:
- `csrf-token`: CSRF token for axios requests
- `api-token`: API token for authenticated users (optional)

## Troubleshooting

### Build Errors

**Issue**: `ERR_OSSL_EVP_UNSUPPORTED`
**Solution**: Scripts already include `NODE_OPTIONS=--openssl-legacy-provider`

**Issue**: Mix not found
**Solution**: Run `npm install`

### Components Not Rendering

**Check**:
1. Component registered in `backend.js`
2. Vue instance mounted to `#app`
3. No JavaScript console errors
4. `v-cloak` attribute present

### Styles Not Applying

**Check**:
1. Assets published: `php artisan vendor:publish --tag=bongo:assets`
2. CSS file loaded in template
3. TailwindCSS not purging classes (check `tailwind.config.js`)
4. Cache cleared: `php artisan cache:clear`

### Assets Not Updating

**Check**:
1. Rebuild assets: `npm run production`
2. Republish: `php artisan vendor:publish --tag=bongo:assets --force`
3. Clear browser cache
4. Check file timestamps in `public/css/` and `public/js/`

## Dependencies

### PHP
- PHP >=8.2
- `illuminate/contracts ^10.0`
- `bongo/framework ^3.0`

### JavaScript (Core)
- Vue 2.5.17
- Laravel Mix 5.x
- TailwindCSS 1.4.6
- Axios 0.19
- jQuery 3.2

### JavaScript (UI Libraries)
- SweetAlert2 11.7.1
- v-tooltip 2.0.3
- vue-color 2.7.1
- vue-multiselect 2.1.6
- vuedraggable 2.23.2
- CodeMirror 5.58.2
- Ace Builds 1.15.3

## Related Packages

This package is used by all Bongo packages for admin UI:

**Core**:
- `bongo/framework` - Core framework

**CMS**:
- `cms/builder` - Page builder
- `cms/page` - Page management
- `cms/menu` - Menu management
- `cms/post` - Blog posts
- `cms/gallery` - Gallery management
- Plus 7 more CMS packages

**Default**:
- `default/blade` - Blade extensions
- `default/captcha` - CAPTCHA
- `default/dashboard` - Dashboard
- `default/document` - Documents
- `default/image` - Image processing
- `default/user` - User management
- Plus 8 more default packages

## Notes

- Each package in the monorepo is a separate git repository
- Changes here affect ALL packages that depend on it
- Always test across multiple dependent packages before releasing
- Assets are compiled once and distributed to all consuming applications
- This provides UI consistency across the entire Bongo ecosystem

## Recent Changes

Based on git history:
- DT-551: Menu builder recursive relationship handling
- DT-518: Individual page schema updates
- DT-470: Plan items form improvements
- DT-435: Custom forms HTML section
- DT-458: Menu document links functionality
- Laravel 10 and PHP 8.2 upgrade (in progress)

## Getting Help

- **Monorepo docs**: See `/Users/stuart/Packages/bongo/CLAUDE.md`
- **Architecture**: See `ARCHITECTURE.md` in this package
- **Cursor**: See `.cursorrules` for Cursor AI
- **Copilot**: See `.github/copilot-instructions.md` for GitHub Copilot
