@php use App\Enums\PriceType; use App\Enums\PriceTypeTravaux; use App\Enums\MarketingTagType; use App\Enums\Fiscalite; use Illuminate\Support\Facades\Auth; // Image - utiliser le CDN $firstMedia = $program->getFirstMedia('images'); $imageUrl = $firstMedia ? getImageFromCDN($firstMedia, 'miniature') : ($themeLogo ?? asset('assets/img/logo.png')); // Prix minimum depuis les lots (uniquement les lots non vendus) // Utiliser les lots déjà chargés si disponibles, sinon faire une requête $lots = $program->relationLoaded('lots') ? $program->lots : $program->lots()->with(['prices', 'states'])->get(); $isDenormandie = $program->fiscalites->contains(function ($fiscalite) { return (($fiscalite->type->value ?? null) === Fiscalite::DENORMANDIE->value); }); // Filtrer les lots non vendus avec un prix de référence > 0 $availableLots = $lots->filter(function($lot) use ($isDenormandie) { // Exclure les lots vendus $isVendu = $lot->states->contains(function($state) { return $state->type->value === \App\Enums\ProductState::VENDU->value; }); if ($isVendu) { return false; } $startingPrice = $isDenormandie ? $lot->getTotalLotEtAnnexes() : ($lot->prices->where('type', PriceType::PRIX_IMMO_TTC->value)->first()?->value ?? 0); return $startingPrice > 0; }); // Trouver le prix minimum $minPrice = 0; if ($availableLots->count() > 0) { $prices = $availableLots->map(function($lot) use ($isDenormandie) { return $isDenormandie ? $lot->getTotalLotEtAnnexes() : ($lot->prices->where('type', PriceType::PRIX_IMMO_TTC->value)->first()?->value ?? 0); })->filter(function($price) { return $price > 0; }); if ($prices->count() > 0) { $minPrice = $prices->min(); } } // Ville - utiliser addresses en priorité, sinon program->city (accessor ou attribut) $address = $program->addresses()->first(); $city = $address ? $address->city : ($program->city ?? 'N/A'); // Date de livraison $deliveryDate = $program->dates()->where('type', 'date_livraison')->first(); $deliveryYear = $deliveryDate ? \Carbon\Carbon::parse($deliveryDate->value)->format('Y') : null; // Fiscalités $fiscalites = $program->fiscalites->pluck('type')->map(fn($f) => $f->label())->toArray(); $fiscaliteLibelle = !empty($fiscalites) ? implode(', ', $fiscalites) : ''; // TVA 5.5% $hasTva5 = $program->lots() ->whereHas('prices', function($q) { $q->where('type', PriceType::PRIX_TVA_5_5->value) ->where('value', '>', 0); }) ->exists(); // LLI (TVA 10%) $hasLli = $program->lots() ->whereHas('prices', function($q) { $q->where('type', PriceType::PRIX_TVA_10->value) ->where('value', '>', 0); }) ->exists(); // Tags marketing (utiliser la relation chargée si disponible, sinon requête pour exclusivité) $marketingTags = $program->relationLoaded('marketingTags') ? $program->marketingTags : $program->marketingTags()->get(); // Opérations commerciales (opeComs) $hasOpeComs = $program->opeComs()->exists() || $program->lots()->whereHas('opeComs')->exists(); $hasCashback = $program->opeComs()->where('type', \App\Enums\OpeCom::CASHBACK->value)->exists() || $program->lots()->whereHas('opeComs', function($q) { $q->where('type', \App\Enums\OpeCom::CASHBACK->value); })->exists(); $hasNonCashbackOpeComs = $program->opeComs()->where('type', '!=', \App\Enums\OpeCom::CASHBACK->value)->exists() || $program->lots()->whereHas('opeComs', function($q) { $q->where('type', '!=', \App\Enums\OpeCom::CASHBACK->value); })->exists(); // Quote/travaux - calculer le pourcentage moyen $quoteTravaux = null; $lotsWithTravaux = $program->lots() ->whereHas('prices', function($q) { $q->whereIn('type', [ PriceTypeTravaux::PRIX_TRAVAUX_ELIGIBLE->value, PriceTypeTravaux::PRIX_TRAVAUX_NON_ELIGIBLE->value ]) ->where('value', '>', 0); }) ->with(['prices' => function($q) { $q->whereIn('type', [ 'prix_ttc', PriceTypeTravaux::PRIX_TRAVAUX_ELIGIBLE->value, PriceTypeTravaux::PRIX_TRAVAUX_NON_ELIGIBLE->value ]); }]) ->get(); if ($lotsWithTravaux->count() > 0) { $quotes = []; foreach ($lotsWithTravaux as $lot) { $prixTTC = $lot->prices->where('type', 'prix_ttc')->first()?->value ?? 0; $prixTravaux = $lot->prices ->whereIn('type', [ PriceTypeTravaux::PRIX_TRAVAUX_ELIGIBLE->value, PriceTypeTravaux::PRIX_TRAVAUX_NON_ELIGIBLE->value ]) ->sum('value'); if ($prixTTC > 0 && $prixTravaux > 0) { $quotes[] = ($prixTravaux / $prixTTC) * 100; } } if (!empty($quotes)) { $quoteTravaux = round(max($quotes)); } } // Déterminer si TTC ou HT (basé sur la fiscalité principale) $isHT = false; $mainFiscalite = $program->fiscalites->first(); if ($mainFiscalite && $mainFiscalite->type->value === 'monument_historique') { $isHT = true; } // Commission de l'utilisateur pour ce programme $commission = null; if (Auth::check() && isset($currentApplication)) { $commission = $program->getHighestCommission(Auth::id(), $currentApplication->id); } // Paramètres optionnels pour personnaliser l'affichage $wrapperClass = $wrapperClass ?? 'col-xs-12 col-sm-12 col-md-6 col-lg-4 wow fadeInLeft'; $linkClass = $linkClass ?? 'programme_miniature_lien'; $linkUrl = $linkUrl ?? route('programmes.show', $program->slug); $itemClass = $itemClass ?? ''; // Pour le carousel (classe 'item') $noWrapper = $noWrapper ?? false; // Ne pas créer de wrapper div (pour carousel) @endphp @if(!$noWrapper)
@endif id)) data-id="{{ $program->id }}" @endif class="{{ $linkClass }} {{ $itemClass }}">
{{ mb_strtolower($program->name) }}
@if($hasOpeComs) @if($hasNonCashbackOpeComs) @endif @if($hasCashback) @endif @endif @foreach($marketingTags->filter(fn($t) => $t->type && $t->type->value !== MarketingTagType::NON_DEFINI->value) as $tag) @endforeach

{{ ucwords(mb_strtolower($program->name)) }}

à partir de
{{ $minPrice > 0 ? number_format($minPrice, 0, ',', ' ') : '0' }} € {{ $isHT ? 'HT' : 'TTC' }}


@if(!$noWrapper)
@endif