From f1e2199fef9c0706fb621b80ef95ebced215d17e Mon Sep 17 00:00:00 2001 From: fatihalp Date: Sun, 8 Mar 2026 03:32:25 +0300 Subject: [PATCH] Fix listings language and actions --- .../Filament/Pages/ManageGeneralSettings.php | 44 +- Modules/Category/routes/web.php | 6 +- .../Controllers/ConversationController.php | 76 ++- .../App/Support/QuickMessageCatalog.php | 8 +- .../resources/views/inbox.blade.php | 61 +-- Modules/Conversation/routes/web.php | 14 +- .../Http/Controllers/FavoriteController.php | 30 +- .../Favorite/App/Models/FavoriteSearch.php | 2 +- .../Favorite/resources/views/index.blade.php | 70 +-- Modules/Favorite/routes/web.php | 18 +- .../Database/Seeders/ListingSeeder.php | 38 +- .../Http/Controllers/ListingController.php | 20 +- Modules/Listing/Models/Listing.php | 34 +- .../ListingCustomFieldSchemaBuilder.php | 4 +- .../Listing/resources/views/index.blade.php | 451 +---------------- .../views/partials/index-content.blade.php | 454 ++++++++++++++++++ .../Listing/resources/views/show.blade.php | 12 +- .../views/themes/default/index.blade.php | 451 +---------------- .../views/themes/default/show.blade.php | 12 +- .../views/themes/otoplus/index.blade.php | 451 +---------------- .../views/themes/otoplus/show.blade.php | 302 ++++++++---- .../Database/Seeders/LocationSeeder.php | 75 ++- .../User/database/seeders/AuthUserSeeder.php | 2 +- app/Http/Controllers/PanelController.php | 6 +- app/Livewire/PanelQuickListingForm.php | 22 +- app/Providers/AppServiceProvider.php | 2 +- resources/css/app.css | 204 ++++++++ resources/js/app.js | 6 - resources/views/errors/403.blade.php | 8 +- resources/views/home.blade.php | 30 +- resources/views/layouts/app.blade.php | 16 +- resources/views/panel/listings.blade.php | 108 ++--- .../panel/partials/page-header.blade.php | 24 + .../views/panel/partials/sidebar.blade.php | 6 - resources/views/panel/videos.blade.php | 10 +- routes/web.php | 12 +- 36 files changed, 1323 insertions(+), 1766 deletions(-) create mode 100644 Modules/Listing/resources/views/partials/index-content.blade.php create mode 100644 resources/views/panel/partials/page-header.blade.php diff --git a/Modules/Admin/Filament/Pages/ManageGeneralSettings.php b/Modules/Admin/Filament/Pages/ManageGeneralSettings.php index 85acc0d70..56992c914 100644 --- a/Modules/Admin/Filament/Pages/ManageGeneralSettings.php +++ b/Modules/Admin/Filament/Pages/ManageGeneralSettings.php @@ -97,29 +97,29 @@ class ManageGeneralSettings extends SettingsPage return $schema ->components([ TextInput::make('site_name') - ->label('Site Adı') + ->label('Site Name') ->default($defaults['site_name']) ->required() ->maxLength(255), Textarea::make('site_description') - ->label('Site Açıklaması') + ->label('Site Description') ->default($defaults['site_description']) ->rows(3) ->maxLength(500), Select::make('media_disk') - ->label('Medya Depolama') + ->label('Media Storage') ->options(MediaStorage::options()) ->default($defaults['media_disk']) ->required() ->native(false) - ->helperText('İlan resimleri, videolar, logo ve slide görselleri için kullanılacak depolama sürücüsü.'), + ->helperText('Storage driver used for listing images, videos, the site logo, and home slide visuals.'), HomeSlideFormSchema::make( $defaults['home_slides'], fn ($state): array => $this->normalizeHomeSlides($state, MediaStorage::activeDisk()), ), Hidden::make('site_logo_disk'), FileUpload::make('site_logo') - ->label('Site Logosu') + ->label('Site Logo') ->image() ->disk(fn (Get $get): string => MediaStorage::storedDisk($get('site_logo_disk'), $get('media_disk'))) ->directory('settings') @@ -133,32 +133,32 @@ class ManageGeneralSettings extends SettingsPage ); }), TextInput::make('sender_name') - ->label('Gönderici Adı') + ->label('Sender Name') ->default($defaults['sender_name']) ->required() ->maxLength(120), TextInput::make('sender_email') - ->label('Gönderici E-postası') + ->label('Sender Email') ->email() ->default($defaults['sender_email']) ->required() ->maxLength(255), Select::make('default_language') - ->label('Varsayılan Dil') + ->label('Default Language') ->options($this->localeOptions()) ->default($defaults['default_language']) ->required() ->searchable(), CountryCodeSelect::make('default_country_code') - ->label('Varsayılan Ülke') + ->label('Default Country') ->default($defaults['default_country_code']) ->required() - ->helperText('Panel formlarında varsayılan ülke olarak kullanılır.'), + ->helperText('Used as the default country in panel forms.'), TagsInput::make('currencies') - ->label('Para Birimleri') + ->label('Currencies') ->placeholder('TRY') ->default($defaults['currencies']) - ->helperText('TRY, USD, EUR gibi 3 harfli para birimi kodları ekleyin.') + ->helperText('Add 3-letter currency codes such as TRY, USD, or EUR.') ->required() ->rules(['array', 'min:1']) ->afterStateHydrated(fn (TagsInput $component, $state) => $component->state($this->normalizeCurrencies($state))) @@ -181,19 +181,19 @@ class ManageGeneralSettings extends SettingsPage ->default($defaults['whatsapp']) ->nullable() ->formatAsYouType() - ->helperText('Uluslararası format kullanın. Örnek: +905551112233'), + ->helperText('Use international format. Example: +905551112233'), Toggle::make('enable_google_maps') - ->label('Google Maps Aktif') + ->label('Google Maps Enabled') ->default($defaults['enable_google_maps']), TextInput::make('google_maps_api_key') - ->label('Google Maps API Anahtarı') + ->label('Google Maps API Key') ->password() ->revealable() ->nullable() ->maxLength(255) - ->helperText('İlan formlarındaki harita alanlarını açmak için gereklidir.'), + ->helperText('Required to enable map fields in listing forms.'), Toggle::make('enable_google_login') - ->label('Google ile Giriş Aktif') + ->label('Google Login Enabled') ->default($defaults['enable_google_login']), TextInput::make('google_client_id') ->label('Google Client ID') @@ -206,7 +206,7 @@ class ManageGeneralSettings extends SettingsPage ->nullable() ->maxLength(255), Toggle::make('enable_facebook_login') - ->label('Facebook ile Giriş Aktif') + ->label('Facebook Login Enabled') ->default($defaults['enable_facebook_login']), TextInput::make('facebook_client_id') ->label('Facebook Client ID') @@ -219,7 +219,7 @@ class ManageGeneralSettings extends SettingsPage ->nullable() ->maxLength(255), Toggle::make('enable_apple_login') - ->label('Apple ile Giriş Aktif') + ->label('Apple Login Enabled') ->default($defaults['enable_apple_login']), TextInput::make('apple_client_id') ->label('Apple Client ID') @@ -241,13 +241,13 @@ class ManageGeneralSettings extends SettingsPage return [ 'site_name' => $siteName, - 'site_description' => 'Alim satim icin hizli ve guvenli ilan platformu.', + 'site_description' => 'A fast and secure marketplace for buying and selling.', 'media_disk' => MediaStorage::defaultDriver(), 'home_slides' => $this->defaultHomeSlides(), 'site_logo_disk' => null, 'sender_name' => $siteName, 'sender_email' => (string) config('mail.from.address', 'info@' . $siteHost), - 'default_language' => in_array(config('app.locale'), array_keys($this->localeOptions()), true) ? (string) config('app.locale') : 'tr', + 'default_language' => in_array(config('app.locale'), array_keys($this->localeOptions()), true) ? (string) config('app.locale') : 'en', 'default_country_code' => CountryCodeManager::normalizeCountryCode(config('app.default_country_code', '+90')), 'currencies' => $this->normalizeCurrencies(config('app.currencies', ['TRY'])), 'linkedin_url' => 'https://www.linkedin.com/company/openclassify', @@ -264,7 +264,7 @@ class ManageGeneralSettings extends SettingsPage { $labels = [ 'en' => 'English', - 'tr' => 'Türkçe', + 'tr' => 'Turkish', ]; return collect(config('app.available_locales', ['en'])) diff --git a/Modules/Category/routes/web.php b/Modules/Category/routes/web.php index 760490fc6..5ce9962d6 100644 --- a/Modules/Category/routes/web.php +++ b/Modules/Category/routes/web.php @@ -2,6 +2,8 @@ use Illuminate\Support\Facades\Route; use Modules\Category\Http\Controllers\CategoryController; -Route::prefix('categories')->name('categories.')->group(function () { - Route::get('/', [CategoryController::class, 'index'])->name('index'); +Route::middleware('web')->group(function () { + Route::prefix('categories')->name('categories.')->group(function () { + Route::get('/', [CategoryController::class, 'index'])->name('index'); + }); }); diff --git a/Modules/Conversation/App/Http/Controllers/ConversationController.php b/Modules/Conversation/App/Http/Controllers/ConversationController.php index 0b8150e83..d11e548f4 100644 --- a/Modules/Conversation/App/Http/Controllers/ConversationController.php +++ b/Modules/Conversation/App/Http/Controllers/ConversationController.php @@ -3,11 +3,13 @@ namespace Modules\Conversation\App\Http\Controllers; use App\Http\Controllers\Controller; +use Illuminate\Http\JsonResponse; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Schema; use Illuminate\View\View; use Modules\Conversation\App\Models\Conversation; +use Modules\Conversation\App\Models\ConversationMessage; use Modules\Conversation\App\Support\QuickMessageCatalog; use Modules\Listing\Models\Listing; use Throwable; @@ -56,28 +58,45 @@ class ConversationController extends Controller ]); } - public function start(Request $request, Listing $listing): RedirectResponse + public function start(Request $request, Listing $listing): RedirectResponse | JsonResponse { if (! $this->messagingTablesReady()) { - return back()->with('error', 'Mesajlaşma altyapısı henüz hazır değil.'); + if ($request->expectsJson()) { + return response()->json(['message' => 'Messaging is not available yet.'], 503); + } + + return back()->with('error', 'Messaging is not available yet.'); } $user = $request->user(); if (! $listing->user_id) { - return back()->with('error', 'Bu ilan için mesajlaşma açılamadı.'); + if ($request->expectsJson()) { + return response()->json(['message' => 'A conversation cannot be started for this listing.'], 422); + } + + return back()->with('error', 'A conversation cannot be started for this listing.'); } if ((int) $listing->user_id === (int) $user->getKey()) { - return back()->with('error', 'Kendi ilanına mesaj gönderemezsin.'); + if ($request->expectsJson()) { + return response()->json(['message' => 'You cannot message your own listing.'], 422); + } + + return back()->with('error', 'You cannot message your own listing.'); + } + + $messageBody = trim((string) $request->string('message')); + + if ($request->expectsJson() && $messageBody === '') { + return response()->json(['message' => 'Message cannot be empty.'], 422); } $conversation = Conversation::openForListingBuyer($listing, (int) $user->getKey()); $user->favoriteListings()->syncWithoutDetaching([$listing->getKey()]); - $messageBody = trim((string) $request->string('message')); - + $message = null; if ($messageBody !== '') { $message = $conversation->messages()->create([ 'sender_id' => $user->getKey(), @@ -87,15 +106,23 @@ class ConversationController extends Controller $conversation->forceFill(['last_message_at' => $message->created_at])->save(); } + if ($request->expectsJson()) { + return $this->conversationJsonResponse($conversation, $message, (int) $user->getKey()); + } + return redirect() ->route('panel.inbox.index', array_merge($this->inboxFilters($request), ['conversation' => $conversation->getKey()])) - ->with('success', $messageBody !== '' ? 'Mesaj gönderildi.' : 'Sohbet açıldı.'); + ->with('success', $messageBody !== '' ? 'Message sent.' : 'Conversation started.'); } - public function send(Request $request, Conversation $conversation): RedirectResponse + public function send(Request $request, Conversation $conversation): RedirectResponse | JsonResponse { if (! $this->messagingTablesReady()) { - return back()->with('error', 'Mesajlaşma altyapısı henüz hazır değil.'); + if ($request->expectsJson()) { + return response()->json(['message' => 'Messaging is not available yet.'], 503); + } + + return back()->with('error', 'Messaging is not available yet.'); } $user = $request->user(); @@ -112,7 +139,11 @@ class ConversationController extends Controller $messageBody = trim($payload['message']); if ($messageBody === '') { - return back()->with('error', 'Mesaj boş olamaz.'); + if ($request->expectsJson()) { + return response()->json(['message' => 'Message cannot be empty.'], 422); + } + + return back()->with('error', 'Message cannot be empty.'); } $message = $conversation->messages()->create([ @@ -122,9 +153,32 @@ class ConversationController extends Controller $conversation->forceFill(['last_message_at' => $message->created_at])->save(); + if ($request->expectsJson()) { + return $this->conversationJsonResponse($conversation, $message, $userId); + } + return redirect() ->route('panel.inbox.index', array_merge($this->inboxFilters($request), ['conversation' => $conversation->getKey()])) - ->with('success', 'Mesaj gönderildi.'); + ->with('success', 'Message sent.'); + } + + private function conversationJsonResponse(Conversation $conversation, ?ConversationMessage $message, int $userId): JsonResponse + { + return response()->json([ + 'conversation_id' => (int) $conversation->getKey(), + 'send_url' => route('conversations.messages.send', $conversation), + 'message' => $message ? $this->messagePayload($message, $userId) : null, + ]); + } + + private function messagePayload(ConversationMessage $message, int $userId): array + { + return [ + 'id' => (int) $message->getKey(), + 'body' => (string) $message->body, + 'time' => $message->created_at?->format('H:i') ?? now()->format('H:i'), + 'is_mine' => (int) $message->sender_id === $userId, + ]; } private function inboxFilters(Request $request): array diff --git a/Modules/Conversation/App/Support/QuickMessageCatalog.php b/Modules/Conversation/App/Support/QuickMessageCatalog.php index 7792a705d..2680437a7 100644 --- a/Modules/Conversation/App/Support/QuickMessageCatalog.php +++ b/Modules/Conversation/App/Support/QuickMessageCatalog.php @@ -7,10 +7,10 @@ class QuickMessageCatalog public static function all(): array { return [ - 'Merhaba', - 'İlan hâlâ satışta mı?', - 'Son fiyat nedir?', - 'Teşekkürler', + 'Hi', + 'Is this listing still available?', + 'What is your best price?', + 'Thanks', ]; } } diff --git a/Modules/Conversation/resources/views/inbox.blade.php b/Modules/Conversation/resources/views/inbox.blade.php index edf96e25c..d40c0d5ad 100644 --- a/Modules/Conversation/resources/views/inbox.blade.php +++ b/Modules/Conversation/resources/views/inbox.blade.php @@ -1,44 +1,44 @@ @extends('app::layouts.app') -@section('title', 'Gelen Kutusu') +@section('title', 'Inbox') @section('content')
@include('panel.partials.sidebar', ['activeMenu' => 'inbox']) -
+
+ @include('panel.partials.page-header', [ + 'title' => 'Inbox', + 'description' => 'Read and reply to buyer messages from the same panel shell used across the site.', + 'actions' => $requiresLogin ?? false + ? new \Illuminate\Support\HtmlString('Log in') + : null, + ]) + +
@if($requiresLogin ?? false) -
+

Inbox

-

Stay on this page and log in when you want to access your conversations.

+

Stay on this page and log in when you want to access your conversations.

- - Log in -
@endif
-
-

Gelen Kutusu

- - - -
@@ -57,17 +57,17 @@ @if($conversationImage) {{ $conversationListing?->title }} @else -
İlan
+
Listing
@endif
-

{{ $partner?->name ?? 'Kullanıcı' }}

+

{{ $partner?->name ?? 'User' }}

{{ $conversation->last_message_at?->format('d.m.Y') }}

-

{{ $conversationListing?->title ?? 'İlan silinmiş' }}

+

{{ $conversationListing?->title ?? 'Listing removed' }}

- {{ $lastMessage !== '' ? $lastMessage : 'Henüz mesaj yok' }} + {{ $lastMessage !== '' ? $lastMessage : 'No messages yet' }}

@if($conversation->unread_count > 0) @@ -79,7 +79,7 @@ @empty
- Henüz bir sohbetin yok. + No conversations yet.
@endforelse
@@ -101,8 +101,8 @@ {{ strtoupper(substr((string) ($activePartner?->name ?? 'K'), 0, 1)) }}
-

{{ $activePartner?->name ?? 'Kullanıcı' }}

-

{{ $activeListing?->title ?? 'İlan silinmiş' }}

+

{{ $activePartner?->name ?? 'User' }}

+

{{ $activeListing?->title ?? 'Listing removed' }}

@if($activePriceLabel)
{{ $activePriceLabel }}
@@ -125,8 +125,8 @@ @empty
-

Henüz mesaj yok.

-

Aşağıdaki hazır metinlerden birini seçebilir veya yeni mesaj yazabilirsin.

+

No messages yet.

+

Use a quick reply or send the first message below.

@endforelse @@ -148,8 +148,8 @@
@csrf - -
+
diff --git a/Modules/Conversation/routes/web.php b/Modules/Conversation/routes/web.php index 7b1bc3a23..b5acdfb42 100644 --- a/Modules/Conversation/routes/web.php +++ b/Modules/Conversation/routes/web.php @@ -3,11 +3,13 @@ use Illuminate\Support\Facades\Route; use Modules\Conversation\App\Http\Controllers\ConversationController; -Route::prefix('panel')->name('panel.')->group(function () { - Route::get('/inbox', [ConversationController::class, 'inbox'])->name('inbox.index'); -}); +Route::middleware('web')->group(function () { + Route::prefix('panel')->name('panel.')->group(function () { + Route::get('/inbox', [ConversationController::class, 'inbox'])->name('inbox.index'); + }); -Route::middleware('auth')->name('conversations.')->group(function () { - Route::post('/listings/{listing}/conversation', [ConversationController::class, 'start'])->name('start'); - Route::post('/conversations/{conversation}/messages', [ConversationController::class, 'send'])->name('messages.send'); + Route::middleware('auth')->name('conversations.')->group(function () { + Route::post('/listings/{listing}/conversation', [ConversationController::class, 'start'])->name('start'); + Route::post('/conversations/{conversation}/messages', [ConversationController::class, 'send'])->name('messages.send'); + }); }); diff --git a/Modules/Favorite/App/Http/Controllers/FavoriteController.php b/Modules/Favorite/App/Http/Controllers/FavoriteController.php index e140cc3e2..1bae61310 100644 --- a/Modules/Favorite/App/Http/Controllers/FavoriteController.php +++ b/Modules/Favorite/App/Http/Controllers/FavoriteController.php @@ -11,10 +11,15 @@ use Modules\Conversation\App\Models\Conversation; use Modules\Favorite\App\Models\FavoriteSearch; use Modules\Listing\Models\Listing; use Modules\User\App\Models\User; +use Modules\User\App\Support\AuthRedirector; use Throwable; class FavoriteController extends Controller { + public function __construct(private AuthRedirector $redirector) + { + } + public function index(Request $request) { $activeTab = (string) $request->string('tab', 'listings'); @@ -126,7 +131,7 @@ class FavoriteController extends Controller { $isNowFavorite = $request->user()->toggleFavoriteListing($listing); - return back()->with('success', $isNowFavorite ? 'İlan favorilere eklendi.' : 'İlan favorilerden kaldırıldı.'); + return $this->redirectBack($request)->with('success', $isNowFavorite ? 'Listing added to favorites.' : 'Listing removed from favorites.'); } public function toggleSeller(Request $request, User $seller) @@ -134,12 +139,12 @@ class FavoriteController extends Controller $user = $request->user(); if ((int) $user->getKey() === (int) $seller->getKey()) { - return back()->with('error', 'Kendi hesabını favorilere ekleyemezsin.'); + return $this->redirectBack($request)->with('error', 'You cannot favorite your own account.'); } $isNowFavorite = $user->toggleFavoriteSeller($seller); - return back()->with('success', $isNowFavorite ? 'Satıcı favorilere eklendi.' : 'Satıcı favorilerden kaldırıldı.'); + return $this->redirectBack($request)->with('success', $isNowFavorite ? 'Seller added to favorites.' : 'Seller removed from favorites.'); } public function storeSearch(Request $request) @@ -155,7 +160,7 @@ class FavoriteController extends Controller ]); if ($filters === []) { - return back()->with('error', 'Favoriye eklemek için en az bir filtre seçmelisin.'); + return back()->with('error', 'Select at least one filter before saving a search.'); } $signature = FavoriteSearch::signatureFor($filters); @@ -178,10 +183,10 @@ class FavoriteController extends Controller ); if (! $favoriteSearch->wasRecentlyCreated) { - return back()->with('success', 'Bu arama zaten favorilerinde.'); + return back()->with('success', 'This search is already in your favorites.'); } - return back()->with('success', 'Arama favorilere eklendi.'); + return back()->with('success', 'Search added to favorites.'); } public function destroySearch(Request $request, FavoriteSearch $favoriteSearch) @@ -192,7 +197,7 @@ class FavoriteController extends Controller $favoriteSearch->delete(); - return back()->with('success', 'Favori arama silindi.'); + return back()->with('success', 'Saved search deleted.'); } private function tableExists(string $table): bool @@ -211,4 +216,15 @@ class FavoriteController extends Controller 'query' => request()->query(), ]); } + + private function redirectBack(Request $request): \Illuminate\Http\RedirectResponse + { + $target = $this->redirector->sanitize((string) $request->input('redirect_to', '')); + + if ($target !== null) { + return redirect()->to($target); + } + + return back(); + } } diff --git a/Modules/Favorite/App/Models/FavoriteSearch.php b/Modules/Favorite/App/Models/FavoriteSearch.php index 07130acc1..c424eb1a2 100644 --- a/Modules/Favorite/App/Models/FavoriteSearch.php +++ b/Modules/Favorite/App/Models/FavoriteSearch.php @@ -51,6 +51,6 @@ class FavoriteSearch extends Model $labelParts[] = $categoryName; } - return $labelParts !== [] ? implode(' · ', $labelParts) : 'Filtreli arama'; + return $labelParts !== [] ? implode(' · ', $labelParts) : 'Filtered search'; } } diff --git a/Modules/Favorite/resources/views/index.blade.php b/Modules/Favorite/resources/views/index.blade.php index 63b3a2ce6..ab5fa414e 100644 --- a/Modules/Favorite/resources/views/index.blade.php +++ b/Modules/Favorite/resources/views/index.blade.php @@ -1,6 +1,6 @@ @extends('app::layouts.app') -@section('title', 'Favoriler') +@section('title', 'Favorites') @section('content')
@@ -29,25 +29,25 @@ ], fn ($value) => !is_null($value) && $value !== ''); @endphp
-

