[ '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 (!session()->has('intern_id')) { return redirect()->route('intern.login')->with('error', 'Lütfen önce giriş yapın.'); } $intern = CareerApplication::findOrFail(session('intern_id')); $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ı.', ] ]); } }