feat: add career application support for blog authors and expand blog status workflows
This commit is contained in:
@@ -6,6 +6,7 @@ use App\Filament\Admin\Resources\Components\TranslationTabs;
|
|||||||
use Filament\Forms\Components\Checkbox;
|
use Filament\Forms\Components\Checkbox;
|
||||||
use Filament\Forms\Components\DateTimePicker;
|
use Filament\Forms\Components\DateTimePicker;
|
||||||
use Filament\Forms\Components\FileUpload;
|
use Filament\Forms\Components\FileUpload;
|
||||||
|
use Filament\Forms\Components\Placeholder;
|
||||||
use Filament\Forms\Components\RichEditor;
|
use Filament\Forms\Components\RichEditor;
|
||||||
use Filament\Schemas\Components\Section;
|
use Filament\Schemas\Components\Section;
|
||||||
use Filament\Forms\Components\Select;
|
use Filament\Forms\Components\Select;
|
||||||
@@ -80,11 +81,17 @@ class BlogForm
|
|||||||
->helperText(__('blog.featured_image_helper'))
|
->helperText(__('blog.featured_image_helper'))
|
||||||
->columnSpanFull(),
|
->columnSpanFull(),
|
||||||
|
|
||||||
|
Placeholder::make('intern_author_info')
|
||||||
|
->label('Stajyer Yazarı')
|
||||||
|
->content(fn ($record) => $record?->careerApplication?->name ?? '-')
|
||||||
|
->visible(fn ($record) => $record?->career_application_id !== null)
|
||||||
|
->columnSpanFull(),
|
||||||
|
|
||||||
Select::make('author_id')
|
Select::make('author_id')
|
||||||
->label(__('blog.author_field'))
|
->label(__('blog.author_field'))
|
||||||
->relationship('author', 'name')
|
->relationship('author', 'name')
|
||||||
->default(auth()->id())
|
->nullable()
|
||||||
->required()
|
->placeholder('Boş bırakılırsa stajyer yazarı veya Trunçgil')
|
||||||
->columnSpanFull(),
|
->columnSpanFull(),
|
||||||
|
|
||||||
Select::make('category_id')
|
Select::make('category_id')
|
||||||
@@ -110,7 +117,9 @@ class BlogForm
|
|||||||
->label(__('blog.status_field'))
|
->label(__('blog.status_field'))
|
||||||
->options([
|
->options([
|
||||||
'draft' => __('blog.status_draft'),
|
'draft' => __('blog.status_draft'),
|
||||||
|
'pending' => __('blog.status_pending'),
|
||||||
'published' => __('blog.status_published'),
|
'published' => __('blog.status_published'),
|
||||||
|
'rejected' => __('blog.status_rejected'),
|
||||||
'archived' => __('blog.status_archived'),
|
'archived' => __('blog.status_archived'),
|
||||||
])
|
])
|
||||||
->default('draft')
|
->default('draft')
|
||||||
|
|||||||
@@ -76,7 +76,13 @@ class BlogsTable
|
|||||||
|
|
||||||
TextColumn::make('author.name')
|
TextColumn::make('author.name')
|
||||||
->label(__('blog.table_author'))
|
->label(__('blog.table_author'))
|
||||||
->searchable()
|
->formatStateUsing(fn ($state, $record) => $record->author_name)
|
||||||
|
->searchable(query: function ($query, string $search) {
|
||||||
|
$query->where(function ($q) use ($search) {
|
||||||
|
$q->whereHas('author', fn ($sub) => $sub->where('name', 'like', "%{$search}%"))
|
||||||
|
->orWhereHas('careerApplication', fn ($sub) => $sub->where('name', 'like', "%{$search}%"));
|
||||||
|
});
|
||||||
|
})
|
||||||
->sortable(),
|
->sortable(),
|
||||||
|
|
||||||
TextColumn::make('category.name')
|
TextColumn::make('category.name')
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class BlogController extends Controller
|
|||||||
$settings = class_exists(Setting::class) ? (Setting::query()->first()) : null;
|
$settings = class_exists(Setting::class) ? (Setting::query()->first()) : null;
|
||||||
|
|
||||||
$query = class_exists(Blog::class)
|
$query = class_exists(Blog::class)
|
||||||
? Blog::with(['category', 'author'])
|
? Blog::with(['category', 'author', 'careerApplication'])
|
||||||
->withCount('comments')
|
->withCount('comments')
|
||||||
->published()
|
->published()
|
||||||
: null;
|
: null;
|
||||||
@@ -29,6 +29,9 @@ class BlogController extends Controller
|
|||||||
if ($query && $request->has('author') && $request->author) {
|
if ($query && $request->has('author') && $request->author) {
|
||||||
$query = $query->where('author_id', $request->author);
|
$query = $query->where('author_id', $request->author);
|
||||||
}
|
}
|
||||||
|
if ($query && $request->has('intern') && $request->intern) {
|
||||||
|
$query = $query->where('career_application_id', $request->intern);
|
||||||
|
}
|
||||||
|
|
||||||
// Category filtresi
|
// Category filtresi
|
||||||
if ($query && $request->has('category') && $request->category) {
|
if ($query && $request->has('category') && $request->category) {
|
||||||
@@ -130,14 +133,14 @@ class BlogController extends Controller
|
|||||||
if (!$request->ajax()) {
|
if (!$request->ajax()) {
|
||||||
if (class_exists(Blog::class)) {
|
if (class_exists(Blog::class)) {
|
||||||
// Karusel: Öne çıkarılan ya da en güncel 5 yazı
|
// Karusel: Öne çıkarılan ya da en güncel 5 yazı
|
||||||
$carouselPosts = Blog::with(['category', 'author'])
|
$carouselPosts = Blog::with(['category', 'author', 'careerApplication'])
|
||||||
->published()
|
->published()
|
||||||
->featured()
|
->featured()
|
||||||
->latest('published_at')
|
->latest('published_at')
|
||||||
->take(5)
|
->take(5)
|
||||||
->get();
|
->get();
|
||||||
if ($carouselPosts->isEmpty()) {
|
if ($carouselPosts->isEmpty()) {
|
||||||
$carouselPosts = Blog::with(['category', 'author'])
|
$carouselPosts = Blog::with(['category', 'author', 'careerApplication'])
|
||||||
->published()
|
->published()
|
||||||
->latest('published_at')
|
->latest('published_at')
|
||||||
->take(5)
|
->take(5)
|
||||||
@@ -145,7 +148,7 @@ class BlogController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Popüler Yazılar: En çok okunan 3 yazı
|
// Popüler Yazılar: En çok okunan 3 yazı
|
||||||
$popularPosts = Blog::with(['category', 'author'])
|
$popularPosts = Blog::with(['category', 'author', 'careerApplication'])
|
||||||
->published()
|
->published()
|
||||||
->orderBy('view_count', 'desc')
|
->orderBy('view_count', 'desc')
|
||||||
->take(3)
|
->take(3)
|
||||||
@@ -224,14 +227,14 @@ class BlogController extends Controller
|
|||||||
if (!class_exists(Blog::class)) {
|
if (!class_exists(Blog::class)) {
|
||||||
abort(404);
|
abort(404);
|
||||||
}
|
}
|
||||||
$post = Blog::with(['category', 'author'])
|
$post = Blog::with(['category', 'author', 'careerApplication'])
|
||||||
->withCount('comments')
|
->withCount('comments')
|
||||||
->published()
|
->published()
|
||||||
->where('slug', $slug)
|
->where('slug', $slug)
|
||||||
->firstOrFail();
|
->firstOrFail();
|
||||||
|
|
||||||
// İlgili blog gönderilerini al (aynı kategoriden, mevcut gönderi hariç)
|
// İlgili blog gönderilerini al (aynı kategoriden, mevcut gönderi hariç)
|
||||||
$relatedPosts = Blog::with(['category', 'author'])
|
$relatedPosts = Blog::with(['category', 'author', 'careerApplication'])
|
||||||
->withCount('comments')
|
->withCount('comments')
|
||||||
->published()
|
->published()
|
||||||
->where('id', '!=', $post->id)
|
->where('id', '!=', $post->id)
|
||||||
@@ -244,7 +247,7 @@ class BlogController extends Controller
|
|||||||
|
|
||||||
// Eğer aynı kategoriden yeterli gönderi yoksa, diğer kategorilerden ekle
|
// Eğer aynı kategoriden yeterli gönderi yoksa, diğer kategorilerden ekle
|
||||||
if ($relatedPosts->count() < 4) {
|
if ($relatedPosts->count() < 4) {
|
||||||
$additionalPosts = Blog::with(['category', 'author'])
|
$additionalPosts = Blog::with(['category', 'author', 'careerApplication'])
|
||||||
->withCount('comments')
|
->withCount('comments')
|
||||||
->published()
|
->published()
|
||||||
->where('id', '!=', $post->id)
|
->where('id', '!=', $post->id)
|
||||||
|
|||||||
@@ -82,6 +82,36 @@ class Blog extends Model
|
|||||||
return '/blog/' . $this->slug;
|
return '/blog/' . $this->slug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getAuthorNameAttribute()
|
||||||
|
{
|
||||||
|
if ($this->author) {
|
||||||
|
return $this->author->name;
|
||||||
|
}
|
||||||
|
if ($this->careerApplication) {
|
||||||
|
return $this->careerApplication->name;
|
||||||
|
}
|
||||||
|
return __('blog.default_author');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAuthorRoleAttribute()
|
||||||
|
{
|
||||||
|
if ($this->author && $this->author->role) {
|
||||||
|
return $this->author->role;
|
||||||
|
}
|
||||||
|
if ($this->careerApplication) {
|
||||||
|
return 'Stajyer Yazılım Geliştirici';
|
||||||
|
}
|
||||||
|
return 'Trunçgil Teknoloji Editörü';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAuthorAvatarUrlAttribute()
|
||||||
|
{
|
||||||
|
if ($this->author && $this->author->avatar) {
|
||||||
|
return asset('storage/' . $this->author->avatar);
|
||||||
|
}
|
||||||
|
return asset('assets/img/avatars/u5.webp');
|
||||||
|
}
|
||||||
|
|
||||||
public function getFeaturedImageUrlAttribute()
|
public function getFeaturedImageUrlAttribute()
|
||||||
{
|
{
|
||||||
if ($this->featured_image) {
|
if ($this->featured_image) {
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ class BlogStructuredData extends StructuredData
|
|||||||
'inLanguage' => app()->getLocale(),
|
'inLanguage' => app()->getLocale(),
|
||||||
'author' => [
|
'author' => [
|
||||||
'@type' => 'Person',
|
'@type' => 'Person',
|
||||||
'name' => $post->author->name ?? __('blog.default_author'),
|
'name' => $post->author_name,
|
||||||
],
|
],
|
||||||
'publisher' => self::publisherNode(),
|
'publisher' => self::publisherNode(),
|
||||||
'datePublished' => $publishedAt->toIso8601String(),
|
'datePublished' => $publishedAt->toIso8601String(),
|
||||||
|
|||||||
@@ -61,7 +61,9 @@ return [
|
|||||||
|
|
||||||
// Status options
|
// Status options
|
||||||
'status_draft' => 'Draft',
|
'status_draft' => 'Draft',
|
||||||
|
'status_pending' => 'Pending Approval',
|
||||||
'status_published' => 'Published',
|
'status_published' => 'Published',
|
||||||
|
'status_rejected' => 'Revision Requested',
|
||||||
'status_archived' => 'Archived',
|
'status_archived' => 'Archived',
|
||||||
|
|
||||||
// Messages
|
// Messages
|
||||||
|
|||||||
@@ -61,7 +61,9 @@ return [
|
|||||||
|
|
||||||
// Status options
|
// Status options
|
||||||
'status_draft' => 'Taslak',
|
'status_draft' => 'Taslak',
|
||||||
|
'status_pending' => 'Onay Bekliyor',
|
||||||
'status_published' => 'Yayınlandı',
|
'status_published' => 'Yayınlandı',
|
||||||
|
'status_rejected' => 'Revize İstendi',
|
||||||
'status_archived' => 'Arşivlendi',
|
'status_archived' => 'Arşivlendi',
|
||||||
|
|
||||||
// Messages
|
// Messages
|
||||||
|
|||||||
@@ -37,11 +37,11 @@
|
|||||||
<i class="uil uil-calendar-alt pr-[0.2rem] align-[-.05rem] before:content-['\e9ba']"></i>
|
<i class="uil uil-calendar-alt pr-[0.2rem] align-[-.05rem] before:content-['\e9ba']"></i>
|
||||||
<span>{{ $cDate }}</span>
|
<span>{{ $cDate }}</span>
|
||||||
</li>
|
</li>
|
||||||
@if($cPost->author)
|
@if($cPost->author || $cPost->careerApplication)
|
||||||
<li class="post-author inline-block before:content-[''] before:inline-block before:w-[0.2rem] before:h-[0.2rem] before:opacity-50 before:m-[0_.6rem_0] before:rounded-[100%] before:align-[.15rem] before:bg-[#aab0bc]">
|
<li class="post-author inline-block before:content-[''] before:inline-block before:w-[0.2rem] before:h-[0.2rem] before:opacity-50 before:m-[0_.6rem_0] before:rounded-[100%] before:align-[.15rem] before:bg-[#aab0bc]">
|
||||||
<span class="!text-[#aab0bc]">
|
<span class="!text-[#aab0bc]">
|
||||||
<i class="uil uil-user pr-[0.2rem] align-[-.05rem] before:content-['\ed6f']"></i>
|
<i class="uil uil-user pr-[0.2rem] align-[-.05rem] before:content-['\ed6f']"></i>
|
||||||
<span>{{ $cPost->author->name }}</span>
|
<span>{{ $cPost->author_name }}</span>
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
@endif
|
@endif
|
||||||
@@ -349,7 +349,7 @@
|
|||||||
"datePublished" => $p->published_at ? $p->published_at->toIso8601String() : $p->created_at->toIso8601String(),
|
"datePublished" => $p->published_at ? $p->published_at->toIso8601String() : $p->created_at->toIso8601String(),
|
||||||
"author" => [
|
"author" => [
|
||||||
"@type" => "Person",
|
"@type" => "Person",
|
||||||
"name" => $p->author ? $p->author->name : 'Trunçgil'
|
"name" => $p->author_name
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
<li class="post-author inline-block before:content-[''] before:inline-block before:w-[0.2rem] before:h-[0.2rem] before:opacity-50 before:m-[0_.6rem_0_.4rem] before:rounded-[100%] before:align-[.15rem] before:bg-[#aab0bc]">
|
<li class="post-author inline-block before:content-[''] before:inline-block before:w-[0.2rem] before:h-[0.2rem] before:opacity-50 before:m-[0_.6rem_0_.4rem] before:rounded-[100%] before:align-[.15rem] before:bg-[#aab0bc]">
|
||||||
<span class="!text-[0.8rem] !text-[#aab0bc]">
|
<span class="!text-[0.8rem] !text-[#aab0bc]">
|
||||||
<i class="uil uil-user pr-[0.2rem] align-[-.05rem] before:content-['\ed6f']"></i>
|
<i class="uil uil-user pr-[0.2rem] align-[-.05rem] before:content-['\ed6f']"></i>
|
||||||
<span>{{ $post->author ? $post->author->name : 'Trunçgil' }}</span>
|
<span>{{ $post->author_name }}</span>
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -84,15 +84,15 @@
|
|||||||
<div class="author-info xl:!flex lg:!flex md:!flex items-center !mb-3">
|
<div class="author-info xl:!flex lg:!flex md:!flex items-center !mb-3">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<figure class="w-12 h-12 !relative !mr-4 rounded-[100%]">
|
<figure class="w-12 h-12 !relative !mr-4 rounded-[100%]">
|
||||||
<img class="rounded-[50%]" alt="image" src="{{ $post->author && $post->author->avatar ? asset('storage/' . $post->author->avatar) : asset('assets/img/avatars/u5.webp') }}" onerror="this.src='{{ asset('assets/img/avatars/u5.webp') }}'" loading="lazy">
|
<img class="rounded-[50%]" alt="image" src="{{ $post->author_avatar_url }}" onerror="this.src='{{ asset('assets/img/avatars/u5.webp') }}'" loading="lazy">
|
||||||
</figure>
|
</figure>
|
||||||
<div>
|
<div>
|
||||||
<h6><a href="#" class="!text-[#343f52] hover:!text-[#e31e24]">{{ $post->author ? $post->author->name : 'Trunçgil' }}</a></h6>
|
<h6><a href="#" class="!text-[#343f52] hover:!text-[#e31e24]">{{ $post->author_name }}</a></h6>
|
||||||
<span class="!text-[0.75rem] !text-[#aab0bc] m-0 p-0 list-none">{{ $post->author && $post->author->role ? $post->author->role : 'Trunçgil Teknoloji Editörü' }}</span>
|
<span class="!text-[0.75rem] !text-[#aab0bc] m-0 p-0 list-none">{{ $post->author_role }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="!mt-3 xl:!mt-0 lg:!mt-0 md:!mt-0 !ml-auto">
|
<div class="!mt-3 xl:!mt-0 lg:!mt-0 md:!mt-0 !ml-auto">
|
||||||
<a href="{{ route('blog.index', ['author' => $post->author_id]) }}" class="btn btn-sm btn-soft-ash !rounded-[50rem] btn-icon btn-icon-start !mb-0 hover:translate-y-[-0.15rem] hover:shadow-[0_0.25rem_0.75rem_rgba(30,34,40,0.15)]"><i class="uil uil-file-alt !mr-[0.3rem] before:content-['\eaec'] text-[.8rem]"></i> Tüm Yazıları</a>
|
<a href="{{ $post->author_id ? route('blog.index', ['author' => $post->author_id]) : ($post->career_application_id ? route('blog.index', ['intern' => $post->career_application_id]) : route('blog.index')) }}" class="btn btn-sm btn-soft-ash !rounded-[50rem] btn-icon btn-icon-start !mb-0 hover:translate-y-[-0.15rem] hover:shadow-[0_0.25rem_0.75rem_rgba(30,34,40,0.15)]"><i class="uil uil-file-alt !mr-[0.3rem] before:content-['\eaec'] text-[.8rem]"></i> Tüm Yazıları</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>Trunçgil Teknoloji editörleri tarafından kaleme alınmış bu makalede teknoloji, yazılım geliştirme ve dijital dönüşüm konularına dair güncel gelişmeleri incelediniz. Destek ve sorularınız için bizimle iletişime geçebilirsiniz.</p>
|
<p>Trunçgil Teknoloji editörleri tarafından kaleme alınmış bu makalede teknoloji, yazılım geliştirme ve dijital dönüşüm konularına dair güncel gelişmeleri incelediniz. Destek ve sorularınız için bizimle iletişime geçebilirsiniz.</p>
|
||||||
@@ -181,9 +181,9 @@
|
|||||||
$publishedDate = $post->published_at ? $post->published_at->toIso8601String() : $post->created_at->toIso8601String();
|
$publishedDate = $post->published_at ? $post->published_at->toIso8601String() : $post->created_at->toIso8601String();
|
||||||
$modifiedDate = $post->updated_at ? $post->updated_at->toIso8601String() : $publishedDate;
|
$modifiedDate = $post->updated_at ? $post->updated_at->toIso8601String() : $publishedDate;
|
||||||
|
|
||||||
$authorName = $post->author ? $post->author->name : 'Trunçgil';
|
$authorName = $post->author_name;
|
||||||
$authorRole = $post->author && $post->author->role ? $post->author->role : 'Trunçgil Teknoloji Editörü';
|
$authorRole = $post->author_role;
|
||||||
$authorUrl = route('blog.index', ['author' => $post->author_id ?? 1]);
|
$authorUrl = $post->author_id ? route('blog.index', ['author' => $post->author_id]) : ($post->career_application_id ? route('blog.index', ['intern' => $post->career_application_id]) : route('blog.index'));
|
||||||
|
|
||||||
$siteName = setting('site_name', 'Trunçgil Teknoloji');
|
$siteName = setting('site_name', 'Trunçgil Teknoloji');
|
||||||
$siteLogo = setting('site_logo') ? (str_starts_with(setting('site_logo'), 'http') ? setting('site_logo') : asset('storage/' . ltrim(setting('site_logo'), '/'))) : asset('assets/img/logo.png');
|
$siteLogo = setting('site_logo') ? (str_starts_with(setting('site_logo'), 'http') ? setting('site_logo') : asset('storage/' . ltrim(setting('site_logo'), '/'))) : asset('assets/img/logo.png');
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
@php
|
@php
|
||||||
// Blog modelinden published içerikleri çek
|
// Blog modelinden published içerikleri çek
|
||||||
$blogs = \App\Models\Blog::with(['category', 'author'])
|
$blogs = \App\Models\Blog::with(['category', 'author', 'careerApplication'])
|
||||||
->withCount('comments')
|
->withCount('comments')
|
||||||
->published()
|
->published()
|
||||||
->latest('published_at')
|
->latest('published_at')
|
||||||
|
|||||||
Reference in New Issue
Block a user