207 lines
5.7 KiB
PHP
207 lines
5.7 KiB
PHP
<?php
|
|
|
|
namespace App\Repositories;
|
|
|
|
use App\Models\Job;
|
|
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
|
use Illuminate\Database\Eloquent\Collection;
|
|
|
|
class JobRepository
|
|
{
|
|
/**
|
|
* Get all active jobs with pagination
|
|
*/
|
|
public function getActiveJobs(int $perPage = 15): LengthAwarePaginator
|
|
{
|
|
return Job::with(['source', 'category', 'jobLocation'])
|
|
->active()
|
|
->latest('posted_at')
|
|
->paginate($perPage);
|
|
}
|
|
|
|
/**
|
|
* Find a job by ID
|
|
*/
|
|
public function find(int $id): ?Job
|
|
{
|
|
return Job::with(['source', 'category', 'jobLocation'])->find($id);
|
|
}
|
|
|
|
/**
|
|
* Get jobs by category
|
|
*/
|
|
public function getByCategory(int $categoryId, int $perPage = 15): LengthAwarePaginator
|
|
{
|
|
return Job::with(['source', 'category', 'jobLocation'])
|
|
->active()
|
|
->where('job_category_id', $categoryId)
|
|
->latest('posted_at')
|
|
->paginate($perPage);
|
|
}
|
|
|
|
/**
|
|
* Get jobs by location
|
|
*/
|
|
public function getByLocation(int $locationId, int $perPage = 15): LengthAwarePaginator
|
|
{
|
|
return Job::with(['source', 'category', 'jobLocation'])
|
|
->active()
|
|
->where('job_location_id', $locationId)
|
|
->latest('posted_at')
|
|
->paginate($perPage);
|
|
}
|
|
|
|
/**
|
|
* Get remote jobs
|
|
*/
|
|
public function getRemoteJobs(int $perPage = 15): LengthAwarePaginator
|
|
{
|
|
return Job::with(['source', 'category', 'jobLocation'])
|
|
->active()
|
|
->remote()
|
|
->latest('posted_at')
|
|
->paginate($perPage);
|
|
}
|
|
|
|
/**
|
|
* Get recent jobs (last N days)
|
|
*/
|
|
public function getRecentJobs(int $days = 7, int $perPage = 15): LengthAwarePaginator
|
|
{
|
|
return Job::with(['source', 'category', 'jobLocation'])
|
|
->active()
|
|
->where(function ($query) use ($days) {
|
|
$query->where('posted_at', '>=', now()->subDays($days))
|
|
->orWhere(function ($q) use ($days) {
|
|
$q->whereNull('posted_at')
|
|
->where('created_at', '>=', now()->subDays($days));
|
|
});
|
|
})
|
|
->latest('posted_at')
|
|
->paginate($perPage);
|
|
}
|
|
|
|
/**
|
|
* Get jobs by experience level
|
|
*/
|
|
public function getByExperienceLevel(string $level, int $perPage = 15): LengthAwarePaginator
|
|
{
|
|
return Job::with(['source', 'category', 'jobLocation'])
|
|
->active()
|
|
->experienceLevel($level)
|
|
->latest('posted_at')
|
|
->paginate($perPage);
|
|
}
|
|
|
|
/**
|
|
* Get jobs by type
|
|
*/
|
|
public function getByJobType(string $type, int $perPage = 15): LengthAwarePaginator
|
|
{
|
|
return Job::with(['source', 'category', 'jobLocation'])
|
|
->active()
|
|
->ofType($type)
|
|
->latest('posted_at')
|
|
->paginate($perPage);
|
|
}
|
|
|
|
/**
|
|
* Get similar jobs (same category, exclude current)
|
|
*/
|
|
public function getSimilarJobs(Job $job, int $limit = 5): Collection
|
|
{
|
|
return Job::with(['source', 'category', 'jobLocation'])
|
|
->active()
|
|
->where('id', '!=', $job->id)
|
|
->where('job_category_id', $job->job_category_id)
|
|
->latest('posted_at')
|
|
->limit($limit)
|
|
->get();
|
|
}
|
|
|
|
/**
|
|
* Get featured jobs (most recent from diverse sources)
|
|
*/
|
|
public function getFeaturedJobs(int $limit = 10): Collection
|
|
{
|
|
return Job::with(['source', 'category', 'jobLocation'])
|
|
->active()
|
|
->select('jobs.*')
|
|
->selectRaw('ROW_NUMBER() OVER (PARTITION BY job_source_id ORDER BY posted_at DESC) as rn')
|
|
->fromSub(function ($query) {
|
|
$query->from('jobs')
|
|
->whereNull('deleted_at')
|
|
->whereNull('expires_at')
|
|
->orWhere('expires_at', '>', now());
|
|
}, 'jobs')
|
|
->havingRaw('rn <= 2') // Max 2 jobs per source
|
|
->latest('posted_at')
|
|
->limit($limit)
|
|
->get();
|
|
}
|
|
|
|
/**
|
|
* Get job statistics
|
|
*/
|
|
public function getStatistics(): array
|
|
{
|
|
$total = Job::count();
|
|
$active = Job::active()->count();
|
|
$remote = Job::active()->remote()->count();
|
|
$recentlyAdded = Job::where('created_at', '>=', now()->subDays(7))->count();
|
|
|
|
$topCategories = Job::active()
|
|
->select('job_category_id', \DB::raw('COUNT(*) as count'))
|
|
->whereNotNull('job_category_id')
|
|
->groupBy('job_category_id')
|
|
->orderBy('count', 'desc')
|
|
->limit(5)
|
|
->with('category')
|
|
->get();
|
|
|
|
return [
|
|
'total_jobs' => $total,
|
|
'active_jobs' => $active,
|
|
'remote_jobs' => $remote,
|
|
'recently_added' => $recentlyAdded,
|
|
'top_categories' => $topCategories,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Create a new job
|
|
*/
|
|
public function create(array $data): Job
|
|
{
|
|
return Job::create($data);
|
|
}
|
|
|
|
/**
|
|
* Update a job
|
|
*/
|
|
public function update(Job $job, array $data): bool
|
|
{
|
|
return $job->update($data);
|
|
}
|
|
|
|
/**
|
|
* Delete a job
|
|
*/
|
|
public function delete(Job $job): bool
|
|
{
|
|
return $job->delete();
|
|
}
|
|
|
|
/**
|
|
* Get jobs count by source
|
|
*/
|
|
public function getCountBySource(): Collection
|
|
{
|
|
return Job::with('source')
|
|
->select('job_source_id', \DB::raw('COUNT(*) as count'))
|
|
->groupBy('job_source_id')
|
|
->orderBy('count', 'desc')
|
|
->get();
|
|
}
|
|
}
|