Skip to main content

Overview

The CategoryController is a resource controller that handles CRUD operations for transaction categories. It supports HTMX for dynamic UI updates and provides customization options including colors, shades, and icons. Namespace: App\Http\Controllers Extends: Controller

Routes

MethodURINameMiddleware
GET/categoriescategories.indexauth, verified
GET/categories/createcategories.createauth, verified
POST/categoriescategories.storeauth, verified
GET/categories/{category}categories.showauth, verified, can:view,category
GET/categories/{category}/editcategories.editauth, verified, can:update,category
PATCH/categories/{category}categories.updateauth, verified, can:update,category
DELETE/categories/{category}categories.destroyauth, verified, can:delete,category

Properties

protected array $availableColors;
protected string $selectedColor;
protected string $colorShade;
Initialized in constructor with default category color options and shade (300).

Methods

index()

Displays categories grouped by type (income and expense).
public function index()

Returns

Returns the categories.index view with:
  • incomeCategories - Collection of income categories with transaction counts
  • expenseCategories - Collection of expense categories with transaction counts

Example Request

curl -X GET https://your-app.com/categories \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"

Example Response

{
  "incomeCategories": [
    {
      "id": 1,
      "name": "Salary",
      "type": "income",
      "color": "emerald",
      "shade": "300",
      "icon": "salary",
      "transactions_count": 12
    },
    {
      "id": 2,
      "name": "Freelance",
      "type": "income",
      "color": "blue",
      "shade": "300",
      "icon": "freelance",
      "transactions_count": 8
    }
  ],
  "expenseCategories": [
    {
      "id": 5,
      "name": "Groceries",
      "type": "expense",
      "color": "red",
      "shade": "300",
      "icon": "groceries",
      "transactions_count": 45
    }
  ]
}

create()

Shows the form for creating a new category.
public function create(HtmxRequest $request)

Returns

Returns the categories.create view with:
  • availableColors - Array of available color options
  • selectedColor - Default color selection
  • colorShade - Default shade value (300)
  • icons - Collection of available icon files from public/images/categories
  • selectedIcon - Default icon name (“image”)

Example Request

curl -X GET https://your-app.com/categories/create \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"

store()

Stores a newly created category.
public function store(CategoryRequest $request)
name
string
required
Category name
type
string
required
Category type: income or expense
color
string
required
Color identifier (e.g., “emerald”, “blue”, “red”)
shade
string
required
Color shade value (e.g., “300”, “500”)
icon
string
required
Icon filename without extension

Behavior

  • Creates the category with validated attributes
  • Redirects to categories index
  • If type is “income”, adds tab=2 query parameter to show income tab
  • Displays success toast message

Example Request

curl -X POST https://your-app.com/categories \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Dining Out",
    "type": "expense",
    "color": "orange",
    "shade": "300",
    "icon": "restaurant"
  }'

Example Response

{
  "success": true,
  "message": "Category created successfully.",
  "redirect": "/categories"
}

show()

Displays details of a specific category. Supports HTMX requests.
public function show(HtmxRequest $request, Category $category)
category
Category
required
The category model instance to display

Returns

  • For HTMX requests: Returns an HTMX fragment targeting the panel element
  • For regular requests: Returns the categories.show view

Example Request

curl -X GET https://your-app.com/categories/5 \
  -H "Authorization: Bearer {token}" \
  -H "HX-Request: true"

edit()

Shows the form for editing a category. Supports HTMX requests.
public function edit(HtmxRequest $request, Category $category)
category
Category
required
The category model instance to edit

Returns

  • For HTMX requests: Returns an HTMX fragment targeting the form element
  • For regular requests: Returns the categories.edit view
Both responses include:
  • category - The category being edited
  • availableColors - Array of color options
  • selectedColor - Current category color
  • colorShade - Current shade value
  • icons - Available icon files
  • selectedIcon - Current category icon

Example Request

curl -X GET https://your-app.com/categories/5/edit \
  -H "Authorization: Bearer {token}" \
  -H "HX-Request: true"

update()

Updates an existing category with special handling for type changes.
public function update(CategoryRequest $request, Category $category)
category
Category
required
The category model instance to update
name
string
required
Updated category name
type
string
required
Updated category type: income or expense
color
string
required
Updated color identifier
shade
string
required
Updated shade value
icon
string
required
Updated icon filename

Behavior

  • Updates the category with validated attributes
  • If category type changed:
    • Performs a full page redirect to appropriate tab
    • Retargets the HTMX response to the new type’s list
    • Inserts at the beginning of the list
  • If type unchanged:
    • Performs in-place update via HTMX
    • Replaces the existing element

Example Request

curl -X PATCH https://your-app.com/categories/5 \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "HX-Request: true" \
  -d '{
    "name": "Updated Dining",
    "type": "expense",
    "color": "amber",
    "shade": "400",
    "icon": "food"
  }'

Example Response (HTMX - Type Unchanged)

{
  "HX-Push-Url": "/categories",
  "HX-Retarget": "this",
  "HX-Reswap": "outerHTML",
  "html": "<div id='panel'>...</div>"
}

Example Response (HTMX - Type Changed)

{
  "HX-Location": "/categories?tab=2",
  "HX-Retarget": "#income-list",
  "HX-Reswap": "afterbegin",
  "html": "<div id='panel'>...</div>"
}

destroy()

Deletes a category.
public function destroy(Category $category)
category
Category
required
The category model instance to delete

Behavior

  • Deletes the category
  • Returns empty response (for HTMX)
Deleting a category that has associated transactions may cause database constraint errors unless proper cascade rules are configured.

Example Request

curl -X DELETE https://your-app.com/categories/5 \
  -H "Authorization: Bearer {token}" \
  -H "HX-Request: true"

Category Types

The system supports the following category types:
  • income - For income transactions (salary, freelance, etc.)
  • expense - For expense transactions (groceries, rent, etc.)
  • correction - System-generated categories for balance corrections
  • transfer - System-generated categories for account transfers
The correction and transfer types are typically created automatically by the system and used internally for balance adjustments and account transfers.

Icon Management

Category icons are stored as image files in the public/images/categories directory. The controller reads available icons dynamically from this directory. Supported Icon Operations:
  • Icons are displayed by filename (without extension)
  • Available icons are loaded from the filesystem
  • Custom icons can be added by placing files in the categories directory

Dependencies

  • App\Http\Requests\CategoryRequest - Form request validation
  • App\Models\Category - Category model
  • Illuminate\Support\Facades\Auth - Authentication facade
  • Illuminate\Support\Facades\File - File system operations
  • Mauricius\LaravelHtmx\Http\HtmxRequest - HTMX request handler
  • Mauricius\LaravelHtmx\Facades\HtmxResponse - HTMX response builder

Helper Functions

  • flashToast($type, $message) - Displays toast notification

Authorization

All routes require authentication and email verification. View, edit, update, and delete operations are additionally protected by Laravel policy gates that check ownership.

HTMX Integration

This controller heavily utilizes HTMX for dynamic UI updates:
  • Fragment Responses: Returns partial HTML fragments instead of full pages
  • Dynamic Retargeting: Changes target elements based on context
  • Smart Reswapping: Uses different swap strategies (outerHTML, afterbegin) based on operation
  • URL Management: Pushes URLs to browser history for proper navigation

Build docs developers (and LLMs) love