Skip to content

Latest commit

 

History

History
255 lines (230 loc) · 6.05 KB

examples.md

File metadata and controls

255 lines (230 loc) · 6.05 KB

Examples

Eloquent Models

An example of Eloquent model.

<?php

namespace Kiwilan\Typescriptable\Tests\Data\Models;

use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Concerns\HasUlids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Kiwilan\Typescriptable\Tests\Data\Enums\PublishStatusEnum;
use Kiwilan\Typescriptable\Tests\Data\Models\Nested\Author;
use Spatie\Image\Enums\Fit;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Media;

class Movie extends Model implements \Spatie\MediaLibrary\HasMedia
{
    use HasFactory;
    use HasUlids;
    use InteractsWithMedia;

    protected $fillable = [
        'title',
        'year',
        'subtitles',
        'french_title',
        'original_title',
        'release_date',
        'original_language',
        'overview',
        'popularity',
        'is_adult',
        'tagline',
        'homepage',
        'status',
        'certification',
        'tmdb_url',
        'poster',
        'poster_tmdb',
        'poster_color',
        'backdrop',
        'backdrop_tmdb',
        'added_at',
        'fetched_at',
        'fetched_has_failed',
        'slug',
        'revenue',
        'edition',
        'version',
        'library',
        'is_multilingual',
    ];

    protected $casts = [
        'subtitles' => 'array',
        'budget' => PublishStatusEnum::class,
        'homepage' => PublishStatusEnum::class,
        'revenue' => 'integer',
        'is_multilingual' => 'boolean',
        'added_at' => 'datetime:Y-m-d',
    ];

    protected $appends = [
        'show_route',
        'api_route',
    ];

    protected $hidden = [
        'budget',
        'edition',
    ];

    public function registerMediaConversions(?Media $media = null): void
    {
        $this
            ->addMediaConversion('preview')
            ->fit(Fit::Contain, 300, 300)
            ->nonQueued();
    }

    public function getShowRouteAttribute(): string
    {
        return 'movies.show';
    }

    /**
     * @return string
     */
    protected function apiRoute(): Attribute
    {
        return Attribute::make(
            get: fn (?string $value) => ucfirst($value),
        );
    }

    public function similars(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
    {
        return $this->belongsToMany(Movie::class, 'similars', 'movie_id', 'similar_id');
    }

    public function recommendations(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
    {
        return $this->belongsToMany(Movie::class, 'recommendations', 'movie_id', 'recommendation_id');
    }

    public function members(): \Illuminate\Database\Eloquent\Relations\MorphToMany
    {
        return $this
            ->morphToMany(Member::class, 'memberable')
            ->withPivot([
                'character',
                'job',
                'department',
                'order',
                'is_adult',
                'known_for_department',
                'is_crew',
            ])
            ->orderBy('order');
    }

    public function author(): BelongsTo
    {
        return $this->belongsTo(Author::class, 'author_id');
    }
}

TS file generated at resources/js/types-eloquent.d.ts

declare namespace App.Models {
    export interface Movie {
        id: string;
        tmdb_id?: number;
        title?: string;
        year?: number;
        subtitles: any[];
        slug: string;
        french_title?: string;
        original_title?: string;
        release_date?: string;
        original_language?: string;
        overview?: string;
        popularity?: number;
        is_adult?: number;
        homepage?: "draft" | "scheduled" | "published";
        tagline?: string;
        status?: string;
        certification?: string;
        tmdb_url?: string;
        imdb_id?: string;
        runtime?: number;
        budget: "draft" | "scheduled" | "published";
        revenue?: number;
        edition?: string;
        version?: string;
        library?: string;
        is_multilingual: boolean;
        poster?: string;
        poster_tmdb?: string;
        poster_color?: string;
        backdrop?: string;
        backdrop_tmdb?: string;
        author_id?: number;
        added_at?: string;
        fetched_at?: string;
        fetched_has_failed: number;
        created_at?: string;
        updated_at?: string;
        show_route?: string;
        api_route?: string;
        similars_count?: number;
        recommendations_count?: number;
        members_count?: number;
        media_count?: number;
        similars?: App.Models.Movie[];
        recommendations?: App.Models.Movie[];
        members?: App.Models.Member[];
        author?: App.Models.NestedAuthor;
        media?: any[];
    }
}

declare namespace App {
    export interface PaginateLink {
        url: string;
        label: string;
        active: boolean;
    }
    export interface Paginate<T = any> {
        data: T[];
        current_page: number;
        first_page_url: string;
        from: number;
        last_page: number;
        last_page_url: string;
        links: App.PaginateLink[];
        next_page_url: string;
        path: string;
        per_page: number;
        prev_page_url: string;
        to: number;
        total: number;
    }
    export interface ApiPaginate<T = any> {
        data: T[];
        links: {
            first?: string;
            last?: string;
            prev?: string;
            next?: string;
        };
        meta: {
            current_page: number;
            from: number;
            last_page: number;
            links: App.PaginateLink[];
            path: string;
            per_page: number;
            to: number;
            total: number;
        };
    }
}

Vue component

Usage in Vue component.

<script lang="ts" setup>
defineProps<{
    movie?: App.Models.Movie;
}>();
</script>

Or with paginate option.

<script lang="ts" setup>
defineProps<{
    movies?: App.Paginate<App.Models.Movie>;
}>();
</script>