mirror of
https://github.com/openclassify/openclassify.git
synced 2026-04-14 11:12:09 -05:00
Refactor Filament module UX
This commit is contained in:
parent
08d0b68349
commit
154b226a03
7
AGENTS.md
Normal file
7
AGENTS.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Act as a Senior Laravel & FilamentPHP Architect. Refactor the attached code as a greenfield project adhering to the following strict constraints:
|
||||||
|
1. Architecture: Enforce strict SOLID principles, prioritize brevity, and completely ignore backward compatibility.
|
||||||
|
2. Cleanup: Remove all legacy code, comments, tests, and PHPDocs.
|
||||||
|
3. Refactoring: Move all database logic into Models and extract repetitive Filament code into dedicated Helper classes. Identify and fix any existing logical errors.
|
||||||
|
4. Database: Consolidate migrations into a single file per table or topic (e.g., users, cache, jobs) to reduce the overall number of migration files.
|
||||||
|
5. Modularity: Use the `laravel-modules` package to encapsulate all features, routing, and Filament resources strictly inside their respective modules.
|
||||||
|
6. Frontend: Optimize and reduce the CSS footprint while maintaining the exact same visual output.
|
||||||
@ -33,16 +33,51 @@ class ManageGeneralSettings extends SettingsPage
|
|||||||
|
|
||||||
protected static ?int $navigationSort = 1;
|
protected static ?int $navigationSort = 1;
|
||||||
|
|
||||||
|
protected function mutateFormDataBeforeFill(array $data): array
|
||||||
|
{
|
||||||
|
$defaults = $this->defaultFormData();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'site_name' => filled($data['site_name'] ?? null) ? $data['site_name'] : $defaults['site_name'],
|
||||||
|
'site_description' => filled($data['site_description'] ?? null) ? $data['site_description'] : $defaults['site_description'],
|
||||||
|
'home_slides' => $this->normalizeHomeSlides($data['home_slides'] ?? $defaults['home_slides']),
|
||||||
|
'site_logo' => $data['site_logo'] ?? null,
|
||||||
|
'sender_name' => filled($data['sender_name'] ?? null) ? $data['sender_name'] : $defaults['sender_name'],
|
||||||
|
'sender_email' => filled($data['sender_email'] ?? null) ? $data['sender_email'] : $defaults['sender_email'],
|
||||||
|
'default_language' => filled($data['default_language'] ?? null) ? $data['default_language'] : $defaults['default_language'],
|
||||||
|
'default_country_code' => filled($data['default_country_code'] ?? null) ? $data['default_country_code'] : $defaults['default_country_code'],
|
||||||
|
'currencies' => $this->normalizeCurrencies($data['currencies'] ?? $defaults['currencies']),
|
||||||
|
'linkedin_url' => filled($data['linkedin_url'] ?? null) ? $data['linkedin_url'] : $defaults['linkedin_url'],
|
||||||
|
'instagram_url' => filled($data['instagram_url'] ?? null) ? $data['instagram_url'] : $defaults['instagram_url'],
|
||||||
|
'whatsapp' => filled($data['whatsapp'] ?? null) ? $data['whatsapp'] : $defaults['whatsapp'],
|
||||||
|
'enable_google_maps' => (bool) ($data['enable_google_maps'] ?? $defaults['enable_google_maps']),
|
||||||
|
'google_maps_api_key' => $data['google_maps_api_key'] ?? null,
|
||||||
|
'enable_google_login' => (bool) ($data['enable_google_login'] ?? $defaults['enable_google_login']),
|
||||||
|
'google_client_id' => $data['google_client_id'] ?? null,
|
||||||
|
'google_client_secret' => $data['google_client_secret'] ?? null,
|
||||||
|
'enable_facebook_login' => (bool) ($data['enable_facebook_login'] ?? $defaults['enable_facebook_login']),
|
||||||
|
'facebook_client_id' => $data['facebook_client_id'] ?? null,
|
||||||
|
'facebook_client_secret' => $data['facebook_client_secret'] ?? null,
|
||||||
|
'enable_apple_login' => (bool) ($data['enable_apple_login'] ?? $defaults['enable_apple_login']),
|
||||||
|
'apple_client_id' => $data['apple_client_id'] ?? null,
|
||||||
|
'apple_client_secret' => $data['apple_client_secret'] ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function form(Schema $schema): Schema
|
public function form(Schema $schema): Schema
|
||||||
{
|
{
|
||||||
|
$defaults = $this->defaultFormData();
|
||||||
|
|
||||||
return $schema
|
return $schema
|
||||||
->components([
|
->components([
|
||||||
TextInput::make('site_name')
|
TextInput::make('site_name')
|
||||||
->label('Site Adı')
|
->label('Site Adı')
|
||||||
|
->default($defaults['site_name'])
|
||||||
->required()
|
->required()
|
||||||
->maxLength(255),
|
->maxLength(255),
|
||||||
Textarea::make('site_description')
|
Textarea::make('site_description')
|
||||||
->label('Site Açıklaması')
|
->label('Site Açıklaması')
|
||||||
|
->default($defaults['site_description'])
|
||||||
->rows(3)
|
->rows(3)
|
||||||
->maxLength(500),
|
->maxLength(500),
|
||||||
Repeater::make('home_slides')
|
Repeater::make('home_slides')
|
||||||
@ -70,7 +105,7 @@ class ManageGeneralSettings extends SettingsPage
|
|||||||
->required()
|
->required()
|
||||||
->maxLength(120),
|
->maxLength(120),
|
||||||
])
|
])
|
||||||
->default($this->defaultHomeSlides())
|
->default($defaults['home_slides'])
|
||||||
->minItems(1)
|
->minItems(1)
|
||||||
->collapsible()
|
->collapsible()
|
||||||
->reorderableWithButtons()
|
->reorderableWithButtons()
|
||||||
@ -86,26 +121,30 @@ class ManageGeneralSettings extends SettingsPage
|
|||||||
->visibility('public'),
|
->visibility('public'),
|
||||||
TextInput::make('sender_name')
|
TextInput::make('sender_name')
|
||||||
->label('Gönderici Adı')
|
->label('Gönderici Adı')
|
||||||
|
->default($defaults['sender_name'])
|
||||||
->required()
|
->required()
|
||||||
->maxLength(120),
|
->maxLength(120),
|
||||||
TextInput::make('sender_email')
|
TextInput::make('sender_email')
|
||||||
->label('Gönderici E-postası')
|
->label('Gönderici E-postası')
|
||||||
->email()
|
->email()
|
||||||
|
->default($defaults['sender_email'])
|
||||||
->required()
|
->required()
|
||||||
->maxLength(255),
|
->maxLength(255),
|
||||||
Select::make('default_language')
|
Select::make('default_language')
|
||||||
->label('Varsayılan Dil')
|
->label('Varsayılan Dil')
|
||||||
->options($this->localeOptions())
|
->options($this->localeOptions())
|
||||||
|
->default($defaults['default_language'])
|
||||||
->required()
|
->required()
|
||||||
->searchable(),
|
->searchable(),
|
||||||
CountryCodeSelect::make('default_country_code')
|
CountryCodeSelect::make('default_country_code')
|
||||||
->label('Varsayılan Ülke')
|
->label('Varsayılan Ülke')
|
||||||
->default('+90')
|
->default($defaults['default_country_code'])
|
||||||
->required()
|
->required()
|
||||||
->helperText('Panel formlarında varsayılan ülke olarak kullanılır.'),
|
->helperText('Panel formlarında varsayılan ülke olarak kullanılır.'),
|
||||||
TagsInput::make('currencies')
|
TagsInput::make('currencies')
|
||||||
->label('Para Birimleri')
|
->label('Para Birimleri')
|
||||||
->placeholder('TRY')
|
->placeholder('TRY')
|
||||||
|
->default($defaults['currencies'])
|
||||||
->helperText('TRY, USD, EUR gibi 3 harfli para birimi kodları ekleyin.')
|
->helperText('TRY, USD, EUR gibi 3 harfli para birimi kodları ekleyin.')
|
||||||
->required()
|
->required()
|
||||||
->rules(['array', 'min:1'])
|
->rules(['array', 'min:1'])
|
||||||
@ -114,22 +153,25 @@ class ManageGeneralSettings extends SettingsPage
|
|||||||
TextInput::make('linkedin_url')
|
TextInput::make('linkedin_url')
|
||||||
->label('LinkedIn URL')
|
->label('LinkedIn URL')
|
||||||
->url()
|
->url()
|
||||||
|
->default($defaults['linkedin_url'])
|
||||||
->nullable()
|
->nullable()
|
||||||
->maxLength(255),
|
->maxLength(255),
|
||||||
TextInput::make('instagram_url')
|
TextInput::make('instagram_url')
|
||||||
->label('Instagram URL')
|
->label('Instagram URL')
|
||||||
->url()
|
->url()
|
||||||
|
->default($defaults['instagram_url'])
|
||||||
->nullable()
|
->nullable()
|
||||||
->maxLength(255),
|
->maxLength(255),
|
||||||
PhoneInput::make('whatsapp')
|
PhoneInput::make('whatsapp')
|
||||||
->label('WhatsApp')
|
->label('WhatsApp')
|
||||||
->defaultCountry(CountryCodeManager::defaultCountryIso2())
|
->defaultCountry(CountryCodeManager::defaultCountryIso2())
|
||||||
|
->default($defaults['whatsapp'])
|
||||||
->nullable()
|
->nullable()
|
||||||
->formatAsYouType()
|
->formatAsYouType()
|
||||||
->helperText('Uluslararası format kullanın. Örnek: +905551112233'),
|
->helperText('Uluslararası format kullanın. Örnek: +905551112233'),
|
||||||
Toggle::make('enable_google_maps')
|
Toggle::make('enable_google_maps')
|
||||||
->label('Google Maps Aktif')
|
->label('Google Maps Aktif')
|
||||||
->default(false),
|
->default($defaults['enable_google_maps']),
|
||||||
TextInput::make('google_maps_api_key')
|
TextInput::make('google_maps_api_key')
|
||||||
->label('Google Maps API Anahtarı')
|
->label('Google Maps API Anahtarı')
|
||||||
->password()
|
->password()
|
||||||
@ -139,7 +181,7 @@ class ManageGeneralSettings extends SettingsPage
|
|||||||
->helperText('İlan formlarındaki harita alanlarını açmak için gereklidir.'),
|
->helperText('İlan formlarındaki harita alanlarını açmak için gereklidir.'),
|
||||||
Toggle::make('enable_google_login')
|
Toggle::make('enable_google_login')
|
||||||
->label('Google ile Giriş Aktif')
|
->label('Google ile Giriş Aktif')
|
||||||
->default(false),
|
->default($defaults['enable_google_login']),
|
||||||
TextInput::make('google_client_id')
|
TextInput::make('google_client_id')
|
||||||
->label('Google Client ID')
|
->label('Google Client ID')
|
||||||
->nullable()
|
->nullable()
|
||||||
@ -152,7 +194,7 @@ class ManageGeneralSettings extends SettingsPage
|
|||||||
->maxLength(255),
|
->maxLength(255),
|
||||||
Toggle::make('enable_facebook_login')
|
Toggle::make('enable_facebook_login')
|
||||||
->label('Facebook ile Giriş Aktif')
|
->label('Facebook ile Giriş Aktif')
|
||||||
->default(false),
|
->default($defaults['enable_facebook_login']),
|
||||||
TextInput::make('facebook_client_id')
|
TextInput::make('facebook_client_id')
|
||||||
->label('Facebook Client ID')
|
->label('Facebook Client ID')
|
||||||
->nullable()
|
->nullable()
|
||||||
@ -165,7 +207,7 @@ class ManageGeneralSettings extends SettingsPage
|
|||||||
->maxLength(255),
|
->maxLength(255),
|
||||||
Toggle::make('enable_apple_login')
|
Toggle::make('enable_apple_login')
|
||||||
->label('Apple ile Giriş Aktif')
|
->label('Apple ile Giriş Aktif')
|
||||||
->default(false),
|
->default($defaults['enable_apple_login']),
|
||||||
TextInput::make('apple_client_id')
|
TextInput::make('apple_client_id')
|
||||||
->label('Apple Client ID')
|
->label('Apple Client ID')
|
||||||
->nullable()
|
->nullable()
|
||||||
@ -179,6 +221,30 @@ class ManageGeneralSettings extends SettingsPage
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function defaultFormData(): array
|
||||||
|
{
|
||||||
|
$siteName = (string) config('app.name', 'OpenClassify');
|
||||||
|
$siteHost = parse_url((string) config('app.url', 'https://oc2.test'), PHP_URL_HOST) ?: 'oc2.test';
|
||||||
|
|
||||||
|
return [
|
||||||
|
'site_name' => $siteName,
|
||||||
|
'site_description' => 'Alim satim icin hizli ve guvenli ilan platformu.',
|
||||||
|
'home_slides' => $this->defaultHomeSlides(),
|
||||||
|
'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_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',
|
||||||
|
'instagram_url' => 'https://www.instagram.com/openclassify',
|
||||||
|
'whatsapp' => '+905551112233',
|
||||||
|
'enable_google_maps' => false,
|
||||||
|
'enable_google_login' => false,
|
||||||
|
'enable_facebook_login' => false,
|
||||||
|
'enable_apple_login' => false,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
private function localeOptions(): array
|
private function localeOptions(): array
|
||||||
{
|
{
|
||||||
$labels = [
|
$labels = [
|
||||||
|
|||||||
@ -45,7 +45,7 @@ class CategoryResource extends Resource
|
|||||||
TextColumn::make('listings_count')->counts('listings')->label('Listings'),
|
TextColumn::make('listings_count')->counts('listings')->label('Listings'),
|
||||||
IconColumn::make('is_active')->boolean(),
|
IconColumn::make('is_active')->boolean(),
|
||||||
TextColumn::make('sort_order')->sortable(),
|
TextColumn::make('sort_order')->sortable(),
|
||||||
])->actions([
|
])->defaultSort('id', 'desc')->actions([
|
||||||
EditAction::make(),
|
EditAction::make(),
|
||||||
Action::make('activities')
|
Action::make('activities')
|
||||||
->icon('heroicon-o-clock')
|
->icon('heroicon-o-clock')
|
||||||
|
|||||||
@ -46,7 +46,7 @@ class CityResource extends Resource
|
|||||||
TextColumn::make('districts_count')->counts('districts')->label('Districts')->sortable(),
|
TextColumn::make('districts_count')->counts('districts')->label('Districts')->sortable(),
|
||||||
IconColumn::make('is_active')->boolean(),
|
IconColumn::make('is_active')->boolean(),
|
||||||
TextColumn::make('created_at')->dateTime()->sortable()->toggleable(isToggledHiddenByDefault: true),
|
TextColumn::make('created_at')->dateTime()->sortable()->toggleable(isToggledHiddenByDefault: true),
|
||||||
])->filters([
|
])->defaultSort('id', 'desc')->filters([
|
||||||
SelectFilter::make('country_id')
|
SelectFilter::make('country_id')
|
||||||
->label('Country')
|
->label('Country')
|
||||||
->relationship('country', 'name')
|
->relationship('country', 'name')
|
||||||
|
|||||||
@ -48,7 +48,7 @@ class DistrictResource extends Resource
|
|||||||
TextColumn::make('city.country.name')->label('Country'),
|
TextColumn::make('city.country.name')->label('Country'),
|
||||||
IconColumn::make('is_active')->boolean(),
|
IconColumn::make('is_active')->boolean(),
|
||||||
TextColumn::make('created_at')->dateTime()->sortable()->toggleable(isToggledHiddenByDefault: true),
|
TextColumn::make('created_at')->dateTime()->sortable()->toggleable(isToggledHiddenByDefault: true),
|
||||||
])->filters([
|
])->defaultSort('id', 'desc')->filters([
|
||||||
SelectFilter::make('country_id')
|
SelectFilter::make('country_id')
|
||||||
->label('Country')
|
->label('Country')
|
||||||
->options(fn (): array => Country::query()->orderBy('name')->pluck('name', 'id')->all())
|
->options(fn (): array => Country::query()->orderBy('name')->pluck('name', 'id')->all())
|
||||||
|
|||||||
@ -105,7 +105,7 @@ class ListingCustomFieldResource extends Resource
|
|||||||
IconColumn::make('is_active')->boolean()->label('Active'),
|
IconColumn::make('is_active')->boolean()->label('Active'),
|
||||||
TextColumn::make('sort_order')->sortable(),
|
TextColumn::make('sort_order')->sortable(),
|
||||||
])
|
])
|
||||||
->defaultSort('sort_order')
|
->defaultSort('id', 'desc')
|
||||||
->actions([
|
->actions([
|
||||||
EditAction::make(),
|
EditAction::make(),
|
||||||
DeleteAction::make(),
|
DeleteAction::make(),
|
||||||
|
|||||||
@ -194,6 +194,7 @@ class ListingResource extends Resource
|
|||||||
->filtersFormColumns(3)
|
->filtersFormColumns(3)
|
||||||
->filtersFormWidth('7xl')
|
->filtersFormWidth('7xl')
|
||||||
->persistFiltersInSession()
|
->persistFiltersInSession()
|
||||||
|
->defaultSort('id', 'desc')
|
||||||
->actions([
|
->actions([
|
||||||
EditAction::make(),
|
EditAction::make(),
|
||||||
Action::make('activities')
|
Action::make('activities')
|
||||||
|
|||||||
@ -46,7 +46,7 @@ class LocationResource extends Resource
|
|||||||
TextColumn::make('cities_count')->counts('cities')->label('Cities')->sortable(),
|
TextColumn::make('cities_count')->counts('cities')->label('Cities')->sortable(),
|
||||||
IconColumn::make('is_active')->boolean(),
|
IconColumn::make('is_active')->boolean(),
|
||||||
TextColumn::make('created_at')->dateTime()->sortable()->toggleable(isToggledHiddenByDefault: true),
|
TextColumn::make('created_at')->dateTime()->sortable()->toggleable(isToggledHiddenByDefault: true),
|
||||||
])->filters([
|
])->defaultSort('id', 'desc')->filters([
|
||||||
TernaryFilter::make('is_active')->label('Active'),
|
TernaryFilter::make('is_active')->label('Active'),
|
||||||
])->actions([
|
])->actions([
|
||||||
EditAction::make(),
|
EditAction::make(),
|
||||||
|
|||||||
@ -43,7 +43,7 @@ class UserResource extends Resource
|
|||||||
TextColumn::make('roles.name')->badge()->label('Roles'),
|
TextColumn::make('roles.name')->badge()->label('Roles'),
|
||||||
StateFusionSelectColumn::make('status'),
|
StateFusionSelectColumn::make('status'),
|
||||||
TextColumn::make('created_at')->dateTime()->sortable(),
|
TextColumn::make('created_at')->dateTime()->sortable(),
|
||||||
])->filters([
|
])->defaultSort('id', 'desc')->filters([
|
||||||
StateFusionSelectFilter::make('status'),
|
StateFusionSelectFilter::make('status'),
|
||||||
])->actions([
|
])->actions([
|
||||||
EditAction::make(),
|
EditAction::make(),
|
||||||
|
|||||||
@ -3,7 +3,6 @@ namespace Modules\Category\Http\Controllers;
|
|||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Modules\Category\Models\Category;
|
use Modules\Category\Models\Category;
|
||||||
use Modules\Listing\Models\Listing;
|
|
||||||
use Modules\Theme\Support\ThemeManager;
|
use Modules\Theme\Support\ThemeManager;
|
||||||
|
|
||||||
class CategoryController extends Controller
|
class CategoryController extends Controller
|
||||||
@ -18,22 +17,4 @@ class CategoryController extends Controller
|
|||||||
|
|
||||||
return view($this->themes->view('category', 'index'), compact('categories'));
|
return view($this->themes->view('category', 'index'), compact('categories'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function show(Category $category)
|
|
||||||
{
|
|
||||||
$category->loadMissing([
|
|
||||||
'children' => fn ($query) => $query->active()->ordered(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$categoryIds = $category->descendantAndSelfIds()->all();
|
|
||||||
|
|
||||||
$listings = Listing::query()
|
|
||||||
->where('status', 'active')
|
|
||||||
->whereIn('category_id', $categoryIds)
|
|
||||||
->with('category:id,name')
|
|
||||||
->latest('id')
|
|
||||||
->paginate(12);
|
|
||||||
|
|
||||||
return view($this->themes->view('category', 'show'), compact('category', 'listings'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
|||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Modules\Listing\Models\Listing;
|
||||||
use Spatie\Activitylog\LogOptions;
|
use Spatie\Activitylog\LogOptions;
|
||||||
use Spatie\Activitylog\Traits\LogsActivity;
|
use Spatie\Activitylog\Traits\LogsActivity;
|
||||||
|
|
||||||
@ -78,6 +79,58 @@ class Category extends Model
|
|||||||
->get();
|
->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function listingDirectory(?int $selectedCategoryId): array
|
||||||
|
{
|
||||||
|
$categories = static::query()
|
||||||
|
->active()
|
||||||
|
->ordered()
|
||||||
|
->get(['id', 'name', 'parent_id']);
|
||||||
|
|
||||||
|
$activeListingCounts = Listing::query()
|
||||||
|
->active()
|
||||||
|
->whereNotNull('category_id')
|
||||||
|
->selectRaw('category_id, count(*) as aggregate')
|
||||||
|
->groupBy('category_id')
|
||||||
|
->pluck('aggregate', 'category_id')
|
||||||
|
->map(fn ($count): int => (int) $count);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'categories' => static::buildListingDirectoryTree($categories, $activeListingCounts),
|
||||||
|
'selectedCategory' => $selectedCategoryId
|
||||||
|
? $categories->firstWhere('id', $selectedCategoryId)
|
||||||
|
: null,
|
||||||
|
'filterIds' => static::listingFilterIds($selectedCategoryId, $categories),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function listingFilterIds(?int $selectedCategoryId, ?Collection $categories = null): ?array
|
||||||
|
{
|
||||||
|
if (! $selectedCategoryId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($categories instanceof Collection) {
|
||||||
|
$selectedCategory = $categories->firstWhere('id', $selectedCategoryId);
|
||||||
|
|
||||||
|
if (! $selectedCategory instanceof self) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return static::descendantAndSelfIdsFromCollection($selectedCategoryId, $categories);
|
||||||
|
}
|
||||||
|
|
||||||
|
$selectedCategory = static::query()
|
||||||
|
->active()
|
||||||
|
->whereKey($selectedCategoryId)
|
||||||
|
->first(['id']);
|
||||||
|
|
||||||
|
if (! $selectedCategory) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $selectedCategory->descendantAndSelfIds()->all();
|
||||||
|
}
|
||||||
|
|
||||||
public function descendantAndSelfIds(): Collection
|
public function descendantAndSelfIds(): Collection
|
||||||
{
|
{
|
||||||
$ids = collect([(int) $this->getKey()]);
|
$ids = collect([(int) $this->getKey()]);
|
||||||
@ -127,4 +180,54 @@ class Category extends Model
|
|||||||
{
|
{
|
||||||
return $this->hasMany(\Modules\Listing\Models\Listing::class)->where('status', 'active');
|
return $this->hasMany(\Modules\Listing\Models\Listing::class)->where('status', 'active');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function buildListingDirectoryTree(Collection $categories, Collection $activeListingCounts, ?int $parentId = null): Collection
|
||||||
|
{
|
||||||
|
return $categories
|
||||||
|
->filter(fn (Category $category): bool => $parentId === null
|
||||||
|
? $category->parent_id === null
|
||||||
|
: (int) $category->parent_id === $parentId)
|
||||||
|
->values()
|
||||||
|
->map(function (Category $category) use ($categories, $activeListingCounts): Category {
|
||||||
|
$children = static::buildListingDirectoryTree($categories, $activeListingCounts, (int) $category->getKey());
|
||||||
|
$directActiveListingsCount = (int) $activeListingCounts->get((int) $category->getKey(), 0);
|
||||||
|
$activeListingTotal = $directActiveListingsCount + $children->sum(
|
||||||
|
fn (Category $child): int => (int) $child->getAttribute('active_listing_total')
|
||||||
|
);
|
||||||
|
|
||||||
|
$category->setRelation('children', $children);
|
||||||
|
$category->setAttribute('direct_active_listings_count', $directActiveListingsCount);
|
||||||
|
$category->setAttribute('active_listing_total', $activeListingTotal);
|
||||||
|
|
||||||
|
return $category;
|
||||||
|
})
|
||||||
|
->values();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function descendantAndSelfIdsFromCollection(int $selectedCategoryId, Collection $categories): array
|
||||||
|
{
|
||||||
|
$ids = collect([$selectedCategoryId]);
|
||||||
|
$frontier = collect([$selectedCategoryId]);
|
||||||
|
|
||||||
|
while ($frontier->isNotEmpty()) {
|
||||||
|
$children = $categories
|
||||||
|
->filter(fn (Category $category): bool => $category->parent_id !== null && in_array((int) $category->parent_id, $frontier->all(), true))
|
||||||
|
->pluck('id')
|
||||||
|
->map(fn ($id): int => (int) $id)
|
||||||
|
->values();
|
||||||
|
|
||||||
|
if ($children->isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ids = $ids
|
||||||
|
->merge($children)
|
||||||
|
->unique()
|
||||||
|
->values();
|
||||||
|
|
||||||
|
$frontier = $children;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ids->all();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<h1 class="text-3xl font-bold mb-6">{{ __('messages.categories') }}</h1>
|
<h1 class="text-3xl font-bold mb-6">{{ __('messages.categories') }}</h1>
|
||||||
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||||
@foreach($categories as $category)
|
@foreach($categories as $category)
|
||||||
<a href="{{ route('categories.show', $category) }}" class="bg-white rounded-lg shadow-md p-6 text-center hover:shadow-lg transition hover:bg-blue-50">
|
<a href="{{ route('listings.index', ['category' => $category->id]) }}" class="bg-white rounded-lg shadow-md p-6 text-center hover:shadow-lg transition hover:bg-blue-50">
|
||||||
<div class="text-4xl mb-3">{{ $category->icon ?? '📦' }}</div>
|
<div class="text-4xl mb-3">{{ $category->icon ?? '📦' }}</div>
|
||||||
<h3 class="font-semibold text-gray-900">{{ $category->name }}</h3>
|
<h3 class="font-semibold text-gray-900">{{ $category->name }}</h3>
|
||||||
<p class="text-gray-500 text-sm mt-1">{{ $category->children->count() }} subcategories</p>
|
<p class="text-gray-500 text-sm mt-1">{{ $category->children->count() }} subcategories</p>
|
||||||
|
|||||||
@ -1,33 +0,0 @@
|
|||||||
@extends('app::layouts.app')
|
|
||||||
@section('content')
|
|
||||||
<div class="container mx-auto px-4 py-8">
|
|
||||||
<div class="mb-6">
|
|
||||||
<h1 class="text-3xl font-bold">{{ $category->icon ?? '' }} {{ $category->name }}</h1>
|
|
||||||
@if($category->description)<p class="text-gray-600 mt-2">{{ $category->description }}</p>@endif
|
|
||||||
</div>
|
|
||||||
@if($category->children->count())
|
|
||||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8">
|
|
||||||
@foreach($category->children as $child)
|
|
||||||
<a href="{{ route('categories.show', $child) }}" class="bg-blue-50 rounded-lg p-4 text-center hover:bg-blue-100 transition">
|
|
||||||
<h3 class="font-medium text-blue-800">{{ $child->name }}</h3>
|
|
||||||
</a>
|
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
<h2 class="text-xl font-bold mb-4">Listings in {{ $category->name }}</h2>
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
||||||
@forelse($listings as $listing)
|
|
||||||
<div class="bg-white rounded-lg shadow-md overflow-hidden">
|
|
||||||
<div class="p-4">
|
|
||||||
<h3 class="font-semibold">{{ $listing->title }}</h3>
|
|
||||||
<p class="text-green-600 font-bold">{{ $listing->price ? number_format($listing->price, 0).' '.$listing->currency : 'Free' }}</p>
|
|
||||||
<a href="{{ route('listings.show', $listing) }}" class="mt-2 block text-blue-600 hover:underline">View →</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@empty
|
|
||||||
<p class="text-gray-500 col-span-3">No listings in this category yet.</p>
|
|
||||||
@endforelse
|
|
||||||
</div>
|
|
||||||
<div class="mt-6">{{ $listings->links() }}</div>
|
|
||||||
</div>
|
|
||||||
@endsection
|
|
||||||
@ -4,7 +4,7 @@
|
|||||||
<h1 class="text-3xl font-bold mb-6">{{ __('messages.categories') }}</h1>
|
<h1 class="text-3xl font-bold mb-6">{{ __('messages.categories') }}</h1>
|
||||||
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||||
@foreach($categories as $category)
|
@foreach($categories as $category)
|
||||||
<a href="{{ route('categories.show', $category) }}" class="bg-white rounded-lg shadow-md p-6 text-center hover:shadow-lg transition hover:bg-blue-50">
|
<a href="{{ route('listings.index', ['category' => $category->id]) }}" class="bg-white rounded-lg shadow-md p-6 text-center hover:shadow-lg transition hover:bg-blue-50">
|
||||||
<div class="text-4xl mb-3">{{ $category->icon ?? '📦' }}</div>
|
<div class="text-4xl mb-3">{{ $category->icon ?? '📦' }}</div>
|
||||||
<h3 class="font-semibold text-gray-900">{{ $category->name }}</h3>
|
<h3 class="font-semibold text-gray-900">{{ $category->name }}</h3>
|
||||||
<p class="text-gray-500 text-sm mt-1">{{ $category->children->count() }} subcategories</p>
|
<p class="text-gray-500 text-sm mt-1">{{ $category->children->count() }} subcategories</p>
|
||||||
|
|||||||
@ -1,33 +0,0 @@
|
|||||||
@extends('app::layouts.app')
|
|
||||||
@section('content')
|
|
||||||
<div class="container mx-auto px-4 py-8">
|
|
||||||
<div class="mb-6">
|
|
||||||
<h1 class="text-3xl font-bold">{{ $category->icon ?? '' }} {{ $category->name }}</h1>
|
|
||||||
@if($category->description)<p class="text-gray-600 mt-2">{{ $category->description }}</p>@endif
|
|
||||||
</div>
|
|
||||||
@if($category->children->count())
|
|
||||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8">
|
|
||||||
@foreach($category->children as $child)
|
|
||||||
<a href="{{ route('categories.show', $child) }}" class="bg-blue-50 rounded-lg p-4 text-center hover:bg-blue-100 transition">
|
|
||||||
<h3 class="font-medium text-blue-800">{{ $child->name }}</h3>
|
|
||||||
</a>
|
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
<h2 class="text-xl font-bold mb-4">Listings in {{ $category->name }}</h2>
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
||||||
@forelse($listings as $listing)
|
|
||||||
<div class="bg-white rounded-lg shadow-md overflow-hidden">
|
|
||||||
<div class="p-4">
|
|
||||||
<h3 class="font-semibold">{{ $listing->title }}</h3>
|
|
||||||
<p class="text-green-600 font-bold">{{ $listing->price ? number_format($listing->price, 0).' '.$listing->currency : 'Free' }}</p>
|
|
||||||
<a href="{{ route('listings.show', $listing) }}" class="mt-2 block text-blue-600 hover:underline">View →</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@empty
|
|
||||||
<p class="text-gray-500 col-span-3">No listings in this category yet.</p>
|
|
||||||
@endforelse
|
|
||||||
</div>
|
|
||||||
<div class="mt-6">{{ $listings->links() }}</div>
|
|
||||||
</div>
|
|
||||||
@endsection
|
|
||||||
@ -4,7 +4,7 @@
|
|||||||
<h1 class="text-3xl font-bold mb-6">{{ __('messages.categories') }}</h1>
|
<h1 class="text-3xl font-bold mb-6">{{ __('messages.categories') }}</h1>
|
||||||
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||||
@foreach($categories as $category)
|
@foreach($categories as $category)
|
||||||
<a href="{{ route('categories.show', $category) }}" class="bg-white rounded-lg shadow-md p-6 text-center hover:shadow-lg transition hover:bg-blue-50">
|
<a href="{{ route('listings.index', ['category' => $category->id]) }}" class="bg-white rounded-lg shadow-md p-6 text-center hover:shadow-lg transition hover:bg-blue-50">
|
||||||
<div class="text-4xl mb-3">{{ $category->icon ?? '📦' }}</div>
|
<div class="text-4xl mb-3">{{ $category->icon ?? '📦' }}</div>
|
||||||
<h3 class="font-semibold text-gray-900">{{ $category->name }}</h3>
|
<h3 class="font-semibold text-gray-900">{{ $category->name }}</h3>
|
||||||
<p class="text-gray-500 text-sm mt-1">{{ $category->children->count() }} subcategories</p>
|
<p class="text-gray-500 text-sm mt-1">{{ $category->children->count() }} subcategories</p>
|
||||||
|
|||||||
@ -1,33 +0,0 @@
|
|||||||
@extends('app::layouts.app')
|
|
||||||
@section('content')
|
|
||||||
<div class="container mx-auto px-4 py-8">
|
|
||||||
<div class="mb-6">
|
|
||||||
<h1 class="text-3xl font-bold">{{ $category->icon ?? '' }} {{ $category->name }}</h1>
|
|
||||||
@if($category->description)<p class="text-gray-600 mt-2">{{ $category->description }}</p>@endif
|
|
||||||
</div>
|
|
||||||
@if($category->children->count())
|
|
||||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8">
|
|
||||||
@foreach($category->children as $child)
|
|
||||||
<a href="{{ route('categories.show', $child) }}" class="bg-blue-50 rounded-lg p-4 text-center hover:bg-blue-100 transition">
|
|
||||||
<h3 class="font-medium text-blue-800">{{ $child->name }}</h3>
|
|
||||||
</a>
|
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
<h2 class="text-xl font-bold mb-4">Listings in {{ $category->name }}</h2>
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
||||||
@forelse($listings as $listing)
|
|
||||||
<div class="bg-white rounded-lg shadow-md overflow-hidden">
|
|
||||||
<div class="p-4">
|
|
||||||
<h3 class="font-semibold">{{ $listing->title }}</h3>
|
|
||||||
<p class="text-green-600 font-bold">{{ $listing->price ? number_format($listing->price, 0).' '.$listing->currency : 'Free' }}</p>
|
|
||||||
<a href="{{ route('listings.show', $listing) }}" class="mt-2 block text-blue-600 hover:underline">View →</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@empty
|
|
||||||
<p class="text-gray-500 col-span-3">No listings in this category yet.</p>
|
|
||||||
@endforelse
|
|
||||||
</div>
|
|
||||||
<div class="mt-6">{{ $listings->links() }}</div>
|
|
||||||
</div>
|
|
||||||
@endsection
|
|
||||||
@ -4,5 +4,4 @@ use Modules\Category\Http\Controllers\CategoryController;
|
|||||||
|
|
||||||
Route::prefix('categories')->name('categories.')->group(function () {
|
Route::prefix('categories')->name('categories.')->group(function () {
|
||||||
Route::get('/', [CategoryController::class, 'index'])->name('index');
|
Route::get('/', [CategoryController::class, 'index'])->name('index');
|
||||||
Route::get('/{category}', [CategoryController::class, 'show'])->name('show');
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -4,7 +4,7 @@ use Illuminate\Support\Facades\Route;
|
|||||||
use Modules\Conversation\App\Http\Controllers\ConversationController;
|
use Modules\Conversation\App\Http\Controllers\ConversationController;
|
||||||
|
|
||||||
Route::middleware('auth')->prefix('panel')->name('panel.')->group(function () {
|
Route::middleware('auth')->prefix('panel')->name('panel.')->group(function () {
|
||||||
Route::get('/gelen-kutusu', [ConversationController::class, 'inbox'])->name('inbox.index');
|
Route::get('/inbox', [ConversationController::class, 'inbox'])->name('inbox.index');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::middleware('auth')->name('conversations.')->group(function () {
|
Route::middleware('auth')->name('conversations.')->group(function () {
|
||||||
|
|||||||
@ -65,11 +65,13 @@ class ListingController extends Controller
|
|||||||
$selectedCityName
|
$selectedCityName
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$listingDirectory = Category::listingDirectory($categoryId);
|
||||||
|
|
||||||
$listingsQuery = Listing::query()
|
$listingsQuery = Listing::query()
|
||||||
->where('status', 'active')
|
->active()
|
||||||
->with('category:id,name')
|
->with('category:id,name')
|
||||||
->searchTerm($search)
|
->searchTerm($search)
|
||||||
->forCategory($categoryId)
|
->forCategoryIds($listingDirectory['filterIds'])
|
||||||
->when($selectedCountryName, fn ($query) => $query->where('country', $selectedCountryName))
|
->when($selectedCountryName, fn ($query) => $query->where('country', $selectedCountryName))
|
||||||
->when($selectedCityName, fn ($query) => $query->where('city', $selectedCityName))
|
->when($selectedCityName, fn ($query) => $query->where('city', $selectedCityName))
|
||||||
->when(! is_null($minPrice), fn ($query) => $query->whereNotNull('price')->where('price', '>=', $minPrice))
|
->when(! is_null($minPrice), fn ($query) => $query->whereNotNull('price')->where('price', '>=', $minPrice))
|
||||||
@ -82,28 +84,8 @@ class ListingController extends Controller
|
|||||||
->paginate(16)
|
->paginate(16)
|
||||||
->withQueryString();
|
->withQueryString();
|
||||||
|
|
||||||
$categories = Category::query()
|
$categories = $listingDirectory['categories'];
|
||||||
->where('is_active', true)
|
$selectedCategory = $listingDirectory['selectedCategory'];
|
||||||
->whereNull('parent_id')
|
|
||||||
->withCount([
|
|
||||||
'listings as active_listings_count' => fn ($query) => $query->where('status', 'active'),
|
|
||||||
])
|
|
||||||
->with([
|
|
||||||
'children' => fn ($query) => $query
|
|
||||||
->where('is_active', true)
|
|
||||||
->withCount([
|
|
||||||
'listings as active_listings_count' => fn ($childQuery) => $childQuery->where('status', 'active'),
|
|
||||||
])
|
|
||||||
->orderBy('sort_order')
|
|
||||||
->orderBy('name'),
|
|
||||||
])
|
|
||||||
->orderBy('sort_order')
|
|
||||||
->orderBy('name')
|
|
||||||
->get(['id', 'name', 'parent_id']);
|
|
||||||
|
|
||||||
$selectedCategory = $categoryId
|
|
||||||
? Category::query()->whereKey($categoryId)->first(['id', 'name'])
|
|
||||||
: null;
|
|
||||||
|
|
||||||
$favoriteListingIds = [];
|
$favoriteListingIds = [];
|
||||||
$isCurrentSearchSaved = false;
|
$isCurrentSearchSaved = false;
|
||||||
|
|||||||
@ -2,11 +2,12 @@
|
|||||||
namespace Modules\Listing\Models;
|
namespace Modules\Listing\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use Modules\Category\Models\Category;
|
||||||
use Modules\Listing\States\ListingStatus;
|
use Modules\Listing\States\ListingStatus;
|
||||||
use Modules\Listing\Support\ListingPanelHelper;
|
use Modules\Listing\Support\ListingPanelHelper;
|
||||||
use Spatie\Activitylog\LogOptions;
|
use Spatie\Activitylog\LogOptions;
|
||||||
@ -72,11 +73,16 @@ class Listing extends Model implements HasMedia
|
|||||||
public function scopePublicFeed(Builder $query): Builder
|
public function scopePublicFeed(Builder $query): Builder
|
||||||
{
|
{
|
||||||
return $query
|
return $query
|
||||||
->where('status', 'active')
|
->active()
|
||||||
->orderByDesc('is_featured')
|
->orderByDesc('is_featured')
|
||||||
->orderByDesc('created_at');
|
->orderByDesc('created_at');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function scopeActive(Builder $query): Builder
|
||||||
|
{
|
||||||
|
return $query->where('status', 'active');
|
||||||
|
}
|
||||||
|
|
||||||
public function scopeSearchTerm(Builder $query, string $search): Builder
|
public function scopeSearchTerm(Builder $query, string $search): Builder
|
||||||
{
|
{
|
||||||
$search = trim($search);
|
$search = trim($search);
|
||||||
@ -96,11 +102,20 @@ class Listing extends Model implements HasMedia
|
|||||||
|
|
||||||
public function scopeForCategory(Builder $query, ?int $categoryId): Builder
|
public function scopeForCategory(Builder $query, ?int $categoryId): Builder
|
||||||
{
|
{
|
||||||
if (! $categoryId) {
|
return $query->forCategoryIds(Category::listingFilterIds($categoryId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeForCategoryIds(Builder $query, ?array $categoryIds): Builder
|
||||||
|
{
|
||||||
|
if ($categoryIds === null) {
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $query->where('category_id', $categoryId);
|
if ($categoryIds === []) {
|
||||||
|
return $query->whereRaw('1 = 0');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query->whereIn('category_id', $categoryIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function themeGallery(): array
|
public function themeGallery(): array
|
||||||
|
|||||||
@ -43,8 +43,7 @@
|
|||||||
|
|
||||||
@foreach($categories as $category)
|
@foreach($categories as $category)
|
||||||
@php
|
@php
|
||||||
$childCount = (int) $category->children->sum('active_listings_count');
|
$categoryCount = (int) $category->active_listing_total;
|
||||||
$categoryCount = (int) $category->active_listings_count + $childCount;
|
|
||||||
$isSelectedParent = (int) $categoryId === (int) $category->id;
|
$isSelectedParent = (int) $categoryId === (int) $category->id;
|
||||||
$categoryUrl = route('listings.index', array_filter(array_merge($baseCategoryQuery, [
|
$categoryUrl = route('listings.index', array_filter(array_merge($baseCategoryQuery, [
|
||||||
'category' => $category->id,
|
'category' => $category->id,
|
||||||
@ -64,7 +63,7 @@
|
|||||||
@endphp
|
@endphp
|
||||||
<a href="{{ $childUrl }}" class="ml-2 flex items-center justify-between rounded-lg px-2 py-1.5 text-[13px] font-medium {{ $isSelectedChild ? 'bg-rose-50 text-rose-600' : 'text-slate-600 hover:bg-slate-100' }}">
|
<a href="{{ $childUrl }}" class="ml-2 flex items-center justify-between rounded-lg px-2 py-1.5 text-[13px] font-medium {{ $isSelectedChild ? 'bg-rose-50 text-rose-600' : 'text-slate-600 hover:bg-slate-100' }}">
|
||||||
<span>{{ $childCategory->name }}</span>
|
<span>{{ $childCategory->name }}</span>
|
||||||
<span>{{ number_format((int) $childCategory->active_listings_count, 0, ',', '.') }}</span>
|
<span>{{ number_format((int) $childCategory->active_listing_total, 0, ',', '.') }}</span>
|
||||||
</a>
|
</a>
|
||||||
@endforeach
|
@endforeach
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|||||||
@ -43,8 +43,7 @@
|
|||||||
|
|
||||||
@foreach($categories as $category)
|
@foreach($categories as $category)
|
||||||
@php
|
@php
|
||||||
$childCount = (int) $category->children->sum('active_listings_count');
|
$categoryCount = (int) $category->active_listing_total;
|
||||||
$categoryCount = (int) $category->active_listings_count + $childCount;
|
|
||||||
$isSelectedParent = (int) $categoryId === (int) $category->id;
|
$isSelectedParent = (int) $categoryId === (int) $category->id;
|
||||||
$categoryUrl = route('listings.index', array_filter(array_merge($baseCategoryQuery, [
|
$categoryUrl = route('listings.index', array_filter(array_merge($baseCategoryQuery, [
|
||||||
'category' => $category->id,
|
'category' => $category->id,
|
||||||
@ -64,7 +63,7 @@
|
|||||||
@endphp
|
@endphp
|
||||||
<a href="{{ $childUrl }}" class="ml-2 flex items-center justify-between rounded-lg px-2 py-1.5 text-[13px] font-medium {{ $isSelectedChild ? 'bg-rose-50 text-rose-600' : 'text-slate-600 hover:bg-slate-100' }}">
|
<a href="{{ $childUrl }}" class="ml-2 flex items-center justify-between rounded-lg px-2 py-1.5 text-[13px] font-medium {{ $isSelectedChild ? 'bg-rose-50 text-rose-600' : 'text-slate-600 hover:bg-slate-100' }}">
|
||||||
<span>{{ $childCategory->name }}</span>
|
<span>{{ $childCategory->name }}</span>
|
||||||
<span>{{ number_format((int) $childCategory->active_listings_count, 0, ',', '.') }}</span>
|
<span>{{ number_format((int) $childCategory->active_listing_total, 0, ',', '.') }}</span>
|
||||||
</a>
|
</a>
|
||||||
@endforeach
|
@endforeach
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|||||||
@ -43,8 +43,7 @@
|
|||||||
|
|
||||||
@foreach($categories as $category)
|
@foreach($categories as $category)
|
||||||
@php
|
@php
|
||||||
$childCount = (int) $category->children->sum('active_listings_count');
|
$categoryCount = (int) $category->active_listing_total;
|
||||||
$categoryCount = (int) $category->active_listings_count + $childCount;
|
|
||||||
$isSelectedParent = (int) $categoryId === (int) $category->id;
|
$isSelectedParent = (int) $categoryId === (int) $category->id;
|
||||||
$categoryUrl = route('listings.index', array_filter(array_merge($baseCategoryQuery, [
|
$categoryUrl = route('listings.index', array_filter(array_merge($baseCategoryQuery, [
|
||||||
'category' => $category->id,
|
'category' => $category->id,
|
||||||
@ -64,7 +63,7 @@
|
|||||||
@endphp
|
@endphp
|
||||||
<a href="{{ $childUrl }}" class="ml-2 flex items-center justify-between rounded-lg px-2 py-1.5 text-[13px] font-medium {{ $isSelectedChild ? 'bg-rose-50 text-rose-600' : 'text-slate-600 hover:bg-slate-100' }}">
|
<a href="{{ $childUrl }}" class="ml-2 flex items-center justify-between rounded-lg px-2 py-1.5 text-[13px] font-medium {{ $isSelectedChild ? 'bg-rose-50 text-rose-600' : 'text-slate-600 hover:bg-slate-100' }}">
|
||||||
<span>{{ $childCategory->name }}</span>
|
<span>{{ $childCategory->name }}</span>
|
||||||
<span>{{ number_format((int) $childCategory->active_listings_count, 0, ',', '.') }}</span>
|
<span>{{ number_format((int) $childCategory->active_listing_total, 0, ',', '.') }}</span>
|
||||||
</a>
|
</a>
|
||||||
@endforeach
|
@endforeach
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|||||||
@ -33,7 +33,7 @@
|
|||||||
<a href="{{ route('home') }}">Anasayfa</a>
|
<a href="{{ route('home') }}">Anasayfa</a>
|
||||||
@foreach(($breadcrumbCategories ?? collect()) as $crumb)
|
@foreach(($breadcrumbCategories ?? collect()) as $crumb)
|
||||||
<span>›</span>
|
<span>›</span>
|
||||||
<a href="{{ route('categories.show', $crumb) }}">{{ $crumb->name }}</a>
|
<a href="{{ route('listings.index', ['category' => $crumb->id]) }}">{{ $crumb->name }}</a>
|
||||||
@endforeach
|
@endforeach
|
||||||
<span>›</span>
|
<span>›</span>
|
||||||
<span>{{ $displayTitle }}</span>
|
<span>{{ $displayTitle }}</span>
|
||||||
|
|||||||
@ -174,7 +174,7 @@ class ListingResource extends Resource
|
|||||||
StateFusionSelectColumn::make('status'),
|
StateFusionSelectColumn::make('status'),
|
||||||
TextColumn::make('city'),
|
TextColumn::make('city'),
|
||||||
TextColumn::make('created_at')->dateTime()->sortable(),
|
TextColumn::make('created_at')->dateTime()->sortable(),
|
||||||
])->filters([
|
])->defaultSort('id', 'desc')->filters([
|
||||||
StateFusionSelectFilter::make('status'),
|
StateFusionSelectFilter::make('status'),
|
||||||
SelectFilter::make('category_id')
|
SelectFilter::make('category_id')
|
||||||
->label('Category')
|
->label('Category')
|
||||||
|
|||||||
@ -188,13 +188,13 @@ class PanelQuickListingForm extends Component
|
|||||||
} catch (Throwable $exception) {
|
} catch (Throwable $exception) {
|
||||||
report($exception);
|
report($exception);
|
||||||
$this->isPublishing = false;
|
$this->isPublishing = false;
|
||||||
session()->flash('error', 'İlan oluşturulamadı. Lütfen tekrar deneyin.');
|
session()->flash('error', 'The listing could not be created. Please try again.');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->isPublishing = false;
|
$this->isPublishing = false;
|
||||||
session()->flash('success', 'İlan başarıyla oluşturuldu.');
|
session()->flash('success', 'Your listing has been created successfully.');
|
||||||
|
|
||||||
$this->redirectRoute('panel.listings.index');
|
$this->redirectRoute('panel.listings.index');
|
||||||
}
|
}
|
||||||
@ -243,23 +243,23 @@ class PanelQuickListingForm extends Component
|
|||||||
public function getCurrentParentNameProperty(): string
|
public function getCurrentParentNameProperty(): string
|
||||||
{
|
{
|
||||||
if (! $this->activeParentCategoryId) {
|
if (! $this->activeParentCategoryId) {
|
||||||
return 'Kategori Seçimi';
|
return 'Category Selection';
|
||||||
}
|
}
|
||||||
|
|
||||||
$category = collect($this->categories)->firstWhere('id', $this->activeParentCategoryId);
|
$category = collect($this->categories)->firstWhere('id', $this->activeParentCategoryId);
|
||||||
|
|
||||||
return (string) ($category['name'] ?? 'Kategori Seçimi');
|
return (string) ($category['name'] ?? 'Category Selection');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCurrentStepTitleProperty(): string
|
public function getCurrentStepTitleProperty(): string
|
||||||
{
|
{
|
||||||
return match ($this->currentStep) {
|
return match ($this->currentStep) {
|
||||||
1 => 'Fotoğraf',
|
1 => 'Photos',
|
||||||
2 => 'Kategori Seçimi',
|
2 => 'Category Selection',
|
||||||
3 => 'İlan Bilgileri',
|
3 => 'Listing Details',
|
||||||
4 => 'İlan Özellikleri',
|
4 => 'Attributes',
|
||||||
5 => 'İlan Önizlemesi',
|
5 => 'Preview',
|
||||||
default => 'İlan Ver',
|
default => 'Create Listing',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,7 +352,7 @@ class PanelQuickListingForm extends Component
|
|||||||
|
|
||||||
public function getCurrentUserNameProperty(): string
|
public function getCurrentUserNameProperty(): string
|
||||||
{
|
{
|
||||||
return (string) (auth()->user()?->name ?: 'Kullanıcı');
|
return (string) (auth()->user()?->name ?: 'User');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCurrentUserInitialProperty(): string
|
public function getCurrentUserInitialProperty(): string
|
||||||
@ -402,8 +402,8 @@ class PanelQuickListingForm extends Component
|
|||||||
Rule::in(collect($this->categories)->pluck('id')->all()),
|
Rule::in(collect($this->categories)->pluck('id')->all()),
|
||||||
],
|
],
|
||||||
], [
|
], [
|
||||||
'selectedCategoryId.required' => 'Lütfen bir kategori seçin.',
|
'selectedCategoryId.required' => 'Please choose a category.',
|
||||||
'selectedCategoryId.in' => 'Geçerli bir kategori seçin.',
|
'selectedCategoryId.in' => 'Please choose a valid category.',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -426,18 +426,18 @@ class PanelQuickListingForm extends Component
|
|||||||
->contains(fn (array $city): bool => $city['id'] === (int) $value);
|
->contains(fn (array $city): bool => $city['id'] === (int) $value);
|
||||||
|
|
||||||
if (! $cityExists) {
|
if (! $cityExists) {
|
||||||
$fail('Seçtiğiniz şehir, seçilen ülkeye ait değil.');
|
$fail('The selected city does not belong to the chosen country.');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
], [
|
], [
|
||||||
'listingTitle.required' => 'İlan başlığı zorunludur.',
|
'listingTitle.required' => 'A title is required.',
|
||||||
'listingTitle.max' => 'İlan başlığı en fazla 70 karakter olabilir.',
|
'listingTitle.max' => 'The title may not exceed 70 characters.',
|
||||||
'price.required' => 'Fiyat zorunludur.',
|
'price.required' => 'A price is required.',
|
||||||
'price.numeric' => 'Fiyat sayısal olmalıdır.',
|
'price.numeric' => 'The price must be numeric.',
|
||||||
'description.required' => 'Açıklama zorunludur.',
|
'description.required' => 'A description is required.',
|
||||||
'description.max' => 'Açıklama en fazla 1450 karakter olabilir.',
|
'description.max' => 'The description may not exceed 1450 characters.',
|
||||||
'selectedCountryId.required' => 'Ülke seçimi zorunludur.',
|
'selectedCountryId.required' => 'Please choose a country.',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -188,7 +188,7 @@
|
|||||||
$trendSkin = $trendSkins[$index % count($trendSkins)];
|
$trendSkin = $trendSkins[$index % count($trendSkins)];
|
||||||
$trendIcon = $trendIcons[$index % count($trendIcons)];
|
$trendIcon = $trendIcons[$index % count($trendIcons)];
|
||||||
@endphp
|
@endphp
|
||||||
<a href="{{ route('categories.show', $category) }}" class="group shrink-0 w-[170px] rounded-xl overflow-hidden border border-slate-300/80 bg-white hover:shadow-md transition snap-start">
|
<a href="{{ route('listings.index', ['category' => $category->id]) }}" class="group shrink-0 w-[170px] rounded-xl overflow-hidden border border-slate-300/80 bg-white hover:shadow-md transition snap-start">
|
||||||
<div class="h-[68px] bg-gradient-to-r {{ $trendSkin['gradient'] }} relative overflow-hidden">
|
<div class="h-[68px] bg-gradient-to-r {{ $trendSkin['gradient'] }} relative overflow-hidden">
|
||||||
<span class="absolute -left-5 top-2 w-20 h-20 rounded-full {{ $trendSkin['glow'] }} blur-2xl"></span>
|
<span class="absolute -left-5 top-2 w-20 h-20 rounded-full {{ $trendSkin['glow'] }} blur-2xl"></span>
|
||||||
<span class="absolute left-5 bottom-2 h-2.5 w-24 rounded-full bg-black/20"></span>
|
<span class="absolute left-5 bottom-2 h-2.5 w-24 rounded-full bg-black/20"></span>
|
||||||
|
|||||||
@ -79,21 +79,21 @@
|
|||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M12 21s7-6.2 7-11a7 7 0 10-14 0c0 4.8 7 11 7 11z"/>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M12 21s7-6.2 7-11a7 7 0 10-14 0c0 4.8 7 11 7 11z"/>
|
||||||
<circle cx="12" cy="10" r="2.3" stroke-width="1.8" />
|
<circle cx="12" cy="10" r="2.3" stroke-width="1.8" />
|
||||||
</svg>
|
</svg>
|
||||||
<span data-location-label class="max-w-44 truncate">Konum seç</span>
|
<span data-location-label class="max-w-44 truncate">Choose location</span>
|
||||||
<svg class="w-4 h-4 text-slate-500 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-4 h-4 text-slate-500 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M6 9l6 6 6-6"/>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M6 9l6 6 6-6"/>
|
||||||
</svg>
|
</svg>
|
||||||
</summary>
|
</summary>
|
||||||
<div class="location-panel absolute right-0 mt-2 bg-white border border-slate-200 shadow-xl rounded-2xl p-4 space-y-3">
|
<div class="location-panel absolute right-0 mt-2 bg-white border border-slate-200 shadow-xl rounded-2xl p-4 space-y-3">
|
||||||
<div class="flex items-center justify-between gap-3">
|
<div class="flex items-center justify-between gap-3">
|
||||||
<p class="text-sm font-semibold text-slate-900">Konum Tercihi</p>
|
<p class="text-sm font-semibold text-slate-900">Location</p>
|
||||||
<button type="button" data-location-detect class="text-xs font-semibold text-rose-500 hover:text-rose-600 transition">Konumumu Bul</button>
|
<button type="button" data-location-detect class="text-xs font-semibold text-rose-500 hover:text-rose-600 transition">Use my location</button>
|
||||||
</div>
|
</div>
|
||||||
<p data-location-status class="text-xs text-slate-500">Tarayıcı konumuna göre ülke ve şehir otomatik seçilebilir.</p>
|
<p data-location-status class="text-xs text-slate-500">Auto-select country and city from your browser location.</p>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<label class="block text-xs font-semibold text-slate-600">Ülke</label>
|
<label class="block text-xs font-semibold text-slate-600">Country</label>
|
||||||
<select data-location-country class="w-full">
|
<select data-location-country class="w-full">
|
||||||
<option value="">Ülke seç</option>
|
<option value="">Select country</option>
|
||||||
@foreach($locationCountries as $country)
|
@foreach($locationCountries as $country)
|
||||||
<option
|
<option
|
||||||
value="{{ $country['id'] }}"
|
value="{{ $country['id'] }}"
|
||||||
@ -107,35 +107,35 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<label class="block text-xs font-semibold text-slate-600">Şehir</label>
|
<label class="block text-xs font-semibold text-slate-600">City</label>
|
||||||
<select data-location-city class="w-full" disabled>
|
<select data-location-city class="w-full" disabled>
|
||||||
<option value="">Önce ülke seç</option>
|
<option value="">Select country first</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" data-location-save class="w-full btn-primary px-4 py-2.5 text-sm font-semibold hover:brightness-95 transition">Uygula</button>
|
<button type="button" data-location-save class="w-full btn-primary px-4 py-2.5 text-sm font-semibold hover:brightness-95 transition">Apply</button>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<div class="ml-auto flex items-center gap-2 md:gap-3">
|
<div class="ml-auto flex items-center gap-2 md:gap-3">
|
||||||
@auth
|
@auth
|
||||||
<a href="{{ $favoritesRoute }}" class="header-utility hidden xl:inline-flex" aria-label="Favoriler">
|
<a href="{{ $favoritesRoute }}" class="header-utility hidden xl:inline-flex" aria-label="Favorites">
|
||||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M12 21l-1.45-1.32C5.4 15.03 2 12.01 2 8.31 2 5.3 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.08A6.04 6.04 0 0116.5 3C19.58 3 22 5.3 22 8.31c0 3.7-3.4 6.72-8.55 11.39L12 21z"/>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M12 21l-1.45-1.32C5.4 15.03 2 12.01 2 8.31 2 5.3 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.08A6.04 6.04 0 0116.5 3C19.58 3 22 5.3 22 8.31c0 3.7-3.4 6.72-8.55 11.39L12 21z"/>
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ $inboxRoute }}" class="header-utility hidden xl:inline-flex" aria-label="Gelen Kutusu">
|
<a href="{{ $inboxRoute }}" class="header-utility hidden xl:inline-flex" aria-label="Inbox">
|
||||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M4 6h16a1 1 0 011 1v10a1 1 0 01-1 1H4a1 1 0 01-1-1V7a1 1 0 011-1z"/>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M4 6h16a1 1 0 011 1v10a1 1 0 01-1 1H4a1 1 0 01-1-1V7a1 1 0 011-1z"/>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M3 8l9 6 9-6"/>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M3 8l9 6 9-6"/>
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ $panelListingsRoute }}" class="header-utility hidden xl:inline-flex" aria-label="Panel">
|
<a href="{{ $panelListingsRoute }}" class="header-utility hidden xl:inline-flex" aria-label="Dashboard">
|
||||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M3 12l9-9 9 9M5 10v10h14V10"/>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M3 12l9-9 9 9M5 10v10h14V10"/>
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ $panelCreateRoute }}" class="btn-primary px-4 md:px-5 py-2.5 text-sm font-semibold shadow-sm hover:brightness-95 transition">
|
<a href="{{ $panelCreateRoute }}" class="btn-primary px-4 md:px-5 py-2.5 text-sm font-semibold shadow-sm hover:brightness-95 transition">
|
||||||
İlan Ver
|
Sell
|
||||||
</a>
|
</a>
|
||||||
<form method="POST" action="{{ $logoutRoute }}" class="hidden xl:block">
|
<form method="POST" action="{{ $logoutRoute }}" class="hidden xl:block">
|
||||||
@csrf
|
@csrf
|
||||||
@ -146,7 +146,7 @@
|
|||||||
{{ __('messages.login') }}
|
{{ __('messages.login') }}
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ $panelCreateRoute }}" class="btn-primary px-4 md:px-5 py-2.5 text-sm font-semibold shadow-sm hover:brightness-95 transition">
|
<a href="{{ $panelCreateRoute }}" class="btn-primary px-4 md:px-5 py-2.5 text-sm font-semibold shadow-sm hover:brightness-95 transition">
|
||||||
İlan Ver
|
Sell
|
||||||
</a>
|
</a>
|
||||||
@endauth
|
@endauth
|
||||||
</div>
|
</div>
|
||||||
@ -167,8 +167,8 @@
|
|||||||
<button type="submit" class="text-xs text-slate-500">{{ __('messages.search') }}</button>
|
<button type="submit" class="text-xs text-slate-500">{{ __('messages.search') }}</button>
|
||||||
</form>
|
</form>
|
||||||
<div class="flex items-center gap-2 overflow-x-auto pb-1">
|
<div class="flex items-center gap-2 overflow-x-auto pb-1">
|
||||||
<span class="chip-btn whitespace-nowrap px-4 py-2 text-sm text-slate-700" data-location-label-mobile>Konum seç</span>
|
<span class="chip-btn whitespace-nowrap px-4 py-2 text-sm text-slate-700" data-location-label-mobile>Choose location</span>
|
||||||
<a href="{{ $panelCreateRoute }}" class="chip-btn whitespace-nowrap px-4 py-2 text-sm text-rose-600 font-semibold">İlan Ver</a>
|
<a href="{{ $panelCreateRoute }}" class="chip-btn whitespace-nowrap px-4 py-2 text-sm text-rose-600 font-semibold">Sell</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -178,10 +178,10 @@
|
|||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M4 6h16M4 12h16M4 18h16"/>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M4 6h16M4 12h16M4 18h16"/>
|
||||||
</svg>
|
</svg>
|
||||||
Tüm Kategoriler
|
All Categories
|
||||||
</a>
|
</a>
|
||||||
@forelse($headerCategories as $headerCategory)
|
@forelse($headerCategories as $headerCategory)
|
||||||
<a href="{{ route('categories.show', ['category' => $headerCategory['id']]) }}" class="px-4 py-2.5 rounded-full text-sm font-medium text-slate-700 hover:bg-slate-100 transition whitespace-nowrap">
|
<a href="{{ route('listings.index', ['category' => $headerCategory['id']]) }}" class="px-4 py-2.5 rounded-full text-sm font-medium text-slate-700 hover:bg-slate-100 transition whitespace-nowrap">
|
||||||
{{ $headerCategory['name'] }}
|
{{ $headerCategory['name'] }}
|
||||||
</a>
|
</a>
|
||||||
@empty
|
@empty
|
||||||
@ -211,22 +211,22 @@
|
|||||||
<p class="text-sm text-slate-500 leading-relaxed">{{ $siteDescription }}</p>
|
<p class="text-sm text-slate-500 leading-relaxed">{{ $siteDescription }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h4 class="text-slate-900 font-medium mb-4">Hızlı Linkler</h4>
|
<h4 class="text-slate-900 font-medium mb-4">Quick Links</h4>
|
||||||
<ul class="space-y-2 text-sm">
|
<ul class="space-y-2 text-sm">
|
||||||
<li><a href="{{ route('home') }}" class="hover:text-slate-900 transition">Ana Sayfa</a></li>
|
<li><a href="{{ route('home') }}" class="hover:text-slate-900 transition">Home</a></li>
|
||||||
<li><a href="{{ route('categories.index') }}" class="hover:text-slate-900 transition">Kategoriler</a></li>
|
<li><a href="{{ route('categories.index') }}" class="hover:text-slate-900 transition">Categories</a></li>
|
||||||
<li><a href="{{ route('listings.index') }}" class="hover:text-slate-900 transition">Tüm İlanlar</a></li>
|
<li><a href="{{ route('listings.index') }}" class="hover:text-slate-900 transition">All Listings</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h4 class="text-slate-900 font-medium mb-4">Hesap</h4>
|
<h4 class="text-slate-900 font-medium mb-4">Account</h4>
|
||||||
<ul class="space-y-2 text-sm">
|
<ul class="space-y-2 text-sm">
|
||||||
<li><a href="{{ $loginRoute }}" class="hover:text-slate-900 transition">{{ __('messages.login') }}</a></li>
|
<li><a href="{{ $loginRoute }}" class="hover:text-slate-900 transition">{{ __('messages.login') }}</a></li>
|
||||||
<li><a href="{{ $registerRoute }}" class="hover:text-slate-900 transition">{{ __('messages.register') }}</a></li>
|
<li><a href="{{ $registerRoute }}" class="hover:text-slate-900 transition">{{ __('messages.register') }}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h4 class="text-slate-900 font-medium mb-4">Bağlantılar</h4>
|
<h4 class="text-slate-900 font-medium mb-4">Links</h4>
|
||||||
<ul class="space-y-2 text-sm mb-4">
|
<ul class="space-y-2 text-sm mb-4">
|
||||||
@if($linkedinUrl)
|
@if($linkedinUrl)
|
||||||
<li><a href="{{ $linkedinUrl }}" target="_blank" rel="noopener" class="hover:text-slate-900 transition">LinkedIn</a></li>
|
<li><a href="{{ $linkedinUrl }}" target="_blank" rel="noopener" class="hover:text-slate-900 transition">LinkedIn</a></li>
|
||||||
@ -238,10 +238,10 @@
|
|||||||
<li><a href="{{ $whatsappUrl }}" target="_blank" rel="noopener" class="hover:text-slate-900 transition">WhatsApp</a></li>
|
<li><a href="{{ $whatsappUrl }}" target="_blank" rel="noopener" class="hover:text-slate-900 transition">WhatsApp</a></li>
|
||||||
@endif
|
@endif
|
||||||
@if(!$linkedinUrl && !$instagramUrl && !$whatsappUrl)
|
@if(!$linkedinUrl && !$instagramUrl && !$whatsappUrl)
|
||||||
<li>Henüz sosyal bağlantı eklenmedi.</li>
|
<li>No social links added yet.</li>
|
||||||
@endif
|
@endif
|
||||||
</ul>
|
</ul>
|
||||||
<h4 class="text-slate-900 font-medium mb-3">Diller</h4>
|
<h4 class="text-slate-900 font-medium mb-3">Languages</h4>
|
||||||
<div class="flex flex-wrap gap-2">
|
<div class="flex flex-wrap gap-2">
|
||||||
@foreach($availableLocales as $locale)
|
@foreach($availableLocales as $locale)
|
||||||
<a href="{{ route('lang.switch', $locale) }}" class="text-xs {{ app()->getLocale() === $locale ? 'text-slate-900' : 'hover:text-slate-900' }} transition">{{ strtoupper($locale) }}</a>
|
<a href="{{ route('lang.switch', $locale) }}" class="text-xs {{ app()->getLocale() === $locale ? 'text-slate-900' : 'hover:text-slate-900' }} transition">{{ strtoupper($locale) }}</a>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
@extends('app::layouts.app')
|
@extends('app::layouts.app')
|
||||||
|
|
||||||
@section('title', 'İlan Ver')
|
@section('title', 'Create Listing')
|
||||||
|
|
||||||
@section('simple_page', '1')
|
@section('simple_page', '1')
|
||||||
|
|
||||||
|
|||||||
@ -5,24 +5,24 @@
|
|||||||
|
|
||||||
<aside class="bg-white border border-slate-200 rounded-xl overflow-hidden">
|
<aside class="bg-white border border-slate-200 rounded-xl overflow-hidden">
|
||||||
<a href="{{ route('panel.listings.create') }}" class="block px-5 py-4 text-base {{ $activeMenu === 'create' ? 'bg-rose-50 text-rose-600 font-semibold' : 'text-slate-700 hover:bg-slate-50' }}">
|
<a href="{{ route('panel.listings.create') }}" class="block px-5 py-4 text-base {{ $activeMenu === 'create' ? 'bg-rose-50 text-rose-600 font-semibold' : 'text-slate-700 hover:bg-slate-50' }}">
|
||||||
İlan Ver
|
Sell
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ route('panel.listings.index') }}" class="block px-5 py-4 border-t border-slate-200 text-base {{ $activeMenu === 'listings' ? 'bg-rose-50 text-rose-600 font-semibold' : 'text-slate-700 hover:bg-slate-50' }}">
|
<a href="{{ route('panel.listings.index') }}" class="block px-5 py-4 border-t border-slate-200 text-base {{ $activeMenu === 'listings' ? 'bg-rose-50 text-rose-600 font-semibold' : 'text-slate-700 hover:bg-slate-50' }}">
|
||||||
İlanlarım
|
My Listings
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ route('favorites.index', ['tab' => 'listings']) }}" class="block px-5 py-4 border-t border-slate-200 text-base {{ $activeMenu === 'favorites' ? 'bg-rose-50 text-rose-600 font-semibold' : 'text-slate-700 hover:bg-slate-50' }}">
|
<a href="{{ route('favorites.index', ['tab' => 'listings']) }}" class="block px-5 py-4 border-t border-slate-200 text-base {{ $activeMenu === 'favorites' ? 'bg-rose-50 text-rose-600 font-semibold' : 'text-slate-700 hover:bg-slate-50' }}">
|
||||||
Favorilerim
|
Favorites
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ route('favorites.index', ['tab' => 'listings']) }}" class="block px-9 py-3 border-t border-slate-100 text-sm {{ $activeFavoritesTab === 'listings' ? 'bg-rose-50 text-rose-600 font-semibold' : 'text-slate-600 hover:bg-slate-50' }}">
|
<a href="{{ route('favorites.index', ['tab' => 'listings']) }}" class="block px-9 py-3 border-t border-slate-100 text-sm {{ $activeFavoritesTab === 'listings' ? 'bg-rose-50 text-rose-600 font-semibold' : 'text-slate-600 hover:bg-slate-50' }}">
|
||||||
Favori İlanlar
|
Saved Listings
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ route('favorites.index', ['tab' => 'searches']) }}" class="block px-9 py-3 border-t border-slate-100 text-sm {{ $activeFavoritesTab === 'searches' ? 'bg-rose-50 text-rose-600 font-semibold' : 'text-slate-600 hover:bg-slate-50' }}">
|
<a href="{{ route('favorites.index', ['tab' => 'searches']) }}" class="block px-9 py-3 border-t border-slate-100 text-sm {{ $activeFavoritesTab === 'searches' ? 'bg-rose-50 text-rose-600 font-semibold' : 'text-slate-600 hover:bg-slate-50' }}">
|
||||||
Favori Aramalar
|
Saved Searches
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ route('favorites.index', ['tab' => 'sellers']) }}" class="block px-9 py-3 border-t border-slate-100 text-sm {{ $activeFavoritesTab === 'sellers' ? 'bg-rose-50 text-rose-600 font-semibold' : 'text-slate-600 hover:bg-slate-50' }}">
|
<a href="{{ route('favorites.index', ['tab' => 'sellers']) }}" class="block px-9 py-3 border-t border-slate-100 text-sm {{ $activeFavoritesTab === 'sellers' ? 'bg-rose-50 text-rose-600 font-semibold' : 'text-slate-600 hover:bg-slate-50' }}">
|
||||||
Favori Satıcılar
|
Saved Sellers
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ route('panel.inbox.index') }}" class="block px-5 py-4 border-t border-slate-200 text-base {{ $activeMenu === 'inbox' ? 'bg-rose-50 text-rose-600 font-semibold' : 'text-slate-700 hover:bg-slate-50' }}">
|
<a href="{{ route('panel.inbox.index') }}" class="block px-5 py-4 border-t border-slate-200 text-base {{ $activeMenu === 'inbox' ? 'bg-rose-50 text-rose-600 font-semibold' : 'text-slate-700 hover:bg-slate-50' }}">
|
||||||
Gelen Kutusu
|
Inbox
|
||||||
</a>
|
</a>
|
||||||
</aside>
|
</aside>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<div class="max-w-[1320px] mx-auto px-4 py-8">
|
<div class="max-w-[1320px] mx-auto px-4 py-5 sm:py-8">
|
||||||
<style>
|
<style>
|
||||||
.qc-shell {
|
.qc-shell {
|
||||||
--qc-card: #ffffff;
|
--qc-card: #ffffff;
|
||||||
@ -853,32 +853,404 @@
|
|||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qc-shell {
|
||||||
|
--qc-card: #ffffff;
|
||||||
|
--qc-border: #dbe3ee;
|
||||||
|
--qc-text: #0f172a;
|
||||||
|
--qc-muted: #64748b;
|
||||||
|
--qc-primary: #111827;
|
||||||
|
--qc-primary-soft: #f3f4f6;
|
||||||
|
--qc-warn: #f8fafc;
|
||||||
|
color: var(--qc-text);
|
||||||
|
font-family: "SF Pro Text", "SF Pro Display", "Helvetica Neue", Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-hero {
|
||||||
|
display: grid;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-hero-copy {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-eyebrow {
|
||||||
|
display: inline-flex;
|
||||||
|
width: fit-content;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #f1f5f9;
|
||||||
|
color: #475569;
|
||||||
|
font-size: .72rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: .08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: .42rem .7rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-title {
|
||||||
|
margin-top: .5rem;
|
||||||
|
font-size: 1.9rem;
|
||||||
|
line-height: 1.05;
|
||||||
|
letter-spacing: -0.04em;
|
||||||
|
font-weight: 700;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-subtitle {
|
||||||
|
margin-top: .45rem;
|
||||||
|
color: var(--qc-muted);
|
||||||
|
font-size: .95rem;
|
||||||
|
line-height: 1.55;
|
||||||
|
max-width: 56rem;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-head {
|
||||||
|
display: grid;
|
||||||
|
gap: .55rem;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
min-width: 0;
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-progress-wrap {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: .9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-progress {
|
||||||
|
width: 100%;
|
||||||
|
gap: .45rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-progress > span {
|
||||||
|
height: .3rem;
|
||||||
|
background: #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-progress > span.is-on {
|
||||||
|
background: var(--qc-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-step-label {
|
||||||
|
font-size: .92rem;
|
||||||
|
color: #334155;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-stage {
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-card {
|
||||||
|
border: 1px solid var(--qc-border);
|
||||||
|
border-radius: 1rem;
|
||||||
|
background: var(--qc-card);
|
||||||
|
box-shadow: 0 12px 32px rgba(15, 23, 42, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-body {
|
||||||
|
min-height: 0;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-body > * {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-footer {
|
||||||
|
padding: 1rem;
|
||||||
|
justify-content: stretch;
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
align-items: stretch;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-btn,
|
||||||
|
.qc-publish,
|
||||||
|
.qc-muted-btn,
|
||||||
|
.qc-upload-btn {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 3rem;
|
||||||
|
padding: .82rem 1rem;
|
||||||
|
font-size: .95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-btn-primary,
|
||||||
|
.qc-publish,
|
||||||
|
.qc-upload-btn {
|
||||||
|
background: #111827;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-btn-primary:hover,
|
||||||
|
.qc-publish:hover,
|
||||||
|
.qc-upload-btn:hover {
|
||||||
|
transform: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-btn-secondary,
|
||||||
|
.qc-muted-btn {
|
||||||
|
background: #f8fafc;
|
||||||
|
color: #0f172a;
|
||||||
|
border: 1px solid var(--qc-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-upload-zone,
|
||||||
|
.qc-warning,
|
||||||
|
.qc-summary,
|
||||||
|
.qc-info-box,
|
||||||
|
.qc-preview-panel,
|
||||||
|
.qc-seller-card,
|
||||||
|
.qc-strip {
|
||||||
|
border-radius: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-upload-zone {
|
||||||
|
min-height: 220px;
|
||||||
|
padding: 1.25rem 1rem;
|
||||||
|
background: #f8fafc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-upload-zone > * {
|
||||||
|
max-width: 760px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-upload-title,
|
||||||
|
.qc-ai-note h3 {
|
||||||
|
font-size: 1.35rem;
|
||||||
|
letter-spacing: -0.03em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-photo-grid {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-root-grid {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-root-item {
|
||||||
|
border: 1px solid var(--qc-border);
|
||||||
|
border-radius: .9rem;
|
||||||
|
padding: .85rem .6rem;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-root-item.is-selected {
|
||||||
|
background: #f8fafc;
|
||||||
|
border-color: #94a3b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-root-icon {
|
||||||
|
background: #f8fafc;
|
||||||
|
color: #111827;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-search input,
|
||||||
|
.qc-input,
|
||||||
|
.qc-select,
|
||||||
|
.qc-textarea {
|
||||||
|
background: #fff;
|
||||||
|
border-color: var(--qc-border);
|
||||||
|
border-radius: .85rem;
|
||||||
|
padding: .85rem .95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-summary {
|
||||||
|
border-top: 0;
|
||||||
|
margin-top: 1rem;
|
||||||
|
padding-top: 0;
|
||||||
|
border: 1px solid var(--qc-border);
|
||||||
|
background: #f8fafc;
|
||||||
|
padding: 1rem;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: .6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-strip {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
background: #f8fafc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-dynamic-grid,
|
||||||
|
.qc-two-col,
|
||||||
|
.qc-preview-grid,
|
||||||
|
.qc-seller-actions {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-preview-grid {
|
||||||
|
display: grid;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-preview-panel,
|
||||||
|
.qc-seller-card {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-warning {
|
||||||
|
background: #f8fafc;
|
||||||
|
border-bottom: 1px solid var(--qc-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-chip,
|
||||||
|
.qc-pill {
|
||||||
|
border-color: var(--qc-border);
|
||||||
|
background: #fff;
|
||||||
|
color: #111827;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-avatar {
|
||||||
|
background: #f3f4f6;
|
||||||
|
color: #111827;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-gallery {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-gallery-item {
|
||||||
|
min-height: 220px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-feature-row {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: .2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-publish-wrap {
|
||||||
|
display: grid;
|
||||||
|
gap: .6rem;
|
||||||
|
margin-top: .9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.qc-title {
|
||||||
|
font-size: 2.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-body,
|
||||||
|
.qc-footer {
|
||||||
|
padding: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-photo-grid,
|
||||||
|
.qc-strip {
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-gallery {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.qc-hero {
|
||||||
|
grid-template-columns: minmax(0, 1fr) 220px;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-head {
|
||||||
|
justify-items: end;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-footer {
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-btn,
|
||||||
|
.qc-publish,
|
||||||
|
.qc-muted-btn {
|
||||||
|
width: auto;
|
||||||
|
min-width: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-root-grid {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-dynamic-grid,
|
||||||
|
.qc-two-col {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-preview-grid {
|
||||||
|
grid-template-columns: minmax(0, 1fr) 280px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-gallery {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-gallery-item {
|
||||||
|
min-height: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-seller-actions {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.qc-body {
|
||||||
|
padding: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qc-preview-grid {
|
||||||
|
grid-template-columns: minmax(0, 1fr) 320px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="qc-shell">
|
<div class="qc-shell">
|
||||||
<div class="qc-head">
|
<div class="qc-hero">
|
||||||
<h1 class="qc-title">{{ $this->currentStepTitle }}</h1>
|
<div class="qc-hero-copy">
|
||||||
<div class="qc-progress-wrap">
|
<span class="qc-eyebrow">Create listing</span>
|
||||||
<div class="qc-progress" aria-hidden="true">
|
<h1 class="qc-title">{{ $this->currentStepTitle }}</h1>
|
||||||
@for ($step = 1; $step <= 5; $step++)
|
<p class="qc-subtitle">A clean, simple flow to publish faster.</p>
|
||||||
<span @class(['is-on' => $step <= $currentStep])></span>
|
</div>
|
||||||
@endfor
|
<div class="qc-head">
|
||||||
|
<div class="qc-step-label">Step {{ $currentStep }} of 5</div>
|
||||||
|
<div class="qc-progress-wrap">
|
||||||
|
<div class="qc-progress" aria-hidden="true">
|
||||||
|
@for ($step = 1; $step <= 5; $step++)
|
||||||
|
<span @class(['is-on' => $step <= $currentStep])></span>
|
||||||
|
@endfor
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="qc-step-label">{{ $currentStep }}/5</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="qc-stage">
|
||||||
<div class="qc-card">
|
<div class="qc-card">
|
||||||
@if ($currentStep === 1)
|
@if ($currentStep === 1)
|
||||||
<div class="qc-body">
|
<div class="qc-body">
|
||||||
<label class="qc-upload-zone" for="quick-listing-photo-input">
|
<label class="qc-upload-zone" for="quick-listing-photo-input">
|
||||||
<x-heroicon-o-photo class="h-10 w-10 text-gray-700" />
|
<x-heroicon-o-photo class="h-10 w-10 text-gray-700" />
|
||||||
<div class="qc-upload-title">Ürün fotoğraflarını yükle</div>
|
<div class="qc-upload-title">Start with photos</div>
|
||||||
<div class="qc-upload-desc">
|
<div class="qc-upload-desc">Add clear images first.</div>
|
||||||
Yüklemeye başlamak için ürün fotoğraflarını
|
<span class="qc-upload-btn">Choose Photos</span>
|
||||||
<strong>bu alana sürükleyip bırakın</strong> veya
|
|
||||||
</div>
|
|
||||||
<span class="qc-upload-btn">Fotoğraf Seç</span>
|
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
@ -890,10 +1262,7 @@
|
|||||||
class="hidden"
|
class="hidden"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<p class="qc-help">
|
<p class="qc-help">1 to {{ (int) config('quick-listing.max_photo_count', 20) }} images. JPG and PNG only.</p>
|
||||||
<strong>İpucu:</strong> En az 1 fotoğraf, en çok {{ (int) config('quick-listing.max_photo_count', 20) }} fotoğraf yükleyebilirsin.<br>
|
|
||||||
Desteklenen formatlar: <strong>.jpg, .jpeg ve .png</strong>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
@error('photos')
|
@error('photos')
|
||||||
<div class="qc-error">{{ $message }}</div>
|
<div class="qc-error">{{ $message }}</div>
|
||||||
@ -904,17 +1273,17 @@
|
|||||||
@enderror
|
@enderror
|
||||||
|
|
||||||
@if (count($photos) > 0)
|
@if (count($photos) > 0)
|
||||||
<h3 class="qc-photo-title">Seçtiğin Fotoğraflar</h3>
|
<h3 class="qc-photo-title">Selected photos</h3>
|
||||||
<div class="qc-photo-sub">Fotoğrafları sıralamak için tut ve sürükle</div>
|
<div class="qc-photo-sub">Drag to reorder</div>
|
||||||
|
|
||||||
<div class="qc-photo-grid">
|
<div class="qc-photo-grid">
|
||||||
@for ($index = 0; $index < (int) config('quick-listing.max_photo_count', 20); $index++)
|
@for ($index = 0; $index < (int) config('quick-listing.max_photo_count', 20); $index++)
|
||||||
<div class="qc-photo-slot">
|
<div class="qc-photo-slot">
|
||||||
@if (isset($photos[$index]))
|
@if (isset($photos[$index]))
|
||||||
<img src="{{ $photos[$index]->temporaryUrl() }}" alt="Yüklenen fotoğraf {{ $index + 1 }}">
|
<img src="{{ $photos[$index]->temporaryUrl() }}" alt="Uploaded photo {{ $index + 1 }}">
|
||||||
<button type="button" class="qc-remove" wire:click="removePhoto({{ $index }})">×</button>
|
<button type="button" class="qc-remove" wire:click="removePhoto({{ $index }})">×</button>
|
||||||
@if ($index === 0)
|
@if ($index === 0)
|
||||||
<div class="qc-cover">KAPAK</div>
|
<div class="qc-cover">COVER</div>
|
||||||
@endif
|
@endif
|
||||||
@else
|
@else
|
||||||
<x-heroicon-o-photo class="h-9 w-9 text-gray-400" />
|
<x-heroicon-o-photo class="h-9 w-9 text-gray-400" />
|
||||||
@ -925,11 +1294,8 @@
|
|||||||
@else
|
@else
|
||||||
<div class="qc-ai-note">
|
<div class="qc-ai-note">
|
||||||
<x-heroicon-o-sparkles class="h-10 w-10 text-pink-500" />
|
<x-heroicon-o-sparkles class="h-10 w-10 text-pink-500" />
|
||||||
<h3>Ürün fotoğraflarını yükle</h3>
|
<h3>Add at least one photo</h3>
|
||||||
<p>
|
<p>We can suggest a category after the first image.</p>
|
||||||
Hızlı ilan vermek için en az 1 fotoğraf yükleyin.<br>
|
|
||||||
<strong>Laravel AI</strong> sizin için otomatik kategori önerileri sunar.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@ -941,7 +1307,7 @@
|
|||||||
wire:click="goToCategoryStep"
|
wire:click="goToCategoryStep"
|
||||||
@disabled(count($photos) === 0 || $isDetecting)
|
@disabled(count($photos) === 0 || $isDetecting)
|
||||||
>
|
>
|
||||||
Devam Et
|
Continue
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@ -950,26 +1316,18 @@
|
|||||||
@if ($isDetecting)
|
@if ($isDetecting)
|
||||||
<div class="qc-warning">
|
<div class="qc-warning">
|
||||||
<x-heroicon-o-arrow-path class="h-5 w-5 animate-spin text-gray-700" />
|
<x-heroicon-o-arrow-path class="h-5 w-5 animate-spin text-gray-700" />
|
||||||
<span>Fotoğraf analiz ediliyor, kategori önerisi hazırlanıyor...</span>
|
<span>Finding the best category...</span>
|
||||||
</div>
|
</div>
|
||||||
@elseif ($detectedCategoryId)
|
@elseif ($detectedCategoryId)
|
||||||
<div class="qc-warning">
|
<div class="qc-warning">
|
||||||
<x-heroicon-o-sparkles class="h-5 w-5 text-pink-500" />
|
<x-heroicon-o-sparkles class="h-5 w-5 text-pink-500" />
|
||||||
<span>
|
<span>Suggested category: <strong>{{ $this->selectedCategoryName }}</strong></span>
|
||||||
AI kategori önerdi: <strong>{{ $this->selectedCategoryName }}</strong>
|
|
||||||
@if ($detectedConfidence)
|
|
||||||
(Güven: {{ number_format($detectedConfidence * 100, 0) }}%)
|
|
||||||
@endif
|
|
||||||
@if ($detectedReason)
|
|
||||||
<span class="qc-warning-sub">{{ $detectedReason }}</span>
|
|
||||||
@endif
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
<div class="qc-warning">
|
<div class="qc-warning">
|
||||||
<x-heroicon-o-sparkles class="h-5 w-5 text-pink-500" />
|
<x-heroicon-o-sparkles class="h-5 w-5 text-pink-500" />
|
||||||
<span>
|
<span>
|
||||||
AI ile kategori tespit edilemedi, lütfen kategori seçimi yapın.
|
Choose a category.
|
||||||
@if ($detectedError)
|
@if ($detectedError)
|
||||||
<span class="qc-warning-sub">{{ $detectedError }}</span>
|
<span class="qc-warning-sub">{{ $detectedError }}</span>
|
||||||
@endif
|
@endif
|
||||||
@ -995,9 +1353,9 @@
|
|||||||
@if (is_null($activeParentCategoryId))
|
@if (is_null($activeParentCategoryId))
|
||||||
<div class="qc-browser-header">
|
<div class="qc-browser-header">
|
||||||
<span></span>
|
<span></span>
|
||||||
<strong>Ne Satıyorsun?</strong>
|
<strong>Choose a category</strong>
|
||||||
<button type="button" class="qc-chip" wire:click="detectCategoryFromImage" @disabled($isDetecting || count($photos) === 0)>
|
<button type="button" class="qc-chip" wire:click="detectCategoryFromImage" @disabled($isDetecting || count($photos) === 0)>
|
||||||
AI ile Tekrar Dene
|
Refresh suggestion
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -1019,14 +1377,14 @@
|
|||||||
<div class="qc-browser-header">
|
<div class="qc-browser-header">
|
||||||
<button type="button" class="qc-back-btn" wire:click="backToRootCategories">
|
<button type="button" class="qc-back-btn" wire:click="backToRootCategories">
|
||||||
<x-heroicon-o-arrow-left class="h-5 w-5" />
|
<x-heroicon-o-arrow-left class="h-5 w-5" />
|
||||||
Geri
|
Back
|
||||||
</button>
|
</button>
|
||||||
<strong>{{ $this->currentParentName }}</strong>
|
<strong>{{ $this->currentParentName }}</strong>
|
||||||
<span></span>
|
<span></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="qc-search">
|
<div class="qc-search">
|
||||||
<input type="text" placeholder="Kategori Ara" wire:model.live.debounce.300ms="categorySearch">
|
<input type="text" placeholder="Search categories" wire:model.live.debounce.300ms="categorySearch">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="qc-list">
|
<div class="qc-list">
|
||||||
@ -1056,7 +1414,7 @@
|
|||||||
</div>
|
</div>
|
||||||
@empty
|
@empty
|
||||||
<div class="qc-row">
|
<div class="qc-row">
|
||||||
<span class="qc-row-main">Aramaya uygun kategori bulunamadı.</span>
|
<span class="qc-row-main">No categories found.</span>
|
||||||
</div>
|
</div>
|
||||||
@endforelse
|
@endforelse
|
||||||
</div>
|
</div>
|
||||||
@ -1067,18 +1425,18 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if ($this->selectedCategoryName)
|
@if ($this->selectedCategoryName)
|
||||||
<div class="qc-selection">Seçilen kategori: <strong>{{ $this->selectedCategoryName }}</strong></div>
|
<div class="qc-selection">Selected: <strong>{{ $this->selectedCategoryName }}</strong></div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<div class="qc-footer">
|
<div class="qc-footer">
|
||||||
<button type="button" class="qc-btn qc-btn-secondary" wire:click="goToStep(1)">Geri</button>
|
<button type="button" class="qc-btn qc-btn-secondary" wire:click="goToStep(1)">Back</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="qc-btn qc-btn-primary"
|
class="qc-btn qc-btn-primary"
|
||||||
wire:click="goToDetailsStep"
|
wire:click="goToDetailsStep"
|
||||||
@disabled(! $selectedCategoryId)
|
@disabled(! $selectedCategoryId)
|
||||||
>
|
>
|
||||||
Devam Et
|
Continue
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@ -1088,10 +1446,10 @@
|
|||||||
<div class="qc-strip">
|
<div class="qc-strip">
|
||||||
@foreach (array_slice($photos, 0, 7) as $index => $photo)
|
@foreach (array_slice($photos, 0, 7) as $index => $photo)
|
||||||
<div class="qc-photo-slot">
|
<div class="qc-photo-slot">
|
||||||
<img src="{{ $photo->temporaryUrl() }}" alt="Seçilen fotoğraf {{ $index + 1 }}">
|
<img src="{{ $photo->temporaryUrl() }}" alt="Selected photo {{ $index + 1 }}">
|
||||||
<button type="button" class="qc-remove" wire:click="removePhoto({{ $index }})">×</button>
|
<button type="button" class="qc-remove" wire:click="removePhoto({{ $index }})">×</button>
|
||||||
@if ($index === 0)
|
@if ($index === 0)
|
||||||
<div class="qc-cover">KAPAK</div>
|
<div class="qc-cover">COVER</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
@ -1099,45 +1457,45 @@
|
|||||||
|
|
||||||
<div class="qc-summary">
|
<div class="qc-summary">
|
||||||
<div>
|
<div>
|
||||||
<h4>Seçilen Kategori</h4>
|
<h4>Category</h4>
|
||||||
<p>{{ $this->selectedCategoryPath ?: '-' }}</p>
|
<p>{{ $this->selectedCategoryPath ?: '-' }}</p>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="qc-link-btn" wire:click="goToStep(2)">Değiştir</button>
|
<button type="button" class="qc-link-btn" wire:click="goToStep(2)">Change</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="qc-form-grid">
|
<div class="qc-form-grid">
|
||||||
<div class="qc-field">
|
<div class="qc-field">
|
||||||
<label for="quick-title">İlan Başlığı *</label>
|
<label for="quick-title">Listing Title *</label>
|
||||||
<input id="quick-title" type="text" class="qc-input" placeholder="Başlık girin" wire:model.live.debounce.300ms="listingTitle" maxlength="70">
|
<input id="quick-title" type="text" class="qc-input" placeholder="Enter a title" wire:model.live.debounce.300ms="listingTitle" maxlength="70">
|
||||||
<p class="qc-hint">Ürünün temel özelliklerinden bahset (ör. marka, model, yaş, tip)</p>
|
<p class="qc-hint">Keep it short and clear.</p>
|
||||||
<div class="qc-counter">{{ $this->titleCharacters }}/70</div>
|
<div class="qc-counter">{{ $this->titleCharacters }}/70</div>
|
||||||
@error('listingTitle')<div class="qc-error">{{ $message }}</div>@enderror
|
@error('listingTitle')<div class="qc-error">{{ $message }}</div>@enderror
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="qc-field">
|
<div class="qc-field">
|
||||||
<label for="quick-price">Fiyat *</label>
|
<label for="quick-price">Price *</label>
|
||||||
<div class="qc-input-row">
|
<div class="qc-input-row">
|
||||||
<input id="quick-price" type="number" step="0.01" class="qc-input" placeholder="Fiyat giriniz" wire:model.live.debounce.300ms="price">
|
<input id="quick-price" type="number" step="0.01" class="qc-input" placeholder="Enter a price" wire:model.live.debounce.300ms="price">
|
||||||
<span class="qc-input-suffix">{{ \Modules\Listing\Support\ListingPanelHelper::defaultCurrency() }}</span>
|
<span class="qc-input-suffix">{{ \Modules\Listing\Support\ListingPanelHelper::defaultCurrency() }}</span>
|
||||||
</div>
|
</div>
|
||||||
<p class="qc-hint">Lütfen unutma; doğru fiyat daha hızlı satmanıza yardımcı olacaktır</p>
|
<p class="qc-hint">Use the final asking price.</p>
|
||||||
@error('price')<div class="qc-error">{{ $message }}</div>@enderror
|
@error('price')<div class="qc-error">{{ $message }}</div>@enderror
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="qc-field">
|
<div class="qc-field">
|
||||||
<label for="quick-description">Açıklama *</label>
|
<label for="quick-description">Description *</label>
|
||||||
<textarea id="quick-description" class="qc-textarea" placeholder="Açıklama girin" wire:model.live.debounce.300ms="description" maxlength="1450"></textarea>
|
<textarea id="quick-description" class="qc-textarea" placeholder="Write a description" wire:model.live.debounce.300ms="description" maxlength="1450"></textarea>
|
||||||
<p class="qc-hint">Durum, özellik ve satma nedeni gibi bilgileri ekle</p>
|
<p class="qc-hint">Condition, key details, and anything important.</p>
|
||||||
<div class="qc-counter">{{ $this->descriptionCharacters }}/1450</div>
|
<div class="qc-counter">{{ $this->descriptionCharacters }}/1450</div>
|
||||||
@error('description')<div class="qc-error">{{ $message }}</div>@enderror
|
@error('description')<div class="qc-error">{{ $message }}</div>@enderror
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="qc-field">
|
<div class="qc-field">
|
||||||
<label>Konum *</label>
|
<label>Location *</label>
|
||||||
<div class="qc-two-col">
|
<div class="qc-two-col">
|
||||||
<div>
|
<div>
|
||||||
<select class="qc-select" wire:model.live="selectedCountryId">
|
<select class="qc-select" wire:model.live="selectedCountryId">
|
||||||
<option value="">Ülke seçin</option>
|
<option value="">Select a country</option>
|
||||||
@foreach ($countries as $country)
|
@foreach ($countries as $country)
|
||||||
<option value="{{ $country['id'] }}">{{ $country['name'] }}</option>
|
<option value="{{ $country['id'] }}">{{ $country['name'] }}</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
@ -1146,7 +1504,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<select class="qc-select" wire:model.live="selectedCityId" @disabled(! $selectedCountryId)>
|
<select class="qc-select" wire:model.live="selectedCityId" @disabled(! $selectedCountryId)>
|
||||||
<option value="">Şehir seçin</option>
|
<option value="">Select a city</option>
|
||||||
@foreach ($this->availableCities as $city)
|
@foreach ($this->availableCities as $city)
|
||||||
<option value="{{ $city['id'] }}">{{ $city['name'] }}</option>
|
<option value="{{ $city['id'] }}">{{ $city['name'] }}</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
@ -1159,8 +1517,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="qc-footer">
|
<div class="qc-footer">
|
||||||
<button type="button" class="qc-btn qc-btn-secondary" wire:click="goToStep(2)">Geri</button>
|
<button type="button" class="qc-btn qc-btn-secondary" wire:click="goToStep(2)">Back</button>
|
||||||
<button type="button" class="qc-btn qc-btn-primary" wire:click="goToFeaturesStep">Devam Et</button>
|
<button type="button" class="qc-btn qc-btn-primary" wire:click="goToFeaturesStep">Continue</button>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@ -1168,15 +1526,15 @@
|
|||||||
<div class="qc-body">
|
<div class="qc-body">
|
||||||
<div class="qc-summary" style="margin-top: 0; border-top: 0; padding-top: 0;">
|
<div class="qc-summary" style="margin-top: 0; border-top: 0; padding-top: 0;">
|
||||||
<div>
|
<div>
|
||||||
<h4>Seçilen Kategori</h4>
|
<h4>Category</h4>
|
||||||
<p>{{ $this->selectedCategoryPath ?: '-' }}</p>
|
<p>{{ $this->selectedCategoryPath ?: '-' }}</p>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="qc-link-btn" wire:click="goToStep(2)">Değiştir</button>
|
<button type="button" class="qc-link-btn" wire:click="goToStep(2)">Change</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if ($listingCustomFields === [])
|
@if ($listingCustomFields === [])
|
||||||
<div class="qc-info-box">
|
<div class="qc-info-box">
|
||||||
Bu kategori için ek ilan özelliği tanımlı değil. Devam ederek önizleme adımına geçebilirsin.
|
No extra details needed for this category.
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
<div class="qc-dynamic-grid">
|
<div class="qc-dynamic-grid">
|
||||||
@ -1212,7 +1570,7 @@
|
|||||||
>
|
>
|
||||||
@elseif ($field['type'] === 'select')
|
@elseif ($field['type'] === 'select')
|
||||||
<select class="qc-select" wire:model.live="customFieldValues.{{ $field['name'] }}">
|
<select class="qc-select" wire:model.live="customFieldValues.{{ $field['name'] }}">
|
||||||
<option value="">Seçiniz</option>
|
<option value="">Select an option</option>
|
||||||
@foreach ($field['options'] as $option)
|
@foreach ($field['options'] as $option)
|
||||||
<option value="{{ $option }}">{{ $option }}</option>
|
<option value="{{ $option }}">{{ $option }}</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
@ -1220,7 +1578,7 @@
|
|||||||
@elseif ($field['type'] === 'boolean')
|
@elseif ($field['type'] === 'boolean')
|
||||||
<label class="qc-toggle-line">
|
<label class="qc-toggle-line">
|
||||||
<input type="checkbox" wire:model.live="customFieldValues.{{ $field['name'] }}">
|
<input type="checkbox" wire:model.live="customFieldValues.{{ $field['name'] }}">
|
||||||
<span>Evet</span>
|
<span>Yes</span>
|
||||||
</label>
|
</label>
|
||||||
@elseif ($field['type'] === 'date')
|
@elseif ($field['type'] === 'date')
|
||||||
<input type="date" class="qc-input" wire:model.live="customFieldValues.{{ $field['name'] }}">
|
<input type="date" class="qc-input" wire:model.live="customFieldValues.{{ $field['name'] }}">
|
||||||
@ -1240,21 +1598,21 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="qc-footer">
|
<div class="qc-footer">
|
||||||
<button type="button" class="qc-btn qc-btn-secondary" wire:click="goToStep(3)">Geri</button>
|
<button type="button" class="qc-btn qc-btn-secondary" wire:click="goToStep(3)">Back</button>
|
||||||
<button type="button" class="qc-btn qc-btn-primary" wire:click="goToPreviewStep">Devam Et</button>
|
<button type="button" class="qc-btn qc-btn-primary" wire:click="goToPreviewStep">Continue</button>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if ($currentStep === 5)
|
@if ($currentStep === 5)
|
||||||
<div class="qc-body">
|
<div class="qc-body">
|
||||||
<div class="qc-preview-breadcrumb">Anasayfa › {{ $this->selectedCategoryPath }}</div>
|
<div class="qc-preview-breadcrumb">Home › {{ $this->selectedCategoryPath }}</div>
|
||||||
|
|
||||||
<div class="qc-preview-grid">
|
<div class="qc-preview-grid">
|
||||||
<div class="qc-preview-panel">
|
<div class="qc-preview-panel">
|
||||||
<div class="qc-gallery">
|
<div class="qc-gallery">
|
||||||
@foreach (array_slice($photos, 0, 3) as $photo)
|
@foreach (array_slice($photos, 0, 3) as $photo)
|
||||||
<div class="qc-gallery-item">
|
<div class="qc-gallery-item">
|
||||||
<img src="{{ $photo->temporaryUrl() }}" alt="Önizleme fotoğrafı">
|
<img src="{{ $photo->temporaryUrl() }}" alt="Preview photo">
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
@for ($empty = count(array_slice($photos, 0, 3)); $empty < 3; $empty++)
|
@for ($empty = count(array_slice($photos, 0, 3)); $empty < 3; $empty++)
|
||||||
@ -1280,7 +1638,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="qc-preview-features">
|
<div class="qc-preview-features">
|
||||||
<h5>İlan Özellikleri</h5>
|
<h5>Details</h5>
|
||||||
@if ($this->previewCustomFields !== [])
|
@if ($this->previewCustomFields !== [])
|
||||||
@foreach ($this->previewCustomFields as $field)
|
@foreach ($this->previewCustomFields as $field)
|
||||||
<div class="qc-feature-row">
|
<div class="qc-feature-row">
|
||||||
@ -1290,8 +1648,8 @@
|
|||||||
@endforeach
|
@endforeach
|
||||||
@else
|
@else
|
||||||
<div class="qc-feature-row">
|
<div class="qc-feature-row">
|
||||||
<div class="qc-feature-label">Ek özellik</div>
|
<div class="qc-feature-label">Details</div>
|
||||||
<div class="qc-feature-value">Bu kategori için seçilmedi</div>
|
<div class="qc-feature-value">No extra details added</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@ -1308,8 +1666,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="qc-seller-actions">
|
<div class="qc-seller-actions">
|
||||||
<div class="qc-pill">Harita</div>
|
<div class="qc-pill">Map</div>
|
||||||
<div class="qc-pill">Satıcı Profili</div>
|
<div class="qc-pill">Profile</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -1320,14 +1678,15 @@
|
|||||||
wire:click="publishListing"
|
wire:click="publishListing"
|
||||||
@disabled($isPublishing)
|
@disabled($isPublishing)
|
||||||
>
|
>
|
||||||
{{ $isPublishing ? 'Yayınlanıyor...' : 'İlanı Şimdi Yayınla' }}
|
{{ $isPublishing ? 'Publishing...' : 'Publish Listing' }}
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="qc-muted-btn" wire:click="goToStep(4)">Geri Dön</button>
|
<button type="button" class="qc-muted-btn" wire:click="goToStep(4)">Back</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -15,7 +15,7 @@ Route::get('/dashboard', fn () => auth()->check()
|
|||||||
Route::middleware('auth')->prefix('panel')->name('panel.')->group(function () {
|
Route::middleware('auth')->prefix('panel')->name('panel.')->group(function () {
|
||||||
Route::get('/', [PanelController::class, 'index'])->name('index');
|
Route::get('/', [PanelController::class, 'index'])->name('index');
|
||||||
Route::get('/ilanlarim', [PanelController::class, 'listings'])->name('listings.index');
|
Route::get('/ilanlarim', [PanelController::class, 'listings'])->name('listings.index');
|
||||||
Route::get('/ilan-ver', [PanelController::class, 'create'])->name('listings.create');
|
Route::get('/create-listing', [PanelController::class, 'create'])->name('listings.create');
|
||||||
Route::post('/ilanlarim/{listing}/kaldir', [PanelController::class, 'destroyListing'])->name('listings.destroy');
|
Route::post('/ilanlarim/{listing}/kaldir', [PanelController::class, 'destroyListing'])->name('listings.destroy');
|
||||||
Route::post('/ilanlarim/{listing}/satildi', [PanelController::class, 'markListingAsSold'])->name('listings.mark-sold');
|
Route::post('/ilanlarim/{listing}/satildi', [PanelController::class, 'markListingAsSold'])->name('listings.mark-sold');
|
||||||
Route::post('/ilanlarim/{listing}/yeniden-yayinla', [PanelController::class, 'republishListing'])->name('listings.republish');
|
Route::post('/ilanlarim/{listing}/yeniden-yayinla', [PanelController::class, 'republishListing'])->name('listings.republish');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user