diff --git a/app/Filament/Admin/Resources/CareerApplications/CareerApplicationResource.php b/app/Filament/Admin/Resources/CareerApplications/CareerApplicationResource.php new file mode 100644 index 0000000..0cfd16a --- /dev/null +++ b/app/Filament/Admin/Resources/CareerApplications/CareerApplicationResource.php @@ -0,0 +1,55 @@ + ListCareerApplications::route('/'), + 'create' => CreateCareerApplication::route('/create'), + 'edit' => EditCareerApplication::route('/{record}/edit'), + ]; + } +} diff --git a/app/Filament/Admin/Resources/CareerApplications/Pages/CreateCareerApplication.php b/app/Filament/Admin/Resources/CareerApplications/Pages/CreateCareerApplication.php new file mode 100644 index 0000000..e37512d --- /dev/null +++ b/app/Filament/Admin/Resources/CareerApplications/Pages/CreateCareerApplication.php @@ -0,0 +1,11 @@ +components([ + TextInput::make('name') + ->label(__('career.name')) + ->required() + ->disabled(), + + TextInput::make('email') + ->label(__('career.email')) + ->email() + ->required() + ->disabled(), + + TextInput::make('phone') + ->label(__('career.phone')) + ->disabled(), + + FileUpload::make('cv_path') + ->label(__('career.cv')) + ->disk('public') + ->directory('cvs') + ->required() + ->disabled(), + + Textarea::make('message') + ->label(__('career.message')) + ->disabled() + ->columnSpanFull(), + + Select::make('status') + ->label(__('career.status')) + ->options([ + 'pending' => 'Pending', + 'reviewed' => 'Reviewed', + 'rejected' => 'Rejected', + 'accepted' => 'Accepted', + ]) + ->required(), + ]); + } +} diff --git a/app/Filament/Admin/Resources/CareerApplications/Tables/CareerApplicationsTable.php b/app/Filament/Admin/Resources/CareerApplications/Tables/CareerApplicationsTable.php new file mode 100644 index 0000000..c4863cc --- /dev/null +++ b/app/Filament/Admin/Resources/CareerApplications/Tables/CareerApplicationsTable.php @@ -0,0 +1,75 @@ +columns([ + TextColumn::make('name') + ->label(__('career.name')) + ->searchable() + ->sortable(), + + TextColumn::make('email') + ->label(__('career.email')) + ->searchable() + ->sortable(), + + TextColumn::make('phone') + ->label(__('career.phone')) + ->searchable(), + + TextColumn::make('status') + ->label(__('career.status')) + ->badge() + ->color(fn (string $state): string => match ($state) { + 'pending' => 'gray', + 'reviewed' => 'info', + 'rejected' => 'danger', + 'accepted' => 'success', + default => 'gray', + }), + + TextColumn::make('created_at') + ->label(__('career.created_at')) + ->dateTime('d.m.Y H:i') + ->sortable(), + ]) + ->filters([ + SelectFilter::make('status') + ->label(__('career.status')) + ->options([ + 'pending' => 'Pending', + 'reviewed' => 'Reviewed', + 'rejected' => 'Rejected', + 'accepted' => 'Accepted', + ]), + ]) + ->actions([ + Action::make('download_cv') + ->label(__('career.download_cv')) + ->icon('heroicon-o-arrow-down-tray') + ->url(fn ($record) => Storage::disk('public')->url($record->cv_path)) + ->openUrlInNewTab(), + DeleteAction::make(), + ]) + ->bulkActions([ + BulkActionGroup::make([ + DeleteBulkAction::make(), + ]), + ]) + ->defaultSort('created_at', 'desc'); + } +} diff --git a/app/Http/Controllers/BlogController.php b/app/Http/Controllers/BlogController.php index ca1ec30..d3eb264 100644 --- a/app/Http/Controllers/BlogController.php +++ b/app/Http/Controllers/BlogController.php @@ -106,9 +106,19 @@ class BlogController extends Controller ); } + // Kategorileri al (filtreleme için) + $categories = class_exists(\App\Models\BlogCategory::class) ? \App\Models\BlogCategory::where('is_active', true)->orderBy('sort_order')->get() : collect(); + + if ($request->ajax()) { + return view('blog.partials.posts', [ + 'posts' => $posts + ]); + } + return view('blog.index', [ 'settings' => $settings, 'posts' => $posts, + 'categories' => $categories, 'renderedHeader' => $renderedHeader, 'renderedFooter' => $renderedFooter, 'meta' => [ diff --git a/app/Http/Controllers/CareerController.php b/app/Http/Controllers/CareerController.php new file mode 100644 index 0000000..43f5cf6 --- /dev/null +++ b/app/Http/Controllers/CareerController.php @@ -0,0 +1,47 @@ + [ + 'title' => __('career.title', ['default' => 'Kariyer']), + 'description' => __('career.description', ['default' => 'Ekibimize katılmak için aşağıdaki formu doldurarak CV\'nizi iletebilirsiniz.']), + ] + ]); + } + + public function store(Request $request) + { + $request->validate([ + 'name' => 'required|string|max:255', + 'email' => 'required|email|max:255', + 'phone' => 'nullable|string|max:20', + 'cv' => 'required|file|mimes:pdf,doc,docx|max:5120', // Max 5MB + 'message' => 'nullable|string', + ]); + + $cvPath = null; + if ($request->hasFile('cv')) { + $cvPath = $request->file('cv')->store('cvs', 'public'); + } + + CareerApplication::create([ + 'name' => $request->name, + 'email' => $request->email, + 'phone' => $request->phone, + 'cv_path' => $cvPath, + 'message' => $request->message, + 'status' => 'pending', + ]); + + return redirect()->back()->with('success', __('career.success_message')); + } +} diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index bfe8e5d..7d45019 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -66,6 +66,7 @@ class ProductController extends Controller $meta = [ 'title' => $product->translate('title'), 'description' => \Str::limit(strip_tags($product->translate('content')), 160), + 'image' => $product->hero_image ? asset('storage/' . $product->hero_image) : null, ]; // Use custom view template if specified diff --git a/app/Http/Controllers/SitemapController.php b/app/Http/Controllers/SitemapController.php new file mode 100644 index 0000000..ebbaf87 --- /dev/null +++ b/app/Http/Controllers/SitemapController.php @@ -0,0 +1,80 @@ + url('/'), + 'lastmod' => now()->startOfDay()->toAtomString(), + 'changefreq' => 'daily', + 'priority' => '1.0', + ]; + + $urls[] = [ + 'loc' => route('blog.index'), + 'lastmod' => now()->startOfDay()->toAtomString(), + 'changefreq' => 'weekly', + 'priority' => '0.8', + ]; + + $urls[] = [ + 'loc' => route('career.index'), + 'lastmod' => now()->startOfMonth()->toAtomString(), + 'changefreq' => 'monthly', + 'priority' => '0.5', + ]; + + // 2. Dynamic Pages + $pages = Page::where('status', 'published') + ->where('is_homepage', false) + ->get(); + foreach ($pages as $page) { + $urls[] = [ + 'loc' => url($page->slug), + 'lastmod' => $page->updated_at->toAtomString(), + 'changefreq' => 'weekly', + 'priority' => '0.7', + ]; + } + + // 3. Blog Posts + if (class_exists(Blog::class)) { + $posts = Blog::published()->get(); + foreach ($posts as $post) { + $urls[] = [ + 'loc' => route('blog.show', $post->slug), + 'lastmod' => $post->updated_at->toAtomString(), + 'changefreq' => 'weekly', + 'priority' => '0.6', + ]; + } + } + + // 4. Products + if (class_exists(Product::class)) { + $products = Product::where('is_active', true)->get(); + foreach ($products as $product) { + $urls[] = [ + 'loc' => route('products.show', $product->slug), + 'lastmod' => $product->updated_at->toAtomString(), + 'changefreq' => 'weekly', + 'priority' => '0.7', + ]; + } + } + + return response()->view('sitemap', compact('urls')) + ->header('Content-Type', 'text/xml'); + } +} diff --git a/app/Models/CareerApplication.php b/app/Models/CareerApplication.php new file mode 100644 index 0000000..134e74f --- /dev/null +++ b/app/Models/CareerApplication.php @@ -0,0 +1,20 @@ +id(); + $blueprint->string('name'); + $blueprint->string('email'); + $blueprint->string('phone')->nullable(); + $blueprint->string('cv_path'); + $blueprint->text('message')->nullable(); + $blueprint->string('status')->default('pending'); // pending, reviewed, rejected, accepted + $blueprint->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('career_applications'); + } +}; diff --git a/database/seeders/SettingSeeder.php b/database/seeders/SettingSeeder.php index bbb80cf..1c19284 100644 --- a/database/seeders/SettingSeeder.php +++ b/database/seeders/SettingSeeder.php @@ -659,6 +659,16 @@ class SettingSeeder extends Seeder 'is_public' => false, 'is_active' => true, ], + [ + 'key' => 'seo_google_search_console', + 'value' => '', + 'type' => 'string', + 'group' => 'seo', + 'label' => 'Google Search Console', + 'description' => 'Google Search Console doğrulama kodu', + 'is_public' => false, + 'is_active' => true, + ], [ 'key' => 'seo_google_tag_manager_id', 'value' => '', diff --git a/lang/en/blog.php b/lang/en/blog.php index c6d745a..1716975 100644 --- a/lang/en/blog.php +++ b/lang/en/blog.php @@ -104,4 +104,5 @@ return [ 'submit' => 'Submit', 'comment_submitted' => 'Your comment has been submitted. It will be published after approval.', 'comments_disabled' => 'Comments are disabled for this blog post.', + 'all_categories' => 'All Categories', ]; diff --git a/lang/en/career.php b/lang/en/career.php new file mode 100644 index 0000000..12c0e22 --- /dev/null +++ b/lang/en/career.php @@ -0,0 +1,19 @@ + 'Career Applications', + 'model_label' => 'Application', + 'plural_model_label' => 'Career Applications', + 'title' => 'Career Form', + 'description' => 'To join our team, please fill out the form below and upload your CV.', + 'name' => 'Full Name', + 'email' => 'Email', + 'phone' => 'Phone', + 'cv' => 'Curriculum Vitae (CV)', + 'message' => 'Message', + 'status' => 'Status', + 'submit' => 'Submit Application', + 'success_message' => 'Your application has been received successfully. Thank you.', + 'download_cv' => 'Download CV', + 'created_at' => 'Application Date', +]; diff --git a/lang/tr/blog.php b/lang/tr/blog.php index 7fb3797..b2fd04b 100644 --- a/lang/tr/blog.php +++ b/lang/tr/blog.php @@ -104,4 +104,5 @@ return [ 'submit' => 'Gönder', 'comment_submitted' => 'Yorumunuz gönderildi. Onaylandıktan sonra yayınlanacaktır.', 'comments_disabled' => 'Bu blog yazısında yorumlar devre dışı bırakılmıştır.', + 'all_categories' => 'Tüm Kategoriler', ]; diff --git a/lang/tr/career.php b/lang/tr/career.php new file mode 100644 index 0000000..1d1b406 --- /dev/null +++ b/lang/tr/career.php @@ -0,0 +1,19 @@ + 'Kariyer Başvuruları', + 'model_label' => 'Başvuru', + 'plural_model_label' => 'Kariyer Başvuruları', + 'title' => 'Kariyer Formu', + 'description' => 'Ekibimize katılmak için aşağıdaki formu doldurarak CV\'nizi iletebilirsiniz.', + 'name' => 'Ad Soyad', + 'email' => 'E-posta', + 'phone' => 'Telefon', + 'cv' => 'Özgeçmiş (CV)', + 'message' => 'Mesaj', + 'status' => 'Durum', + 'submit' => 'Başvuruyu Gönder', + 'success_message' => 'Başvurunuz başarıyla alındı. Teşekkür ederiz.', + 'download_cv' => 'CV İndir', + 'created_at' => 'Başvuru Tarihi', +]; diff --git a/resources/views/blog/index.blade.php b/resources/views/blog/index.blade.php index 38bc131..c73cb7c 100644 --- a/resources/views/blog/index.blade.php +++ b/resources/views/blog/index.blade.php @@ -21,172 +21,23 @@
-
- @forelse($posts as $index => $post) - @php - $title = method_exists($post, 'translate') ? $post->translate('title') : $post->title; - $excerpt = method_exists($post, 'translate') ? $post->translate('excerpt') : ($post->excerpt ?? ''); - $categoryName = $post->category ? $post->category->name : ''; - $categorySlug = $post->category ? $post->category->slug : ''; - $publishedDate = $post->published_at ? $post->published_at->format('d M Y') : $post->created_at->format('d M Y'); - $imageUrl = $post->featured_image ? asset('storage/' . $post->featured_image) : asset('assets/img/photos/b1.webp'); - $blogUrl = route('blog.show', $post->slug); - $commentCount = $post->comments_count ?? 0; - $authorName = $post->author ? $post->author->name : ''; - @endphp - - @if($index < 3) - {{-- İlk 3 blog yazısı classic-view formatında --}} - - - @endif - @empty -
-

