# Module Controllers

## Introduction

In Concord CRM, the backend (Laravel) and front-end (Vue) are separate entities. The backend is responsible for storing and providing data, while the front-end processes and displays this data to the user.

When developing new modules, it's recommended to build a module API to enable interaction between the front-end and the backend. For instance, when the front-end needs to create an invoice, it sends an HTTP request to the backend. The backend then creates the invoice, sends an email, and returns the created invoice data, which the front-end displays to the user.

Creating modules involves building an API that integrates seamlessly with the existing features of Concord CRM. This ensures that new functionalities works fine within the established system.

## Creating API Controller

To create an API controller, you should place the controller in the module `app/Http/Controllers/Api` directory, this will ensure to separate the API related controllers from any `web` controllers if needed to be added later.

    // modules/Invoices/app/Http/Controllers/Api

    namespace Modules\Invoices\Http\Controllers\Api;

    use Modules\Core\Http\Controllers\ApiController;
    use Illuminate\Http\Request;
    use Illuminate\Http\JsonResponse;
    use Modules\Invoices\Models\Invoice;

    class InvoiceStatusController extends ApiController
    {
        public function update(string $id, string $status, Request $request) : JsonResponse
        {
            $invoice = Invoice::findOrFail($id);

            $this->authorize('update', $invoice);

            match($status) {
                'paid'  => $invoice->markAsPaid(),
                default => abort("Invalid Status", JsonResponse::HTTP_CONFLICT),
            };

            return $this->response(new InvoiceResource($invoice), JsonResponse::HTTP_OK);
        }
    }

Refer to Laravel controllers documentation for more information if you are not familiar on how controllers work.

When using the resources feature in Concord CRM, you don't need to create controllers for the following actions:

Verb | URI
--- | ---
GET | /invoices
POST | /invoices
GET | /invoices/{invoice}
PUT/PATCH | /invoices/{invoice}
DELETE | /invoices/{invoice}

## Registering API Routes

When you create a module with the `module:make` command, the scaffoling module code will already register the API related route groups and will create an `routes/api.php` file.

You should use this file to register any API routes for the module.

    // modules/Invoices/routes/api.php

    use Illuminate\Support\Facades\Route;
    use Modules\Invoices\Http\Controllers\Api\InvoiceStatusController;

    Route::middleware('auth:sanctum')->group(function () {
        Route::post('/invoices/{invoice}/{status}', [InvoiceStatusController::class, 'update']);
    });

All routes registered in the `api.php` file, will be prefixed with `api`, for example, the route we registered above will be accessible under the `/api/invoices/{invoice}/{status}` endpoint.

Refer to Laravel routing documentation for more information if you are not familiar on how routing work.

## Registering Web Routes

When you create a module using the `module:make` command, the web routes by default will be disabled, if you need to register web routes, in the module `RouteServiceProvider.php` file uncomment the web route registration.

The module `map` method should look like this:

    /**
    * Define the routes for the application.
    */
    public function map(): void
    {
        $this->mapApiRoutes();

        $this->mapWebRoutes();
    }

In the module `routes` directory, there should be a `web.php` file responsible for registering all the web middleware routes.

    // modules/Invoices/routes/web.php

    use Illuminate\Support\Facades\Route;

    Route::middleware(['auth', 'admin'])->group(function () {
        Route::get(...);
    });

## Making HTTP Requests

To make HTTP requests from the front-end, you can use `Innoclapps.request()`, please refer to the dedicated frontend documentation.

    <template> {{ invoice ? invoice.number : ''}} </template>
    <script setup>
        import { onMounted, ref } from "vue";

        const invoice = ref(null);

        async function fetchInvoice() {
            const { data } = await Innoclapps.request("/invoices/1");

            invoice.value = data;
        }

        async function updateInvoice() {
            const { data } = Innoclapps.request().put("/invoices/1", {
                number: 1,
            });

            invoice.value = data;
        }

        onMounted(fetchInvoice);
    </script>

By calling `Innoclapps.request()` you will receive Axios instance pre-configured for Concord CRM with correct API prefix that you can use to make HTTP request to the specified route URL.