Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/astrxnomo/eventify-app/llms.txt

Use this file to discover all available pages before exploring further.

Events are the core entity in Eventify. Each event record brings together a name, rich description, cover image, pricing, capacity tracking, a geocoded location, and metadata such as category and status — giving organizers a complete picture of every event they run and giving attendees everything they need to discover and attend.

Event Model Fields

Every event is stored in the events table. The table is defined by the migration below and the corresponding Event Eloquent model.
id
bigint
required
Auto-incrementing primary key.
name
string
required
Public-facing title of the event.
description
text
required
Full description of the event shown on the event detail page.
img_url
string
required
Relative storage path to the event’s cover image (e.g. images/example.jpg). Served via the public disk.
capacity
integer
required
Remaining tickets available for purchase. Decremented on each ticket sale.
attendees
integer
Running count of tickets sold. Incremented on each ticket sale. Defaults to 0.
price
integer
required
Ticket price in the application’s base currency unit.
start_date
datetime
required
Date and time the event begins.
end_date
datetime
required
Date and time the event ends.
user_id
bigint
Foreign key referencing the users table. Set to null if the owning user is deleted.
location_id
bigint
Foreign key referencing the locations table. Set to null if the location is deleted.
category_id
bigint
Foreign key referencing the categories table. Set to null if the category is deleted.
status_id
bigint
Foreign key referencing the statuses table. Defaults to 1 (Disponible). Set to null if the status is deleted.
deleted_at
timestamp
Column defined by $table->softDeletes() in the migration. Note: the Event model does not use the SoftDeletes trait, so this column is not automatically managed by Eloquent.
The full migration that creates this table:
Schema::create('events', function (Blueprint $table) {
    $table->id();

    $table->unsignedBigInteger('user_id')->nullable();
    $table->foreign('user_id')->references('id')->on('users')->onDelete('set null');

    $table->unsignedBigInteger('status_id')->default(1)->nullable();
    $table->foreign('status_id')->references('id')->on('statuses')->onDelete('set null');

    $table->unsignedBigInteger('location_id')->nullable();
    $table->foreign('location_id')->references('id')->on('locations')->onDelete('set null');

    $table->unsignedBigInteger('category_id')->nullable();
    $table->foreign('category_id')->references('id')->on('categories')->onDelete('set null');

    $table->string('name');
    $table->text('description');
    $table->string('img_url');
    $table->integer('capacity');
    $table->integer('attendees')->default(0);
    $table->integer('price');
    $table->dateTime('start_date');
    $table->dateTime('end_date');
    $table->softDeletes();
    $table->timestamps();
});

Creating Events

Authenticated users (and admins) create events through the dashboard at GET /dashboard/events/create. The creation form collects the following fields:
Form FieldInput NameDescription
Event NameeventNameTitle of the event
DescriptioneventDescriptionFull event description
Cover ImageeventImageImage file upload
CategoryeventCategoryID from the categories table
CapacityeventCapacityTotal ticket supply
PriceeventPricePer-ticket price
Start DateeventStartDateDatetime the event begins
End DateeventEndDateDatetime the event ends
Street AddresseventAddressStreet-level address
CityeventCityCity name
RegioneventRegionState, province, or region
CountryeventCountryCountry name
When the form is submitted to POST /dashboard/events/store, EventController::store() runs the following sequence:
1

Create the Location record

A new Location is instantiated and populated with country, city, region, and address from the request.
2

Geocode the address via Nominatim

The controller builds a combined address string (address, city) and issues a GET request to the Nominatim OpenStreetMap API using a Guzzle HTTP client:
$fullAddress = $location->address . ', ' . $location->city;

$client = new Client();
$url = "https://nominatim.openstreetmap.org/search?q="
    . urlencode($fullAddress)
    . "&format=json&limit=1";

$response = $client->request('GET', $url, [
    'headers' => ['User-Agent' => 'eventify-app']
]);

$data = json_decode($response->getBody(), true);

if (!empty($data)) {
    $location->latitude  = $data[0]['lat'];
    $location->longitude = $data[0]['lon'];
} else {
    $location->latitude  = null;
    $location->longitude = null;
}
Coordinates are stored on the Location record. If the Nominatim lookup returns no results, latitude and longitude are saved as null.
3

Save the Location

$location->save() persists the record and provides the id needed for the foreign key.
4

Build the Event

A new Event is instantiated and all form fields are assigned, including user_id from auth()->id() and location_id from the saved location.
5

Upload the cover image

If an image was included in the request, it is stored in the public disk under the images/ directory:
if ($request->hasFile('eventImage')) {
    $path = $request->file('eventImage')->store('images', 'public');
    $event->img_url = $path;
}
6

Auto-assign status

The event’s status is determined automatically based on the initial capacity:
if ($event->capacity > 0) {
    $event->status_id = 1; // Disponible
} else {
    $event->status_id = 2; // Agotado
}
7