{{ __('blog.empty') }}

-
- @endforelse + + @if(isset($categories) && $categories->count() > 0) + - - - @if($posts->count() > 3) -
-
- @foreach($posts as $index => $post) - @if($index >= 3) - @php - $title = method_exists($post, 'translate') ? $post->translate('title') : $post->title; - $excerpt = method_exists($post, 'translate') ? $post->translate('excerpt') : ($post->excerpt ?? ''); - $categoryName = $post->category ? $post->category->name : ''; - $categorySlug = $post->category ? $post->category->slug : ''; - $publishedDate = $post->published_at ? $post->published_at->format('d M Y') : $post->created_at->format('d M Y'); - $imageUrl = $post->featured_image ? asset('storage/' . $post->featured_image) : asset('assets/img/photos/b4.webp'); - $blogUrl = route('blog.show', $post->slug); - $commentCount = $post->comments_count ?? 0; - @endphp - -
-
-
- - {{ $title }} - -
-
{{ __('blog.read_more') }}
-
-
-
-
- @if($categoryName) - - @endif - -

- {{ $title }} -

-
- -
-

{{ \Illuminate\Support\Str::limit($excerpt, 120) }}

-
- -
- - - -
- -
- - @endif - @endforeach -
- -
- @endif - {{-- Pagination --}} - @if(method_exists($posts, 'links') && $posts->hasPages()) -
- {{ $posts->links() }} -
- @endif +
+ @include('blog.partials.posts') +
@@ -194,4 +45,179 @@
+ +@push('styles') + +@endpush + +@push('scripts') + +@endpush @endsection diff --git a/resources/views/blog/partials/posts.blade.php b/resources/views/blog/partials/posts.blade.php new file mode 100644 index 0000000..61f1b22 --- /dev/null +++ b/resources/views/blog/partials/posts.blade.php @@ -0,0 +1,166 @@ +
+ @forelse($posts as $index => $post) + @php + $title = method_exists($post, 'translate') ? $post->translate('title') : $post->title; + $excerpt = method_exists($post, 'translate') ? $post->translate('excerpt') : ($post->excerpt ?? ''); + $categoryName = $post->category ? $post->category->name : ''; + $categorySlug = $post->category ? $post->category->slug : ''; + $publishedDate = $post->published_at ? $post->published_at->format('d M Y') : $post->created_at->format('d M Y'); + $imageUrl = $post->featured_image ? asset('storage/' . $post->featured_image) : asset('assets/img/photos/b1.webp'); + $blogUrl = route('blog.show', $post->slug); + $commentCount = $post->comments_count ?? 0; + $authorName = $post->author ? $post->author->name : ''; + @endphp + + @if($index < 3) + {{-- İlk 3 blog yazısı classic-view formatında --}} +
+
+ @if($post->featured_image_url) +
+ + {{ $title }} + +
+
{{ __('blog.read_more') }}
+
+
+ @endif +
+
+ @if($categoryName) + + @endif + +

