feat: kariyer formu, mobil offcanvas menu ve blog modulu iyilestirmeleri

This commit is contained in:
Muhammet Güler
2026-03-10 18:50:23 +03:00
parent f4f601a492
commit 4924cb0dc8
25 changed files with 1220 additions and 182 deletions
@@ -0,0 +1,55 @@
<?php
namespace App\Filament\Admin\Resources\CareerApplications;
use App\Filament\Admin\Resources\CareerApplications\Pages\CreateCareerApplication;
use App\Filament\Admin\Resources\CareerApplications\Pages\EditCareerApplication;
use App\Filament\Admin\Resources\CareerApplications\Pages\ListCareerApplications;
use App\Filament\Admin\Resources\CareerApplications\Schemas\CareerApplicationForm;
use App\Filament\Admin\Resources\CareerApplications\Tables\CareerApplicationsTable;
use App\Models\CareerApplication;
use BackedEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Tables\Table;
class CareerApplicationResource extends Resource
{
protected static ?string $model = CareerApplication::class;
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-user-group';
public static function getNavigationLabel(): string
{
return __('career.navigation_label');
}
public static function getModelLabel(): string
{
return __('career.model_label');
}
public static function getPluralModelLabel(): string
{
return __('career.plural_model_label');
}
public static function form(Schema $schema): Schema
{
return CareerApplicationForm::configure($schema);
}
public static function table(Table $table): Table
{
return CareerApplicationsTable::configure($table);
}
public static function getPages(): array
{
return [
'index' => ListCareerApplications::route('/'),
'create' => CreateCareerApplication::route('/create'),
'edit' => EditCareerApplication::route('/{record}/edit'),
];
}
}
@@ -0,0 +1,11 @@
<?php
namespace App\Filament\Admin\Resources\CareerApplications\Pages;
use App\Filament\Admin\Resources\CareerApplications\CareerApplicationResource;
use Filament\Resources\Pages\CreateRecord;
class CreateCareerApplication extends CreateRecord
{
protected static string $resource = CareerApplicationResource::class;
}
@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Admin\Resources\CareerApplications\Pages;
use App\Filament\Admin\Resources\CareerApplications\CareerApplicationResource;
use Filament\Actions\DeleteAction;
use Filament\Resources\Pages\EditRecord;
class EditCareerApplication extends EditRecord
{
protected static string $resource = CareerApplicationResource::class;
protected function getHeaderActions(): array
{
return [
DeleteAction::make(),
];
}
}
@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Admin\Resources\CareerApplications\Pages;
use App\Filament\Admin\Resources\CareerApplications\CareerApplicationResource;
use Filament\Actions\CreateAction;
use Filament\Resources\Pages\ListRecords;
class ListCareerApplications extends ListRecords
{
protected static string $resource = CareerApplicationResource::class;
protected function getHeaderActions(): array
{
return [
CreateAction::make(),
];
}
}
@@ -0,0 +1,55 @@
<?php
namespace App\Filament\Admin\Resources\CareerApplications\Schemas;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Schema;
class CareerApplicationForm
{
public static function configure(Schema $schema): Schema
{
return $schema
->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(),
]);
}
}
@@ -0,0 +1,75 @@
<?php
namespace App\Filament\Admin\Resources\CareerApplications\Tables;
use Filament\Actions\Action;
use Filament\Actions\DeleteAction;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Support\Facades\Storage;
class CareerApplicationsTable
{
public static function configure(Table $table): Table
{
return $table
->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');
}
}
+10
View File
@@ -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' => [
+47
View File
@@ -0,0 +1,47 @@
<?php
namespace App\Http\Controllers;
use App\Models\CareerApplication;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class CareerController extends Controller
{
public function index()
{
return view('front.career.index', [
'meta' => [
'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'));
}
}
@@ -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
@@ -0,0 +1,80 @@
<?php
namespace App\Http\Controllers;
use App\Models\Page;
use App\Models\Blog;
use App\Models\Product;
use Illuminate\Http\Response;
class SitemapController extends Controller
{
public function index(): Response
{
$urls = [];
// 1. Static & Main Pages
$urls[] = [
'loc' => 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');
}
}
+20
View File
@@ -0,0 +1,20 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class CareerApplication extends Model
{
use HasFactory;
protected $fillable = [
'name',
'email',
'phone',
'cv_path',
'message',
'status',
];
}