Save the Event

$event->save() persists the record, and the user is redirected to /dashboard/events with a success message.
Image uploads require that you have created a symbolic link from public/storage to storage/app/public. Run the following command once after deployment:
php artisan storage:link
Without this link, uploaded cover images will not be publicly accessible.

Editing Events

Organizers can edit their events via GET /dashboard/events/edit/{event}, which loads the edit form pre-populated with the existing values. Changes are submitted via PATCH /dashboard/events/{event}, handled by EventController::update(). The update logic handles two important cases: Image replacement — If a new image file is uploaded, the controller deletes the old image from storage before saving the new one:
if ($request->hasFile('eventImage')) {
    if ($event->img_url) {
        Storage::delete('public/' . $event->img_url);
    }
    $path = $request->file('eventImage')->store('events', 'public');
    $event->img_url = $path;
}
Geocoding on address change — The controller compares the incoming address and city values against the current Location record. Re-geocoding is triggered only when something has actually changed, avoiding unnecessary API calls:
$addressChanged = $location->address !== $request->input('eventAddress')
               || $location->city    !== $request->input('eventCity');

if ($addressChanged) {
    $fullAddress = $location->address . ', ' . $location->city;

    $client = new Client();
    $url = "https://nominatim.openstreetmap.org/search?q="
        . urlencode($fullAddress)
        . "&format=json&limit=1";

    $response = $client->request('GET', $url, [
        'headers' => ['User-Agent' => 'eventify-app']
    ]);

    $data = json_decode($response->getBody(), true);

    if (!empty($data)) {
        $location->latitude  = $data[0]['lat'];
        $location->longitude = $data[0]['lon'];
    } else {
        $location->latitude  = null;
        $location->longitude = null;
    }
}
On the edit form, admins can also manually override the status_id field — for example, to mark an event as Finalizado after it has concluded.

Event Status

Status is automatically managed by the application and reflects the current availability of an event. The assignment logic is applied both at creation time and during ticket purchases:
Conditionstatus_idLabel
Created with capacity > 01Disponible
Created with capacity == 02Agotado
Last ticket sold (capacity reaches 0)2Agotado
Manually set by admin after the event3Finalizado
See Categories & Status for the full list of status labels and their meanings.

Deleting Events

Events are deleted via DELETE /dashboard/events/delete/{event}, handled by EventController::destroy():
public function destroy(string $id)
{
    $event = Event::findOrFail($id);
    $event->delete();
    return redirect()->route('events.index');
}
The events table migration defines a deleted_at column via $table->softDeletes(), but the Event model does not use the SoftDeletes trait. As a result, $event->delete() performs a hard delete — the row is permanently removed from the database. Ticket records and any other data referencing the deleted event’s ID will lose their association.

Explore Page

The public /explore route displays all events to unauthenticated and authenticated visitors alike. Events are ordered from newest to oldest:
public function showExplore()
{
    $events = Event::orderBy('created_at', 'desc')->get();
    return view('explore', compact('events'));
}
The home page (/) uses the same ordering logic via showHome(), providing a consistent discovery experience across both surfaces.

PDF Reports

Authenticated users can download a PDF summary of any event by visiting:
GET /events/{event}/report
The EventController::downloadEventReport() method loads the reports.event-report Blade view and streams it as a PDF download using the DomPDF library:
public function downloadEventReport(Event $event)
{
    $data = compact('event');
    $pdf  = Pdf::loadView('reports.event-report', $data);
    return $pdf->download('event-' . $event->id . '.pdf');
}
The downloaded file is named event-{id}.pdf. The report view receives the full $event model instance, including its related location, category, status, and ticket data.
The PDF report route is defined outside the /dashboard prefix group and carries no auth middleware. It is publicly accessible to any visitor who knows or guesses the event ID. If you want to restrict report downloads to authenticated users, add the auth middleware to this route in routes/web.php.

Relationships

The Event model declares the following Eloquent relationships:
// Event belongs to the user who created it
public function user()
{
    return $this->belongsTo(User::class);
}

// Event belongs to a location (geocoded address)
public function location()
{
    return $this->belongsTo(Location::class);
}

// Event belongs to a category
public function category()
{
    return $this->belongsTo(Category::class);
}

// Event belongs to a status
public function status()
{
    return $this->belongsTo(Status::class);
}

// Event has many tickets
public function tickets()
{
    return $this->hasMany(Ticket::class);
}

User

The organizer who created the event. Foreign key user_id; set to null on user deletion.

Location

A dedicated locations record holding address, city, region, country, and geocoded latitude/longitude.

Category

One of the seeded categories (Musical, Teatro, Deportivo, etc.) used for filtering and discovery.

Status

Reflects current availability — Disponible, Agotado, or Finalizado.

Build docs developers (and LLMs) love