+ {{ $title }} +

+
+ +
+

{{ $excerpt }}

+
+ +
+ + + +
+ +
+ + @endif + @empty +
+

{{ __('blog.empty') }}

+
+ @endforelse +
+ + +@if($posts->count() > 3) +
+
+ @foreach($posts as $index => $post) + @if($index >= 3) + @php + $title = method_exists($post, 'translate') ? $post->translate('title') : $post->title; + $excerpt = method_exists($post, 'translate') ? $post->translate('excerpt') : ($post->excerpt ?? ''); + $categoryName = $post->category ? $post->category->name : ''; + $categorySlug = $post->category ? $post->category->slug : ''; + $publishedDate = $post->published_at ? $post->published_at->format('d M Y') : $post->created_at->format('d M Y'); + $imageUrl = $post->featured_image ? asset('storage/' . $post->featured_image) : asset('assets/img/photos/b4.webp'); + $blogUrl = route('blog.show', $post->slug); + $commentCount = $post->comments_count ?? 0; + @endphp + +
+
+
+ + {{ $title }} + +
+
{{ __('blog.read_more') }}
+
+
+
+
+ @if($categoryName) + + @endif + +

+ {{ $title }} +

+
+ +
+

{{ \Illuminate\Support\Str::limit($excerpt, 120) }}

