Files
citrus/app/Http/Controllers/CareerController.php
T

423 lines
16 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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.job_application_title', ['default' => 'İş Başvurusu']),
'description' => __('career.job_application_description', ['default' => 'Ekibimize katılmak için aşağıdaki formu doldurarak CV\'nizi iletebilirsiniz.']),
]
]);
}
public function internship()
{
return view('front.career.internship', [
'meta' => [
'title' => __('career.internship_title', ['default' => 'Staj Başvurusu']),
'description' => __('career.internship_description', ['default' => 'Uzaktan staj programımız hakkında bilgi alın ve başvurunuzu yapın.']),
]
]);
}
public function store(Request $request)
{
$rules = [
'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',
];
if ($request->type === 'job') {
$rules['nda'] = 'required|file|mimes:pdf|max:5120';
$rules['contract'] = 'required|file|mimes:pdf|max:5120';
$rules['id_photocopy'] = 'required|file|mimes:pdf,jpg,jpeg,png|max:5120'; // Max 5MB
$rules['git_knowledge'] = 'accepted';
$rules['ai_usage'] = 'accepted';
}
$request->validate($rules);
$cvPath = $request->file('cv') ? $request->file('cv')->store('cvs', 'public') : null;
$ndaPath = $request->file('nda') ? $request->file('nda')->store('ndas', 'public') : null;
$contractPath = $request->file('contract') ? $request->file('contract')->store('contracts', 'public') : null;
$idPhotocopyPath = $request->file('id_photocopy') ? $request->file('id_photocopy')->store('id_photocopies', 'public') : null;
CareerApplication::create([
'name' => $request->name,
'email' => $request->email,
'phone' => $request->phone,
'type' => $request->type ?? 'job',
'cv_path' => $cvPath,
'nda_path' => $ndaPath,
'contract_path' => $contractPath,
'id_photocopy_path' => $idPhotocopyPath,
'git_knowledge' => $request->has('git_knowledge'),
'ai_usage' => $request->has('ai_usage'),
'message' => $request->message,
'status' => 'pending',
]);
if ($request->ajax()) {
return response()->json([
'success' => true,
'message' => __('career.success_message')
]);
}
return redirect()->back()->with('success', __('career.success_message'));
}
public function internLoginForm()
{
if (session()->has('intern_id')) {
return redirect()->route('intern.dashboard');
}
return view('front.career.intern_login', [
'meta' => [
'title' => 'Stajyer Girişi',
'description' => 'İmzalı staj belgelerinize erişmek için lütfen giriş yapın.',
]
]);
}
public function internLogin(Request $request)
{
$request->validate([
'username' => 'required|string',
'password' => 'required|string',
]);
$intern = CareerApplication::where('username', $request->username)
->where('type', 'internship')
->first();
if (!$intern || !\Illuminate\Support\Facades\Hash::check($request->password, $intern->password)) {
return redirect()->back()
->withInput($request->only('username'))
->withErrors([
'username' => 'Girdiğiniz kullanıcı adı veya şifre hatalı.',
]);
}
session(['intern_id' => $intern->id]);
return redirect()->route('intern.dashboard')->with('success', 'Başarıyla giriş yapıldı.');
}
public function internDashboard()
{
if (!session()->has('intern_id')) {
return redirect()->route('intern.login')->with('error', 'Lütfen giriş yapın.');
}
$intern = CareerApplication::findOrFail(session('intern_id'));
return view('front.career.intern_dashboard', [
'intern' => $intern,
'meta' => [
'title' => 'Stajyer Paneli',
'description' => 'Belgelerinizi buradan indirebilirsiniz.',
]
]);
}
public function uploadInternshipForm(Request $request)
{
if (!session()->has('intern_id')) {
return redirect()->route('intern.login')->with('error', 'Lütfen önce giriş yapın.');
}
$request->validate([
'internship_form' => 'required|file|mimes:pdf,docx,jpg,png,jpeg|max:51200',
'internship_start_date' => 'required|date',
'internship_total_days' => 'required|integer|min:1',
], [
'internship_form.required' => 'Lütfen bir dosya seçin.',
'internship_form.file' => 'Yüklenen öğe geçerli bir dosya olmalıdır.',
'internship_form.mimes' => 'Yalnızca PDF, DOCX, JPG ve PNG formatındaki dosyalar kabul edilir.',
'internship_form.max' => 'Dosya boyutu en fazla 50MB olabilir.',
'internship_start_date.required' => 'Lütfen staj başlangıç tarihini girin.',
'internship_start_date.date' => 'Geçerli bir başlangıç tarihi girin.',
'internship_total_days.required' => 'Lütfen staj süresini girin.',
'internship_total_days.integer' => 'Staj süresi geçerli bir tam sayı olmalıdır.',
'internship_total_days.min' => 'Staj süresi en az 1 gün olmalıdır.',
]);
$intern = CareerApplication::findOrFail(session('intern_id'));
if ($request->hasFile('internship_form')) {
// Delete old file if exists
if ($intern->to_be_signed_internship_form_path) {
Storage::disk('public')->delete($intern->to_be_signed_internship_form_path);
}
$path = $request->file('internship_form')->store('to_be_signed_interns', 'public');
// Calculate end date based on weekdays and duration
$startDate = \Carbon\Carbon::parse($request->internship_start_date);
$daysToAdd = intval($request->internship_total_days);
$endDate = $startDate->copy();
$count = 0;
$temp = $startDate->copy();
while ($count < $daysToAdd) {
if ($temp->isWeekend()) {
$temp->addDay();
continue;
}
$endDate = $temp->copy();
$temp->addDay();
$count++;
}
$intern->update([
'to_be_signed_internship_form_path' => $path,
'internship_start_date' => $request->internship_start_date,
'internship_end_date' => $endDate->format('Y-m-d'),
'internship_total_days' => $daysToAdd,
'status' => 'waiting_document',
]);
return redirect()->back()->with('success', 'İmzalanacak staj formunuz ve staj tarihleri başarıyla kaydedildi.');
}
return redirect()->back()->with('error', 'Dosya yüklenirken bir hata oluştu.');
}
public function saveGithubRepo(Request $request)
{
if (!session()->has('intern_id')) {
return redirect()->route('intern.login')->with('error', 'Lütfen önce giriş yapın.');
}
$request->validate([
'github_repo' => 'required|string|url|max:255',
], [
'github_repo.required' => 'Lütfen Github depo URL\'sini girin.',
'github_repo.url' => 'Geçerli bir URL girilmelidir.',
'github_repo.max' => 'Github depo URL\'si en fazla 255 karakter olabilir.',
]);
$intern = CareerApplication::findOrFail(session('intern_id'));
// Sanitize & format github URL
$repoUrl = trim($request->github_repo);
$intern->update([
'github_repo' => $repoUrl
]);
return redirect()->back()->with('success', 'Github deposu başarıyla güncellendi.');
}
public function downloadMarkdown()
{
if (request()->has('intern_id') && auth()->check() && auth()->user()->hasRole('super_admin')) {
$internId = request('intern_id');
} else {
if (!session()->has('intern_id')) {
return redirect()->route('intern.login')->with('error', 'Lütfen önce giriş yapın.');
}
$internId = session('intern_id');
}
$intern = CareerApplication::findOrFail($internId);
$repo = $intern->github_repo;
if (!$repo) {
return redirect()->back()->with('error', 'Lütfen önce Github deposunu tanımlayın.');
}
// Parse owner and repo
// E.g., https://github.com/owner/repo or owner/repo
$repoClean = str_replace(['https://github.com/', 'http://github.com/', 'https://www.github.com/', 'http://www.github.com/'], '', $repo);
$repoClean = trim($repoClean, '/');
$parts = explode('/', $repoClean);
if (count($parts) < 2) {
return redirect()->back()->with('error', 'Geçersiz Github depo formatı.');
}
$owner = $parts[0];
$repoName = explode('.', $parts[1])[0]; // Remove .git if exists
// Fetch commits
$url = "https://api.github.com/repos/{$owner}/{$repoName}/commits?per_page=100";
$opts = [
'http' => [
'method' => 'GET',
'header' => [
'User-Agent: PHP-Github-Client',
]
]
];
$context = stream_context_create($opts);
$response = @file_get_contents($url, false, $context);
if ($response === false) {
return redirect()->back()->with('error', 'Github API\'den commit bilgileri alınamadı. Deponuzun public olduğundan emin olun.');
}
$commits = json_decode($response, true);
if (!is_array($commits)) {
return redirect()->back()->with('error', 'Github API yanıtı çözümlenemedi.');
}
// Sort commits chronological (ascending)
$commits = array_reverse($commits);
// Group commits by date (YYYY-MM-DD)
$grouped = [];
foreach ($commits as $c) {
$dateStr = $c['commit']['author']['date'] ?? '';
if ($dateStr) {
$dateOnly = \Carbon\Carbon::parse($dateStr)->format('Y-m-d');
$grouped[$dateOnly][] = $c;
}
}
// Sort dates chronological (ascending)
ksort($grouped);
// Generate Markdown content
$md = "# Staj Günlüğü - " . $intern->name . "\n";
$md .= "Depo: https://github.com/{$owner}/{$repoName}\n\n";
$day = 1;
foreach ($grouped as $date => $dayCommits) {
$formattedDate = \Carbon\Carbon::parse($date)->format('d.m.Y');
$md .= "## {$day}. Gün ({$formattedDate})\n";
foreach ($dayCommits as $c) {
$message = trim($c['commit']['message'] ?? '');
$time = \Carbon\Carbon::parse($c['commit']['author']['date'] ?? '')->format('H:i');
$hash = substr($c['sha'] ?? '', 0, 7);
$md .= "- [{$time}] `{$hash}`: {$message}\n";
}
$md .= "\n";
$day++;
}
$fileName = str()->slug($intern->name) . "-staj-gunlugu.md";
return response($md, 200, [
'Content-Type' => 'text/markdown; charset=UTF-8',
'Content-Disposition' => 'attachment; filename="' . $fileName . '"',
]);
}
public function internLogout()
{
session()->forget('intern_id');
return redirect()->route('intern.login')->with('success', 'Başarıyla çıkış yapıldı.');
}
public function verifyCertificate($code)
{
$application = CareerApplication::where('certificate_code', $code)
->where('type', 'internship')
->firstOrFail();
return view('front.career.verify', [
'application' => $application,
'meta' => [
'title' => 'Staj Bitirme Sertifikası Doğrulama - ' . $application->name,
'description' => $application->name . ' isimli stajyerimizin staj bitirme sertifikası ve performans raporu doğrulama sayfası.',
]
]);
}
public function internAdminLoginForm()
{
if (auth()->check() && auth()->user()->hasRole('super_admin')) {
return redirect()->route('intern.admin.dashboard');
}
return view('front.career.admin_login', [
'meta' => [
'title' => 'Yönetici Girişi - Staj Takip',
'description' => 'Stajyerleri yönetmek için giriş yapın.',
]
]);
}
public function internAdminLogin(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required|string',
]);
if (auth()->attempt($request->only('email', 'password'))) {
if (auth()->user()->hasRole('super_admin')) {
return redirect()->route('intern.admin.dashboard')->with('success', 'Yönetici girişi başarıyla gerçekleştirildi.');
}
auth()->logout();
return redirect()->back()
->withInput($request->only('email'))
->withErrors([
'email' => 'Bu panele erişmek için super_admin yetkinizin olması gerekir.',
]);
}
return redirect()->back()
->withInput($request->only('email'))
->withErrors([
'email' => 'Girdiğiniz bilgiler eşleşmedi veya hatalı.',
]);
}
public function internAdminDashboard()
{
if (!auth()->check() || !auth()->user()->hasRole('super_admin')) {
return redirect()->route('intern.admin.login')->with('error', 'Lütfen önce yönetici olarak giriş yapın.');
}
$allInterns = CareerApplication::where('type', 'internship')
->orderBy('created_at', 'desc')
->get();
$ganttInterns = CareerApplication::where('type', 'internship')
->where('status', 'accepted')
->whereNotNull('internship_start_date')
->whereNotNull('internship_end_date')
->orderBy('internship_start_date', 'asc')
->get()
->map(function ($intern) {
return [
'id' => $intern->id,
'parentId' => 0,
'title' => $intern->name,
'start' => $intern->internship_start_date,
'end' => $intern->internship_end_date,
'progress' => 100
];
});
return view('front.career.admin_dashboard', [
'allInterns' => $allInterns,
'ganttInterns' => $ganttInterns,
'meta' => [
'title' => 'Staj Yönetici Paneli',
'description' => 'Stajyer bilgilerini ve takvimlerini izleyin.',
]
]);
}
public function internAdminLogout()
{
auth()->logout();
return redirect()->route('intern.admin.login')->with('success', 'Yönetici oturumu sonlandırıldı.');
}
}