# Architecture Documentation - Bongo Asset Package

## Table of Contents

1. [Overview](#overview)
2. [Directory Structure](#directory-structure)
3. [Build Pipeline](#build-pipeline)
4. [Vue Application Architecture](#vue-application-architecture)
5. [Component Hierarchy](#component-hierarchy)
6. [Data Flow Patterns](#data-flow-patterns)
7. [Styling Architecture](#styling-architecture)
8. [Extension Points](#extension-points)
9. [Adding New Features](#adding-new-features)

## Overview

The Bongo Asset package is a centralized frontend asset compilation and distribution system for the Bongo ecosystem. It provides:

- **Compiled Assets**: Single CSS and JS bundles for admin interfaces
- **Vue Components**: 50+ reusable components for building admin UIs
- **Global Utilities**: Filters, directives, and event bus for cross-component communication
- **Consistent Theming**: TailwindCSS-based design system with custom brand colors

**Package Type**: Pure asset package (no routes, controllers, or models)

**Deployment Model**:
1. Assets compiled in this package (`npm run production`)
2. Published to Laravel app's public directory (`php artisan vendor:publish --tag=bongo:assets`)
3. Included in Blade templates via `<link>` and `<script>` tags

## Directory Structure

```
asset/
│
├── src/                                    # Source code root
│   │
│   ├── AssetServiceProvider.php            # Laravel service provider
│   │   └── Publishes: src/public/ → public_path()
│   │
│   ├── package.json                        # npm dependencies and build scripts
│   ├── webpack.mix.js                      # Laravel Mix build configuration
│   ├── tailwind.config.js                  # TailwindCSS theme configuration
│   │
│   ├── public/                             # Compiled assets (generated, git-ignored)
│   │   ├── css/
│   │   │   └── backend.css                 # Compiled CSS bundle
│   │   ├── js/
│   │   │   ├── backend.js                  # Compiled JS bundle
│   │   │   └── [name].bundle.js            # Code-split chunks
│   │   └── images/                         # Copied image assets
│   │
│   └── resources/                          # Source assets
│       │
│       ├── js/                             # JavaScript/Vue source
│       │   │
│       │   ├── backend.js                  # Vue app entry point
│       │   │   ├── Loads: jQuery, lodash, moment, axios, swal
│       │   │   ├── Configures: CSRF tokens, API tokens
│       │   │   ├── Registers: Filters, directives, components
│       │   │   └── Creates: Vue instance mounted to #app
│       │   │
│       │   ├── layout/                     # Layout components (5)
│       │   │   ├── Container.vue           # Main app container
│       │   │   ├── Header.vue              # Top header bar
│       │   │   ├── HeaderMenu.vue          # Header menu items
│       │   │   ├── Sidebar.vue             # Left sidebar navigation
│       │   │   └── Main.vue                # Main content area
│       │   │
│       │   ├── components/                 # Feature components (50+)
│       │   │   │
│       │   │   ├── DataTable/              # Data table with pagination
│       │   │   │   ├── DataTable.vue       # Main table container
│       │   │   │   ├── DataTableFilter.vue
│       │   │   │   ├── DataTablePagination.vue
│       │   │   │   ├── DataTablePerPage.vue
│       │   │   │   ├── DataTableSearch.vue
│       │   │   │   └── DataTableCount.vue
│       │   │   │
│       │   │   ├── FormBuilder/            # Drag-and-drop form builder
│       │   │   │   ├── FormBuilder.vue     # Parent container
│       │   │   │   ├── FormBuilderForm.vue # Form component
│       │   │   │   └── FormBuilderItem.vue # Individual field item
│       │   │   │
│       │   │   ├── MenuBuilder/            # Hierarchical menu editor
│       │   │   │   ├── MenuBuilder.vue     # Parent with dirty state
│       │   │   │   ├── MenuBuilderForm.vue # Form with entity types
│       │   │   │   └── MenuBuilderItem.vue # Recursive item display
│       │   │   │
│       │   │   ├── EstimatePlanBuilder/    # Plan item builder
│       │   │   │   ├── EstimatePlanBuilder.vue
│       │   │   │   ├── EstimatePlanForm.vue
│       │   │   │   └── EstimatePlanItem.vue
│       │   │   │
│       │   │   ├── ImageManager/           # Image upload/management
│       │   │   │   ├── ImageManager.vue
│       │   │   │   └── ImageManagerItem.vue
│       │   │   │
│       │   │   ├── DocumentManager/        # Document management
│       │   │   │   ├── DocumentManager.vue
│       │   │   │   └── DocumentManagerItem.vue
│       │   │   │
│       │   │   ├── GalleryBuilder/         # Gallery builder
│       │   │   │   ├── GalleryBuilder.vue
│       │   │   │   └── GalleryBuilderItem.vue
│       │   │   │
│       │   │   ├── SideMenu/               # Sidebar menu
│       │   │   │   ├── Menu.vue
│       │   │   │   └── MenuItem.vue
│       │   │   │
│       │   │   ├── Tabs/                   # Tab system
│       │   │   │   ├── Tabs.vue
│       │   │   │   └── Tab.vue
│       │   │   │
│       │   │   ├── Alert.vue               # Alert messages
│       │   │   ├── Button.vue              # Button component
│       │   │   ├── Card.vue                # Card container
│       │   │   ├── ComboBox.vue            # Multi-select dropdown
│       │   │   ├── ColorPicker.vue         # Color picker
│       │   │   ├── DatePicker.vue          # Date picker
│       │   │   ├── Dropdown.vue            # Generic dropdown
│       │   │   ├── Editor.vue              # WYSIWYG editor
│       │   │   ├── Error.vue               # Error display
│       │   │   ├── FileUploader.vue        # File upload
│       │   │   ├── Label.vue               # Form label
│       │   │   ├── Modal.vue               # Modal dialog
│       │   │   ├── Preview.vue             # Content preview
│       │   │   ├── Search.vue              # Search input
│       │   │   ├── Select.vue              # Select dropdown
│       │   │   ├── Spinner.vue             # Loading spinner
│       │   │   ├── CssEditor.vue           # CSS code editor
│       │   │   ├── CssEditorButton.vue     # CSS editor trigger
│       │   │   ├── CustomCssEditor.vue     # Custom CSS editor
│       │   │   ├── JsEditor.vue            # JS code editor
│       │   │   ├── JsEditorButton.vue      # JS editor trigger
│       │   │   ├── CustomJsEditor.vue      # Custom JS editor
│       │   │   ├── SchemaEditor.vue        # JSON schema editor
│       │   │   ├── SchemaEditorButton.vue  # Schema editor trigger
│       │   │   └── CustomSchemaEditor.vue  # Custom schema editor
│       │   │
│       │   └── vendor/                     # Third-party JS
│       │       ├── redactor.js             # Redactor WYSIWYG core
│       │       ├── redactor-alignment.js   # Text alignment plugin
│       │       ├── redactor-definedlinks.js # Predefined links
│       │       ├── redactor-fontcolor.js   # Font color picker
│       │       ├── redactor-source.js      # HTML source view
│       │       ├── redactor-table.js       # Table editor
│       │       ├── redactor-video.js       # Video embed
│       │       ├── PasswordStrength.js     # Password strength meter
│       │       ├── SEOHandler.js           # SEO utilities
│       │       ├── WysiwygHandler.js       # WYSIWYG helpers
│       │       └── SweetAlertHandler.js    # SweetAlert helpers
│       │
│       ├── sass/                           # Sass source files
│       │   │
│       │   ├── backend.scss                # Main Sass entry point
│       │   │   ├── @import tailwindcss/base
│       │   │   ├── @import tailwindcss/components
│       │   │   ├── @import components/index
│       │   │   ├── @import pages/index
│       │   │   ├── @import vendor/index
│       │   │   ├── @import tailwindcss/utilities
│       │   │   └── [v-cloak] styles
│       │   │
│       │   ├── components/                 # Custom component styles
│       │   │   ├── _code_mirror.scss       # CodeMirror overrides
│       │   │   ├── _preview.scss           # Preview component
│       │   │   ├── _tooltip.scss           # Tooltip styles
│       │   │   └── index.scss              # Component imports
│       │   │
│       │   ├── pages/                      # Page-specific styles
│       │   │   └── index.scss
│       │   │
│       │   └── vendor/                     # Third-party overrides
│       │       └── index.scss
│       │
│       └── images/                         # Source images (copied to public)
│
├── tests/                                  # PHPUnit tests
│   └── TestCase.php                        # Orchestra Testbench base
│
├── composer.json                           # PHP dependencies
├── phpunit.xml                             # PHPUnit configuration
├── .gitignore                              # Git ignore rules
├── .php_cs                                 # Legacy PHP CS Fixer config
├── .styleci.yml                            # StyleCI configuration
├── LICENSE                                 # MIT license
└── README.md                               # Package documentation
```

## Build Pipeline

### Build Flow Diagram

```
┌─────────────────────────────────────────────────────────────────┐
│                         Source Files                            │
└─────────────────────────────────────────────────────────────────┘
                                │
                                ▼
        ┌───────────────────────────────────────────┐
        │                                           │
        ▼                                           ▼
┌───────────────┐                          ┌───────────────┐
│ JavaScript    │                          │     Sass      │
│ Entry Point   │                          │ Entry Point   │
│ backend.js    │                          │ backend.scss  │
└───────────────┘                          └───────────────┘
        │                                           │
        ▼                                           ▼
┌───────────────┐                          ┌───────────────┐
│ Webpack       │                          │ Sass Loader   │
│ - Babel       │                          │ - TailwindCSS │
│ - Vue Loader  │                          │ - PostCSS     │
│ - Code Split  │                          │ - Autoprefixer│
└───────────────┘                          └───────────────┘
        │                                           │
        ▼                                           ▼
┌───────────────┐                          ┌───────────────┐
│ Minification  │                          │ PurgeCSS      │
│ (Production)  │                          │ (Production)  │
└───────────────┘                          └───────────────┘
        │                                           │
        └───────────────┬───────────────────────────┘
                        ▼
        ┌───────────────────────────────┐
        │  Compiled Assets (src/public) │
        │  - css/backend.css            │
        │  - js/backend.js              │
        │  - js/[name].bundle.js        │
        │  - images/*                   │
        └───────────────────────────────┘
                        │
                        ▼
        ┌───────────────────────────────┐
        │  Laravel Artisan Command      │
        │  vendor:publish               │
        │  --tag=bongo:assets           │
        └───────────────────────────────┘
                        │
                        ▼
        ┌───────────────────────────────┐
        │  Laravel Public Directory     │
        │  public/css/backend.css       │
        │  public/js/backend.js         │
        │  public/images/*              │
        └───────────────────────────────┘
                        │
                        ▼
        ┌───────────────────────────────┐
        │  Included in Blade Templates  │
        │  <link href="css/backend.css">│
        │  <script src="js/backend.js"> │
        └───────────────────────────────┘
```

### Build Configuration

**Laravel Mix** (`webpack.mix.js`):
- Public path: `./public`
- Resource root: `./resources`
- Entry points:
  - JS: `./resources/js/backend.js` → `./public/js/backend.js`
  - Sass: `./resources/sass/backend.scss` → `./public/css/backend.css`
- Code splitting: `js/[name].bundle.js`
- jQuery autoload: Global `$`, `jQuery`, `window.jQuery`
- Source maps: Development only

**TailwindCSS** (`tailwind.config.js`):
- Purge paths:
  - `./../../**/src/Views/**/*.blade.php` (sibling packages)
  - `./resources/js/**/*.vue` (local components)
- Custom theme: Colors, fonts, utilities
- Plugins: `@tailwindcss/ui`

**Package Scripts** (`package.json`):
```json
{
  "dev": "cross-env NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=development webpack",
  "watch": "cross-env NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=development webpack --watch",
  "production": "cross-env NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=production webpack"
}
```

## Vue Application Architecture

### Application Bootstrap Flow

```
┌─────────────────────────────────────────────────────────────┐
│                    browser loads backend.js                 │
└─────────────────────────────────────────────────────────────┘
                            │
                            ▼
        ┌───────────────────────────────────────┐
        │  1. Load Global Dependencies          │
        │     - jQuery → window.$               │
        │     - lodash → window._               │
        │     - moment → window.moment          │
        │     - axios → window.axios            │
        │     - SweetAlert2 → window.swal       │
        └───────────────────────────────────────┘
                            │
                            ▼
        ┌───────────────────────────────────────┐
        │  2. Configure Axios                   │
        │     - Set CSRF token header           │
        │     - Set API token header (if auth)  │
        │     - Enable withCredentials          │
        └───────────────────────────────────────┘
                            │
                            ▼
        ┌───────────────────────────────────────┐
        │  3. Load Redactor WYSIWYG             │
        │     - Core redactor.js                │
        │     - Plugins (alignment, table, etc) │
        │     - Handlers (SEO, Password, etc)   │
        └───────────────────────────────────────┘
                            │
                            ▼
        ┌───────────────────────────────────────┐
        │  4. Create Global Event Bus           │
        │     window.EventBus = new Vue()       │
        └───────────────────────────────────────┘
                            │
                            ▼
        ┌───────────────────────────────────────┐
        │  5. Register Global Filters           │
        │     date, percent, currency, truncate │
        │     uppercase, lowercase, ucwords, etc│
        └───────────────────────────────────────┘
                            │
                            ▼
        ┌───────────────────────────────────────┐
        │  6. Register Global Directives        │
        │     v-uppercase, v-alpha, v-numeric   │
        │     v-currency, v-date, v-maxnumber   │
        └───────────────────────────────────────┘
                            │
                            ▼
        ┌───────────────────────────────────────┐
        │  7. Register Global Components        │
        │     Layout: v-container, v-header, etc│
        │     UI: v-button, v-card, v-alert, etc│
        │     Features: data-table, builders, etc│
        └───────────────────────────────────────┘
                            │
                            ▼
        ┌───────────────────────────────────────┐
        │  8. Create Vue Instance               │
        │     new Vue({ el: '#app' })           │
        └───────────────────────────────────────┘
                            │
                            ▼
        ┌───────────────────────────────────────┐
        │  9. Mount to DOM                      │
        │     Vue compiles templates in #app    │
        │     Components become interactive     │
        └───────────────────────────────────────┘
```

### Global State Management

**Event Bus Pattern**:
```javascript
// Created in backend.js
window.EventBus = new Vue();

// Emit events from any component
EventBus.$emit('eventName', payload);

// Listen in any component
EventBus.$on('eventName', (payload) => {
    // Handle event
});

// Common events:
// - 'newItem' - Create new item
// - 'saveItem' - Save item
// - 'editItem' - Edit item
// - 'deleteItem' - Delete item
// - 'updateSortOrder' - Reorder items
```

**No Vuex**: This application uses the event bus pattern instead of Vuex for simplicity.

## Component Hierarchy

### Layout Component Structure

```
┌─────────────────────────────────────────────────────────────┐
│                        <v-container>                        │
│  ┌───────────────────────────────────────────────────────┐  │
│  │                     <v-header>                        │  │
│  │  ┌─────────────────────────────────────────────────┐  │  │
│  │  │            <v-header-menu>                      │  │  │
│  │  │  - Logo                                         │  │  │
│  │  │  - Navigation items                             │  │  │
│  │  │  - User menu                                    │  │  │
│  │  └─────────────────────────────────────────────────┘  │  │
│  └───────────────────────────────────────────────────────┘  │
│                                                              │
│  ┌──────────────┬───────────────────────────────────────┐   │
│  │ <v-sidebar>  │          <v-main>                     │   │
│  │              │  ┌─────────────────────────────────┐  │   │
│  │ - Menu       │  │   Page Content                  │  │   │
│  │ - Navigation │  │   - DataTables                  │  │   │
│  │              │  │   - Forms                       │  │   │
│  │              │  │   - Builders                    │  │   │
│  │              │  │   - Custom components           │  │   │
│  │              │  └─────────────────────────────────┘  │   │
│  └──────────────┴───────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘
```

### Builder Component Pattern

All builder components (FormBuilder, MenuBuilder, GalleryBuilder, etc.) follow this structure:

```
┌─────────────────────────────────────────────────────────────┐
│                     Builder Component                       │
│  ┌───────────────┬──────────────────────────────────────┐   │
│  │               │                                      │   │
│  │  BuilderForm  │        Items Display Area            │   │
│  │               │                                      │   │
│  │ ┌───────────┐ │  ┌────────────────────────────────┐ │   │
│  │ │ Mode:     │ │  │  State: loading                │ │   │
│  │ │ - create  │ │  │  ┌──────────────────────────┐  │ │   │
│  │ │ - edit    │ │  │  │   <v-spinner>            │  │ │   │
│  │ └───────────┘ │  │  │   "Loading items..."     │  │ │   │
│  │               │ │  │  └──────────────────────────┘  │ │   │
│  │ ┌───────────┐ │  └────────────────────────────────┘ │   │
│  │ │ Form      │ │                                      │   │
│  │ │ Fields    │ │  OR                                  │   │
│  │ │           │ │                                      │   │
│  │ │ [Save]    │ │  ┌────────────────────────────────┐ │   │
│  │ │ [Cancel]  │ │  │  State: has-items              │ │   │
│  │ └───────────┘ │  │  ┌──────────────────────────┐  │ │   │
│  │               │ │  │  │ <draggable>            │  │ │   │
│  │               │ │  │  │ ┌────────────────────┐ │  │ │   │
│  │ Events:       │ │  │  │ │ BuilderItem        │ │  │ │   │
│  │ - @newItem    │ │  │  │ │  - Edit button     │ │  │ │   │
│  │ - @saveItem   │ │  │  │ │  - Delete button   │ │  │ │   │
│  │               │ │  │  │ └────────────────────┘ │  │ │   │
│  │               │ │  │  │ ┌────────────────────┐ │  │ │   │
│  │               │ │  │  │ │ BuilderItem        │ │  │ │   │
│  │               │ │  │  │ └────────────────────┘ │  │ │   │
│  │               │ │  │  │ (Drag to reorder)      │  │ │   │
│  │               │ │  │  └────────────────────────┘  │ │   │
│  │               │ │  └────────────────────────────────┘ │   │
│  │               │ │                                      │   │
│  │               │ │  OR                                  │   │
│  │               │ │                                      │   │
│  │               │ │  ┌────────────────────────────────┐ │   │
│  │               │ │  │  State: no-items               │ │   │
│  │               │ │  │  ┌──────────────────────────┐  │ │   │
│  │               │ │  │  │  <v-card>                │  │ │   │
│  │               │ │  │  │  "No items found"        │  │ │   │
│  │               │ │  │  └──────────────────────────┘  │ │   │
│  │               │ │  └────────────────────────────────┘ │   │
│  └───────────────┴──────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

Events flowing up:
  BuilderItem → Builder: @editItem, @deleteItem
  BuilderForm → Builder: @newItem, @saveItem
  Builder → API: HTTP requests
```

### DataTable Component Pattern

```
┌─────────────────────────────────────────────────────────────┐
│                      <data-table>                           │
│  ┌───────────────────────────────────────────────────────┐  │
│  │                   Table Header                        │  │
│  │  ┌──────────┬──────────┬──────────────────────────┐  │  │
│  │  │ Per Page │  Search  │   Custom Filters (slot)  │  │  │
│  │  └──────────┴──────────┴──────────────────────────┘  │  │
│  └───────────────────────────────────────────────────────┘  │
│                                                              │
│  ┌───────────────────────────────────────────────────────┐  │
│  │                   Table Body (slot)                   │  │
│  │  ┌─────────────────────────────────────────────────┐  │  │
│  │  │  Default: Grid of v-card components             │  │  │
│  │  │  Custom: Consumer defines layout                │  │  │
│  │  │                                                  │  │  │
│  │  │  Scoped slot props:                             │  │  │
│  │  │  - items: Array of items                        │  │  │
│  │  │  - itemIndex: Get item index                    │  │  │
│  │  │  - isSelected: Check if selected                │  │  │
│  │  │  - setAsSelectedItem: Select item               │  │  │
│  │  │  - viewUrl: Generate view URL                   │  │  │
│  │  │  - editUrl: Generate edit URL                   │  │  │
│  │  │  - duplicateUrl: Generate duplicate URL         │  │  │
│  │  │  - builderUrl: Generate builder URL             │  │  │
│  │  └─────────────────────────────────────────────────┘  │  │
│  └───────────────────────────────────────────────────────┘  │
│                                                              │
│  ┌───────────────────────────────────────────────────────┐  │
│  │                   Table Footer                        │  │
│  │  ┌──────────────────┬───────────────────────────┐    │  │
│  │  │ Item Count       │  Pagination (if needed)   │    │  │
│  │  │ "Showing 1-10"   │  [1] [2] [3] ...          │    │  │
│  │  └──────────────────┴───────────────────────────┘    │  │
│  └───────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘
```

## Data Flow Patterns

### Builder Component Data Flow

```
┌──────────────────────────────────────────────────────────────┐
│                        User Actions                          │
└──────────────────────────────────────────────────────────────┘
                            │
        ┌───────────────────┴───────────────────┐
        │                                       │
        ▼                                       ▼
┌──────────────────┐                  ┌──────────────────┐
│  Click "New"     │                  │  Click "Edit"    │
│  in Form         │                  │  in Item         │
└──────────────────┘                  └──────────────────┘
        │                                       │
        ▼                                       ▼
┌──────────────────┐                  ┌──────────────────┐
│ EventBus.$emit   │                  │ EventBus.$emit   │
│ ('newItem')      │                  │ ('editItem',item)│
└──────────────────┘                  └──────────────────┘
        │                                       │
        └───────────────────┬───────────────────┘
                            ▼
                  ┌──────────────────┐
                  │ Builder Component│
                  │ Handles Event    │
                  └──────────────────┘
                            │
        ┌───────────────────┼───────────────────┐
        │                   │                   │
        ▼                   ▼                   ▼
┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│ Set mode     │  │ Set          │  │ Update form  │
│ to 'create'  │  │ currentItem  │  │ fields       │
└──────────────┘  └──────────────┘  └──────────────┘
                                              │
                                              ▼
                                    ┌──────────────────┐
                                    │ User fills form  │
                                    │ Clicks "Save"    │
                                    └──────────────────┘
                                              │
                                              ▼
                                    ┌──────────────────┐
                                    │ EventBus.$emit   │
                                    │ ('saveItem',data)│
                                    └──────────────────┘
                                              │
                                              ▼
                                    ┌──────────────────┐
                                    │ Builder handles  │
                                    │ Save event       │
                                    └──────────────────┘
                                              │
                                              ▼
                                    ┌──────────────────┐
                                    │ HTTP POST/PUT    │
                                    │ to API endpoint  │
                                    └──────────────────┘
                                              │
                ┌─────────────────────────────┼─────────────────────────────┐
                │                             │                             │
                ▼                             ▼                             ▼
        ┌──────────────┐            ┌──────────────┐            ┌──────────────┐
        │  Success     │            │  Error       │            │  Validation  │
        │  Response    │            │  Response    │            │  Error       │
        └──────────────┘            └──────────────┘            └──────────────┘
                │                             │                             │
                ▼                             ▼                             ▼
        ┌──────────────┐            ┌──────────────┐            ┌──────────────┐
        │ swal.fire()  │            │ swal.fire()  │            │ Show errors  │
        │ "Success!"   │            │ "Error!"     │            │ in form      │
        └──────────────┘            └──────────────┘            └──────────────┘
                │
                ▼
        ┌──────────────┐
        │ fetchItems() │
        │ Reload data  │
        └──────────────┘
                │
                ▼
        ┌──────────────┐
        │ Reset form   │
        │ mode='create'│
        └──────────────┘
```

### DataTable Data Flow

```
┌──────────────────────────────────────────────────────────────┐
│                    Component Mounted                         │
└──────────────────────────────────────────────────────────────┘
                            │
                            ▼
                  ┌──────────────────┐
                  │ fetchItems()     │
                  │ Initial load     │
                  └──────────────────┘
                            │
                            ▼
            ┌───────────────────────────────────┐
            │ Build query params:               │
            │ - page (pagination)               │
            │ - per_page (items per page)       │
            │ - search (search query)           │
            │ - filters (custom filters)        │
            │ - sort_by, sort_direction         │
            └───────────────────────────────────┘
                            │
                            ▼
                  ┌──────────────────┐
                  │ axios.get(       │
                  │   endpoint,      │
                  │   { params }     │
                  │ )                │
                  └──────────────────┘
                            │
                            ▼
                  ┌──────────────────┐
                  │ API Response     │
                  │ {                │
                  │   data: [...],   │
                  │   meta: {        │
                  │     total,       │
                  │     current_page,│
                  │     per_page     │
                  │   }              │
                  │ }                │
                  └──────────────────┘
                            │
                            ▼
                  ┌──────────────────┐
                  │ Update component │
                  │ state:           │
                  │ - items          │
                  │ - totalItems     │
                  │ - currentPage    │
                  │ - state          │
                  └──────────────────┘
                            │
        ┌───────────────────┼───────────────────┐
        │                   │                   │
        ▼                   ▼                   ▼
┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│ User changes │  │ User changes │  │ User changes │
│ search       │  │ per page     │  │ page         │
└──────────────┘  └──────────────┘  └──────────────┘
        │                   │                   │
        └───────────────────┴───────────────────┘
                            │
                            ▼
                  ┌──────────────────┐
                  │ fetchItems()     │
                  │ Reload with new  │
                  │ parameters       │
                  └──────────────────┘
```

## Styling Architecture

### Sass Import Hierarchy

```
backend.scss
│
├─── @import "tailwindcss/base"
│    └─── Tailwind base styles (normalize, etc)
│
├─── @import "tailwindcss/components"
│    └─── Tailwind component classes
│
├─── @import "components/index"
│    │
│    ├─── @import "_code_mirror"
│    │    └─── CodeMirror editor overrides
│    │
│    ├─── @import "_preview"
│    │    └─── Preview component styles
│    │
│    └─── @import "_tooltip"
│         └─── Tooltip styles
│
├─── @import "pages/index"
│    └─── Page-specific styles (if any)
│
├─── @import "vendor/index"
│    └─── Third-party library overrides
│
├─── @import "tailwindcss/utilities"
│    └─── Tailwind utility classes
│
└─── [v-cloak] { display: none; }
     └─── Hide Vue templates until mounted
```

### TailwindCSS Custom Theme

**Color Palette**:
```javascript
colors: {
  // Primary brand color (green-yellow)
  'primary': {
    100: '#D4E477',  // Lightest
    200: '#CEE166',
    300: '#C9DD55',
    400: '#C3DA44',
    500: '#BED62F',  // Base
    600: '#B4CC28',
    700: '#A5BB25',
    800: '#96AA22',
    900: '#87991E',  // Darkest
  },

  // Light greys
  'light': {
    100: '#F5F5F5',  // Very light
    500: '#EEEEEE',  // Base
    900: '#D9D9D9',  // Dark
  },

  // Medium greys
  'medium': {
    100: '#cccccc',
    500: '#888888',  // Base
    900: '#4B4B4B',
  },

  // Dark greys
  'dark': {
    100: '#444444',
    500: '#222222',  // Base
    900: '#161616',
    'alpha': 'rgba(0, 0, 0, 0.8)',
    'alpha-500': 'rgba(34, 34, 34, 0.8)',
  },
}
```

**Usage Pattern**:
- **Primary**: Buttons, links, highlights
- **Light**: Backgrounds, borders, subtle dividers
- **Medium**: Secondary text, disabled states
- **Dark**: Primary text, icons, strong emphasis

## Extension Points

### 1. Adding New Global Components

**Location**: `src/resources/js/backend.js`

```javascript
// Import component
Vue.component('your-component', require('./components/YourComponent').default);

// Or for component directories
Vue.component('your-builder', require('./components/YourBuilder/YourBuilder').default);
```

### 2. Adding New Global Filters

**Location**: `src/resources/js/backend.js`

```javascript
Vue.filter('yourFilter', function (value, arg1, arg2) {
    if (!value) return '';
    // Transform value
    return transformedValue;
});
```

### 3. Adding New Global Directives

**Location**: `src/resources/js/backend.js`

```javascript
Vue.directive('yourDirective', {
    bind: function (el, binding, vnode) {
        el.addEventListener("input", (e) => {
            e.target.value = transformValue(e.target.value);
        });
    }
});
```

### 4. Adding New Redactor Plugins

**Steps**:
1. Add plugin file to `src/resources/js/vendor/redactor-yourplugin.js`
2. Require in `backend.js`: `require('./vendor/redactor-yourplugin');`

### 5. Extending Tailwind Theme

**Location**: `src/tailwind.config.js`

```javascript
module.exports = {
    theme: {
        extend: {
            colors: {
                'your-color': {
                    '500': '#hexcode'
                }
            },
            spacing: {
                '72': '18rem',
                '84': '21rem',
                '96': '24rem',
            }
        }
    }
};
```

### 6. Adding Custom Sass Components

**Steps**:
1. Create `src/resources/sass/components/_your-component.scss`
2. Import in `src/resources/sass/components/index.scss`:
   ```scss
   @import "your-component";
   ```

## Adding New Features

### Creating a New Builder Component

**1. Create component directory**:
```bash
mkdir -p src/resources/js/components/YourBuilder
```

**2. Create three Vue files**:

**YourBuilder.vue** (Parent):
```vue
<template>
    <div class="your-builder" v-cloak>
        <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
            <div class="col-span-1">
                <your-builder-form
                    :current-item="currentItem"
                    :mode="mode"
                ></your-builder-form>
            </div>
            <div class="col-span-1">
                <div v-if="items && items.length" :class="['has-items', state]">
                    <draggable :list="items" @update="updateSortOrder">
                        <transition-group name="list" tag="div">
                            <your-builder-item
                                v-for="(item, index) in items"
                                :key="item.id"
                                :item="item"
                            ></your-builder-item>
                        </transition-group>
                    </draggable>
                </div>
                <div v-else :class="['no-items', state]">
                    <v-card>
                        <div class="message text-center">
                            <div class="message-text font-semibold">{{ message }}</div>
                        </div>
                    </v-card>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import YourBuilderForm from "./YourBuilderForm";
import YourBuilderItem from "./YourBuilderItem";
import Draggable from 'vuedraggable';

export default {
    name: "YourBuilder",
    components: { YourBuilderForm, YourBuilderItem, Draggable },
    props: {
        endpoint: { type: String, required: true }
    },
    data() {
        return {
            items: [],
            currentItem: null,
            mode: 'create',
            state: 'loading',
            message: 'Loading items...'
        };
    },
    mounted() {
        this.fetchItems();
        EventBus.$on('newItem', this.newItem);
        EventBus.$on('saveItem', this.saveItem);
        EventBus.$on('editItem', this.editItem);
        EventBus.$on('deleteItem', this.deleteItem);
    },
    beforeDestroy() {
        EventBus.$off('newItem', this.newItem);
        EventBus.$off('saveItem', this.saveItem);
        EventBus.$off('editItem', this.editItem);
        EventBus.$off('deleteItem', this.deleteItem);
    },
    methods: {
        fetchItems() {
            this.state = 'loading';
            this.message = 'Loading items...';

            axios.get(this.endpoint)
                .then(response => {
                    this.items = response.data.data;
                    this.state = this.items.length ? 'has-items' : 'no-items';
                    this.message = this.items.length ? '' : 'No items found';
                })
                .catch(error => {
                    this.state = 'error';
                    this.message = 'Failed to load items';
                });
        },
        newItem() {
            this.mode = 'create';
            this.currentItem = null;
        },
        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', 'Item saved successfully', 'success');
                    this.fetchItems();
                    this.newItem();
                })
                .catch(() => {
                    swal.fire('Error', 'Failed to save item', 'error');
                });
        },
        editItem(item) {
            this.mode = 'edit';
            this.currentItem = item;
        },
        deleteItem(item) {
            swal.fire({
                title: 'Are you sure?',
                text: 'This action cannot be undone',
                icon: 'warning',
                showCancelButton: true,
                confirmButtonText: 'Yes, delete it'
            }).then((result) => {
                if (result.isConfirmed) {
                    axios.delete(`${this.endpoint}/${item.id}`)
                        .then(() => {
                            swal.fire('Deleted', 'Item deleted successfully', 'success');
                            this.fetchItems();
                        })
                        .catch(() => {
                            swal.fire('Error', 'Failed to delete item', 'error');
                        });
                }
            });
        },
        updateSortOrder() {
            const ids = this.items.map(item => item.id);
            axios.post(`${this.endpoint}/reorder`, { ids })
                .then(() => {
                    swal.fire('Success', 'Order updated', 'success');
                })
                .catch(() => {
                    swal.fire('Error', 'Failed to update order', 'error');
                });
        }
    }
};
</script>
```

**YourBuilderForm.vue**:
```vue
<template>
    <v-card>
        <form @submit.prevent="handleSubmit">
            <!-- Form fields here -->
            <div class="flex justify-end space-x-2 mt-4">
                <v-button @click="handleNew">New</v-button>
                <v-button type="submit">Save</v-button>
            </div>
        </form>
    </v-card>
</template>

<script>
export default {
    props: {
        currentItem: Object,
        mode: String
    },
    data() {
        return {
            form: {
                // Form fields
            }
        };
    },
    watch: {
        currentItem(item) {
            if (item) {
                this.form = { ...item };
            } else {
                this.resetForm();
            }
        }
    },
    methods: {
        handleSubmit() {
            EventBus.$emit('saveItem', this.form);
        },
        handleNew() {
            EventBus.$emit('newItem');
            this.resetForm();
        },
        resetForm() {
            this.form = {
                // Reset to defaults
            };
        }
    }
};
</script>
```

**YourBuilderItem.vue**:
```vue
<template>
    <v-card>
        <template slot="left">
            <div class="font-semibold">{{ item.name }}</div>
        </template>
        <template slot="right">
            <v-button @click="handleEdit">Edit</v-button>
            <v-button @click="handleDelete">Delete</v-button>
        </template>
    </v-card>
</template>

<script>
export default {
    props: {
        item: { type: Object, required: true }
    },
    methods: {
        handleEdit() {
            EventBus.$emit('editItem', this.item);
        },
        handleDelete() {
            EventBus.$emit('deleteItem', this.item);
        }
    }
};
</script>
```

**3. Register globally**:

In `src/resources/js/backend.js`:
```javascript
Vue.component('your-builder', require('./components/YourBuilder/YourBuilder').default);
```

**4. Rebuild assets**:
```bash
npm run dev
```

**5. Use in Blade templates**:
```blade
<your-builder endpoint="/api/your-endpoint"></your-builder>
```

### Creating a New UI Component

**1. Create component file**:
```bash
touch src/resources/js/components/YourComponent.vue
```

**2. Component template**:
```vue
<template>
    <div class="your-component">
        <!-- Use Tailwind utilities -->
        <slot></slot>
    </div>
</template>

<script>
export default {
    name: "YourComponent",
    props: {
        variant: { type: String, default: 'default' }
    }
};
</script>
```

**3. Register and rebuild** (same as above).

### Publishing Updated Assets

**1. Build for production**:
```bash
cd /Users/stuart/Packages/bongo/default/asset/src
npm run production
```

**2. Commit changes**:
```bash
cd /Users/stuart/Packages/bongo/default/asset
git add .
git commit -m "Add new component"
git push
```

**3. Publish to Laravel app**:
```bash
php artisan vendor:publish --tag=bongo:assets --force
```

**4. Clear cache** (in Laravel app):
```bash
php artisan cache:clear
php artisan view:clear
```

---

**End of Architecture Documentation**