+
+ +
+ + + +
+ +
+ + @endif + @endforeach +
+ +
+ +@endif + +{{-- Pagination --}} +@if(method_exists($posts, 'links') && $posts->hasPages()) +
+ {{ $posts->links() }} +
+@endif diff --git a/resources/views/components/front/header.blade.php b/resources/views/components/front/header.blade.php index 90c7ac8..dc82893 100644 --- a/resources/views/components/front/header.blade.php +++ b/resources/views/components/front/header.blade.php @@ -140,3 +140,54 @@ $isHomepage = $currentRoute === 'homepage' || $currentPath === '/' || request()- + +@push('styles') + +@endpush + +@push('scripts') + +@endpush diff --git a/resources/views/front/career/index.blade.php b/resources/views/front/career/index.blade.php new file mode 100644 index 0000000..82d63af --- /dev/null +++ b/resources/views/front/career/index.blade.php @@ -0,0 +1,179 @@ +@extends('layouts.site') + +@section('content') +
+
+
+
+

{{ __('career.title', ['default' => 'Kariyer']) }}

+

{{ __('career.description', ['default' => 'Ekibimize katılmak için aşağıdaki formu doldurarak CV\'nizi iletebilirsiniz.']) }}

+
+
+
+
+ +
+
+
+
+
+
+
+
+

