feat: add NDA/contract file uploads and technical skill checkboxes to career applications
This commit is contained in:
@@ -52,6 +52,18 @@ class CareerApplicationsTable
|
|||||||
default => 'gray',
|
default => 'gray',
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
TextColumn::make('git_knowledge')
|
||||||
|
->label(__('career.git_knowledge'))
|
||||||
|
->badge()
|
||||||
|
->color(fn ($state) => $state ? 'success' : 'danger')
|
||||||
|
->formatStateUsing(fn ($state) => $state ? 'Evet' : 'Hayır'),
|
||||||
|
|
||||||
|
TextColumn::make('ai_usage')
|
||||||
|
->label(__('career.ai_usage'))
|
||||||
|
->badge()
|
||||||
|
->color(fn ($state) => $state ? 'success' : 'danger')
|
||||||
|
->formatStateUsing(fn ($state) => $state ? 'Evet' : 'Hayır'),
|
||||||
|
|
||||||
TextColumn::make('created_at')
|
TextColumn::make('created_at')
|
||||||
->label(__('career.created_at'))
|
->label(__('career.created_at'))
|
||||||
->dateTime('d.m.Y H:i')
|
->dateTime('d.m.Y H:i')
|
||||||
@@ -79,6 +91,18 @@ class CareerApplicationsTable
|
|||||||
->icon('heroicon-o-arrow-down-tray')
|
->icon('heroicon-o-arrow-down-tray')
|
||||||
->url(fn ($record) => Storage::disk('public')->url($record->cv_path))
|
->url(fn ($record) => Storage::disk('public')->url($record->cv_path))
|
||||||
->openUrlInNewTab(),
|
->openUrlInNewTab(),
|
||||||
|
Action::make('download_nda')
|
||||||
|
->label(__('career.nda'))
|
||||||
|
->icon('heroicon-o-shield-check')
|
||||||
|
->url(fn ($record) => $record->nda_path ? Storage::disk('public')->url($record->nda_path) : null)
|
||||||
|
->visible(fn ($record) => $record->nda_path !== null)
|
||||||
|
->openUrlInNewTab(),
|
||||||
|
Action::make('download_contract')
|
||||||
|
->label(__('career.contract'))
|
||||||
|
->icon('heroicon-o-document-text')
|
||||||
|
->url(fn ($record) => $record->contract_path ? Storage::disk('public')->url($record->contract_path) : null)
|
||||||
|
->visible(fn ($record) => $record->contract_path !== null)
|
||||||
|
->openUrlInNewTab(),
|
||||||
DeleteAction::make(),
|
DeleteAction::make(),
|
||||||
])
|
])
|
||||||
->bulkActions([
|
->bulkActions([
|
||||||
|
|||||||
@@ -30,25 +30,37 @@ class CareerController extends Controller
|
|||||||
|
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$rules = [
|
||||||
'name' => 'required|string|max:255',
|
'name' => 'required|string|max:255',
|
||||||
'email' => 'required|email|max:255',
|
'email' => 'required|email|max:255',
|
||||||
'phone' => 'nullable|string|max:20',
|
'phone' => 'nullable|string|max:20',
|
||||||
'cv' => 'required|file|mimes:pdf,doc,docx|max:5120', // Max 5MB
|
'cv' => 'required|file|mimes:pdf,doc,docx|max:5120', // Max 5MB
|
||||||
'message' => 'nullable|string',
|
'message' => 'nullable|string',
|
||||||
]);
|
];
|
||||||
|
|
||||||
$cvPath = null;
|
if ($request->type === 'job') {
|
||||||
if ($request->hasFile('cv')) {
|
$rules['nda'] = 'required|file|mimes:pdf|max:5120';
|
||||||
$cvPath = $request->file('cv')->store('cvs', 'public');
|
$rules['contract'] = 'required|file|mimes:pdf|max:5120';
|
||||||
|
$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;
|
||||||
|
|
||||||
CareerApplication::create([
|
CareerApplication::create([
|
||||||
'name' => $request->name,
|
'name' => $request->name,
|
||||||
'email' => $request->email,
|
'email' => $request->email,
|
||||||
'phone' => $request->phone,
|
'phone' => $request->phone,
|
||||||
'type' => $request->type ?? 'job',
|
'type' => $request->type ?? 'job',
|
||||||
'cv_path' => $cvPath,
|
'cv_path' => $cvPath,
|
||||||
|
'nda_path' => $ndaPath,
|
||||||
|
'contract_path' => $contractPath,
|
||||||
|
'git_knowledge' => $request->has('git_knowledge'),
|
||||||
|
'ai_usage' => $request->has('ai_usage'),
|
||||||
'message' => $request->message,
|
'message' => $request->message,
|
||||||
'status' => 'pending',
|
'status' => 'pending',
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ class CareerApplication extends Model
|
|||||||
'phone',
|
'phone',
|
||||||
'type',
|
'type',
|
||||||
'cv_path',
|
'cv_path',
|
||||||
|
'nda_path',
|
||||||
|
'contract_path',
|
||||||
|
'git_knowledge',
|
||||||
|
'ai_usage',
|
||||||
'message',
|
'message',
|
||||||
'status',
|
'status',
|
||||||
];
|
];
|
||||||
|
|||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('career_applications', function (Blueprint $table) {
|
||||||
|
$table->string('nda_path')->nullable()->after('cv_path');
|
||||||
|
$table->string('contract_path')->nullable()->after('nda_path');
|
||||||
|
$table->boolean('git_knowledge')->default(false)->after('contract_path');
|
||||||
|
$table->boolean('ai_usage')->default(false)->after('git_knowledge');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('career_applications', function (Blueprint $table) {
|
||||||
|
$table->dropColumn(['nda_path', 'contract_path', 'git_knowledge', 'ai_usage']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -22,6 +22,10 @@ return [
|
|||||||
'submit' => 'Başvuruyu Gönder',
|
'submit' => 'Başvuruyu Gönder',
|
||||||
'success_message' => 'Başvurunuz başarıyla alındı. Teşekkür ederiz.',
|
'success_message' => 'Başvurunuz başarıyla alındı. Teşekkür ederiz.',
|
||||||
'download_cv' => 'CV İndir',
|
'download_cv' => 'CV İndir',
|
||||||
|
'nda' => 'İmzalı NDA',
|
||||||
|
'contract' => 'İmzalı Sözleşme',
|
||||||
|
'git_knowledge' => 'GIT Bilgisi',
|
||||||
|
'ai_usage' => 'AI Araçları Kullanımı',
|
||||||
'created_at' => 'Başvuru Tarihi',
|
'created_at' => 'Başvuru Tarihi',
|
||||||
'remote_work_title' => 'Tamamen Uzaktan Çalışma',
|
'remote_work_title' => 'Tamamen Uzaktan Çalışma',
|
||||||
'remote_work_details' => 'Günlük standup toplantıları ile ekip koordinasyonu sağlanır. Bazı projelerde çalışma saatleri daha esnektir. Stajyerler, CV\'lerine ve yetkinliklerine uygun olan bir veya birden fazla gerçek projede değerlendirilir.',
|
'remote_work_details' => 'Günlük standup toplantıları ile ekip koordinasyonu sağlanır. Bazı projelerde çalışma saatleri daha esnektir. Stajyerler, CV\'lerine ve yetkinliklerine uygun olan bir veya birden fazla gerçek projede değerlendirilir.',
|
||||||
|
|||||||
@@ -119,10 +119,39 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-12 gap-6 items-center">
|
<div class="grid grid-cols-1 md:grid-cols-12 gap-6 items-center">
|
||||||
<label for="cv" class="md:col-span-3 text-sm font-bold text-slate-700 md:text-right">{{ __('career.cv', ['default' => 'Özgeçmiş ve İmzalı Belgeler']) }} <span class="text-[#e31e24]">*</span></label>
|
<label for="cv" class="md:col-span-3 text-sm font-bold text-slate-700 md:text-right">{{ __('career.cv', ['default' => 'Özgeçmiş (CV)']) }} <span class="text-[#e31e24]">*</span></label>
|
||||||
<div class="md:col-span-9">
|
<div class="md:col-span-9">
|
||||||
<input type="file" name="cv" id="cv" class="w-full px-5 py-2.5 rounded-xl border border-slate-200 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-xs file:font-semibold file:bg-red-50 file:text-[#e31e24] hover:file:bg-red-100 transition-all" required>
|
<input type="file" name="cv" id="cv" class="w-full px-5 py-2.5 rounded-xl border border-slate-200 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-xs file:font-semibold file:bg-red-50 file:text-[#e31e24] hover:file:bg-red-100 transition-all" required>
|
||||||
<p class="mt-2 text-xs text-slate-400">PDF veya ZIP (Maks. 5MB). Lütfen CV ve imzalı NDA/Sözleşme belgelerini yükleyiniz.</p>
|
<p class="mt-2 text-xs text-slate-400">PDF, DOC, DOCX (Maks. 5MB)</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-12 gap-6 items-center">
|
||||||
|
<label for="nda" class="md:col-span-3 text-sm font-bold text-slate-700 md:text-right">{{ __('career.nda') }} <span class="text-[#e31e24]">*</span></label>
|
||||||
|
<div class="md:col-span-9">
|
||||||
|
<input type="file" name="nda" id="nda" class="w-full px-5 py-2.5 rounded-xl border border-slate-200 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-xs file:font-semibold file:bg-red-50 file:text-[#e31e24] hover:file:bg-red-100 transition-all" required>
|
||||||
|
<p class="mt-2 text-xs text-slate-400">İmzalanmış Gizlilik Sözleşmesi (PDF, Maks. 5MB)</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-12 gap-6 items-center">
|
||||||
|
<label for="contract" class="md:col-span-3 text-sm font-bold text-slate-700 md:text-right">{{ __('career.contract') }} <span class="text-[#e31e24]">*</span></label>
|
||||||
|
<div class="md:col-span-9">
|
||||||
|
<input type="file" name="contract" id="contract" class="w-full px-5 py-2.5 rounded-xl border border-slate-200 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-xs file:font-semibold file:bg-red-50 file:text-[#e31e24] hover:file:bg-red-100 transition-all" required>
|
||||||
|
<p class="mt-2 text-xs text-slate-400">İmzalanmış Bağımsız Sözleşmeli Sözleşmesi (PDF, Maks. 5MB)</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-12 gap-6">
|
||||||
|
<div class="md:col-start-4 md:col-span-9 space-y-4">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<input type="checkbox" name="git_knowledge" id="git_knowledge" class="w-5 h-5 rounded border-slate-300 text-[#e31e24] focus:ring-[#e31e24]" required>
|
||||||
|
<label for="git_knowledge" class="text-sm text-slate-700 font-medium">GIT versiyon kontrol sistemini kullanmayı biliyorum. <span class="text-[#e31e24]">*</span></label>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<input type="checkbox" name="ai_usage" id="ai_usage" class="w-5 h-5 rounded border-slate-300 text-[#e31e24] focus:ring-[#e31e24]" required>
|
||||||
|
<label for="ai_usage" class="text-sm text-slate-700 font-medium">Yazılım geliştirme süreçlerinde AI araçlarını (Copilot, ChatGPT vb.) etkin kullanıyorum. <span class="text-[#e31e24]">*</span></label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -207,6 +236,16 @@
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
-webkit-appearance: checkbox !important;
|
||||||
|
appearance: checkbox !important;
|
||||||
|
width: 1.25rem !important;
|
||||||
|
height: 1.25rem !important;
|
||||||
|
accent-color: var(--citrus-red);
|
||||||
|
cursor: pointer;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.bg-soft-primary {
|
.bg-soft-primary {
|
||||||
background: linear-gradient(135deg, #f0f7ff 0%, #e8f1ff 100%) !important;
|
background: linear-gradient(135deg, #f0f7ff 0%, #e8f1ff 100%) !important;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user