phase 4
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
<?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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user