Başvuru Formu

+
+
+
+ + @if(session('success')) +
+
+ +
{{ session('success') }}
+
+
+ + @endif + +
+ @csrf + + +
+ +
+ + @error('name')
{{ $message }}
@enderror +
+
+ +
+ +
+ + @error('email')
{{ $message }}
@enderror +
+
+ +
+ +
+ + @error('phone')
{{ $message }}
@enderror +
+
+ +
+ +
+
+ +
+
PDF, DOC, DOCX dosyaları kabul edilir. (Maks. 5MB)
+ @error('cv')
{{ $message }}
@enderror +
+
+ +
+ +
+ + @error('message')
{{ $message }}
@enderror +
+
+ +
+
+ +
+
+
+
+ +
+ +
+ +
+ +
+ +
+ +@push('styles') + +@endpush +@endsection diff --git a/resources/views/layouts/site.blade.php b/resources/views/layouts/site.blade.php index 95db8e3..6e7ada1 100644 --- a/resources/views/layouts/site.blade.php +++ b/resources/views/layouts/site.blade.php @@ -8,8 +8,35 @@ $favicon_path = setting('site_favicon'); - {{ setting('seo_meta_title') }} - {{ $meta['title'] ?? ($settings->default_meta_title ?? config('app.name')) }} - + @php + $seo_title = ($meta['title'] ?? null) ? $meta['title'] . ' - ' . setting('site_name') : setting('seo_meta_title'); + $seo_description = $meta['description'] ?? setting('seo_meta_description'); + $seo_image = $meta['image'] ?? setting('default_meta_image'); + if ($seo_image && !str_starts_with($seo_image, 'http')) { + $seo_image = asset($seo_image); + } + @endphp + {{ $seo_title }} + + + + + + + + @if($seo_image) + + @endif + + + + + + + @if($seo_image) + + @endif + @@ -18,10 +45,36 @@ $favicon_path = setting('site_favicon'); + + @if(setting('seo_google_search_console')) + + @endif + @if(setting('seo_bing_webmaster')) + + @endif + + + @if(setting('seo_google_analytics_id')) + + + @endif + @stack('styles') diff --git a/resources/views/partials/header.blade.php b/resources/views/partials/header.blade.php index 7bd9ad0..28b1c48 100644 --- a/resources/views/partials/header.blade.php +++ b/resources/views/partials/header.blade.php @@ -29,13 +29,13 @@ $isHomepage = $currentRoute === 'homepage' || $currentPath === '/' || request()-
@@ -45,10 +45,12 @@ $isHomepage = $currentRoute === 'homepage' || $currentPath === '/' || request()- @if($isHomepage)