Favori Listem

+

Saved Listings

- +
@@ -55,9 +55,9 @@ - - - + + + @@ -65,7 +65,7 @@ @forelse($favoriteListings as $listing) @php $listingImage = $listing->getFirstMediaUrl('listing-images'); - $priceLabel = $listing->price ? number_format((float) $listing->price, 0).' '.$listing->currency : 'Ücretsiz'; + $priceLabel = $listing->price ? number_format((float) $listing->price, 0).' '.$listing->currency : 'Free'; $meta = collect([ $listing->category?->name, $listing->city, @@ -82,15 +82,15 @@ @if($listingImage) {{ $listing->title }} @else -
Görsel yok
+
No image
@endif
{{ $listing->title }} -

{{ $meta !== '' ? $meta : 'Kategori / konum bilgisi yok' }}

-

Favoriye eklenme: {{ $listing->pivot->created_at?->format('d.m.Y') }}

+

{{ $meta !== '' ? $meta : 'No category or location data' }}

+

Saved on: {{ $listing->pivot->created_at?->format('M j, Y') }}

@@ -99,31 +99,31 @@ @if($canMessageListing) @if($conversationId) - Sohbete Git + Open chat @else @csrf @endif @else - {{ $isOwnListing ? 'Kendi ilanın' : 'Satıcı bilgisi yok' }} + {{ $isOwnListing ? 'Your own listing' : 'Seller unavailable' }} @endif @empty @endforelse @@ -132,7 +132,7 @@
- * Son 1 yıl içinde favoriye eklediğiniz ilanlar listelenmektedir. + * Listings saved within the last year are shown here.
@if($favoriteListings?->hasPages()) @@ -142,8 +142,8 @@ @if($activeTab === 'searches')
-

Favori Aramalar

-

Kayıtlı aramalarına tek tıkla geri dön.

+

Saved Searches

+

Return to your saved searches with one click.

@forelse($favoriteSearches as $favoriteSearch) @@ -155,29 +155,29 @@ @endphp
-

{{ $favoriteSearch->label ?: 'Kayıtlı arama' }}

+

{{ $favoriteSearch->label ?: 'Saved search' }}

- @if($favoriteSearch->search_term) Arama: "{{ $favoriteSearch->search_term }}" · @endif - @if($favoriteSearch->category) Kategori: {{ $favoriteSearch->category->name }} · @endif - Kaydedilme: {{ $favoriteSearch->created_at?->format('d.m.Y H:i') }} + @if($favoriteSearch->search_term) Search: "{{ $favoriteSearch->search_term }}" · @endif + @if($favoriteSearch->category) Category: {{ $favoriteSearch->category->name }} · @endif + Saved: {{ $favoriteSearch->created_at?->format('M j, Y H:i') }}

- Aramayı Aç + Open search
@csrf @method('DELETE')
@empty
- Henüz favori arama eklenmedi. + No saved searches yet.
@endforelse
@@ -188,32 +188,32 @@ @if($activeTab === 'sellers')
-

Favori Satıcılar

-

Takip etmek istediğin satıcıları burada yönetebilirsin.

+

Saved Sellers

+

Manage the sellers you want to follow here.

@forelse($favoriteSellers as $seller) @empty
- Henüz favori satıcı eklenmedi. + No saved sellers yet.
@endforelse
diff --git a/Modules/Favorite/routes/web.php b/Modules/Favorite/routes/web.php index 12afcf09b..79d30bf97 100644 --- a/Modules/Favorite/routes/web.php +++ b/Modules/Favorite/routes/web.php @@ -3,13 +3,15 @@ use Illuminate\Support\Facades\Route; use Modules\Favorite\App\Http\Controllers\FavoriteController; -Route::prefix('favorites')->name('favorites.')->group(function () { - Route::get('/', [FavoriteController::class, 'index'])->name('index'); -}); +Route::middleware('web')->group(function () { + Route::prefix('favorites')->name('favorites.')->group(function () { + Route::get('/', [FavoriteController::class, 'index'])->name('index'); + }); -Route::middleware('auth')->prefix('favorites')->name('favorites.')->group(function () { - Route::post('/listings/{listing}/toggle', [FavoriteController::class, 'toggleListing'])->name('listings.toggle'); - Route::post('/sellers/{seller}/toggle', [FavoriteController::class, 'toggleSeller'])->name('sellers.toggle'); - Route::post('/searches', [FavoriteController::class, 'storeSearch'])->name('searches.store'); - Route::delete('/searches/{favoriteSearch}', [FavoriteController::class, 'destroySearch'])->name('searches.destroy'); + Route::middleware('auth')->prefix('favorites')->name('favorites.')->group(function () { + Route::post('/listings/{listing}/toggle', [FavoriteController::class, 'toggleListing'])->name('listings.toggle'); + Route::post('/sellers/{seller}/toggle', [FavoriteController::class, 'toggleSeller'])->name('sellers.toggle'); + Route::post('/searches', [FavoriteController::class, 'storeSearch'])->name('searches.store'); + Route::delete('/searches/{favoriteSearch}', [FavoriteController::class, 'destroySearch'])->name('searches.destroy'); + }); }); diff --git a/Modules/Listing/Database/Seeders/ListingSeeder.php b/Modules/Listing/Database/Seeders/ListingSeeder.php index f037f9db2..ea7d84f50 100644 --- a/Modules/Listing/Database/Seeders/ListingSeeder.php +++ b/Modules/Listing/Database/Seeders/ListingSeeder.php @@ -25,13 +25,13 @@ class ListingSeeder extends Seeder ]; private const TITLE_PREFIXES = [ - 'Temiz kullanılmış', - 'Az kullanılmış', - 'Fırsat ürün', - 'Uygun fiyatlı', - 'Sahibinden', - 'Kaçırılmayacak', - 'Bakımlı', + 'Clean', + 'Lightly used', + 'Special offer', + 'Well priced', + 'Owner listed', + 'Must-see', + 'Well kept', ]; public function run(): void @@ -100,7 +100,7 @@ class ListingSeeder extends Seeder private function resolveTurkeyCities(): Collection { if (! class_exists(City::class) || ! Schema::hasTable('cities') || ! Schema::hasTable('countries')) { - return collect(['İstanbul', 'Ankara', 'İzmir', 'Bursa', 'Antalya']); + return collect(['Istanbul', 'Ankara', 'Izmir', 'Bursa', 'Antalya']); } $turkey = Country::query() @@ -108,7 +108,7 @@ class ListingSeeder extends Seeder ->first(['id']); if (! $turkey) { - return collect(['İstanbul', 'Ankara', 'İzmir', 'Bursa', 'Antalya']); + return collect(['Istanbul', 'Ankara', 'Izmir', 'Bursa', 'Antalya']); } $cities = City::query() @@ -122,7 +122,7 @@ class ListingSeeder extends Seeder return $cities->isNotEmpty() ? $cities - : collect(['İstanbul', 'Ankara', 'İzmir', 'Bursa', 'Antalya']); + : collect(['Istanbul', 'Ankara', 'Izmir', 'Bursa', 'Antalya']); } private function buildListingData( @@ -147,7 +147,7 @@ class ListingSeeder extends Seeder private function resolveLocation(int $index, Collection $countries, Collection $turkeyCities): array { $turkeyCountry = $countries->first(fn ($country): bool => strtoupper((string) $country->code) === 'TR'); - $turkeyName = trim((string) ($turkeyCountry->name ?? 'Türkiye')) ?: 'Türkiye'; + $turkeyName = trim((string) ($turkeyCountry->name ?? 'Turkey')) ?: 'Turkey'; $useForeignCountry = $countries->count() > 1 && $index % 4 === 0; @@ -161,8 +161,8 @@ class ListingSeeder extends Seeder $countryName = trim((string) ($selected->name ?? '')); return [ - 'country' => $countryName !== '' ? $countryName : 'Türkiye', - 'city' => $countryName !== '' ? $countryName : 'İstanbul', + 'country' => $countryName !== '' ? $countryName : 'Turkey', + 'city' => $countryName !== '' ? $countryName : 'Istanbul', ]; } } @@ -171,7 +171,7 @@ class ListingSeeder extends Seeder return [ 'country' => $turkeyName, - 'city' => $city !== '' ? $city : 'İstanbul', + 'city' => $city !== '' ? $city : 'Istanbul', ]; } @@ -180,7 +180,7 @@ class ListingSeeder extends Seeder $prefix = self::TITLE_PREFIXES[$index % count(self::TITLE_PREFIXES)]; $categoryName = trim((string) $category->name); - return sprintf('%s %s ilanı', $prefix, $categoryName !== '' ? $categoryName : 'ürün'); + return sprintf('%s %s listing', $prefix, $categoryName !== '' ? $categoryName : 'item'); } private function buildDescription(Category $category, string $city, string $country): string @@ -189,9 +189,9 @@ class ListingSeeder extends Seeder $location = trim(collect([$city, $country])->filter()->join(', ')); return sprintf( - '%s kategorisinde, durum olarak sorunsuz ve kullanıma hazırdır. Teslimat noktası: %s. Detaylar için mesaj atabilirsiniz.', - $categoryName !== '' ? $categoryName : 'Ürün', - $location !== '' ? $location : 'Türkiye' + 'Listed in %s, in clean condition and ready to use. Pickup area: %s. Message for more details.', + $categoryName !== '' ? $categoryName : 'Item', + $location !== '' ? $location : 'Turkey' ); } @@ -244,7 +244,7 @@ class ListingSeeder extends Seeder if (! is_file($imageAbsolutePath)) { if ($this->command) { - $this->command->warn("Gorsel bulunamadi: {$imageRelativePath}"); + $this->command->warn("Image not found: {$imageRelativePath}"); } return; diff --git a/Modules/Listing/Http/Controllers/ListingController.php b/Modules/Listing/Http/Controllers/ListingController.php index 26b45f36c..6efcc8945 100644 --- a/Modules/Listing/Http/Controllers/ListingController.php +++ b/Modules/Listing/Http/Controllers/ListingController.php @@ -33,6 +33,9 @@ class ListingController extends Controller $cityId = request()->integer('city'); $cityId = $cityId > 0 ? $cityId : null; + $sellerUserId = request()->integer('user'); + $sellerUserId = $sellerUserId > 0 ? $sellerUserId : null; + $minPriceInput = trim((string) request('min_price', '')); $maxPriceInput = trim((string) request('max_price', '')); $minPrice = is_numeric($minPriceInput) ? max((float) $minPriceInput, 0) : null; @@ -70,6 +73,7 @@ class ListingController extends Controller 'search' => $search, 'country' => $selectedCountryName, 'city' => $selectedCityName, + 'user_id' => $sellerUserId, 'min_price' => $minPrice, 'max_price' => $maxPrice, 'date_filter' => $dateFilter, @@ -136,6 +140,7 @@ class ListingController extends Controller 'categoryId', 'countryId', 'cityId', + 'sellerUserId', 'minPriceInput', 'maxPriceInput', 'dateFilter', @@ -184,6 +189,7 @@ class ListingController extends Controller $isListingFavorited = false; $isSellerFavorited = false; $existingConversationId = null; + $detailConversation = null; if (auth()->check()) { $userId = (int) auth()->id(); @@ -205,6 +211,17 @@ class ListingController extends Controller (int) $listing->getKey(), $userId, ); + + if ($existingConversationId) { + $detailConversation = Conversation::query() + ->forUser($userId) + ->find($existingConversationId); + + if ($detailConversation) { + $detailConversation->loadThread(); + $detailConversation->markAsReadFor($userId); + } + } } } @@ -214,6 +231,7 @@ class ListingController extends Controller 'isSellerFavorited', 'presentableCustomFields', 'existingConversationId', + 'detailConversation', 'gallery', 'listingVideos', 'relatedListings', @@ -239,7 +257,7 @@ class ListingController extends Controller return redirect() ->route('panel.listings.create') - ->with('success', 'İlan oluşturma ekranına yönlendirildin.'); + ->with('success', 'You were redirected to the listing creation screen.'); } private function resolveLocationFilters( diff --git a/Modules/Listing/Models/Listing.php b/Modules/Listing/Models/Listing.php index 15a079f20..f9255a805 100644 --- a/Modules/Listing/Models/Listing.php +++ b/Modules/Listing/Models/Listing.php @@ -146,6 +146,7 @@ class Listing extends Model implements HasMedia $search = trim((string) ($filters['search'] ?? '')); $country = isset($filters['country']) ? trim((string) $filters['country']) : null; $city = isset($filters['city']) ? trim((string) $filters['city']) : null; + $userId = isset($filters['user_id']) && is_numeric($filters['user_id']) ? (int) $filters['user_id'] : null; $minPrice = is_numeric($filters['min_price'] ?? null) ? max((float) $filters['min_price'], 0) : null; $maxPrice = is_numeric($filters['max_price'] ?? null) ? max((float) $filters['max_price'], 0) : null; $dateFilter = (string) ($filters['date_filter'] ?? 'all'); @@ -154,6 +155,7 @@ class Listing extends Model implements HasMedia $query ->searchTerm($search) ->forCategoryIds(is_array($categoryIds) ? $categoryIds : null) + ->when(! is_null($userId) && $userId > 0, fn (Builder $builder) => $builder->where('user_id', $userId)) ->when($country !== null && $country !== '', fn (Builder $builder) => $builder->where('country', $country)) ->when($city !== null && $city !== '', fn (Builder $builder) => $builder->where('city', $city)) ->when(! is_null($minPrice), fn (Builder $builder) => $builder->whereNotNull('price')->where('price', '>=', $minPrice)) @@ -259,7 +261,7 @@ class Listing extends Model implements HasMedia public function panelPriceLabel(): string { if (is_null($this->price)) { - return 'Ücretsiz'; + return 'Free'; } return number_format((float) $this->price, 2, ',', '.').' '.($this->currency ?? 'TL'); @@ -269,24 +271,24 @@ class Listing extends Model implements HasMedia { return match ($this->statusValue()) { 'sold' => [ - 'label' => 'Satıldı', + 'label' => 'Sold', 'badge_class' => 'is-success', - 'hint' => 'İlan satıldı olarak işaretlendi.', + 'hint' => 'This listing is marked as sold.', ], 'expired' => [ - 'label' => 'Süresi doldu', + 'label' => 'Expired', 'badge_class' => 'is-danger', - 'hint' => 'Yeniden yayına alınmayı bekliyor.', + 'hint' => 'This listing is waiting to be republished.', ], 'pending' => [ - 'label' => 'İncelemede', + 'label' => 'Pending review', 'badge_class' => 'is-warning', - 'hint' => 'Moderasyon onayı bekleniyor.', + 'hint' => 'Waiting for moderation approval.', ], default => [ - 'label' => 'Yayında', + 'label' => 'Live', 'badge_class' => 'is-primary', - 'hint' => 'Şu anda ziyaretçilere görünüyor.', + 'hint' => 'Visible to visitors right now.', ], }; } @@ -298,7 +300,7 @@ class Listing extends Model implements HasMedia trim((string) $this->country), ])->filter()->values(); - return $parts->isNotEmpty() ? $parts->implode(', ') : 'Konum belirtilmedi'; + return $parts->isNotEmpty() ? $parts->implode(', ') : 'Location not specified'; } public function panelPublishedAt(): ?Carbon @@ -320,16 +322,16 @@ class Listing extends Model implements HasMedia public function panelExpirySummary(): string { if (! $this->expires_at) { - return 'Süre sınırı yok'; + return 'No expiry limit'; } $expiresAt = $this->expires_at->copy()->startOfDay(); $days = Carbon::today()->diffInDays($expiresAt, false); return match (true) { - $days > 0 => $days.' gün kaldı', - $days === 0 => 'Bugün sona eriyor', - default => abs($days).' gün önce sona erdi', + $days > 0 => $days.' days left', + $days === 0 => 'Ends today', + default => 'Expired '.abs($days).' days ago', }; } @@ -340,8 +342,8 @@ class Listing extends Model implements HasMedia } return [ - 'label' => $total.' video', - 'detail' => $ready.' hazır'.($pending > 0 ? ', '.$pending.' işleniyor' : ''), + 'label' => $total.' videos', + 'detail' => $ready.' ready'.($pending > 0 ? ', '.$pending.' processing' : ''), ]; } diff --git a/Modules/Listing/Support/ListingCustomFieldSchemaBuilder.php b/Modules/Listing/Support/ListingCustomFieldSchemaBuilder.php index a5ef96481..43731d971 100644 --- a/Modules/Listing/Support/ListingCustomFieldSchemaBuilder.php +++ b/Modules/Listing/Support/ListingCustomFieldSchemaBuilder.php @@ -66,12 +66,12 @@ class ListingCustomFieldSchemaBuilder $label = $field?->label ?: Str::headline((string) $key); if (is_bool($value)) { - $displayValue = $value ? 'Evet' : 'Hayır'; + $displayValue = $value ? 'Yes' : 'No'; } elseif (is_array($value)) { $displayValue = implode(', ', array_map(fn ($item): string => (string) $item, $value)); } elseif ($field?->type === ListingCustomField::TYPE_DATE) { try { - $displayValue = Carbon::parse((string) $value)->format('d.m.Y'); + $displayValue = Carbon::parse((string) $value)->format('M j, Y'); } catch (\Throwable) { $displayValue = (string) $value; } diff --git a/Modules/Listing/resources/views/index.blade.php b/Modules/Listing/resources/views/index.blade.php index b744e299c..561bb9a1b 100644 --- a/Modules/Listing/resources/views/index.blade.php +++ b/Modules/Listing/resources/views/index.blade.php @@ -1,450 +1,7 @@ @extends('app::layouts.app') + +@section('title', trim((string) ($selectedCategory?->name ?? '')) !== '' ? trim((string) $selectedCategory->name).' Listings and Prices' : 'All Listings and Prices') + @section('content') -@php - $allListingsCount = isset($allListingsTotal) ? (int) $allListingsTotal : (int) $listings->total(); - $resultListingsCount = isset($filteredListingsTotal) ? (int) $filteredListingsTotal : (int) $listings->total(); - $activeCategoryName = $selectedCategory?->name ? trim((string) $selectedCategory->name) : ''; - $pageTitle = $activeCategoryName !== '' - ? 'İkinci El '.$activeCategoryName.' İlanları ve Fiyatları' - : 'İkinci El Araba İlanları ve Fiyatları'; - $canSaveSearch = $search !== '' || ! is_null($categoryId); - $normalizeQuery = static fn ($value): bool => ! is_null($value) && $value !== ''; - $baseCategoryQuery = array_filter([ - 'search' => $search !== '' ? $search : null, - 'country' => $countryId, - 'city' => $cityId, - 'min_price' => $minPriceInput !== '' ? $minPriceInput : null, - 'max_price' => $maxPriceInput !== '' ? $maxPriceInput : null, - 'date_filter' => $dateFilter !== 'all' ? $dateFilter : null, - 'sort' => $sort !== 'smart' ? $sort : null, - ], $normalizeQuery); - $clearFiltersQuery = array_filter([ - 'search' => $search !== '' ? $search : null, - ], $normalizeQuery); -@endphp - -
-

{{ $pageTitle }}

- -
- - -
-
-

- {{ $activeCategoryName !== '' ? 'İkinci El '.$activeCategoryName.' kategorisinde' : 'İkinci El Araba kategorisinde' }} - {{ number_format($resultListingsCount, 0, ',', '.') }} - ilan bulundu -

-
- @auth -
- @csrf - - - - - @else - - Arama Kaydet - - @endauth - -
- @if($search !== '') - - @endif - @if($categoryId) - - @endif - @if($countryId) - - @endif - @if($cityId) - - @endif - @if($minPriceInput !== '') - - @endif - @if($maxPriceInput !== '') - - @endif - @if($dateFilter !== 'all') - - @endif - - - -
-
- - @if($listings->isEmpty()) -
- Bu filtreye uygun ilan bulunamadı. -
- @else -
- @foreach($listings as $listing) - @php - $listingImage = $listing->getFirstMediaUrl('listing-images'); - $isFavorited = in_array($listing->id, $favoriteListingIds ?? [], true); - $priceValue = ! is_null($listing->price) ? (float) $listing->price : null; - $locationParts = array_filter([ - trim((string) ($listing->city ?? '')), - trim((string) ($listing->country ?? '')), - ], fn ($value) => $value !== ''); - $locationText = implode(', ', $locationParts); - @endphp -
-
- @if($listingImage) - - {{ $listing->title }} - - @else - - - - - - @endif - - @if($listing->is_featured) - - Öne Çıkan - - @endif - -
- @auth -
- @csrf - - - @else - - ♥ - - @endauth -
-
- -
- -

- @if(!is_null($priceValue) && $priceValue > 0) - {{ number_format($priceValue, 0, ',', '.') }} {{ $listing->currency }} - @else - Ücretsiz - @endif -

-

- {{ $listing->title }} -

-
- -

- {{ $listing->category?->name ?: 'Kategori yok' }} -

- -
- {{ $locationText !== '' ? $locationText : 'Konum belirtilmedi' }} - {{ $listing->created_at?->format('d.m.Y') }} -
-
-
- @endforeach -
- @endif - -
- {{ $listings->links() }} -
-
-
-
- - + @include('listing::partials.index-content') @endsection diff --git a/Modules/Listing/resources/views/partials/index-content.blade.php b/Modules/Listing/resources/views/partials/index-content.blade.php new file mode 100644 index 000000000..df506b651 --- /dev/null +++ b/Modules/Listing/resources/views/partials/index-content.blade.php @@ -0,0 +1,454 @@ +@php + $allListingsCount = isset($allListingsTotal) ? (int) $allListingsTotal : (int) $listings->total(); + $resultListingsCount = isset($filteredListingsTotal) ? (int) $filteredListingsTotal : (int) $listings->total(); + $activeCategoryName = $selectedCategory?->name ? trim((string) $selectedCategory->name) : ''; + $seoHeading = $activeCategoryName !== '' + ? $activeCategoryName.' Listings and Prices' + : 'All Listings and Prices'; + $canSaveSearch = $search !== '' || ! is_null($categoryId); + $normalizeQuery = static fn ($value): bool => ! is_null($value) && $value !== ''; + $baseCategoryQuery = array_filter([ + 'search' => $search !== '' ? $search : null, + 'user' => $sellerUserId ?? null, + 'country' => $countryId, + 'city' => $cityId, + 'min_price' => $minPriceInput !== '' ? $minPriceInput : null, + 'max_price' => $maxPriceInput !== '' ? $maxPriceInput : null, + 'date_filter' => $dateFilter !== 'all' ? $dateFilter : null, + 'sort' => $sort !== 'smart' ? $sort : null, + ], $normalizeQuery); + $clearFiltersQuery = array_filter([ + 'search' => $search !== '' ? $search : null, + 'user' => $sellerUserId ?? null, + ], $normalizeQuery); +@endphp + +
+

{{ $seoHeading }}

+ +
+ + +
+
+

+ {{ number_format($resultListingsCount) }} + {{ $activeCategoryName !== '' ? ' listings found in '.$activeCategoryName : ' listings found' }} +

+
+ @auth +
+ @csrf + + + + + @else + + Save search + + @endauth + +
+ @if($search !== '') + + @endif + @if($categoryId) + + @endif + @if(! empty($sellerUserId)) + + @endif + @if($countryId) + + @endif + @if($cityId) + + @endif + @if($minPriceInput !== '') + + @endif + @if($maxPriceInput !== '') + + @endif + @if($dateFilter !== 'all') + + @endif + + + +
+
+ + @if($listings->isEmpty()) +
+ No listings match this filter. +
+ @else +
+ @foreach($listings as $listing) + @php + $listingImage = $listing->getFirstMediaUrl('listing-images'); + $isFavorited = in_array($listing->id, $favoriteListingIds ?? [], true); + $priceValue = ! is_null($listing->price) ? (float) $listing->price : null; + $locationParts = array_filter([ + trim((string) ($listing->city ?? '')), + trim((string) ($listing->country ?? '')), + ], fn ($value) => $value !== ''); + $locationText = implode(', ', $locationParts); + @endphp +
+
+ @if($listingImage) + + {{ $listing->title }} + + @else + + + + + + @endif + + @if($listing->is_featured) + + Featured + + @endif + +
+ @auth +
+ @csrf + + + @else + + ♥ + + @endauth +
+
+ +
+ +

+ @if(!is_null($priceValue) && $priceValue > 0) + {{ number_format($priceValue, 0) }} {{ $listing->currency }} + @else + Free + @endif +

+

+ {{ $listing->title }} +

+
+ +

+ {{ $listing->category?->name ?: 'No category' }} +

+ +
+ {{ $locationText !== '' ? $locationText : 'Location not specified' }} + {{ $listing->created_at?->format('M j, Y') }} +
+
+
+ @endforeach +
+ @endif + +
+ {{ $listings->links() }} +
+
+
+
+ + diff --git a/Modules/Listing/resources/views/show.blade.php b/Modules/Listing/resources/views/show.blade.php index a219646e4..50e27b959 100644 --- a/Modules/Listing/resources/views/show.blade.php +++ b/Modules/Listing/resources/views/show.blade.php @@ -42,32 +42,32 @@ @csrf @if($listing->user && (int) $listing->user->id !== (int) auth()->id()) @csrf @if($existingConversationId) - Sohbete Git + Open chat @else @csrf @endif @endif @else - Giriş yap ve favorile + Log in to save @endauth @@ -79,7 +79,7 @@ @if(($presentableCustomFields ?? []) !== [])
-

İlan Özellikleri

+

Listing details

@foreach($presentableCustomFields as $field)
diff --git a/Modules/Listing/resources/views/themes/default/index.blade.php b/Modules/Listing/resources/views/themes/default/index.blade.php index b744e299c..561bb9a1b 100644 --- a/Modules/Listing/resources/views/themes/default/index.blade.php +++ b/Modules/Listing/resources/views/themes/default/index.blade.php @@ -1,450 +1,7 @@ @extends('app::layouts.app') + +@section('title', trim((string) ($selectedCategory?->name ?? '')) !== '' ? trim((string) $selectedCategory->name).' Listings and Prices' : 'All Listings and Prices') + @section('content') -@php - $allListingsCount = isset($allListingsTotal) ? (int) $allListingsTotal : (int) $listings->total(); - $resultListingsCount = isset($filteredListingsTotal) ? (int) $filteredListingsTotal : (int) $listings->total(); - $activeCategoryName = $selectedCategory?->name ? trim((string) $selectedCategory->name) : ''; - $pageTitle = $activeCategoryName !== '' - ? 'İkinci El '.$activeCategoryName.' İlanları ve Fiyatları' - : 'İkinci El Araba İlanları ve Fiyatları'; - $canSaveSearch = $search !== '' || ! is_null($categoryId); - $normalizeQuery = static fn ($value): bool => ! is_null($value) && $value !== ''; - $baseCategoryQuery = array_filter([ - 'search' => $search !== '' ? $search : null, - 'country' => $countryId, - 'city' => $cityId, - 'min_price' => $minPriceInput !== '' ? $minPriceInput : null, - 'max_price' => $maxPriceInput !== '' ? $maxPriceInput : null, - 'date_filter' => $dateFilter !== 'all' ? $dateFilter : null, - 'sort' => $sort !== 'smart' ? $sort : null, - ], $normalizeQuery); - $clearFiltersQuery = array_filter([ - 'search' => $search !== '' ? $search : null, - ], $normalizeQuery); -@endphp - -
-

{{ $pageTitle }}

- -
- - -
-
-

- {{ $activeCategoryName !== '' ? 'İkinci El '.$activeCategoryName.' kategorisinde' : 'İkinci El Araba kategorisinde' }} - {{ number_format($resultListingsCount, 0, ',', '.') }} - ilan bulundu -

-
- @auth -
- @csrf - - - - - @else - - Arama Kaydet - - @endauth - -
- @if($search !== '') - - @endif - @if($categoryId) - - @endif - @if($countryId) - - @endif - @if($cityId) - - @endif - @if($minPriceInput !== '') - - @endif - @if($maxPriceInput !== '') - - @endif - @if($dateFilter !== 'all') - - @endif - - - -
-
- - @if($listings->isEmpty()) -
- Bu filtreye uygun ilan bulunamadı. -
- @else -
- @foreach($listings as $listing) - @php - $listingImage = $listing->getFirstMediaUrl('listing-images'); - $isFavorited = in_array($listing->id, $favoriteListingIds ?? [], true); - $priceValue = ! is_null($listing->price) ? (float) $listing->price : null; - $locationParts = array_filter([ - trim((string) ($listing->city ?? '')), - trim((string) ($listing->country ?? '')), - ], fn ($value) => $value !== ''); - $locationText = implode(', ', $locationParts); - @endphp -
-
- @if($listingImage) - - {{ $listing->title }} - - @else - - - - - - @endif - - @if($listing->is_featured) - - Öne Çıkan - - @endif - -
- @auth -
- @csrf - - - @else - - ♥ - - @endauth -
-
- -
- -

- @if(!is_null($priceValue) && $priceValue > 0) - {{ number_format($priceValue, 0, ',', '.') }} {{ $listing->currency }} - @else - Ücretsiz - @endif -

-

- {{ $listing->title }} -

-
- -

- {{ $listing->category?->name ?: 'Kategori yok' }} -

- -
- {{ $locationText !== '' ? $locationText : 'Konum belirtilmedi' }} - {{ $listing->created_at?->format('d.m.Y') }} -
-
-
- @endforeach -
- @endif - -
- {{ $listings->links() }} -
-
-
-
- - + @include('listing::partials.index-content') @endsection diff --git a/Modules/Listing/resources/views/themes/default/show.blade.php b/Modules/Listing/resources/views/themes/default/show.blade.php index 58a27991f..244530ac1 100644 --- a/Modules/Listing/resources/views/themes/default/show.blade.php +++ b/Modules/Listing/resources/views/themes/default/show.blade.php @@ -42,32 +42,32 @@
@csrf @if($listing->user && (int) $listing->user->id !== (int) auth()->id())
@csrf @if($existingConversationId) - Sohbete Git + Open chat @else
@csrf @endif @endif @else - Giriş yap ve favorile + Log in to save @endauth
@@ -92,7 +92,7 @@ @endif @if(($presentableCustomFields ?? []) !== [])
-

İlan Özellikleri

+

Listing details

@foreach($presentableCustomFields as $field)
diff --git a/Modules/Listing/resources/views/themes/otoplus/index.blade.php b/Modules/Listing/resources/views/themes/otoplus/index.blade.php index b744e299c..561bb9a1b 100644 --- a/Modules/Listing/resources/views/themes/otoplus/index.blade.php +++ b/Modules/Listing/resources/views/themes/otoplus/index.blade.php @@ -1,450 +1,7 @@ @extends('app::layouts.app') + +@section('title', trim((string) ($selectedCategory?->name ?? '')) !== '' ? trim((string) $selectedCategory->name).' Listings and Prices' : 'All Listings and Prices') + @section('content') -@php - $allListingsCount = isset($allListingsTotal) ? (int) $allListingsTotal : (int) $listings->total(); - $resultListingsCount = isset($filteredListingsTotal) ? (int) $filteredListingsTotal : (int) $listings->total(); - $activeCategoryName = $selectedCategory?->name ? trim((string) $selectedCategory->name) : ''; - $pageTitle = $activeCategoryName !== '' - ? 'İkinci El '.$activeCategoryName.' İlanları ve Fiyatları' - : 'İkinci El Araba İlanları ve Fiyatları'; - $canSaveSearch = $search !== '' || ! is_null($categoryId); - $normalizeQuery = static fn ($value): bool => ! is_null($value) && $value !== ''; - $baseCategoryQuery = array_filter([ - 'search' => $search !== '' ? $search : null, - 'country' => $countryId, - 'city' => $cityId, - 'min_price' => $minPriceInput !== '' ? $minPriceInput : null, - 'max_price' => $maxPriceInput !== '' ? $maxPriceInput : null, - 'date_filter' => $dateFilter !== 'all' ? $dateFilter : null, - 'sort' => $sort !== 'smart' ? $sort : null, - ], $normalizeQuery); - $clearFiltersQuery = array_filter([ - 'search' => $search !== '' ? $search : null, - ], $normalizeQuery); -@endphp - -
-

{{ $pageTitle }}

- -
- - -
-
-

- {{ $activeCategoryName !== '' ? 'İkinci El '.$activeCategoryName.' kategorisinde' : 'İkinci El Araba kategorisinde' }} - {{ number_format($resultListingsCount, 0, ',', '.') }} - ilan bulundu -

-
- @auth -
- @csrf - - - - - @else - - Arama Kaydet - - @endauth - -
- @if($search !== '') - - @endif - @if($categoryId) - - @endif - @if($countryId) - - @endif - @if($cityId) - - @endif - @if($minPriceInput !== '') - - @endif - @if($maxPriceInput !== '') - - @endif - @if($dateFilter !== 'all') - - @endif - - - -
-
- - @if($listings->isEmpty()) -
- Bu filtreye uygun ilan bulunamadı. -
- @else -
- @foreach($listings as $listing) - @php - $listingImage = $listing->getFirstMediaUrl('listing-images'); - $isFavorited = in_array($listing->id, $favoriteListingIds ?? [], true); - $priceValue = ! is_null($listing->price) ? (float) $listing->price : null; - $locationParts = array_filter([ - trim((string) ($listing->city ?? '')), - trim((string) ($listing->country ?? '')), - ], fn ($value) => $value !== ''); - $locationText = implode(', ', $locationParts); - @endphp -
-
- @if($listingImage) - - {{ $listing->title }} - - @else - - - - - - @endif - - @if($listing->is_featured) - - Öne Çıkan - - @endif - -
- @auth -
- @csrf - - - @else - - ♥ - - @endauth -
-
- -
- -

- @if(!is_null($priceValue) && $priceValue > 0) - {{ number_format($priceValue, 0, ',', '.') }} {{ $listing->currency }} - @else - Ücretsiz - @endif -

-

- {{ $listing->title }} -

-
- -

- {{ $listing->category?->name ?: 'Kategori yok' }} -

- -
- {{ $locationText !== '' ? $locationText : 'Konum belirtilmedi' }} - {{ $listing->created_at?->format('d.m.Y') }} -
-
-
- @endforeach -
- @endif - -
- {{ $listings->links() }} -
-
-
-
- - + @include('listing::partials.index-content') @endsection diff --git a/Modules/Listing/resources/views/themes/otoplus/show.blade.php b/Modules/Listing/resources/views/themes/otoplus/show.blade.php index 86827157b..e2930b6f2 100644 --- a/Modules/Listing/resources/views/themes/otoplus/show.blade.php +++ b/Modules/Listing/resources/views/themes/otoplus/show.blade.php @@ -40,6 +40,12 @@ $referenceCode = '#'.str_pad((string) $listing->getKey(), 8, '0', STR_PAD_LEFT); $canContactSeller = $listing->user && (! auth()->check() || (int) auth()->id() !== (int) $listing->user_id); $isOwnListing = auth()->check() && (int) auth()->id() === (int) $listing->user_id; + $canStartConversation = auth()->check() && $listing->user && ! $isOwnListing; + $loginRedirectRoute = route('login', ['redirect' => request()->fullUrl()]); + $chatConversation = $detailConversation ?? null; + $chatMessages = $chatConversation?->messages ?? collect(); + $chatSendUrl = $chatConversation ? route('conversations.messages.send', $chatConversation) : ''; + $chatStartUrl = route('conversations.start', $listing); $primaryContactHref = null; $primaryContactLabel = 'Call'; @@ -51,13 +57,6 @@ $primaryContactLabel = 'Email'; } - $mapQuery = filled($listing->latitude) && filled($listing->longitude) - ? trim((string) $listing->latitude).','.trim((string) $listing->longitude) - : str_replace(' / ', ', ', $locationLabel); - $mapUrl = $mapQuery !== '' - ? 'https://www.google.com/maps/search/?api=1&query='.urlencode($mapQuery) - : null; - $reportEmail = config('mail.from.address', 'support@example.com'); $reportUrl = 'mailto:'.$reportEmail.'?subject='.rawurlencode('Report listing '.$referenceCode); $shareUrl = route('listings.show', $listing); @@ -358,21 +357,12 @@
@if(! $listing->user) - @elseif($canContactSeller) - @if($existingConversationId) - - Message - - @else -
- @csrf - - - @endif + @elseif($canStartConversation) + @elseif($isOwnListing) @else - Message + Message @endif @if($primaryContactHref) @@ -382,49 +372,21 @@ @endif
- @if(! $listing->user) - - @elseif($canContactSeller) - @if($existingConversationId) - - Make offer - - @else -
+ @if($listing->user && ! $isOwnListing) + @auth + @csrf - + + - @endif + @else + Save seller + @endauth @elseif($isOwnListing) - - @else - Make offer + @endif - -
- @if($mapUrl) - - View map - - @else - - @endif - - @if($listing->user && ! $isOwnListing) - @auth -
- @csrf - - - @else - Save seller - @endauth - @else - - @endif -
@@ -441,21 +403,12 @@
@if(! $listing->user) - @elseif($canContactSeller) - @if($existingConversationId) - - Message - - @else -
- @csrf - - - @endif + @elseif($canStartConversation) + @elseif($isOwnListing) @else - Message + Message @endif @if($primaryContactHref) @@ -465,27 +418,76 @@ @endif
- @if(! $listing->user) - - @elseif($canContactSeller) - @if($existingConversationId) - - Make offer - - @else -
+ @if($listing->user && ! $isOwnListing) + @auth + @csrf - + + - @endif + @else + Save seller + @endauth @elseif($isOwnListing) - - @else - Make offer + @endif
+ @if($canStartConversation) +
+ +
+ @endif + @if(($relatedListings ?? collect())->isNotEmpty() || ($themePillCategories ?? collect())->isNotEmpty())
İlan BaşlığıFiyatMesajlaşmaListingPriceMessaging
@csrf - +
- Henüz favori ilan bulunmuyor. + No saved listings yet.