'boolean', 'start_at' => 'datetime', 'end_at' => 'datetime', 'latitude' => 'float', 'longitude' => 'float', 'estimated_duration_min' => 'integer', 'status' => HuntStatus::class, 'difficulty' => HuntDifficulty::class, ]; public function steps(): HasMany { return $this->hasMany(HuntSteps::class, 'hunt_id'); } public function participants(): BelongsToMany { return $this->belongsToMany(User::class, 'hunt_participants', 'hunt_id', 'user_id') ->withPivot(['current_step_number', 'status']) ->withTimestamps(); } /** * Configure Meilisearch index settings */ public function searchableOptions(): array { return [ 'filterableAttributes' => [ 'city', 'difficulty', 'status', 'is_public', 'creator_id', 'participant_ids', 'start_at_timestamp', 'end_at_timestamp', 'created_at_timestamp', ], 'sortableAttributes' => [ 'start_at_timestamp', 'end_at_timestamp', 'created_at_timestamp', ], ]; } /** * @return array{ * id: int, * title: string, * slug: string, * description: string|null, * city: string, * status: string, * difficulty: string, * is_public: bool, * creator_id: int, * latitude: float|null, * longitude: float|null, * start_at: string|null, * end_at: string|null, * start_at_timestamp: int|null, * end_at_timestamp: int|null, * created_at_timestamp: int, * participant_ids: array * } */ public function toSearchableArray(): array { $status = $this->status instanceof HuntStatus ? $this->status->value : $this->status; $difficulty = $this->difficulty instanceof HuntDifficulty ? $this->difficulty->value : $this->difficulty; try { $participantIds = $this->participants()->pluck('user_id')->toArray(); } catch (\Throwable $e) { \Illuminate\Support\Facades\Log::error('TO_SEARCHABLE_ARRAY_PARTICIPANTS_ERROR', [ 'hunt_id' => $this->id, 'error' => $e->getMessage(), ]); $participantIds = []; } return [ 'id' => $this->id, 'title' => $this->title, 'slug' => $this->slug, 'description' => $this->description, 'city' => $this->city, 'status' => $status, 'difficulty' => $difficulty, 'is_public' => $this->is_public, 'creator_id' => $this->creator_id, 'latitude' => $this->latitude, 'longitude' => $this->longitude, 'start_at' => $this->start_at?->toAtomString(), 'end_at' => $this->end_at?->toAtomString(), // Timestamps Unix pour les filtres de date dans Meilisearch 'start_at_timestamp' => $this->start_at?->timestamp, 'end_at_timestamp' => $this->end_at?->timestamp, 'created_at_timestamp' => $this->created_at->timestamp, // IDs des participants pour le filtre de participation 'participant_ids' => $participantIds, ]; } }